diff options
Diffstat (limited to 'src/mesa/shader/slang/slang_codegen.c')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 187 |
1 files changed, 110 insertions, 77 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 11340d26e2..8263aae334 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -296,46 +296,6 @@ _slang_array_size(GLint elemSize, GLint arrayLen) } - -/** - * Establish the binding between a slang_ir_node and a slang_variable. - * Then, allocate/attach a slang_ir_storage object to the IR node if needed. - * The IR node must be a IR_VAR or IR_VAR_DECL node. - * \param n the IR node - * \param var the variable to associate with the IR node - */ -static void -_slang_attach_storage(slang_ir_node *n, slang_variable *var) -{ - assert(n); - assert(var); - assert(n->Opcode == IR_VAR || n->Opcode == IR_VAR_DECL); - assert(!n->Var || n->Var == var); - - n->Var = var; - - if (!n->Store) { - /* need to setup storage */ - if (n->Var && n->Var->store) { - /* node storage info = var storage info */ - n->Store = n->Var->store; - } - else { - /* alloc new storage info */ - n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -7, -5); -#if 0 - printf("%s var=%s Store=%p Size=%d\n", __FUNCTION__, - (char*) var->a_name, - (void*) n->Store, n->Store->Size); -#endif - if (n->Var) - n->Var->store = n->Store; - assert(n->Var->store); - } - } -} - - /** * Return the TEXTURE_*_INDEX value that corresponds to a sampler type, * or -1 if the type is not a sampler. @@ -450,8 +410,8 @@ _slang_output_index(const char *name, GLenum target) { NULL, 0 } }; static const struct output_info fragOutputs[] = { - { "gl_FragColor", FRAG_RESULT_COLR }, - { "gl_FragDepth", FRAG_RESULT_DEPR }, + { "gl_FragColor", FRAG_RESULT_COLOR }, + { "gl_FragDepth", FRAG_RESULT_DEPTH }, { "gl_FragData", FRAG_RESULT_DATA0 }, { NULL, 0 } }; @@ -516,18 +476,28 @@ static slang_asm_info AsmInfo[] = { /* float binary op */ { "float_power", IR_POW, 1, 2 }, /* texture / sampler */ - { "vec4_tex1d", IR_TEX, 1, 2 }, - { "vec4_texb1d", IR_TEXB, 1, 2 }, /* 1d w/ bias */ - { "vec4_texp1d", IR_TEXP, 1, 2 }, /* 1d w/ projection */ - { "vec4_tex2d", IR_TEX, 1, 2 }, - { "vec4_texb2d", IR_TEXB, 1, 2 }, /* 2d w/ bias */ - { "vec4_texp2d", IR_TEXP, 1, 2 }, /* 2d w/ projection */ - { "vec4_tex3d", IR_TEX, 1, 2 }, - { "vec4_texb3d", IR_TEXB, 1, 2 }, /* 3d w/ bias */ - { "vec4_texp3d", IR_TEXP, 1, 2 }, /* 3d w/ projection */ - { "vec4_texcube", IR_TEX, 1, 2 }, /* cubemap */ - { "vec4_tex_rect", IR_TEX, 1, 2 }, /* rectangle */ - { "vec4_texp_rect", IR_TEX, 1, 2 },/* rectangle w/ projection */ + { "vec4_tex_1d", IR_TEX, 1, 2 }, + { "vec4_tex_1d_bias", IR_TEXB, 1, 2 }, /* 1d w/ bias */ + { "vec4_tex_1d_proj", IR_TEXP, 1, 2 }, /* 1d w/ projection */ + { "vec4_tex_2d", IR_TEX, 1, 2 }, + { "vec4_tex_2d_bias", IR_TEXB, 1, 2 }, /* 2d w/ bias */ + { "vec4_tex_2d_proj", IR_TEXP, 1, 2 }, /* 2d w/ projection */ + { "vec4_tex_3d", IR_TEX, 1, 2 }, + { "vec4_tex_3d_bias", IR_TEXB, 1, 2 }, /* 3d w/ bias */ + { "vec4_tex_3d_proj", IR_TEXP, 1, 2 }, /* 3d w/ projection */ + { "vec4_tex_cube", IR_TEX, 1, 2 }, /* cubemap */ + { "vec4_tex_rect", IR_TEX, 1, 2 }, /* rectangle */ + { "vec4_tex_rect_bias", IR_TEX, 1, 2 }, /* rectangle w/ projection */ + + /* texture / sampler but with shadow comparison */ + { "vec4_tex_1d_shadow", IR_TEX_SH, 1, 2 }, + { "vec4_tex_1d_bias_shadow", IR_TEXB_SH, 1, 2 }, + { "vec4_tex_1d_proj_shadow", IR_TEXP_SH, 1, 2 }, + { "vec4_tex_2d_shadow", IR_TEX_SH, 1, 2 }, + { "vec4_tex_2d_bias_shadow", IR_TEXB_SH, 1, 2 }, + { "vec4_tex_2d_proj_shadow", IR_TEXP_SH, 1, 2 }, + { "vec4_tex_rect_shadow", IR_TEX_SH, 1, 2 }, + { "vec4_tex_rect_proj_shadow", IR_TEXP_SH, 1, 2 }, /* unary op */ { "ivec4_to_vec4", IR_I_TO_F, 1, 1 }, /* int[4] to float[4] */ @@ -735,7 +705,14 @@ new_var(slang_assemble_ctx *A, slang_variable *var) { slang_ir_node *n = new_node0(IR_VAR); if (n) { - _slang_attach_storage(n, var); + ASSERT(var); + ASSERT(var->store); + ASSERT(!n->Store); + ASSERT(!n->Var); + + /* Set IR node's Var and Store pointers */ + n->Var = var; + n->Store = var->store; } return n; } @@ -1462,6 +1439,12 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun, /*_slang_label_delete(A->curFuncEndLabel);*/ A->curFuncEndLabel = prevFuncEndLabel; + if (A->pragmas->Debug) { + char s[1000]; + snprintf(s, sizeof(s), "Call/inline %s()", (char *) fun->header.a_name); + n->Comment = _slang_strdup(s); + } + return n; } @@ -2598,6 +2581,20 @@ _slang_can_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) } +static void +_unroll_loop_inc(slang_assemble_ctx * A) +{ + A->UnrollLoop++; +} + + +static void +_unroll_loop_dec(slang_assemble_ctx * A) +{ + A->UnrollLoop--; +} + + /** * Unroll a for-loop. * First we determine the number of iterations to unroll. @@ -2614,6 +2611,9 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) slang_ir_node *n, *root = NULL; slang_atom varId; + /* Set flag so code generator knows we're unrolling loops */ + _unroll_loop_inc( A ); + if (oper->children[0].type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) { /* for (int i=0; ... */ slang_variable *var; @@ -2636,11 +2636,15 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) /* make a copy of the loop body */ body = slang_operation_new(1); - if (!body) + if (!body) { + _unroll_loop_dec( A ); return NULL; + } - if (!slang_operation_copy(body, &oper->children[3])) + if (!slang_operation_copy(body, &oper->children[3])) { + _unroll_loop_dec( A ); return NULL; + } /* in body, replace instances of 'varId' with literal 'iter' */ { @@ -2651,6 +2655,7 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) if (!oldVar) { /* undeclared loop variable */ slang_operation_delete(body); + _unroll_loop_dec( A ); return NULL; } @@ -2665,11 +2670,18 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) /* do IR codegen for body */ n = _slang_gen_operation(A, body); + if (!n) { + _unroll_loop_dec( A ); + return NULL; + } + root = new_seq(root, n); slang_operation_delete(body); } + _unroll_loop_dec( A ); + return root; } @@ -2806,18 +2818,24 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK) && !haveElseClause) { /* Special case: generate a conditional break */ + if (!A->CurLoop && A->UnrollLoop) /* trying to unroll */ + return NULL; ifBody = new_break_if_true(A->CurLoop, cond); return ifBody; } else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE) && !haveElseClause) { - /* Special case: generate a conditional break */ + /* Special case: generate a conditional continue */ + if (!A->CurLoop && A->UnrollLoop) /* trying to unroll */ + return NULL; ifBody = new_cont_if_true(A->CurLoop, cond); return ifBody; } else { /* general case */ ifBody = _slang_gen_operation(A, &oper->children[1]); + if (!ifBody) + return NULL; if (haveElseClause) elseBody = _slang_gen_operation(A, &oper->children[2]); else @@ -2988,7 +3006,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var, slang_ir_node *varDecl, *n; slang_ir_storage *store; GLint arrayLen, size, totalSize; /* if array then totalSize > size */ - enum register_file file; + gl_register_file file; /*assert(!var->declared);*/ var->declared = GL_TRUE; @@ -3004,7 +3022,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var, file = PROGRAM_TEMPORARY; } - totalSize = size = _slang_sizeof_type_specifier(&var->type.specifier); + size = _slang_sizeof_type_specifier(&var->type.specifier); if (size <= 0) { slang_info_log_error(A->log, "invalid declaration for '%s'", varName); return NULL; @@ -3018,22 +3036,23 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var, if (!varDecl) return NULL; - _slang_attach_storage(varDecl, var); /* undefined storage at first */ - assert(var->store); - assert(varDecl->Store == var->store); - assert(varDecl->Store); - assert(varDecl->Store->Index < 0); - store = var->store; + /* Allocate slang_ir_storage for this variable if needed. + * Note that we may not actually allocate a constant or temporary register + * until later. + */ + if (!var->store) { + GLint index = -7; /* TBD / unknown */ + var->store = _slang_new_ir_storage(file, index, totalSize); + if (!var->store) + return NULL; /* out of memory */ + } - assert(store == varDecl->Store); + /* set the IR node's Var and Store pointers */ + varDecl->Var = var; + varDecl->Store = var->store; - /* Fill in storage fields which we now know. store->Index/Swizzle may be - * set for some cases below. Otherwise, store->Index/Swizzle will be set - * during code emit. - */ - store->File = file; - store->Size = totalSize; + store = var->store; /* if there's an initializer, generate IR for the expression */ if (initializer) { @@ -3662,7 +3681,7 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper) if (lhs && rhs) { /* convert lhs swizzle into writemask */ const GLuint swizzle = root_swizzle(lhs->Store); - GLuint writemask, newSwizzle; + GLuint writemask, newSwizzle = 0x0; if (!swizzle_to_writemask(A, swizzle, &writemask, &newSwizzle)) { /* Non-simple writemask, need to swizzle right hand side in * order to put components into the right place. @@ -4029,13 +4048,15 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) return _slang_gen_while(A, oper); case SLANG_OPER_BREAK: if (!A->CurLoop) { - slang_info_log_error(A->log, "'break' not in loop"); + if (!A->UnrollLoop) + slang_info_log_error(A->log, "'break' not in loop"); return NULL; } return new_break(A->CurLoop); case SLANG_OPER_CONTINUE: if (!A->CurLoop) { - slang_info_log_error(A->log, "'continue' not in loop"); + if (!A->UnrollLoop) + slang_info_log_error(A->log, "'continue' not in loop"); return NULL; } return _slang_gen_continue(A, oper); @@ -4333,13 +4354,25 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, if (prog) { /* user-defined uniform */ if (datatype == GL_NONE) { - if (var->type.specifier.type == SLANG_SPEC_STRUCT) { + if ((var->type.specifier.type == SLANG_SPEC_ARRAY && + var->type.specifier._array->type == SLANG_SPEC_STRUCT) || + (var->type.specifier.type == SLANG_SPEC_STRUCT)) { /* temporary work-around */ GLenum datatype = GL_FLOAT; GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName, totalSize, datatype, NULL); store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc, totalSize, swizzle); + + if (arrayLen > 0) { + GLint a = arrayLen - 1; + GLint i; + for (i = 0; i < a; i++) { + GLfloat value = (GLfloat)(i + uniformLoc + 1); + (void) _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM, + varName, 1, datatype, &value, NULL, 0x0); + } + } /* XXX what we need to do is unroll the struct into its * basic types, creating a uniform variable for each. |