diff options
Diffstat (limited to 'src/mesa/program')
30 files changed, 811 insertions, 490 deletions
diff --git a/src/mesa/program/arbprogparse.c b/src/mesa/program/arbprogparse.c index f834aaf568..ca63e72c08 100644 --- a/src/mesa/program/arbprogparse.c +++ b/src/mesa/program/arbprogparse.c @@ -64,7 +64,7 @@ having three separate program parameter arrays. void -_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, +_mesa_parse_arb_fragment_program(struct gl_context* ctx, GLenum target, const GLvoid *str, GLsizei len, struct gl_fragment_program *program) { @@ -162,7 +162,7 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, * object unchanged. */ void -_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target, +_mesa_parse_arb_vertex_program(struct gl_context *ctx, GLenum target, const GLvoid *str, GLsizei len, struct gl_vertex_program *program) { diff --git a/src/mesa/program/arbprogparse.h b/src/mesa/program/arbprogparse.h index 980d39fb9f..08e25a1c16 100644 --- a/src/mesa/program/arbprogparse.h +++ b/src/mesa/program/arbprogparse.h @@ -29,12 +29,12 @@ #include "main/mtypes.h" extern void -_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target, +_mesa_parse_arb_vertex_program(struct gl_context *ctx, GLenum target, const GLvoid *str, GLsizei len, struct gl_vertex_program *program); extern void -_mesa_parse_arb_fragment_program(GLcontext *ctx, GLenum target, +_mesa_parse_arb_fragment_program(struct gl_context *ctx, GLenum target, const GLvoid *str, GLsizei len, struct gl_fragment_program *program); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index f24dce79f6..bdd3fd92ff 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -26,8 +26,7 @@ /** * \file ir_to_mesa.cpp * - * Translates the IR to ARB_fragment_program text if possible, - * printing the result + * Translate GLSL IR to Mesa's gl_program representation. */ #include <stdio.h> @@ -54,6 +53,7 @@ extern "C" { #include "program/program.h" #include "program/prog_uniform.h" #include "program/prog_parameter.h" +#include "program/sampler.h" } static int swizzle_for_size(int size); @@ -183,7 +183,7 @@ public: function_entry *current_function; - GLcontext *ctx; + struct gl_context *ctx; struct gl_program *prog; struct gl_shader_program *shader_program; struct gl_shader_compiler_options *options; @@ -274,8 +274,6 @@ public: GLboolean try_emit_mad(ir_expression *ir, int mul_operand); - int get_sampler_uniform_value(ir_dereference *deref); - void *mem_ctx; }; @@ -289,19 +287,22 @@ ir_to_mesa_dst_reg ir_to_mesa_address_reg = { PROGRAM_ADDRESS, 0, WRITEMASK_X, COND_TR, NULL }; -static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3); +static void +fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3); -static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) - { - va_list args; - va_start(args, fmt); - prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args); - va_end(args); +static void +fail_link(struct gl_shader_program *prog, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args); + va_end(args); - prog->LinkStatus = GL_FALSE; - } + prog->LinkStatus = GL_FALSE; +} -static int swizzle_for_size(int size) +static int +swizzle_for_size(int size) { int size_swizzles[4] = { MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X), @@ -310,6 +311,7 @@ static int swizzle_for_size(int size) MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), }; + assert((size >= 1) && (size <= 4)); return size_swizzles[size - 1]; } @@ -578,243 +580,6 @@ ir_to_mesa_visitor::find_variable_storage(ir_variable *var) return NULL; } -struct statevar_element { - const char *field; - int tokens[STATE_LENGTH]; - int swizzle; -}; - -static struct statevar_element gl_DepthRange_elements[] = { - {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX}, - {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY}, - {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ}, -}; - -static struct statevar_element gl_ClipPlane_elements[] = { - {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW} -}; - -static struct statevar_element gl_Point_elements[] = { - {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX}, - {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY}, - {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ}, - {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW}, - {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX}, - {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY}, - {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ}, -}; - -static struct statevar_element gl_FrontMaterial_elements[] = { - {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW}, - {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, - {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, - {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, - {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX}, -}; - -static struct statevar_element gl_BackMaterial_elements[] = { - {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW}, - {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, - {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, - {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, - {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX}, -}; - -static struct statevar_element gl_LightSource_elements[] = { - {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, - {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, - {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, - {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW}, - {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW}, - {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_XYZW}, - {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW}, - {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX}, - {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW}, - {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX}, - {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY}, - {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ}, -}; - -static struct statevar_element gl_LightModel_elements[] = { - {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_FrontLightModelProduct_elements[] = { - {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_BackLightModelProduct_elements[] = { - {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_FrontLightProduct_elements[] = { - {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW}, - {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW}, - {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_BackLightProduct_elements[] = { - {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW}, - {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW}, - {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_TextureEnvColor_elements[] = { - {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_EyePlaneS_elements[] = { - {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_EyePlaneT_elements[] = { - {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_EyePlaneR_elements[] = { - {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_EyePlaneQ_elements[] = { - {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_ObjectPlaneS_elements[] = { - {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_ObjectPlaneT_elements[] = { - {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_ObjectPlaneR_elements[] = { - {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_ObjectPlaneQ_elements[] = { - {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW}, -}; - -static struct statevar_element gl_Fog_elements[] = { - {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW}, - {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX}, - {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY}, - {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ}, - {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW}, -}; - -static struct statevar_element gl_NormalScale_elements[] = { - {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX}, -}; - -#define MATRIX(name, statevar, modifier) \ - static struct statevar_element name ## _elements[] = { \ - { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \ - { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \ - { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \ - { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW }, \ - } - -MATRIX(gl_ModelViewMatrix, - STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE); -MATRIX(gl_ModelViewMatrixInverse, - STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS); -MATRIX(gl_ModelViewMatrixTranspose, - STATE_MODELVIEW_MATRIX, 0); -MATRIX(gl_ModelViewMatrixInverseTranspose, - STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE); - -MATRIX(gl_ProjectionMatrix, - STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE); -MATRIX(gl_ProjectionMatrixInverse, - STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS); -MATRIX(gl_ProjectionMatrixTranspose, - STATE_PROJECTION_MATRIX, 0); -MATRIX(gl_ProjectionMatrixInverseTranspose, - STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE); - -MATRIX(gl_ModelViewProjectionMatrix, - STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE); -MATRIX(gl_ModelViewProjectionMatrixInverse, - STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS); -MATRIX(gl_ModelViewProjectionMatrixTranspose, - STATE_MVP_MATRIX, 0); -MATRIX(gl_ModelViewProjectionMatrixInverseTranspose, - STATE_MVP_MATRIX, STATE_MATRIX_INVERSE); - -MATRIX(gl_TextureMatrix, - STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE); -MATRIX(gl_TextureMatrixInverse, - STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS); -MATRIX(gl_TextureMatrixTranspose, - STATE_TEXTURE_MATRIX, 0); -MATRIX(gl_TextureMatrixInverseTranspose, - STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE); - -static struct statevar_element gl_NormalMatrix_elements[] = { - { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE}, - SWIZZLE_XYZW }, - { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE}, - SWIZZLE_XYZW }, - { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE}, - SWIZZLE_XYZW }, -}; - -#undef MATRIX - -#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)} - -static const struct statevar { - const char *name; - struct statevar_element *elements; - unsigned int num_elements; -} statevars[] = { - STATEVAR(gl_DepthRange), - STATEVAR(gl_ClipPlane), - STATEVAR(gl_Point), - STATEVAR(gl_FrontMaterial), - STATEVAR(gl_BackMaterial), - STATEVAR(gl_LightSource), - STATEVAR(gl_LightModel), - STATEVAR(gl_FrontLightModelProduct), - STATEVAR(gl_BackLightModelProduct), - STATEVAR(gl_FrontLightProduct), - STATEVAR(gl_BackLightProduct), - STATEVAR(gl_TextureEnvColor), - STATEVAR(gl_EyePlaneS), - STATEVAR(gl_EyePlaneT), - STATEVAR(gl_EyePlaneR), - STATEVAR(gl_EyePlaneQ), - STATEVAR(gl_ObjectPlaneS), - STATEVAR(gl_ObjectPlaneT), - STATEVAR(gl_ObjectPlaneR), - STATEVAR(gl_ObjectPlaneQ), - STATEVAR(gl_Fog), - - STATEVAR(gl_ModelViewMatrix), - STATEVAR(gl_ModelViewMatrixInverse), - STATEVAR(gl_ModelViewMatrixTranspose), - STATEVAR(gl_ModelViewMatrixInverseTranspose), - - STATEVAR(gl_ProjectionMatrix), - STATEVAR(gl_ProjectionMatrixInverse), - STATEVAR(gl_ProjectionMatrixTranspose), - STATEVAR(gl_ProjectionMatrixInverseTranspose), - - STATEVAR(gl_ModelViewProjectionMatrix), - STATEVAR(gl_ModelViewProjectionMatrixInverse), - STATEVAR(gl_ModelViewProjectionMatrixTranspose), - STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose), - - STATEVAR(gl_TextureMatrix), - STATEVAR(gl_TextureMatrixInverse), - STATEVAR(gl_TextureMatrixTranspose), - STATEVAR(gl_TextureMatrixInverseTranspose), - - STATEVAR(gl_NormalMatrix), - STATEVAR(gl_NormalScale), -}; - void ir_to_mesa_visitor::visit(ir_variable *ir) { @@ -827,19 +592,20 @@ ir_to_mesa_visitor::visit(ir_variable *ir) if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { unsigned int i; + const struct gl_builtin_uniform_desc *statevar; - for (i = 0; i < Elements(statevars); i++) { - if (strcmp(ir->name, statevars[i].name) == 0) + for (i = 0; _mesa_builtin_uniform_desc[i].name; i++) { + if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0) break; } - if (i == Elements(statevars)) { + if (!_mesa_builtin_uniform_desc[i].name) { fail_link(this->shader_program, "Failed to find builtin uniform `%s'\n", ir->name); return; } - const struct statevar *statevar = &statevars[i]; + statevar = &_mesa_builtin_uniform_desc[i]; int array_count; if (ir->type->is_array()) { @@ -882,7 +648,7 @@ ir_to_mesa_visitor::visit(ir_variable *ir) for (int a = 0; a < array_count; a++) { for (unsigned int i = 0; i < statevar->num_elements; i++) { - struct statevar_element *element = &statevar->elements[i]; + struct gl_builtin_uniform_element *element = &statevar->elements[i]; int tokens[STATE_LENGTH]; memcpy(tokens, element->tokens, sizeof(element->tokens)); @@ -1096,6 +862,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir) assert(!ir->operands[operand]->type->is_matrix()); } + int vector_elements = ir->operands[0]->type->vector_elements; + if (ir->operands[1]) { + vector_elements = MAX2(vector_elements, + ir->operands[1]->type->vector_elements); + } + this->result.file = PROGRAM_UNDEFINED; /* Storage for our result. Ideally for an assignment we'd be using @@ -1204,7 +976,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir) ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type); ir_to_mesa_emit_op2(ir, OPCODE_SNE, ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]); - ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp); + if (vector_elements == 4) + ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp); + else if (vector_elements == 3) + ir_to_mesa_emit_op2(ir, OPCODE_DP3, result_dst, temp, temp); + else + ir_to_mesa_emit_op2(ir, OPCODE_DP2, result_dst, temp, temp); ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, result_src, src_reg_for_float(0.0)); } else { @@ -1218,7 +995,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir) ir_to_mesa_src_reg temp = get_temp(glsl_type::vec4_type); ir_to_mesa_emit_op2(ir, OPCODE_SNE, ir_to_mesa_dst_reg_from_src(temp), op[0], op[1]); - ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp); + if (vector_elements == 4) + ir_to_mesa_emit_op2(ir, OPCODE_DP4, result_dst, temp, temp); + else if (vector_elements == 3) + ir_to_mesa_emit_op2(ir, OPCODE_DP3, result_dst, temp, temp); + else + ir_to_mesa_emit_op2(ir, OPCODE_DP2, result_dst, temp, temp); ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, result_src, src_reg_for_float(0.0)); } else { @@ -1348,6 +1130,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_binop_bit_and: case ir_binop_bit_xor: case ir_binop_bit_or: + case ir_unop_round_even: assert(!"GLSL 1.30 features unsupported"); break; } @@ -1577,13 +1360,39 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector()); l.writemask = WRITEMASK_XYZW; } else if (ir->lhs->type->is_scalar()) { - /* FINISHME: This hack makes writing to gl_FragData, which lives in the + /* FINISHME: This hack makes writing to gl_FragDepth, which lives in the * FINISHME: W component of fragment shader output zero, work correctly. */ l.writemask = WRITEMASK_XYZW; } else { + int swizzles[4]; + int first_enabled_chan = 0; + int rhs_chan = 0; + assert(ir->lhs->type->is_vector()); l.writemask = ir->write_mask; + + for (int i = 0; i < 4; i++) { + if (l.writemask & (1 << i)) { + first_enabled_chan = GET_SWZ(r.swizzle, i); + break; + } + } + + /* Swizzle a small RHS vector into the channels being written. + * + * glsl ir treats write_mask as dictating how many channels are + * present on the RHS while Mesa IR treats write_mask as just + * showing which channels of the vec4 RHS get written. + */ + for (int i = 0; i < 4; i++) { + if (l.writemask & (1 << i)) + swizzles[i] = GET_SWZ(r.swizzle, rhs_chan++); + else + swizzles[i] = first_enabled_chan; + } + r.swizzle = MAKE_SWIZZLE4(swizzles[0], swizzles[1], + swizzles[2], swizzles[3]); } assert(l.file != PROGRAM_UNDEFINED); @@ -1852,89 +1661,6 @@ ir_to_mesa_visitor::visit(ir_call *ir) this->result = entry->return_reg; } -class get_sampler_name : public ir_hierarchical_visitor -{ -public: - get_sampler_name(ir_to_mesa_visitor *mesa, ir_dereference *last) - { - this->mem_ctx = mesa->mem_ctx; - this->mesa = mesa; - this->name = NULL; - this->offset = 0; - this->last = last; - } - - virtual ir_visitor_status visit(ir_dereference_variable *ir) - { - this->name = ir->var->name; - return visit_continue; - } - - virtual ir_visitor_status visit_leave(ir_dereference_record *ir) - { - this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field); - return visit_continue; - } - - virtual ir_visitor_status visit_leave(ir_dereference_array *ir) - { - ir_constant *index = ir->array_index->as_constant(); - int i; - - if (index) { - i = index->value.i[0]; - } else { - /* GLSL 1.10 and 1.20 allowed variable sampler array indices, - * while GLSL 1.30 requires that the array indices be - * constant integer expressions. We don't expect any driver - * to actually work with a really variable array index, so - * all that would work would be an unrolled loop counter that ends - * up being constant above. - */ - mesa->shader_program->InfoLog = - talloc_asprintf_append(mesa->shader_program->InfoLog, - "warning: Variable sampler array index " - "unsupported.\nThis feature of the language " - "was removed in GLSL 1.20 and is unlikely " - "to be supported for 1.10 in Mesa.\n"); - i = 0; - } - if (ir != last) { - this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i); - } else { - offset = i; - } - return visit_continue; - } - - ir_to_mesa_visitor *mesa; - const char *name; - void *mem_ctx; - int offset; - ir_dereference *last; -}; - -int -ir_to_mesa_visitor::get_sampler_uniform_value(ir_dereference *sampler) -{ - get_sampler_name getname(this, sampler); - - sampler->accept(&getname); - - GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1, - getname.name); - - if (index < 0) { - fail_link(this->shader_program, - "failed to find sampler named %s.\n", getname.name); - return 0; - } - - index += getname.offset; - - return this->prog->Parameters->ParameterValues[index][0]; -} - void ir_to_mesa_visitor::visit(ir_texture *ir) { @@ -2034,7 +1760,9 @@ ir_to_mesa_visitor::visit(ir_texture *ir) if (ir->shadow_comparitor) inst->tex_shadow = GL_TRUE; - inst->sampler = get_sampler_uniform_value(ir->sampler); + inst->sampler = _mesa_get_sampler_uniform_value(ir->sampler, + this->shader_program, + this->prog); const glsl_type *sampler_type = ir->sampler->type; @@ -2435,7 +2163,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program, } static void -set_uniform_initializer(GLcontext *ctx, void *mem_ctx, +set_uniform_initializer(struct gl_context *ctx, void *mem_ctx, struct gl_shader_program *shader_program, const char *name, const glsl_type *type, ir_constant *val) @@ -2505,13 +2233,17 @@ set_uniform_initializer(GLcontext *ctx, void *mem_ctx, } static void -set_uniform_initializers(GLcontext *ctx, +set_uniform_initializers(struct gl_context *ctx, struct gl_shader_program *shader_program) { void *mem_ctx = NULL; - for (unsigned int i = 0; i < shader_program->_NumLinkedShaders; i++) { + for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) { struct gl_shader *shader = shader_program->_LinkedShaders[i]; + + if (shader == NULL) + continue; + foreach_iter(exec_list_iterator, iter, *shader->ir) { ir_instruction *ir = (ir_instruction *)iter.get(); ir_variable *var = ir->as_variable(); @@ -2530,8 +2262,12 @@ set_uniform_initializers(GLcontext *ctx, talloc_free(mem_ctx); } + +/** + * Convert a shader's GLSL IR into a Mesa gl_program. + */ struct gl_program * -get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, +get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program, struct gl_shader *shader) { ir_to_mesa_visitor v; @@ -2620,10 +2356,12 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *, num_instructions); + /* Convert ir_mesa_instructions into prog_instructions. + */ mesa_inst = mesa_instructions; i = 0; foreach_iter(exec_list_iterator, iter, v.instructions) { - ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get(); + const ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get(); mesa_inst->Opcode = inst->op; mesa_inst->CondUpdate = inst->cond_update; @@ -2644,6 +2382,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, if (mesa_inst->DstReg.RelAddr) prog->IndirectRegisterFiles |= 1 << mesa_inst->DstReg.File; + /* Update program's bitmask of indirectly accessed register files */ for (unsigned src = 0; src < 3; src++) if (mesa_inst->SrcReg[src].RelAddr) prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File; @@ -2705,8 +2444,14 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program, } extern "C" { + +/** + * Called via ctx->Driver.CompilerShader(). + * This is a no-op. + * XXX can we remove the ctx->Driver.CompileShader() hook? + */ GLboolean -_mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader) +_mesa_ir_compile_shader(struct gl_context *ctx, struct gl_shader *shader) { assert(shader->CompileStatus); (void) ctx; @@ -2714,15 +2459,25 @@ _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader) return GL_TRUE; } + +/** + * Link a shader. + * Called via ctx->Driver.LinkShader() + * This actually involves converting GLSL IR into Mesa gl_programs with + * code lowering and other optimizations. + */ GLboolean -_mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog) +_mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) { assert(prog->LinkStatus); - for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { + for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { + if (prog->_LinkedShaders[i] == NULL) + continue; + bool progress; exec_list *ir = prog->_LinkedShaders[i]->ir; - struct gl_shader_compiler_options *options = + const struct gl_shader_compiler_options *options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(prog->_LinkedShaders[i]->Type)]; do { @@ -2763,10 +2518,13 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog) validate_ir_tree(ir); } - for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { + for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { struct gl_program *linked_prog; bool ok = true; + if (prog->_LinkedShaders[i] == NULL) + continue; + linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); switch (prog->_LinkedShaders[i]->Type) { @@ -2792,8 +2550,12 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog) return GL_TRUE; } + +/** + * Compile a GLSL shader. Called via glCompileShader(). + */ void -_mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) +_mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) { struct _mesa_glsl_parse_state *state = new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader); @@ -2876,8 +2638,12 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader) } } + +/** + * Link a GLSL shader program. Called via glLinkProgram(). + */ void -_mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog) +_mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) { unsigned int i; diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h index ecaacde4bb..7197615f94 100644 --- a/src/mesa/program/ir_to_mesa.h +++ b/src/mesa/program/ir_to_mesa.h @@ -28,10 +28,10 @@ extern "C" { #include "main/config.h" #include "main/mtypes.h" -void _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *sh); -void _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog); -GLboolean _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader); -GLboolean _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog); +void _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *sh); +void _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); +GLboolean _mesa_ir_compile_shader(struct gl_context *ctx, struct gl_shader *shader); +GLboolean _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); #ifdef __cplusplus } diff --git a/src/mesa/program/nvfragparse.c b/src/mesa/program/nvfragparse.c index 0de3c5804d..8516b5fc1f 100644 --- a/src/mesa/program/nvfragparse.c +++ b/src/mesa/program/nvfragparse.c @@ -141,7 +141,7 @@ static const struct instruction_pattern Instructions[] = { * _successfully_ parsed the program text. */ struct parse_state { - GLcontext *ctx; + struct gl_context *ctx; const GLubyte *start; /* start of program string */ const GLubyte *pos; /* current position */ const GLubyte *curLine; @@ -1463,7 +1463,7 @@ Parse_InstructionSequence(struct parse_state *parseState, * indicates the position of the error in 'str'. */ void -_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget, +_mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum dstTarget, const GLubyte *str, GLsizei len, struct gl_fragment_program *program) { diff --git a/src/mesa/program/nvfragparse.h b/src/mesa/program/nvfragparse.h index e28a6c4934..3e85dd2c30 100644 --- a/src/mesa/program/nvfragparse.h +++ b/src/mesa/program/nvfragparse.h @@ -33,7 +33,7 @@ #include "main/mtypes.h" extern void -_mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum target, +_mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum target, const GLubyte *str, GLsizei len, struct gl_fragment_program *program); diff --git a/src/mesa/program/nvvertparse.c b/src/mesa/program/nvvertparse.c index 1ac83d0e59..bdd44a4513 100644 --- a/src/mesa/program/nvvertparse.c +++ b/src/mesa/program/nvvertparse.c @@ -54,7 +54,7 @@ * program attributes. */ struct parse_state { - GLcontext *ctx; + struct gl_context *ctx; const GLubyte *start; const GLubyte *pos; const GLubyte *curLine; @@ -1282,7 +1282,7 @@ Parse_Program(struct parse_state *parseState, * indicates the position of the error in 'str'. */ void -_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget, +_mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum dstTarget, const GLubyte *str, GLsizei len, struct gl_vertex_program *program) { diff --git a/src/mesa/program/nvvertparse.h b/src/mesa/program/nvvertparse.h index 91ef79e6c3..e98e867320 100644 --- a/src/mesa/program/nvvertparse.h +++ b/src/mesa/program/nvvertparse.h @@ -32,7 +32,7 @@ #include "main/mtypes.h" extern void -_mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum target, +_mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum target, const GLubyte *str, GLsizei len, struct gl_vertex_program *program); diff --git a/src/mesa/program/prog_cache.c b/src/mesa/program/prog_cache.c index 8af689754b..56ca59890d 100644 --- a/src/mesa/program/prog_cache.c +++ b/src/mesa/program/prog_cache.c @@ -104,7 +104,7 @@ rehash(struct gl_program_cache *cache) static void -clear_cache(GLcontext *ctx, struct gl_program_cache *cache) +clear_cache(struct gl_context *ctx, struct gl_program_cache *cache) { struct cache_item *c, *next; GLuint i; @@ -145,7 +145,7 @@ _mesa_new_program_cache(void) void -_mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *cache) +_mesa_delete_program_cache(struct gl_context *ctx, struct gl_program_cache *cache) { clear_cache(ctx, cache); free(cache->items); @@ -178,7 +178,7 @@ _mesa_search_program_cache(struct gl_program_cache *cache, void -_mesa_program_cache_insert(GLcontext *ctx, +_mesa_program_cache_insert(struct gl_context *ctx, struct gl_program_cache *cache, const void *key, GLuint keysize, struct gl_program *program) diff --git a/src/mesa/program/prog_cache.h b/src/mesa/program/prog_cache.h index bfe8f99d44..4907ae3030 100644 --- a/src/mesa/program/prog_cache.h +++ b/src/mesa/program/prog_cache.h @@ -41,7 +41,7 @@ extern struct gl_program_cache * _mesa_new_program_cache(void); extern void -_mesa_delete_program_cache(GLcontext *ctx, struct gl_program_cache *pc); +_mesa_delete_program_cache(struct gl_context *ctx, struct gl_program_cache *pc); extern struct gl_program * @@ -49,7 +49,7 @@ _mesa_search_program_cache(struct gl_program_cache *cache, const void *key, GLuint keysize); extern void -_mesa_program_cache_insert(GLcontext *ctx, +_mesa_program_cache_insert(struct gl_context *ctx, struct gl_program_cache *cache, const void *key, GLuint keysize, struct gl_program *program); diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c index 2ae5bc572a..1d97a077f5 100644 --- a/src/mesa/program/prog_execute.c +++ b/src/mesa/program/prog_execute.c @@ -296,7 +296,7 @@ fetch_vector4ui(const struct prog_src_register *source, * XXX this currently only works for fragment program input attribs. */ static void -fetch_vector4_deriv(GLcontext * ctx, +fetch_vector4_deriv(struct gl_context * ctx, const struct prog_src_register *source, const struct gl_program_machine *machine, char xOrY, GLfloat result[4]) @@ -380,7 +380,7 @@ fetch_vector1ui(const struct prog_src_register *source, * Fetch texel from texture. Use partial derivatives when possible. */ static INLINE void -fetch_texel(GLcontext *ctx, +fetch_texel(struct gl_context *ctx, const struct gl_program_machine *machine, const struct prog_instruction *inst, const GLfloat texcoord[4], GLfloat lodBias, @@ -630,7 +630,7 @@ store_vector4ui(const struct prog_instruction *inst, * \return GL_TRUE if program completed or GL_FALSE if program executed KIL. */ GLboolean -_mesa_execute_program(GLcontext * ctx, +_mesa_execute_program(struct gl_context * ctx, const struct gl_program *program, struct gl_program_machine *machine) { diff --git a/src/mesa/program/prog_execute.h b/src/mesa/program/prog_execute.h index f59b65176f..cefd468c36 100644 --- a/src/mesa/program/prog_execute.h +++ b/src/mesa/program/prog_execute.h @@ -29,10 +29,10 @@ #include "main/mtypes.h" -typedef void (*FetchTexelLodFunc)(GLcontext *ctx, const GLfloat texcoord[4], +typedef void (*FetchTexelLodFunc)(struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda, GLuint unit, GLfloat color[4]); -typedef void (*FetchTexelDerivFunc)(GLcontext *ctx, const GLfloat texcoord[4], +typedef void (*FetchTexelDerivFunc)(struct gl_context *ctx, const GLfloat texcoord[4], const GLfloat texdx[4], const GLfloat texdy[4], GLfloat lodBias, @@ -74,11 +74,11 @@ struct gl_program_machine extern void -_mesa_get_program_register(GLcontext *ctx, gl_register_file file, +_mesa_get_program_register(struct gl_context *ctx, gl_register_file file, GLuint index, GLfloat val[4]); extern GLboolean -_mesa_execute_program(GLcontext *ctx, +_mesa_execute_program(struct gl_context *ctx, const struct gl_program *program, struct gl_program_machine *machine); diff --git a/src/mesa/program/prog_optimize.c b/src/mesa/program/prog_optimize.c index 0dc779073d..96971f2eda 100644 --- a/src/mesa/program/prog_optimize.c +++ b/src/mesa/program/prog_optimize.c @@ -1216,7 +1216,7 @@ _mesa_reallocate_registers(struct gl_program *prog) #if 0 static void -print_it(GLcontext *ctx, struct gl_program *program, const char *txt) { +print_it(struct gl_context *ctx, struct gl_program *program, const char *txt) { fprintf(stderr, "%s (%u inst):\n", txt, program->NumInstructions); _mesa_print_program(program); _mesa_print_program_parameters(ctx, program); @@ -1230,7 +1230,7 @@ print_it(GLcontext *ctx, struct gl_program *program, const char *txt) { * instructions, temp regs, etc. */ void -_mesa_optimize_program(GLcontext *ctx, struct gl_program *program) +_mesa_optimize_program(struct gl_context *ctx, struct gl_program *program) { GLboolean any_change; diff --git a/src/mesa/program/prog_optimize.h b/src/mesa/program/prog_optimize.h index 06cd9cb2c2..00f1080449 100644 --- a/src/mesa/program/prog_optimize.h +++ b/src/mesa/program/prog_optimize.h @@ -41,6 +41,6 @@ _mesa_find_temp_intervals(const struct prog_instruction *instructions, GLint intEnd[MAX_PROGRAM_TEMPS]); extern void -_mesa_optimize_program(GLcontext *ctx, struct gl_program *program); +_mesa_optimize_program(struct gl_context *ctx, struct gl_program *program); #endif diff --git a/src/mesa/program/prog_parameter.c b/src/mesa/program/prog_parameter.c index 6bf8a081b0..3570cab118 100644 --- a/src/mesa/program/prog_parameter.c +++ b/src/mesa/program/prog_parameter.c @@ -378,18 +378,9 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList, /* Check if the state reference is already in the list */ for (index = 0; index < (GLint) paramList->NumParameters; index++) { - GLuint i, match = 0; - for (i = 0; i < STATE_LENGTH; i++) { - if (paramList->Parameters[index].StateIndexes[i] == stateTokens[i]) { - match++; - } - else { - break; - } - } - if (match == STATE_LENGTH) { - /* this state reference is already in the parameter list */ - return index; + if (!memcmp(paramList->Parameters[index].StateIndexes, + stateTokens, STATE_LENGTH * sizeof(gl_state_index))) { + return index; } } diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index 00aa6de963..79c01020eb 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -909,7 +909,7 @@ binary(GLbitfield64 val) */ static void _mesa_fprint_program_parameters(FILE *f, - GLcontext *ctx, + struct gl_context *ctx, const struct gl_program *prog) { GLuint i; @@ -951,7 +951,7 @@ _mesa_fprint_program_parameters(FILE *f, * Print all of a program's parameters/fields to stderr. */ void -_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog) +_mesa_print_program_parameters(struct gl_context *ctx, const struct gl_program *prog) { _mesa_fprint_program_parameters(stderr, ctx, prog); } diff --git a/src/mesa/program/prog_print.h b/src/mesa/program/prog_print.h index 78b90aeb4d..f080b3fd2e 100644 --- a/src/mesa/program/prog_print.h +++ b/src/mesa/program/prog_print.h @@ -100,7 +100,7 @@ _mesa_fprint_program_opt(FILE *f, GLboolean lineNumbers); extern void -_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog); +_mesa_print_program_parameters(struct gl_context *ctx, const struct gl_program *prog); extern void _mesa_print_parameter_list(const struct gl_program_parameter_list *list); diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c index 2687f8ae2c..baac29ff0d 100644 --- a/src/mesa/program/prog_statevars.c +++ b/src/mesa/program/prog_statevars.c @@ -46,7 +46,7 @@ * The program parser will produce the state[] values. */ static void -_mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], +_mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], GLfloat *value) { switch (state[0]) { @@ -273,7 +273,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], case STATE_MVP_MATRIX: case STATE_TEXTURE_MATRIX: case STATE_PROGRAM_MATRIX: - case STATE_COLOR_MATRIX: { /* state[0] = modelview, projection, texture, etc. */ /* state[1] = which texture matrix or program matrix */ @@ -309,9 +308,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], ASSERT(index < Elements(ctx->ProgramMatrixStack)); matrix = ctx->ProgramMatrixStack[index].Top; } - else if (mat == STATE_COLOR_MATRIX) { - matrix = ctx->ColorMatrixStack.Top; - } else { _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); return; @@ -555,14 +551,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], value[3] = ctx->Pixel.AlphaBias; return; - case STATE_PCM_SCALE: - COPY_4V(value, ctx->Pixel.PostColorMatrixScale); - return; - - case STATE_PCM_BIAS: - COPY_4V(value, ctx->Pixel.PostColorMatrixBias); - return; - case STATE_SHADOW_AMBIENT: { const int unit = (int) state[2]; @@ -667,8 +655,6 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) return _NEW_TEXTURE_MATRIX; case STATE_PROGRAM_MATRIX: return _NEW_TRACK_MATRIX; - case STATE_COLOR_MATRIX: - return _NEW_COLOR_MATRIX; case STATE_DEPTH_RANGE: return _NEW_VIEWPORT; @@ -706,8 +692,6 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) case STATE_PT_SCALE: case STATE_PT_BIAS: - case STATE_PCM_SCALE: - case STATE_PCM_BIAS: return _NEW_PIXEL; case STATE_FB_SIZE: @@ -792,9 +776,6 @@ append_token(char *dst, gl_state_index k) case STATE_PROGRAM_MATRIX: append(dst, "matrix.program"); break; - case STATE_COLOR_MATRIX: - append(dst, "matrix.color"); - break; case STATE_MATRIX_INVERSE: append(dst, ".inverse"); break; @@ -913,12 +894,6 @@ append_token(char *dst, gl_state_index k) case STATE_PT_BIAS: append(dst, "PTbias"); break; - case STATE_PCM_SCALE: - append(dst, "PCMscale"); - break; - case STATE_PCM_BIAS: - append(dst, "PCMbias"); - break; case STATE_SHADOW_AMBIENT: append(dst, "CompareFailValue"); break; @@ -1010,7 +985,6 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) case STATE_MVP_MATRIX: case STATE_TEXTURE_MATRIX: case STATE_PROGRAM_MATRIX: - case STATE_COLOR_MATRIX: { /* state[0] = modelview, projection, texture, etc. */ /* state[1] = which texture matrix or program matrix */ @@ -1075,7 +1049,7 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) * This would be called at glBegin time when using a fragment program. */ void -_mesa_load_state_parameters(GLcontext *ctx, +_mesa_load_state_parameters(struct gl_context *ctx, struct gl_program_parameter_list *paramList) { GLuint i; @@ -1129,7 +1103,7 @@ load_transpose_matrix(GLfloat registers[][4], GLuint pos, * glBegin/glEnd, not per-vertex. */ void -_mesa_load_tracked_matrices(GLcontext *ctx) +_mesa_load_tracked_matrices(struct gl_context *ctx) { GLuint i; @@ -1147,9 +1121,6 @@ _mesa_load_tracked_matrices(GLcontext *ctx) Elements(ctx->TextureMatrixStack) - 1); mat = ctx->TextureMatrixStack[unit].Top; } - else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) { - mat = ctx->ColorMatrixStack.Top; - } else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) { /* XXX verify the combined matrix is up to date */ mat = &ctx->_ModelProjectMatrix; diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h index 1753471ffb..6e5be53630 100644 --- a/src/mesa/program/prog_statevars.h +++ b/src/mesa/program/prog_statevars.h @@ -67,7 +67,6 @@ typedef enum gl_state_index_ { STATE_MVP_MATRIX, STATE_TEXTURE_MATRIX, STATE_PROGRAM_MATRIX, - STATE_COLOR_MATRIX, STATE_MATRIX_INVERSE, STATE_MATRIX_TRANSPOSE, STATE_MATRIX_INVTRANS, @@ -116,8 +115,6 @@ typedef enum gl_state_index_ { STATE_LIGHT_HALF_VECTOR, /* object vs eye space */ STATE_PT_SCALE, /**< Pixel transfer RGBA scale */ STATE_PT_BIAS, /**< Pixel transfer RGBA bias */ - STATE_PCM_SCALE, /**< Post color matrix RGBA scale */ - STATE_PCM_BIAS, /**< Post color matrix RGBA bias */ STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */ STATE_FB_SIZE, /**< (width-1, height-1, 0, 0) */ STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */ @@ -128,7 +125,7 @@ typedef enum gl_state_index_ { extern void -_mesa_load_state_parameters(GLcontext *ctx, +_mesa_load_state_parameters(struct gl_context *ctx, struct gl_program_parameter_list *paramList); @@ -141,7 +138,7 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]); extern void -_mesa_load_tracked_matrices(GLcontext *ctx); +_mesa_load_tracked_matrices(struct gl_context *ctx); #endif /* PROG_STATEVARS_H */ diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c index 06b9539bda..cdcf4ec265 100644 --- a/src/mesa/program/program.c +++ b/src/mesa/program/program.c @@ -49,7 +49,7 @@ struct gl_program _mesa_DummyProgram; * Init context's vertex/fragment program state */ void -_mesa_init_program(GLcontext *ctx) +_mesa_init_program(struct gl_context *ctx) { GLuint i; @@ -128,7 +128,7 @@ _mesa_init_program(GLcontext *ctx) * Free a context's vertex/fragment program state */ void -_mesa_free_program_data(GLcontext *ctx) +_mesa_free_program_data(struct gl_context *ctx) { #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); @@ -161,7 +161,7 @@ _mesa_free_program_data(GLcontext *ctx) * shared state. */ void -_mesa_update_default_objects_program(GLcontext *ctx) +_mesa_update_default_objects_program(struct gl_context *ctx) { #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, @@ -203,7 +203,7 @@ _mesa_update_default_objects_program(GLcontext *ctx) * This is generally called from within the parsers. */ void -_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string) +_mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string) { ctx->Program.ErrorPos = pos; free((void *) ctx->Program.ErrorString); @@ -260,7 +260,7 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos, * Initialize a new vertex/fragment program object. */ static struct gl_program * -_mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog, +_mesa_init_program_struct( struct gl_context *ctx, struct gl_program *prog, GLenum target, GLuint id) { (void) ctx; @@ -286,7 +286,7 @@ _mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog, * Initialize a new fragment program object. */ struct gl_program * -_mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog, +_mesa_init_fragment_program( struct gl_context *ctx, struct gl_fragment_program *prog, GLenum target, GLuint id) { if (prog) @@ -300,7 +300,7 @@ _mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog, * Initialize a new vertex program object. */ struct gl_program * -_mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog, +_mesa_init_vertex_program( struct gl_context *ctx, struct gl_vertex_program *prog, GLenum target, GLuint id) { if (prog) @@ -314,7 +314,7 @@ _mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog, * Initialize a new geometry program object. */ struct gl_program * -_mesa_init_geometry_program( GLcontext *ctx, struct gl_geometry_program *prog, +_mesa_init_geometry_program( struct gl_context *ctx, struct gl_geometry_program *prog, GLenum target, GLuint id) { if (prog) @@ -337,7 +337,7 @@ _mesa_init_geometry_program( GLcontext *ctx, struct gl_geometry_program *prog, * \return pointer to new program object */ struct gl_program * -_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id) +_mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id) { struct gl_program *prog; switch (target) { @@ -372,7 +372,7 @@ _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id) * by a device driver function. */ void -_mesa_delete_program(GLcontext *ctx, struct gl_program *prog) +_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog) { (void) ctx; ASSERT(prog); @@ -406,7 +406,7 @@ _mesa_delete_program(GLcontext *ctx, struct gl_program *prog) * casts elsewhere. */ struct gl_program * -_mesa_lookup_program(GLcontext *ctx, GLuint id) +_mesa_lookup_program(struct gl_context *ctx, GLuint id) { if (id) return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id); @@ -419,7 +419,7 @@ _mesa_lookup_program(GLcontext *ctx, GLuint id) * Reference counting for vertex/fragment programs */ void -_mesa_reference_program(GLcontext *ctx, +_mesa_reference_program(struct gl_context *ctx, struct gl_program **ptr, struct gl_program *prog) { @@ -486,7 +486,7 @@ _mesa_reference_program(GLcontext *ctx, * made by a device driver. */ struct gl_program * -_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog) +_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog) { struct gl_program *clone; @@ -729,7 +729,7 @@ adjust_param_indexes(struct prog_instruction *inst, GLuint numInst, * the first program go to the inputs of the second program. */ struct gl_program * -_mesa_combine_programs(GLcontext *ctx, +_mesa_combine_programs(struct gl_context *ctx, const struct gl_program *progA, const struct gl_program *progB) { @@ -923,7 +923,7 @@ _mesa_find_free_register(const GLboolean used[], * behaviour. */ void -_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog) +_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog) { static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 }; GLuint i; diff --git a/src/mesa/program/program.h b/src/mesa/program/program.h index 03b1066f32..70cc2c3aae 100644 --- a/src/mesa/program/program.h +++ b/src/mesa/program/program.h @@ -48,16 +48,16 @@ extern struct gl_program _mesa_DummyProgram; extern void -_mesa_init_program(GLcontext *ctx); +_mesa_init_program(struct gl_context *ctx); extern void -_mesa_free_program_data(GLcontext *ctx); +_mesa_free_program_data(struct gl_context *ctx); extern void -_mesa_update_default_objects_program(GLcontext *ctx); +_mesa_update_default_objects_program(struct gl_context *ctx); extern void -_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string); +_mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string); extern const GLubyte * _mesa_find_line_column(const GLubyte *string, const GLubyte *pos, @@ -65,36 +65,36 @@ _mesa_find_line_column(const GLubyte *string, const GLubyte *pos, extern struct gl_program * -_mesa_init_vertex_program(GLcontext *ctx, +_mesa_init_vertex_program(struct gl_context *ctx, struct gl_vertex_program *prog, GLenum target, GLuint id); extern struct gl_program * -_mesa_init_fragment_program(GLcontext *ctx, +_mesa_init_fragment_program(struct gl_context *ctx, struct gl_fragment_program *prog, GLenum target, GLuint id); extern struct gl_program * -_mesa_init_geometry_program(GLcontext *ctx, +_mesa_init_geometry_program(struct gl_context *ctx, struct gl_geometry_program *prog, GLenum target, GLuint id); extern struct gl_program * -_mesa_new_program(GLcontext *ctx, GLenum target, GLuint id); +_mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id); extern void -_mesa_delete_program(GLcontext *ctx, struct gl_program *prog); +_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog); extern struct gl_program * -_mesa_lookup_program(GLcontext *ctx, GLuint id); +_mesa_lookup_program(struct gl_context *ctx, GLuint id); extern void -_mesa_reference_program(GLcontext *ctx, +_mesa_reference_program(struct gl_context *ctx, struct gl_program **ptr, struct gl_program *prog); static INLINE void -_mesa_reference_vertprog(GLcontext *ctx, +_mesa_reference_vertprog(struct gl_context *ctx, struct gl_vertex_program **ptr, struct gl_vertex_program *prog) { @@ -103,7 +103,7 @@ _mesa_reference_vertprog(GLcontext *ctx, } static INLINE void -_mesa_reference_fragprog(GLcontext *ctx, +_mesa_reference_fragprog(struct gl_context *ctx, struct gl_fragment_program **ptr, struct gl_fragment_program *prog) { @@ -112,7 +112,7 @@ _mesa_reference_fragprog(GLcontext *ctx, } static INLINE void -_mesa_reference_geomprog(GLcontext *ctx, +_mesa_reference_geomprog(struct gl_context *ctx, struct gl_geometry_program **ptr, struct gl_geometry_program *prog) { @@ -121,24 +121,24 @@ _mesa_reference_geomprog(GLcontext *ctx, } extern struct gl_program * -_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog); +_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog); static INLINE struct gl_vertex_program * -_mesa_clone_vertex_program(GLcontext *ctx, +_mesa_clone_vertex_program(struct gl_context *ctx, const struct gl_vertex_program *prog) { return (struct gl_vertex_program *) _mesa_clone_program(ctx, &prog->Base); } static INLINE struct gl_geometry_program * -_mesa_clone_geometry_program(GLcontext *ctx, +_mesa_clone_geometry_program(struct gl_context *ctx, const struct gl_geometry_program *prog) { return (struct gl_geometry_program *) _mesa_clone_program(ctx, &prog->Base); } static INLINE struct gl_fragment_program * -_mesa_clone_fragment_program(GLcontext *ctx, +_mesa_clone_fragment_program(struct gl_context *ctx, const struct gl_fragment_program *prog) { return (struct gl_fragment_program *) _mesa_clone_program(ctx, &prog->Base); @@ -152,7 +152,7 @@ extern GLboolean _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count); extern struct gl_program * -_mesa_combine_programs(GLcontext *ctx, +_mesa_combine_programs(struct gl_context *ctx, const struct gl_program *progA, const struct gl_program *progB); @@ -166,7 +166,7 @@ _mesa_find_free_register(const GLboolean used[], GLuint maxRegs, GLuint firstReg); extern void -_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog); +_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog); /* keep these in the same order as TGSI_PROCESSOR_* */ diff --git a/src/mesa/program/program_parse.tab.c b/src/mesa/program/program_parse.tab.c index 08ead30def..baef311d0c 100644 --- a/src/mesa/program/program_parse.tab.c +++ b/src/mesa/program/program_parse.tab.c @@ -5604,7 +5604,7 @@ yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s) GLboolean -_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str, +_mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *str, GLsizei len, struct asm_parser_state *state) { struct asm_instruction *inst; diff --git a/src/mesa/program/program_parse.y b/src/mesa/program/program_parse.y index cf621ae424..784ea28c17 100644 --- a/src/mesa/program/program_parse.y +++ b/src/mesa/program/program_parse.y @@ -2643,7 +2643,7 @@ yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s) GLboolean -_mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str, +_mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *str, GLsizei len, struct asm_parser_state *state) { struct asm_instruction *inst; diff --git a/src/mesa/program/program_parser.h b/src/mesa/program/program_parser.h index be952d4b9c..d689eef795 100644 --- a/src/mesa/program/program_parser.h +++ b/src/mesa/program/program_parser.h @@ -24,10 +24,7 @@ #include "main/config.h" -#ifndef MTYPES_H -struct __GLcontextRec; -typedef struct __GLcontextRec GLcontext; -#endif +struct gl_context; enum asm_type { at_none, @@ -131,7 +128,7 @@ struct asm_instruction { struct asm_parser_state { - GLcontext *ctx; + struct gl_context *ctx; struct gl_program *prog; /** @@ -237,7 +234,7 @@ typedef struct YYLTYPE { #define YYLTYPE_IS_TRIVIAL 1 -extern GLboolean _mesa_parse_arb_program(GLcontext *ctx, GLenum target, +extern GLboolean _mesa_parse_arb_program(struct gl_context *ctx, GLenum target, const GLubyte *str, GLsizei len, struct asm_parser_state *state); diff --git a/src/mesa/program/programopt.c b/src/mesa/program/programopt.c index fb2ebe6338..f92881f833 100644 --- a/src/mesa/program/programopt.c +++ b/src/mesa/program/programopt.c @@ -46,7 +46,7 @@ * May be used to implement the position_invariant option. */ static void -_mesa_insert_mvp_dp4_code(GLcontext *ctx, struct gl_vertex_program *vprog) +_mesa_insert_mvp_dp4_code(struct gl_context *ctx, struct gl_vertex_program *vprog) { struct prog_instruction *newInst; const GLuint origLen = vprog->Base.NumInstructions; @@ -114,7 +114,7 @@ _mesa_insert_mvp_dp4_code(GLcontext *ctx, struct gl_vertex_program *vprog) static void -_mesa_insert_mvp_mad_code(GLcontext *ctx, struct gl_vertex_program *vprog) +_mesa_insert_mvp_mad_code(struct gl_context *ctx, struct gl_vertex_program *vprog) { struct prog_instruction *newInst; const GLuint origLen = vprog->Base.NumInstructions; @@ -216,7 +216,7 @@ _mesa_insert_mvp_mad_code(GLcontext *ctx, struct gl_vertex_program *vprog) void -_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) +_mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog) { if (ctx->mvp_with_dp4) _mesa_insert_mvp_dp4_code( ctx, vprog ); @@ -238,7 +238,7 @@ _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) * to vertex programs too. */ void -_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog) +_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog) { static const gl_state_index fogPStateOpt[STATE_LENGTH] = { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 }; @@ -585,7 +585,7 @@ _mesa_remove_output_reads(struct gl_program *prog, gl_register_file type) * This is for debug/test purposes. */ void -_mesa_nop_fragment_program(GLcontext *ctx, struct gl_fragment_program *prog) +_mesa_nop_fragment_program(struct gl_context *ctx, struct gl_fragment_program *prog) { struct prog_instruction *inst; GLuint inputAttr; @@ -626,7 +626,7 @@ _mesa_nop_fragment_program(GLcontext *ctx, struct gl_fragment_program *prog) * transforms vertex position and emits color. */ void -_mesa_nop_vertex_program(GLcontext *ctx, struct gl_vertex_program *prog) +_mesa_nop_vertex_program(struct gl_context *ctx, struct gl_vertex_program *prog) { struct prog_instruction *inst; GLuint inputAttr; diff --git a/src/mesa/program/programopt.h b/src/mesa/program/programopt.h index 4af6357f97..ef6f1bd079 100644 --- a/src/mesa/program/programopt.h +++ b/src/mesa/program/programopt.h @@ -29,10 +29,10 @@ #include "main/mtypes.h" extern void -_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog); +_mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog); extern void -_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog); +_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog); extern void _mesa_count_texture_indirections(struct gl_program *prog); @@ -44,10 +44,10 @@ extern void _mesa_remove_output_reads(struct gl_program *prog, gl_register_file type); extern void -_mesa_nop_fragment_program(GLcontext *ctx, struct gl_fragment_program *prog); +_mesa_nop_fragment_program(struct gl_context *ctx, struct gl_fragment_program *prog); extern void -_mesa_nop_vertex_program(GLcontext *ctx, struct gl_vertex_program *prog); +_mesa_nop_vertex_program(struct gl_context *ctx, struct gl_vertex_program *prog); #endif /* PROGRAMOPT_H */ diff --git a/src/mesa/program/register_allocate.c b/src/mesa/program/register_allocate.c new file mode 100644 index 0000000000..03f04697bf --- /dev/null +++ b/src/mesa/program/register_allocate.c @@ -0,0 +1,361 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +/** @file register_allocate.c + * + * Graph-coloring register allocator. + */ + +#include <talloc.h> + +#include "main/imports.h" +#include "main/macros.h" +#include "main/mtypes.h" +#include "register_allocate.h" + +struct ra_reg { + char *name; + GLboolean *conflicts; +}; + +struct ra_regs { + struct ra_reg *regs; + unsigned int count; + + struct ra_class **classes; + unsigned int class_count; +}; + +struct ra_class { + GLboolean *regs; + + /** + * p_B in Runeson/Nyström paper. + * + * This is "how many regs are in the set." + */ + unsigned int p; + + /** + * q_B,C in Runeson/Nyström paper. + */ + unsigned int *q; +}; + +struct ra_node { + GLboolean *adjacency; + unsigned int class; + unsigned int adjacency_count; + unsigned int reg; + GLboolean in_stack; +}; + +struct ra_graph { + struct ra_regs *regs; + /** + * the variables that need register allocation. + */ + struct ra_node *nodes; + unsigned int count; /**< count of nodes. */ + + unsigned int *stack; + unsigned int stack_count; +}; + +struct ra_regs * +ra_alloc_reg_set(unsigned int count) +{ + unsigned int i; + struct ra_regs *regs; + + regs = talloc_zero(NULL, struct ra_regs); + regs->count = count; + regs->regs = talloc_zero_array(regs, struct ra_reg, count); + + for (i = 0; i < count; i++) { + regs->regs[i].conflicts = talloc_zero_array(regs->regs, GLboolean, count); + regs->regs[i].conflicts[i] = GL_TRUE; + } + + return regs; +} + +void +ra_add_reg_conflict(struct ra_regs *regs, unsigned int r1, unsigned int r2) +{ + regs->regs[r1].conflicts[r2] = GL_TRUE; + regs->regs[r2].conflicts[r1] = GL_TRUE; +} + +unsigned int +ra_alloc_reg_class(struct ra_regs *regs) +{ + struct ra_class *class; + + regs->classes = talloc_realloc(regs, regs->classes, + struct ra_class *, + regs->class_count + 1); + + class = talloc_zero(regs, struct ra_class); + regs->classes[regs->class_count] = class; + + class->regs = talloc_zero_array(class, GLboolean, regs->count); + + return regs->class_count++; +} + +void +ra_class_add_reg(struct ra_regs *regs, unsigned int c, unsigned int r) +{ + struct ra_class *class = regs->classes[c]; + + class->regs[r] = GL_TRUE; + class->p++; +} + +/** + * Must be called after all conflicts and register classes have been + * set up and before the register set is used for allocation. + */ +void +ra_set_finalize(struct ra_regs *regs) +{ + unsigned int b, c; + + for (b = 0; b < regs->class_count; b++) { + regs->classes[b]->q = talloc_array(regs, unsigned int, regs->class_count); + } + + /* Compute, for each class B and C, how many regs of B an + * allocation to C could conflict with. + */ + for (b = 0; b < regs->class_count; b++) { + for (c = 0; c < regs->class_count; c++) { + unsigned int rc; + int max_conflicts = 0; + + for (rc = 0; rc < regs->count; rc++) { + unsigned int rb; + int conflicts = 0; + + if (!regs->classes[c]->regs[rc]) + continue; + + for (rb = 0; rb < regs->count; rb++) { + if (regs->classes[b]->regs[rb] && + regs->regs[rb].conflicts[rc]) + conflicts++; + } + max_conflicts = MAX2(max_conflicts, conflicts); + } + regs->classes[b]->q[c] = max_conflicts; + } + } +} + +struct ra_graph * +ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count) +{ + struct ra_graph *g; + unsigned int i; + + g = talloc_zero(regs, struct ra_graph); + g->regs = regs; + g->nodes = talloc_zero_array(g, struct ra_node, count); + g->count = count; + + g->stack = talloc_zero_array(g, unsigned int, count); + + for (i = 0; i < count; i++) { + g->nodes[i].adjacency = talloc_zero_array(g, GLboolean, count); + g->nodes[i].adjacency[i] = GL_TRUE; + g->nodes[i].reg = ~0; + } + + return g; +} + +void +ra_set_node_class(struct ra_graph *g, + unsigned int n, unsigned int class) +{ + g->nodes[n].class = class; +} + +void +ra_add_node_interference(struct ra_graph *g, + unsigned int n1, unsigned int n2) +{ + if (g->nodes[n1].adjacency[n2]) + return; + + g->nodes[n1].adjacency[n2] = GL_TRUE; + g->nodes[n2].adjacency_count++; + g->nodes[n2].adjacency[n1] = GL_TRUE; + g->nodes[n2].adjacency_count++; +} + +static GLboolean pq_test(struct ra_graph *g, unsigned int n) +{ + unsigned int j; + unsigned int q = 0; + int n_class = g->nodes[n].class; + + for (j = 0; j < g->count; j++) { + if (j == n || g->nodes[j].in_stack) + continue; + + if (g->nodes[n].adjacency[j]) { + unsigned int j_class = g->nodes[j].class; + q += g->regs->classes[n_class]->q[j_class]; + } + } + + return q < g->regs->classes[n_class]->p; +} + +/** + * Simplifies the interference graph by pushing all + * trivially-colorable nodes into a stack of nodes to be colored, + * removing them from the graph, and rinsing and repeating. + * + * Returns GL_TRUE if all nodes were removed from the graph. GL_FALSE + * means that either spilling will be required, or optimistic coloring + * should be applied. + */ +GLboolean +ra_simplify(struct ra_graph *g) +{ + GLboolean progress = GL_TRUE; + int i; + + while (progress) { + progress = GL_FALSE; + + for (i = g->count - 1; i >= 0; i--) { + if (g->nodes[i].in_stack) + continue; + + if (pq_test(g, i)) { + g->stack[g->stack_count] = i; + g->stack_count++; + g->nodes[i].in_stack = GL_TRUE; + progress = GL_TRUE; + } + } + } + + for (i = 0; i < g->count; i++) { + if (!g->nodes[i].in_stack) + return GL_FALSE; + } + + return GL_TRUE; +} + +/** + * Pops nodes from the stack back into the graph, coloring them with + * registers as they go. + * + * If all nodes were trivially colorable, then this must succeed. If + * not (optimistic coloring), then it may return GL_FALSE; + */ +GLboolean +ra_select(struct ra_graph *g) +{ + int i; + + while (g->stack_count != 0) { + unsigned int r; + int n = g->stack[g->stack_count - 1]; + struct ra_class *c = g->regs->classes[g->nodes[n].class]; + + /* Find the lowest-numbered reg which is not used by a member + * of the graph adjacent to us. + */ + for (r = 0; r < g->regs->count; r++) { + if (!c->regs[r]) + continue; + + /* Check if any of our neighbors conflict with this register choice. */ + for (i = 0; i < g->count; i++) { + if (g->nodes[n].adjacency[i] && + !g->nodes[i].in_stack && + g->regs->regs[r].conflicts[g->nodes[i].reg]) { + break; + } + } + if (i == g->count) + break; + } + if (r == g->regs->count) + return GL_FALSE; + + g->nodes[n].reg = r; + g->nodes[n].in_stack = GL_FALSE; + g->stack_count--; + } + + return GL_TRUE; +} + +/** + * Optimistic register coloring: Just push the remaining nodes + * on the stack. They'll be colored first in ra_select(), and + * if they succeed then the locally-colorable nodes are still + * locally-colorable and the rest of the register allocation + * will succeed. + */ +void +ra_optimistic_color(struct ra_graph *g) +{ + unsigned int i; + + for (i = 0; i < g->count; i++) { + if (g->nodes[i].in_stack) + continue; + + g->stack[g->stack_count] = i; + g->stack_count++; + g->nodes[i].in_stack = GL_TRUE; + } +} + +GLboolean +ra_allocate_no_spills(struct ra_graph *g) +{ + if (!ra_simplify(g)) { + ra_optimistic_color(g); + } + return ra_select(g); +} + +unsigned int +ra_get_node_reg(struct ra_graph *g, unsigned int n) +{ + return g->nodes[n].reg; +} diff --git a/src/mesa/program/register_allocate.h b/src/mesa/program/register_allocate.h new file mode 100644 index 0000000000..42647b50b8 --- /dev/null +++ b/src/mesa/program/register_allocate.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +struct ra_class; +struct ra_regs; + +/* @{ + * Register set setup. + * + * This should be done once at backend initializaion, as + * ra_set_finalize is O(r^2*c^2). The registers may be virtual + * registers, such as aligned register pairs that conflict with the + * two real registers from which they are composed. + */ +struct ra_regs *ra_alloc_reg_set(unsigned int count); +unsigned int ra_alloc_reg_class(struct ra_regs *regs); +void ra_add_reg_conflict(struct ra_regs *regs, + unsigned int r1, unsigned int r2); +void ra_class_add_reg(struct ra_regs *regs, unsigned int c, unsigned int reg); +void ra_set_finalize(struct ra_regs *regs); +/** @} */ + +/** @{ Interference graph setup. + * + * Each interference graph node is a virtual variable in the IL. It + * is up to the user to ra_set_node_class() for the virtual variable, + * and compute live ranges and ra_node_interfere() between conflicting + * live ranges. + */ +struct ra_graph *ra_alloc_interference_graph(struct ra_regs *regs, + unsigned int count); +void ra_set_node_class(struct ra_graph *g, unsigned int n, unsigned int c); +void ra_add_node_interference(struct ra_graph *g, + unsigned int n1, unsigned int n2); +/** @} */ + +/** @{ Graph-coloring register allocation */ +GLboolean ra_simplify(struct ra_graph *g); +void ra_optimistic_color(struct ra_graph *g); +GLboolean ra_select(struct ra_graph *g); +GLboolean ra_allocate_no_spills(struct ra_graph *g); + +unsigned int ra_get_node_reg(struct ra_graph *g, unsigned int n); +/** @} */ + diff --git a/src/mesa/program/sampler.cpp b/src/mesa/program/sampler.cpp new file mode 100644 index 0000000000..0e58aef9c9 --- /dev/null +++ b/src/mesa/program/sampler.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2008 VMware, Inc. All Rights Reserved. + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdio.h> + +extern "C" { +#include "main/compiler.h" +#include "main/mtypes.h" +#include "program/prog_parameter.h" +#include "ir.h" +#include "ir_visitor.h" +#include "glsl_types.h" +} + +static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3); + +static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, args); + va_end(args); + + prog->LinkStatus = GL_FALSE; +} + +class get_sampler_name : public ir_hierarchical_visitor +{ +public: + get_sampler_name(ir_dereference *last, + struct gl_shader_program *shader_program) + { + this->mem_ctx = talloc_new(NULL); + this->shader_program = shader_program; + this->name = NULL; + this->offset = 0; + this->last = last; + } + + ~get_sampler_name() + { + talloc_free(this->mem_ctx); + } + + virtual ir_visitor_status visit(ir_dereference_variable *ir) + { + this->name = ir->var->name; + return visit_continue; + } + + virtual ir_visitor_status visit_leave(ir_dereference_record *ir) + { + this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field); + return visit_continue; + } + + virtual ir_visitor_status visit_leave(ir_dereference_array *ir) + { + ir_constant *index = ir->array_index->as_constant(); + int i; + + if (index) { + i = index->value.i[0]; + } else { + /* GLSL 1.10 and 1.20 allowed variable sampler array indices, + * while GLSL 1.30 requires that the array indices be + * constant integer expressions. We don't expect any driver + * to actually work with a really variable array index, so + * all that would work would be an unrolled loop counter that ends + * up being constant above. + */ + shader_program->InfoLog = + talloc_asprintf_append(shader_program->InfoLog, + "warning: Variable sampler array index " + "unsupported.\nThis feature of the language " + "was removed in GLSL 1.20 and is unlikely " + "to be supported for 1.10 in Mesa.\n"); + i = 0; + } + if (ir != last) { + this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i); + } else { + offset = i; + } + return visit_continue; + } + + struct gl_shader_program *shader_program; + const char *name; + void *mem_ctx; + int offset; + ir_dereference *last; +}; + +extern "C" { +int +_mesa_get_sampler_uniform_value(class ir_dereference *sampler, + struct gl_shader_program *shader_program, + const struct gl_program *prog) +{ + get_sampler_name getname(sampler, shader_program); + + sampler->accept(&getname); + + GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1, + getname.name); + + if (index < 0) { + fail_link(shader_program, + "failed to find sampler named %s.\n", getname.name); + return 0; + } + + index += getname.offset; + + return prog->Parameters->ParameterValues[index][0]; +} +} diff --git a/src/mesa/program/sampler.h b/src/mesa/program/sampler.h new file mode 100644 index 0000000000..22467e9902 --- /dev/null +++ b/src/mesa/program/sampler.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * Copyright (C) 2008 VMware, Inc. All Rights Reserved. + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +int +_mesa_get_sampler_uniform_value(class ir_dereference *sampler, + struct gl_shader_program *shader_program, + const struct gl_program *prog); |