From: Timothy Arceri Date: Wed, 24 Feb 2016 05:40:32 +0000 (+1100) Subject: glsl: basic linking support for xfb qualifiers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0c66460fc65e1c45ec2268c978ea11b259441212;p=mesa.git glsl: basic linking support for xfb qualifiers This adds the initial infrastructure for enabling transform feedback mode via in shader qualifiers and adds initial buffer support. Reviewed-by: Dave Airlie --- diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp index 57c3d217200..33eb7d0e8bc 100644 --- a/src/compiler/glsl/link_varyings.cpp +++ b/src/compiler/glsl/link_varyings.cpp @@ -715,7 +715,8 @@ tfeedback_decl::get_num_outputs() const bool tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, struct gl_transform_feedback_info *info, - unsigned buffer, const unsigned max_outputs) const + unsigned buffer, const unsigned max_outputs, + bool has_xfb_qualifiers) const { assert(!this->next_buffer_separator); @@ -858,7 +859,7 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, bool store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, unsigned num_tfeedback_decls, - tfeedback_decl *tfeedback_decls) + tfeedback_decl *tfeedback_decls, bool has_xfb_qualifiers) { bool separate_attribs_mode = prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS; @@ -885,11 +886,12 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, unsigned num_buffers = 0; - if (separate_attribs_mode) { + if (!has_xfb_qualifiers && separate_attribs_mode) { /* GL_SEPARATE_ATTRIBS */ for (unsigned i = 0; i < num_tfeedback_decls; ++i) { if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback, - num_buffers, num_outputs)) + num_buffers, num_outputs, + has_xfb_qualifiers)) return false; num_buffers++; @@ -898,6 +900,9 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, else { /* GL_INVERLEAVED_ATTRIBS */ int buffer_stream_id = -1; + unsigned buffer = + num_tfeedback_decls ? tfeedback_decls[0].get_buffer() : 0; + for (unsigned i = 0; i < num_tfeedback_decls; ++i) { if (tfeedback_decls[i].is_next_buffer_separator()) { num_buffers++; @@ -920,9 +925,16 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, return false; } + if (has_xfb_qualifiers) { + buffer = tfeedback_decls[i].get_buffer(); + } else { + buffer = num_buffers; + } + if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback, - num_buffers, num_outputs)) + num_buffers, num_outputs, + has_xfb_qualifiers)) return false; } num_buffers++; diff --git a/src/compiler/glsl/link_varyings.h b/src/compiler/glsl/link_varyings.h index 339e9cf2f18..7165ecb9184 100644 --- a/src/compiler/glsl/link_varyings.h +++ b/src/compiler/glsl/link_varyings.h @@ -98,7 +98,7 @@ public: unsigned get_num_outputs() const; bool store(struct gl_context *ctx, struct gl_shader_program *prog, struct gl_transform_feedback_info *info, unsigned buffer, - const unsigned max_outputs) const; + const unsigned max_outputs, bool has_xfb_qualifiers) const; const tfeedback_candidate *find_candidate(gl_shader_program *prog, hash_table *tfeedback_candidates); @@ -301,7 +301,8 @@ remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object, bool store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, unsigned num_tfeedback_decls, - tfeedback_decl *tfeedback_decls); + tfeedback_decl *tfeedback_decls, + bool has_xfb_qualifiers); bool assign_varying_locations(struct gl_context *ctx, diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index cd35464eeeb..3ae958cacb7 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -4169,9 +4169,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) return; } - tfeedback_decl *tfeedback_decls = NULL; - unsigned num_tfeedback_decls = prog->TransformFeedback.NumVarying; + unsigned num_tfeedback_decls = 0; unsigned int num_explicit_uniform_locs = 0; + bool has_xfb_qualifiers = false; + char **varying_names = NULL; + tfeedback_decl *tfeedback_decls = NULL; void *mem_ctx = ralloc_context(NULL); // temporary linker context @@ -4481,6 +4483,30 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } + /* From the ARB_enhanced_layouts spec: + * + * "If the shader used to record output variables for transform feedback + * varyings uses the "xfb_buffer", "xfb_offset", or "xfb_stride" layout + * qualifiers, the values specified by TransformFeedbackVaryings are + * ignored, and the set of variables captured for transform feedback is + * instead derived from the specified layout qualifiers." + */ + for (int i = MESA_SHADER_FRAGMENT - 1; i >= 0; i--) { + /* Find last stage before fragment shader */ + if (prog->_LinkedShaders[i]) { + has_xfb_qualifiers = + process_xfb_layout_qualifiers(mem_ctx, prog->_LinkedShaders[i], + &num_tfeedback_decls, + &varying_names); + break; + } + } + + if (!has_xfb_qualifiers) { + num_tfeedback_decls = prog->TransformFeedback.NumVarying; + varying_names = prog->TransformFeedback.VaryingNames; + } + if (num_tfeedback_decls != 0) { /* From GL_EXT_transform_feedback: * A program will fail to link if: @@ -4497,10 +4523,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } tfeedback_decls = ralloc_array(mem_ctx, tfeedback_decl, - prog->TransformFeedback.NumVarying); + num_tfeedback_decls); if (!parse_tfeedback_decls(ctx, prog, mem_ctx, num_tfeedback_decls, - prog->TransformFeedback.VaryingNames, - tfeedback_decls)) + varying_names, tfeedback_decls)) goto done; } @@ -4580,7 +4605,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } } - if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls)) + if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls, + has_xfb_qualifiers)) goto done; update_array_sizes(prog);