2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **********************************************************************/
29 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "main/glheader.h"
34 #include "main/macros.h"
35 #include "main/enums.h"
36 #include "brw_context.h"
40 #include "program/prog_parameter.h"
41 #include "program/prog_print.h"
42 #include "program/prog_statevars.h"
45 /** An invalid texture target */
46 #define TEX_TARGET_NONE NUM_TEXTURE_TARGETS
48 /** An invalid texture unit */
49 #define TEX_UNIT_NONE BRW_MAX_TEX_UNIT
51 #define FIRST_INTERNAL_TEMP MAX_NV_FRAGMENT_PROGRAM_TEMPS
59 static const char *wm_opcode_strings
[] = {
72 static const char *wm_file_strings
[] = {
78 /***********************************************************************
82 static struct prog_src_register
src_reg(GLuint file
, GLuint idx
)
84 struct prog_src_register reg
;
87 reg
.Swizzle
= SWIZZLE_NOOP
;
89 reg
.Negate
= NEGATE_NONE
;
97 static struct prog_src_register
src_reg_from_dst(struct prog_dst_register dst
)
99 return src_reg(dst
.File
, dst
.Index
);
102 static struct prog_src_register
src_undef( void )
104 return src_reg(PROGRAM_UNDEFINED
, 0);
107 static bool src_is_undef(struct prog_src_register src
)
109 return src
.File
== PROGRAM_UNDEFINED
;
112 static struct prog_src_register
src_swizzle( struct prog_src_register reg
, int x
, int y
, int z
, int w
)
114 reg
.Swizzle
= MAKE_SWIZZLE4(x
,y
,z
,w
);
118 static struct prog_src_register
src_swizzle1( struct prog_src_register reg
, int x
)
120 return src_swizzle(reg
, x
, x
, x
, x
);
123 static struct prog_src_register
src_swizzle4( struct prog_src_register reg
, uint swizzle
)
125 reg
.Swizzle
= swizzle
;
130 /***********************************************************************
134 static struct prog_dst_register
dst_reg(GLuint file
, GLuint idx
)
136 struct prog_dst_register reg
;
139 reg
.WriteMask
= WRITEMASK_XYZW
;
141 reg
.CondMask
= COND_TR
;
147 static struct prog_dst_register
dst_mask( struct prog_dst_register reg
, int mask
)
149 reg
.WriteMask
&= mask
;
153 static struct prog_dst_register
dst_undef( void )
155 return dst_reg(PROGRAM_UNDEFINED
, 0);
160 static struct prog_dst_register
get_temp( struct brw_wm_compile
*c
)
162 int bit
= _mesa_ffs( ~c
->fp_temp
);
165 printf("%s: out of temporaries\n", __FILE__
);
169 c
->fp_temp
|= 1<<(bit
-1);
170 return dst_reg(PROGRAM_TEMPORARY
, FIRST_INTERNAL_TEMP
+(bit
-1));
174 static void release_temp( struct brw_wm_compile
*c
, struct prog_dst_register temp
)
176 c
->fp_temp
&= ~(1 << (temp
.Index
- FIRST_INTERNAL_TEMP
));
180 /***********************************************************************
184 static struct prog_instruction
*get_fp_inst(struct brw_wm_compile
*c
)
186 assert(c
->nr_fp_insns
< BRW_WM_MAX_INSN
);
187 memset(&c
->prog_instructions
[c
->nr_fp_insns
], 0,
188 sizeof(*c
->prog_instructions
));
189 return &c
->prog_instructions
[c
->nr_fp_insns
++];
192 static struct prog_instruction
*emit_insn(struct brw_wm_compile
*c
,
193 const struct prog_instruction
*inst0
)
195 struct prog_instruction
*inst
= get_fp_inst(c
);
200 static struct prog_instruction
* emit_tex_op(struct brw_wm_compile
*c
,
202 struct prog_dst_register dest
,
205 GLuint tex_src_target
,
207 struct prog_src_register src0
,
208 struct prog_src_register src1
,
209 struct prog_src_register src2
)
211 struct prog_instruction
*inst
= get_fp_inst(c
);
213 assert(tex_src_unit
< BRW_MAX_TEX_UNIT
||
214 tex_src_unit
== TEX_UNIT_NONE
);
215 assert(tex_src_target
< NUM_TEXTURE_TARGETS
||
216 tex_src_target
== TEX_TARGET_NONE
);
218 memset(inst
, 0, sizeof(*inst
));
222 inst
->SaturateMode
= saturate
;
223 inst
->TexSrcUnit
= tex_src_unit
;
224 inst
->TexSrcTarget
= tex_src_target
;
225 inst
->TexShadow
= tex_shadow
;
226 inst
->SrcReg
[0] = src0
;
227 inst
->SrcReg
[1] = src1
;
228 inst
->SrcReg
[2] = src2
;
233 static struct prog_instruction
* emit_op(struct brw_wm_compile
*c
,
235 struct prog_dst_register dest
,
237 struct prog_src_register src0
,
238 struct prog_src_register src1
,
239 struct prog_src_register src2
)
241 return emit_tex_op(c
, op
, dest
, saturate
,
242 TEX_UNIT_NONE
, TEX_TARGET_NONE
, 0, /* unit, tgt, shadow */
247 /* Many Mesa opcodes produce the same value across all the result channels.
248 * We'd rather not have to support that splatting in the opcode implementations,
249 * and brw_wm_pass*.c wants to optimize them out by shuffling references around
250 * anyway. We can easily get both by emitting the opcode to one channel, and
251 * then MOVing it to the others, which brw_wm_pass*.c already understands.
253 static struct prog_instruction
*emit_scalar_insn(struct brw_wm_compile
*c
,
254 const struct prog_instruction
*inst0
)
256 struct prog_instruction
*inst
;
257 unsigned int dst_chan
;
258 unsigned int other_channel_mask
;
260 if (inst0
->DstReg
.WriteMask
== 0)
263 dst_chan
= _mesa_ffs(inst0
->DstReg
.WriteMask
) - 1;
264 inst
= get_fp_inst(c
);
266 inst
->DstReg
.WriteMask
= 1 << dst_chan
;
268 other_channel_mask
= inst0
->DstReg
.WriteMask
& ~(1 << dst_chan
);
269 if (other_channel_mask
!= 0) {
272 dst_mask(inst0
->DstReg
, other_channel_mask
),
274 src_swizzle1(src_reg_from_dst(inst0
->DstReg
), dst_chan
),
282 /***********************************************************************
283 * Special instructions for interpolation and other tasks
286 static struct prog_src_register
get_pixel_xy( struct brw_wm_compile
*c
)
288 if (src_is_undef(c
->pixel_xy
)) {
289 struct prog_dst_register pixel_xy
= get_temp(c
);
290 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
293 /* Emit the out calculations, and hold onto the results. Use
294 * two instructions as a temporary is required.
296 /* pixel_xy.xy = PIXELXY payload[0];
300 dst_mask(pixel_xy
, WRITEMASK_XY
),
306 c
->pixel_xy
= src_reg_from_dst(pixel_xy
);
312 static struct prog_src_register
get_delta_xy( struct brw_wm_compile
*c
)
314 if (src_is_undef(c
->delta_xy
)) {
315 struct prog_dst_register delta_xy
= get_temp(c
);
316 struct prog_src_register pixel_xy
= get_pixel_xy(c
);
317 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
319 /* deltas.xy = DELTAXY pixel_xy, payload[0]
323 dst_mask(delta_xy
, WRITEMASK_XY
),
329 c
->delta_xy
= src_reg_from_dst(delta_xy
);
335 static struct prog_src_register
get_pixel_w( struct brw_wm_compile
*c
)
337 /* This is called for producing 1/w in pre-gen6 interp. for gen6,
338 * the interp opcodes don't use this argument. But to keep the
339 * nr_args = 3 expectations of pinterp happy, just stuff delta_xy
342 if (c
->func
.brw
->intel
.gen
>= 6)
345 if (src_is_undef(c
->pixel_w
)) {
346 struct prog_dst_register pixel_w
= get_temp(c
);
347 struct prog_src_register deltas
= get_delta_xy(c
);
348 struct prog_src_register interp_wpos
= src_reg(PROGRAM_PAYLOAD
, FRAG_ATTRIB_WPOS
);
350 /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x
354 dst_mask(pixel_w
, WRITEMASK_W
),
361 c
->pixel_w
= src_reg_from_dst(pixel_w
);
367 static void emit_interp( struct brw_wm_compile
*c
,
370 struct prog_dst_register dst
= dst_reg(PROGRAM_INPUT
, idx
);
371 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
372 struct prog_src_register deltas
;
374 deltas
= get_delta_xy(c
);
376 /* Need to use PINTERP on attributes which have been
377 * multiplied by 1/W in the SF program, and LINTERP on those
381 case FRAG_ATTRIB_WPOS
:
382 /* Have to treat wpos.xy specially:
386 dst_mask(dst
, WRITEMASK_XY
),
392 dst
= dst_mask(dst
, WRITEMASK_ZW
);
394 /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
404 case FRAG_ATTRIB_COL0
:
405 case FRAG_ATTRIB_COL1
:
406 if (c
->key
.flat_shade
) {
416 /* perspective-corrected color interpolation */
426 case FRAG_ATTRIB_FOGC
:
427 /* Interpolate the fog coordinate */
430 dst_mask(dst
, WRITEMASK_X
),
438 dst_mask(dst
, WRITEMASK_YZW
),
449 case FRAG_ATTRIB_FACE
:
452 dst_mask(dst
, WRITEMASK_X
),
459 case FRAG_ATTRIB_PNTC
:
460 /* XXX review/test this case */
463 dst_mask(dst
, WRITEMASK_XY
),
471 dst_mask(dst
, WRITEMASK_ZW
),
493 c
->fp_interp_emitted
|= 1<<idx
;
496 /***********************************************************************
497 * Hacks to extend the program parameter and constant lists.
500 /* Add the fog parameters to the parameter list of the original
501 * program, rather than creating a new list. Doesn't really do any
502 * harm and it's not as if the parameter handling isn't a big hack
505 static struct prog_src_register
search_or_add_param5(struct brw_wm_compile
*c
,
512 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
513 gl_state_index tokens
[STATE_LENGTH
];
521 idx
= _mesa_add_state_reference( paramList
, tokens
);
523 return src_reg(PROGRAM_STATE_VAR
, idx
);
527 static struct prog_src_register
search_or_add_const4f( struct brw_wm_compile
*c
,
533 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
534 gl_constant_value values
[4];
537 struct prog_src_register reg
;
544 idx
= _mesa_add_unnamed_constant( paramList
, values
, 4, &swizzle
);
545 reg
= src_reg(PROGRAM_STATE_VAR
, idx
);
546 reg
.Swizzle
= swizzle
;
553 /***********************************************************************
554 * Expand various instructions here to simpler forms.
556 static void precalc_dst( struct brw_wm_compile
*c
,
557 const struct prog_instruction
*inst
)
559 struct prog_src_register src0
= inst
->SrcReg
[0];
560 struct prog_src_register src1
= inst
->SrcReg
[1];
561 struct prog_dst_register dst
= inst
->DstReg
;
562 struct prog_dst_register temp
= get_temp(c
);
564 if (dst
.WriteMask
& WRITEMASK_Y
) {
565 /* dst.y = mul src0.y, src1.y
569 dst_mask(temp
, WRITEMASK_Y
),
576 if (dst
.WriteMask
& WRITEMASK_XZ
) {
577 struct prog_instruction
*swz
;
578 GLuint z
= GET_SWZ(src0
.Swizzle
, Z
);
580 /* dst.xz = swz src0.1zzz
584 dst_mask(temp
, WRITEMASK_XZ
),
586 src_swizzle(src0
, SWIZZLE_ONE
, z
, z
, z
),
589 /* Avoid letting negation flag of src0 affect our 1 constant. */
590 swz
->SrcReg
[0].Negate
&= ~NEGATE_X
;
592 if (dst
.WriteMask
& WRITEMASK_W
) {
593 /* dst.w = mov src1.w
597 dst_mask(temp
, WRITEMASK_W
),
604 /* This will get optimized out in general, but it ensures that we
605 * don't overwrite src operands in our channel-wise splitting
606 * above. See piglit fp-dst-aliasing-[12].
612 src_reg_from_dst(temp
),
616 release_temp(c
, temp
);
620 static void precalc_lit( struct brw_wm_compile
*c
,
621 const struct prog_instruction
*inst
)
623 struct prog_src_register src0
= inst
->SrcReg
[0];
624 struct prog_dst_register dst
= inst
->DstReg
;
626 if (dst
.WriteMask
& WRITEMASK_YZ
) {
629 dst_mask(dst
, WRITEMASK_YZ
),
636 if (dst
.WriteMask
& WRITEMASK_XW
) {
637 struct prog_instruction
*swz
;
639 /* dst.xw = swz src0.1111
643 dst_mask(dst
, WRITEMASK_XW
),
645 src_swizzle1(src0
, SWIZZLE_ONE
),
648 /* Avoid letting the negation flag of src0 affect our 1 constant. */
649 swz
->SrcReg
[0].Negate
= NEGATE_NONE
;
655 * Some TEX instructions require extra code, cube map coordinate
656 * normalization, or coordinate scaling for RECT textures, etc.
657 * This function emits those extra instructions and the TEX
658 * instruction itself.
660 static void precalc_tex( struct brw_wm_compile
*c
,
661 const struct prog_instruction
*inst
)
663 struct brw_compile
*p
= &c
->func
;
664 struct intel_context
*intel
= &p
->brw
->intel
;
665 struct prog_src_register coord
;
666 struct prog_dst_register tmpcoord
= { 0 };
667 const GLuint unit
= c
->fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
668 struct prog_dst_register unswizzled_tmp
;
670 /* If we are doing EXT_texture_swizzle, we need to write our result into a
671 * temporary, otherwise writemasking of the real dst could lose some of our
674 if (c
->key
.tex_swizzles
[unit
] != SWIZZLE_NOOP
) {
675 unswizzled_tmp
= get_temp(c
);
677 unswizzled_tmp
= inst
->DstReg
;
680 assert(unit
< BRW_MAX_TEX_UNIT
);
682 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
) {
683 struct prog_instruction
*out
;
684 struct prog_dst_register tmp0
= get_temp(c
);
685 struct prog_src_register tmp0src
= src_reg_from_dst(tmp0
);
686 struct prog_dst_register tmp1
= get_temp(c
);
687 struct prog_src_register tmp1src
= src_reg_from_dst(tmp1
);
688 struct prog_src_register src0
= inst
->SrcReg
[0];
690 /* find longest component of coord vector and normalize it */
691 tmpcoord
= get_temp(c
);
692 coord
= src_reg_from_dst(tmpcoord
);
694 /* tmpcoord = src0 (i.e.: coord = src0) */
695 out
= emit_op(c
, OPCODE_MOV
,
701 out
->SrcReg
[0].Negate
= NEGATE_NONE
;
702 out
->SrcReg
[0].Abs
= 1;
704 /* tmp0 = MAX(coord.X, coord.Y) */
705 emit_op(c
, OPCODE_MAX
,
708 src_swizzle1(coord
, X
),
709 src_swizzle1(coord
, Y
),
712 /* tmp1 = MAX(tmp0, coord.Z) */
713 emit_op(c
, OPCODE_MAX
,
717 src_swizzle1(coord
, Z
),
720 /* tmp0 = 1 / tmp1 */
721 emit_op(c
, OPCODE_RCP
,
722 dst_mask(tmp0
, WRITEMASK_X
),
728 /* tmpCoord = src0 * tmp0 */
729 emit_op(c
, OPCODE_MUL
,
733 src_swizzle1(tmp0src
, SWIZZLE_X
),
736 release_temp(c
, tmp0
);
737 release_temp(c
, tmp1
);
739 else if (intel
->gen
< 6 && inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) {
740 struct prog_src_register scale
=
741 search_or_add_param5( c
,
747 tmpcoord
= get_temp(c
);
749 /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height }
763 coord
= src_reg_from_dst(tmpcoord
);
766 coord
= inst
->SrcReg
[0];
769 /* Need to emit YUV texture conversions by hand. Probably need to
770 * do this here - the alternative is in brw_wm_emit.c, but the
771 * conversion requires allocating a temporary variable which we
772 * don't have the facility to do that late in the compilation.
774 if (c
->key
.yuvtex_mask
& (1 << unit
)) {
775 /* convert ycbcr to RGBA */
776 bool swap_uv
= c
->key
.yuvtex_swap_mask
& (1<<unit
);
779 CONST C0 = { -.5, -.0625, -.5, 1.164 }
780 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
782 UYV.xyz = ADD UYV, C0
783 UYV.y = MUL UYV.y, C0.w
785 RGB.xyz = MAD UYV.zzx, C1, UYV.y
787 RGB.xyz = MAD UYV.xxz, C1, UYV.y
788 RGB.y = MAD UYV.z, C1.w, RGB.y
790 struct prog_dst_register tmp
= get_temp(c
);
791 struct prog_src_register tmpsrc
= src_reg_from_dst(tmp
);
792 struct prog_src_register C0
= search_or_add_const4f( c
, -.5, -.0625, -.5, 1.164 );
793 struct prog_src_register C1
= search_or_add_const4f( c
, 1.596, -0.813, 2.018, -.391 );
808 /* tmp.xyz = ADD TMP, C0
812 dst_mask(tmp
, WRITEMASK_XYZ
),
818 /* YUV.y = MUL YUV.y, C0.w
823 dst_mask(tmp
, WRITEMASK_Y
),
831 * RGB.xyz = MAD YUV.zzx, C1, YUV.y
833 * RGB.xyz = MAD YUV.xxz, C1, YUV.y
838 dst_mask(unswizzled_tmp
, WRITEMASK_XYZ
),
840 swap_uv
?src_swizzle(tmpsrc
, Z
,Z
,X
,X
):src_swizzle(tmpsrc
, X
,X
,Z
,Z
),
842 src_swizzle1(tmpsrc
, Y
));
844 /* RGB.y = MAD YUV.z, C1.w, RGB.y
848 dst_mask(unswizzled_tmp
, WRITEMASK_Y
),
850 src_swizzle1(tmpsrc
, Z
),
852 src_swizzle1(src_reg_from_dst(unswizzled_tmp
), Y
));
854 release_temp(c
, tmp
);
857 /* ordinary RGBA tex instruction */
870 /* For GL_EXT_texture_swizzle: */
871 if (c
->key
.tex_swizzles
[unit
] != SWIZZLE_NOOP
) {
872 /* swizzle the result of the TEX instruction */
873 struct prog_src_register tmpsrc
= src_reg_from_dst(unswizzled_tmp
);
874 emit_op(c
, OPCODE_SWZ
,
876 SATURATE_OFF
, /* saturate already done above */
877 src_swizzle4(tmpsrc
, c
->key
.tex_swizzles
[unit
]),
882 if ((inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) ||
883 (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
))
884 release_temp(c
, tmpcoord
);
889 * Check if the given TXP instruction really needs the divide-by-W step.
892 projtex(struct brw_wm_compile
*c
, const struct prog_instruction
*inst
)
894 const struct prog_src_register src
= inst
->SrcReg
[0];
897 assert(inst
->Opcode
== OPCODE_TXP
);
899 /* Only try to detect the simplest cases. Could detect (later)
900 * cases where we are trying to emit code like RCP {1.0}, MUL x,
903 * More complex cases than this typically only arise from
904 * user-provided fragment programs anyway:
906 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
)
907 retVal
= false; /* ut2004 gun rendering !?! */
908 else if (src
.File
== PROGRAM_INPUT
&&
909 GET_SWZ(src
.Swizzle
, W
) == W
&&
910 (c
->key
.proj_attrib_mask
& (1 << src
.Index
)) == 0)
922 static void precalc_txp( struct brw_wm_compile
*c
,
923 const struct prog_instruction
*inst
)
925 struct prog_src_register src0
= inst
->SrcReg
[0];
927 if (projtex(c
, inst
)) {
928 struct prog_dst_register tmp
= get_temp(c
);
929 struct prog_instruction tmp_inst
;
931 /* tmp0.w = RCP inst.arg[0][3]
935 dst_mask(tmp
, WRITEMASK_W
),
937 src_swizzle1(src0
, GET_SWZ(src0
.Swizzle
, W
)),
941 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww
945 dst_mask(tmp
, WRITEMASK_XYZ
),
948 src_swizzle1(src_reg_from_dst(tmp
), W
),
951 /* dst = precalc(TEX tmp0)
954 tmp_inst
.SrcReg
[0] = src_reg_from_dst(tmp
);
955 precalc_tex(c
, &tmp_inst
);
957 release_temp(c
, tmp
);
961 /* dst = precalc(TEX src0)
963 precalc_tex(c
, inst
);
969 static void emit_render_target_writes( struct brw_wm_compile
*c
)
971 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
972 struct prog_src_register outdepth
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DEPTH
);
973 struct prog_src_register outcolor
;
976 struct prog_instruction
*inst
= NULL
;
978 /* The inst->Aux field is used for FB write target and the EOT marker */
980 for (i
= 0; i
< c
->key
.nr_color_regions
; i
++) {
981 if (c
->fp
->program
.Base
.OutputsWritten
& (1 << FRAG_RESULT_COLOR
)) {
982 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
984 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
+ i
);
986 inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(), 0),
987 0, outcolor
, payload_r0_depth
, outdepth
);
988 inst
->Aux
= INST_AUX_TARGET(i
);
991 /* Mark the last FB write as final, or emit a dummy write if we had
992 * no render targets bound.
994 if (c
->key
.nr_color_regions
!= 0) {
995 inst
->Aux
|= INST_AUX_EOT
;
997 inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(), 0),
998 0, src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
),
999 payload_r0_depth
, outdepth
);
1000 inst
->Aux
= INST_AUX_TARGET(0) | INST_AUX_EOT
;
1007 /***********************************************************************
1008 * Emit INTERP instructions ahead of first use of each attrib.
1011 static void validate_src_regs( struct brw_wm_compile
*c
,
1012 const struct prog_instruction
*inst
)
1014 GLuint nr_args
= brw_wm_nr_args( inst
->Opcode
);
1017 for (i
= 0; i
< nr_args
; i
++) {
1018 if (inst
->SrcReg
[i
].File
== PROGRAM_INPUT
) {
1019 GLuint idx
= inst
->SrcReg
[i
].Index
;
1020 if (!(c
->fp_interp_emitted
& (1<<idx
))) {
1021 emit_interp(c
, idx
);
1027 static void print_insns( const struct prog_instruction
*insn
,
1031 for (i
= 0; i
< nr
; i
++, insn
++) {
1033 if (insn
->Opcode
< MAX_OPCODE
)
1034 _mesa_fprint_instruction_opt(stdout
, insn
, 0, PROG_PRINT_DEBUG
, NULL
);
1035 else if (insn
->Opcode
< MAX_WM_OPCODE
) {
1036 GLuint idx
= insn
->Opcode
- MAX_OPCODE
;
1038 _mesa_fprint_alu_instruction(stdout
, insn
, wm_opcode_strings
[idx
],
1039 3, PROG_PRINT_DEBUG
, NULL
);
1042 printf("965 Opcode %d\n", insn
->Opcode
);
1048 * Initial pass for fragment program code generation.
1049 * This function is used by both the GLSL and non-GLSL paths.
1051 void brw_wm_pass_fp( struct brw_wm_compile
*c
)
1053 struct intel_context
*intel
= &c
->func
.brw
->intel
;
1054 struct brw_fragment_program
*fp
= c
->fp
;
1057 if (unlikely(INTEL_DEBUG
& DEBUG_WM
)) {
1058 printf("pre-fp:\n");
1059 _mesa_fprint_program_opt(stdout
, &fp
->program
.Base
, PROG_PRINT_DEBUG
,
1064 c
->pixel_xy
= src_undef();
1065 if (intel
->gen
>= 6) {
1066 /* The interpolation deltas come in as the perspective pixel
1067 * location barycentric params.
1069 c
->delta_xy
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
1071 c
->delta_xy
= src_undef();
1073 c
->pixel_w
= src_undef();
1076 /* Emit preamble instructions. This is where special instructions such as
1077 * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
1078 * compute shader inputs from varying vars.
1080 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
1081 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
1082 validate_src_regs(c
, inst
);
1085 /* Loop over all instructions doing assorted simplifications and
1088 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
1089 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
1090 struct prog_instruction
*out
;
1092 /* Check for INPUT values, emit INTERP instructions where
1096 switch (inst
->Opcode
) {
1098 out
= emit_insn(c
, inst
);
1099 out
->Opcode
= OPCODE_MOV
;
1103 out
= emit_insn(c
, inst
);
1104 out
->Opcode
= OPCODE_MOV
;
1105 out
->SrcReg
[0].Negate
= NEGATE_NONE
;
1106 out
->SrcReg
[0].Abs
= 1;
1110 out
= emit_insn(c
, inst
);
1111 out
->Opcode
= OPCODE_ADD
;
1112 out
->SrcReg
[1].Negate
^= NEGATE_XYZW
;
1116 out
= emit_insn(c
, inst
);
1117 /* This should probably be done in the parser.
1119 out
->DstReg
.WriteMask
&= WRITEMASK_XY
;
1123 precalc_dst(c
, inst
);
1127 precalc_lit(c
, inst
);
1131 out
= emit_scalar_insn(c
, inst
);
1132 out
->SrcReg
[0].Abs
= true;
1136 precalc_tex(c
, inst
);
1140 precalc_txp(c
, inst
);
1144 out
= emit_insn(c
, inst
);
1145 out
->TexSrcUnit
= fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
1146 assert(out
->TexSrcUnit
< BRW_MAX_TEX_UNIT
);
1150 out
= emit_insn(c
, inst
);
1151 /* This should probably be done in the parser.
1153 out
->DstReg
.WriteMask
&= WRITEMASK_XYZ
;
1157 out
= emit_insn(c
, inst
);
1158 /* This should probably be done in the parser.
1160 out
->DstReg
.WriteMask
= 0;
1163 emit_render_target_writes(c
);
1168 if (brw_wm_is_scalar_result(inst
->Opcode
))
1169 emit_scalar_insn(c
, inst
);
1176 if (unlikely(INTEL_DEBUG
& DEBUG_WM
)) {
1177 printf("pass_fp:\n");
1178 print_insns( c
->prog_instructions
, c
->nr_fp_insns
);