📄 r200_vertprog.c
字号:
/**************************************************************************Copyright (C) 2005 Aapo Tahkola.All Rights Reserved.Permission is hereby granted, free of charge, to any person obtaining acopy of this software and associated documentation files (the "Software"),to deal in the Software without restriction, including without limitationon the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whomthe Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice (including the nextparagraph) shall be included in all copies or substantial portions of theSoftware.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALLTHE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OROTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THEUSE OR OTHER DEALINGS IN THE SOFTWARE.**************************************************************************//* * Authors: * Aapo Tahkola <aet@rasterburn.org> * Roland Scheidegger <rscheidegger_lists@hispeed.ch> */#include "main/glheader.h"#include "main/macros.h"#include "main/enums.h"#include "shader/program.h"#include "shader/prog_instruction.h"#include "shader/prog_parameter.h"#include "shader/prog_statevars.h"#include "shader/programopt.h"#include "tnl/tnl.h"#include "r200_context.h"#include "r200_vertprog.h"#include "r200_ioctl.h"#include "r200_tcl.h"#if SWIZZLE_X != VSF_IN_COMPONENT_X || \ SWIZZLE_Y != VSF_IN_COMPONENT_Y || \ SWIZZLE_Z != VSF_IN_COMPONENT_Z || \ SWIZZLE_W != VSF_IN_COMPONENT_W || \ SWIZZLE_ZERO != VSF_IN_COMPONENT_ZERO || \ SWIZZLE_ONE != VSF_IN_COMPONENT_ONE || \ WRITEMASK_X != VSF_FLAG_X || \ WRITEMASK_Y != VSF_FLAG_Y || \ WRITEMASK_Z != VSF_FLAG_Z || \ WRITEMASK_W != VSF_FLAG_W#error Cannot change these!#endif#define SCALAR_FLAG (1<<31)#define FLAG_MASK (1<<31)#define OP_MASK (0xf) /* we are unlikely to have more than 15 */#define OPN(operator, ip) {#operator, OPCODE_##operator, ip}static struct{ char *name; int opcode; unsigned long ip; /* number of input operands and flags */}op_names[]={ OPN(ABS, 1), OPN(ADD, 2), OPN(ARL, 1|SCALAR_FLAG), OPN(DP3, 2), OPN(DP4, 2), OPN(DPH, 2), OPN(DST, 2), OPN(EX2, 1|SCALAR_FLAG), OPN(EXP, 1|SCALAR_FLAG), OPN(FLR, 1), OPN(FRC, 1), OPN(LG2, 1|SCALAR_FLAG), OPN(LIT, 1), OPN(LOG, 1|SCALAR_FLAG), OPN(MAD, 3), OPN(MAX, 2), OPN(MIN, 2), OPN(MOV, 1), OPN(MUL, 2), OPN(POW, 2|SCALAR_FLAG), OPN(RCP, 1|SCALAR_FLAG), OPN(RSQ, 1|SCALAR_FLAG), OPN(SGE, 2), OPN(SLT, 2), OPN(SUB, 2), OPN(SWZ, 1), OPN(XPD, 2), OPN(PRINT, 0), OPN(END, 0),};#undef OPNstatic GLboolean r200VertexProgUpdateParams(GLcontext *ctx, struct r200_vertex_program *vp){ r200ContextPtr rmesa = R200_CONTEXT( ctx ); GLfloat *fcmd = (GLfloat *)&rmesa->hw.vpp[0].cmd[VPP_CMD_0 + 1]; int pi; struct gl_vertex_program *mesa_vp = &vp->mesa_program; struct gl_program_parameter_list *paramList; drm_radeon_cmd_header_t tmp; R200_STATECHANGE( rmesa, vpp[0] ); R200_STATECHANGE( rmesa, vpp[1] ); assert(mesa_vp->Base.Parameters); _mesa_load_state_parameters(ctx, mesa_vp->Base.Parameters); paramList = mesa_vp->Base.Parameters; if(paramList->NumParameters > R200_VSF_MAX_PARAM){ fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__); return GL_FALSE; } for(pi = 0; pi < paramList->NumParameters; pi++) { switch(paramList->Parameters[pi].Type) { case PROGRAM_STATE_VAR: case PROGRAM_NAMED_PARAM: //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name); case PROGRAM_CONSTANT: *fcmd++ = paramList->ParameterValues[pi][0]; *fcmd++ = paramList->ParameterValues[pi][1]; *fcmd++ = paramList->ParameterValues[pi][2]; *fcmd++ = paramList->ParameterValues[pi][3]; break; default: _mesa_problem(NULL, "Bad param type in %s", __FUNCTION__); break; } if (pi == 95) { fcmd = (GLfloat *)&rmesa->hw.vpp[1].cmd[VPP_CMD_0 + 1]; } } /* hack up the cmd_size so not the whole state atom is emitted always. */ rmesa->hw.vpp[0].cmd_size = 1 + 4 * ((paramList->NumParameters > 96) ? 96 : paramList->NumParameters); tmp.i = rmesa->hw.vpp[0].cmd[VPP_CMD_0]; tmp.veclinear.count = (paramList->NumParameters > 96) ? 96 : paramList->NumParameters; rmesa->hw.vpp[0].cmd[VPP_CMD_0] = tmp.i; if (paramList->NumParameters > 96) { rmesa->hw.vpp[1].cmd_size = 1 + 4 * (paramList->NumParameters - 96); tmp.i = rmesa->hw.vpp[1].cmd[VPP_CMD_0]; tmp.veclinear.count = paramList->NumParameters - 96; rmesa->hw.vpp[1].cmd[VPP_CMD_0] = tmp.i; } return GL_TRUE;}static INLINE unsigned long t_dst_mask(GLuint mask){ /* WRITEMASK_* is equivalent to VSF_FLAG_* */ return mask & VSF_FLAG_ALL;}static unsigned long t_dst(struct prog_dst_register *dst){ switch(dst->File) { case PROGRAM_TEMPORARY: return ((dst->Index << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP); case PROGRAM_OUTPUT: switch (dst->Index) { case VERT_RESULT_HPOS: return R200_VSF_OUT_CLASS_RESULT_POS; case VERT_RESULT_COL0: return R200_VSF_OUT_CLASS_RESULT_COLOR; case VERT_RESULT_COL1: return ((1 << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_RESULT_COLOR); case VERT_RESULT_FOGC: return R200_VSF_OUT_CLASS_RESULT_FOGC; case VERT_RESULT_TEX0: case VERT_RESULT_TEX1: case VERT_RESULT_TEX2: case VERT_RESULT_TEX3: case VERT_RESULT_TEX4: case VERT_RESULT_TEX5: return (((dst->Index - VERT_RESULT_TEX0) << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_RESULT_TEXC); case VERT_RESULT_PSIZ: return R200_VSF_OUT_CLASS_RESULT_POINTSIZE; default: fprintf(stderr, "problem in %s, unknown dst output reg %d\n", __FUNCTION__, dst->Index); exit(0); return 0; } case PROGRAM_ADDRESS: assert (dst->Index == 0); return R200_VSF_OUT_CLASS_ADDR; default: fprintf(stderr, "problem in %s, unknown register type %d\n", __FUNCTION__, dst->File); exit(0); return 0; }}static unsigned long t_src_class(enum register_file file){ switch(file){ case PROGRAM_TEMPORARY: return VSF_IN_CLASS_TMP; case PROGRAM_INPUT: return VSF_IN_CLASS_ATTR; case PROGRAM_LOCAL_PARAM: case PROGRAM_ENV_PARAM: case PROGRAM_NAMED_PARAM: case PROGRAM_CONSTANT: case PROGRAM_STATE_VAR: return VSF_IN_CLASS_PARAM; /* case PROGRAM_OUTPUT: case PROGRAM_WRITE_ONLY: case PROGRAM_ADDRESS: */ default: fprintf(stderr, "problem in %s", __FUNCTION__); exit(0); }}static INLINE unsigned long t_swizzle(GLubyte swizzle){/* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */ return swizzle;}#if 0static void vp_dump_inputs(struct r200_vertex_program *vp, char *caller){ int i; if(vp == NULL){ fprintf(stderr, "vp null in call to %s from %s\n", __FUNCTION__, caller); return ; } fprintf(stderr, "%s:<", caller); for(i=0; i < VERT_ATTRIB_MAX; i++) fprintf(stderr, "%d ", vp->inputs[i]); fprintf(stderr, ">\n");}#endifstatic unsigned long t_src_index(struct r200_vertex_program *vp, struct prog_src_register *src){/* int i; int max_reg = -1;*/ if(src->File == PROGRAM_INPUT){/* if(vp->inputs[src->Index] != -1) return vp->inputs[src->Index]; for(i=0; i < VERT_ATTRIB_MAX; i++) if(vp->inputs[i] > max_reg) max_reg = vp->inputs[i]; vp->inputs[src->Index] = max_reg+1;*/ //vp_dump_inputs(vp, __FUNCTION__); assert(vp->inputs[src->Index] != -1); return vp->inputs[src->Index]; } else { if (src->Index < 0) { fprintf(stderr, "WARNING negative offsets for indirect addressing do not work\n"); return 0; } return src->Index; }}static unsigned long t_src(struct r200_vertex_program *vp, struct prog_src_register *src){ return MAKE_VSF_SOURCE(t_src_index(vp, src), t_swizzle(GET_SWZ(src->Swizzle, 0)), t_swizzle(GET_SWZ(src->Swizzle, 1)), t_swizzle(GET_SWZ(src->Swizzle, 2)), t_swizzle(GET_SWZ(src->Swizzle, 3)), t_src_class(src->File), src->NegateBase) | (src->RelAddr << 4);}static unsigned long t_src_scalar(struct r200_vertex_program *vp, struct prog_src_register *src){ return MAKE_VSF_SOURCE(t_src_index(vp, src), t_swizzle(GET_SWZ(src->Swizzle, 0)), t_swizzle(GET_SWZ(src->Swizzle, 0)), t_swizzle(GET_SWZ(src->Swizzle, 0)), t_swizzle(GET_SWZ(src->Swizzle, 0)), t_src_class(src->File), src->NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src->RelAddr << 4);}static unsigned long t_opcode(enum prog_opcode opcode){ switch(opcode){ case OPCODE_ADD: return R200_VPI_OUT_OP_ADD; /* FIXME: ARL works fine, but negative offsets won't work - fglrx just * seems to ignore neg offsets which isn't quite correct... */ case OPCODE_ARL: return R200_VPI_OUT_OP_ARL; case OPCODE_DP4: return R200_VPI_OUT_OP_DOT; case OPCODE_DST: return R200_VPI_OUT_OP_DST; case OPCODE_EX2: return R200_VPI_OUT_OP_EX2; case OPCODE_EXP: return R200_VPI_OUT_OP_EXP; case OPCODE_FRC: return R200_VPI_OUT_OP_FRC; case OPCODE_LG2: return R200_VPI_OUT_OP_LG2; case OPCODE_LIT: return R200_VPI_OUT_OP_LIT; case OPCODE_LOG: return R200_VPI_OUT_OP_LOG; case OPCODE_MAX: return R200_VPI_OUT_OP_MAX; case OPCODE_MIN: return R200_VPI_OUT_OP_MIN; case OPCODE_MUL: return R200_VPI_OUT_OP_MUL; case OPCODE_RCP: return R200_VPI_OUT_OP_RCP; case OPCODE_RSQ: return R200_VPI_OUT_OP_RSQ; case OPCODE_SGE: return R200_VPI_OUT_OP_SGE; case OPCODE_SLT: return R200_VPI_OUT_OP_SLT; default: fprintf(stderr, "%s: Should not be called with opcode %d!", __FUNCTION__, opcode); } exit(-1); return 0;}static unsigned long op_operands(enum prog_opcode opcode){ int i; /* Can we trust mesas opcodes to be in order ? */ for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++) if(op_names[i].opcode == opcode) return op_names[i].ip; fprintf(stderr, "op %d not found in op_names\n", opcode); exit(-1); return 0;}/* TODO: Get rid of t_src_class call */#define CMP_SRCS(a, b) (((a.RelAddr != b.RelAddr) || (a.Index != b.Index)) && \ ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \ t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \ (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \ t_src_class(b.File) == VSF_IN_CLASS_ATTR))) \/* fglrx on rv250 codes up unused sources as follows: unused but necessary sources are same as previous source, zero-ed out. unnecessary sources are same as previous source but with VSF_IN_CLASS_NONE set. i.e. an add (2 args) has its 2nd arg (if you use it as mov) zero-ed out, and 3rd arg set to VSF_IN_CLASS_NONE. Not sure if strictly necessary. *//* use these simpler definitions. Must obviously not be used with not yet set up regs. Those are NOT semantically equivalent to the r300 ones, requires code changes */#define ZERO_SRC_0 (((o_inst->src0 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \ | ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT))))#define ZERO_SRC_1 (((o_inst->src1 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \ | ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT))))#define ZERO_SRC_2 (((o_inst->src2 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \ | ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \ | (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT))))#define UNUSED_SRC_0 ((o_inst->src0 & ~15) | 9)#define UNUSED_SRC_1 ((o_inst->src1 & ~15) | 9)#define UNUSED_SRC_2 ((o_inst->src2 & ~15) | 9)/** * Generate an R200 vertex program from Mesa's internal representation. * * \return GL_TRUE for success, GL_FALSE for failure. */static GLboolean r200_translate_vertex_program(GLcontext *ctx, struct r200_vertex_program *vp){ struct gl_vertex_program *mesa_vp = &vp->mesa_program; struct prog_instruction *vpi; int i; VERTEX_SHADER_INSTRUCTION *o_inst; unsigned long operands; int are_srcs_scalar; unsigned long hw_op; int dofogfix = 0; int fog_temp_i = 0; int free_inputs; int array_count = 0; int u_temp_used; vp->native = GL_FALSE; vp->translated = GL_TRUE; vp->fogmode = ctx->Fog.Mode; if (mesa_vp->Base.NumInstructions == 0) return GL_FALSE;#if 0 if ((mesa_vp->Base.InputsRead & ~(VERT_BIT_POS | VERT_BIT_NORMAL | VERT_BIT_COLOR0 | VERT_BIT_COLOR1 | VERT_BIT_FOG | VERT_BIT_TEX0 | VERT_BIT_TEX1 | VERT_BIT_TEX2 |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -