From 7bccfa10269f228844d65ee198414970ad8cc881 Mon Sep 17 00:00:00 2001 From: Aapo Tahkola Date: Tue, 1 Feb 2005 16:56:52 +0000 Subject: [PATCH] Vertex programs work now with some restrictions. I expect arbvptorus to work correctly when normals are delivered. Please note that some programs only start in vb mode as there is something wrong in immediate mode vb code. --- src/mesa/drivers/dri/r300/r300_context.h | 7 +- src/mesa/drivers/dri/r300/r300_render.c | 1 - src/mesa/drivers/dri/r300/r300_state.c | 100 ++++-- src/mesa/drivers/dri/r300/r300_vertexprog.c | 351 +++++++++++++------- 4 files changed, 320 insertions(+), 139 deletions(-) diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h index 0e0aa665a56..14f06fba4cc 100644 --- a/src/mesa/drivers/dri/r300/r300_context.h +++ b/src/mesa/drivers/dri/r300/r300_context.h @@ -538,7 +538,10 @@ struct r300_vertex_program { struct r300_vertex_shader_fragment program; struct r300_vertex_shader_fragment params; - + + int t2rs; + unsigned long num_temporaries; /* Number of temp vars used by program */ + int inputs[VERT_ATTRIB_MAX]; }; /* 64 appears to be the maximum */ @@ -686,6 +689,8 @@ extern void r300DestroyContext(__DRIcontextPrivate * driContextPriv); extern GLboolean r300CreateContext(const __GLcontextModes * glVisual, __DRIcontextPrivate * driContextPriv, void *sharedContextPrivate); + extern void r300InitVertexProgFuncs(struct dd_function_table *functions); +extern void r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp); #endif /* __R300_CONTEXT_H__ */ diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c index 75ef2bfacc1..1e4db5e1d34 100644 --- a/src/mesa/drivers/dri/r300/r300_render.c +++ b/src/mesa/drivers/dri/r300/r300_render.c @@ -626,7 +626,6 @@ static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage) for (i = 1; i < ctx->Const.MaxTextureUnits; i++) FALLBACK_IF(ctx->Texture.Unit[i].Enabled); - /* let r300_run_render do its job */ #if 0 stage->active = GL_FALSE; diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index c75f2154e1a..e17cb8fe4d8 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -844,28 +844,80 @@ void r300_setup_routing(GLcontext *ctx, GLboolean immediate) /* All offsets are 0 - for use by immediate mode. Should change later to handle vertex buffers */ + if(r300->current_vp){ + + /* VERT_ATTRIB_WEIGHT, VERT_ATTRIB_SIX, VERT_ATTRIB_SEVEN, VERT_ATTRIB_GENERIC0, + VERT_ATTRIB_GENERIC1, VERT_ATTRIB_GENERIC2, VERT_ATTRIB_GENERIC3 */ + + if(r300->current_vp->inputs[VERT_ATTRIB_POS] != -1){ + if(tnl->render_inputs & _TNL_BIT_POS){ + reg=r300->current_vp->inputs[VERT_ATTRIB_POS]; + CONFIGURE_AOS(VB->ObjPtr, 0, i_coords, AOS_FORMAT_FLOAT); + }else fprintf(stderr, "vp expects pos but none was given\n"); + } + if(r300->current_vp->inputs[VERT_ATTRIB_NORMAL] != -1){ + if(tnl->render_inputs & _TNL_BIT_NORMAL){ + reg=r300->current_vp->inputs[VERT_ATTRIB_NORMAL]; + CONFIGURE_AOS(VB->NormalPtr, 0, i_normal, AOS_FORMAT_FLOAT); + }else fprintf(stderr, "vp expects normal but none was given\n"); + } + if(r300->current_vp->inputs[VERT_ATTRIB_COLOR0] != -1){ + if(tnl->render_inputs & _TNL_BIT_COLOR0){ + reg=r300->current_vp->inputs[VERT_ATTRIB_COLOR0]; + CONFIGURE_AOS(VB->ColorPtr[0], 0, i_color[0], AOS_FORMAT_FLOAT_COLOR); + }else fprintf(stderr, "vp expects primary color but none was given\n"); + } + if(r300->current_vp->inputs[VERT_ATTRIB_COLOR1] != -1){ + if(tnl->render_inputs & _TNL_BIT_COLOR1){ + reg=r300->current_vp->inputs[VERT_ATTRIB_COLOR1]; + CONFIGURE_AOS(VB->SecondaryColorPtr[0], 0, i_color[1], AOS_FORMAT_FLOAT_COLOR); + }else fprintf(stderr, "vp expects secondary color but none was given\n"); + } + if(r300->current_vp->inputs[VERT_ATTRIB_FOG] != -1){ + if(tnl->render_inputs & _TNL_BIT_FOG){ + reg=r300->current_vp->inputs[VERT_ATTRIB_FOG]; + CONFIGURE_AOS(VB->FogCoordPtr, 0, i_fog, AOS_FORMAT_FLOAT); + }else fprintf(stderr, "vp expects fog but none was given\n"); + } + for(i=0;i < ctx->Const.MaxTextureUnits;i++) // tex 7 is last + if(r300->current_vp->inputs[VERT_ATTRIB_TEX0+i] != -1){ + if(tnl->render_inputs & (_TNL_BIT_TEX0<current_vp->inputs[VERT_ATTRIB_TEX0+i]; + CONFIGURE_AOS(VB->TexCoordPtr[i], 0, i_tex[i], AOS_FORMAT_FLOAT); + }else fprintf(stderr, "vp expects tex%d but none was given\n", i); + } +#if 0 + if((tnl->render_inputs & _TNL_BIT_INDEX)) + CONFIGURE_AOS(VB->IndexPtr[0], 0, i_index, AOS_FORMAT_FLOAT); + + if((tnl->render_inputs & _TNL_BIT_POINTSIZE)) + CONFIGURE_AOS(VB->PointSizePtr, 0, i_pointsize, AOS_FORMAT_FLOAT); +#endif + }else{ + if(tnl->render_inputs & _TNL_BIT_POS) CONFIGURE_AOS(VB->ObjPtr, 0, i_coords, AOS_FORMAT_FLOAT); if(tnl->render_inputs & _TNL_BIT_NORMAL) CONFIGURE_AOS(VB->NormalPtr, 0, i_normal, AOS_FORMAT_FLOAT); - + if(tnl->render_inputs & _TNL_BIT_COLOR0) CONFIGURE_AOS(VB->ColorPtr[0], 0, i_color[0], AOS_FORMAT_FLOAT_COLOR); if(tnl->render_inputs & _TNL_BIT_COLOR1) CONFIGURE_AOS(VB->SecondaryColorPtr[0], 0, i_color[1], AOS_FORMAT_FLOAT_COLOR); - + if(tnl->render_inputs & _TNL_BIT_FOG) CONFIGURE_AOS(VB->FogCoordPtr, 0, i_fog, AOS_FORMAT_FLOAT); - + for(i=0;i < ctx->Const.MaxTextureUnits;i++) if(tnl->render_inputs & (_TNL_BIT_TEX0<TexCoordPtr[i], 0, i_tex[i], AOS_FORMAT_FLOAT); - + if(tnl->render_inputs & _TNL_BIT_INDEX) CONFIGURE_AOS(VB->IndexPtr[0], 0, i_index, AOS_FORMAT_FLOAT); if(tnl->render_inputs & _TNL_BIT_POINTSIZE) CONFIGURE_AOS(VB->PointSizePtr, 0, i_pointsize, AOS_FORMAT_FLOAT); - + } + r300->state.aos_count=count; if (RADEON_DEBUG & DEBUG_STATE) @@ -1245,11 +1297,16 @@ void static inline setup_vertex_shader_fragment(r300ContextPtr r300, int dest, s } } +void r300SetupVertexProgram(r300ContextPtr rmesa); void r300SetupVertexShader(r300ContextPtr rmesa) { GLcontext* ctx = rmesa->radeon.glCtx; - + + if(rmesa->current_vp){ + r300SetupVertexProgram(rmesa); + return ; + } /* Reset state, in case we don't use something */ ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0; ((drm_r300_cmd_header_t*)rmesa->hw.vpi.cmd)->vpu.count = 0; @@ -1306,27 +1363,15 @@ void r300SetupVertexShader(r300ContextPtr rmesa) void r300SetupVertexProgram(r300ContextPtr rmesa) { GLcontext* ctx = rmesa->radeon.glCtx; + int inst_count; + int param_count; /* Reset state, in case we don't use something */ ((drm_r300_cmd_header_t*)rmesa->hw.vpp.cmd)->vpu.count = 0; ((drm_r300_cmd_header_t*)rmesa->hw.vpi.cmd)->vpu.count = 0; ((drm_r300_cmd_header_t*)rmesa->hw.vps.cmd)->vpu.count = 0; -#if 0 -/* This needs to be replaced by vertex shader generation code */ - - - /* textures enabled ? */ - if(rmesa->state.texture.tc_count>0){ - rmesa->state.vertex_shader=SINGLE_TEXTURE_VERTEX_SHADER; - } else { - rmesa->state.vertex_shader=FLAT_COLOR_VERTEX_SHADER; - } - - - rmesa->state.vertex_shader.matrix[0].length=16; - memcpy(rmesa->state.vertex_shader.matrix[0].body.f, ctx->_ModelProjectMatrix.m, 16*4); -#endif + r300VertexProgUpdateParams(ctx, rmesa->current_vp); setup_vertex_shader_fragment(rmesa, VSF_DEST_PROGRAM, &(rmesa->current_vp->program)); @@ -1336,15 +1381,18 @@ void r300SetupVertexProgram(r300ContextPtr rmesa) setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN1, &(rmesa->state.vertex_shader.unknown1)); setup_vertex_shader_fragment(rmesa, VSF_DEST_UNKNOWN2, &(rmesa->state.vertex_shader.unknown2)); #endif - + + inst_count=rmesa->current_vp->program.length/4 - 1; + param_count=rmesa->current_vp->params.length/4; + R300_STATECHANGE(rmesa, pvs); rmesa->hw.pvs.cmd[R300_PVS_CNTL_1]=(0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) - | (rmesa->state.vertex_shader.unknown_ptr1 << R300_PVS_CNTL_1_UNKNOWN_SHIFT) - | (rmesa->current_vp->program.length/4 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); + | (inst_count/*0*/ << R300_PVS_CNTL_1_UNKNOWN_SHIFT) + | (inst_count << R300_PVS_CNTL_1_PROGRAM_END_SHIFT); rmesa->hw.pvs.cmd[R300_PVS_CNTL_2]=(0 << R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT) - | (rmesa->current_vp->params.length/4 << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT); + | (param_count << R300_PVS_CNTL_2_PARAM_COUNT_SHIFT); rmesa->hw.pvs.cmd[R300_PVS_CNTL_3]=(0/*rmesa->state.vertex_shader.unknown_ptr2*/ << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT) - | (rmesa->current_vp->program.length/4/*rmesa->state.vertex_shader.unknown_ptr3*/ << 0); + | ((inst_count-rmesa->current_vp->t2rs) /*rmesa->state.vertex_shader.unknown_ptr3*/ << 0); /* This is done for vertex shader fragments, but also needs to be done for vap_pvs, so I leave it as a reminder */ diff --git a/src/mesa/drivers/dri/r300/r300_vertexprog.c b/src/mesa/drivers/dri/r300/r300_vertexprog.c index 50a816c6d41..c137c847644 100644 --- a/src/mesa/drivers/dri/r300/r300_vertexprog.c +++ b/src/mesa/drivers/dri/r300/r300_vertexprog.c @@ -1,3 +1,34 @@ +/************************************************************************** + +Copyright (C) 2005 Aapo Tahkola. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Aapo Tahkola + */ #include "glheader.h" #include "macros.h" #include "enums.h" @@ -99,7 +130,7 @@ char *dst_mask_names[4]={ "X", "Y", "Z", "W" }; XPD v,v v cross product */ -void dump_program_params(struct vertex_program *vp) +void dump_program_params(GLcontext *ctx, struct vertex_program *vp) { int i; int pi; @@ -110,6 +141,8 @@ void dump_program_params(struct vertex_program *vp) fprintf(stderr, "NumAttributes=%d\n", vp->Base.NumAttributes); fprintf(stderr, "NumAddressRegs=%d\n", vp->Base.NumAddressRegs); + _mesa_load_state_parameters(ctx, vp->Parameters); + #if 0 for(pi=0; pi < vp->Base.NumParameters; pi++){ fprintf(stderr, "{ "); @@ -134,8 +167,6 @@ void dump_program_params(struct vertex_program *vp) case STATE: fprintf(stderr, "(STATE)\n"); - /* fetch state info */ - continue; break; } @@ -148,13 +179,13 @@ void dump_program_params(struct vertex_program *vp) } } -static void debug_vp(struct vertex_program *vp) +static void debug_vp(GLcontext *ctx, struct vertex_program *vp) { struct vp_instruction *vpi; int i, operand_index; int operator_index; - dump_program_params(vp); + dump_program_params(ctx, vp); vpi=vp->Instructions; @@ -209,42 +240,39 @@ static void debug_vp(struct vertex_program *vp) } -void update_params(struct r300_vertex_program *vp) +void r300VertexProgUpdateParams(GLcontext *ctx, struct r300_vertex_program *vp) { int pi; struct vertex_program *mesa_vp=(void *)vp; + int dst_index; - vp->params.length=0; + _mesa_load_state_parameters(ctx, mesa_vp->Parameters); - /* Temporary solution */ + //debug_vp(ctx, mesa_vp); + dst_index=0; for(pi=0; pi < mesa_vp->Parameters->NumParameters; pi++){ switch(mesa_vp->Parameters->Parameters[pi].Type){ + case STATE: case NAMED_PARAMETER: //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name); case CONSTANT: - vp->params.body.f[pi*4+0]=mesa_vp->Parameters->Parameters[pi].Values[0]; - vp->params.body.f[pi*4+1]=mesa_vp->Parameters->Parameters[pi].Values[1]; - vp->params.body.f[pi*4+2]=mesa_vp->Parameters->Parameters[pi].Values[2]; - vp->params.body.f[pi*4+3]=mesa_vp->Parameters->Parameters[pi].Values[3]; - vp->params.length+=4; - break; - - case STATE: - fprintf(stderr, "State found! bailing out.\n"); - exit(0); - /* fetch state info */ - continue; + vp->params.body.f[dst_index++]=mesa_vp->Parameters->Parameters[pi].Values[0]; + vp->params.body.f[dst_index++]=mesa_vp->Parameters->Parameters[pi].Values[1]; + vp->params.body.f[dst_index++]=mesa_vp->Parameters->Parameters[pi].Values[2]; + vp->params.body.f[dst_index++]=mesa_vp->Parameters->Parameters[pi].Values[3]; break; + default: _mesa_problem(NULL, "Bad param type in %s", __FUNCTION__); } } + vp->params.length=dst_index; } -unsigned long translate_dst_mask(GLboolean *mask) +static unsigned long t_dst_mask(GLboolean *mask) { unsigned long flags=0; @@ -256,14 +284,14 @@ unsigned long translate_dst_mask(GLboolean *mask) return flags; } -unsigned long translate_dst_class(enum register_file file) +static unsigned long t_dst_class(enum register_file file) { switch(file){ case PROGRAM_TEMPORARY: - return R300_VPI_OUT_REG_CLASS_TEMPORARY; + return VSF_OUT_CLASS_TMP; case PROGRAM_OUTPUT: - return R300_VPI_OUT_REG_CLASS_RESULT; + return VSF_OUT_CLASS_RESULT; /* case PROGRAM_INPUT: case PROGRAM_LOCAL_PARAM: @@ -279,20 +307,21 @@ unsigned long translate_dst_class(enum register_file file) } } -unsigned long translate_src_class(enum register_file file) +static unsigned long t_src_class(enum register_file file) { switch(file){ case PROGRAM_TEMPORARY: - return R300_VPI_IN_REG_CLASS_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_STATE_VAR: - return R300_VPI_IN_REG_CLASS_PARAMETER; + return VSF_IN_CLASS_PARAM; /* case PROGRAM_OUTPUT: case PROGRAM_WRITE_ONLY: @@ -304,7 +333,7 @@ unsigned long translate_src_class(enum register_file file) } } -unsigned long translate_swizzle(GLubyte swizzle) +static unsigned long t_swizzle(GLubyte swizzle) { switch(swizzle){ case 0: return VSF_IN_COMPONENT_X; @@ -319,19 +348,52 @@ unsigned long translate_swizzle(GLubyte swizzle) exit(0); } } + +static unsigned long t_src_index(struct r300_vertex_program *vp, struct vp_src_register *src) +{ + int i; + int max_reg=-1; + + if(src->File == PROGRAM_INPUT){ + /* + switch(src->Index){ + case 0: return 0; + case 3: return 1; + + case 2: return 2; + case 8: return 8; + + default: printf("unknown input index %d\n", src->Index); exit(0); break; + }*/ + + 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; + + return vp->inputs[src->Index]; + }else{ + return src->Index; + } +} -unsigned long translate_src(struct vp_src_register *src) +static unsigned long t_src(struct r300_vertex_program *vp, struct vp_src_register *src) { - return MAKE_VSF_SOURCE(src->Index, - translate_swizzle(src->Swizzle[0]), - translate_swizzle(src->Swizzle[1]), - translate_swizzle(src->Swizzle[2]), - translate_swizzle(src->Swizzle[3]), - translate_src_class(src->File), + + return MAKE_VSF_SOURCE(t_src_index(vp, src), + t_swizzle(src->Swizzle[0]), + t_swizzle(src->Swizzle[1]), + t_swizzle(src->Swizzle[2]), + t_swizzle(src->Swizzle[3]), + t_src_class(src->File), src->Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); } -unsigned long translate_opcode(enum vp_opcode opcode) +static unsigned long t_opcode(enum vp_opcode opcode) { switch(opcode){ @@ -352,55 +414,105 @@ unsigned long translate_opcode(enum vp_opcode opcode) case VP_OPCODE_RSQ: return R300_VPI_OUT_OP_RSQ; case VP_OPCODE_SGE: return R300_VPI_OUT_OP_SGE; case VP_OPCODE_SLT: return R300_VPI_OUT_OP_SLT; - /* these ops need special handling */ - case VP_OPCODE_ABS: - case VP_OPCODE_ARL: - case VP_OPCODE_DP3: - case VP_OPCODE_DP4: - case VP_OPCODE_DPH: - case VP_OPCODE_FLR: - case VP_OPCODE_MOV: - case VP_OPCODE_SUB: - case VP_OPCODE_SWZ: - case VP_OPCODE_XPD: - case VP_OPCODE_RCC: - case VP_OPCODE_PRINT: - case VP_OPCODE_END: - fprintf(stderr, "%s should not be called with opcode %d", __FUNCTION__, opcode); - break; + case VP_OPCODE_DP4: return R300_VPI_OUT_OP_DOT; + default: - fprintf(stderr, "%s unknown opcode %d", __FUNCTION__, opcode); + fprintf(stderr, "%s: Should not be called with opcode %d!", __FUNCTION__, opcode); } exit(-1); return 0; } - + +static unsigned long op_operands(enum vp_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; +} + static void translate_program(struct r300_vertex_program *vp) { struct vertex_program *mesa_vp=(void *)vp; struct vp_instruction *vpi; - int inst_index=0; int operand_index, i; - int op_found; - update_params(vp); + VERTEX_SHADER_INSTRUCTION t2rs[1024]; + VERTEX_SHADER_INSTRUCTION *o_inst; + unsigned long operands; + vp->t2rs=0; vp->program.length=0; + vp->num_temporaries=mesa_vp->Base.NumTemporaries; + + for(i=0; i < VERT_ATTRIB_MAX; i++) + vp->inputs[i]=-1; - for(vpi=mesa_vp->Instructions; vpi->Opcode != VP_OPCODE_END; vpi++, inst_index++){ + o_inst=vp->program.body.i; + for(vpi=mesa_vp->Instructions; vpi->Opcode != VP_OPCODE_END; vpi++, o_inst++){ + + operands=op_operands(vpi->Opcode); + + /* these ops need special handling. + Ops that need temp vars should probably be given reg indexes starting at the end of tmp area. */ switch(vpi->Opcode){ - case VP_OPCODE_ABS: + case VP_OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, vpi->DstReg.Index, + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + o_inst->src1=t_src(vp, &vpi->SrcReg[0]); + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &vpi->SrcReg[0]), + SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ZERO, + t_src_class(vpi->SrcReg[0].File), VSF_FLAG_NONE); + + o_inst->src3=0; + goto next; + + case VP_OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO} + o_inst->op=MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, vpi->DstReg.Index, + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &vpi->SrcReg[0]), + t_swizzle(vpi->SrcReg[0].Swizzle[0]), + t_swizzle(vpi->SrcReg[0].Swizzle[1]), + t_swizzle(vpi->SrcReg[0].Swizzle[2]), + SWIZZLE_ZERO, + t_src_class(vpi->SrcReg[0].File), + vpi->SrcReg[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + + o_inst->src2=MAKE_VSF_SOURCE(t_src_index(vp, &vpi->SrcReg[1]), + t_swizzle(vpi->SrcReg[1].Swizzle[0]), + t_swizzle(vpi->SrcReg[1].Swizzle[1]), + t_swizzle(vpi->SrcReg[1].Swizzle[2]), + SWIZZLE_ZERO, + t_src_class(vpi->SrcReg[1].File), + vpi->SrcReg[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE); + + o_inst->src3=0; + goto next; + + case VP_OPCODE_ABS://MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W case VP_OPCODE_ARL: - case VP_OPCODE_DP3: - case VP_OPCODE_DP4: - case VP_OPCODE_DPH: - case VP_OPCODE_DST: + case VP_OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W} case VP_OPCODE_FLR: - case VP_OPCODE_MOV: - case VP_OPCODE_SUB: + /* 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 */ + + case VP_OPCODE_SUB://ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W case VP_OPCODE_SWZ: case VP_OPCODE_XPD: + /* ADD TMP 0.X Y Z PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} + MUL TMP 1.X Y Z W TMP 0{} {Z X Y ZERO} PARAM 1{} {Y Z X ZERO} + MAD RESULT 1.X Y Z W TMP 0{} {Y Z X ONE} PARAM 1{} {Z X Y ONE} TMP 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W*/ + case VP_OPCODE_RCC: case VP_OPCODE_PRINT: + //vp->num_temporaries++; fprintf(stderr, "Dont know how to handle op %d yet\n", vpi->Opcode); exit(-1); break; @@ -409,37 +521,27 @@ static void translate_program(struct r300_vertex_program *vp) default: break; } - vp->program.body.i[inst_index].op=MAKE_VSF_OP(translate_opcode(vpi->Opcode), vpi->DstReg.Index, - translate_dst_mask(vpi->DstReg.WriteMask), translate_dst_class(vpi->DstReg.File)); - - op_found=0; - for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++) - if(op_names[i].opcode == vpi->Opcode){ - op_found=1; - break; - } - if(!op_found){ - fprintf(stderr, "op %d not found in op_names\n", vpi->Opcode); - exit(-1); - } - - switch(op_names[i].ip){ + + o_inst->op=MAKE_VSF_OP(t_opcode(vpi->Opcode), vpi->DstReg.Index, + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + + switch(operands){ case 1: - vp->program.body.i[inst_index].src1=translate_src(&vpi->SrcReg[0]); - vp->program.body.i[inst_index].src2=0; - vp->program.body.i[inst_index].src3=0; + o_inst->src1=t_src(vp, &vpi->SrcReg[0]); + o_inst->src2=0; + o_inst->src3=0; break; case 2: - vp->program.body.i[inst_index].src1=translate_src(&vpi->SrcReg[0]); - vp->program.body.i[inst_index].src2=translate_src(&vpi->SrcReg[1]); - vp->program.body.i[inst_index].src3=0; + o_inst->src1=t_src(vp, &vpi->SrcReg[0]); + o_inst->src2=t_src(vp, &vpi->SrcReg[1]); + o_inst->src3=0; break; case 3: - vp->program.body.i[inst_index].src1=translate_src(&vpi->SrcReg[0]); - vp->program.body.i[inst_index].src2=translate_src(&vpi->SrcReg[1]); - vp->program.body.i[inst_index].src3=translate_src(&vpi->SrcReg[2]); + o_inst->src1=t_src(vp, &vpi->SrcReg[0]); + o_inst->src2=t_src(vp, &vpi->SrcReg[1]); + o_inst->src3=t_src(vp, &vpi->SrcReg[2]); break; default: @@ -447,14 +549,38 @@ static void translate_program(struct r300_vertex_program *vp) exit(-1); break; } + next: + + /* If instruction writes to result and one of the inputs is tmp, we move it at the end of program */ + if(vpi->DstReg.File == PROGRAM_OUTPUT){ + for(operand_index=0; operand_index < operands; operand_index++) + if(vpi->SrcReg[operand_index].File == PROGRAM_TEMPORARY){ + t2rs[vp->t2rs++]=*o_inst; + o_inst--; /* FIXME */ + break; + } + } + } - vp->program.length=inst_index*4; - + /* Put "tmp to result" instructions in */ + for(i=0; i < vp->t2rs; i++, o_inst++) + *o_inst=t2rs[i]; + + vp->program.length=(o_inst - vp->program.body.i) * 4; + vp->translated=GL_TRUE; } static void r300BindProgram(GLcontext *ctx, GLenum target, struct program *prog) { + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct r300_vertex_program *vp=(void *)prog; +#if 0 fprintf(stderr, "r300BindProgram\n"); +#endif + if(rmesa->current_vp == vp) + return ; + + rmesa->current_vp = vp; } /* Mesa doesnt seem to have prototype for this */ @@ -464,34 +590,26 @@ _mesa_init_ati_fragment_shader( GLcontext *ctx, struct ati_fragment_shader *prog static struct program *r300NewProgram(GLcontext *ctx, GLenum target, GLuint id) { - r300ContextPtr rmesa = R300_CONTEXT(ctx); struct r300_vertex_program *vp; struct fragment_program *fp; struct ati_fragment_shader *afs; - +#if 0 fprintf(stderr, "r300NewProgram, target=%d, id=%d\n", target, id); - +#endif switch(target){ case GL_VERTEX_PROGRAM_ARB: - fprintf(stderr, "vertex prog\n"); vp=CALLOC_STRUCT(r300_vertex_program); - - /* note that vp points to mesa_program since its first on the struct - */ return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id); case GL_FRAGMENT_PROGRAM_ARB: - fprintf(stderr, "fragment prog\n"); fp=CALLOC_STRUCT(fragment_program); return _mesa_init_fragment_program(ctx, fp, target, id); case GL_FRAGMENT_PROGRAM_NV: - fprintf(stderr, "nv fragment prog\n"); fp=CALLOC_STRUCT(fragment_program); return _mesa_init_fragment_program(ctx, fp, target, id); case GL_FRAGMENT_SHADER_ATI: - fprintf(stderr, "ati fragment prog\n"); afs=CALLOC_STRUCT(ati_fragment_shader); return _mesa_init_ati_fragment_shader(ctx, afs, target, id); } @@ -502,9 +620,14 @@ static struct program *r300NewProgram(GLcontext *ctx, GLenum target, GLuint id) static void r300DeleteProgram(GLcontext *ctx, struct program *prog) { + r300ContextPtr rmesa = R300_CONTEXT(ctx); + struct r300_vertex_program *vp=(void *)prog; +#if 0 fprintf(stderr, "r300DeleteProgram\n"); +#endif + if(rmesa->current_vp == vp) + rmesa->current_vp = NULL; - /* check that not active */ _mesa_delete_program(ctx, prog); } @@ -515,38 +638,44 @@ static void r300ProgramStringNotify(GLcontext *ctx, GLenum target, struct program *prog) { struct r300_vertex_program *vp=(void *)prog; - +#if 0 fprintf(stderr, "r300ProgramStringNotify\n"); - /* XXX: There is still something wrong as mesa doesnt call r300IsProgramNative at all */ - (void)r300IsProgramNative(ctx, target, prog); - +#endif + switch(target) { case GL_VERTEX_PROGRAM_ARB: vp->translated=GL_FALSE; break; } + /* XXX: There is still something wrong as mesa doesnt call r300IsProgramNative at all */ + (void)r300IsProgramNative(ctx, target, prog); + } static GLboolean r300IsProgramNative(GLcontext *ctx, GLenum target, struct program *prog) { + struct r300_vertex_program *vp=(void *)prog; + r300ContextPtr rmesa = R300_CONTEXT(ctx); +#if 0 fprintf(stderr, "r300IsProgramNative\n"); //exit(0); - debug_vp((struct vertex_program *)prog); - + debug_vp(ctx, vp); +#endif + translate_program(vp); + //r300VertexProgUpdateParams(ctx, vp); + return 1; } /* This is misnamed and shouldnt be here since fragment programs use these functions too */ void r300InitVertexProgFuncs(struct dd_function_table *functions) { -#if 1 functions->NewProgram=r300NewProgram; functions->BindProgram=r300BindProgram; functions->DeleteProgram=r300DeleteProgram; functions->ProgramStringNotify=r300ProgramStringNotify; functions->IsProgramNative=r300IsProgramNative; -#endif } -- 2.30.2