📄 brw_wm_fp.c
字号:
0, 0, 0, src_swizzle1(src0, SWIZZLE_ONE), src_undef(), src_undef()); /* Avoid letting the negation flag of src0 affect our 1 constant. */ swz->SrcReg[0].NegateBase = 0; } if (dst.WriteMask & WRITEMASK_YZ) { emit_op(c, OPCODE_LIT, dst_mask(dst, WRITEMASK_YZ), inst->SaturateMode, 0, 0, src0, src_undef(), src_undef()); }}static void precalc_tex( struct brw_wm_compile *c, const struct prog_instruction *inst ){ struct prog_src_register coord; struct prog_dst_register tmpcoord; GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit]; if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) { struct prog_instruction *out; struct prog_dst_register tmp0 = get_temp(c); struct prog_src_register tmp0src = src_reg_from_dst(tmp0); struct prog_dst_register tmp1 = get_temp(c); struct prog_src_register tmp1src = src_reg_from_dst(tmp1); struct prog_src_register src0 = inst->SrcReg[0]; tmpcoord = get_temp(c); coord = src_reg_from_dst(tmpcoord); out = emit_op(c, OPCODE_MOV, tmpcoord, 0, 0, 0, src0, src_undef(), src_undef()); out->SrcReg[0].NegateBase = 0; out->SrcReg[0].Abs = 1; emit_op(c, OPCODE_MAX, tmp0, 0, 0, 0, src_swizzle1(coord, X), src_swizzle1(coord, Y), src_undef()); emit_op(c, OPCODE_MAX, tmp1, 0, 0, 0, tmp0src, src_swizzle1(coord, Z), src_undef()); emit_op(c, OPCODE_RCP, tmp0, 0, 0, 0, tmp1src, src_undef(), src_undef()); emit_op(c, OPCODE_MUL, tmpcoord, 0, 0, 0, src0, tmp0src, src_undef()); release_temp(c, tmp0); release_temp(c, tmp1); } else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) { struct prog_src_register scale = search_or_add_param5( c, STATE_INTERNAL, STATE_TEXRECT_SCALE, unit, 0,0 ); tmpcoord = get_temp(c); /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height } */ emit_op(c, OPCODE_MUL, tmpcoord, 0, 0, 0, inst->SrcReg[0], scale, src_undef()); coord = src_reg_from_dst(tmpcoord); } else { coord = inst->SrcReg[0]; } /* Need to emit YUV texture conversions by hand. Probably need to * do this here - the alternative is in brw_wm_emit.c, but the * conversion requires allocating a temporary variable which we * don't have the facility to do that late in the compilation. */ if (!(c->key.yuvtex_mask & (1<<unit))) { emit_op(c, OPCODE_TEX, inst->DstReg, inst->SaturateMode, unit, inst->TexSrcTarget, coord, src_undef(), src_undef()); } else { GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit); /* CONST C0 = { -.5, -.0625, -.5, 1.164 } CONST C1 = { 1.596, -0.813, 2.018, -.391 } UYV = TEX ... UYV.xyz = ADD UYV, C0 UYV.y = MUL UYV.y, C0.w if (UV swaped) RGB.xyz = MAD UYV.zzx, C1, UYV.y else RGB.xyz = MAD UYV.xxz, C1, UYV.y RGB.y = MAD UYV.z, C1.w, RGB.y */ struct prog_dst_register dst = inst->DstReg; struct prog_dst_register tmp = get_temp(c); struct prog_src_register tmpsrc = src_reg_from_dst(tmp); struct prog_src_register C0 = search_or_add_const4f( c, -.5, -.0625, -.5, 1.164 ); struct prog_src_register C1 = search_or_add_const4f( c, 1.596, -0.813, 2.018, -.391 ); /* tmp = TEX ... */ emit_op(c, OPCODE_TEX, tmp, inst->SaturateMode, unit, inst->TexSrcTarget, coord, src_undef(), src_undef()); /* tmp.xyz = ADD TMP, C0 */ emit_op(c, OPCODE_ADD, dst_mask(tmp, WRITEMASK_XYZ), 0, 0, 0, tmpsrc, C0, src_undef()); /* YUV.y = MUL YUV.y, C0.w */ emit_op(c, OPCODE_MUL, dst_mask(tmp, WRITEMASK_Y), 0, 0, 0, tmpsrc, src_swizzle1(C0, W), src_undef()); /* * if (UV swaped) * RGB.xyz = MAD YUV.zzx, C1, YUV.y * else * RGB.xyz = MAD YUV.xxz, C1, YUV.y */ emit_op(c, OPCODE_MAD, dst_mask(dst, WRITEMASK_XYZ), 0, 0, 0, swap_uv?src_swizzle(tmpsrc, Z,Z,X,X):src_swizzle(tmpsrc, X,X,Z,Z), C1, src_swizzle1(tmpsrc, Y)); /* RGB.y = MAD YUV.z, C1.w, RGB.y */ emit_op(c, OPCODE_MAD, dst_mask(dst, WRITEMASK_Y), 0, 0, 0, src_swizzle1(tmpsrc, Z), src_swizzle1(C1, W), src_swizzle1(src_reg_from_dst(dst), Y)); release_temp(c, tmp); } if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) || (inst->TexSrcTarget == TEXTURE_CUBE_INDEX)) release_temp(c, tmpcoord);}static GLboolean projtex( struct brw_wm_compile *c, const struct prog_instruction *inst ){ struct prog_src_register src = inst->SrcReg[0]; /* Only try to detect the simplest cases. Could detect (later) * cases where we are trying to emit code like RCP {1.0}, MUL x, * {1.0}, and so on. * * More complex cases than this typically only arise from * user-provided fragment programs anyway: */ if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) return 0; /* ut2004 gun rendering !?! */ else if (src.File == PROGRAM_INPUT && GET_SWZ(src.Swizzle, W) == W && (c->key.projtex_mask & (1<<(src.Index + FRAG_ATTRIB_WPOS - FRAG_ATTRIB_TEX0))) == 0) return 0; else return 1;}static void precalc_txp( struct brw_wm_compile *c, const struct prog_instruction *inst ){ struct prog_src_register src0 = inst->SrcReg[0]; if (projtex(c, inst)) { struct prog_dst_register tmp = get_temp(c); struct prog_instruction tmp_inst; /* tmp0.w = RCP inst.arg[0][3] */ emit_op(c, OPCODE_RCP, dst_mask(tmp, WRITEMASK_W), 0, 0, 0, src_swizzle1(src0, GET_SWZ(src0.Swizzle, W)), src_undef(), src_undef()); /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww */ emit_op(c, OPCODE_MUL, dst_mask(tmp, WRITEMASK_XYZ), 0, 0, 0, src0, src_swizzle1(src_reg_from_dst(tmp), W), src_undef()); /* dst = precalc(TEX tmp0) */ tmp_inst = *inst; tmp_inst.SrcReg[0] = src_reg_from_dst(tmp); precalc_tex(c, &tmp_inst); release_temp(c, tmp); } else { /* dst = precalc(TEX src0) */ precalc_tex(c, inst); }}/*********************************************************************** * Add instructions to perform fog blending */static void fog_blend( struct brw_wm_compile *c, struct prog_src_register fog_factor ){ struct prog_dst_register outcolor = dst_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR); struct prog_src_register fogcolor = search_or_add_param5( c, STATE_FOG_COLOR, 0,0,0,0 ); /* color.xyz = LRP fog_factor.xxxx, output_color, fog_color */ emit_op(c, OPCODE_LRP, dst_mask(outcolor, WRITEMASK_XYZ), 0, 0, 0, fog_factor, src_reg_from_dst(outcolor), fogcolor);}/* This one is simple - just take the interpolated fog coordinate and * use it as the fog blend factor. */static void fog_interpolated( struct brw_wm_compile *c ){ struct prog_src_register fogc = src_reg(PROGRAM_INPUT, FRAG_ATTRIB_FOGC); if (!(c->fp_interp_emitted & (1<<FRAG_ATTRIB_FOGC))) emit_interp(c, FRAG_ATTRIB_FOGC); fog_blend( c, src_swizzle1(fogc, GET_SWZ(fogc.Swizzle,X)));}static void emit_fog( struct brw_wm_compile *c ) { if (!c->fp->program.FogOption) return; if (1) fog_interpolated( c ); else { /* TODO: per-pixel fog */ assert(0); }}static void emit_fb_write( struct brw_wm_compile *c ){ struct prog_src_register outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR); struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH); struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPR); GLuint i; struct prog_instruction *inst, *last_inst; struct brw_context *brw = c->func.brw; /* inst->Sampler is not used by backend, use it for fb write target and eot */ if (brw->state.nr_draw_regions > 1) { for (i = 0 ; i < brw->state.nr_draw_regions; i++) { outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i); last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0, outcolor, payload_r0_depth, outdepth); inst->Sampler = (i<<1); if (c->fp_fragcolor_emitted) { outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR); last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0, outcolor, payload_r0_depth, outdepth); inst->Sampler = (i<<1); } } last_inst->Sampler |= 1; //eot }else { inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0, outcolor, payload_r0_depth, outdepth); inst->Sampler = 1|(0<<1); }}/*********************************************************************** * Emit INTERP instructions ahead of first use of each attrib. */static void validate_src_regs( struct brw_wm_compile *c, const struct prog_instruction *inst ){ GLuint nr_args = brw_wm_nr_args( inst->Opcode ); GLuint i; for (i = 0; i < nr_args; i++) { if (inst->SrcReg[i].File == PROGRAM_INPUT) { GLuint idx = inst->SrcReg[i].Index; if (!(c->fp_interp_emitted & (1<<idx))) { emit_interp(c, idx); } } }} static void validate_dst_regs( struct brw_wm_compile *c, const struct prog_instruction *inst ){ if (inst->DstReg.File == PROGRAM_OUTPUT) { GLuint idx = inst->DstReg.Index; if (idx == FRAG_RESULT_COLR) c->fp_fragcolor_emitted = 1; }}static void print_insns( const struct prog_instruction *insn, GLuint nr ){ GLuint i; for (i = 0; i < nr; i++, insn++) { _mesa_printf("%3d: ", i); if (insn->Opcode < MAX_OPCODE) _mesa_print_instruction(insn); else if (insn->Opcode < MAX_WM_OPCODE) { GLuint idx = insn->Opcode - MAX_OPCODE; _mesa_print_alu_instruction(insn, wm_opcode_strings[idx], 3); } else _mesa_printf("UNKNOWN\n"); }}void brw_wm_pass_fp( struct brw_wm_compile *c ){ struct brw_fragment_program *fp = c->fp; GLuint insn; if (INTEL_DEBUG & DEBUG_WM) { _mesa_printf("\n\n\npre-fp:\n"); _mesa_print_program(&fp->program.Base); _mesa_printf("\n"); } c->pixel_xy = src_undef(); c->delta_xy = src_undef(); c->pixel_w = src_undef(); c->nr_fp_insns = 0; /* Emit preamble instructions: */ for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) { const struct prog_instruction *inst = &fp->program.Base.Instructions[insn]; validate_src_regs(c, inst); validate_dst_regs(c, inst); } for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) { const struct prog_instruction *inst = &fp->program.Base.Instructions[insn]; struct prog_instruction *out; /* Check for INPUT values, emit INTERP instructions where * necessary: */ switch (inst->Opcode) { case OPCODE_SWZ: out = emit_insn(c, inst); out->Opcode = OPCODE_MOV; break; case OPCODE_ABS: out = emit_insn(c, inst); out->Opcode = OPCODE_MOV; out->SrcReg[0].NegateBase = 0; out->SrcReg[0].Abs = 1; break; case OPCODE_SUB: out = emit_insn(c, inst); out->Opcode = OPCODE_ADD; out->SrcReg[1].NegateBase ^= 0xf; break; case OPCODE_SCS: out = emit_insn(c, inst); /* This should probably be done in the parser. */ out->DstReg.WriteMask &= WRITEMASK_XY; break; case OPCODE_DST: precalc_dst(c, inst); break; case OPCODE_LIT: precalc_lit(c, inst); break; case OPCODE_TEX: precalc_tex(c, inst); break; case OPCODE_TXP: precalc_txp(c, inst); break; case OPCODE_TXB: out = emit_insn(c, inst); out->TexSrcUnit = fp->program.Base.SamplerUnits[inst->TexSrcUnit]; break; case OPCODE_XPD: out = emit_insn(c, inst); /* This should probably be done in the parser. */ out->DstReg.WriteMask &= WRITEMASK_XYZ; break; case OPCODE_KIL: out = emit_insn(c, inst); /* This should probably be done in the parser. */ out->DstReg.WriteMask = 0; break; case OPCODE_DDX: emit_ddx(c, inst); break; case OPCODE_DDY: emit_ddy(c, inst); break; case OPCODE_END: emit_fog(c); emit_fb_write(c); break; case OPCODE_PRINT: break; default: emit_insn(c, inst); break; } } if (INTEL_DEBUG & DEBUG_WM) { _mesa_printf("\n\n\npass_fp:\n"); print_insns( c->prog_instructions, c->nr_fp_insns ); _mesa_printf("\n"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -