diff options
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_shader_0.c | 779 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau/nouveau_shader_2.c | 311 |
2 files changed, 566 insertions, 524 deletions
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c index 503eae36b7..d6ea42573a 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c @@ -188,7 +188,8 @@ pass0_create_subroutine(nouveauShader *nvs, const char *label) if (!nvs->program_tree) nvs->program_tree = &sub->header; else - pass0_append_fragment(nvs->program_tree, &sub->header, 0); + pass0_append_fragment(nvs->program_tree, + &sub->header, 0); } return sub; @@ -196,162 +197,168 @@ pass0_create_subroutine(nouveauShader *nvs, const char *label) static void pass0_make_reg(nouveauShader *nvs, nvsRegister *reg, - nvsRegFile file, unsigned int index) + nvsRegFile file, unsigned int index) { - struct pass0_rec *rec = nvs->pass_rec; - - /* defaults */ - *reg = nvr_unused; - /* -1 == quick-and-dirty temp alloc */ - if (file == NVS_FILE_TEMP && index == -1) { - index = rec->next_temp++; - assert(index < NVS_MAX_TEMPS); - } - reg->file = file; - reg->index = index; + struct pass0_rec *rec = nvs->pass_rec; + + /* defaults */ + *reg = nvr_unused; + /* -1 == quick-and-dirty temp alloc */ + if (file == NVS_FILE_TEMP && index == -1) { + index = rec->next_temp++; + assert(index < NVS_MAX_TEMPS); + } + reg->file = file; + reg->index = index; } static void pass0_make_swizzle(nvsSwzComp *swz, unsigned int mesa) { - int i; + int i; - for (i=0;i<4;i++) - swz[i] = _tx_mesa_swizzle[GET_SWZ(mesa, i)]; + for (i=0;i<4;i++) + swz[i] = _tx_mesa_swizzle[GET_SWZ(mesa, i)]; } static nvsOpcode pass0_make_opcode(enum prog_opcode op) { - if (op > MAX_OPCODE) - return NVS_OP_UNKNOWN; - return _tx_mesa_opcode[op]; + if (op > MAX_OPCODE) + return NVS_OP_UNKNOWN; + return _tx_mesa_opcode[op]; } static nvsCond pass0_make_condmask(GLuint mesa) { - if (mesa > COND_FL) - return NVS_COND_UNKNOWN; - return _tx_mesa_condmask[mesa]; + if (mesa > COND_FL) + return NVS_COND_UNKNOWN; + return _tx_mesa_condmask[mesa]; } static unsigned int pass0_make_mask(GLuint mesa_mask) { - unsigned int mask = 0; + unsigned int mask = 0; - if (mesa_mask & WRITEMASK_X) mask |= SMASK_X; - if (mesa_mask & WRITEMASK_Y) mask |= SMASK_Y; - if (mesa_mask & WRITEMASK_Z) mask |= SMASK_Z; - if (mesa_mask & WRITEMASK_W) mask |= SMASK_W; + if (mesa_mask & WRITEMASK_X) mask |= SMASK_X; + if (mesa_mask & WRITEMASK_Y) mask |= SMASK_Y; + if (mesa_mask & WRITEMASK_Z) mask |= SMASK_Z; + if (mesa_mask & WRITEMASK_W) mask |= SMASK_W; - return mask; + return mask; } static nvsTexTarget pass0_make_tex_target(GLuint mesa) { - switch (mesa) { - case TEXTURE_1D_INDEX: return NVS_TEX_TARGET_1D; - case TEXTURE_2D_INDEX: return NVS_TEX_TARGET_2D; - case TEXTURE_3D_INDEX: return NVS_TEX_TARGET_3D; - case TEXTURE_CUBE_INDEX: return NVS_TEX_TARGET_CUBE; - case TEXTURE_RECT_INDEX: return NVS_TEX_TARGET_RECT; - default: - return NVS_TEX_TARGET_UNKNOWN; - } + switch (mesa) { + case TEXTURE_1D_INDEX: return NVS_TEX_TARGET_1D; + case TEXTURE_2D_INDEX: return NVS_TEX_TARGET_2D; + case TEXTURE_3D_INDEX: return NVS_TEX_TARGET_3D; + case TEXTURE_CUBE_INDEX: return NVS_TEX_TARGET_CUBE; + case TEXTURE_RECT_INDEX: return NVS_TEX_TARGET_RECT; + default: + return NVS_TEX_TARGET_UNKNOWN; + } } static void pass0_make_dst_reg(nvsPtr nvs, nvsRegister *reg, struct prog_dst_register *dst) { - struct gl_program *mesa = (struct gl_program*)&nvs->mesa.vp; - nvsFixedReg sfr; - - switch (dst->File) { - case PROGRAM_OUTPUT: - if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { - sfr = (dst->Index < VERT_RESULT_MAX) ? - _tx_mesa_vp_dst_reg[dst->Index] : NVS_FR_UNKNOWN; - } else { - sfr = (dst->Index < FRAG_RESULT_MAX) ? - _tx_mesa_fp_dst_reg[dst->Index] : NVS_FR_UNKNOWN; - } - pass0_make_reg(nvs, reg, NVS_FILE_RESULT, sfr); - break; - case PROGRAM_TEMPORARY: - pass0_make_reg(nvs, reg, NVS_FILE_TEMP, dst->Index); - break; - case PROGRAM_ADDRESS: - pass0_make_reg(nvs, reg, NVS_FILE_ADDRESS, dst->Index); - break; - default: - fprintf(stderr, "Unknown dest file %d\n", dst->File); - assert(0); - } + struct gl_program *mesa = (struct gl_program*)&nvs->mesa.vp; + nvsFixedReg sfr; + + switch (dst->File) { + case PROGRAM_OUTPUT: + if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { + sfr = (dst->Index < VERT_RESULT_MAX) ? + _tx_mesa_vp_dst_reg[dst->Index] : + NVS_FR_UNKNOWN; + } else { + sfr = (dst->Index < FRAG_RESULT_MAX) ? + _tx_mesa_fp_dst_reg[dst->Index] : + NVS_FR_UNKNOWN; + } + pass0_make_reg(nvs, reg, NVS_FILE_RESULT, sfr); + break; + case PROGRAM_TEMPORARY: + pass0_make_reg(nvs, reg, NVS_FILE_TEMP, dst->Index); + break; + case PROGRAM_ADDRESS: + pass0_make_reg(nvs, reg, NVS_FILE_ADDRESS, dst->Index); + break; + default: + fprintf(stderr, "Unknown dest file %d\n", dst->File); + assert(0); + } } static void pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src) { - struct gl_program *mesa = (struct gl_program *)&nvs->mesa.vp.Base; - struct gl_program_parameter_list *p = mesa->Parameters; - - *reg = nvr_unused; - - switch (src->File) { - case PROGRAM_INPUT: - reg->file = NVS_FILE_ATTRIB; - if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { - reg->index = (src->Index < VERT_ATTRIB_MAX) ? - _tx_mesa_vp_src_reg[src->Index] : NVS_FR_UNKNOWN; - } else { - reg->index = (src->Index < FRAG_ATTRIB_MAX) ? - _tx_mesa_fp_src_reg[src->Index] : NVS_FR_UNKNOWN; - } - break; - /* All const types seem to get shoved into here, not really sure why */ - case PROGRAM_STATE_VAR: - switch (p->Parameters[src->Index].Type) { - case PROGRAM_NAMED_PARAM: - case PROGRAM_CONSTANT: - nvs->params[src->Index].source_val = NULL; - COPY_4V(nvs->params[src->Index].val, p->ParameterValues[src->Index]); - break; - case PROGRAM_STATE_VAR: - nvs->params[src->Index].source_val = p->ParameterValues[src->Index]; - break; - default: - fprintf(stderr, "Unknown parameter type %d\n", - p->Parameters[src->Index].Type); - assert(0); - break; - } - - if (src->RelAddr) { - reg->indexed = 1; - reg->addr_reg = 0; - reg->addr_comp = NVS_SWZ_X; - } else - reg->indexed = 0; - reg->file = NVS_FILE_CONST; - reg->index = src->Index; - break; - case PROGRAM_TEMPORARY: - reg->file = NVS_FILE_TEMP; - reg->index = src->Index; - break; - default: - fprintf(stderr, "Unknown source type %d\n", src->File); - assert(0); - } - - /* per-component negate handled elsewhere */ - reg->negate = src->NegateBase != 0; - reg->abs = src->Abs; - pass0_make_swizzle(reg->swizzle, src->Swizzle); + struct gl_program *mesa = (struct gl_program *)&nvs->mesa.vp.Base; + struct gl_program_parameter_list *p = mesa->Parameters; + + *reg = nvr_unused; + + switch (src->File) { + case PROGRAM_INPUT: + reg->file = NVS_FILE_ATTRIB; + if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { + reg->index = (src->Index < VERT_ATTRIB_MAX) ? + _tx_mesa_vp_src_reg[src->Index] : + NVS_FR_UNKNOWN; + } else { + reg->index = (src->Index < FRAG_ATTRIB_MAX) ? + _tx_mesa_fp_src_reg[src->Index] : + NVS_FR_UNKNOWN; + } + break; + /* All const types seem to get shoved into here, not really sure why */ + case PROGRAM_STATE_VAR: + switch (p->Parameters[src->Index].Type) { + case PROGRAM_NAMED_PARAM: + case PROGRAM_CONSTANT: + nvs->params[src->Index].source_val = NULL; + COPY_4V(nvs->params[src->Index].val, + p->ParameterValues[src->Index]); + break; + case PROGRAM_STATE_VAR: + nvs->params[src->Index].source_val = + p->ParameterValues[src->Index]; + break; + default: + fprintf(stderr, "Unknown parameter type %d\n", + p->Parameters[src->Index].Type); + assert(0); + break; + } + + if (src->RelAddr) { + reg->indexed = 1; + reg->addr_reg = 0; + reg->addr_comp = NVS_SWZ_X; + } else + reg->indexed = 0; + reg->file = NVS_FILE_CONST; + reg->index = src->Index; + break; + case PROGRAM_TEMPORARY: + reg->file = NVS_FILE_TEMP; + reg->index = src->Index; + break; + default: + fprintf(stderr, "Unknown source type %d\n", src->File); + assert(0); + } + + /* per-component negate handled elsewhere */ + reg->negate = src->NegateBase != 0; + reg->abs = src->Abs; + pass0_make_swizzle(reg->swizzle, src->Swizzle); } static nvsInstruction * @@ -389,59 +396,66 @@ pass0_emit(nouveauShader *nvs, nvsFragmentHeader *parent, int fpos, static void pass0_fixup_swizzle(nvsPtr nvs, nvsFragmentHeader *parent, int fpos, - struct prog_src_register *src, + struct prog_src_register *src, unsigned int sm1, unsigned int sm2) { - static const float sc[4] = { 1.0, 0.0, -1.0, 0.0 }; - struct pass0_rec *rec = nvs->pass_rec; - int fixup_1, fixup_2; - nvsRegister sr, dr = nvr_unused; - nvsRegister sm1const, sm2const; - - if (!rec->swzconst_done) { - struct gl_program *prog = &nvs->mesa.vp.Base; - rec->swzconst_id = _mesa_add_unnamed_constant(prog->Parameters, sc, 4); - rec->swzconst_done = 1; - COPY_4V(nvs->params[rec->swzconst_id].val, sc); - } - - fixup_1 = (sm1 != MAKE_SWIZZLE4(0,0,0,0) && sm2 != MAKE_SWIZZLE4(2,2,2,2)); - fixup_2 = (sm2 != MAKE_SWIZZLE4(2,2,2,2)); - - if (src->File != PROGRAM_TEMPORARY && src->File != PROGRAM_INPUT) { - /* We can't use more than one const in an instruction, so move the const - * into a temp, and swizzle from there. - *TODO: should just emit the swizzled const, instead of swizzling it - * in the shader.. would need to reswizzle any state params when they - * change however.. - */ - pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); - pass0_make_src_reg(nvs, &sr, src); - pass0_emit(nvs, parent, fpos, NVS_OP_MOV, dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused); - pass0_make_reg(nvs, &sr, NVS_FILE_TEMP, dr.index); - } else { - if (fixup_1) - src->NegateBase = 0; - pass0_make_src_reg(nvs, &sr, src); - pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); - } - - pass0_make_reg(nvs, &sm1const, NVS_FILE_CONST, rec->swzconst_id); - pass0_make_swizzle(sm1const.swizzle, sm1); - if (fixup_1 && fixup_2) { - /* Any combination with SWIZZLE_ONE */ - pass0_make_reg(nvs, &sm2const, NVS_FILE_CONST, rec->swzconst_id); - pass0_make_swizzle(sm2const.swizzle, sm2); - pass0_emit(nvs, parent, fpos, NVS_OP_MAD, dr, SMASK_ALL, 0, sr, sm1const, sm2const); - } else { - /* SWIZZLE_ZERO || arbitrary negate */ - pass0_emit(nvs, parent, fpos, NVS_OP_MUL, dr, SMASK_ALL, 0, sr, sm1const, nvr_unused); - } - - src->File = PROGRAM_TEMPORARY; - src->Index = dr.index; - src->Swizzle = SWIZZLE_NOOP; + static const float sc[4] = { 1.0, 0.0, -1.0, 0.0 }; + struct pass0_rec *rec = nvs->pass_rec; + int fixup_1, fixup_2; + nvsRegister sr, dr = nvr_unused; + nvsRegister sm1const, sm2const; + + if (!rec->swzconst_done) { + struct gl_program *prog = &nvs->mesa.vp.Base; + rec->swzconst_id = _mesa_add_unnamed_constant(prog->Parameters, + sc, 4); + rec->swzconst_done = 1; + COPY_4V(nvs->params[rec->swzconst_id].val, sc); + } + + fixup_1 = (sm1 != MAKE_SWIZZLE4(0,0,0,0) && + sm2 != MAKE_SWIZZLE4(2,2,2,2)); + fixup_2 = (sm2 != MAKE_SWIZZLE4(2,2,2,2)); + + if (src->File != PROGRAM_TEMPORARY && src->File != PROGRAM_INPUT) { + /* We can't use more than one const in an instruction, + * so move the const into a temp, and swizzle from there. + * + * TODO: should just emit the swizzled const, instead of + * swizzling it in the shader.. would need to reswizzle + * any state params when they change however.. + */ + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + pass0_make_src_reg(nvs, &sr, src); + pass0_emit(nvs, parent, fpos, NVS_OP_MOV, + dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused); + pass0_make_reg(nvs, &sr, NVS_FILE_TEMP, dr.index); + } else { + if (fixup_1) + src->NegateBase = 0; + pass0_make_src_reg(nvs, &sr, src); + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + } + + pass0_make_reg(nvs, &sm1const, NVS_FILE_CONST, rec->swzconst_id); + pass0_make_swizzle(sm1const.swizzle, sm1); + if (fixup_1 && fixup_2) { + /* Any combination with SWIZZLE_ONE */ + pass0_make_reg(nvs, &sm2const, + NVS_FILE_CONST, rec->swzconst_id); + pass0_make_swizzle(sm2const.swizzle, sm2); + pass0_emit(nvs, parent, fpos, NVS_OP_MAD, + dr, SMASK_ALL, 0, sr, sm1const, sm2const); + } else { + /* SWIZZLE_ZERO || arbitrary negate */ + pass0_emit(nvs, parent, fpos, NVS_OP_MUL, + dr, SMASK_ALL, 0, sr, sm1const, nvr_unused); + } + + src->File = PROGRAM_TEMPORARY; + src->Index = dr.index; + src->Swizzle = SWIZZLE_NOOP; } #define SET_SWZ(fs, cp, c) fs = (fs & ~(0x7<<(cp*3))) | (c<<(cp*3)) @@ -449,81 +463,86 @@ static void pass0_check_sources(nvsPtr nvs, nvsFragmentHeader *parent, int fpos, struct prog_instruction *inst) { - unsigned int insrc = -1, constsrc = -1; - int i; - - for (i=0;i<_mesa_num_inst_src_regs(inst->Opcode);i++) { - struct prog_src_register *src = &inst->SrcReg[i]; - unsigned int sm_1 = 0, sm_2 = 0; - nvsRegister sr, dr; - int do_mov = 0, c; - - /* Build up swizzle masks as if we were going to use - * "MAD new, src, const1, const2" to support arbitrary negation - * and SWIZZLE_ZERO/SWIZZLE_ONE. - */ - for (c=0;c<4;c++) { - if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ZERO) { - SET_SWZ(sm_1, c, SWIZZLE_Y); /* 0.0 */ - SET_SWZ(sm_2, c, SWIZZLE_Y); - SET_SWZ(src->Swizzle, c, SWIZZLE_X); - } else if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ONE) { - SET_SWZ(sm_1, c, SWIZZLE_Y); - if (src->NegateBase & (1<<c)) - SET_SWZ(sm_2, c, SWIZZLE_Z); /* -1.0 */ - else - SET_SWZ(sm_2, c, SWIZZLE_X); /* 1.0 */ - SET_SWZ(src->Swizzle, c, SWIZZLE_X); - } else { - if (src->NegateBase & (1<<c)) - SET_SWZ(sm_1, c, SWIZZLE_Z); /* -[xyzw] */ - else - SET_SWZ(sm_1, c, SWIZZLE_X); /* [xyzw] */ - SET_SWZ(sm_2, c, SWIZZLE_Y); - } - } - /* Unless we're multiplying by 1.0 or -1.0 on all components, and we're - * adding nothing to any component we have to emulate the swizzle. - */ - if ((sm_1 != MAKE_SWIZZLE4(0,0,0,0) && sm_1 != MAKE_SWIZZLE4(2,2,2,2)) || - sm_2 != MAKE_SWIZZLE4(1,1,1,1)) { - pass0_fixup_swizzle(nvs, parent, fpos, src, sm_1, sm_2); - /* The source is definitely in a temp now, so don't bother checking - * for multiple ATTRIB/CONST regs. - */ - continue; - } - - /* HW can't use more than one ATTRIB or PARAM in a single instruction */ - switch (src->File) { - case PROGRAM_INPUT: - if (insrc != -1 && insrc != src->Index) - do_mov = 1; - else insrc = src->Index; - break; - case PROGRAM_STATE_VAR: - if (constsrc != -1 && constsrc != src->Index) - do_mov = 1; - else constsrc = src->Index; - break; - default: - break; - } - - /* Emit any extra ATTRIB/CONST to a temp, and modify the Mesa instruction - * to point at the temp. - */ - if (do_mov) { - pass0_make_src_reg(nvs, &sr, src); - pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); - pass0_emit(nvs, parent, fpos, NVS_OP_MOV, dr, SMASK_ALL, 0, - sr, nvr_unused, nvr_unused); - - src->File = PROGRAM_TEMPORARY; - src->Index = dr.index; - src->Swizzle= SWIZZLE_NOOP; - } - } + unsigned int insrc = -1, constsrc = -1; + int i; + + for (i=0;i<_mesa_num_inst_src_regs(inst->Opcode);i++) { + struct prog_src_register *src = &inst->SrcReg[i]; + unsigned int sm_1 = 0, sm_2 = 0; + nvsRegister sr, dr; + int do_mov = 0, c; + + /* Build up swizzle masks as if we were going to use + * "MAD new, src, const1, const2" to support arbitrary negation + * and SWIZZLE_ZERO/SWIZZLE_ONE. + */ + for (c=0;c<4;c++) { + if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ZERO) { + SET_SWZ(sm_1, c, SWIZZLE_Y); /* 0.0 */ + SET_SWZ(sm_2, c, SWIZZLE_Y); + SET_SWZ(src->Swizzle, c, SWIZZLE_X); + } else if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ONE) { + SET_SWZ(sm_1, c, SWIZZLE_Y); + if (src->NegateBase & (1<<c)) + SET_SWZ(sm_2, c, SWIZZLE_Z); /* -1.0 */ + else + SET_SWZ(sm_2, c, SWIZZLE_X); /* 1.0 */ + SET_SWZ(src->Swizzle, c, SWIZZLE_X); + } else { + if (src->NegateBase & (1<<c)) + SET_SWZ(sm_1, c, SWIZZLE_Z); /* -[xyzw] */ + else + SET_SWZ(sm_1, c, SWIZZLE_X); /*[xyzw]*/ + SET_SWZ(sm_2, c, SWIZZLE_Y); + } + } + + /* Unless we're multiplying by 1.0 or -1.0 on all components, + * and we're adding nothing to any component we have to + * emulate the swizzle. + */ + if ((sm_1 != MAKE_SWIZZLE4(0,0,0,0) && + sm_1 != MAKE_SWIZZLE4(2,2,2,2)) || + sm_2 != MAKE_SWIZZLE4(1,1,1,1)) { + pass0_fixup_swizzle(nvs, parent, fpos, src, sm_1, sm_2); + /* The source is definitely in a temp now, so don't + * bother checking for multiple ATTRIB/CONST regs. + */ + continue; + } + + /* HW can't use more than one ATTRIB or PARAM in a single + * instruction */ + switch (src->File) { + case PROGRAM_INPUT: + if (insrc != -1 && insrc != src->Index) + do_mov = 1; + else insrc = src->Index; + break; + case PROGRAM_STATE_VAR: + if (constsrc != -1 && constsrc != src->Index) + do_mov = 1; + else constsrc = src->Index; + break; + default: + break; + } + + /* Emit any extra ATTRIB/CONST to a temp, and modify the Mesa + * instruction to point at the temp. + */ + if (do_mov) { + pass0_make_src_reg(nvs, &sr, src); + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + pass0_emit(nvs, parent, fpos, NVS_OP_MOV, + dr, SMASK_ALL, 0, + sr, nvr_unused, nvr_unused); + + src->File = PROGRAM_TEMPORARY; + src->Index = dr.index; + src->Swizzle= SWIZZLE_NOOP; + } + } } static GLboolean @@ -531,138 +550,150 @@ pass0_emulate_instruction(nouveauShader *nvs, nvsFragmentHeader *parent, int fpos, struct prog_instruction *inst) { - nvsFunc *shader = nvs->func; - nvsRegister src[3], dest, temp; - nvsInstruction *nvsinst; - struct pass0_rec *rec = nvs->pass_rec; - unsigned int mask = pass0_make_mask(inst->DstReg.WriteMask); - int i, sat; - - sat = (inst->SaturateMode == SATURATE_ZERO_ONE); - - /* Build all the "real" regs for the instruction */ - for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) - pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); - if (inst->Opcode != OPCODE_KIL) - pass0_make_dst_reg(nvs, &dest, &inst->DstReg); - - switch (inst->Opcode) { - case OPCODE_ABS: - if (shader->caps & SCAP_SRC_ABS) - pass0_emit(nvs, parent, fpos, NVS_OP_MOV, dest, mask, sat, - nvsAbs(src[0]), nvr_unused, nvr_unused); - else - pass0_emit(nvs, parent, fpos, NVS_OP_MAX, dest, mask, sat, - src[0], nvsNegate(src[0]), nvr_unused); - break; - case OPCODE_KIL: - /* This is only in ARB shaders, so we don't have to worry - * about clobbering a CC reg as they aren't supported anyway. - */ - /* MOVC0 temp, src */ - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - nvsinst = pass0_emit(nvs, parent, fpos, NVS_OP_MOV, temp, SMASK_ALL, 0, - src[0], nvr_unused, nvr_unused); - nvsinst->cond_update = 1; - nvsinst->cond_reg = 0; - /* KIL_NV (LT0.xyzw) temp */ - nvsinst = pass0_emit(nvs, parent, fpos, NVS_OP_KIL, nvr_unused, 0, 0, - nvr_unused, nvr_unused, nvr_unused); - nvsinst->cond = COND_LT; - nvsinst->cond_reg = 0; - nvsinst->cond_test = 1; - pass0_make_swizzle(nvsinst->cond_swizzle, MAKE_SWIZZLE4(0,1,2,3)); - break; - case OPCODE_LIT: - break; - case OPCODE_LRP: - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, parent, fpos, NVS_OP_MAD, temp, mask, 0, - nvsNegate(src[0]), src[2], src[2]); - pass0_emit(nvs, parent, fpos, NVS_OP_MAD, dest, mask, sat, - src[0], src[1], temp); - break; - case OPCODE_POW: - if (shader->SupportsOpcode(shader, NVS_OP_LG2) && - shader->SupportsOpcode(shader, NVS_OP_EX2)) { - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - /* LG2 temp.x, src0.c */ - pass0_emit(nvs, parent, fpos, NVS_OP_LG2, temp, SMASK_X, 0, - nvsSwizzle(src[0], X, X, X, X), - nvr_unused, - nvr_unused); - /* MUL temp.x, temp.x, src1.c */ - pass0_emit(nvs, parent, fpos, NVS_OP_MUL, temp, SMASK_X, 0, - nvsSwizzle(temp, X, X, X, X), - nvsSwizzle(src[1], X, X, X, X), - nvr_unused); - /* EX2 dest, temp.x */ - pass0_emit(nvs, parent, fpos, NVS_OP_EX2, dest, mask, sat, - nvsSwizzle(temp, X, X, X, X), - nvr_unused, - nvr_unused); - } else { - /* can we use EXP/LOG instead of EX2/LG2?? */ - fprintf(stderr, "Implement POW for NV20 vtxprog!\n"); - return GL_FALSE; - } - break; - case OPCODE_RSQ: - if (rec->const_half.file != NVS_FILE_CONST) { - GLfloat const_half[4] = { 0.5, 0.0, 0.0, 0.0 }; - pass0_make_reg(nvs, &rec->const_half, NVS_FILE_CONST, - _mesa_add_unnamed_constant(nvs->mesa.vp.Base.Parameters, - const_half, 4)); - COPY_4V(nvs->params[rec->const_half.index].val, const_half); - } - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, parent, fpos, NVS_OP_LG2, temp, SMASK_X, 0, - nvsAbs(nvsSwizzle(src[0], X, X, X, X)), - nvr_unused, - nvr_unused); - pass0_emit(nvs, parent, fpos, NVS_OP_MUL, temp, SMASK_X, 0, - nvsSwizzle(temp, X, X, X, X), - nvsNegate(rec->const_half), - nvr_unused); - pass0_emit(nvs, parent, fpos, NVS_OP_EX2, dest, mask, sat, - nvsSwizzle(temp, X, X, X, X), - nvr_unused, - nvr_unused); - break; - case OPCODE_SCS: - if (mask & SMASK_X) - pass0_emit(nvs, parent, fpos, NVS_OP_COS, dest, SMASK_X, sat, - nvsSwizzle(src[0], X, X, X, X), - nvr_unused, - nvr_unused); - if (mask & SMASK_Y) - pass0_emit(nvs, parent, fpos, NVS_OP_SIN, dest, SMASK_Y, sat, - nvsSwizzle(src[0], X, X, X, X), - nvr_unused, - nvr_unused); - break; - case OPCODE_SUB: - pass0_emit(nvs, parent, fpos, NVS_OP_ADD, dest, mask, sat, - src[0], nvsNegate(src[1]), nvr_unused); - break; - case OPCODE_XPD: - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, parent, fpos, NVS_OP_MUL, temp, SMASK_ALL, 0, - nvsSwizzle(src[0], Z, X, Y, Y), - nvsSwizzle(src[1], Y, Z, X, X), - nvr_unused); - pass0_emit(nvs, parent, fpos, NVS_OP_MAD, dest, (mask & ~SMASK_W), sat, - nvsSwizzle(src[0], Y, Z, X, X), - nvsSwizzle(src[1], Z, X, Y, Y), - nvsNegate(temp)); - break; - default: - fprintf(stderr, "hw doesn't support opcode \"%s\", and no emulation found\n", - _mesa_opcode_string(inst->Opcode)); - return GL_FALSE; - } - - return GL_TRUE; + nvsFunc *shader = nvs->func; + nvsRegister src[3], dest, temp; + nvsInstruction *nvsinst; + struct pass0_rec *rec = nvs->pass_rec; + unsigned int mask = pass0_make_mask(inst->DstReg.WriteMask); + int i, sat; + + sat = (inst->SaturateMode == SATURATE_ZERO_ONE); + + /* Build all the "real" regs for the instruction */ + for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) + pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); + if (inst->Opcode != OPCODE_KIL) + pass0_make_dst_reg(nvs, &dest, &inst->DstReg); + + switch (inst->Opcode) { + case OPCODE_ABS: + if (shader->caps & SCAP_SRC_ABS) + pass0_emit(nvs, parent, fpos, NVS_OP_MOV, + dest, mask, sat, + nvsAbs(src[0]), nvr_unused, nvr_unused); + else + pass0_emit(nvs, parent, fpos, NVS_OP_MAX, + dest, mask, sat, + src[0], nvsNegate(src[0]), nvr_unused); + break; + case OPCODE_KIL: + /* This is only in ARB shaders, so we don't have to worry + * about clobbering a CC reg as they aren't supported anyway. + */ + /* MOVC0 temp, src */ + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + nvsinst = pass0_emit(nvs, parent, fpos, NVS_OP_MOV, + temp, SMASK_ALL, 0, + src[0], nvr_unused, nvr_unused); + nvsinst->cond_update = 1; + nvsinst->cond_reg = 0; + /* KIL_NV (LT0.xyzw) temp */ + nvsinst = pass0_emit(nvs, parent, fpos, NVS_OP_KIL, + nvr_unused, 0, 0, + nvr_unused, nvr_unused, nvr_unused); + nvsinst->cond = COND_LT; + nvsinst->cond_reg = 0; + nvsinst->cond_test = 1; + pass0_make_swizzle(nvsinst->cond_swizzle, + MAKE_SWIZZLE4(0,1,2,3)); + break; + case OPCODE_LRP: + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + pass0_emit(nvs, parent, fpos, NVS_OP_MAD, temp, mask, 0, + nvsNegate(src[0]), src[2], src[2]); + pass0_emit(nvs, parent, fpos, NVS_OP_MAD, dest, mask, sat, + src[0], src[1], temp); + break; + case OPCODE_POW: + if (shader->SupportsOpcode(shader, NVS_OP_LG2) && + shader->SupportsOpcode(shader, NVS_OP_EX2)) { + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + /* LG2 temp.x, src0.c */ + pass0_emit(nvs, parent, fpos, NVS_OP_LG2, + temp, SMASK_X, 0, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, + nvr_unused); + /* MUL temp.x, temp.x, src1.c */ + pass0_emit(nvs, parent, fpos, NVS_OP_MUL, + temp, SMASK_X, 0, + nvsSwizzle(temp, X, X, X, X), + nvsSwizzle(src[1], X, X, X, X), + nvr_unused); + /* EX2 dest, temp.x */ + pass0_emit(nvs, parent, fpos, NVS_OP_EX2, + dest, mask, sat, + nvsSwizzle(temp, X, X, X, X), + nvr_unused, + nvr_unused); + } else { + /* can we use EXP/LOG instead of EX2/LG2?? */ + fprintf(stderr, "Implement POW for NV20 vtxprog!\n"); + return GL_FALSE; + } + break; + case OPCODE_RSQ: + if (rec->const_half.file != NVS_FILE_CONST) { + GLfloat const_half[4] = { 0.5, 0.0, 0.0, 0.0 }; + pass0_make_reg(nvs, &rec->const_half, NVS_FILE_CONST, + _mesa_add_unnamed_constant( + nvs->mesa.vp.Base.Parameters, + const_half, 4)); + COPY_4V(nvs->params[rec->const_half.index].val, + const_half); + } + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + pass0_emit(nvs, parent, fpos, NVS_OP_LG2, temp, SMASK_X, 0, + nvsAbs(nvsSwizzle(src[0], X, X, X, X)), + nvr_unused, + nvr_unused); + pass0_emit(nvs, parent, fpos, NVS_OP_MUL, temp, SMASK_X, 0, + nvsSwizzle(temp, X, X, X, X), + nvsNegate(rec->const_half), + nvr_unused); + pass0_emit(nvs, parent, fpos, NVS_OP_EX2, dest, mask, sat, + nvsSwizzle(temp, X, X, X, X), + nvr_unused, + nvr_unused); + break; + case OPCODE_SCS: + if (mask & SMASK_X) + pass0_emit(nvs, parent, fpos, NVS_OP_COS, + dest, SMASK_X, sat, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, + nvr_unused); + if (mask & SMASK_Y) + pass0_emit(nvs, parent, fpos, NVS_OP_SIN, + dest, SMASK_Y, sat, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, + nvr_unused); + break; + case OPCODE_SUB: + pass0_emit(nvs, parent, fpos, NVS_OP_ADD, dest, mask, sat, + src[0], nvsNegate(src[1]), nvr_unused); + break; + case OPCODE_XPD: + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + pass0_emit(nvs, parent, fpos, NVS_OP_MUL, temp, SMASK_ALL, 0, + nvsSwizzle(src[0], Z, X, Y, Y), + nvsSwizzle(src[1], Y, Z, X, X), + nvr_unused); + pass0_emit(nvs, parent, fpos, NVS_OP_MAD, + dest, (mask & ~SMASK_W), sat, + nvsSwizzle(src[0], Y, Z, X, X), + nvsSwizzle(src[1], Z, X, Y, Y), + nvsNegate(temp)); + break; + default: + WARN_ONCE("hw doesn't support opcode \"%s\"," + "and no emulation found\n", + _mesa_opcode_string(inst->Opcode)); + return GL_FALSE; + } + + return GL_TRUE; } static GLboolean diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c index b9b87ccf91..6fb36c1daf 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c @@ -41,130 +41,138 @@ #include "nouveau_msg.h" struct pass2_rec { - /* Map nvsRegister temp ID onto hw temp ID */ - unsigned int temps[NVS_MAX_TEMPS]; - /* Track free hw registers */ - unsigned int hw_temps[NVS_MAX_TEMPS]; + /* Map nvsRegister temp ID onto hw temp ID */ + unsigned int temps[NVS_MAX_TEMPS]; + /* Track free hw registers */ + unsigned int hw_temps[NVS_MAX_TEMPS]; }; static int pass2_alloc_hw_temp(nvsPtr nvs) { - struct pass2_rec *rec = nvs->pass_rec; - int i; - - for (i=0; i<nvs->func->MaxTemp; i++) { - /* This is a *horrible* hack.. R0 is both temp0 and result.color - * in NV30/40 fragprogs, we can use R0 as a temp before result is - * written however.. - */ - if (nvs->mesa.vp.Base.Target == GL_FRAGMENT_PROGRAM_ARB && i==0) - continue; - - if (rec->hw_temps[i] == 0) { - rec->hw_temps[i] = 1; - return i; - } - } - return -1; + struct pass2_rec *rec = nvs->pass_rec; + int i; + + for (i=0; i<nvs->func->MaxTemp; i++) { + /* This is a *horrible* hack.. R0 is both temp0 and result.color + * in NV30/40 fragprogs, we can use R0 as a temp before result + * is written however.. + */ + if (nvs->mesa.vp.Base.Target == GL_FRAGMENT_PROGRAM_ARB && i==0) + continue; + if (rec->hw_temps[i] == 0) { + rec->hw_temps[i] = 1; + return i; + } + } + + return -1; } static nvsRegister pass2_mangle_reg(nvsPtr nvs, nvsInstruction *inst, nvsRegister reg) { - struct pass2_rec *rec = nvs->pass_rec; + struct pass2_rec *rec = nvs->pass_rec; - if (reg.file == NVS_FILE_TEMP) { - if (rec->temps[reg.index] == -1) - rec->temps[reg.index] = pass2_alloc_hw_temp(nvs); - reg.index = rec->temps[reg.index]; - } + if (reg.file == NVS_FILE_TEMP) { + if (rec->temps[reg.index] == -1) + rec->temps[reg.index] = pass2_alloc_hw_temp(nvs); + reg.index = rec->temps[reg.index]; + } - return reg; + return reg; } static void pass2_add_instruction(nvsPtr nvs, nvsInstruction *inst, - struct _op_xlat *op, int slot) + struct _op_xlat *op, int slot) { - nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W }; - nvsFunc *shader = nvs->func; - nvsRegister reg; - int i; - - shader->SetOpcode(shader, op->NV, slot); - if (inst->saturate ) shader->SetSaturate(shader); - if (inst->cond_update) shader->SetCCUpdate(shader); - if (inst->cond_test ) shader->SetCondition(shader, 1, inst->cond, - inst->cond_reg, - inst->cond_swizzle); - else shader->SetCondition(shader, 0, NVS_COND_TR, - 0, - default_swz); - switch (inst->op) { - case NVS_OP_TEX: - case NVS_OP_TXB: - case NVS_OP_TXL: - case NVS_OP_TXP: - case NVS_OP_TXD: - shader->SetTexImageUnit(shader, inst->tex_unit); - break; - default: - break; - } - - for (i = 0; i < 3; i++) { - if (op->srcpos[i] != -1) { - reg = pass2_mangle_reg(nvs, inst, inst->src[i]); - if (reg.file == NVS_FILE_ATTRIB) - nvs->inputs_read |= (1 << reg.index); - shader->SetSource(shader, ®, op->srcpos[i]); - if (reg.file == NVS_FILE_CONST && shader->GetSourceConstVal) { - int idx_slot = nvs->params[reg.index].hw_index_cnt++; - nvs->params[reg.index].hw_index = realloc( - nvs->params[reg.index].hw_index, sizeof(int) * idx_slot+1); - nvs->params[reg.index].hw_index[idx_slot] = nvs->program_current + 4; - } - } - } - - reg = pass2_mangle_reg(nvs, inst, inst->dest); - if (reg.file == NVS_FILE_RESULT) - nvs->outputs_written |= (1 << reg.index); - shader->SetResult(shader, ®, inst->mask, slot); + nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, + NVS_SWZ_Z, NVS_SWZ_W }; + nvsFunc *shader = nvs->func; + nvsRegister reg; + int i; + + shader->SetOpcode(shader, op->NV, slot); + if (inst->saturate ) shader->SetSaturate(shader); + if (inst->cond_update ) shader->SetCCUpdate(shader); + if (inst->cond_test ) shader->SetCondition(shader, 1, inst->cond, + inst->cond_reg, + inst->cond_swizzle); + else shader->SetCondition(shader, 0, NVS_COND_TR, + 0, + default_swz); + switch (inst->op) { + case NVS_OP_TEX: + case NVS_OP_TXB: + case NVS_OP_TXL: + case NVS_OP_TXP: + case NVS_OP_TXD: + shader->SetTexImageUnit(shader, inst->tex_unit); + break; + default: + break; + } + + for (i = 0; i < 3; i++) { + if (op->srcpos[i] != -1) { + reg = pass2_mangle_reg(nvs, inst, inst->src[i]); + + if (reg.file == NVS_FILE_ATTRIB) + nvs->inputs_read |= (1 << reg.index); + shader->SetSource(shader, ®, op->srcpos[i]); + + if (reg.file == NVS_FILE_CONST && + shader->GetSourceConstVal) { + int idx_slot = + nvs->params[reg.index].hw_index_cnt++; + nvs->params[reg.index].hw_index = realloc( + nvs->params[reg.index].hw_index, + sizeof(int) * idx_slot+1); + nvs->params[reg.index].hw_index[idx_slot] = + nvs->program_current + 4; + } + } + } + + reg = pass2_mangle_reg(nvs, inst, inst->dest); + if (reg.file == NVS_FILE_RESULT) + nvs->outputs_written |= (1 << reg.index); + shader->SetResult(shader, ®, inst->mask, slot); } static int pass2_assemble_instruction(nvsPtr nvs, nvsInstruction *inst, int last) { - nvsFunc *shader = nvs->func; - struct _op_xlat *op; - unsigned int hw_inst[8]; - int slot; - int instsz; - int i; - - shader->inst = hw_inst; - - /* Assemble this instruction */ - if (!(op = shader->GetOPTXFromSOP(inst->op, &slot))) - return 0; - shader->InitInstruction(shader); - pass2_add_instruction(nvs, inst, op, slot); - if (last) - shader->SetLastInst(shader); - - instsz = shader->GetOffsetNext(nvs->func); - if (nvs->program_size + instsz >= nvs->program_alloc_size) { - nvs->program_alloc_size *= 2; - nvs->program = realloc(nvs->program, - nvs->program_alloc_size * sizeof(uint32_t)); - } - - for (i=0; i<instsz; i++) - nvs->program[nvs->program_current++] = hw_inst[i]; - nvs->program_size = nvs->program_current; - return 1; + nvsFunc *shader = nvs->func; + struct _op_xlat *op; + unsigned int hw_inst[8]; + int slot; + int instsz; + int i; + + shader->inst = hw_inst; + + /* Assemble this instruction */ + if (!(op = shader->GetOPTXFromSOP(inst->op, &slot))) + return 0; + shader->InitInstruction(shader); + pass2_add_instruction(nvs, inst, op, slot); + if (last) + shader->SetLastInst(shader); + + instsz = shader->GetOffsetNext(nvs->func); + if (nvs->program_size + instsz >= nvs->program_alloc_size) { + nvs->program_alloc_size *= 2; + nvs->program = realloc(nvs->program, + nvs->program_alloc_size * + sizeof(uint32_t)); + } + + for (i=0; i<instsz; i++) + nvs->program[nvs->program_current++] = hw_inst[i]; + nvs->program_size = nvs->program_current; + return 1; } static GLboolean @@ -198,53 +206,56 @@ pass2_translate(nvsPtr nvs, nvsFragmentHeader *f) GLboolean nouveau_shader_pass2(nvsPtr nvs) { - struct pass2_rec *rec; - int i; - - rec = calloc(1, sizeof(struct pass2_rec)); - for (i=0; i<NVS_MAX_TEMPS; i++) - rec->temps[i] = -1; - nvs->pass_rec = rec; - - /* Start off with allocating 4 uint32_t's for each inst, will be grown - * if necessary.. - */ - nvs->program_alloc_size = nvs->mesa.vp.Base.NumInstructions * 4; - nvs->program = calloc(nvs->program_alloc_size, sizeof(uint32_t)); - nvs->program_size = 0; - nvs->program_current = 0; - - if (!pass2_translate(nvs, ((nvsSubroutine*)nvs->program_tree)->insn_head)) { - free(nvs->program); - nvs->program = NULL; - return GL_FALSE; - } - - /* Shrink allocated memory to only what we need */ - nvs->program = realloc(nvs->program, nvs->program_size * sizeof(uint32_t)); - nvs->program_alloc_size = nvs->program_size; - - nvs->translated = 1; - nvs->on_hardware = 0; - - if (NOUVEAU_DEBUG & DEBUG_SHADERS) { - fflush(stdout); fflush(stderr); - fprintf(stderr, "----------------MESA PROGRAM target=%s, id=0x%x\n", - _mesa_lookup_enum_by_nr(nvs->mesa.vp.Base.Target), - nvs->mesa.vp.Base.Id); - fflush(stdout); fflush(stderr); - _mesa_print_program(&nvs->mesa.vp.Base); - fflush(stdout); fflush(stderr); - fprintf(stderr, "^^^^^^^^^^^^^^^^MESA PROGRAM\n"); - fflush(stdout); fflush(stderr); - fprintf(stderr, "----------------NV PROGRAM\n"); - fflush(stdout); fflush(stderr); - nvsDisasmHWShader(nvs); - fflush(stdout); fflush(stderr); - fprintf(stderr, "^^^^^^^^^^^^^^^^NV PROGRAM\n"); - fflush(stdout); fflush(stderr); - } - - return GL_TRUE; + struct pass2_rec *rec; + int i; + + rec = calloc(1, sizeof(struct pass2_rec)); + for (i=0; i<NVS_MAX_TEMPS; i++) + rec->temps[i] = -1; + nvs->pass_rec = rec; + + /* Start off with allocating 4 uint32_t's for each inst, will be grown + * if necessary.. + */ + nvs->program_alloc_size = nvs->mesa.vp.Base.NumInstructions * 4; + nvs->program = calloc(nvs->program_alloc_size, sizeof(uint32_t)); + nvs->program_size = 0; + nvs->program_current = 0; + + if (!pass2_translate(nvs, + ((nvsSubroutine*)nvs->program_tree)->insn_head)) { + free(nvs->program); + nvs->program = NULL; + return GL_FALSE; + } + + /* Shrink allocated memory to only what we need */ + nvs->program = realloc(nvs->program, + nvs->program_size * sizeof(uint32_t)); + nvs->program_alloc_size = nvs->program_size; + + nvs->translated = 1; + nvs->on_hardware = 0; + + if (NOUVEAU_DEBUG & DEBUG_SHADERS) { + fflush(stdout); fflush(stderr); + fprintf(stderr, "-----------MESA PROGRAM target=%s, id=0x%x\n", + _mesa_lookup_enum_by_nr( + nvs->mesa.vp.Base.Target), + nvs->mesa.vp.Base.Id); + fflush(stdout); fflush(stderr); + _mesa_print_program(&nvs->mesa.vp.Base); + fflush(stdout); fflush(stderr); + fprintf(stderr, "^^^^^^^^^^^^^^^^MESA PROGRAM\n"); + fflush(stdout); fflush(stderr); + fprintf(stderr, "----------------NV PROGRAM\n"); + fflush(stdout); fflush(stderr); + nvsDisasmHWShader(nvs); + fflush(stdout); fflush(stderr); + fprintf(stderr, "^^^^^^^^^^^^^^^^NV PROGRAM\n"); + fflush(stdout); fflush(stderr); + } + + return GL_TRUE; } |