glsl: add NV_viewport_array2 support
This enables gl_Layer/gl_ViewportIndex when the ext is enabled, as well as adding the new gl_ViewportMask[] array and viewport_relative layout qualifier for gl_Layer. Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Acked-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4529>
This commit is contained in:
parent
54424a3d13
commit
cc6661bfc8
|
@ -663,6 +663,12 @@ struct ast_type_qualifier {
|
|||
/** \{ */
|
||||
unsigned derivative_group:1;
|
||||
/** \} */
|
||||
|
||||
/**
|
||||
* Flag set if GL_NV_viewport_array2 viewport_relative layout
|
||||
* qualifier is used.
|
||||
*/
|
||||
unsigned viewport_relative:1;
|
||||
}
|
||||
/** \brief Set of flags, accessed by name. */
|
||||
q;
|
||||
|
|
|
@ -3548,6 +3548,16 @@ is_conflicting_fragcoord_redeclaration(struct _mesa_glsl_parse_state *state,
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_conflicting_layer_redeclaration(struct _mesa_glsl_parse_state *state,
|
||||
const struct ast_type_qualifier *qual)
|
||||
{
|
||||
if (state->redeclares_gl_layer) {
|
||||
return state->layer_viewport_relative != qual->flags.q.viewport_relative;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void
|
||||
validate_array_dimensions(const glsl_type *t,
|
||||
struct _mesa_glsl_parse_state *state,
|
||||
|
@ -3937,6 +3947,21 @@ apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
|
|||
"sample_interlock_ordered and sample_interlock_unordered, "
|
||||
"only valid in fragment shader input layout declaration.");
|
||||
}
|
||||
|
||||
if (var->name != NULL && strcmp(var->name, "gl_Layer") == 0) {
|
||||
if (is_conflicting_layer_redeclaration(state, qual)) {
|
||||
_mesa_glsl_error(loc, state, "gl_Layer redeclaration with "
|
||||
"different viewport_relative setting than earlier");
|
||||
}
|
||||
state->redeclares_gl_layer = 1;
|
||||
if (qual->flags.q.viewport_relative) {
|
||||
state->layer_viewport_relative = 1;
|
||||
}
|
||||
} else if (qual->flags.q.viewport_relative) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"viewport_relative qualifier "
|
||||
"can only be applied to gl_Layer.");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -4378,6 +4403,11 @@ get_variable_being_redeclared(ir_variable **var_ptr, YYLTYPE loc,
|
|||
earlier->data.precision = var->data.precision;
|
||||
earlier->data.memory_coherent = var->data.memory_coherent;
|
||||
|
||||
} else if (state->NV_viewport_array2_enable &&
|
||||
strcmp(var->name, "gl_Layer") == 0 &&
|
||||
earlier->data.how_declared == ir_var_declared_implicitly) {
|
||||
/* No need to do anything, just allow it. Qualifier is stored in state */
|
||||
|
||||
} else if ((earlier->data.how_declared == ir_var_declared_implicitly &&
|
||||
state->allow_builtin_variable_redeclaration) ||
|
||||
allow_all_redeclarations) {
|
||||
|
|
|
@ -1097,15 +1097,32 @@ builtin_variable_generator::generate_vs_special_vars()
|
|||
add_system_value(SYSTEM_VALUE_DRAW_ID, int_t, "gl_DrawIDARB");
|
||||
}
|
||||
if (state->AMD_vertex_shader_layer_enable ||
|
||||
state->ARB_shader_viewport_layer_array_enable) {
|
||||
state->ARB_shader_viewport_layer_array_enable ||
|
||||
state->NV_viewport_array2_enable) {
|
||||
var = add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer");
|
||||
var->data.interpolation = INTERP_MODE_FLAT;
|
||||
}
|
||||
if (state->AMD_vertex_shader_viewport_index_enable ||
|
||||
state->ARB_shader_viewport_layer_array_enable) {
|
||||
state->ARB_shader_viewport_layer_array_enable ||
|
||||
state->NV_viewport_array2_enable) {
|
||||
var = add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex");
|
||||
var->data.interpolation = INTERP_MODE_FLAT;
|
||||
}
|
||||
if (state->NV_viewport_array2_enable) {
|
||||
/* From the NV_viewport_array2 specification:
|
||||
*
|
||||
* "The variable gl_ViewportMask[] is available as an output variable
|
||||
* in the VTG languages. The array has ceil(v/32) elements where v is
|
||||
* the maximum number of viewports supported by the implementation."
|
||||
*
|
||||
* Since no drivers expose more than 16 viewports, we can simply set the
|
||||
* array size to 1 rather than computing it and dealing with varying
|
||||
* slot complication.
|
||||
*/
|
||||
var = add_output(VARYING_SLOT_VIEWPORT_MASK, array(int_t, 1),
|
||||
"gl_ViewportMask");
|
||||
var->data.interpolation = INTERP_MODE_FLAT;
|
||||
}
|
||||
if (compatibility) {
|
||||
add_input(VERT_ATTRIB_POS, vec4_t, "gl_Vertex");
|
||||
add_input(VERT_ATTRIB_NORMAL, vec3_t, "gl_Normal");
|
||||
|
@ -1155,6 +1172,17 @@ builtin_variable_generator::generate_tcs_special_vars()
|
|||
add_output(bbox_slot, array(vec4_t, 2), GLSL_PRECISION_HIGH,
|
||||
"gl_BoundingBox")->data.patch = 1;
|
||||
}
|
||||
|
||||
/* NOTE: These are completely pointless. Writing these will never go
|
||||
* anywhere. But the specs demands it. So we add them with a slot of -1,
|
||||
* which makes the data go nowhere.
|
||||
*/
|
||||
if (state->NV_viewport_array2_enable) {
|
||||
add_output(-1, int_t, "gl_Layer");
|
||||
add_output(-1, int_t, "gl_ViewportIndex");
|
||||
add_output(-1, array(int_t, 1), "gl_ViewportMask");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1183,12 +1211,18 @@ builtin_variable_generator::generate_tes_special_vars()
|
|||
add_system_value(SYSTEM_VALUE_TESS_LEVEL_INNER, array(float_t, 2),
|
||||
GLSL_PRECISION_HIGH, "gl_TessLevelInner");
|
||||
}
|
||||
if (state->ARB_shader_viewport_layer_array_enable) {
|
||||
if (state->ARB_shader_viewport_layer_array_enable ||
|
||||
state->NV_viewport_array2_enable) {
|
||||
var = add_output(VARYING_SLOT_LAYER, int_t, "gl_Layer");
|
||||
var->data.interpolation = INTERP_MODE_FLAT;
|
||||
var = add_output(VARYING_SLOT_VIEWPORT, int_t, "gl_ViewportIndex");
|
||||
var->data.interpolation = INTERP_MODE_FLAT;
|
||||
}
|
||||
if (state->NV_viewport_array2_enable) {
|
||||
var = add_output(VARYING_SLOT_VIEWPORT_MASK, array(int_t, 1),
|
||||
"gl_ViewportMask");
|
||||
var->data.interpolation = INTERP_MODE_FLAT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1208,6 +1242,11 @@ builtin_variable_generator::generate_gs_special_vars()
|
|||
"gl_ViewportIndex");
|
||||
var->data.interpolation = INTERP_MODE_FLAT;
|
||||
}
|
||||
if (state->NV_viewport_array2_enable) {
|
||||
var = add_output(VARYING_SLOT_VIEWPORT_MASK, array(int_t, 1),
|
||||
"gl_ViewportMask");
|
||||
var->data.interpolation = INTERP_MODE_FLAT;
|
||||
}
|
||||
if (state->is_version(400, 320) || state->ARB_gpu_shader5_enable ||
|
||||
state->OES_geometry_shader_enable || state->EXT_geometry_shader_enable) {
|
||||
add_system_value(SYSTEM_VALUE_INVOCATION_ID, int_t, GLSL_PRECISION_HIGH,
|
||||
|
|
|
@ -1709,6 +1709,25 @@ layout_qualifier_id:
|
|||
}
|
||||
}
|
||||
|
||||
/* Layout qualifier for NV_viewport_array2. */
|
||||
if (!$$.flags.i && state->stage != MESA_SHADER_FRAGMENT) {
|
||||
if (match_layout_qualifier($1, "viewport_relative", state) == 0) {
|
||||
$$.flags.q.viewport_relative = 1;
|
||||
}
|
||||
|
||||
if ($$.flags.i && !state->NV_viewport_array2_enable) {
|
||||
_mesa_glsl_error(& @1, state,
|
||||
"qualifier `%s' requires "
|
||||
"GL_NV_viewport_array2", $1);
|
||||
}
|
||||
|
||||
if ($$.flags.i && state->NV_viewport_array2_warn) {
|
||||
_mesa_glsl_warning(& @1, state,
|
||||
"GL_NV_viewport_array2 layout "
|
||||
"identifier `%s' used", $1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$$.flags.i) {
|
||||
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
|
||||
"`%s'", $1);
|
||||
|
|
|
@ -1929,6 +1929,8 @@ set_shader_inout_layout(struct gl_shader *shader,
|
|||
shader->bindless_image = state->bindless_image_specified;
|
||||
shader->bound_sampler = state->bound_sampler_specified;
|
||||
shader->bound_image = state->bound_image_specified;
|
||||
shader->redeclares_gl_layer = state->redeclares_gl_layer;
|
||||
shader->layer_viewport_relative = state->layer_viewport_relative;
|
||||
}
|
||||
|
||||
/* src can be NULL if only the symbols found in the exec_list should be
|
||||
|
|
|
@ -884,6 +884,8 @@ struct _mesa_glsl_parse_state {
|
|||
bool NV_image_formats_warn;
|
||||
bool NV_shader_atomic_float_enable;
|
||||
bool NV_shader_atomic_float_warn;
|
||||
bool NV_viewport_array2_enable;
|
||||
bool NV_viewport_array2_warn;
|
||||
/*@}*/
|
||||
|
||||
/** Extensions supported by the OpenGL implementation. */
|
||||
|
@ -926,6 +928,10 @@ struct _mesa_glsl_parse_state {
|
|||
/** Atomic counter offsets by binding */
|
||||
unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS];
|
||||
|
||||
/** Whether gl_Layer output is viewport-relative. */
|
||||
bool redeclares_gl_layer;
|
||||
bool layer_viewport_relative;
|
||||
|
||||
bool allow_extension_directive_midshader;
|
||||
bool allow_builtin_variable_redeclaration;
|
||||
bool allow_layout_qualifier_on_function_parameter;
|
||||
|
|
|
@ -1816,6 +1816,40 @@ link_bindless_layout_qualifiers(struct gl_shader_program *prog,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for conflicting viewport_relative settings across shaders, and sets
|
||||
* the value for the linked shader.
|
||||
*/
|
||||
static void
|
||||
link_layer_viewport_relative_qualifier(struct gl_shader_program *prog,
|
||||
struct gl_program *gl_prog,
|
||||
struct gl_shader **shader_list,
|
||||
unsigned num_shaders)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* Find first shader with explicit layer declaration */
|
||||
for (i = 0; i < num_shaders; i++) {
|
||||
if (shader_list[i]->redeclares_gl_layer) {
|
||||
gl_prog->info.layer_viewport_relative =
|
||||
shader_list[i]->layer_viewport_relative;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now make sure that each subsequent shader's explicit layer declaration
|
||||
* matches the first one's.
|
||||
*/
|
||||
for (; i < num_shaders; i++) {
|
||||
if (shader_list[i]->redeclares_gl_layer &&
|
||||
shader_list[i]->layer_viewport_relative !=
|
||||
gl_prog->info.layer_viewport_relative) {
|
||||
linker_error(prog, "all gl_Layer redeclarations must have identical "
|
||||
"viewport_relative settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the cross-validation of tessellation control shader vertices and
|
||||
* layout qualifiers for the attached tessellation control shaders,
|
||||
|
@ -2461,6 +2495,8 @@ link_intrastage_shaders(void *mem_ctx,
|
|||
|
||||
link_bindless_layout_qualifiers(prog, shader_list, num_shaders);
|
||||
|
||||
link_layer_viewport_relative_qualifier(prog, gl_prog, shader_list, num_shaders);
|
||||
|
||||
populate_symbol_table(linked, shader_list[0]->symbols);
|
||||
|
||||
/* The pointer to the main function in the final linked shader (i.e., the
|
||||
|
|
|
@ -191,6 +191,9 @@ typedef struct shader_info {
|
|||
/* Whether the shader writes memory, including transform feedback. */
|
||||
bool writes_memory:1;
|
||||
|
||||
/* Whether gl_Layer is viewport-relative */
|
||||
bool layer_viewport_relative:1;
|
||||
|
||||
union {
|
||||
struct {
|
||||
/* Which inputs are doubles */
|
||||
|
|
|
@ -2674,6 +2674,12 @@ struct gl_shader
|
|||
bool bound_sampler;
|
||||
bool bound_image;
|
||||
|
||||
/**
|
||||
* Whether layer output is viewport-relative.
|
||||
*/
|
||||
bool redeclares_gl_layer;
|
||||
bool layer_viewport_relative;
|
||||
|
||||
/** Global xfb_stride out qualifier if any */
|
||||
GLuint TransformFeedbackBufferStride[MAX_FEEDBACK_BUFFERS];
|
||||
|
||||
|
|
Loading…
Reference in New Issue