diff options
Diffstat (limited to 'src/mesa/shader/slang/slang_emit.c')
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 114 |
1 files changed, 91 insertions, 23 deletions
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index ea446fa5d4..3f455e0640 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -62,6 +62,8 @@ typedef struct GLuint MaxInstructions; /**< size of prog->Instructions[] buffer */ + GLboolean UnresolvedFunctions; + /* code-gen options */ GLboolean EmitHighLevelInstructions; GLboolean EmitCondCodes; @@ -164,7 +166,7 @@ _slang_var_swizzle(GLint size, GLint comp) { switch (size) { case 1: - return MAKE_SWIZZLE4(comp, comp, comp, comp); + return MAKE_SWIZZLE4(comp, SWIZZLE_NIL, SWIZZLE_NIL, SWIZZLE_NIL); case 2: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL); case 3: @@ -446,12 +448,12 @@ new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode) static struct prog_instruction * emit_arl_load(slang_emit_info *emitInfo, - enum register_file file, GLint index, GLuint swizzle) + gl_register_file file, GLint index, GLuint swizzle) { struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL); inst->SrcReg[0].File = file; inst->SrcReg[0].Index = index; - inst->SrcReg[0].Swizzle = swizzle; + inst->SrcReg[0].Swizzle = fix_swizzle(swizzle); inst->DstReg.File = PROGRAM_ADDRESS; inst->DstReg.Index = 0; inst->DstReg.WriteMask = WRITEMASK_X; @@ -872,7 +874,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) emit(emitInfo, n->Children[1]); if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) { + /* XXX this error should have been caught in slang_codegen.c */ slang_info_log_error(emitInfo->log, "invalid operands to == or !="); + n->Store = NULL; return NULL; } @@ -902,6 +906,7 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) slang_ir_storage tempStore; if (!alloc_local_temp(emitInfo, &tempStore, 4)) { + n->Store = NULL; return NULL; /* out of temps */ } @@ -1130,7 +1135,7 @@ emit_negation(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[0]->Store, NULL, NULL); - inst->SrcReg[0].NegateBase = NEGATE_XYZW; + inst->SrcReg[0].Negate = NEGATE_XYZW; return inst; } @@ -1259,16 +1264,33 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) { struct prog_instruction *inst; gl_inst_opcode opcode; + GLboolean shadow = GL_FALSE; - if (n->Opcode == IR_TEX) { + switch (n->Opcode) { + case IR_TEX: opcode = OPCODE_TEX; - } - else if (n->Opcode == IR_TEXB) { + break; + case IR_TEX_SH: + opcode = OPCODE_TEX; + shadow = GL_TRUE; + break; + case IR_TEXB: opcode = OPCODE_TXB; - } - else { - assert(n->Opcode == IR_TEXP); + break; + case IR_TEXB_SH: + opcode = OPCODE_TXB; + shadow = GL_TRUE; + break; + case IR_TEXP: opcode = OPCODE_TXP; + break; + case IR_TEXP_SH: + opcode = OPCODE_TXP; + shadow = GL_TRUE; + break; + default: + _mesa_problem(NULL, "Bad IR TEX code"); + return NULL; } if (n->Children[0]->Opcode == IR_ELEMENT) { @@ -1300,6 +1322,8 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) NULL, NULL); + inst->TexShadow = shadow; + /* Store->Index is the uniform/sampler index */ assert(n->Children[0]->Store->Index >= 0); inst->TexSrcUnit = n->Children[0]->Store->Index; @@ -1335,7 +1359,8 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) inst = emit(emitInfo, n->Children[1]); if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) { - if (!emitInfo->log->text) { + if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) { + /* XXX this error should have been caught in slang_codegen.c */ slang_info_log_error(emitInfo->log, "invalid assignment"); } return NULL; @@ -1358,6 +1383,7 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) #if PEEPHOLE_OPTIMIZATIONS if (inst && + (n->Children[1]->Opcode != IR_SWIZZLE) && _slang_is_temp(emitInfo->vt, n->Children[1]->Store) && (inst->DstReg.File == n->Children[1]->Store->File) && (inst->DstReg.Index == n->Children[1]->Store->Index) && @@ -1374,13 +1400,9 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) * becomes: * MUL a, x, y; */ - if (n->Children[1]->Opcode != IR_SWIZZLE) - _slang_free_temp(emitInfo->vt, n->Children[1]->Store); - *n->Children[1]->Store = *n->Children[0]->Store; /* fixup the previous instruction (which stored the RHS result) */ assert(n->Children[0]->Store->Index >= 0); - storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store); return inst; } @@ -1813,6 +1835,25 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n) } +/** + * Return the size of a swizzle mask given that some swizzle components + * may be NIL/undefined. For example: + * swizzle_size(".zzxx") = 4 + * swizzle_size(".xy??") = 2 + * swizzle_size(".w???") = 1 + */ +static GLuint +swizzle_size(GLuint swizzle) +{ + GLuint i; + for (i = 0; i < 4; i++) { + if (GET_SWZ(swizzle, i) == SWIZZLE_NIL) + return i; + } + return 4; +} + + static struct prog_instruction * emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) { @@ -1820,14 +1861,25 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) inst = emit(emitInfo, n->Children[0]); -#if 0 - assert(n->Store->Parent); - /* Apply this node's swizzle to parent's storage */ - GLuint swizzle = n->Store->Swizzle; - _slang_copy_ir_storage(n->Store, n->Store->Parent); - n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle); + if (!n->Store->Parent) { + /* this covers a case such as "(b ? p : q).x" */ + n->Store->Parent = n->Children[0]->Store; + assert(n->Store->Parent); + } + + { + const GLuint swizzle = n->Store->Swizzle; + /* new storage is parent storage with updated Swizzle + Size fields */ + _slang_copy_ir_storage(n->Store, n->Store->Parent); + /* Apply this node's swizzle to parent's storage */ + n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle); + /* Update size */ + n->Store->Size = swizzle_size(n->Store->Swizzle); + } + assert(!n->Store->Parent); -#endif + assert(n->Store->Index >= 0); + return inst; } @@ -2107,6 +2159,7 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n) if (index < 0) { /* error */ char s[100]; + /* XXX isn't this really an out of memory/resources error? */ _mesa_snprintf(s, sizeof(s), "Undefined variable '%s'", (char *) n->Var->a_name); slang_info_log_error(emitInfo->log, s); @@ -2120,6 +2173,10 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n) /* mark var as used */ _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name); } + else if (n->Store->File == PROGRAM_INPUT) { + assert(n->Store->Index >= 0); + emitInfo->prog->InputsRead |= (1 << n->Store->Index); + } if (n->Store->Index < 0) { /* probably ran out of registers */ @@ -2142,6 +2199,12 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) return NULL; } + if (n->Comment) { + inst = new_instruction(emitInfo, OPCODE_NOP); + inst->Comment = _mesa_strdup(n->Comment); + inst = NULL; + } + switch (n->Opcode) { case IR_SEQ: /* sequence of two sub-trees */ @@ -2235,6 +2298,9 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_TEX: case IR_TEXB: case IR_TEXP: + case IR_TEX_SH: + case IR_TEXB_SH: + case IR_TEXP_SH: return emit_tex(emitInfo, n); case IR_NEG: return emit_negation(emitInfo, n); @@ -2424,7 +2490,9 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt, maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4; } if (prog->Parameters->NumParameters > maxUniforms) { - slang_info_log_error(log, "Constant/uniform register limit exceeded"); + slang_info_log_error(log, "Constant/uniform register limit exceeded " + "(max=%u vec4)", maxUniforms); + return GL_FALSE; } |