From 456279bb33e09679de61d560aeafa74bb902fe43 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Mon, 26 Dec 2011 19:39:25 -0800 Subject: mesa: Fix transform feedback of gl_ClipDistance. On drivers that set gl_shader_compiler_options::LowerClipDistance (for example i965), references to gl_ClipDistance (a float[8] array) will be converted to references to gl_ClipDistanceMESA (a vec4[2] array). This patch modifies the linker so that requests for transform feedback of gl_ClipDistance are similarly converted. Fixes Piglit test "EXT_transform_feedback/builtin-varyings gl_ClipDistance". Reviewed-by: Kenneth Graunke --- src/glsl/linker.cpp | 59 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index e98b4ca..c778d9a 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1376,8 +1376,8 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode) class tfeedback_decl { public: - bool init(struct gl_shader_program *prog, const void *mem_ctx, - const char *input); + bool init(struct gl_context *ctx, struct gl_shader_program *prog, + const void *mem_ctx, const char *input); static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y); bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog, ir_variable *output_var); @@ -1434,6 +1434,13 @@ private: unsigned array_index; /** + * Which component to extract from the vertex shader output location that + * the linker assigned to this variable. -1 if all components should be + * extracted. + */ + int single_component; + + /** * The vertex shader output location that the linker assigned for this * variable. -1 if a location hasn't been assigned yet. */ @@ -1462,8 +1469,8 @@ private: * reported using linker_error(), and false is returned. */ bool -tfeedback_decl::init(struct gl_shader_program *prog, const void *mem_ctx, - const char *input) +tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog, + const void *mem_ctx, const char *input) { /* We don't have to be pedantic about what is a valid GLSL variable name, * because any variable with an invalid name can't exist in the IR anyway. @@ -1471,23 +1478,34 @@ tfeedback_decl::init(struct gl_shader_program *prog, const void *mem_ctx, this->location = -1; this->orig_name = input; + this->single_component = -1; const char *bracket = strrchr(input, '['); if (bracket) { this->var_name = ralloc_strndup(mem_ctx, input, bracket - input); - if (sscanf(bracket, "[%u]", &this->array_index) == 1) { - this->is_array = true; - return true; + if (sscanf(bracket, "[%u]", &this->array_index) != 1) { + linker_error(prog, "Cannot parse transform feedback varying %s", input); + return false; } + this->is_array = true; } else { this->var_name = ralloc_strdup(mem_ctx, input); this->is_array = false; - return true; } - linker_error(prog, "Cannot parse transform feedback varying %s", input); - return false; + /* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, we need + * to convert a request for gl_ClipDistance[n] into a request for a + * component of gl_ClipDistanceMESA[n/4]. + */ + if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance && + strcmp(this->var_name, "gl_ClipDistance") == 0) { + this->var_name = "gl_ClipDistanceMESA"; + this->single_component = this->array_index % 4; + this->array_index /= 4; + } + + return true; } @@ -1504,6 +1522,8 @@ tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y) return false; if (x.is_array && x.array_index != y.array_index) return false; + if (x.single_component != y.single_component) + return false; return true; } @@ -1602,13 +1622,16 @@ tfeedback_decl::store(struct gl_shader_program *prog, return false; } for (unsigned v = 0; v < this->matrix_columns; ++v) { + unsigned num_components = + this->single_component >= 0 ? 1 : this->vector_elements; info->Outputs[info->NumOutputs].OutputRegister = this->location + v; - info->Outputs[info->NumOutputs].NumComponents = this->vector_elements; + info->Outputs[info->NumOutputs].NumComponents = num_components; info->Outputs[info->NumOutputs].OutputBuffer = buffer; info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer]; - info->Outputs[info->NumOutputs].ComponentOffset = 0; + info->Outputs[info->NumOutputs].ComponentOffset = + this->single_component >= 0 ? this->single_component : 0; ++info->NumOutputs; - info->BufferStride[buffer] += this->vector_elements; + info->BufferStride[buffer] += num_components; } info->Varyings[varying].Name = ralloc_strdup(prog, this->orig_name); @@ -1632,12 +1655,12 @@ tfeedback_decl::store(struct gl_shader_program *prog, * is returned. */ static bool -parse_tfeedback_decls(struct gl_shader_program *prog, const void *mem_ctx, - unsigned num_names, char **varying_names, - tfeedback_decl *decls) +parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, + const void *mem_ctx, unsigned num_names, + char **varying_names, tfeedback_decl *decls) { for (unsigned i = 0; i < num_names; ++i) { - if (!decls[i].init(prog, mem_ctx, varying_names[i])) + if (!decls[i].init(ctx, prog, mem_ctx, varying_names[i])) return false; /* From GL_EXT_transform_feedback: * A program will fail to link if: @@ -2213,7 +2236,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) tfeedback_decls = ralloc_array(mem_ctx, tfeedback_decl, prog->TransformFeedback.NumVarying); - if (!parse_tfeedback_decls(prog, mem_ctx, num_tfeedback_decls, + if (!parse_tfeedback_decls(ctx, prog, mem_ctx, num_tfeedback_decls, prog->TransformFeedback.VaryingNames, tfeedback_decls)) goto done; -- cgit v1.1