diff options
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r-- | mesalib/src/glsl/ir.h | 3 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_builder.cpp | 23 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_builder.h | 6 | ||||
-rw-r--r-- | mesalib/src/glsl/linker.cpp | 119 |
4 files changed, 135 insertions, 16 deletions
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index b54e2f2e0..9bbf3b7ef 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -1341,7 +1341,8 @@ enum ir_texture_opcode { class ir_texture : public ir_rvalue { public: ir_texture(enum ir_texture_opcode op) - : op(op), projector(NULL), shadow_comparitor(NULL), offset(NULL) + : op(op), coordinate(NULL), projector(NULL), shadow_comparitor(NULL), + offset(NULL) { this->ir_type = ir_type_texture; } diff --git a/mesalib/src/glsl/ir_builder.cpp b/mesalib/src/glsl/ir_builder.cpp index 9a16c90e5..d96e25c18 100644 --- a/mesalib/src/glsl/ir_builder.cpp +++ b/mesalib/src/glsl/ir_builder.cpp @@ -77,6 +77,21 @@ swizzle(operand a, int swizzle, int components) } ir_swizzle * +swizzle_for_size(operand a, int components) +{ + void *mem_ctx = ralloc_parent(a.val); + + if (a.val->type->vector_elements < components) + components = a.val->type->vector_elements; + + unsigned s[4] = { 0, 1, 2, 3 }; + for (int i = components; i < 4; i++) + s[i] = components - 1; + + return new(mem_ctx) ir_swizzle(a.val, s, components); +} + +ir_swizzle * swizzle_xxxx(operand a) { return swizzle(a, SWIZZLE_XXXX, 4); @@ -143,6 +158,14 @@ swizzle_xyzw(operand a) } ir_expression * +expr(ir_expression_operation op, operand a) +{ + void *mem_ctx = ralloc_parent(a.val); + + return new(mem_ctx) ir_expression(op, a.val); +} + +ir_expression * expr(ir_expression_operation op, operand a, operand b) { void *mem_ctx = ralloc_parent(a.val); diff --git a/mesalib/src/glsl/ir_builder.h b/mesalib/src/glsl/ir_builder.h index 0ebcbab95..7a0a196ee 100644 --- a/mesalib/src/glsl/ir_builder.h +++ b/mesalib/src/glsl/ir_builder.h @@ -83,6 +83,7 @@ public: ir_assignment *assign(deref lhs, operand rhs); ir_assignment *assign(deref lhs, operand rhs, int writemask); +ir_expression *expr(ir_expression_operation op, operand a); ir_expression *expr(ir_expression_operation op, operand a, operand b); ir_expression *add(operand a, operand b); ir_expression *sub(operand a, operand b); @@ -90,6 +91,11 @@ ir_expression *mul(operand a, operand b); ir_expression *dot(operand a, operand b); ir_expression *saturate(operand a); +/** + * Swizzle away later components, but preserve the ordering. + */ +ir_swizzle *swizzle_for_size(operand a, int components); + ir_swizzle *swizzle_xxxx(operand a); ir_swizzle *swizzle_yyyy(operand a); ir_swizzle *swizzle_zzzz(operand a); diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 310944752..f06298cf6 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1439,8 +1439,7 @@ public: 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 max_outputs) const; - + const unsigned max_outputs) const; /** * True if assign_location() has been called for this object. @@ -1450,6 +1449,16 @@ public: return this->location != -1; } + bool is_next_buffer_separator() const + { + return this->next_buffer_separator; + } + + bool is_varying() const + { + return !this->next_buffer_separator && !this->skip_components; + } + /** * Determine whether this object refers to the variable var. */ @@ -1527,6 +1536,17 @@ private: * glGetTransformFeedbackVarying(). */ unsigned size; + + /** + * How many components to skip. If non-zero, this is + * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3. + */ + unsigned skip_components; + + /** + * Whether this is gl_NextBuffer from ARB_transform_feedback3. + */ + bool next_buffer_separator; }; @@ -1546,7 +1566,31 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog, this->location = -1; this->orig_name = input; this->is_clip_distance_mesa = false; + this->skip_components = 0; + this->next_buffer_separator = false; + if (ctx->Extensions.ARB_transform_feedback3) { + /* Parse gl_NextBuffer. */ + if (strcmp(input, "gl_NextBuffer") == 0) { + this->next_buffer_separator = true; + return true; + } + + /* Parse gl_SkipComponents. */ + if (strcmp(input, "gl_SkipComponents1") == 0) + this->skip_components = 1; + else if (strcmp(input, "gl_SkipComponents2") == 0) + this->skip_components = 2; + else if (strcmp(input, "gl_SkipComponents3") == 0) + this->skip_components = 3; + else if (strcmp(input, "gl_SkipComponents4") == 0) + this->skip_components = 4; + + if (this->skip_components) + return true; + } + + /* Parse a declaration. */ const char *bracket = strrchr(input, '['); if (bracket) { @@ -1581,6 +1625,8 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog, bool tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y) { + assert(x.is_varying() && y.is_varying()); + if (strcmp(x.var_name, y.var_name) != 0) return false; if (x.is_subscripted != y.is_subscripted) @@ -1603,6 +1649,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx, struct gl_shader_program *prog, ir_variable *output_var) { + assert(this->is_varying()); + if (output_var->type->is_array()) { /* Array variable */ const unsigned matrix_cols = @@ -1677,6 +1725,10 @@ bool tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count) { + if (!this->is_varying()) { + return true; + } + if (!this->is_assigned()) { /* From GL_EXT_transform_feedback: * A program will fail to link if: @@ -1709,9 +1761,16 @@ tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog, 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 + unsigned buffer, const unsigned max_outputs) const { + assert(!this->next_buffer_separator); + + /* Handle gl_SkipComponents. */ + if (this->skip_components) { + info->BufferStride[buffer] += this->skip_components; + return true; + } + /* From GL_EXT_transform_feedback: * A program will fail to link if: * @@ -1757,9 +1816,9 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, } assert(components_so_far == this->num_components()); - info->Varyings[varying].Name = ralloc_strdup(prog, this->orig_name); - info->Varyings[varying].Type = this->type; - info->Varyings[varying].Size = this->size; + info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name); + info->Varyings[info->NumVarying].Type = this->type; + info->Varyings[info->NumVarying].Size = this->size; info->NumVarying++; return true; @@ -1781,6 +1840,10 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, for (unsigned i = 0; i < num_names; ++i) { if (!decls[i].init(ctx, prog, mem_ctx, varying_names[i])) return false; + + if (!decls[i].is_varying()) + continue; + /* From GL_EXT_transform_feedback: * A program will fail to link if: * @@ -1792,6 +1855,9 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog, * feedback of arrays would be useless otherwise. */ for (unsigned j = 0; j < i; ++j) { + if (!decls[j].is_varying()) + continue; + if (tfeedback_decl::is_same(decls[i], decls[j])) { linker_error(prog, "Transform feedback varying %s specified " "more than once.", varying_names[i]); @@ -1948,6 +2014,9 @@ assign_varying_locations(struct gl_context *ctx, } for (unsigned i = 0; i < num_tfeedback_decls; ++i) { + if (!tfeedback_decls[i].is_varying()) + continue; + if (!tfeedback_decls[i].is_assigned() && tfeedback_decls[i].matches_var(output_var)) { if (output_var->location == -1) { @@ -2059,9 +2128,6 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog, memset(&prog->LinkedTransformFeedback, 0, sizeof(prog->LinkedTransformFeedback)); - prog->LinkedTransformFeedback.NumBuffers = - separate_attribs_mode ? num_tfeedback_decls : 1; - prog->LinkedTransformFeedback.Varyings = rzalloc_array(prog, struct gl_transform_feedback_varying_info, @@ -2077,14 +2143,37 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *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, num_outputs)) - return false; + unsigned num_buffers = 0; + + if (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)) + return false; + + num_buffers++; + } + } + else { + /* GL_INVERLEAVED_ATTRIBS */ + for (unsigned i = 0; i < num_tfeedback_decls; ++i) { + if (tfeedback_decls[i].is_next_buffer_separator()) { + num_buffers++; + continue; + } + + if (!tfeedback_decls[i].store(ctx, prog, + &prog->LinkedTransformFeedback, + num_buffers, num_outputs)) + return false; + } + num_buffers++; } + assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs); + prog->LinkedTransformFeedback.NumBuffers = num_buffers; return true; } |