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 "pipe/p_shader_tokens.h"
35 #include "util/u_math.h"
36 #include "util/u_memory.h"
38 #include "tgsi/tgsi_parse.h"
39 #include "tgsi/tgsi_dump.h"
40 #include "tgsi/tgsi_info.h"
41 #include "tgsi/tgsi_util.h"
45 #include "brw_debug.h"
48 /***********************************************************************
52 static struct brw_fp_src
src_reg(GLuint file
, GLuint idx
)
54 struct brw_fp_src reg
;
57 reg
.swizzle
= BRW_SWIZZLE_XYZW
;
64 static struct brw_fp_src
src_reg_from_dst(struct brw_fp_dst dst
)
66 return src_reg(dst
.file
, dst
.index
);
69 static struct brw_fp_src
src_undef( void )
71 return src_reg(TGSI_FILE_NULL
, 0);
74 static GLboolean
src_is_undef(struct brw_fp_src src
)
76 return src
.file
== TGSI_FILE_NULL
;
79 static struct brw_fp_src
src_swizzle( struct brw_fp_src reg
, int x
, int y
, int z
, int w
)
81 unsigned swz
= reg
.swizzle
;
83 reg
.swizzle
= ( BRW_GET_SWZ(swz
, x
) << 0 |
84 BRW_GET_SWZ(swz
, y
) << 2 |
85 BRW_GET_SWZ(swz
, z
) << 4 |
86 BRW_GET_SWZ(swz
, w
) << 6 );
91 static struct brw_fp_src
src_scalar( struct brw_fp_src reg
, int x
)
93 return src_swizzle(reg
, x
, x
, x
, x
);
96 static struct brw_fp_src
src_abs( struct brw_fp_src src
)
103 static struct brw_fp_src
src_negate( struct brw_fp_src src
)
111 static int match_or_expand_immediate( const float *v
,
121 for (i
= 0; i
< nr
; i
++) {
122 boolean found
= FALSE
;
124 for (j
= 0; j
< *nr2
&& !found
; j
++) {
126 *swizzle
|= j
<< (i
* 2);
136 *swizzle
|= *nr2
<< (i
* 2);
146 /* Internally generated immediates: overkill...
148 static struct brw_fp_src
src_imm( struct brw_wm_compile
*c
,
155 /* Could do a first pass where we examine all existing immediates
159 for (i
= 0; i
< c
->nr_immediates
; i
++) {
160 if (match_or_expand_immediate( v
,
168 if (c
->nr_immediates
< Elements(c
->immediate
)) {
169 i
= c
->nr_immediates
++;
170 if (match_or_expand_immediate( v
,
182 /* Make sure that all referenced elements are from this immediate.
183 * Has the effect of making size-one immediates into scalars.
185 for (j
= nr
; j
< 4; j
++)
186 swizzle
|= (swizzle
& 0x3) << (j
* 2);
188 return src_swizzle( src_reg( TGSI_FILE_IMMEDIATE
, i
),
189 BRW_GET_SWZ(swizzle
, X
),
190 BRW_GET_SWZ(swizzle
, Y
),
191 BRW_GET_SWZ(swizzle
, Z
),
192 BRW_GET_SWZ(swizzle
, W
) );
197 static struct brw_fp_src
src_imm1f( struct brw_wm_compile
*c
,
200 return src_imm(c
, &f
, 1);
203 static struct brw_fp_src
src_imm4f( struct brw_wm_compile
*c
,
209 GLfloat f
[4] = {x
,y
,z
,w
};
210 return src_imm(c
, f
, 4);
215 /***********************************************************************
219 static struct brw_fp_dst
dst_reg(GLuint file
, GLuint idx
)
221 struct brw_fp_dst reg
;
224 reg
.writemask
= BRW_WRITEMASK_XYZW
;
230 static struct brw_fp_dst
dst_mask( struct brw_fp_dst reg
, int mask
)
232 reg
.writemask
&= mask
;
236 static struct brw_fp_dst
dst_undef( void )
238 return dst_reg(TGSI_FILE_NULL
, 0);
241 static boolean
dst_is_undef( struct brw_fp_dst dst
)
243 return dst
.file
== TGSI_FILE_NULL
;
246 static struct brw_fp_dst
dst_saturate( struct brw_fp_dst reg
, boolean flag
)
252 static struct brw_fp_dst
get_temp( struct brw_wm_compile
*c
)
254 int bit
= ffs( ~c
->fp_temp
);
257 debug_printf("%s: out of temporaries\n", __FILE__
);
260 c
->fp_temp
|= 1<<(bit
-1);
261 return dst_reg(TGSI_FILE_TEMPORARY
, c
->fp_first_internal_temp
+(bit
-1));
265 static void release_temp( struct brw_wm_compile
*c
, struct brw_fp_dst temp
)
267 c
->fp_temp
&= ~(1 << (temp
.index
- c
->fp_first_internal_temp
));
271 /***********************************************************************
275 static struct brw_fp_instruction
*get_fp_inst(struct brw_wm_compile
*c
)
277 return &c
->fp_instructions
[c
->nr_fp_insns
++];
280 static struct brw_fp_instruction
* emit_tex_op(struct brw_wm_compile
*c
,
282 struct brw_fp_dst dest
,
286 struct brw_fp_src src0
,
287 struct brw_fp_src src1
,
288 struct brw_fp_src src2
)
290 struct brw_fp_instruction
*inst
= get_fp_inst(c
);
292 if (tex_unit
|| target
)
293 assert(op
== TGSI_OPCODE_TXP
||
294 op
== TGSI_OPCODE_TXB
||
295 op
== TGSI_OPCODE_TEX
||
300 inst
->tex_unit
= tex_unit
;
301 inst
->target
= target
;
302 inst
->sampler
= sampler
;
311 static INLINE
void emit_op3(struct brw_wm_compile
*c
,
313 struct brw_fp_dst dest
,
314 struct brw_fp_src src0
,
315 struct brw_fp_src src1
,
316 struct brw_fp_src src2
)
318 emit_tex_op(c
, op
, dest
, 0, 0, 0, src0
, src1
, src2
);
322 static INLINE
void emit_op2(struct brw_wm_compile
*c
,
324 struct brw_fp_dst dest
,
325 struct brw_fp_src src0
,
326 struct brw_fp_src src1
)
328 emit_tex_op(c
, op
, dest
, 0, 0, 0, src0
, src1
, src_undef());
331 static INLINE
void emit_op1(struct brw_wm_compile
*c
,
333 struct brw_fp_dst dest
,
334 struct brw_fp_src src0
)
336 emit_tex_op(c
, op
, dest
, 0, 0, 0, src0
, src_undef(), src_undef());
339 static INLINE
void emit_op0(struct brw_wm_compile
*c
,
341 struct brw_fp_dst dest
)
343 emit_tex_op(c
, op
, dest
, 0, 0, 0, src_undef(), src_undef(), src_undef());
348 /* Many opcodes produce the same value across all the result channels.
349 * We'd rather not have to support that splatting in the opcode implementations,
350 * and brw_wm_pass*.c wants to optimize them out by shuffling references around
351 * anyway. We can easily get both by emitting the opcode to one channel, and
352 * then MOVing it to the others, which brw_wm_pass*.c already understands.
354 static void emit_scalar_insn(struct brw_wm_compile
*c
,
356 struct brw_fp_dst dst
,
357 struct brw_fp_src src0
,
358 struct brw_fp_src src1
,
359 struct brw_fp_src src2
)
361 unsigned first_chan
= ffs(dst
.writemask
) - 1;
362 unsigned first_mask
= 1 << first_chan
;
364 if (dst
.writemask
== 0)
368 dst_mask(dst
, first_mask
),
371 if (dst
.writemask
!= first_mask
) {
372 emit_op1(c
, TGSI_OPCODE_MOV
,
373 dst_mask(dst
, ~first_mask
),
374 src_scalar(src_reg_from_dst(dst
), first_chan
));
379 /***********************************************************************
380 * Special instructions for interpolation and other tasks
383 static struct brw_fp_src
get_pixel_xy( struct brw_wm_compile
*c
)
385 if (src_is_undef(c
->fp_pixel_xy
)) {
386 struct brw_fp_dst pixel_xy
= get_temp(c
);
387 struct brw_fp_src payload_r0_depth
= src_reg(BRW_FILE_PAYLOAD
, PAYLOAD_DEPTH
);
390 /* Emit the out calculations, and hold onto the results. Use
391 * two instructions as a temporary is required.
393 /* pixel_xy.xy = PIXELXY payload[0];
397 dst_mask(pixel_xy
, BRW_WRITEMASK_XY
),
400 c
->fp_pixel_xy
= src_reg_from_dst(pixel_xy
);
403 return c
->fp_pixel_xy
;
406 static struct brw_fp_src
get_delta_xy( struct brw_wm_compile
*c
)
408 if (src_is_undef(c
->fp_delta_xy
)) {
409 struct brw_fp_dst delta_xy
= get_temp(c
);
410 struct brw_fp_src pixel_xy
= get_pixel_xy(c
);
411 struct brw_fp_src payload_r0_depth
= src_reg(BRW_FILE_PAYLOAD
, PAYLOAD_DEPTH
);
413 /* deltas.xy = DELTAXY pixel_xy, payload[0]
417 dst_mask(delta_xy
, BRW_WRITEMASK_XY
),
422 c
->fp_delta_xy
= src_reg_from_dst(delta_xy
);
425 return c
->fp_delta_xy
;
428 static struct brw_fp_src
get_pixel_w( struct brw_wm_compile
*c
)
430 if (src_is_undef(c
->fp_pixel_w
)) {
431 struct brw_fp_dst pixel_w
= get_temp(c
);
432 struct brw_fp_src deltas
= get_delta_xy(c
);
434 /* XXX: assuming position is always first -- valid?
436 struct brw_fp_src interp_wpos
= src_reg(BRW_FILE_PAYLOAD
, 0);
438 /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x
442 dst_mask(pixel_w
, BRW_WRITEMASK_W
),
448 c
->fp_pixel_w
= src_reg_from_dst(pixel_w
);
451 return c
->fp_pixel_w
;
455 /***********************************************************************
456 * Emit INTERP instructions ahead of first use of each attrib.
459 static void emit_interp( struct brw_wm_compile
*c
,
464 struct brw_fp_dst dst
= dst_reg(TGSI_FILE_INPUT
, idx
);
465 struct brw_fp_src interp
= src_reg(BRW_FILE_PAYLOAD
, idx
);
466 struct brw_fp_src deltas
= get_delta_xy(c
);
468 /* Need to use PINTERP on attributes which have been
469 * multiplied by 1/W in the SF program, and LINTERP on those
473 case TGSI_SEMANTIC_POSITION
:
474 /* Have to treat wpos.xy specially:
478 dst_mask(dst
, BRW_WRITEMASK_XY
),
481 /* TGSI_FILE_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
485 dst_mask(dst
, BRW_WRITEMASK_ZW
),
490 case TGSI_SEMANTIC_COLOR
:
491 if (c
->key
.flat_shade
) {
497 else if (interp_mode
== TGSI_INTERPOLATE_LINEAR
) {
515 case TGSI_SEMANTIC_FOG
:
516 /* Interpolate the fog coordinate */
519 dst_mask(dst
, BRW_WRITEMASK_X
),
526 dst_mask(dst
, BRW_WRITEMASK_YZ
),
531 dst_mask(dst
, BRW_WRITEMASK_W
),
535 case TGSI_SEMANTIC_FACE
:
536 /* XXX review/test this case */
539 dst_mask(dst
, BRW_WRITEMASK_X
));
543 dst_mask(dst
, BRW_WRITEMASK_YZ
),
548 dst_mask(dst
, BRW_WRITEMASK_W
),
552 case TGSI_SEMANTIC_PSIZE
:
553 /* XXX review/test this case */
556 dst_mask(dst
, BRW_WRITEMASK_XY
),
563 dst_mask(dst
, BRW_WRITEMASK_Z
),
568 dst_mask(dst
, BRW_WRITEMASK_W
),
573 switch (interp_mode
) {
574 case TGSI_INTERPOLATE_CONSTANT
:
581 case TGSI_INTERPOLATE_LINEAR
:
589 case TGSI_INTERPOLATE_PERSPECTIVE
:
603 /***********************************************************************
604 * Expand various instructions here to simpler forms.
606 static void precalc_dst( struct brw_wm_compile
*c
,
607 struct brw_fp_dst dst
,
608 struct brw_fp_src src0
,
609 struct brw_fp_src src1
)
611 if (dst
.writemask
& BRW_WRITEMASK_Y
) {
612 /* dst.y = mul src0.y, src1.y
616 dst_mask(dst
, BRW_WRITEMASK_Y
),
621 if (dst
.writemask
& BRW_WRITEMASK_XZ
) {
622 /* dst.z = mov src0.zzzz
626 dst_mask(dst
, BRW_WRITEMASK_Z
),
627 src_scalar(src0
, Z
));
629 /* dst.x = imm1f(1.0)
633 dst_saturate(dst_mask(dst
, BRW_WRITEMASK_X
), 0),
636 if (dst
.writemask
& BRW_WRITEMASK_W
) {
637 /* dst.w = mov src1.w
641 dst_mask(dst
, BRW_WRITEMASK_W
),
647 static void precalc_lit( struct brw_wm_compile
*c
,
648 struct brw_fp_dst dst
,
649 struct brw_fp_src src0
)
651 if (dst
.writemask
& BRW_WRITEMASK_XW
) {
652 /* dst.xw = imm(1.0f)
656 dst_saturate(dst_mask(dst
, BRW_WRITEMASK_XW
), 0),
660 if (dst
.writemask
& BRW_WRITEMASK_YZ
) {
663 dst_mask(dst
, BRW_WRITEMASK_YZ
),
670 * Some TEX instructions require extra code, cube map coordinate
671 * normalization, or coordinate scaling for RECT textures, etc.
672 * This function emits those extra instructions and the TEX
673 * instruction itself.
675 static void precalc_tex( struct brw_wm_compile
*c
,
676 struct brw_fp_dst dst
,
679 struct brw_fp_src src0
,
680 struct brw_fp_src sampler
)
682 struct brw_fp_src coord
= src_undef();
683 struct brw_fp_dst tmp
= dst_undef();
685 assert(unit
< BRW_MAX_TEX_UNIT
);
687 /* Cubemap: find longest component of coord vector and normalize
690 if (target
== TGSI_TEXTURE_CUBE
) {
691 struct brw_fp_src tmpsrc
;
694 tmpsrc
= src_reg_from_dst(tmp
);
696 /* tmp = abs(src0) */
702 /* tmp.X = MAX(tmp.X, tmp.Y) */
703 emit_op2(c
, TGSI_OPCODE_MAX
,
704 dst_mask(tmp
, BRW_WRITEMASK_X
),
705 src_scalar(tmpsrc
, X
),
706 src_scalar(tmpsrc
, Y
));
708 /* tmp.X = MAX(tmp.X, tmp.Z) */
709 emit_op2(c
, TGSI_OPCODE_MAX
,
710 dst_mask(tmp
, BRW_WRITEMASK_X
),
712 src_scalar(tmpsrc
, Z
));
714 /* tmp.X = 1 / tmp.X */
715 emit_op1(c
, TGSI_OPCODE_RCP
,
716 dst_mask(tmp
, BRW_WRITEMASK_X
),
719 /* tmp = src0 * tmp.xxxx */
720 emit_op2(c
, TGSI_OPCODE_MUL
,
723 src_scalar(tmpsrc
, X
));
727 else if (target
== TGSI_TEXTURE_RECT
||
728 target
== TGSI_TEXTURE_SHADOWRECT
) {
729 /* XXX: need a mechanism for internally generated constants.
737 /* Need to emit YUV texture conversions by hand. Probably need to
738 * do this here - the alternative is in brw_wm_emit.c, but the
739 * conversion requires allocating a temporary variable which we
740 * don't have the facility to do that late in the compilation.
742 if (c
->key
.yuvtex_mask
& (1 << unit
)) {
743 /* convert ycbcr to RGBA */
744 GLboolean swap_uv
= c
->key
.yuvtex_swap_mask
& (1<<unit
);
745 struct brw_fp_dst tmp
= get_temp(c
);
746 struct brw_fp_src tmpsrc
= src_reg_from_dst(tmp
);
747 struct brw_fp_src C0
= src_imm4f( c
, -.5, -.0625, -.5, 1.164 );
748 struct brw_fp_src C1
= src_imm4f( c
, 1.596, -0.813, 2.018, -.391 );
754 dst_saturate(tmp
, dst
.saturate
),
762 /* tmp.xyz = ADD TMP, C0
764 emit_op2(c
, TGSI_OPCODE_ADD
,
765 dst_mask(tmp
, BRW_WRITEMASK_XYZ
),
769 /* YUV.y = MUL YUV.y, C0.w
771 emit_op2(c
, TGSI_OPCODE_MUL
,
772 dst_mask(tmp
, BRW_WRITEMASK_Y
),
778 * RGB.xyz = MAD YUV.zzx, C1, YUV.y
780 * RGB.xyz = MAD YUV.xxz, C1, YUV.y
783 emit_op3(c
, TGSI_OPCODE_MAD
,
784 dst_mask(dst
, BRW_WRITEMASK_XYZ
),
786 src_swizzle(tmpsrc
, Z
,Z
,X
,X
) :
787 src_swizzle(tmpsrc
, X
,X
,Z
,Z
)),
789 src_scalar(tmpsrc
, Y
));
791 /* RGB.y = MAD YUV.z, C1.w, RGB.y
795 dst_mask(dst
, BRW_WRITEMASK_Y
),
796 src_scalar(tmpsrc
, Z
),
798 src_scalar(src_reg_from_dst(dst
), Y
));
800 release_temp(c
, tmp
);
803 /* ordinary RGBA tex instruction */
815 /* XXX: add GL_EXT_texture_swizzle support to gallium -- by
816 * generating shader varients in mesa state tracker.
819 /* Release this temp if we ended up allocating it:
821 if (!dst_is_undef(tmp
))
822 release_temp(c
, tmp
);
827 * Check if the given TXP instruction really needs the divide-by-W step.
829 static GLboolean
projtex( struct brw_wm_compile
*c
,
831 struct brw_fp_src src
)
833 /* Only try to detect the simplest cases. Could detect (later)
834 * cases where we are trying to emit code like RCP {1.0}, MUL x,
837 * More complex cases than this typically only arise from
838 * user-provided fragment programs anyway:
840 if (target
== TGSI_TEXTURE_CUBE
)
841 return GL_FALSE
; /* ut2004 gun rendering !?! */
843 if (src
.file
== TGSI_FILE_INPUT
&&
844 BRW_GET_SWZ(src
.swizzle
, W
) == W
&&
845 c
->fp
->info
.input_interpolate
[src
.index
] != TGSI_INTERPOLATE_PERSPECTIVE
)
855 static void precalc_txp( struct brw_wm_compile
*c
,
856 struct brw_fp_dst dst
,
859 struct brw_fp_src src0
,
860 struct brw_fp_src sampler
)
862 if (projtex(c
, target
, src0
)) {
863 struct brw_fp_dst tmp
= get_temp(c
);
865 /* tmp0.w = RCP inst.arg[0][3]
869 dst_mask(tmp
, BRW_WRITEMASK_W
),
870 src_scalar(src0
, W
));
872 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww
876 dst_mask(tmp
, BRW_WRITEMASK_XYZ
),
878 src_scalar(src_reg_from_dst(tmp
), W
));
886 src_reg_from_dst(tmp
),
889 release_temp(c
, tmp
);
895 precalc_tex(c
, dst
, target
, unit
, src0
, sampler
);
900 /* XXX: note this returns a src_reg.
902 static struct brw_fp_src
903 find_output_by_semantic( struct brw_wm_compile
*c
,
907 const struct tgsi_shader_info
*info
= &c
->fp
->info
;
910 for (i
= 0; i
< info
->num_outputs
; i
++)
911 if (info
->output_semantic_name
[i
] == semantic
&&
912 info
->output_semantic_index
[i
] == index
)
913 return src_reg( TGSI_FILE_OUTPUT
, i
);
915 /* If not found, return some arbitrary immediate value:
917 * XXX: this is a good idea but immediates are up generating extra
918 * curbe entries atm, as they would have in the original driver.
920 return src_reg( TGSI_FILE_OUTPUT
, 0 ); /* src_imm1f(c, 1.0); */
924 static void emit_fb_write( struct brw_wm_compile
*c
)
926 struct brw_fp_src payload_r0_depth
= src_reg(BRW_FILE_PAYLOAD
, PAYLOAD_DEPTH
);
927 struct brw_fp_src outdepth
= find_output_by_semantic(c
, TGSI_SEMANTIC_POSITION
, 0);
931 outdepth
= src_scalar(outdepth
, Z
);
933 for (i
= 0 ; i
< c
->key
.nr_cbufs
; i
++) {
934 struct brw_fp_src outcolor
;
936 outcolor
= find_output_by_semantic(c
, TGSI_SEMANTIC_COLOR
, i
);
938 /* Use emit_tex_op so that we can specify the inst->target
939 * field, which is abused to contain the FB write target and the
942 emit_tex_op(c
, WM_FB_WRITE
,
944 (i
== c
->key
.nr_cbufs
- 1), /* EOT */
954 static struct brw_fp_dst
translate_dst( struct brw_wm_compile
*c
,
955 const struct tgsi_full_dst_register
*dst
,
958 struct brw_fp_dst out
;
960 out
.file
= dst
->DstRegister
.File
;
961 out
.index
= dst
->DstRegister
.Index
;
962 out
.writemask
= dst
->DstRegister
.WriteMask
;
963 out
.indirect
= dst
->DstRegister
.Indirect
;
964 out
.saturate
= (saturate
== TGSI_SAT_ZERO_ONE
);
967 assert(dst
->DstRegisterInd
.File
== TGSI_FILE_ADDRESS
);
968 assert(dst
->DstRegisterInd
.Index
== 0);
975 static struct brw_fp_src
translate_src( struct brw_wm_compile
*c
,
976 const struct tgsi_full_src_register
*src
)
978 struct brw_fp_src out
;
980 out
.file
= src
->SrcRegister
.File
;
981 out
.index
= src
->SrcRegister
.Index
;
982 out
.indirect
= src
->SrcRegister
.Indirect
;
984 out
.swizzle
= ((src
->SrcRegister
.SwizzleX
<< 0) |
985 (src
->SrcRegister
.SwizzleY
<< 2) |
986 (src
->SrcRegister
.SwizzleZ
<< 4) |
987 (src
->SrcRegister
.SwizzleW
<< 6));
989 switch (tgsi_util_get_full_src_register_sign_mode( src
, 0 )) {
990 case TGSI_UTIL_SIGN_CLEAR
:
995 case TGSI_UTIL_SIGN_SET
:
1000 case TGSI_UTIL_SIGN_TOGGLE
:
1005 case TGSI_UTIL_SIGN_KEEP
:
1013 assert(src
->SrcRegisterInd
.File
== TGSI_FILE_ADDRESS
);
1014 assert(src
->SrcRegisterInd
.Index
== 0);
1022 static void emit_insn( struct brw_wm_compile
*c
,
1023 const struct tgsi_full_instruction
*inst
)
1025 unsigned opcode
= inst
->Instruction
.Opcode
;
1026 struct brw_fp_dst dst
;
1027 struct brw_fp_src src
[3];
1030 dst
= translate_dst( c
, &inst
->FullDstRegisters
[0],
1031 inst
->Instruction
.Saturate
);
1033 for (i
= 0; i
< inst
->Instruction
.NumSrcRegs
; i
++)
1034 src
[i
] = translate_src( c
, &inst
->FullSrcRegisters
[i
] );
1037 case TGSI_OPCODE_ABS
:
1038 emit_op1(c
, TGSI_OPCODE_MOV
,
1043 case TGSI_OPCODE_SUB
:
1044 emit_op2(c
, TGSI_OPCODE_ADD
,
1047 src_negate(src
[1]));
1050 case TGSI_OPCODE_SCS
:
1051 emit_op1(c
, TGSI_OPCODE_SCS
,
1052 dst_mask(dst
, BRW_WRITEMASK_XY
),
1056 case TGSI_OPCODE_DST
:
1057 precalc_dst(c
, dst
, src
[0], src
[1]);
1060 case TGSI_OPCODE_LIT
:
1061 precalc_lit(c
, dst
, src
[0]);
1064 case TGSI_OPCODE_TEX
:
1066 inst
->InstructionExtTexture
.Texture
,
1067 src
[1].index
, /* use sampler unit for tex idx */
1069 src
[1]); /* sampler */
1072 case TGSI_OPCODE_TXP
:
1074 inst
->InstructionExtTexture
.Texture
,
1075 src
[1].index
, /* use sampler unit for tex idx */
1077 src
[1]); /* sampler */
1080 case TGSI_OPCODE_TXB
:
1081 /* XXX: TXB not done
1084 inst
->InstructionExtTexture
.Texture
,
1085 src
[1].index
, /* use sampler unit for tex idx*/
1090 case TGSI_OPCODE_XPD
:
1091 emit_op2(c
, TGSI_OPCODE_XPD
,
1092 dst_mask(dst
, BRW_WRITEMASK_XYZ
),
1097 case TGSI_OPCODE_KIL
:
1098 emit_op1(c
, TGSI_OPCODE_KIL
,
1099 dst_mask(dst_undef(), 0),
1103 case TGSI_OPCODE_END
:
1107 if (!c
->key
.has_flow_control
&&
1108 brw_wm_is_scalar_result(opcode
))
1109 emit_scalar_insn(c
, opcode
, dst
, src
[0], src
[1], src
[2]);
1111 emit_op3(c
, opcode
, dst
, src
[0], src
[1], src
[2]);
1117 * Initial pass for fragment program code generation.
1118 * This function is used by both the GLSL and non-GLSL paths.
1120 int brw_wm_pass_fp( struct brw_wm_compile
*c
)
1122 struct brw_fragment_shader
*fs
= c
->fp
;
1123 struct tgsi_parse_context parse
;
1124 struct tgsi_full_instruction
*inst
;
1125 struct tgsi_full_declaration
*decl
;
1130 if (BRW_DEBUG
& DEBUG_WM
) {
1131 debug_printf("pre-fp:\n");
1132 tgsi_dump(fs
->tokens
, 0);
1135 c
->fp_pixel_xy
= src_undef();
1136 c
->fp_delta_xy
= src_undef();
1137 c
->fp_pixel_w
= src_undef();
1139 c
->nr_immediates
= 0;
1142 /* Loop over all instructions doing assorted simplifications and
1145 tgsi_parse_init( &parse
, fs
->tokens
);
1146 while( !tgsi_parse_end_of_tokens( &parse
) ) {
1147 tgsi_parse_token( &parse
);
1149 switch( parse
.FullToken
.Token
.Type
) {
1150 case TGSI_TOKEN_TYPE_DECLARATION
:
1151 /* Turn intput declarations into special WM_* instructions.
1153 * XXX: For non-branching shaders, consider deferring variable
1154 * initialization as late as possible to minimize register
1155 * usage. This is how the original BRW driver worked.
1157 * In a branching shader, must preamble instructions at decl
1158 * time, as instruction order in the shader does not
1159 * correspond to the order instructions are executed in the
1162 * This is where special instructions such as WM_CINTERP,
1163 * WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
1164 * compute shader inputs from the payload registers and pixel
1167 decl
= &parse
.FullToken
.FullDeclaration
;
1168 if( decl
->Declaration
.File
== TGSI_FILE_INPUT
) {
1169 unsigned first
, last
, mask
;
1172 first
= decl
->DeclarationRange
.First
;
1173 last
= decl
->DeclarationRange
.Last
;
1174 mask
= decl
->Declaration
.UsageMask
;
1176 for (attrib
= first
; attrib
<= last
; attrib
++) {
1179 decl
->Semantic
.SemanticName
,
1180 decl
->Declaration
.Interpolate
);
1186 case TGSI_TOKEN_TYPE_IMMEDIATE
:
1187 /* Unlike VS programs we can probably manage fine encoding
1188 * immediate values directly into the emitted EU
1189 * instructions, as we probably only need to reference one
1190 * float value per instruction. Just save the data for now
1191 * and use directly later.
1193 i
= c
->nr_immediates
++;
1194 imm
= &parse
.FullToken
.FullImmediate
.u
[i
].Float
;
1195 size
= parse
.FullToken
.FullImmediate
.Immediate
.NrTokens
- 1;
1197 if (c
->nr_immediates
>= BRW_WM_MAX_CONST
)
1198 return PIPE_ERROR_OUT_OF_MEMORY
;
1200 for (i
= 0; i
< size
; i
++)
1201 c
->immediate
[c
->nr_immediates
].v
[i
] = imm
[i
];
1204 c
->immediate
[c
->nr_immediates
].v
[i
] = 0.0;
1206 c
->immediate
[c
->nr_immediates
].nr
= size
;
1210 case TGSI_TOKEN_TYPE_INSTRUCTION
:
1211 inst
= &parse
.FullToken
.FullInstruction
;
1217 if (BRW_DEBUG
& DEBUG_WM
) {
1218 brw_wm_print_fp_program( c
, "pass_fp" );