📄 r300_vertprog.c
字号:
} if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC1)) { vp->outputs[VERT_RESULT_BFC1] = vp->outputs[VERT_RESULT_COL0] + 3; cur_reg = vp->outputs[VERT_RESULT_BFC1] + 1; }#if 0 if (vp->key.OutputsWritten & (1 << VERT_RESULT_FOGC)) { vp->outputs[VERT_RESULT_FOGC] = cur_reg++; }#endif for (i = VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++) { if (vp->key.OutputsWritten & (1 << i)) { vp->outputs[i] = cur_reg++; } }}static void r300TranslateVertexShader(struct r300_vertex_program *vp, struct prog_instruction *vpi){ int i; GLuint *inst; unsigned long num_operands; /* Initial value should be last tmp reg that hw supports. Strangely enough r300 doesnt mind even though these would be out of range. Smart enough to realize that it doesnt need it? */ int u_temp_i = VSF_MAX_FRAGMENT_TEMPS - 1; struct prog_src_register src[3]; vp->pos_end = 0; /* Not supported yet */ vp->program.length = 0; /*vp->num_temporaries=mesa_vp->Base.NumTemporaries; */ vp->translated = GL_TRUE; vp->native = GL_TRUE; t_inputs_outputs(vp); for (inst = vp->program.body.i; vpi->Opcode != OPCODE_END; vpi++, inst += 4) { FREE_TEMPS(); if (!valid_dst(vp, &vpi->DstReg)) { /* redirect result to unused temp */ vpi->DstReg.File = PROGRAM_TEMPORARY; vpi->DstReg.Index = u_temp_i; } num_operands = _mesa_num_inst_src_regs(vpi->Opcode); /* copy the sources (src) from mesa into a local variable... is this needed? */ for (i = 0; i < num_operands; i++) { src[i] = vpi->SrcReg[i]; } if (num_operands == 3) { /* TODO: scalars */ if (CMP_SRCS(src[1], src[2]) || CMP_SRCS(src[0], src[2])) { inst[0] = PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, u_temp_i, VSF_FLAG_ALL, PVS_DST_REG_TEMPORARY); inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &src[2]), SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2]. RelAddr << 4); inst[2] = __CONST(2, SWIZZLE_ZERO); inst[3] = __CONST(2, SWIZZLE_ZERO); inst += 4; src[2].File = PROGRAM_TEMPORARY; src[2].Index = u_temp_i; src[2].RelAddr = 0; u_temp_i--; } } if (num_operands >= 2) { if (CMP_SRCS(src[1], src[0])) { inst[0] = PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, u_temp_i, VSF_FLAG_ALL, PVS_DST_REG_TEMPORARY); inst[1] = PVS_SRC_OPERAND(t_src_index(vp, &src[0]), SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0]. RelAddr << 4); inst[2] = __CONST(0, SWIZZLE_ZERO); inst[3] = __CONST(0, SWIZZLE_ZERO); inst += 4; src[0].File = PROGRAM_TEMPORARY; src[0].Index = u_temp_i; src[0].RelAddr = 0; u_temp_i--; } } switch (vpi->Opcode) { case OPCODE_ABS: inst = r300TranslateOpcodeABS(vp, vpi, inst, src); break; case OPCODE_ADD: inst = r300TranslateOpcodeADD(vp, vpi, inst, src); break; case OPCODE_ARL: inst = r300TranslateOpcodeARL(vp, vpi, inst, src); break; case OPCODE_DP3: inst = r300TranslateOpcodeDP3(vp, vpi, inst, src); break; case OPCODE_DP4: inst = r300TranslateOpcodeDP4(vp, vpi, inst, src); break; case OPCODE_DPH: inst = r300TranslateOpcodeDPH(vp, vpi, inst, src); break; case OPCODE_DST: inst = r300TranslateOpcodeDST(vp, vpi, inst, src); break; case OPCODE_EX2: inst = r300TranslateOpcodeEX2(vp, vpi, inst, src); break; case OPCODE_EXP: inst = r300TranslateOpcodeEXP(vp, vpi, inst, src); break; case OPCODE_FLR: inst = r300TranslateOpcodeFLR(vp, vpi, inst, src, /* FIXME */ &u_temp_i); break; case OPCODE_FRC: inst = r300TranslateOpcodeFRC(vp, vpi, inst, src); break; case OPCODE_LG2: inst = r300TranslateOpcodeLG2(vp, vpi, inst, src); break; case OPCODE_LIT: inst = r300TranslateOpcodeLIT(vp, vpi, inst, src); break; case OPCODE_LOG: inst = r300TranslateOpcodeLOG(vp, vpi, inst, src); break; case OPCODE_MAD: inst = r300TranslateOpcodeMAD(vp, vpi, inst, src); break; case OPCODE_MAX: inst = r300TranslateOpcodeMAX(vp, vpi, inst, src); break; case OPCODE_MIN: inst = r300TranslateOpcodeMIN(vp, vpi, inst, src); break; case OPCODE_MOV: inst = r300TranslateOpcodeMOV(vp, vpi, inst, src); break; case OPCODE_MUL: inst = r300TranslateOpcodeMUL(vp, vpi, inst, src); break; case OPCODE_POW: inst = r300TranslateOpcodePOW(vp, vpi, inst, src); break; case OPCODE_RCP: inst = r300TranslateOpcodeRCP(vp, vpi, inst, src); break; case OPCODE_RSQ: inst = r300TranslateOpcodeRSQ(vp, vpi, inst, src); break; case OPCODE_SGE: inst = r300TranslateOpcodeSGE(vp, vpi, inst, src); break; case OPCODE_SLT: inst = r300TranslateOpcodeSLT(vp, vpi, inst, src); break; case OPCODE_SUB: inst = r300TranslateOpcodeSUB(vp, vpi, inst, src); break; case OPCODE_SWZ: inst = r300TranslateOpcodeSWZ(vp, vpi, inst, src); break; case OPCODE_XPD: inst = r300TranslateOpcodeXPD(vp, vpi, inst, src, /* FIXME */ &u_temp_i); break; default: assert(0); break; } } /* Some outputs may be artificially added, to match the inputs of the fragment program. Blank the outputs here. */ for (i = 0; i < VERT_RESULT_MAX; i++) { if (vp->key.OutputsAdded & (1 << i)) { inst[0] = PVS_OP_DST_OPERAND(VE_ADD, GL_FALSE, GL_FALSE, vp->outputs[i], VSF_FLAG_ALL, PVS_DST_REG_OUT); inst[1] = __CONST(0, SWIZZLE_ZERO); inst[2] = __CONST(0, SWIZZLE_ZERO); inst[3] = __CONST(0, SWIZZLE_ZERO); inst += 4; } } vp->program.length = (inst - vp->program.body.i); if (vp->program.length >= VSF_MAX_FRAGMENT_LENGTH) { vp->program.length = 0; vp->native = GL_FALSE; }#if 0 fprintf(stderr, "hw program:\n"); for (i = 0; i < vp->program.length; i++) fprintf(stderr, "%08x\n", vp->program.body.d[i]);#endif}/* DP4 version seems to trigger some hw peculiarity *///#define PREFER_DP4static void position_invariant(struct gl_program *prog){ struct prog_instruction *vpi; struct gl_program_parameter_list *paramList; int i; gl_state_index tokens[STATE_LENGTH] = { STATE_MVP_MATRIX, 0, 0, 0, 0 }; /* tokens[4] = matrix modifier */#ifdef PREFER_DP4 tokens[4] = 0; /* not transposed or inverted */#else tokens[4] = STATE_MATRIX_TRANSPOSE;#endif paramList = prog->Parameters; vpi = _mesa_alloc_instructions(prog->NumInstructions + 4); _mesa_init_instructions(vpi, prog->NumInstructions + 4); for (i = 0; i < 4; i++) { GLint idx; tokens[2] = tokens[3] = i; /* matrix row[i]..row[i] */ idx = _mesa_add_state_reference(paramList, tokens);#ifdef PREFER_DP4 vpi[i].Opcode = OPCODE_DP4; vpi[i].StringPos = 0; vpi[i].Data = 0; vpi[i].DstReg.File = PROGRAM_OUTPUT; vpi[i].DstReg.Index = VERT_RESULT_HPOS; vpi[i].DstReg.WriteMask = 1 << i; vpi[i].DstReg.CondMask = COND_TR; vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; vpi[i].SrcReg[0].Index = idx; vpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW; vpi[i].SrcReg[1].File = PROGRAM_INPUT; vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; vpi[i].SrcReg[1].Swizzle = SWIZZLE_XYZW;#else if (i == 0) vpi[i].Opcode = OPCODE_MUL; else vpi[i].Opcode = OPCODE_MAD; vpi[i].StringPos = 0; vpi[i].Data = 0; if (i == 3) vpi[i].DstReg.File = PROGRAM_OUTPUT; else vpi[i].DstReg.File = PROGRAM_TEMPORARY; vpi[i].DstReg.Index = 0; vpi[i].DstReg.WriteMask = 0xf; vpi[i].DstReg.CondMask = COND_TR; vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; vpi[i].SrcReg[0].Index = idx; vpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW; vpi[i].SrcReg[1].File = PROGRAM_INPUT; vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i); if (i > 0) { vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY; vpi[i].SrcReg[2].Index = 0; vpi[i].SrcReg[2].Swizzle = SWIZZLE_XYZW; }#endif } _mesa_copy_instructions(&vpi[i], prog->Instructions, prog->NumInstructions); free(prog->Instructions); prog->Instructions = vpi; prog->NumInstructions += 4; vpi = &prog->Instructions[prog->NumInstructions - 1]; assert(vpi->Opcode == OPCODE_END);}static void insert_wpos(struct r300_vertex_program *vp, struct gl_program *prog, GLuint temp_index){ struct prog_instruction *vpi; struct prog_instruction *vpi_insert; int i = 0; vpi = _mesa_alloc_instructions(prog->NumInstructions + 2); _mesa_init_instructions(vpi, prog->NumInstructions + 2); /* all but END */ _mesa_copy_instructions(vpi, prog->Instructions, prog->NumInstructions - 1); /* END */ _mesa_copy_instructions(&vpi[prog->NumInstructions + 1], &prog->Instructions[prog->NumInstructions - 1], 1); vpi_insert = &vpi[prog->NumInstructions - 1]; vpi_insert[i].Opcode = OPCODE_MOV; vpi_insert[i].DstReg.File = PROGRAM_OUTPUT; vpi_insert[i].DstReg.Index = VERT_RESULT_HPOS; vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW; vpi_insert[i].DstReg.CondMask = COND_TR; vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; vpi_insert[i].SrcReg[0].Index = temp_index; vpi_insert[i].SrcReg[0].Swizzle = SWIZZLE_XYZW; i++; vpi_insert[i].Opcode = OPCODE_MOV; vpi_insert[i].DstReg.File = PROGRAM_OUTPUT; vpi_insert[i].DstReg.Index = VERT_RESULT_TEX0 + vp->wpos_idx; vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW; vpi_insert[i].DstReg.CondMask = COND_TR; vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; vpi_insert[i].SrcReg[0].Index = temp_index; vpi_insert[i].SrcReg[0].Swizzle = SWIZZLE_XYZW; i++; free(prog->Instructions); prog->Instructions = vpi; prog->NumInstructions += i; vpi = &prog->Instructions[prog->NumInstructions - 1]; assert(vpi->Opcode == OPCODE_END);}static void pos_as_texcoord(struct r300_vertex_program *vp, struct gl_program *prog){ struct prog_instruction *vpi; GLuint tempregi = prog->NumTemporaries; /* should do something else if no temps left... */ prog->NumTemporaries++; for (vpi = prog->Instructions; vpi->Opcode != OPCODE_END; vpi++) { if (vpi->DstReg.File == PROGRAM_OUTPUT && vpi->DstReg.Index == VERT_RESULT_HPOS) { vpi->DstReg.File = PROGRAM_TEMPORARY; vpi->DstReg.Index = tempregi; } } insert_wpos(vp, prog, tempregi);}static struct r300_vertex_program *build_program(struct r300_vertex_program_key *wanted_key, struct gl_vertex_program *mesa_vp, GLint wpos_idx){ struct r300_vertex_program *vp; vp = _mesa_calloc(sizeof(*vp)); _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key)); vp->wpos_idx = wpos_idx; if (mesa_vp->IsPositionInvariant) { position_invariant(&mesa_vp->Base); } if (wpos_idx > -1) { pos_as_texcoord(vp, &mesa_vp->Base); } assert(mesa_vp->Base.NumInstructions); vp->num_temporaries = mesa_vp->Base.NumTemporaries; r300TranslateVertexShader(vp, mesa_vp->Base.Instructions); return vp;}static void add_outputs(struct r300_vertex_program_key *key, GLint vert){ if (key->OutputsWritten & (1 << vert)) return; key->OutputsWritten |= 1 << vert; key->OutputsAdded |= 1 << vert;}void r300SelectVertexShader(r300ContextPtr r300){ GLcontext *ctx = ctx = r300->radeon.glCtx; GLuint InputsRead; struct r300_vertex_program_key wanted_key = { 0 }; GLint i; struct r300_vertex_program_cont *vpc; struct r300_vertex_program *vp; GLint wpos_idx; vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; wanted_key.InputsRead = vpc->mesa_program.Base.InputsRead; wanted_key.OutputsWritten = vpc->mesa_program.Base.OutputsWritten; InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; wpos_idx = -1; if (InputsRead & FRAG_BIT_WPOS) { for (i = 0; i < ctx->Const.MaxTextureUnits; i++) if (!(InputsRead & (FRAG_BIT_TEX0 << i))) break; if (i == ctx->Const.MaxTextureUnits) { fprintf(stderr, "\tno free texcoord found\n"); _mesa_exit(-1); } wanted_key.OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i); wpos_idx = i; } add_outputs(&wanted_key, VERT_RESULT_HPOS); if (InputsRead & FRAG_BIT_COL0) { add_outputs(&wanted_key, VERT_RESULT_COL0); } if (InputsRead & FRAG_BIT_COL1) { add_outputs(&wanted_key, VERT_RESULT_COL1); } for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { if (InputsRead & (FRAG_BIT_TEX0 << i)) { add_outputs(&wanted_key, VERT_RESULT_TEX0 + i); } } if (vpc->mesa_program.IsPositionInvariant) { /* we wan't position don't we ? */ wanted_key.InputsRead |= (1 << VERT_ATTRIB_POS); } for (vp = vpc->progs; vp; vp = vp->next) if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key)) == 0) { r300->selected_vp = vp; return; } //_mesa_print_program(&vpc->mesa_program.Base); vp = build_program(&wanted_key, &vpc->mesa_program, wpos_idx); vp->next = vpc->progs; vpc->progs = vp; r300->selected_vp = vp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -