summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIlia Mirkin <[email protected]>2020-04-10 16:02:09 -0400
committerIlia Mirkin <[email protected]>2020-04-15 20:12:00 -0400
commitcc6661bfc87f6a8a46455ddaf2e0fb1c1fd332ed (patch)
tree9f8dd8677bff5ca9304f0265de9f11a2ee251072 /src
parent54424a3d13f97bb1714f168f127f40d180f78a6b (diff)
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 <[email protected]> Acked-by: Marek Olšák <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4529>
Diffstat (limited to 'src')
-rw-r--r--src/compiler/glsl/ast.h6
-rw-r--r--src/compiler/glsl/ast_to_hir.cpp30
-rw-r--r--src/compiler/glsl/builtin_variables.cpp45
-rw-r--r--src/compiler/glsl/glsl_parser.yy19
-rw-r--r--src/compiler/glsl/glsl_parser_extras.cpp2
-rw-r--r--src/compiler/glsl/glsl_parser_extras.h6
-rw-r--r--src/compiler/glsl/linker.cpp36
-rw-r--r--src/compiler/shader_info.h3
-rw-r--r--src/mesa/main/mtypes.h6
9 files changed, 150 insertions, 3 deletions
diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h
index f6487643d42..3a960c2ff32 100644
--- a/src/compiler/glsl/ast.h
+++ b/src/compiler/glsl/ast.h
@@ -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;
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
index b5b0a509ea1..1201c11b778 100644
--- a/src/compiler/glsl/ast_to_hir.cpp
+++ b/src/compiler/glsl/ast_to_hir.cpp
@@ -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) {
diff --git a/src/compiler/glsl/builtin_variables.cpp b/src/compiler/glsl/builtin_variables.cpp
index 6f960837321..e305ab9b9b8 100644
--- a/src/compiler/glsl/builtin_variables.cpp
+++ b/src/compiler/glsl/builtin_variables.cpp
@@ -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,
diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy
index dc8a8b3db01..944329a92d8 100644
--- a/src/compiler/glsl/glsl_parser.yy
+++ b/src/compiler/glsl/glsl_parser.yy
@@ -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);
diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp
index c6e3999caf5..4f6a493f71a 100644
--- a/src/compiler/glsl/glsl_parser_extras.cpp
+++ b/src/compiler/glsl/glsl_parser_extras.cpp
@@ -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
diff --git a/src/compiler/glsl/glsl_parser_extras.h b/src/compiler/glsl/glsl_parser_extras.h
index dc94a5b94c1..b5e687d6038 100644
--- a/src/compiler/glsl/glsl_parser_extras.h
+++ b/src/compiler/glsl/glsl_parser_extras.h
@@ -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;
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index e0f9c3d06de..292da60b9d9 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -1817,6 +1817,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,
* and propagates them to the linked TCS and linked shader program.
@@ -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
diff --git a/src/compiler/shader_info.h b/src/compiler/shader_info.h
index 13da17fa264..2e22614b75b 100644
--- a/src/compiler/shader_info.h
+++ b/src/compiler/shader_info.h
@@ -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 */
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 487e7e6f326..0f39041f73b 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -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];