From 7732822c833ee22e259af3f8bd2bfb57c986612e Mon Sep 17 00:00:00 2001 From: Bryan Cain Date: Thu, 21 Jul 2011 15:49:26 -0500 Subject: [PATCH] glsl_to_tgsi: separate immediates from array constants during IR translation Before, if any uniform or constant array was accessed with indirect addressing, st_translate_program() would emit uniform constants in the place of immediates. This behavior was unavoidable with ir_to_mesa/mesa_to_tgsi, but glsl_to_tgsi can work around it since the GLSL IR backend and the TGSI emission are both inside the state tracker. --- src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 143 ++++++++++++++------- 1 file changed, 95 insertions(+), 48 deletions(-) diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 3df22eae918..389e5d8e2ef 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -70,6 +70,7 @@ extern "C" { #include "st_mesa_to_tgsi.h" } +#define PROGRAM_IMMEDIATE PROGRAM_FILE_MAX #define PROGRAM_ANY_CONST ((1 << PROGRAM_LOCAL_PARAM) | \ (1 << PROGRAM_ENV_PARAM) | \ (1 << PROGRAM_STATE_VAR) | \ @@ -272,6 +273,7 @@ public: struct gl_program *prog; struct gl_shader_program *shader_program; struct gl_shader_compiler_options *options; + struct gl_program_parameter_list *immediates; int next_temp; @@ -505,6 +507,9 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, case PROGRAM_UNIFORM: this->indirect_addr_consts = true; break; + case PROGRAM_IMMEDIATE: + assert(!"immediates should not have indirect addressing"); + break; default: break; } @@ -524,6 +529,9 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, case PROGRAM_UNIFORM: this->indirect_addr_consts = true; break; + case PROGRAM_IMMEDIATE: + assert(!"immediates should not have indirect addressing"); + break; default: break; } @@ -804,12 +812,12 @@ glsl_to_tgsi_visitor::emit_scs(ir_instruction *ir, unsigned op, struct st_src_reg glsl_to_tgsi_visitor::st_src_reg_for_float(float val) { - st_src_reg src(PROGRAM_CONSTANT, -1, GLSL_TYPE_FLOAT); + st_src_reg src(PROGRAM_IMMEDIATE, -1, GLSL_TYPE_FLOAT); union gl_constant_value uval; uval.f = val; - src.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters, - &uval, 1, GL_FLOAT, &src.swizzle); + src.index = _mesa_add_typed_unnamed_constant(this->immediates, &uval, 1, + GL_FLOAT, &src.swizzle); return src; } @@ -817,14 +825,14 @@ glsl_to_tgsi_visitor::st_src_reg_for_float(float val) struct st_src_reg glsl_to_tgsi_visitor::st_src_reg_for_int(int val) { - st_src_reg src(PROGRAM_CONSTANT, -1, GLSL_TYPE_INT); + st_src_reg src(PROGRAM_IMMEDIATE, -1, GLSL_TYPE_INT); union gl_constant_value uval; assert(glsl_version >= 130); uval.i = val; - src.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters, - &uval, 1, GL_INT, &src.swizzle); + src.index = _mesa_add_typed_unnamed_constant(this->immediates, &uval, 1, + GL_INT, &src.swizzle); return src; } @@ -1933,9 +1941,15 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) gl_constant_value *values = (gl_constant_value *) stack_vals; GLenum gl_type = GL_NONE; unsigned int i; + gl_register_file file; + gl_program_parameter_list *param_list; + static int in_array = 0; + + file = in_array ? PROGRAM_CONSTANT : PROGRAM_IMMEDIATE; + param_list = in_array ? this->prog->Parameters : this->immediates; /* Unfortunately, 4 floats is all we can get into - * _mesa_add_unnamed_constant. So, make a temp to store an + * _mesa_add_typed_unnamed_constant. So, make a temp to store an * aggregate constant and move each constant value into it. If we * get lucky, copy propagation will eliminate the extra moves. */ @@ -1969,6 +1983,7 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) int size = type_size(ir->type->fields.array); assert(size > 0); + in_array++; for (i = 0; i < ir->type->length; i++) { ir->array_elements[i]->accept(this); @@ -1981,6 +1996,7 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) } } this->result = temp_base; + in_array--; return; } @@ -1992,8 +2008,8 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) assert(ir->type->base_type == GLSL_TYPE_FLOAT); values = (gl_constant_value *) &ir->value.f[i * ir->type->vector_elements]; - src = st_src_reg(PROGRAM_CONSTANT, -1, ir->type->base_type); - src.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters, + src = st_src_reg(file, -1, ir->type->base_type); + src.index = _mesa_add_typed_unnamed_constant(param_list, values, ir->type->vector_elements, GL_FLOAT, @@ -2007,7 +2023,6 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) return; } - src.file = PROGRAM_CONSTANT; switch (ir->type->base_type) { case GLSL_TYPE_FLOAT: gl_type = GL_FLOAT; @@ -2046,8 +2061,8 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) assert(!"Non-float/uint/int/bool constant"); } - this->result = st_src_reg(PROGRAM_CONSTANT, -1, ir->type); - this->result.index = _mesa_add_typed_unnamed_constant(this->prog->Parameters, + this->result = st_src_reg(file, -1, ir->type); + this->result.index = _mesa_add_typed_unnamed_constant(param_list, values, ir->type->vector_elements, gl_type, &this->result.swizzle); } @@ -2430,11 +2445,13 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() num_address_regs = 0; indirect_addr_temps = false; indirect_addr_consts = false; + immediates = _mesa_new_parameter_list(); mem_ctx = ralloc_context(NULL); } glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor() { + _mesa_free_parameter_list(immediates); ralloc_free(mem_ctx); } @@ -3521,6 +3538,8 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, v->samplers_used = prog->SamplersUsed = original->samplers_used; v->indirect_addr_temps = original->indirect_addr_temps; v->indirect_addr_consts = original->indirect_addr_consts; + _mesa_free_parameter_list(v->immediates); + v->immediates = _mesa_clone_parameter_list(original->immediates); /* * Get initial pixel color from the texture. @@ -3648,6 +3667,8 @@ get_bitmap_visitor(struct st_fragment_program *fp, v->samplers_used = prog->SamplersUsed = original->samplers_used; v->indirect_addr_temps = original->indirect_addr_temps; v->indirect_addr_consts = original->indirect_addr_consts; + _mesa_free_parameter_list(v->immediates); + v->immediates = _mesa_clone_parameter_list(original->immediates); /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */ coord = st_src_reg(PROGRAM_INPUT, FRAG_ATTRIB_TEX0, glsl_type::vec2_type); @@ -3707,6 +3728,7 @@ struct st_translate { struct ureg_dst temps[MAX_TEMPS]; struct ureg_src *constants; + struct ureg_src *immediates; struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS]; struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS]; struct ureg_dst address[1]; @@ -3797,6 +3819,43 @@ static void set_insn_start( struct st_translate *t, t->insn[t->insn_count++] = start; } +/** + * Map a glsl_to_tgsi constant/immediate to a TGSI immediate. + */ +static struct ureg_src +emit_immediate( struct st_translate *t, + struct gl_program_parameter_list *params, + int index) +{ + struct ureg_program *ureg = t->ureg; + + switch(params->Parameters[index].DataType) + { + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + return ureg_DECL_immediate(ureg, (float *)params->ParameterValues[index], 4); + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + return ureg_DECL_immediate_int(ureg, (int *)params->ParameterValues[index], 4); + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_VEC2: + case GL_UNSIGNED_INT_VEC3: + case GL_UNSIGNED_INT_VEC4: + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + return ureg_DECL_immediate_uint(ureg, (unsigned *)params->ParameterValues[index], 4); + default: + assert(!"should not get here - type must be float, int, uint, or bool"); + return ureg_src_undef(); + } +} + /** * Map a Mesa dst register to a TGSI ureg_dst register. */ @@ -3871,6 +3930,9 @@ src_register( struct st_translate *t, else return t->constants[index]; + case PROGRAM_IMMEDIATE: + return t->immediates[index]; + case PROGRAM_INPUT: assert(t->inputMapping[index] < Elements(t->inputs)); return t->inputs[t->inputMapping[index]]; @@ -4402,9 +4464,8 @@ st_translate_program( } } - /* Emit constants and immediates. Mesa uses a single index space - * for these, so we put all the translated regs in t->constants. - * XXX: this entire if block depends on proginfo->Parameters from Mesa IR + /* Emit constants and uniforms. TGSI uses a single index space for these, + * so we put all the translated regs in t->constants. */ if (proginfo->Parameters) { t->constants = (struct ureg_src *)CALLOC( proginfo->Parameters->NumParameters * sizeof t->constants[0] ); @@ -4423,49 +4484,34 @@ st_translate_program( t->constants[i] = ureg_DECL_constant( ureg, i ); break; - /* Emit immediates only when there's no indirect addressing of - * the const buffer. - * FIXME: Be smarter and recognize param arrays: - * indirect addressing is only valid within the referenced - * array. - */ + /* Emit immediates for PROGRAM_CONSTANT only when there's no indirect + * addressing of the const buffer. + * FIXME: Be smarter and recognize param arrays: + * indirect addressing is only valid within the referenced + * array. + */ case PROGRAM_CONSTANT: if (program->indirect_addr_consts) t->constants[i] = ureg_DECL_constant( ureg, i ); else - switch(proginfo->Parameters->Parameters[i].DataType) - { - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - t->constants[i] = ureg_DECL_immediate(ureg, (float *)proginfo->Parameters->ParameterValues[i], 4); - break; - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - t->constants[i] = ureg_DECL_immediate_int(ureg, (int *)proginfo->Parameters->ParameterValues[i], 4); - break; - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_VEC2: - case GL_UNSIGNED_INT_VEC3: - case GL_UNSIGNED_INT_VEC4: - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - t->constants[i] = ureg_DECL_immediate_uint(ureg, (unsigned *)proginfo->Parameters->ParameterValues[i], 4); - break; - default: - assert(!"should not get here"); - } + t->constants[i] = emit_immediate( t, proginfo->Parameters, i ); break; default: break; } } } + + /* Emit immediate values. + */ + t->immediates = (struct ureg_src *)CALLOC( program->immediates->NumParameters * sizeof(struct ureg_src) ); + if (t->immediates == NULL) { + ret = PIPE_ERROR_OUT_OF_MEMORY; + goto out; + } + for (i = 0; i < program->immediates->NumParameters; i++) { + t->immediates[i] = emit_immediate( t, program->immediates, i ); + } /* texture samplers */ for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { @@ -4512,6 +4558,7 @@ out: FREE(t->insn); FREE(t->labels); FREE(t->constants); + FREE(t->immediates); if (t->error) { debug_printf("%s: translate error flag set\n", __FUNCTION__); -- 2.30.2