diff options
author | Christoph Bumiller <[email protected]> | 2012-01-20 13:24:46 +0100 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2012-01-20 19:24:31 +0100 |
commit | d540af554adfe302387014c0f46d6ac3aaa75121 (patch) | |
tree | 1b470569cc1c0fefd7e14623f903eaf9e0850959 /src/glsl/linker.cpp | |
parent | c96b9834032952492efbd2d1f5511fe225704918 (diff) |
mesa: allocate transform_feedback_info::Outputs array dynamically
The nvc0 gallium driver is advertising 128 MAX_INTERLEAVED_COMPS
which made it always assert in the linker when TFB was used since
the Outputs array was smaller than that maximum.
v2: added assertions
NOTE: This is a candidate for the 8.0 branch.
Reviewed-by: Paul Berry <[email protected]>
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r-- | src/glsl/linker.cpp | 64 |
1 files changed, 40 insertions, 24 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index adedfe6f33a..509575192e7 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1388,9 +1388,10 @@ public: 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); + bool accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count); bool store(struct gl_context *ctx, struct gl_shader_program *prog, struct gl_transform_feedback_info *info, unsigned buffer, - unsigned varying) const; + unsigned varying, const unsigned max_outputs) const; /** @@ -1624,16 +1625,9 @@ tfeedback_decl::assign_location(struct gl_context *ctx, } -/** - * Update gl_transform_feedback_info to reflect this tfeedback_decl. - * - * If an error occurs, the error is reported through linker_error() and false - * is returned. - */ bool -tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, - struct gl_transform_feedback_info *info, - unsigned buffer, unsigned varying) const +tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog, + unsigned *count) { if (!this->is_assigned()) { /* From GL_EXT_transform_feedback: @@ -1648,6 +1642,28 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, return false; } + unsigned translated_size = this->size; + if (this->is_clip_distance_mesa) + translated_size = (translated_size + 3) / 4; + + *count += translated_size * this->matrix_columns; + + return true; +} + + +/** + * Update gl_transform_feedback_info to reflect this tfeedback_decl. + * + * If an error occurs, the error is reported through linker_error() and false + * is returned. + */ +bool +tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, + struct gl_transform_feedback_info *info, + unsigned buffer, + unsigned varying, const unsigned max_outputs) const +{ /* From GL_EXT_transform_feedback: * A program will fail to link if: * @@ -1663,19 +1679,6 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, return false; } - /* Verify that the checks on MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS - * and MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS are sufficient to prevent - * overflow of info->Outputs[]. In worst case we generate one entry in - * Outputs[] per component so a conservative check is to verify that the - * size of the array is greater than or equal to both - * MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS and - * MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS. - */ - assert(Elements(info->Outputs) >= - ctx->Const.MaxTransformFeedbackInterleavedComponents); - assert(Elements(info->Outputs) >= - ctx->Const.MaxTransformFeedbackSeparateComponents); - unsigned translated_size = this->size; if (this->is_clip_distance_mesa) translated_size = (translated_size + 3) / 4; @@ -1683,6 +1686,7 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, for (unsigned index = 0; index < translated_size; ++index) { for (unsigned v = 0; v < this->matrix_columns; ++v) { unsigned num_components = this->vector_elements; + assert(info->NumOutputs < max_outputs); info->Outputs[info->NumOutputs].ComponentOffset = 0; if (this->is_clip_distance_mesa) { if (this->is_subscripted) { @@ -1976,6 +1980,7 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS; ralloc_free(prog->LinkedTransformFeedback.Varyings); + ralloc_free(prog->LinkedTransformFeedback.Outputs); memset(&prog->LinkedTransformFeedback, 0, sizeof(prog->LinkedTransformFeedback)); @@ -1988,12 +1993,23 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, struct gl_transform_feedback_varying_info, num_tfeedback_decls); + unsigned num_outputs = 0; + for (unsigned i = 0; i < num_tfeedback_decls; ++i) + if (!tfeedback_decls[i].accumulate_num_outputs(prog, &num_outputs)) + return false; + + prog->LinkedTransformFeedback.Outputs = + rzalloc_array(prog, + struct gl_transform_feedback_output, + num_outputs); + for (unsigned i = 0; i < num_tfeedback_decls; ++i) { unsigned buffer = separate_attribs_mode ? i : 0; if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback, - buffer, i)) + buffer, i, num_outputs)) return false; } + assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs); return true; } |