void CCompiler::Compile(CParser *pParser) { struct nvfx_src tmp; struct nvfx_relocation reloc; std::vector<u32> insns_pos; std::list<struct nvfx_relocation> label_reloc; int i,nICount = pParser->GetInstructionCount(); struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE,0)); struct nvfx_insn tmp_insn,*insns = pParser->GetInstructions(); Prepare(pParser); for(i=0;i<nICount;i++) { /* u32 idx = (u32)insns_pos.size(); */ struct nvfx_insn *insn = &insns[i]; insns_pos.push_back(m_nInstructions); switch(insn->op) { case OPCODE_NOP: tmp_insn = arith(0,none.reg,0,none,none,none); emit_insn(gen_op(NOP,VEC),&tmp_insn); break; case OPCODE_ABS: tmp_insn = arith_ctor(insn,insn->dst,abs(insn->src[0]),none,none); emit_insn(gen_op(MOV,VEC),&tmp_insn); break; case OPCODE_ADD: emit_insn(gen_op(ADD,VEC),insn); break; case OPCODE_ARA: break; case OPCODE_ARL: break; case OPCODE_ARR: break; case OPCODE_BRA: reloc.location = m_nInstructions; reloc.target = insn->dst.index; label_reloc.push_back(reloc); tmp_insn = arith(0,none.reg,0,none,none,none); emit_insn(gen_op(BRA,SCA),&tmp_insn); break; case OPCODE_CAL: reloc.location = m_nInstructions; reloc.target = insn->dst.index; label_reloc.push_back(reloc); tmp_insn = arith(0,none.reg,0,none,none,none); emit_insn(gen_op(CAL,SCA),&tmp_insn); break; case OPCODE_COS: emit_insn(gen_op(COS,SCA),insn); break; case OPCODE_DP3: emit_insn(gen_op(DP3,VEC),insn); break; case OPCODE_DP4: emit_insn(gen_op(DP4,VEC),insn); break; case OPCODE_DPH: emit_insn(gen_op(DPH,VEC),insn); break; case OPCODE_DST: emit_insn(gen_op(DST,VEC),insn); break; case OPCODE_EX2: emit_insn(gen_op(EX2,SCA),insn); break; case OPCODE_EXP: emit_insn(gen_op(EXP,SCA),insn); break; case OPCODE_FLR: emit_insn(gen_op(FLR,VEC),insn); break; case OPCODE_FRC: emit_insn(gen_op(FRC,VEC),insn); break; case OPCODE_LG2: emit_insn(gen_op(LG2,SCA),insn); break; case OPCODE_LIT: emit_insn(gen_op(LIT,SCA),insn); break; case OPCODE_LOG: emit_insn(gen_op(LOG,SCA),insn); break; case OPCODE_MAD: emit_insn(gen_op(MAD,VEC),insn); break; case OPCODE_MAX: emit_insn(gen_op(MAX,VEC),insn); break; case OPCODE_MIN: emit_insn(gen_op(MIN,VEC),insn); break; case OPCODE_MOV: emit_insn(gen_op(MOV,VEC),insn); break; case OPCODE_MUL: emit_insn(gen_op(MUL,VEC),insn); break; case OPCODE_POW: tmp = nvfx_src(temp()); tmp_insn = arith(0, tmp.reg, NVFX_VP_MASK_X, none, none, insn->src[0]); emit_insn(gen_op(LG2,SCA),&tmp_insn); tmp_insn = arith(0, tmp.reg, NVFX_VP_MASK_X, swz(tmp, X, X, X, X), insn->src[1], none); emit_insn(gen_op(MUL,VEC),&tmp_insn); tmp_insn = arith_ctor(insn, insn->dst, none, none, swz(tmp, X, X, X, X)); emit_insn(gen_op(EX2,SCA),&tmp_insn); break; case OPCODE_RCC: emit_insn(gen_op(RCC,SCA),insn); break; case OPCODE_RCP: emit_insn(gen_op(RCP,SCA),insn); break; case OPCODE_RSQ: emit_insn(gen_op(RSQ,SCA),insn); break; case OPCODE_SEQ: emit_insn(gen_op(SEQ,VEC),insn); break; case OPCODE_SFL: emit_insn(gen_op(SFL,VEC),insn); break; case OPCODE_SGE: emit_insn(gen_op(SGE,VEC),insn); break; case OPCODE_SGT: emit_insn(gen_op(SGT,VEC),insn); break; case OPCODE_SIN: emit_insn(gen_op(SIN,SCA),insn); break; case OPCODE_SLE: emit_insn(gen_op(SLE,VEC),insn); break; case OPCODE_SLT: emit_insn(gen_op(SLT,VEC),insn); break; case OPCODE_SNE: emit_insn(gen_op(SNE,VEC),insn); break; case OPCODE_SSG: emit_insn(gen_op(SSG,VEC),insn); break; case OPCODE_STR: emit_insn(gen_op(STR,VEC),insn); break; case OPCODE_SUB: tmp_insn = arith_ctor(insn,insn->dst,insn->src[0],none,neg(insn->src[2])); emit_insn(gen_op(ADD,VEC),&tmp_insn); break; case OPCODE_END: if(m_nInstructions) m_pInstructions[m_nCurInstruction].data[3] |= NVFX_VP_INST_LAST; else { tmp_insn = arith(0,none.reg,0,none,none,none); emit_insn(gen_op(NOP,VEC),&tmp_insn); m_pInstructions[m_nCurInstruction].data[3] |= NVFX_VP_INST_LAST; } break; } release_temps(); } for(std::list<struct nvfx_relocation>::iterator it = label_reloc.begin();it!=label_reloc.end();it++) { struct nvfx_relocation hw_reloc; hw_reloc.location = it->location; hw_reloc.target = insns_pos[it->target]; m_lBranchRelocation.push_back(hw_reloc); } }
static void build_texture_transform( struct tnl_program *p ) { GLuint i, j; for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i))) continue; if (p->state->unit[i].texgen_enabled || p->state->unit[i].texmat_enabled) { GLuint texmat_enabled = p->state->unit[i].texmat_enabled; struct ureg out = register_output(p, VERT_RESULT_TEX0 + i); struct ureg out_texgen = undef; if (p->state->unit[i].texgen_enabled) { GLuint copy_mask = 0; GLuint sphere_mask = 0; GLuint reflect_mask = 0; GLuint normal_mask = 0; GLuint modes[4]; if (texmat_enabled) out_texgen = get_temp(p); else out_texgen = out; modes[0] = p->state->unit[i].texgen_mode0; modes[1] = p->state->unit[i].texgen_mode1; modes[2] = p->state->unit[i].texgen_mode2; modes[3] = p->state->unit[i].texgen_mode3; for (j = 0; j < 4; j++) { switch (modes[j]) { case TXG_OBJ_LINEAR: { struct ureg obj = register_input(p, VERT_ATTRIB_POS); struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_OBJECT_S + j); emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, obj, plane ); break; } case TXG_EYE_LINEAR: { struct ureg eye = get_eye_position(p); struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_EYE_S + j); emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, eye, plane ); break; } case TXG_SPHERE_MAP: sphere_mask |= WRITEMASK_X << j; break; case TXG_REFLECTION_MAP: reflect_mask |= WRITEMASK_X << j; break; case TXG_NORMAL_MAP: normal_mask |= WRITEMASK_X << j; break; case TXG_NONE: copy_mask |= WRITEMASK_X << j; } } if (sphere_mask) { build_sphere_texgen(p, out_texgen, sphere_mask); } if (reflect_mask) { build_reflect_texgen(p, out_texgen, reflect_mask); } if (normal_mask) { struct ureg normal = get_transformed_normal(p); emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal ); } if (copy_mask) { struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i); emit_op1(p, OPCODE_MOV, out_texgen, copy_mask, in ); } } if (texmat_enabled) { struct ureg texmat[4]; struct ureg in = (!is_undef(out_texgen) ? out_texgen : register_input(p, VERT_ATTRIB_TEX0+i)); if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, 0, texmat ); emit_matrix_transform_vec4( p, out, texmat, in ); } else { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, STATE_MATRIX_TRANSPOSE, texmat ); emit_transpose_matrix_transform_vec4( p, out, texmat, in ); } } release_temps(p); } else { emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i); } } }
/* Need to add some addtional parameters to allow lighting in object * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye * space lighting. */ static void build_lighting( struct tnl_program *p ) { const GLboolean twoside = p->state->light_twoside; const GLboolean separate = p->state->separate_specular; GLuint nr_lights = 0, count = 0; struct ureg normal = get_eye_normal(p); struct ureg lit = get_temp(p); struct ureg dots = get_temp(p); struct ureg _col0 = undef, _col1 = undef; struct ureg _bfc0 = undef, _bfc1 = undef; GLuint i; for (i = 0; i < MAX_LIGHTS; i++) if (p->state->unit[i].light_enabled) nr_lights++; set_material_flags(p); { struct ureg shininess = get_material(p, 0, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X)); release_temp(p, shininess); _col0 = make_temp(p, get_scenecolor(p, 0)); if (separate) _col1 = make_temp(p, get_identity_param(p)); else _col1 = _col0; } if (twoside) { struct ureg shininess = get_material(p, 1, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z, ureg_negate(swizzle1(shininess,X))); release_temp(p, shininess); _bfc0 = make_temp(p, get_scenecolor(p, 1)); if (separate) _bfc1 = make_temp(p, get_identity_param(p)); else _bfc1 = _bfc0; } /* If no lights, still need to emit the scenecolor. */ /* KW: changed to do this always - v1.17 "Fix lighting alpha result"? */ if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) { struct ureg res0 = register_output( p, VERT_RESULT_COL0 ); emit_op1(p, OPCODE_MOV, res0, 0, _col0); if (twoside) { struct ureg res0 = register_output( p, VERT_RESULT_BFC0 ); emit_op1(p, OPCODE_MOV, res0, 0, _bfc0); } } if (separate && (p->state->fragprog_inputs_read & FRAG_BIT_COL1)) { struct ureg res1 = register_output( p, VERT_RESULT_COL1 ); emit_op1(p, OPCODE_MOV, res1, 0, _col1); if (twoside) { struct ureg res1 = register_output( p, VERT_RESULT_BFC1 ); emit_op1(p, OPCODE_MOV, res1, 0, _bfc1); } } if (nr_lights == 0) { release_temps(p); return; } for (i = 0; i < MAX_LIGHTS; i++) { if (p->state->unit[i].light_enabled) { struct ureg half = undef; struct ureg att = undef, VPpli = undef; count++; if (p->state->unit[i].light_eyepos3_is_zero) { /* Can used precomputed constants in this case. * Attenuation never applies to infinite lights. */ VPpli = register_param3(p, STATE_LIGHT, i, STATE_POSITION_NORMALIZED); if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); half = get_temp(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); emit_normalize_vec3(p, half, half); } else { half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR); } } else { struct ureg Ppli = register_param3(p, STATE_LIGHT, i, STATE_POSITION); struct ureg V = get_eye_position(p); struct ureg dist = get_temp(p); VPpli = get_temp(p); half = get_temp(p); /* Calulate VPpli vector */ emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); /* Normalize VPpli. The dist value also used in * attenuation below. */ emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli); emit_op1(p, OPCODE_RSQ, dist, 0, dist); emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist); /* Calculate attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180 || p->state->unit[i].light_attenuated) { att = calculate_light_attenuation(p, i, VPpli, dist); } /* Calculate viewer direction, or use infinite viewer: */ if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); } else { struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir); } emit_normalize_vec3(p, half, half); release_temp(p, dist); } /* Calculate dot products: */ emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli); emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half); /* Front face lighting: */ { struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; emit_op1(p, OPCODE_LIT, lit, 0, dots); if (!is_undef(att)) emit_op2(p, OPCODE_MUL, lit, 0, lit, att); mask0 = 0; mask1 = 0; res0 = _col0; res1 = _col1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res0 = register_output( p, VERT_RESULT_COL0 ); if (p->state->fragprog_inputs_read & FRAG_BIT_COL1) res1 = register_output( p, VERT_RESULT_COL1 ); } else { mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res1 = register_output( p, VERT_RESULT_COL0 ); } } emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0); emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } /* Back face lighting: */ if (twoside) { struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; emit_op1(p, OPCODE_LIT, lit, 0, ureg_negate(swizzle(dots,X,Y,W,Z))); if (!is_undef(att)) emit_op2(p, OPCODE_MUL, lit, 0, lit, att); mask0 = 0; mask1 = 0; res0 = _bfc0; res1 = _bfc1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res0 = register_output( p, VERT_RESULT_BFC0 ); if (p->state->fragprog_inputs_read & FRAG_BIT_COL1) res1 = register_output( p, VERT_RESULT_BFC1 ); } else { mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res1 = register_output( p, VERT_RESULT_BFC0 ); } } emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0); emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } release_temp(p, half); release_temp(p, VPpli); release_temp(p, att); } } release_temps( p ); }
/* Need to add some addtional parameters to allow lighting in object * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye * space lighting. */ static void build_lighting( struct tnl_program *p ) { const GLboolean twoside = p->state->light_twoside; const GLboolean separate = p->state->separate_specular; GLuint nr_lights = 0, count = 0; struct ureg normal = get_transformed_normal(p); struct ureg lit = get_temp(p); struct ureg dots = get_temp(p); struct ureg _col0 = undef, _col1 = undef; struct ureg _bfc0 = undef, _bfc1 = undef; GLuint i; /* * NOTE: * dots.x = dot(normal, VPpli) * dots.y = dot(normal, halfAngle) * dots.z = back.shininess * dots.w = front.shininess */ for (i = 0; i < MAX_LIGHTS; i++) if (p->state->unit[i].light_enabled) nr_lights++; set_material_flags(p); { if (!p->state->material_shininess_is_zero) { struct ureg shininess = get_material(p, 0, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X)); release_temp(p, shininess); } _col0 = make_temp(p, get_scenecolor(p, 0)); if (separate) _col1 = make_temp(p, get_identity_param(p)); else _col1 = _col0; } if (twoside) { if (!p->state->material_shininess_is_zero) { /* Note that we negate the back-face specular exponent here. * The negation will be un-done later in the back-face code below. */ struct ureg shininess = get_material(p, 1, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z, negate(swizzle1(shininess,X))); release_temp(p, shininess); } _bfc0 = make_temp(p, get_scenecolor(p, 1)); if (separate) _bfc1 = make_temp(p, get_identity_param(p)); else _bfc1 = _bfc0; } /* If no lights, still need to emit the scenecolor. */ { struct ureg res0 = register_output( p, VERT_RESULT_COL0 ); emit_op1(p, OPCODE_MOV, res0, 0, _col0); } if (separate) { struct ureg res1 = register_output( p, VERT_RESULT_COL1 ); emit_op1(p, OPCODE_MOV, res1, 0, _col1); } if (twoside) { struct ureg res0 = register_output( p, VERT_RESULT_BFC0 ); emit_op1(p, OPCODE_MOV, res0, 0, _bfc0); } if (twoside && separate) { struct ureg res1 = register_output( p, VERT_RESULT_BFC1 ); emit_op1(p, OPCODE_MOV, res1, 0, _bfc1); } if (nr_lights == 0) { release_temps(p); return; } for (i = 0; i < MAX_LIGHTS; i++) { if (p->state->unit[i].light_enabled) { struct ureg half = undef; struct ureg att = undef, VPpli = undef; count++; if (p->state->unit[i].light_eyepos3_is_zero) { /* Can used precomputed constants in this case. * Attenuation never applies to infinite lights. */ VPpli = register_param3(p, STATE_INTERNAL, STATE_LIGHT_POSITION_NORMALIZED, i); if (!p->state->material_shininess_is_zero) { if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); half = get_temp(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); emit_normalize_vec3(p, half, half); } else { half = register_param3(p, STATE_INTERNAL, STATE_LIGHT_HALF_VECTOR, i); } } } else { struct ureg Ppli = register_param3(p, STATE_INTERNAL, STATE_LIGHT_POSITION, i); struct ureg V = get_eye_position(p); struct ureg dist = get_temp(p); VPpli = get_temp(p); /* Calculate VPpli vector */ emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); /* Normalize VPpli. The dist value also used in * attenuation below. */ emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli); emit_op1(p, OPCODE_RSQ, dist, 0, dist); emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist); /* Calculate attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180 || p->state->unit[i].light_attenuated) { att = calculate_light_attenuation(p, i, VPpli, dist); } /* Calculate viewer direction, or use infinite viewer: */ if (!p->state->material_shininess_is_zero) { half = get_temp(p); if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); } else { struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir); } emit_normalize_vec3(p, half, half); } release_temp(p, dist); } /* Calculate dot products: */ if (p->state->material_shininess_is_zero) { emit_op2(p, OPCODE_DP3, dots, 0, normal, VPpli); } else { emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli); emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half); } /* Front face lighting: */ { struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; res0 = register_output( p, VERT_RESULT_COL0 ); res1 = register_output( p, VERT_RESULT_COL1 ); } else { mask0 = 0; mask1 = WRITEMASK_XYZ; res0 = _col0; res1 = register_output( p, VERT_RESULT_COL0 ); } } else { mask0 = 0; mask1 = 0; res0 = _col0; res1 = _col1; } if (!is_undef(att)) { /* light is attenuated by distance */ emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_MUL, lit, 0, lit, att); emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0); } else if (!p->state->material_shininess_is_zero) { /* there's a non-zero specular term */ emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0); } else { /* no attenutation, no specular */ emit_degenerate_lit(p, lit, dots); emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0); } emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } /* Back face lighting: */ if (twoside) { struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; res0 = register_output( p, VERT_RESULT_BFC0 ); res1 = register_output( p, VERT_RESULT_BFC1 ); } else { mask0 = 0; mask1 = WRITEMASK_XYZ; res0 = _bfc0; res1 = register_output( p, VERT_RESULT_BFC0 ); } } else { res0 = _bfc0; res1 = _bfc1; mask0 = 0; mask1 = 0; } /* For the back face we need to negate the X and Y component * dot products. dots.Z has the negated back-face specular * exponent. We swizzle that into the W position. This * negation makes the back-face specular term positive again. */ dots = negate(swizzle(dots,X,Y,W,Z)); if (!is_undef(att)) { emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_MUL, lit, 0, lit, att); emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0); } else if (!p->state->material_shininess_is_zero) { emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); /**/ } else { emit_degenerate_lit(p, lit, dots); emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); } emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1); /* restore dots to its original state for subsequent lights * by negating and swizzling again. */ dots = negate(swizzle(dots,X,Y,W,Z)); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } release_temp(p, half); release_temp(p, VPpli); release_temp(p, att); } } release_temps( p ); }
void CCompilerFP::Compile(CParser *pParser) { int i,nCount = pParser->GetInstructionCount(); struct nvfx_insn tmp_insn,*insns = pParser->GetInstructions(); struct nvfx_src tmp,none = nvfx_src(nvfx_reg(NVFXSR_NONE,0)); Prepare(pParser); for(i=0;i<nCount;i++) { struct nvfx_insn *insn = &insns[i]; switch(insn->op) { case OPCODE_ADD: emit_insn(NVFX_FP_OP_OPCODE_ADD,insn); break; case OPCODE_BRK: emit_brk(insn); break; case OPCODE_COS: emit_insn(NVFX_FP_OP_OPCODE_COS,insn); break; case OPCODE_DP3: emit_insn(NVFX_FP_OP_OPCODE_DP3,insn); break; case OPCODE_DP4: emit_insn(NVFX_FP_OP_OPCODE_DP4,insn); break; case OPCODE_EX2: emit_insn(NVFX_FP_OP_OPCODE_EX2,insn); break; case OPCODE_LG2: emit_insn(NVFX_FP_OP_OPCODE_LG2,insn); break; case OPCODE_LRP: tmp = nvfx_src(temp()); tmp_insn = arith(0,tmp.reg,insn->mask,neg(insn->src[0]),insn->src[2],insn->src[2]); emit_insn(NVFX_FP_OP_OPCODE_MAD,&tmp_insn); tmp_insn = arith(insn->sat,insn->dst,insn->mask,insn->src[0],insn->src[1],tmp); emit_insn(NVFX_FP_OP_OPCODE_MAD,&tmp_insn); break; case OPCODE_MAX: emit_insn(NVFX_FP_OP_OPCODE_MAX,insn); break; case OPCODE_MIN: emit_insn(NVFX_FP_OP_OPCODE_MIN,insn); break; case OPCODE_MAD: emit_insn(NVFX_FP_OP_OPCODE_MAD,insn); break; case OPCODE_MOV: emit_insn(NVFX_FP_OP_OPCODE_MOV,insn); break; case OPCODE_MUL: emit_insn(NVFX_FP_OP_OPCODE_MUL,insn); break; case OPCODE_POW: tmp = nvfx_src(temp()); tmp_insn = arith(0,tmp.reg, NVFX_FP_MASK_X, insn->src[0], none, none); emit_insn(NVFX_FP_OP_OPCODE_LG2,&tmp_insn); tmp_insn = arith(0,tmp.reg, NVFX_FP_MASK_X, swz(tmp, X, X, X, X),insn->src[1], none); emit_insn(NVFX_FP_OP_OPCODE_MUL,&tmp_insn); tmp_insn = arith_ctor(insn,insn->dst,swz(tmp, X, X, X, X), none, none); emit_insn(NVFX_FP_OP_OPCODE_EX2,&tmp_insn); break; case OPCODE_RCP: emit_insn(NVFX_FP_OP_OPCODE_RCP,insn); break; case OPCODE_RSQ: tmp = nvfx_src(temp()); tmp_insn = arith(0,tmp.reg,NVFX_FP_MASK_X,abs(insn->src[0]),none,none); tmp_insn.scale = NVFX_FP_OP_DST_SCALE_INV_2X; emit_insn(NVFX_FP_OP_OPCODE_LG2,&tmp_insn); tmp_insn = arith_ctor(insn,insn->dst,neg(swz(tmp,X,X,X,X)),none,none); emit_insn(NVFX_FP_OP_OPCODE_EX2,&tmp_insn); break; case OPCODE_SEQ: emit_insn(NVFX_FP_OP_OPCODE_SEQ,insn); break; case OPCODE_SFL: emit_insn(NVFX_FP_OP_OPCODE_SFL,insn); break; case OPCODE_SGE: emit_insn(NVFX_FP_OP_OPCODE_SGE,insn); break; case OPCODE_SGT: emit_insn(NVFX_FP_OP_OPCODE_SGT,insn); break; case OPCODE_SIN: emit_insn(NVFX_FP_OP_OPCODE_SIN,insn); break; case OPCODE_SLE: emit_insn(NVFX_FP_OP_OPCODE_SLE,insn); break; case OPCODE_SLT: emit_insn(NVFX_FP_OP_OPCODE_SLT,insn); break; case OPCODE_SNE: emit_insn(NVFX_FP_OP_OPCODE_SNE,insn); break; case OPCODE_TEX: emit_insn(NVFX_FP_OP_OPCODE_TEX,insn); break; case OPCODE_TXB: emit_insn(NVFX_FP_OP_OPCODE_TXB,insn); break; case OPCODE_TXL: emit_insn(NVFX_FP_OP_OPCODE_TXL_NV40,insn); break; case OPCODE_TXP: emit_insn(NVFX_FP_OP_OPCODE_TXP,insn); break; case OPCODE_BGNREP: emit_rep(insn); break; case OPCODE_ENDREP: fixup_rep(); break; case OPCODE_END: if(m_nInstructions) m_pInstructions[m_nCurInstruction].data[0] |= NVFX_FP_OP_PROGRAM_END; else { m_nCurInstruction = m_nInstructions; grow_insns(1); m_pInstructions[m_nCurInstruction].data[0] = 0x00000001; m_pInstructions[m_nCurInstruction].data[1] = 0x00000000; m_pInstructions[m_nCurInstruction].data[2] = 0x00000000; m_pInstructions[m_nCurInstruction].data[3] = 0x00000000; } } release_temps(); } }