diff options
Diffstat (limited to 'src/mesa/shader/slang/slang_codegen.c')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 73ad20a73d9..df361fbb3db 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -29,6 +29,7 @@ */ #include "imports.h" +#include "get.h" #include "macros.h" #include "slang_assemble.h" #include "slang_codegen.h" @@ -42,6 +43,7 @@ #include "program.h" #include "prog_instruction.h" #include "prog_parameter.h" +#include "prog_statevars.h" #include "slang_print.h" @@ -57,6 +59,285 @@ static slang_ir_node * _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper); + + +/** + * Lookup a named constant and allocate storage for the parameter in + * the given parameter list. + * \return position of the constant in the paramList. + */ +static GLint +slang_lookup_constant(const char *name, GLint index, + struct gl_program_parameter_list *paramList) +{ + struct constant_info { + const char *Name; + const GLenum Token; + }; + static const struct constant_info info[] = { + { "gl_MaxLights", GL_MAX_LIGHTS }, + { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES }, + { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS }, + { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS }, + { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS }, + { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS }, + { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS }, + { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS }, + { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS }, + { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS }, + { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS }, + { NULL, 0 } + }; + GLuint i; + GLuint swizzle; /* XXX use this */ + + for (i = 0; info[i].Name; i++) { + if (strcmp(info[i].Name, name) == 0) { + /* found */ + GLfloat value = -1.0; + GLint pos; + _mesa_GetFloatv(info[i].Token, &value); + ASSERT(value >= 0.0); /* sanity check that glGetFloatv worked */ + /* XXX named constant! */ + pos = _mesa_add_unnamed_constant(paramList, &value, 1, &swizzle); + return pos; + } + } + return -1; +} + + +/** + * Determine if 'name' is a state variable. If so, create a new program + * parameter for it, and return the param's index. Else, return -1. + */ +static GLint +slang_lookup_statevar(const char *name, GLint index, + struct gl_program_parameter_list *paramList) +{ + struct state_info { + const char *Name; + const GLuint NumRows; /** for matrices */ + const GLuint Swizzle; + const GLint Indexes[6]; + }; + static const struct state_info state[] = { + { "gl_ModelViewMatrix", 4, SWIZZLE_NOOP, + { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, 0 } }, + { "gl_NormalMatrix", 3, SWIZZLE_NOOP, + { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, 0 } }, + { "gl_ProjectionMatrix", 4, SWIZZLE_NOOP, + { STATE_MATRIX, STATE_PROJECTION, 0, 0, 0, 0 } }, + { "gl_ModelViewProjectionMatrix", 4, SWIZZLE_NOOP, + { STATE_MATRIX, STATE_MVP, 0, 0, 0, 0 } }, + { "gl_TextureMatrix", 4, SWIZZLE_NOOP, + { STATE_MATRIX, STATE_TEXTURE, 0, 0, 0, 0 } }, + { NULL, 0, 0, {0, 0, 0, 0, 0, 0} } + }; + GLuint i; + + for (i = 0; state[i].Name; i++) { + if (strcmp(state[i].Name, name) == 0) { + /* found */ + if (paramList) { + if (state[i].NumRows > 1) { + /* a matrix */ + GLuint j; + GLint pos[4], indexesCopy[6]; + /* make copy of state tokens */ + for (j = 0; j < 6; j++) + indexesCopy[j] = state[i].Indexes[j]; + /* load rows */ + for (j = 0; j < state[i].NumRows; j++) { + indexesCopy[3] = indexesCopy[4] = j; /* jth row of matrix */ + pos[j] = _mesa_add_state_reference(paramList, indexesCopy); + assert(pos[j] >= 0); + } + return pos[0]; + } + else { + /* non-matrix state */ + GLint pos + = _mesa_add_state_reference(paramList, state[i].Indexes); + assert(pos >= 0); + return pos; + } + } + } + } + return -1; +} + + +static GLboolean +is_sampler_type(const slang_fully_specified_type *t) +{ + switch (t->specifier.type) { + case slang_spec_sampler1D: + case slang_spec_sampler2D: + case slang_spec_sampler3D: + case slang_spec_samplerCube: + case slang_spec_sampler1DShadow: + case slang_spec_sampler2DShadow: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +static GLuint +_slang_sizeof_struct(const slang_struct *s) +{ + return 0; +} + + +static GLuint +_slang_sizeof_type_specifier(const slang_type_specifier *spec) +{ + switch (spec->type) { + case slang_spec_void: + abort(); + return 0; + case slang_spec_bool: + return 1; + case slang_spec_bvec2: + return 2; + case slang_spec_bvec3: + return 3; + case slang_spec_bvec4: + return 4; + case slang_spec_int: + return 1; + case slang_spec_ivec2: + return 2; + case slang_spec_ivec3: + return 3; + case slang_spec_ivec4: + return 4; + case slang_spec_float: + return 1; + case slang_spec_vec2: + return 2; + case slang_spec_vec3: + return 3; + case slang_spec_vec4: + return 4; + case slang_spec_mat2: + return 2 * 2; + case slang_spec_mat3: + return 3 * 3; + case slang_spec_mat4: + return 4 * 4; + case slang_spec_sampler1D: + case slang_spec_sampler2D: + case slang_spec_sampler3D: + case slang_spec_samplerCube: + case slang_spec_sampler1DShadow: + case slang_spec_sampler2DShadow: + return 1; /* special case */ + case slang_spec_struct: + return _slang_sizeof_struct(spec->_struct); + case slang_spec_array: + return 1; /* XXX */ + default: + abort(); + return 0; + } + return 0; +} + + +/** + * Allocate storage info for an IR node (n->Store). + * We may do any of the following: + * 1. Compute Store->File/Index for program inputs/outputs/uniforms/etc. + * 2. Allocate storage for user-declared variables. + * 3. Allocate intermediate/unnamed storage for complex expressions. + * 4. other? + */ +static void +slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n, + struct gl_program *prog) +{ + assert(gc); + assert(n); + assert(n->Opcode == IR_VAR_DECL || n->Opcode == IR_VAR); + assert(prog); + + if (!n->Store) { + /* allocate storage info for this node */ + if (n->Var && n->Var->aux) { + /* node storage info = var storage info */ + n->Store = (slang_ir_storage *) n->Var->aux; + } + else { + /* alloc new storage info */ + n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -5); + if (n->Var) + n->Var->aux = n->Store; + } + } + + if (n->Opcode == IR_VAR_DECL) { + /* variable declaration */ + assert(n->Var); + assert(!is_sampler_type(&n->Var->type)); + assert(n->Store->Index < 0); + + n->Store->File = PROGRAM_TEMPORARY; + n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier); + assert(n->Store->Size > 0); + n->Store->Index = _slang_alloc_temporary(gc, n->Store->Size); + printf("alloc var %s storage at %d (size %d)\n", + (char *) n->Var->a_name, + n->Store->Index, + n->Store->Size); + assert(n->Store->Size > 0); + n->Var->declared = GL_TRUE; + return; + } + + assert(n->Store->File != PROGRAM_UNDEFINED); + + if (n->Store->Index < 0) { + /* determine storage location for this var */ + + assert(n->Var); + assert(n->Store->Size > 0); + + if (n->Store->File == PROGRAM_STATE_VAR) { + GLint i = slang_lookup_statevar((char *) n->Var->a_name, 0, + prog->Parameters); + assert(i >= 0); + if (i >= 0) { + assert(n->Store->File == PROGRAM_STATE_VAR /*|| + n->Store->File == PROGRAM_UNIFORM*/); + n->Store->File = PROGRAM_STATE_VAR; + n->Store->Index = i; + return; + } + } + else if (n->Store->File == PROGRAM_CONSTANT) { + GLint i = slang_lookup_constant((char *) n->Var->a_name, 0, + prog->Parameters); + assert(i >= 0); + if (i >= 0) { + n->Store->File = PROGRAM_CONSTANT; + n->Store->Index = i; + return; + } + } + else { + /* what's this??? */ + abort(); + } + } +} + + + /** * Map "_asm foo" to IR_FOO, etc. */ |