[Mesa-dev] [PATCH 25/37] glsl: validate global out xfb_stride qualifiers and set stride on empty buffers
Timothy Arceri
timothy.arceri at collabora.com
Tue Mar 15 12:57:15 UTC 2016
Here we use the built-in validation in
ast_layout_expression::process_qualifier_constant() to check for mismatching
global out strides on buffers in a single shader.
>From the ARB_enhanced_layouts spec:
"While *xfb_stride* can be declared multiple times for the same buffer,
it is a compile-time or link-time error to have different values
specified for the stride for the same buffer."
For intrastage validation a new helper link_xfb_stride_layout_qualifiers()
is created. We also take this opportunity to make sure stride is at least
a multiple of 4, we will validate doubles at a later stage.
>From the ARB_enhanced_layouts spec:
"If the buffer is capturing any double-typed outputs, the stride must
be a multiple of 8, otherwise it must be a multiple of 4, or a
compile-time or link-time error results."
Finally we update store_tfeedback_info() to apply the strides to
LinkedTransformFeedback and update the buffers bitmask to mark any global
buffers with a stride as active. For example a shader with:
layout (xfb_buffer = 0, xfb_offset = 0) out vec4 gs_fs;
layout (xfb_buffer = 1, xfb_stride = 64) out;
Is expected to have a buffer bound to both 0 and 1.
>From the ARB_enhanced_layouts spec:
"A binding point requires a bound buffer object if and only if its
associated stride in the program object used for transform feedback
primitive capture is non-zero."
---
src/compiler/glsl/glsl_parser_extras.cpp | 11 ++++++
src/compiler/glsl/link_varyings.cpp | 11 ++++++
src/compiler/glsl/linker.cpp | 65 ++++++++++++++++++++++++++++++++
src/mesa/main/mtypes.h | 7 ++++
4 files changed, 94 insertions(+)
diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp
index 4415b83..f5890a8 100644
--- a/src/compiler/glsl/glsl_parser_extras.cpp
+++ b/src/compiler/glsl/glsl_parser_extras.cpp
@@ -1614,6 +1614,17 @@ set_shader_inout_layout(struct gl_shader *shader,
assert(!state->fs_early_fragment_tests);
}
+ for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
+ if (state->out_qualifier->out_xfb_stride[i]) {
+ unsigned xfb_stride;
+ if (state->out_qualifier->out_xfb_stride[i]->
+ process_qualifier_constant(state, "xfb_stride", &xfb_stride,
+ true)) {
+ shader->TransformFeedback.BufferStride[i] = xfb_stride;
+ }
+ }
+ }
+
switch (shader->Stage) {
case MESA_SHADER_TESS_CTRL:
shader->TessCtrl.VerticesOut = 0;
diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp
index 421b91c..cb096b4 100644
--- a/src/compiler/glsl/link_varyings.cpp
+++ b/src/compiler/glsl/link_varyings.cpp
@@ -996,6 +996,17 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
unsigned buffer =
num_tfeedback_decls ? tfeedback_decls[0].get_buffer() : 0;
+ /* Apply any xfb_stride global qualifiers */
+ if (has_xfb_qualifiers) {
+ for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
+ if (prog->TransformFeedback.BufferStride[j]) {
+ buffers |= 1 << j;
+ prog->LinkedTransformFeedback.Buffers[j].Stride =
+ prog->TransformFeedback.BufferStride[j] / 4;
+ }
+ }
+ }
+
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
if (tfeedback_decls[i].is_next_buffer_separator()) {
num_buffers++;
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index 40d216f..3c961b1 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -1574,6 +1574,69 @@ private:
hash_table *unnamed_interfaces;
};
+/**
+ * Check for conflicting xfb_stride default qualifiers and store buffer stride
+ * for later use.
+ */
+static void
+link_xfb_stride_layout_qualifiers(struct gl_context *ctx,
+ struct gl_shader_program *prog,
+ struct gl_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
+{
+ for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
+ linked_shader->TransformFeedback.BufferStride[i] = 0;
+ }
+
+ for (unsigned i = 0; i < num_shaders; i++) {
+ struct gl_shader *shader = shader_list[i];
+
+ for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
+ if (shader->TransformFeedback.BufferStride[j]) {
+ if (linked_shader->TransformFeedback.BufferStride[j] != 0 &&
+ shader->TransformFeedback.BufferStride[j] != 0 &&
+ linked_shader->TransformFeedback.BufferStride[j] !=
+ shader->TransformFeedback.BufferStride[j]) {
+ linker_error(prog,
+ "intrastage shaders defined with conflicting "
+ "xfb_stride for buffer %d (%d and %d)\n", j,
+ linked_shader->TransformFeedback.BufferStride[j],
+ shader->TransformFeedback.BufferStride[j]);
+ return;
+ }
+
+ if (shader->TransformFeedback.BufferStride[j])
+ linked_shader->TransformFeedback.BufferStride[j] =
+ shader->TransformFeedback.BufferStride[j];
+ }
+ }
+ }
+
+ for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
+ if (linked_shader->TransformFeedback.BufferStride[j]) {
+ prog->TransformFeedback.BufferStride[j] =
+ linked_shader->TransformFeedback.BufferStride[j];
+
+ /* We will validate doubles at a later stage */
+ if (prog->TransformFeedback.BufferStride[j] % 4) {
+ linker_error(prog, "invalid qualifier xfb_stride=%d must be a "
+ "multiple of 4 or if its applied to a type that is "
+ "or contains a double a multiple of 8.",
+ prog->TransformFeedback.BufferStride[j]);
+ return;
+ }
+
+ if (prog->TransformFeedback.BufferStride[j] / 4 >
+ ctx->Const.MaxTransformFeedbackInterleavedComponents) {
+ linker_error(prog,
+ "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
+ "limit has been exceeded.");
+ return;
+ }
+ }
+ }
+}
/**
* Performs the cross-validation of tessellation control shader vertices and
@@ -2085,6 +2148,8 @@ link_intrastage_shaders(void *mem_ctx,
link_tes_in_layout_qualifiers(prog, linked, shader_list, num_shaders);
link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders);
link_cs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
+ link_xfb_stride_layout_qualifiers(ctx, prog, linked, shader_list,
+ num_shaders);
populate_symbol_table(linked);
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 852d0b5..217afe8 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2337,6 +2337,11 @@ struct gl_shader
bool origin_upper_left;
bool pixel_center_integer;
+ struct {
+ /** Global xfb_stride out qualifier if any */
+ GLuint BufferStride[MAX_FEEDBACK_BUFFERS];
+ } TransformFeedback;
+
/**
* Tessellation Control shader state from layout qualifiers.
*/
@@ -2680,6 +2685,8 @@ struct gl_shader_program
*/
struct {
GLenum BufferMode;
+ /** Global xfb_stride out qualifier if any */
+ GLuint BufferStride[MAX_FEEDBACK_BUFFERS];
GLuint NumVarying;
GLchar **VaryingNames; /**< Array [NumVarying] of char * */
} TransformFeedback;
--
2.5.0
More information about the mesa-dev
mailing list