mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 17:10:11 +01:00
glsl, mesa: add EXT_shader_pixel_local_storage extension
This commit also checks for and issues errors for the following: INVALID_OPERATION is generated if the application attempts enable pixel local storage while the value of SAMPLE_BUFFERS is one. INVALID_OPERATION is generated if the application attempts to enable pixel local storage while the current draw framebuffer is a user-defined frame- buffer object and has an image attached to any color attachment other than color attachment zero. INVALID_OPERATION is generated if the application attempts to enable pixel local storage while the current draw framebuffer is a user-defined frame- buffer and the draw buffer for any color output other than color output zero is not NONE. INVALID_FRAMEBUFFER_OPERATION is generated if the application attempts to enable pixel local storage while the current draw framebuffer is incomplete. INVALID_OPERATION is generated if pixel local storage is disabled and the application attempts to issue a rendering command while a program object that accesses pixel local storage is bound. INVALID_OPERATION is generated if pixel local storage is enabled and the application attempts to bind a new draw framebuffer, delete the currently bound draw framebuffer, change color buffer selection via DrawBuffers, or modify any attachment of the currently bound draw framebuffer including their underlying storage. Reviewed-by: Marek Olšák <marek.olsak@amd.com> Reviewed-by: Eric R. Smith <eric.smith@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37110>
This commit is contained in:
parent
04d3da19c6
commit
7f7c4ebbba
26 changed files with 519 additions and 72 deletions
|
|
@ -667,6 +667,11 @@ struct ast_type_qualifier {
|
|||
unsigned non_coherent:1;
|
||||
/** \} */
|
||||
|
||||
/** \name Qualifiers for GL_EXT_shader_pixel_local_storage */
|
||||
/** \{ */
|
||||
unsigned pixel_local_storage:2;
|
||||
/** \} */
|
||||
|
||||
/** \name Layout qualifiers for NV_compute_shader_derivatives */
|
||||
/** \{ */
|
||||
unsigned derivative_group:1;
|
||||
|
|
|
|||
|
|
@ -94,14 +94,24 @@ public:
|
|||
/* We can have memory_write_only set on both images and buffer variables,
|
||||
* but in the former there is a distinction between reads from
|
||||
* the variable itself (write_only) and from the memory they point to
|
||||
* (memory_write_only), while in the case of buffer variables there is
|
||||
* no such distinction, that is why this check here is limited to
|
||||
* buffer variables alone.
|
||||
* (memory_write_only), while in the case of buffer and pixel local
|
||||
* storage variables there is no such distinction, that is why this check
|
||||
* here is limited to buffer and pixel local storage variables.
|
||||
*/
|
||||
if (!var || var->data.mode != ir_var_shader_storage)
|
||||
if (!var)
|
||||
return visit_continue;
|
||||
|
||||
if (var->data.memory_write_only) {
|
||||
if (var->data.mode == ir_var_shader_storage &&
|
||||
var->data.memory_write_only)
|
||||
{
|
||||
found = var;
|
||||
return visit_stop;
|
||||
}
|
||||
|
||||
/* Variables declared with the__pixel_local_outEXT qualifier are
|
||||
* write-only.
|
||||
*/
|
||||
if (var->data.pixel_local_storage == GLSL_PIXEL_LOCAL_STORAGE_OUT) {
|
||||
found = var;
|
||||
return visit_stop;
|
||||
}
|
||||
|
|
@ -994,6 +1004,28 @@ do_assignment(ir_exec_list *instructions, struct _mesa_glsl_parse_state *state,
|
|||
} else if (!lhs->is_lvalue(state)) {
|
||||
_mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment");
|
||||
error_emitted = true;
|
||||
} else if (lhs_var != NULL) {
|
||||
switch(lhs_var->data.mode) {
|
||||
case ir_var_shader_pixel_local_storage:
|
||||
state->fs_writes_pixel_local_storage = true;
|
||||
break;
|
||||
case ir_var_shader_out:
|
||||
state->fs_writes_output = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* From the GL_EXT_shader_pixel_local_storage spec:
|
||||
*
|
||||
* "It is a compile-time error for a shader to statically write to
|
||||
* both regular user-defined fragment outputs and to pixel local
|
||||
* storage variables."
|
||||
*/
|
||||
if (state->fs_writes_pixel_local_storage && state->fs_writes_output) {
|
||||
_mesa_glsl_error(&lhs_loc, state,
|
||||
"shader writes to both output and pixel local "
|
||||
"storage");
|
||||
error_emitted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3602,7 +3634,10 @@ validate_image_format_qualifier_for_type(struct _mesa_glsl_parse_state *state,
|
|||
* "Format layout qualifiers can be used on image variable declarations
|
||||
* (those declared with a basic type having “image ” in its keyword)."
|
||||
*/
|
||||
if (!glsl_type_is_image(type) && qual->flags.q.explicit_image_format) {
|
||||
if (!glsl_type_is_image(type) &&
|
||||
(qual->flags.q.explicit_image_format &&
|
||||
!qual->flags.q.pixel_local_storage))
|
||||
{
|
||||
_mesa_glsl_error(loc, state, "format layout qualifiers may only be "
|
||||
"applied to images");
|
||||
return false;
|
||||
|
|
@ -5323,6 +5358,17 @@ ast_declarator_list::hir(ir_exec_list *instructions,
|
|||
"interface blocks");
|
||||
}
|
||||
|
||||
/* Similarly, the EXT_shader_pixel_local_storage spec says:
|
||||
* "Pixel local storage variables may only be declared inside
|
||||
* interface blocks..."
|
||||
*/
|
||||
if (type->qualifier.flags.q.pixel_local_storage &&
|
||||
!glsl_type_is_interface(decl_type)) {
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"pixel local storage variables cannot be declared "
|
||||
"outside interface blocks");
|
||||
}
|
||||
|
||||
/* An offset-qualified atomic counter declaration sets the default
|
||||
* offset for the next declaration within the same atomic counter
|
||||
* buffer.
|
||||
|
|
@ -7815,8 +7861,13 @@ ast_process_struct_or_iface_block_members(ir_exec_list *instructions,
|
|||
fields[i].explicit_xfb_buffer = explicit_xfb_buffer;
|
||||
fields[i].xfb_buffer = xfb_buffer;
|
||||
fields[i].xfb_stride = xfb_stride;
|
||||
fields[i].pixel_local_storage = qual->flags.q.pixel_local_storage;
|
||||
|
||||
if (qual->flags.q.explicit_location) {
|
||||
/* for pixel local storage, all locations are effectively "explicit" */
|
||||
if (var_mode == ir_var_shader_pixel_local_storage) {
|
||||
fields[i].location = FRAG_RESULT_DATA0 + expl_location;
|
||||
expl_location += glsl_count_attribute_slots(fields[i].type, false);
|
||||
} else if (qual->flags.q.explicit_location) {
|
||||
unsigned qual_location;
|
||||
if (process_qualifier_constant(state, &loc, "location",
|
||||
qual->location, &qual_location)) {
|
||||
|
|
@ -7975,6 +8026,7 @@ ast_process_struct_or_iface_block_members(ir_exec_list *instructions,
|
|||
* the format qualifier is only accepted for images.
|
||||
*/
|
||||
if (var_mode == ir_var_shader_storage ||
|
||||
var_mode == ir_var_shader_pixel_local_storage ||
|
||||
glsl_type_is_image(glsl_without_array(field_type))) {
|
||||
/* For readonly and writeonly qualifiers the field definition,
|
||||
* if set, overwrites the layout qualifier.
|
||||
|
|
@ -7999,6 +8051,22 @@ ast_process_struct_or_iface_block_members(ir_exec_list *instructions,
|
|||
fields[i].memory_restrict = qual->flags.q.restrict_flag ||
|
||||
(layout && layout->flags.q.restrict_flag);
|
||||
|
||||
if (qual->flags.q.pixel_local_storage) {
|
||||
pipe_format this_image_format = layout->image_format;
|
||||
glsl_base_type this_image_type = layout->image_base_type;
|
||||
if (qual->flags.q.explicit_image_format) {
|
||||
this_image_format = qual->image_format;
|
||||
this_image_type = qual->image_base_type;
|
||||
}
|
||||
if (this_image_type != field_type->base_type ||
|
||||
util_format_get_nr_components(this_image_format) !=
|
||||
field_type->vector_elements) {
|
||||
_mesa_glsl_error(&loc, state, "format qualifier doesn't "
|
||||
"match the base data type of the image");
|
||||
}
|
||||
|
||||
fields[i].image_format = this_image_format;
|
||||
}
|
||||
if (glsl_type_is_image(glsl_without_array(field_type))) {
|
||||
if (qual->flags.q.explicit_image_format) {
|
||||
if (qual->image_base_type !=
|
||||
|
|
@ -8220,6 +8288,11 @@ ast_interface_block::hir(ir_exec_list *instructions,
|
|||
} else {
|
||||
allowed_blk_qualifiers.flags.q.uniform = 1;
|
||||
}
|
||||
} else if (this->layout.flags.q.pixel_local_storage) {
|
||||
allowed_blk_qualifiers.flags.q.pixel_local_storage = 3;
|
||||
allowed_blk_qualifiers.flags.q.read_only = 1;
|
||||
allowed_blk_qualifiers.flags.q.write_only = 1;
|
||||
allowed_blk_qualifiers.flags.q.explicit_image_format = 1;
|
||||
} else {
|
||||
/* Interface block */
|
||||
assert(this->layout.flags.q.in || this->layout.flags.q.out);
|
||||
|
|
@ -8286,6 +8359,9 @@ ast_interface_block::hir(ir_exec_list *instructions,
|
|||
} else if (this->layout.flags.q.buffer) {
|
||||
var_mode = ir_var_shader_storage;
|
||||
iface_type_name = "buffer";
|
||||
} else if (this->layout.flags.q.pixel_local_storage) {
|
||||
var_mode = ir_var_shader_pixel_local_storage;
|
||||
iface_type_name = "pixel local storage";
|
||||
} else {
|
||||
var_mode = ir_var_auto;
|
||||
iface_type_name = "UNKNOWN";
|
||||
|
|
@ -8628,6 +8704,41 @@ ast_interface_block::hir(ir_exec_list *instructions,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check various features for EXT_shader_pixel_local_storage
|
||||
*/
|
||||
if (var_mode == ir_var_shader_pixel_local_storage) {
|
||||
/* ensure we do not exceed the available space */
|
||||
unsigned bytes_used = 4 * num_variables;
|
||||
if (bytes_used > state->caps->shader_pixel_local_storage_size) {
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"bytes needed for pixel local storage (%u) exceeds "
|
||||
"maximum (%u)", bytes_used,
|
||||
state->caps->shader_pixel_local_storage_size);
|
||||
}
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
*
|
||||
* "A shader may only declare a single input and a single output pixel
|
||||
* local storage block."
|
||||
*/
|
||||
unsigned flags = this->layout.flags.q.pixel_local_storage;
|
||||
if (flags & GLSL_PIXEL_LOCAL_STORAGE_IN) {
|
||||
if (state->pixel_local_input_specified) {
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"multiple pixel local storage input interfaces "
|
||||
"specified");
|
||||
}
|
||||
state->pixel_local_input_specified = true;
|
||||
}
|
||||
if (flags & GLSL_PIXEL_LOCAL_STORAGE_OUT) {
|
||||
if (state->pixel_local_output_specified) {
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"multiple pixel local storage output interfaces "
|
||||
"specified");
|
||||
}
|
||||
state->pixel_local_output_specified = true;
|
||||
}
|
||||
}
|
||||
/* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec
|
||||
* says:
|
||||
*
|
||||
|
|
@ -8794,9 +8905,14 @@ ast_interface_block::hir(ir_exec_list *instructions,
|
|||
|
||||
if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
|
||||
var->data.read_only = true;
|
||||
else if (var_mode == ir_var_shader_pixel_local_storage)
|
||||
var->data.read_only =
|
||||
this->layout.flags.q.pixel_local_storage ==
|
||||
GLSL_PIXEL_LOCAL_STORAGE_IN;
|
||||
|
||||
var->data.patch = this->layout.flags.q.patch;
|
||||
var->data.per_primitive = this->layout.flags.q.per_primitive;
|
||||
var->data.pixel_local_storage = this->layout.flags.q.pixel_local_storage;
|
||||
|
||||
if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
|
||||
handle_geometry_shader_input_decl(state, loc, var);
|
||||
|
|
@ -8832,6 +8948,9 @@ ast_interface_block::hir(ir_exec_list *instructions,
|
|||
if (layout.flags.q.explicit_location) {
|
||||
var->data.location = expl_location;
|
||||
var->data.explicit_location = true;
|
||||
} else if (layout.flags.q.pixel_local_storage) {
|
||||
var->data.location = FRAG_RESULT_DATA0;
|
||||
var->data.explicit_location = true;
|
||||
}
|
||||
|
||||
state->symbols->add_variable(var);
|
||||
|
|
@ -8871,6 +8990,14 @@ ast_interface_block::hir(ir_exec_list *instructions,
|
|||
if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
|
||||
var->data.read_only = true;
|
||||
|
||||
if (var_mode == ir_var_shader_pixel_local_storage) {
|
||||
var->data.pixel_local_storage =
|
||||
this->layout.flags.q.pixel_local_storage;
|
||||
var->data.read_only =
|
||||
var->data.pixel_local_storage == GLSL_PIXEL_LOCAL_STORAGE_IN;
|
||||
var->data.image_format = fields[i].image_format;
|
||||
}
|
||||
|
||||
/* Precision qualifiers do not have any meaning in Desktop GLSL */
|
||||
if (state->es_shader) {
|
||||
var->data.precision =
|
||||
|
|
|
|||
|
|
@ -942,6 +942,7 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc,
|
|||
Q(noperspective);
|
||||
Q(origin_upper_left);
|
||||
Q(pixel_center_integer);
|
||||
Q(pixel_local_storage);
|
||||
Q2(explicit_align, align);
|
||||
Q2(explicit_component, component);
|
||||
Q2(explicit_location, location);
|
||||
|
|
|
|||
|
|
@ -574,6 +574,13 @@ gl_nir_validate_intrastage_interface_blocks(struct gl_shader_program *prog,
|
|||
case nir_var_mem_ssbo:
|
||||
definitions = buffer_interfaces;
|
||||
break;
|
||||
case nir_var_mem_pixel_local_in:
|
||||
case nir_var_mem_pixel_local_out:
|
||||
case nir_var_mem_pixel_local_inout:
|
||||
/* These aren't intrastage, they're fragment shader
|
||||
* only, so they don't need to be checked here.
|
||||
*/
|
||||
continue;
|
||||
default:
|
||||
/* Only in, out, and uniform interfaces are legal, so we should
|
||||
* never get here.
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ flatten_named_interface_deref(void *mem_ctx, nir_builder *b,
|
|||
struct hash_table *interface_namespace,
|
||||
bool is_src0)
|
||||
{
|
||||
nir_variable_mode mask = nir_var_shader_in | nir_var_shader_out;
|
||||
nir_variable_mode mask = nir_var_shader_in | nir_var_shader_out |
|
||||
nir_var_any_pixel_local;
|
||||
|
||||
if (!nir_deref_mode_is_one_of(deref, mask))
|
||||
return false;
|
||||
|
|
@ -252,7 +253,8 @@ lower_named_interface_blocks(struct gl_linked_shader *sh)
|
|||
* hash table so they can be used in the second pass.
|
||||
*/
|
||||
nir_foreach_variable_with_modes_safe(var, sh->Program->nir,
|
||||
nir_var_shader_in | nir_var_shader_out) {
|
||||
nir_var_shader_in | nir_var_shader_out |
|
||||
nir_var_any_pixel_local) {
|
||||
const struct glsl_type * iface_t = glsl_without_array(var->type);
|
||||
if (iface_t != var->interface_type)
|
||||
continue;
|
||||
|
|
@ -283,7 +285,6 @@ lower_named_interface_blocks(struct gl_linked_shader *sh)
|
|||
new_var->data.explicit_location = (new_var->data.location >= 0);
|
||||
new_var->data.offset = field_data->offset;
|
||||
new_var->data.explicit_offset = (field_data->offset >= 0);
|
||||
new_var->data.xfb.buffer = field_data->xfb_buffer;
|
||||
new_var->data.explicit_xfb_buffer = field_data->explicit_xfb_buffer;
|
||||
new_var->data.interpolation = field_data->interpolation;
|
||||
new_var->data.centroid = field_data->centroid;
|
||||
|
|
@ -294,6 +295,11 @@ lower_named_interface_blocks(struct gl_linked_shader *sh)
|
|||
new_var->data.how_declared = var->data.how_declared;
|
||||
new_var->data.from_named_ifc_block = 1;
|
||||
|
||||
if (new_var->data.mode & nir_var_any_pixel_local)
|
||||
new_var->data.image.format = field_data->image_format;
|
||||
else
|
||||
new_var->data.xfb.buffer = field_data->xfb_buffer;
|
||||
|
||||
new_var->interface_type = var->type;
|
||||
_mesa_hash_table_insert(interface_namespace, iface_field_name,
|
||||
new_var);
|
||||
|
|
@ -315,7 +321,8 @@ lower_named_interface_blocks(struct gl_linked_shader *sh)
|
|||
* needed now that the default interface block has been lowered away.
|
||||
*/
|
||||
nir_foreach_variable_with_modes(var, sh->Program->nir,
|
||||
nir_var_shader_in | nir_var_shader_out) {
|
||||
nir_var_shader_in | nir_var_shader_out |
|
||||
nir_var_any_pixel_local) {
|
||||
|
||||
if (var->data.mode == nir_var_shader_in) {
|
||||
if (sh->Program->nir->info.stage == MESA_SHADER_TESS_EVAL &&
|
||||
|
|
@ -331,9 +338,7 @@ lower_named_interface_blocks(struct gl_linked_shader *sh)
|
|||
var->data.compact =
|
||||
glsl_type_is_scalar(glsl_without_array(var->type));
|
||||
}
|
||||
} else {
|
||||
assert(var->data.mode == nir_var_shader_out);
|
||||
|
||||
} else if (var->data.mode == nir_var_shader_out) {
|
||||
if (sh->Program->nir->info.stage == MESA_SHADER_TESS_CTRL &&
|
||||
(var->data.location == VARYING_SLOT_TESS_LEVEL_INNER ||
|
||||
var->data.location == VARYING_SLOT_TESS_LEVEL_OUTER)) {
|
||||
|
|
|
|||
|
|
@ -450,6 +450,9 @@ flat KEYWORD_WITH_ALT(130, 100, 130, 300, yyextra->EXT_gpu_shader4_enable, FLAT
|
|||
smooth KEYWORD(130, 300, 130, 300, SMOOTH);
|
||||
noperspective KEYWORD_WITH_ALT(130, 300, 130, 0, yyextra->EXT_gpu_shader4_enable || yyextra->NV_shader_noperspective_interpolation_enable, NOPERSPECTIVE);
|
||||
patch KEYWORD_WITH_ALT(0, 300, 400, 320, yyextra->has_tessellation_shader(), PATCH);
|
||||
__pixel_localEXT KEYWORD_WITH_ALT(0, 0, 0, 300, yyextra->EXT_shader_pixel_local_storage_enable, PIXEL_LOCAL);
|
||||
__pixel_local_inEXT KEYWORD_WITH_ALT(0, 0, 0, 300, yyextra->EXT_shader_pixel_local_storage_enable, PIXEL_LOCAL_IN);
|
||||
__pixel_local_outEXT KEYWORD_WITH_ALT(0, 0, 0, 300, yyextra->EXT_shader_pixel_local_storage_enable, PIXEL_LOCAL_OUT);
|
||||
|
||||
sampler1D DEPRECATED_ES_TYPE(&glsl_type_builtin_sampler1D);
|
||||
sampler2D { yylval->type = &glsl_type_builtin_sampler2D; return BASIC_TYPE_TOK; }
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
|
|||
%token BREAK BUFFER CONTINUE DO ELSE FOR IF DEMOTE DISCARD RETURN SWITCH CASE DEFAULT
|
||||
%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING SAMPLE
|
||||
%token NOPERSPECTIVE FLAT SMOOTH
|
||||
%token PIXEL_LOCAL PIXEL_LOCAL_IN PIXEL_LOCAL_OUT
|
||||
%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGE1DARRAYSHADOW IMAGE2DARRAYSHADOW
|
||||
%token COHERENT VOLATILE RESTRICT READONLY WRITEONLY
|
||||
%token SHARED
|
||||
|
|
@ -1335,7 +1336,8 @@ layout_qualifier_id:
|
|||
}
|
||||
|
||||
/* Layout qualifiers for ARB_shader_image_load_store. */
|
||||
if (state->has_shader_image_load_store()) {
|
||||
if (state->has_shader_image_load_store() ||
|
||||
state->EXT_shader_pixel_local_storage_enable) {
|
||||
if (!$$.flags.i) {
|
||||
static const struct {
|
||||
const char *name;
|
||||
|
|
@ -1351,58 +1353,68 @@ layout_qualifier_id:
|
|||
/* NV_image_formats */
|
||||
bool nv_image_formats;
|
||||
bool ext_qualifiers;
|
||||
/* for __pixel_localEXT */
|
||||
bool pixel_local_qualifiers;
|
||||
} map[] = {
|
||||
{ "rgba32f", PIPE_FORMAT_R32G32B32A32_FLOAT, GLSL_TYPE_FLOAT, 130, 310, false, false },
|
||||
{ "rgba16f", PIPE_FORMAT_R16G16B16A16_FLOAT, GLSL_TYPE_FLOAT, 130, 310, false, false },
|
||||
{ "rg32f", PIPE_FORMAT_R32G32_FLOAT, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rg16f", PIPE_FORMAT_R16G16_FLOAT, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "r11f_g11f_b10f", PIPE_FORMAT_R11G11B10_FLOAT, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "r32f", PIPE_FORMAT_R32_FLOAT, GLSL_TYPE_FLOAT, 130, 310, false, false },
|
||||
{ "r16f", PIPE_FORMAT_R16_FLOAT, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rgba32ui", PIPE_FORMAT_R32G32B32A32_UINT, GLSL_TYPE_UINT, 130, 310, false, false },
|
||||
{ "rgba16ui", PIPE_FORMAT_R16G16B16A16_UINT, GLSL_TYPE_UINT, 130, 310, false, false },
|
||||
{ "rgb10_a2ui", PIPE_FORMAT_R10G10B10A2_UINT, GLSL_TYPE_UINT, 130, 0, true, false },
|
||||
{ "rgba8ui", PIPE_FORMAT_R8G8B8A8_UINT, GLSL_TYPE_UINT, 130, 310, false, false },
|
||||
{ "rg32ui", PIPE_FORMAT_R32G32_UINT, GLSL_TYPE_UINT, 130, 0, true, false },
|
||||
{ "rg16ui", PIPE_FORMAT_R16G16_UINT, GLSL_TYPE_UINT, 130, 0, true, false },
|
||||
{ "rg8ui", PIPE_FORMAT_R8G8_UINT, GLSL_TYPE_UINT, 130, 0, true, false },
|
||||
{ "r32ui", PIPE_FORMAT_R32_UINT, GLSL_TYPE_UINT, 130, 310, false, false },
|
||||
{ "r16ui", PIPE_FORMAT_R16_UINT, GLSL_TYPE_UINT, 130, 0, true, false },
|
||||
{ "r8ui", PIPE_FORMAT_R8_UINT, GLSL_TYPE_UINT, 130, 0, true, false },
|
||||
{ "rgba32i", PIPE_FORMAT_R32G32B32A32_SINT, GLSL_TYPE_INT, 130, 310, false, false },
|
||||
{ "rgba16i", PIPE_FORMAT_R16G16B16A16_SINT, GLSL_TYPE_INT, 130, 310, false, false },
|
||||
{ "rgba8i", PIPE_FORMAT_R8G8B8A8_SINT, GLSL_TYPE_INT, 130, 310, false, false },
|
||||
{ "rg32i", PIPE_FORMAT_R32G32_SINT, GLSL_TYPE_INT, 130, 0, true, false },
|
||||
{ "rg16i", PIPE_FORMAT_R16G16_SINT, GLSL_TYPE_INT, 130, 0, true, false },
|
||||
{ "rg8i", PIPE_FORMAT_R8G8_SINT, GLSL_TYPE_INT, 130, 0, true, false },
|
||||
{ "r32i", PIPE_FORMAT_R32_SINT, GLSL_TYPE_INT, 130, 310, false, false },
|
||||
{ "r16i", PIPE_FORMAT_R16_SINT, GLSL_TYPE_INT, 130, 0, true, false },
|
||||
{ "r8i", PIPE_FORMAT_R8_SINT, GLSL_TYPE_INT, 130, 0, true, false },
|
||||
{ "rgba16", PIPE_FORMAT_R16G16B16A16_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rgb10_a2", PIPE_FORMAT_R10G10B10A2_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rgba8", PIPE_FORMAT_R8G8B8A8_UNORM, GLSL_TYPE_FLOAT, 130, 310, false, false },
|
||||
{ "rg16", PIPE_FORMAT_R16G16_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rg8", PIPE_FORMAT_R8G8_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "r16", PIPE_FORMAT_R16_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "r8", PIPE_FORMAT_R8_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rgba16_snorm", PIPE_FORMAT_R16G16B16A16_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rgba8_snorm", PIPE_FORMAT_R8G8B8A8_SNORM, GLSL_TYPE_FLOAT, 130, 310, false, false },
|
||||
{ "rg16_snorm", PIPE_FORMAT_R16G16_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rg8_snorm", PIPE_FORMAT_R8G8_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "r16_snorm", PIPE_FORMAT_R16_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "r8_snorm", PIPE_FORMAT_R8_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false },
|
||||
{ "rgba32f", PIPE_FORMAT_R32G32B32A32_FLOAT, GLSL_TYPE_FLOAT, 130, 310, false, false, false },
|
||||
{ "rgba16f", PIPE_FORMAT_R16G16B16A16_FLOAT, GLSL_TYPE_FLOAT, 130, 310, false, false, false },
|
||||
{ "rg32f", PIPE_FORMAT_R32G32_FLOAT, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "rg16f", PIPE_FORMAT_R16G16_FLOAT, GLSL_TYPE_FLOAT, 130, 0, true, false, true },
|
||||
{ "r11f_g11f_b10f", PIPE_FORMAT_R11G11B10_FLOAT, GLSL_TYPE_FLOAT, 130, 0, true, false, true },
|
||||
{ "r32f", PIPE_FORMAT_R32_FLOAT, GLSL_TYPE_FLOAT, 130, 310, false, false, true },
|
||||
{ "r16f", PIPE_FORMAT_R16_FLOAT, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "rgba32ui", PIPE_FORMAT_R32G32B32A32_UINT, GLSL_TYPE_UINT, 130, 310, false, false, false },
|
||||
{ "rgba16ui", PIPE_FORMAT_R16G16B16A16_UINT, GLSL_TYPE_UINT, 130, 310, false, false, false },
|
||||
{ "rgb10_a2ui", PIPE_FORMAT_R10G10B10A2_UINT, GLSL_TYPE_UINT, 130, 0, true, false, true },
|
||||
{ "rgba8ui", PIPE_FORMAT_R8G8B8A8_UINT, GLSL_TYPE_UINT, 130, 310, false, false, true },
|
||||
{ "rg32ui", PIPE_FORMAT_R32G32_UINT, GLSL_TYPE_UINT, 130, 0, true, false, false },
|
||||
{ "rg16ui", PIPE_FORMAT_R16G16_UINT, GLSL_TYPE_UINT, 130, 0, true, false, true },
|
||||
{ "rg8ui", PIPE_FORMAT_R8G8_UINT, GLSL_TYPE_UINT, 130, 0, true, false, false },
|
||||
{ "r32ui", PIPE_FORMAT_R32_UINT, GLSL_TYPE_UINT, 130, 310, false, false, true },
|
||||
{ "r16ui", PIPE_FORMAT_R16_UINT, GLSL_TYPE_UINT, 130, 0, true, false, false },
|
||||
{ "r8ui", PIPE_FORMAT_R8_UINT, GLSL_TYPE_UINT, 130, 0, true, false, false },
|
||||
{ "rgba32i", PIPE_FORMAT_R32G32B32A32_SINT, GLSL_TYPE_INT, 130, 310, false, false, false },
|
||||
{ "rgba16i", PIPE_FORMAT_R16G16B16A16_SINT, GLSL_TYPE_INT, 130, 310, false, false, false },
|
||||
{ "rgba8i", PIPE_FORMAT_R8G8B8A8_SINT, GLSL_TYPE_INT, 130, 310, false, false, true },
|
||||
{ "rg32i", PIPE_FORMAT_R32G32_SINT, GLSL_TYPE_INT, 130, 0, true, false, false },
|
||||
{ "rg16i", PIPE_FORMAT_R16G16_SINT, GLSL_TYPE_INT, 130, 0, true, false, true },
|
||||
{ "rg8i", PIPE_FORMAT_R8G8_SINT, GLSL_TYPE_INT, 130, 0, true, false, false },
|
||||
{ "r32i", PIPE_FORMAT_R32_SINT, GLSL_TYPE_INT, 130, 310, false, false, true },
|
||||
{ "r16i", PIPE_FORMAT_R16_SINT, GLSL_TYPE_INT, 130, 0, true, false, false },
|
||||
{ "r8i", PIPE_FORMAT_R8_SINT, GLSL_TYPE_INT, 130, 0, true, false, false },
|
||||
{ "rgba16", PIPE_FORMAT_R16G16B16A16_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "rgb10_a2", PIPE_FORMAT_R10G10B10A2_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, true },
|
||||
{ "rgba8", PIPE_FORMAT_R8G8B8A8_UNORM, GLSL_TYPE_FLOAT, 130, 310, false, false, true },
|
||||
{ "rg16", PIPE_FORMAT_R16G16_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, true },
|
||||
{ "rg8", PIPE_FORMAT_R8G8_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "r16", PIPE_FORMAT_R16_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "r8", PIPE_FORMAT_R8_UNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "rgba16_snorm", PIPE_FORMAT_R16G16B16A16_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "rgba8_snorm", PIPE_FORMAT_R8G8B8A8_SNORM, GLSL_TYPE_FLOAT, 130, 310, false, false, false },
|
||||
{ "rg16_snorm", PIPE_FORMAT_R16G16_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "rg8_snorm", PIPE_FORMAT_R8G8_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "r16_snorm", PIPE_FORMAT_R16_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
{ "r8_snorm", PIPE_FORMAT_R8_SNORM, GLSL_TYPE_FLOAT, 130, 0, true, false, false },
|
||||
|
||||
/* From GL_EXT_shader_image_load_store: */
|
||||
/* base_type is incorrect but it'll be patched later when we know
|
||||
* the variable type. See ast_to_hir.cpp */
|
||||
{ "size1x8", PIPE_FORMAT_R8_SINT, GLSL_TYPE_VOID, 130, 0, false, true },
|
||||
{ "size1x16", PIPE_FORMAT_R16_SINT, GLSL_TYPE_VOID, 130, 0, false, true },
|
||||
{ "size1x32", PIPE_FORMAT_R32_SINT, GLSL_TYPE_VOID, 130, 0, false, true },
|
||||
{ "size2x32", PIPE_FORMAT_R32G32_SINT, GLSL_TYPE_VOID, 130, 0, false, true },
|
||||
{ "size4x32", PIPE_FORMAT_R32G32B32A32_SINT, GLSL_TYPE_VOID, 130, 0, false, true },
|
||||
{ "size1x8", PIPE_FORMAT_R8_SINT, GLSL_TYPE_VOID, 130, 0, false, true, false },
|
||||
{ "size1x16", PIPE_FORMAT_R16_SINT, GLSL_TYPE_VOID, 130, 0, false, true, false },
|
||||
{ "size1x32", PIPE_FORMAT_R32_SINT, GLSL_TYPE_VOID, 130, 0, false, true, false },
|
||||
{ "size2x32", PIPE_FORMAT_R32G32_SINT, GLSL_TYPE_VOID, 130, 0, false, true, false },
|
||||
{ "size4x32", PIPE_FORMAT_R32G32B32A32_SINT, GLSL_TYPE_VOID, 130, 0, false, true, false },
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
|
||||
if (state->EXT_shader_pixel_local_storage_enable &&
|
||||
map[i].pixel_local_qualifiers &&
|
||||
match_layout_qualifier($1, map[i].name, state) == 0) {
|
||||
$$.flags.q.explicit_image_format = 1;
|
||||
$$.image_format = map[i].format;
|
||||
$$.image_base_type = map[i].base_type;
|
||||
break;
|
||||
}
|
||||
if ((state->is_version(map[i].required_glsl,
|
||||
map[i].required_essl) ||
|
||||
(state->NV_image_formats_enable &&
|
||||
|
|
@ -2282,6 +2294,21 @@ storage_qualifier:
|
|||
memset(& $$, 0, sizeof($$));
|
||||
$$.flags.q.task_payload = 1;
|
||||
}
|
||||
| PIXEL_LOCAL
|
||||
{
|
||||
memset(& $$, 0, sizeof($$));
|
||||
$$.flags.q.pixel_local_storage = GLSL_PIXEL_LOCAL_STORAGE_INOUT;
|
||||
}
|
||||
| PIXEL_LOCAL_IN
|
||||
{
|
||||
memset(& $$, 0, sizeof($$));
|
||||
$$.flags.q.pixel_local_storage = GLSL_PIXEL_LOCAL_STORAGE_IN;
|
||||
}
|
||||
| PIXEL_LOCAL_OUT
|
||||
{
|
||||
memset(& $$, 0, sizeof($$));
|
||||
$$.flags.q.pixel_local_storage = GLSL_PIXEL_LOCAL_STORAGE_OUT;
|
||||
}
|
||||
;
|
||||
|
||||
memory_qualifier:
|
||||
|
|
@ -2962,6 +2989,21 @@ interface_qualifier:
|
|||
memset(& $$, 0, sizeof($$));
|
||||
$$.flags.q.buffer = 1;
|
||||
}
|
||||
| PIXEL_LOCAL
|
||||
{
|
||||
memset(& $$, 0, sizeof($$));
|
||||
$$.flags.q.pixel_local_storage = GLSL_PIXEL_LOCAL_STORAGE_INOUT;
|
||||
}
|
||||
| PIXEL_LOCAL_IN
|
||||
{
|
||||
memset(& $$, 0, sizeof($$));
|
||||
$$.flags.q.pixel_local_storage = GLSL_PIXEL_LOCAL_STORAGE_IN;
|
||||
}
|
||||
| PIXEL_LOCAL_OUT
|
||||
{
|
||||
memset(& $$, 0, sizeof($$));
|
||||
$$.flags.q.pixel_local_storage = GLSL_PIXEL_LOCAL_STORAGE_OUT;
|
||||
}
|
||||
| auxiliary_storage_qualifier interface_qualifier
|
||||
{
|
||||
if (!$1.flags.q.patch && !$1.flags.q.per_primitive) {
|
||||
|
|
|
|||
|
|
@ -840,6 +840,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
|
|||
EXT(EXT_shader_implicit_conversions),
|
||||
EXT(EXT_shader_integer_mix),
|
||||
EXT_AEP(EXT_shader_io_blocks),
|
||||
EXT(EXT_shader_pixel_local_storage),
|
||||
EXT(EXT_shader_realtime_clock),
|
||||
EXT(EXT_shader_samples_identical),
|
||||
EXT(EXT_shadow_samplers),
|
||||
|
|
@ -1175,6 +1176,17 @@ _mesa_ast_process_interface_block(YYLTYPE *locp,
|
|||
"#version 140 / GL_ARB_uniform_buffer_object "
|
||||
"required for defining uniform blocks");
|
||||
}
|
||||
} else if (q.flags.q.pixel_local_storage) {
|
||||
if (!state->EXT_shader_pixel_local_storage_enable) {
|
||||
_mesa_glsl_error(locp, state,
|
||||
"GL_EXT_shader_pixel_local_storage "
|
||||
"required for defining pixel local storage blocks");
|
||||
|
||||
} else if (state->EXT_shader_pixel_local_storage_warn) {
|
||||
_mesa_glsl_warning(locp, state,
|
||||
"GL_EXT_shader_pixel_local_storage "
|
||||
"required for defining pixel local storage blocks");
|
||||
}
|
||||
} else {
|
||||
if (!state->has_shader_io_blocks()) {
|
||||
if (state->es_shader) {
|
||||
|
|
@ -1215,7 +1227,7 @@ _mesa_ast_process_interface_block(YYLTYPE *locp,
|
|||
ast_type_qualifier::bitset_t interface_type_mask;
|
||||
struct ast_type_qualifier temp_type_qualifier;
|
||||
|
||||
/* Get a bitmask containing only the in/out/uniform/buffer
|
||||
/* Get a bitmask containing only the in/out/uniform/buffer/pls
|
||||
* flags, allowing us to ignore other irrelevant flags like
|
||||
* interpolation qualifiers.
|
||||
*/
|
||||
|
|
@ -1226,11 +1238,13 @@ _mesa_ast_process_interface_block(YYLTYPE *locp,
|
|||
temp_type_qualifier.flags.q.buffer = true;
|
||||
temp_type_qualifier.flags.q.patch = true;
|
||||
temp_type_qualifier.flags.q.per_primitive = true;
|
||||
temp_type_qualifier.flags.q.pixel_local_storage =
|
||||
GLSL_PIXEL_LOCAL_STORAGE_INOUT;
|
||||
interface_type_mask = temp_type_qualifier.flags.i;
|
||||
|
||||
/* Get the block's interface qualifier. The interface_qualifier
|
||||
* production rule guarantees that only one bit will be set (and
|
||||
* it will be in/out/uniform).
|
||||
* it will be in/out/uniform/pls).
|
||||
*/
|
||||
ast_type_qualifier::bitset_t block_interface_qualifier = q.flags.i;
|
||||
|
||||
|
|
@ -1274,7 +1288,7 @@ _mesa_ast_process_interface_block(YYLTYPE *locp,
|
|||
* the block."
|
||||
*/
|
||||
_mesa_glsl_error(locp, state,
|
||||
"uniform/in/out qualifier on "
|
||||
"optional qualifier on "
|
||||
"interface block member does not match "
|
||||
"the interface block");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -493,6 +493,13 @@ struct _mesa_glsl_parse_state {
|
|||
bool ms_output_max_vertices_specified;
|
||||
bool ms_output_max_primitives_specified;
|
||||
|
||||
/**
|
||||
* True if a shader declares input/output pixel local storage interfaces;
|
||||
* at most one input and one output may be declared.
|
||||
*/
|
||||
bool pixel_local_input_specified;
|
||||
bool pixel_local_output_specified;
|
||||
|
||||
/**
|
||||
* Output layout qualifiers from GLSL 1.50 (geometry shader controls),
|
||||
* and GLSL 4.00 (tessellation control shader).
|
||||
|
|
@ -908,6 +915,8 @@ struct _mesa_glsl_parse_state {
|
|||
bool EXT_shader_integer_mix_warn;
|
||||
bool EXT_shader_io_blocks_enable;
|
||||
bool EXT_shader_io_blocks_warn;
|
||||
bool EXT_shader_pixel_local_storage_enable;
|
||||
bool EXT_shader_pixel_local_storage_warn;
|
||||
bool EXT_shader_realtime_clock_enable;
|
||||
bool EXT_shader_realtime_clock_warn;
|
||||
bool EXT_shader_samples_identical_enable;
|
||||
|
|
@ -1042,6 +1051,10 @@ struct _mesa_glsl_parse_state {
|
|||
*/
|
||||
unsigned clip_dist_size, cull_dist_size;
|
||||
|
||||
/* for EXT_shader_pixel_local_storage */
|
||||
bool fs_writes_output;
|
||||
bool fs_writes_pixel_local_storage;
|
||||
|
||||
/* for OVR_multiview */
|
||||
uint32_t view_mask;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ public:
|
|||
case ir_var_shader_out:
|
||||
dest = &ibo;
|
||||
break;
|
||||
case ir_var_shader_pixel_local_storage:
|
||||
dest = &ipl;
|
||||
break;
|
||||
default:
|
||||
assert(!"Unsupported interface variable mode!");
|
||||
return false;
|
||||
|
|
@ -60,19 +63,19 @@ public:
|
|||
}
|
||||
|
||||
symbol_table_entry(ir_variable *v) :
|
||||
v(v), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0) {}
|
||||
v(v), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), ipl(0), a(0) {}
|
||||
symbol_table_entry(ir_function *f) :
|
||||
v(0), f(f), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0) {}
|
||||
v(0), f(f), t(0), ibu(0), iss(0), ibi(0), ibo(0), ipl(0), a(0) {}
|
||||
symbol_table_entry(const glsl_type *t) :
|
||||
v(0), f(0), t(t), ibu(0), iss(0), ibi(0), ibo(0), a(0) {}
|
||||
v(0), f(0), t(t), ibu(0), iss(0), ibi(0), ibo(0), ipl(0), a(0) {}
|
||||
symbol_table_entry(const glsl_type *t, enum ir_variable_mode mode) :
|
||||
v(0), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0)
|
||||
v(0), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), ipl(0), a(0)
|
||||
{
|
||||
assert(glsl_type_is_interface(t));
|
||||
add_interface(t, mode);
|
||||
}
|
||||
symbol_table_entry(const class ast_type_specifier *a):
|
||||
v(0), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(a) {}
|
||||
v(0), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), ipl(0), a(a) {}
|
||||
|
||||
ir_variable *v;
|
||||
ir_function *f;
|
||||
|
|
@ -81,6 +84,7 @@ public:
|
|||
const glsl_type *iss;
|
||||
const glsl_type *ibi;
|
||||
const glsl_type *ibo;
|
||||
const glsl_type *ipl;
|
||||
const class ast_type_specifier *a;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -531,6 +531,23 @@ nir_visitor::visit(ir_variable *ir)
|
|||
var->data.mode = nir_var_mem_task_payload;
|
||||
break;
|
||||
|
||||
case ir_var_shader_pixel_local_storage:
|
||||
switch (ir->data.pixel_local_storage) {
|
||||
case GLSL_PIXEL_LOCAL_STORAGE_IN:
|
||||
var->data.mode = nir_var_mem_pixel_local_in;
|
||||
break;
|
||||
case GLSL_PIXEL_LOCAL_STORAGE_OUT:
|
||||
var->data.mode = nir_var_mem_pixel_local_out;
|
||||
break;
|
||||
case GLSL_PIXEL_LOCAL_STORAGE_INOUT:
|
||||
var->data.mode = nir_var_mem_pixel_local_inout;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("bad pixel local storage field");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE("not reached");
|
||||
}
|
||||
|
|
@ -616,6 +633,8 @@ nir_visitor::visit(ir_variable *ir)
|
|||
} else if (var->data.mode == nir_var_shader_out) {
|
||||
var->data.xfb.buffer = ir->data.xfb_buffer;
|
||||
var->data.xfb.stride = ir->data.xfb_stride;
|
||||
} else if (var->data.mode & nir_var_any_pixel_local) {
|
||||
var->data.image.format = ir->data.image_format;
|
||||
}
|
||||
|
||||
var->data.fb_fetch_output = ir->data.fb_fetch_output;
|
||||
|
|
|
|||
|
|
@ -322,6 +322,7 @@ enum ir_variable_mode {
|
|||
ir_var_shader_task_payload,
|
||||
ir_var_shader_in,
|
||||
ir_var_shader_out,
|
||||
ir_var_shader_pixel_local_storage, /**< Variable declared as pixel local storage */
|
||||
ir_var_function_in,
|
||||
ir_var_function_out,
|
||||
ir_var_function_inout,
|
||||
|
|
@ -863,6 +864,12 @@ public:
|
|||
*/
|
||||
unsigned per_primitive:1;
|
||||
|
||||
/**
|
||||
* Non-zero if the variable is pixel local storage; in this
|
||||
* case bit 0 indicates read access, bit 1 write access
|
||||
*/
|
||||
unsigned pixel_local_storage:2;
|
||||
|
||||
/**
|
||||
* Emit a warning if this variable is accessed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ void ir_print_visitor::visit(ir_variable *ir)
|
|||
const char *const memory_restrict = (ir->data.memory_restrict) ? "restrict " : "";
|
||||
const char *const mode[] = { "", "uniform ", "shader_storage ",
|
||||
"shader_shared ", "task_payload ", "shader_in ", "shader_out ",
|
||||
"shader_pixel_local ",
|
||||
"in ", "out ", "inout ",
|
||||
"const_in ", "sys ", "temporary " };
|
||||
const char *const per_primitive = (ir->data.per_primitive) ? "per_primitive " : "";
|
||||
|
|
|
|||
|
|
@ -288,6 +288,13 @@ enum {
|
|||
GLSL_PRECISION_LOW
|
||||
};
|
||||
|
||||
enum {
|
||||
GLSL_PIXEL_LOCAL_STORAGE_NONE = 0,
|
||||
GLSL_PIXEL_LOCAL_STORAGE_IN,
|
||||
GLSL_PIXEL_LOCAL_STORAGE_OUT,
|
||||
GLSL_PIXEL_LOCAL_STORAGE_INOUT
|
||||
};
|
||||
|
||||
enum glsl_cmat_use {
|
||||
GLSL_CMAT_USE_NONE = 0,
|
||||
GLSL_CMAT_USE_A,
|
||||
|
|
|
|||
|
|
@ -1125,6 +1125,8 @@ struct pipe_caps {
|
|||
unsigned shader_subgroup_size;
|
||||
unsigned shader_subgroup_supported_stages;
|
||||
unsigned shader_subgroup_supported_features;
|
||||
unsigned shader_pixel_local_storage_size;
|
||||
unsigned shader_pixel_local_storage_fast_size;
|
||||
unsigned multiview;
|
||||
unsigned max_label_length;
|
||||
uint64_t max_timeline_semaphore_difference;
|
||||
|
|
|
|||
|
|
@ -465,6 +465,16 @@ draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, GLsizei n,
|
|||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid buffers)", caller);
|
||||
return;
|
||||
}
|
||||
|
||||
/* From the GL_EXT_shader_pixel_local_storage spec:
|
||||
* "INVALID_OPERATION is generated if pixel local storage is enabled and
|
||||
* the application attempts to [...] change color buffer selection via
|
||||
* DrawBuffers, [...]"
|
||||
*/
|
||||
if (ctx->PixelLocalStorage) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(): pixel local storage enabled", caller);
|
||||
}
|
||||
}
|
||||
|
||||
supportedMask = supported_buffer_bitmask(ctx, fb);
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ struct gl_extensions
|
|||
GLboolean EXT_shader_image_load_formatted;
|
||||
GLboolean EXT_shader_image_load_store;
|
||||
GLboolean EXT_shader_integer_mix;
|
||||
GLboolean EXT_shader_pixel_local_storage;
|
||||
GLboolean EXT_shader_realtime_clock;
|
||||
GLboolean EXT_shader_samples_identical;
|
||||
GLboolean EXT_sRGB;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,19 @@ _mesa_update_valid_to_render_state(struct gl_context *ctx)
|
|||
num_color_buffers - max_dual_source_buffers))
|
||||
return;
|
||||
|
||||
/* From the GL_EXT_shader_pixel_local_storage spec:
|
||||
*
|
||||
* "INVALID_OPERATION is generated if pixel local storage is disabled and
|
||||
* the application attempts to issue a rendering command while a program
|
||||
* object that accesses pixel local storage is bound."
|
||||
*/
|
||||
const struct gl_program *fp =
|
||||
ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
|
||||
|
||||
if (!ctx->PixelLocalStorage && fp &&
|
||||
fp->info.fs.accesses_pixel_local_storage)
|
||||
return;
|
||||
|
||||
if (ctx->Color.BlendEnabled &&
|
||||
ctx->Color._AdvancedBlendMode != BLEND_NONE) {
|
||||
/* The KHR_blend_equation_advanced spec says:
|
||||
|
|
@ -138,16 +151,14 @@ _mesa_update_valid_to_render_state(struct gl_context *ctx)
|
|||
* the blend equation or "blend_support_all_equations", the error
|
||||
* INVALID_OPERATION is generated [...]"
|
||||
*/
|
||||
const struct gl_program *prog =
|
||||
ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
|
||||
const GLbitfield blend_support = !prog ? 0 : prog->info.fs.advanced_blend_modes;
|
||||
const GLbitfield blend_support = !fp ? 0 : fp->info.fs.advanced_blend_modes;
|
||||
|
||||
if ((blend_support & BITFIELD_BIT(ctx->Color._AdvancedBlendMode)) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_mesa_is_desktop_gl_compat(ctx)) {
|
||||
if (!shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
|
||||
if (!fp) {
|
||||
if (ctx->FragmentProgram.Enabled &&
|
||||
!_mesa_arb_fragment_program_enabled(ctx))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -48,8 +48,14 @@ draw_texture(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
|
|||
if (ctx->NewState)
|
||||
_mesa_update_state(ctx);
|
||||
|
||||
if (!ctx->DrawPixValid) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
|
||||
goto end;
|
||||
}
|
||||
|
||||
st_DrawTex(ctx, x, y, z, width, height);
|
||||
|
||||
end:
|
||||
_mesa_set_vp_override(ctx, GL_FALSE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "draw_validate.h"
|
||||
#include "enable.h"
|
||||
#include "errors.h"
|
||||
#include "framebuffer.h"
|
||||
#include "light.h"
|
||||
#include "mtypes.h"
|
||||
#include "enums.h"
|
||||
|
|
@ -363,6 +364,93 @@ _mesa_set_multisample(struct gl_context *ctx, GLboolean state)
|
|||
ctx->Multisample.Enabled = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to enable or disable GL_EXT_shader_pixel_local_storage
|
||||
*/
|
||||
static GLboolean
|
||||
_mesa_set_pixel_local_storage(struct gl_context *ctx, GLboolean state)
|
||||
{
|
||||
if (!state) {
|
||||
/* turning the feature off is always safe */
|
||||
ctx->PixelLocalStorage = state;
|
||||
return state;
|
||||
}
|
||||
/* check that turning the feature on is legal */
|
||||
struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
const char *func = "glEnable(SHADER_PIXEL_LOCAL_STORAGE)";
|
||||
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
* "INVALID_OPERATION is generated if the application attempts enable
|
||||
* pixel local storage while the value of SAMPLE_BUFFERS is one."
|
||||
*
|
||||
* calling _mesa_GetIntegerv(SAMPLE_BUFFERS,...) has the side effect of
|
||||
* updating the frame buffer state with any pending attachment changes
|
||||
*/
|
||||
GLint sample_buffers = 0;
|
||||
_mesa_GetIntegerv(GL_SAMPLE_BUFFERS, &sample_buffers);
|
||||
if (sample_buffers != 0) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s: SAMPLE_BUFFERS==1", func);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (_mesa_is_user_fbo(fb)) {
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
* "INVALID_FRAMEBUFFER_OPERATION is generated if the application
|
||||
* attempts to enable pixel local storage while the current draw
|
||||
* framebuffer is incomplete."
|
||||
*/
|
||||
if (fb->_Status == 0)
|
||||
_mesa_test_framebuffer_completeness(ctx, fb);
|
||||
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
|
||||
"%s: incomplete framebuffer", func);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
int nz_color_attachments = 0;
|
||||
for (int i = 0; i < BUFFER_COUNT && nz_color_attachments < 1; i++) {
|
||||
switch(i) {
|
||||
case BUFFER_COLOR0:
|
||||
case BUFFER_DEPTH:
|
||||
case BUFFER_STENCIL:
|
||||
case BUFFER_NONE:
|
||||
break;
|
||||
default:
|
||||
if (fb->Attachment[i].Type != GL_NONE)
|
||||
nz_color_attachments++;
|
||||
}
|
||||
}
|
||||
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
* "INVALID_OPERATION is generated if the application attempts to
|
||||
* enable pixel local storage while the current draw framebuffer is
|
||||
* a user-defined framebuffer object and has an image attached to
|
||||
* any color attachment other than color attachment zero."
|
||||
*/
|
||||
if (nz_color_attachments > 0) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s: too many color attachments", func);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
* "INVALID_OPERATION is generated if the application attempts to
|
||||
* enable pixel local storage while the current draw framebuffer is
|
||||
* a user-defined framebuffer and the draw buffer for any color
|
||||
* output other than color output zero is not NONE."
|
||||
*/
|
||||
for (int i = 1; i < fb->_NumColorDrawBuffers; i++) {
|
||||
if (fb->_ColorDrawBufferIndexes[i] != BUFFER_NONE) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s: too many draw buffers", func);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to enable or disable GL_FRAMEBUFFER_SRGB, skipping the
|
||||
* check for whether the API supports it (GLES doesn't).
|
||||
|
|
@ -1332,6 +1420,18 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
|
|||
ctx->pipe->set_frontend_noop(ctx->pipe, state);
|
||||
break;
|
||||
|
||||
case GL_SHADER_PIXEL_LOCAL_STORAGE_EXT:
|
||||
if (!_mesa_has_EXT_shader_pixel_local_storage(ctx))
|
||||
goto invalid_enum_error;
|
||||
if (ctx->PixelLocalStorage == state)
|
||||
return;
|
||||
FLUSH_VERTICES(ctx, 0, 0);
|
||||
ST_SET_STATE(ctx->NewDriverState, ST_NEW_FB_STATE);
|
||||
/* need to validate that pixel local storage is legal */
|
||||
ctx->PixelLocalStorage = _mesa_set_pixel_local_storage(ctx, state);
|
||||
_mesa_update_valid_to_render_state(ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto invalid_enum_error;
|
||||
}
|
||||
|
|
@ -2017,6 +2117,11 @@ _mesa_IsEnabled( GLenum cap )
|
|||
goto invalid_enum_error;
|
||||
return ctx->IntelBlackholeRender;
|
||||
|
||||
case GL_SHADER_PIXEL_LOCAL_STORAGE_EXT:
|
||||
if (!_mesa_has_EXT_shader_pixel_local_storage(ctx))
|
||||
goto invalid_enum_error;
|
||||
return ctx->PixelLocalStorage;
|
||||
|
||||
default:
|
||||
goto invalid_enum_error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ EXT(EXT_shader_image_load_store , EXT_shader_image_load_store
|
|||
EXT(EXT_shader_implicit_conversions , dummy_true , x , x , x , 31, 2013)
|
||||
EXT(EXT_shader_integer_mix , EXT_shader_integer_mix , GLL, GLC, x , 30, 2013)
|
||||
EXT(EXT_shader_io_blocks , dummy_true , x , x , x , 31, 2014)
|
||||
EXT(EXT_shader_pixel_local_storage , EXT_shader_pixel_local_storage , x , x , x , 30, 2014)
|
||||
EXT(EXT_shader_realtime_clock , EXT_shader_realtime_clock , GLL, GLC, x , 31, 2018)
|
||||
EXT(EXT_shader_samples_identical , EXT_shader_samples_identical , GLL, GLC, x , 31, 2015)
|
||||
EXT(EXT_shadow_funcs , ARB_shadow , GLL, x , x , x , 2002)
|
||||
|
|
|
|||
|
|
@ -3362,6 +3362,17 @@ bind_framebuffer(GLenum target, GLuint framebuffer)
|
|||
return;
|
||||
}
|
||||
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
*
|
||||
* "INVALID_OPERATION is generated if pixel local storage is enabled and
|
||||
* the application attempts to bind a new draw framebuffer, [...]"
|
||||
*/
|
||||
if (bindDrawBuf && ctx->PixelLocalStorage) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glBindFrameBuffer(draw fb): pixel local storage enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (framebuffer) {
|
||||
_mesa_HashLockMutex(&ctx->Shared->FrameBuffers);
|
||||
|
||||
|
|
@ -3478,8 +3489,9 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
|
|||
GLint i;
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
const char *func = "glDeleteFramebuffers";
|
||||
if (n < 0) {
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "glDeleteFramebuffers(n < 0)");
|
||||
_mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3496,6 +3508,19 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
|
|||
if (fb == ctx->DrawBuffer) {
|
||||
/* bind default */
|
||||
assert(fb->RefCount >= 2);
|
||||
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
*
|
||||
* "INVALID_OPERATION is generated if pixel local storage is
|
||||
* enabled and the application attempts to [...] delete the
|
||||
* currently bound draw framebuffer, [...]"
|
||||
*/
|
||||
if (ctx->PixelLocalStorage) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(draw fb): pixel local storage enabled", func);
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
if (fb == ctx->ReadBuffer) {
|
||||
|
|
@ -4248,6 +4273,18 @@ framebuffer_texture_with_dims(int dims, GLenum target, GLuint framebuffer,
|
|||
struct gl_framebuffer *fb;
|
||||
struct gl_texture_object *texObj;
|
||||
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
*
|
||||
* "INVALID_OPERATION is generated if pixel local storage is enabled and
|
||||
* the application attempts to [...] modify any attachment of the
|
||||
* currently bound draw framebuffer including their underlying storage."
|
||||
*/
|
||||
if (ctx->PixelLocalStorage) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(): pixel local storage enabled", caller);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the framebuffer object */
|
||||
if (dsa) {
|
||||
fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer, caller);
|
||||
|
|
@ -4376,6 +4413,18 @@ frame_buffer_texture(GLuint framebuffer, GLenum target,
|
|||
}
|
||||
}
|
||||
|
||||
/* The GL_EXT_shader_pixel_local_storage spec says:
|
||||
*
|
||||
* "INVALID_OPERATION is generated if pixel local storage is enabled and
|
||||
* the application attempts to [...] modify any attachment of the
|
||||
* currently bound draw framebuffer including their underlying storage."
|
||||
*/
|
||||
if (!no_error && ctx->PixelLocalStorage) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(): pixel local storage enabled", func);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the framebuffer object */
|
||||
struct gl_framebuffer *fb;
|
||||
if (no_error) {
|
||||
|
|
|
|||
|
|
@ -602,6 +602,7 @@ EXTRA_EXT(KHR_shader_subgroup);
|
|||
EXTRA_EXT(OVR_multiview);
|
||||
EXTRA_EXT(NV_timeline_semaphore);
|
||||
EXTRA_EXT(EXT_mesh_shader);
|
||||
EXTRA_EXT(EXT_shader_pixel_local_storage);
|
||||
|
||||
static const int extra_ARB_gl_spirv_or_es2_compat[] = {
|
||||
EXT(ARB_gl_spirv),
|
||||
|
|
|
|||
|
|
@ -703,6 +703,10 @@ descriptor=[
|
|||
[ "VIEWPORT_SWIZZLE_Z_NV", "LOC_CUSTOM, TYPE_ENUM, 0, extra_NV_viewport_swizzle" ],
|
||||
[ "VIEWPORT_SWIZZLE_W_NV", "LOC_CUSTOM, TYPE_ENUM, 0, extra_NV_viewport_swizzle" ],
|
||||
|
||||
# GL_EXT_shader_pixel_local_storage
|
||||
[ "MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT", "CAPS_UINT(shader_pixel_local_storage_size), extra_EXT_shader_pixel_local_storage" ],
|
||||
[ "MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT", "CAPS_UINT(shader_pixel_local_storage_fast_size), extra_EXT_shader_pixel_local_storage" ],
|
||||
|
||||
# GL_KHR_shader_subgroup
|
||||
[ "SUBGROUP_SIZE_KHR", "CONTEXT_INT(Const.ShaderSubgroupSize), extra_KHR_shader_subgroup" ],
|
||||
[ "SUBGROUP_SUPPORTED_STAGES_KHR", "CONTEXT_INT(Const.ShaderSubgroupSupportedStages), extra_KHR_shader_subgroup" ],
|
||||
|
|
|
|||
|
|
@ -3593,6 +3593,7 @@ struct gl_context
|
|||
GLboolean RepresentativeFragmentTest; /**< GL_REPRESENTATIVE_FRAGMENT_TEST_NV */
|
||||
|
||||
GLboolean IntelBlackholeRender; /**< GL_INTEL_blackhole_render */
|
||||
GLboolean PixelLocalStorage; /**< GL_EXT_shader_pixel_local_storage */
|
||||
|
||||
/** Does glVertexAttrib(0) alias glVertex()? */
|
||||
bool _AttribZeroAliasesVertex;
|
||||
|
|
|
|||
|
|
@ -1116,6 +1116,7 @@ void st_init_extensions(struct pipe_screen *screen,
|
|||
#else
|
||||
EXT_CAP(EXT_semaphore_win32, fence_signal);
|
||||
#endif
|
||||
EXT_CAP(EXT_shader_pixel_local_storage, shader_pixel_local_storage_size);
|
||||
EXT_CAP(EXT_shader_realtime_clock, shader_realtime_clock);
|
||||
EXT_CAP(EXT_shader_samples_identical, shader_samples_identical);
|
||||
EXT_CAP(EXT_texture_array, max_texture_array_layers);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue