📄 r200_vertprog.c
字号:
(!src[0].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4); o_inst->src2 = UNUSED_SRC_1; goto next; case OPCODE_FLR: /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W} ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */ o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_FRC, (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, t_dst_mask(dst.WriteMask)); o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = UNUSED_SRC_0; o_inst->src2 = UNUSED_SRC_1; o_inst++; o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst), t_dst_mask(dst.WriteMask)); o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = MAKE_VSF_SOURCE(u_temp_i, VSF_IN_COMPONENT_X, VSF_IN_COMPONENT_Y, VSF_IN_COMPONENT_Z, VSF_IN_COMPONENT_W, VSF_IN_CLASS_TMP, /* Not 100% sure about this */ (!src[0].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/); o_inst->src2 = UNUSED_SRC_0; u_temp_i--; goto next; case OPCODE_XPD: /* mul r0, r1.yzxw, r2.zxyw mad r0, -r2.yzxw, r1.zxyw, r0 */ hw_op=(src[0].File == PROGRAM_TEMPORARY && src[1].File == PROGRAM_TEMPORARY && (((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index))) ? R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD; o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, t_dst_mask(dst.WriteMask)); o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w t_src_class(src[0].File), src[0].NegateBase) | (src[0].RelAddr << 4); o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w t_src_class(src[1].File), src[1].NegateBase) | (src[1].RelAddr << 4); o_inst->src2 = UNUSED_SRC_1; o_inst++; u_temp_i--; o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst), t_dst_mask(dst.WriteMask)); o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w t_src_class(src[1].File), (!src[1].NegateBase) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4); o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w t_src_class(src[0].File), src[0].NegateBase) | (src[0].RelAddr << 4); o_inst->src2 = MAKE_VSF_SOURCE(u_temp_i+1, VSF_IN_COMPONENT_X, VSF_IN_COMPONENT_Y, VSF_IN_COMPONENT_Z, VSF_IN_COMPONENT_W, VSF_IN_CLASS_TMP, VSF_FLAG_NONE); goto next; case OPCODE_END: assert(0); default: break; } o_inst->op = MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst(&dst), t_dst_mask(dst.WriteMask)); if(are_srcs_scalar){ switch(operands){ case 1: o_inst->src0 = t_src_scalar(vp, &src[0]); o_inst->src1 = UNUSED_SRC_0; o_inst->src2 = UNUSED_SRC_1; break; case 2: o_inst->src0 = t_src_scalar(vp, &src[0]); o_inst->src1 = t_src_scalar(vp, &src[1]); o_inst->src2 = UNUSED_SRC_1; break; case 3: o_inst->src0 = t_src_scalar(vp, &src[0]); o_inst->src1 = t_src_scalar(vp, &src[1]); o_inst->src2 = t_src_scalar(vp, &src[2]); break; default: fprintf(stderr, "illegal number of operands %lu\n", operands); exit(-1); break; } } else { switch(operands){ case 1: o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = UNUSED_SRC_0; o_inst->src2 = UNUSED_SRC_1; break; case 2: o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = t_src(vp, &src[1]); o_inst->src2 = UNUSED_SRC_1; break; case 3: o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = t_src(vp, &src[1]); o_inst->src2 = t_src(vp, &src[2]); break; default: fprintf(stderr, "illegal number of operands %lu\n", operands); exit(-1); break; } } next: if (dofogfix) { o_inst++; if (vp->fogmode == GL_EXP) { o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, VSF_FLAG_X); o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE); o_inst->src2 = UNUSED_SRC_1; o_inst++; o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_E, R200_VSF_OUT_CLASS_RESULT_FOGC, VSF_FLAG_X); o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); o_inst->src1 = UNUSED_SRC_0; o_inst->src2 = UNUSED_SRC_1; } else if (vp->fogmode == GL_EXP2) { o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, VSF_FLAG_X); o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE); o_inst->src2 = UNUSED_SRC_1; o_inst++; o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, VSF_FLAG_X); o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); o_inst->src1 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); o_inst->src2 = UNUSED_SRC_1; o_inst++; o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_E, R200_VSF_OUT_CLASS_RESULT_FOGC, VSF_FLAG_X); o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); o_inst->src1 = UNUSED_SRC_0; o_inst->src2 = UNUSED_SRC_1; } else { /* fogmode == GL_LINEAR */ /* could do that with single op (dot) if using params like with fixed function pipeline fog */ o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, VSF_FLAG_X); o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, Z, Z, Z, Z, PARAM, NONE); o_inst->src2 = UNUSED_SRC_1; o_inst++; o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, R200_VSF_OUT_CLASS_RESULT_FOGC, VSF_FLAG_X); o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, W, W, W, W, PARAM, NONE); o_inst->src2 = UNUSED_SRC_1; } dofogfix = 0; } u_temp_used = (R200_VSF_MAX_TEMPS - 1) - u_temp_i; if (mesa_vp->Base.NumNativeTemporaries < (mesa_vp->Base.NumTemporaries + u_temp_used)) { mesa_vp->Base.NumNativeTemporaries = mesa_vp->Base.NumTemporaries + u_temp_used; } if ((mesa_vp->Base.NumTemporaries + u_temp_used) > R200_VSF_MAX_TEMPS) { if (R200_DEBUG & DEBUG_FALLBACKS) { fprintf(stderr, "Ran out of temps, num temps %d, us %d\n", mesa_vp->Base.NumTemporaries, u_temp_used); } return GL_FALSE; } u_temp_i = R200_VSF_MAX_TEMPS - 1; if(o_inst - vp->instr >= R200_VSF_MAX_INST) { mesa_vp->Base.NumNativeInstructions = 129; if (R200_DEBUG & DEBUG_FALLBACKS) { fprintf(stderr, "more than 128 native instructions\n"); } return GL_FALSE; } if ((o_inst->op & R200_VSF_OUT_CLASS_MASK) == R200_VSF_OUT_CLASS_RESULT_POS) { vp->pos_end = (o_inst - vp->instr); } } vp->native = GL_TRUE; mesa_vp->Base.NumNativeInstructions = (o_inst - vp->instr);#if 0 fprintf(stderr, "hw program:\n"); for(i=0; i < vp->program.length; i++) fprintf(stderr, "%08x\n", vp->instr[i]);#endif return GL_TRUE;}void r200SetupVertexProg( GLcontext *ctx ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); struct r200_vertex_program *vp = (struct r200_vertex_program *)ctx->VertexProgram.Current; GLboolean fallback; GLint i; if (!vp->translated || (ctx->Fog.Enabled && ctx->Fog.Mode != vp->fogmode)) { rmesa->curr_vp_hw = NULL; r200_translate_vertex_program(ctx, vp); } /* could optimize setting up vertex progs away for non-tcl hw */ fallback = !(vp->native && r200VertexProgUpdateParams(ctx, vp) && rmesa->r200Screen->drmSupportsVertexProgram); TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, fallback); if (rmesa->TclFallback) return; R200_STATECHANGE( rmesa, vap ); /* FIXME: fglrx sets R200_VAP_SINGLE_BUF_STATE_ENABLE too. Do we need it? maybe only when using more than 64 inst / 96 param? */ rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE /*| R200_VAP_SINGLE_BUF_STATE_ENABLE*/; R200_STATECHANGE( rmesa, pvs ); rmesa->hw.pvs.cmd[PVS_CNTL_1] = (0 << R200_PVS_CNTL_1_PROGRAM_START_SHIFT) | ((vp->mesa_program.Base.NumNativeInstructions - 1) << R200_PVS_CNTL_1_PROGRAM_END_SHIFT) | (vp->pos_end << R200_PVS_CNTL_1_POS_END_SHIFT); rmesa->hw.pvs.cmd[PVS_CNTL_2] = (0 << R200_PVS_CNTL_2_PARAM_OFFSET_SHIFT) | (vp->mesa_program.Base.NumNativeParameters << R200_PVS_CNTL_2_PARAM_COUNT_SHIFT); /* maybe user clip planes just work with vertex progs... untested */ if (ctx->Transform.ClipPlanesEnabled) { R200_STATECHANGE( rmesa, tcl ); if (vp->mesa_program.IsPositionInvariant) { rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (ctx->Transform.ClipPlanesEnabled << 2); } else { rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(0xfc); } } if (vp != rmesa->curr_vp_hw) { GLuint count = vp->mesa_program.Base.NumNativeInstructions; drm_radeon_cmd_header_t tmp; R200_STATECHANGE( rmesa, vpi[0] ); R200_STATECHANGE( rmesa, vpi[1] ); /* FIXME: what about using a memcopy... */ for (i = 0; (i < 64) && i < count; i++) { rmesa->hw.vpi[0].cmd[VPI_OPDST_0 + 4 * i] = vp->instr[i].op; rmesa->hw.vpi[0].cmd[VPI_SRC0_0 + 4 * i] = vp->instr[i].src0; rmesa->hw.vpi[0].cmd[VPI_SRC1_0 + 4 * i] = vp->instr[i].src1; rmesa->hw.vpi[0].cmd[VPI_SRC2_0 + 4 * i] = vp->instr[i].src2; } /* hack up the cmd_size so not the whole state atom is emitted always. This may require some more thought, we may emit half progs on lost state, but hopefully it won't matter? WARNING: must not use R200_DB_STATECHANGE, this will produce bogus (and rejected) packet emits (due to the mismatched cmd_size and count in cmd/last_cmd) */ rmesa->hw.vpi[0].cmd_size = 1 + 4 * ((count > 64) ? 64 : count); tmp.i = rmesa->hw.vpi[0].cmd[VPI_CMD_0]; tmp.veclinear.count = (count > 64) ? 64 : count; rmesa->hw.vpi[0].cmd[VPI_CMD_0] = tmp.i; if (count > 64) { for (i = 0; i < (count - 64); i++) { rmesa->hw.vpi[1].cmd[VPI_OPDST_0 + 4 * i] = vp->instr[i + 64].op; rmesa->hw.vpi[1].cmd[VPI_SRC0_0 + 4 * i] = vp->instr[i + 64].src0; rmesa->hw.vpi[1].cmd[VPI_SRC1_0 + 4 * i] = vp->instr[i + 64].src1; rmesa->hw.vpi[1].cmd[VPI_SRC2_0 + 4 * i] = vp->instr[i + 64].src2; } rmesa->hw.vpi[1].cmd_size = 1 + 4 * (count - 64); tmp.i = rmesa->hw.vpi[1].cmd[VPI_CMD_0]; tmp.veclinear.count = count - 64; rmesa->hw.vpi[1].cmd[VPI_CMD_0] = tmp.i; } rmesa->curr_vp_hw = vp; }}static voidr200BindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog){ r200ContextPtr rmesa = R200_CONTEXT(ctx); switch(target){ case GL_VERTEX_PROGRAM_ARB: rmesa->curr_vp_hw = NULL; break; default: _mesa_problem(ctx, "Target not supported yet!"); break; }}static struct gl_program *r200NewProgram(GLcontext *ctx, GLenum target, GLuint id){ struct r200_vertex_program *vp; switch(target){ case GL_VERTEX_PROGRAM_ARB: vp = CALLOC_STRUCT(r200_vertex_program); return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id); case GL_FRAGMENT_PROGRAM_ARB: case GL_FRAGMENT_PROGRAM_NV: return _mesa_init_fragment_program( ctx, CALLOC_STRUCT(gl_fragment_program), target, id ); default: _mesa_problem(ctx, "Bad target in r200NewProgram"); } return NULL; }static voidr200DeleteProgram(GLcontext *ctx, struct gl_program *prog){ _mesa_delete_program(ctx, prog);}static voidr200ProgramStringNotify(GLcontext *ctx, GLenum target, struct gl_program *prog){ struct r200_vertex_program *vp = (void *)prog; r200ContextPtr rmesa = R200_CONTEXT(ctx); switch(target) { case GL_VERTEX_PROGRAM_ARB: vp->translated = GL_FALSE; vp->fogpidx = 0;/* memset(&vp->translated, 0, sizeof(struct r200_vertex_program) - sizeof(struct gl_vertex_program));*/ r200_translate_vertex_program(ctx, vp); rmesa->curr_vp_hw = NULL; break; case GL_FRAGMENT_SHADER_ATI: rmesa->afs_loaded = NULL; break; } /* need this for tcl fallbacks */ _tnl_program_string(ctx, target, prog);}static GLbooleanr200IsProgramNative(GLcontext *ctx, GLenum target, struct gl_program *prog){ struct r200_vertex_program *vp = (void *)prog; switch(target){ case GL_VERTEX_STATE_PROGRAM_NV: case GL_VERTEX_PROGRAM_ARB: if (!vp->translated) { r200_translate_vertex_program(ctx, vp); } /* does not take parameters etc. into account */ return vp->native; default: _mesa_problem(ctx, "Bad target in r200NewProgram"); } return 0;}void r200InitShaderFuncs(struct dd_function_table *functions){ functions->NewProgram = r200NewProgram; functions->BindProgram = r200BindProgram; functions->DeleteProgram = r200DeleteProgram; functions->ProgramStringNotify = r200ProgramStringNotify; functions->IsProgramNative = r200IsProgramNative;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -