/** \{ */
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;
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,
"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
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) {
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");
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");
+ }
+
}
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;
+ }
}
"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,
}
}
+ /* 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);
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
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. */
/** 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;
}
}
+/**
+ * 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,
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
/* 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 */
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];