ソースを参照

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 <stereotype441@gmail.com>
tags/i965-primitive-restart-v2
Christoph Bumiller 13年前
コミット
d540af554a
2個のファイルの変更57行の追加39行の削除
  1. 40
    24
      src/glsl/linker.cpp
  2. 17
    15
      src/mesa/main/mtypes.h

+ 40
- 24
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;
}

+ 17
- 15
src/mesa/main/mtypes.h ファイルの表示

@@ -1827,6 +1827,22 @@ struct gl_transform_feedback_varying_info {
GLint Size;
};

struct gl_transform_feedback_output {
unsigned OutputRegister;
unsigned OutputBuffer;
unsigned NumComponents;

/** offset (in DWORDs) of this output within the interleaved structure */
unsigned DstOffset;

/**
* Offset into the output register of the data to output. For example,
* if NumComponents is 2 and ComponentOffset is 1, then the data to
* offset is in the y and z components of the output register.
*/
unsigned ComponentOffset;
};

/** Post-link transform feedback info. */
struct gl_transform_feedback_info {
unsigned NumOutputs;
@@ -1836,21 +1852,7 @@ struct gl_transform_feedback_info {
*/
unsigned NumBuffers;

struct {
unsigned OutputRegister;
unsigned OutputBuffer;
unsigned NumComponents;

/** offset (in DWORDs) of this output within the interleaved structure */
unsigned DstOffset;

/**
* Offset into the output register of the data to output. For example,
* if NumComponents is 2 and ComponentOffset is 1, then the data to
* offset is in the y and z components of the output register.
*/
unsigned ComponentOffset;
} Outputs[MAX_PROGRAM_OUTPUTS];
struct gl_transform_feedback_output *Outputs;

/** Transform feedback varyings used for the linking of this shader program.
*

読み込み中…
キャンセル
保存