From page 76 (page 80 of the PDF) of the GLSL 4.60 v.5 spec: " No aliasing in output buffers is allowed: It is a compile-time or link-time error to specify variables with overlapping transform feedback offsets."
Currently, this is expected to fail, but it succeeds: " ... layout (xfb_offset = 0) out vec2 a; layout (xfb_offset = 0) out vec4 b; ... " v2: use a data structure to track the used components instead of a nested loop (Ilia). Cc: Timothy Arceri <tarc...@itsqueeze.com> Cc: Ilia Mirkin <imir...@alum.mit.edu> Signed-off-by: Andres Gomez <ago...@igalia.com> --- src/compiler/glsl/link_varyings.cpp | 89 ++++++++++++++++++++++------- src/mesa/main/mtypes.h | 3 + 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp index 8c7d6c14c8f..95e9ae895d2 100644 --- a/src/compiler/glsl/link_varyings.cpp +++ b/src/compiler/glsl/link_varyings.cpp @@ -1173,6 +1173,73 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, unsigned location = this->location; unsigned location_frac = this->location_frac; unsigned num_components = this->num_components(); + + /* From GL_EXT_transform_feedback: + * A program will fail to link if: + * + * * the total number of components to capture is greater than the + * constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT and + * the buffer mode is INTERLEAVED_ATTRIBS_EXT. + * + * From GL_ARB_enhanced_layouts: + * + * "The resulting stride (implicit or explicit) must be less than or + * equal to the implementation-dependent constant + * gl_MaxTransformFeedbackInterleavedComponents." + */ + if ((prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS || + has_xfb_qualifiers) && + xfb_offset + num_components > + ctx->Const.MaxTransformFeedbackInterleavedComponents) { + linker_error(prog, + "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS " + "limit has been exceeded."); + return false; + } + + { + /* From the OpenGL 4.60.5 spec, section 4.4.2. Output Layout + * Qualifiers, Page 76, (Transform Feedback Layout Qualifiers): + * + * "No aliasing in output buffers is allowed: It is a compile-time or + * link-time error to specify variables with overlapping transform + * feedback offsets." + */ + const unsigned max_components = + ctx->Const.MaxTransformFeedbackInterleavedComponents; + const unsigned first_component = xfb_offset; + const unsigned last_component = xfb_offset + num_components - 1; + const unsigned start_word = BITSET_BITWORD(first_component); + const unsigned end_word = BITSET_BITWORD(last_component); + assert(last_component < max_components); + + if (!info->Buffers[buffer].UsedComponents) { + info->Buffers[buffer].UsedComponents = + rzalloc_array(info, BITSET_WORD, BITSET_WORDS(max_components)); + } + BITSET_WORD *used = info->Buffers[buffer].UsedComponents; + + for (unsigned word = start_word; word <= end_word; word++) { + unsigned start_range = 0; + unsigned end_range = BITSET_WORDBITS - 1; + + if (word == start_word) + start_range = first_component % BITSET_WORDBITS; + + if (word == end_word) + end_range = last_component % BITSET_WORDBITS; + + if (used[word] & BITSET_RANGE(start_range, end_range)) { + linker_error(prog, + "variable '%s', xfb_offset (%d) " + "is causing aliasing.", + this->orig_name, xfb_offset * 4); + return false; + } + used[word] |= BITSET_RANGE(start_range, end_range); + } + } + while (num_components > 0) { unsigned output_size = MIN2(num_components, 4 - location_frac); assert((info->NumOutputs == 0 && max_outputs == 0) || @@ -1223,28 +1290,6 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, info->Buffers[buffer].Stride = xfb_offset; } - /* From GL_EXT_transform_feedback: - * A program will fail to link if: - * - * * the total number of components to capture is greater than - * the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT - * and the buffer mode is INTERLEAVED_ATTRIBS_EXT. - * - * From GL_ARB_enhanced_layouts: - * - * "The resulting stride (implicit or explicit) must be less than or - * equal to the implementation-dependent constant - * gl_MaxTransformFeedbackInterleavedComponents." - */ - if ((prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS || - has_xfb_qualifiers) && - info->Buffers[buffer].Stride > - ctx->Const.MaxTransformFeedbackInterleavedComponents) { - linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS " - "limit has been exceeded."); - return false; - } - store_varying: info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index dda96cd2f19..a32128ec6b9 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -49,6 +49,7 @@ #include "compiler/glsl/list.h" #include "util/simple_mtx.h" #include "util/u_dynarray.h" +#include "util/bitset.h" #ifdef __cplusplus @@ -1764,6 +1765,8 @@ struct gl_transform_feedback_buffer uint32_t NumVaryings; + BITSET_WORD *UsedComponents; + /** * Total number of components stored in each buffer. This may be used by * hardware back-ends to determine the correct stride when interleaving -- 2.20.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev