diff options
Diffstat (limited to 'src/mesa/shader/slang')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 2 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 109 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_log.c | 2 |
3 files changed, 101 insertions, 12 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index e7b2bad8c2..d83e3b01e6 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -3253,7 +3253,7 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper) index = _slang_gen_operation(A, &oper->children[1]); if (array && index) { /* bounds check */ - GLint constIndex = 0; + GLint constIndex = -1; if (index->Opcode == IR_FLOAT) { constIndex = (int) index->Value[0]; if (constIndex < 0 || constIndex >= arrayLen) { diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 6ab06864b9..672ec4bd60 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -330,6 +330,17 @@ constant_to_src_reg(struct prog_src_register *src, GLfloat val, } +static void +address_to_dst_reg(struct prog_dst_register *dst, GLuint index) +{ + assert(index == 0); /* only one address reg at this time */ + dst->File = PROGRAM_ADDRESS; + dst->Index = index; + dst->WriteMask = WRITEMASK_X; +} + + + /** * Add new instruction at end of given program. * \param prog the program to append instruction onto @@ -614,6 +625,7 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n) /* result storage */ alloc_node_storage(emitInfo, n, -1); + assert(n->Store->Index >= 0); if (n->Store->Size == 2) n->Writemask = WRITEMASK_XY; @@ -1546,6 +1558,60 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) /** + * Move a block registers from src to dst (or move a single register). + * \param size size of block, in floats (<=4 means one register) + */ +static struct prog_instruction * +move_block(slang_emit_info *emitInfo, + GLuint size, GLboolean relAddr, + const slang_ir_storage *dst, + const slang_ir_storage *src) +{ + struct prog_instruction *inst; + + if (size > 4) { + /* move matrix/struct etc (block of registers) */ + slang_ir_storage dstStore = *dst; + slang_ir_storage srcStore = *src; + //GLint size = srcStore.Size; + /*ASSERT(n->Children[0]->Writemask == WRITEMASK_XYZW); + ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP); + */ + dstStore.Size = 4; + srcStore.Size = 4; + while (size >= 4) { + inst = new_instruction(emitInfo, OPCODE_MOV); + inst->Comment = _mesa_strdup("IR_COPY block"); + storage_to_dst_reg(&inst->DstReg, &dstStore, WRITEMASK_XYZW); + storage_to_src_reg(&inst->SrcReg[0], &srcStore); + inst->SrcReg[0].RelAddr = relAddr; + srcStore.Index++; + dstStore.Index++; + size -= 4; + } + } + else { + /* single register move */ + GLuint writemask; + if (size == 1) { + GLuint comp = GET_SWZ(src->Swizzle, 0); + assert(comp < 4); + writemask = WRITEMASK_X << comp; + } + else { + writemask = WRITEMASK_XYZW; + } + inst = new_instruction(emitInfo, OPCODE_MOV); + storage_to_dst_reg(&inst->DstReg, dst, writemask); + storage_to_src_reg(&inst->SrcReg[0], src); + inst->SrcReg[0].RelAddr = relAddr; + } + return inst; +} + + + +/** * Dereference array element. Just resolve storage for the array * element represented by this node. */ @@ -1587,24 +1653,47 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n) else { /* Variable array index */ struct prog_instruction *inst; - slang_ir_storage dstStore = *n->Store; /* do codegen for array index expression */ emit(emitInfo, n->Children[1]); - inst = new_instruction(emitInfo, OPCODE_ARL); + /* allocate temp storage for the array element */ + assert(n->Store->Index < 0); + n->Store->File = PROGRAM_TEMPORARY; + n->Store->Parent = NULL; + alloc_node_storage(emitInfo, n, -1); + + if (n->Store->Size > 4) { + /* need to multiply the index by the element size */ + GLint elemSize = (n->Store->Size + 3) / 4; + slang_ir_storage indexTemp; - if (dstStore.Size > 4) - dstStore.Size = 4; /* only emit one instruction */ + /* allocate 1 float indexTemp */ + alloc_local_temp(emitInfo, &indexTemp, 1); + + /* MUL temp, index, elemSize */ + inst = new_instruction(emitInfo, OPCODE_MUL); + storage_to_dst_reg(&inst->DstReg, &indexTemp, WRITEMASK_X); + storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + constant_to_src_reg(&inst->SrcReg[1], elemSize, emitInfo); - storage_to_dst_reg(&inst->DstReg, &dstStore, n->Writemask); - storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + /* load ADDR[0].X = temp */ + inst = new_instruction(emitInfo, OPCODE_ARL); + storage_to_src_reg(&inst->SrcReg[0], &indexTemp); + address_to_dst_reg(&inst->DstReg, 0); - inst->DstReg.File = PROGRAM_ADDRESS; - inst->DstReg.Index = 0; /* always address register [0] */ - inst->Comment = _mesa_strdup("ARL ADDR"); + _slang_free_temp(emitInfo->vt, &indexTemp); + } + else { + /* simply load address reg w/ array index */ + inst = new_instruction(emitInfo, OPCODE_ARL); + storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + address_to_dst_reg(&inst->DstReg, 0); + } - n->Store->RelAddr = GL_TRUE; + /* copy from array element to temp storage */ + move_block(emitInfo, n->Store->Size, GL_TRUE, + n->Store, n->Children[0]->Store); } /* if array element size is one, make sure we only access X */ diff --git a/src/mesa/shader/slang/slang_log.c b/src/mesa/shader/slang/slang_log.c index dc838c72ad..25f696f67e 100644 --- a/src/mesa/shader/slang/slang_log.c +++ b/src/mesa/shader/slang/slang_log.c @@ -89,7 +89,7 @@ slang_info_log_message(slang_info_log * log, const char *prefix, slang_string_concat(log->text, "\n"); if (MESA_VERBOSE & VERBOSE_GLSL) { - _mesa_printf("Mesa: GLSL %s\n", log->text); + _mesa_printf("Mesa: GLSL %s", log->text); } return 1; |