2 * Copyright (C) 2016 Miklós Máté
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #include "main/mtypes.h"
24 #include "main/atifragshader.h"
25 #include "main/errors.h"
26 #include "program/prog_parameter.h"
28 #include "tgsi/tgsi_ureg.h"
29 #include "tgsi/tgsi_scan.h"
30 #include "tgsi/tgsi_transform.h"
32 #include "st_program.h"
33 #include "st_atifs_to_tgsi.h"
36 * Intermediate state used during shader translation.
39 struct ureg_program
*ureg
;
40 struct ati_fragment_shader
*atifs
;
42 struct ureg_dst temps
[MAX_PROGRAM_TEMPS
];
43 struct ureg_src
*constants
;
44 struct ureg_dst outputs
[PIPE_MAX_SHADER_OUTPUTS
];
45 struct ureg_src inputs
[PIPE_MAX_SHADER_INPUTS
];
46 struct ureg_src samplers
[PIPE_MAX_SAMPLERS
];
48 const GLuint
*inputMapping
;
49 const GLuint
*outputMapping
;
51 unsigned current_pass
;
53 bool regs_written
[MAX_NUM_PASSES_ATI
][MAX_NUM_FRAGMENT_REGISTERS_ATI
];
58 struct instruction_desc
{
61 unsigned char arg_count
;
64 static const struct instruction_desc inst_desc
[] = {
65 {TGSI_OPCODE_MOV
, "MOV", 1},
66 {TGSI_OPCODE_NOP
, "UND", 0}, /* unused */
67 {TGSI_OPCODE_ADD
, "ADD", 2},
68 {TGSI_OPCODE_MUL
, "MUL", 2},
69 {TGSI_OPCODE_SUB
, "SUB", 2},
70 {TGSI_OPCODE_DP3
, "DOT3", 2},
71 {TGSI_OPCODE_DP4
, "DOT4", 2},
72 {TGSI_OPCODE_MAD
, "MAD", 3},
73 {TGSI_OPCODE_LRP
, "LERP", 3},
74 {TGSI_OPCODE_NOP
, "CND", 3},
75 {TGSI_OPCODE_NOP
, "CND0", 3},
76 {TGSI_OPCODE_NOP
, "DOT2_ADD", 3}
79 static struct ureg_dst
80 get_temp(struct st_translate
*t
, unsigned index
)
82 if (ureg_dst_is_undef(t
->temps
[index
]))
83 t
->temps
[index
] = ureg_DECL_temporary(t
->ureg
);
84 return t
->temps
[index
];
87 static struct ureg_src
88 apply_swizzle(struct st_translate
*t
,
89 struct ureg_src src
, GLuint swizzle
)
91 if (swizzle
== GL_SWIZZLE_STR_ATI
) {
93 } else if (swizzle
== GL_SWIZZLE_STQ_ATI
) {
94 return ureg_swizzle(src
,
100 struct ureg_dst tmp
[2];
101 struct ureg_src imm
[3];
103 tmp
[0] = get_temp(t
, MAX_NUM_FRAGMENT_REGISTERS_ATI
);
104 tmp
[1] = get_temp(t
, MAX_NUM_FRAGMENT_REGISTERS_ATI
+ 1);
106 imm
[1] = ureg_imm4f(t
->ureg
, 1.0f
, 1.0f
, 0.0f
, 0.0f
);
107 imm
[2] = ureg_imm4f(t
->ureg
, 0.0f
, 0.0f
, 1.0f
, 1.0f
);
108 ureg_insn(t
->ureg
, TGSI_OPCODE_MAD
, &tmp
[0], 1, imm
, 3);
110 if (swizzle
== GL_SWIZZLE_STR_DR_ATI
) {
111 imm
[0] = ureg_scalar(src
, TGSI_SWIZZLE_Z
);
113 imm
[0] = ureg_scalar(src
, TGSI_SWIZZLE_W
);
115 ureg_insn(t
->ureg
, TGSI_OPCODE_RCP
, &tmp
[1], 1, &imm
[0], 1);
117 imm
[0] = ureg_src(tmp
[0]);
118 imm
[1] = ureg_src(tmp
[1]);
119 ureg_insn(t
->ureg
, TGSI_OPCODE_MUL
, &tmp
[0], 1, imm
, 2);
121 return ureg_src(tmp
[0]);
125 static struct ureg_src
126 get_source(struct st_translate
*t
, GLuint src_type
)
128 if (src_type
>= GL_REG_0_ATI
&& src_type
<= GL_REG_5_ATI
) {
129 if (t
->regs_written
[t
->current_pass
][src_type
- GL_REG_0_ATI
]) {
130 return ureg_src(get_temp(t
, src_type
- GL_REG_0_ATI
));
132 return ureg_imm1f(t
->ureg
, 0.0f
);
134 } else if (src_type
>= GL_CON_0_ATI
&& src_type
<= GL_CON_7_ATI
) {
135 return t
->constants
[src_type
- GL_CON_0_ATI
];
136 } else if (src_type
== GL_ZERO
) {
137 return ureg_imm1f(t
->ureg
, 0.0f
);
138 } else if (src_type
== GL_ONE
) {
139 return ureg_imm1f(t
->ureg
, 1.0f
);
140 } else if (src_type
== GL_PRIMARY_COLOR_ARB
) {
141 return t
->inputs
[t
->inputMapping
[VARYING_SLOT_COL0
]];
142 } else if (src_type
== GL_SECONDARY_INTERPOLATOR_ATI
) {
143 return t
->inputs
[t
->inputMapping
[VARYING_SLOT_COL1
]];
145 /* frontend prevents this */
146 unreachable("unknown source");
150 static struct ureg_src
151 prepare_argument(struct st_translate
*t
, const unsigned argId
,
152 const struct atifragshader_src_register
*srcReg
)
154 struct ureg_src src
= get_source(t
, srcReg
->Index
);
155 struct ureg_dst arg
= get_temp(t
, MAX_NUM_FRAGMENT_REGISTERS_ATI
+ argId
);
157 switch (srcReg
->argRep
) {
161 src
= ureg_scalar(src
, TGSI_SWIZZLE_X
);
164 src
= ureg_scalar(src
, TGSI_SWIZZLE_Y
);
167 src
= ureg_scalar(src
, TGSI_SWIZZLE_Z
);
170 src
= ureg_scalar(src
, TGSI_SWIZZLE_W
);
173 ureg_insn(t
->ureg
, TGSI_OPCODE_MOV
, &arg
, 1, &src
, 1);
175 if (srcReg
->argMod
& GL_COMP_BIT_ATI
) {
176 struct ureg_src modsrc
[2];
177 modsrc
[0] = ureg_imm1f(t
->ureg
, 1.0f
);
178 modsrc
[1] = ureg_src(arg
);
180 ureg_insn(t
->ureg
, TGSI_OPCODE_SUB
, &arg
, 1, modsrc
, 2);
182 if (srcReg
->argMod
& GL_BIAS_BIT_ATI
) {
183 struct ureg_src modsrc
[2];
184 modsrc
[0] = ureg_src(arg
);
185 modsrc
[1] = ureg_imm1f(t
->ureg
, 0.5f
);
187 ureg_insn(t
->ureg
, TGSI_OPCODE_SUB
, &arg
, 1, modsrc
, 2);
189 if (srcReg
->argMod
& GL_2X_BIT_ATI
) {
190 struct ureg_src modsrc
[2];
191 modsrc
[0] = ureg_src(arg
);
192 modsrc
[1] = ureg_src(arg
);
194 ureg_insn(t
->ureg
, TGSI_OPCODE_ADD
, &arg
, 1, modsrc
, 2);
196 if (srcReg
->argMod
& GL_NEGATE_BIT_ATI
) {
197 struct ureg_src modsrc
[2];
198 modsrc
[0] = ureg_src(arg
);
199 modsrc
[1] = ureg_imm1f(t
->ureg
, -1.0f
);
201 ureg_insn(t
->ureg
, TGSI_OPCODE_MUL
, &arg
, 1, modsrc
, 2);
203 return ureg_src(arg
);
206 /* These instructions need special treatment */
208 emit_special_inst(struct st_translate
*t
, const struct instruction_desc
*desc
,
209 struct ureg_dst
*dst
, struct ureg_src
*args
, unsigned argcount
)
211 struct ureg_dst tmp
[1];
212 struct ureg_src src
[3];
214 if (!strcmp(desc
->name
, "CND")) {
215 tmp
[0] = get_temp(t
, MAX_NUM_FRAGMENT_REGISTERS_ATI
+ 2); /* re-purpose a3 */
216 src
[0] = ureg_imm1f(t
->ureg
, 0.5f
);
218 ureg_insn(t
->ureg
, TGSI_OPCODE_SUB
, tmp
, 1, src
, 2);
219 src
[0] = ureg_src(tmp
[0]);
222 ureg_insn(t
->ureg
, TGSI_OPCODE_CMP
, dst
, 1, src
, 3);
223 } else if (!strcmp(desc
->name
, "CND0")) {
227 ureg_insn(t
->ureg
, TGSI_OPCODE_CMP
, dst
, 1, src
, 3);
228 } else if (!strcmp(desc
->name
, "DOT2_ADD")) {
229 /* note: DP2A is not implemented in most pipe drivers */
230 tmp
[0] = get_temp(t
, MAX_NUM_FRAGMENT_REGISTERS_ATI
); /* re-purpose a1 */
233 ureg_insn(t
->ureg
, TGSI_OPCODE_DP2
, tmp
, 1, src
, 2);
234 src
[0] = ureg_src(tmp
[0]);
235 src
[1] = ureg_scalar(args
[2], TGSI_SWIZZLE_Z
);
236 ureg_insn(t
->ureg
, TGSI_OPCODE_ADD
, dst
, 1, src
, 2);
241 emit_arith_inst(struct st_translate
*t
,
242 const struct instruction_desc
*desc
,
243 struct ureg_dst
*dst
, struct ureg_src
*args
, unsigned argcount
)
245 if (desc
->TGSI_opcode
== TGSI_OPCODE_NOP
) {
246 return emit_special_inst(t
, desc
, dst
, args
, argcount
);
249 ureg_insn(t
->ureg
, desc
->TGSI_opcode
, dst
, 1, args
, argcount
);
253 emit_dstmod(struct st_translate
*t
,
254 struct ureg_dst dst
, GLuint dstMod
)
257 struct ureg_src src
[3];
258 GLuint scale
= dstMod
& ~GL_SATURATE_BIT_ATI
;
260 if (dstMod
== GL_NONE
) {
274 case GL_HALF_BIT_ATI
:
277 case GL_QUARTER_BIT_ATI
:
280 case GL_EIGHTH_BIT_ATI
:
287 src
[0] = ureg_src(dst
);
288 src
[1] = ureg_imm1f(t
->ureg
, imm
);
289 if (dstMod
& GL_SATURATE_BIT_ATI
) {
290 dst
= ureg_saturate(dst
);
292 ureg_insn(t
->ureg
, TGSI_OPCODE_MUL
, &dst
, 1, src
, 2);
296 * Compile one setup instruction to TGSI instructions.
299 compile_setupinst(struct st_translate
*t
,
301 const struct atifs_setupinst
*texinst
)
303 struct ureg_dst dst
[1];
304 struct ureg_src src
[2];
306 if (!texinst
->Opcode
)
309 dst
[0] = get_temp(t
, r
);
311 GLuint pass_tex
= texinst
->src
;
313 if (pass_tex
>= GL_TEXTURE0_ARB
&& pass_tex
<= GL_TEXTURE7_ARB
) {
314 unsigned attr
= pass_tex
- GL_TEXTURE0_ARB
+ VARYING_SLOT_TEX0
;
316 src
[0] = t
->inputs
[t
->inputMapping
[attr
]];
317 } else if (pass_tex
>= GL_REG_0_ATI
&& pass_tex
<= GL_REG_5_ATI
) {
318 unsigned reg
= pass_tex
- GL_REG_0_ATI
;
320 /* the frontend already validated that REG is only allowed in second pass */
321 if (t
->regs_written
[0][reg
]) {
322 src
[0] = ureg_src(t
->temps
[reg
]);
324 src
[0] = ureg_imm1f(t
->ureg
, 0.0f
);
327 src
[0] = apply_swizzle(t
, src
[0], texinst
->swizzle
);
329 if (texinst
->Opcode
== ATI_FRAGMENT_SHADER_SAMPLE_OP
) {
330 /* by default texture and sampler indexes are the same */
331 src
[1] = t
->samplers
[r
];
332 /* the texture target is still unknown, it will be fixed in the draw call */
333 ureg_tex_insn(t
->ureg
, TGSI_OPCODE_TEX
, dst
, 1, TGSI_TEXTURE_2D
,
335 } else if (texinst
->Opcode
== ATI_FRAGMENT_SHADER_PASS_OP
) {
336 ureg_insn(t
->ureg
, TGSI_OPCODE_MOV
, dst
, 1, src
, 1);
339 t
->regs_written
[t
->current_pass
][r
] = true;
343 * Compile one arithmetic operation COLOR&ALPHA pair into TGSI instructions.
346 compile_instruction(struct st_translate
*t
,
347 const struct atifs_instruction
*inst
)
351 for (optype
= 0; optype
< 2; optype
++) { /* color, alpha */
352 const struct instruction_desc
*desc
;
353 struct ureg_dst dst
[1];
354 struct ureg_src args
[3]; /* arguments for the main operation */
356 unsigned dstreg
= inst
->DstReg
[optype
].Index
- GL_REG_0_ATI
;
358 if (!inst
->Opcode
[optype
])
361 desc
= &inst_desc
[inst
->Opcode
[optype
] - GL_MOV_ATI
];
363 /* prepare the arguments */
364 for (arg
= 0; arg
< desc
->arg_count
; arg
++) {
365 if (arg
>= inst
->ArgCount
[optype
]) {
366 _mesa_warning(0, "Using 0 for missing argument %d of %s\n",
368 args
[arg
] = ureg_imm1f(t
->ureg
, 0.0f
);
370 args
[arg
] = prepare_argument(t
, arg
,
371 &inst
->SrcReg
[optype
][arg
]);
376 dst
[0] = get_temp(t
, dstreg
);
379 dst
[0] = ureg_writemask(dst
[0], TGSI_WRITEMASK_W
);
381 GLuint dstMask
= inst
->DstReg
[optype
].dstMask
;
382 if (dstMask
== GL_NONE
) {
383 dst
[0] = ureg_writemask(dst
[0], TGSI_WRITEMASK_XYZ
);
385 dst
[0] = ureg_writemask(dst
[0], dstMask
); /* the enum values match */
389 /* emit the main instruction */
390 emit_arith_inst(t
, desc
, dst
, args
, arg
);
392 emit_dstmod(t
, *dst
, inst
->DstReg
[optype
].dstMod
);
394 t
->regs_written
[t
->current_pass
][dstreg
] = true;
399 finalize_shader(struct st_translate
*t
, unsigned numPasses
)
401 struct ureg_dst dst
[1] = { { 0 } };
402 struct ureg_src src
[1] = { { 0 } };
404 if (t
->regs_written
[numPasses
-1][0]) {
405 /* copy the result into the OUT slot */
406 dst
[0] = t
->outputs
[t
->outputMapping
[FRAG_RESULT_COLOR
]];
407 src
[0] = ureg_src(t
->temps
[0]);
408 ureg_insn(t
->ureg
, TGSI_OPCODE_MOV
, dst
, 1, src
, 1);
411 /* signal the end of the program */
412 ureg_insn(t
->ureg
, TGSI_OPCODE_END
, dst
, 0, src
, 0);
416 * Called when a new variant is needed, we need to translate
417 * the ATI fragment shader to TGSI
420 st_translate_atifs_program(
421 struct ureg_program
*ureg
,
422 struct ati_fragment_shader
*atifs
,
423 struct gl_program
*program
,
425 const GLuint inputMapping
[],
426 const ubyte inputSemanticName
[],
427 const ubyte inputSemanticIndex
[],
428 const GLuint interpMode
[],
430 const GLuint outputMapping
[],
431 const ubyte outputSemanticName
[],
432 const ubyte outputSemanticIndex
[])
434 enum pipe_error ret
= PIPE_OK
;
438 struct st_translate translate
, *t
;
440 memset(t
, 0, sizeof *t
);
442 t
->inputMapping
= inputMapping
;
443 t
->outputMapping
= outputMapping
;
448 * Declare input attributes.
450 for (i
= 0; i
< numInputs
; i
++) {
451 t
->inputs
[i
] = ureg_DECL_fs_input(ureg
,
452 inputSemanticName
[i
],
453 inputSemanticIndex
[i
],
458 * Declare output attributes:
459 * we always have numOutputs=1 and it's FRAG_RESULT_COLOR
461 t
->outputs
[0] = ureg_DECL_output(ureg
,
463 outputSemanticIndex
[0]);
465 /* Emit constants and immediates. Mesa uses a single index space
466 * for these, so we put all the translated regs in t->constants.
468 if (program
->Parameters
) {
469 t
->constants
= calloc(program
->Parameters
->NumParameters
,
470 sizeof t
->constants
[0]);
471 if (t
->constants
== NULL
) {
472 ret
= PIPE_ERROR_OUT_OF_MEMORY
;
476 for (i
= 0; i
< program
->Parameters
->NumParameters
; i
++) {
477 switch (program
->Parameters
->Parameters
[i
].Type
) {
478 case PROGRAM_STATE_VAR
:
479 case PROGRAM_UNIFORM
:
480 t
->constants
[i
] = ureg_DECL_constant(ureg
, i
);
482 case PROGRAM_CONSTANT
:
484 ureg_DECL_immediate(ureg
,
485 (const float*)program
->Parameters
->ParameterValues
[i
],
494 /* texture samplers */
495 for (i
= 0; i
< MAX_NUM_FRAGMENT_REGISTERS_ATI
; i
++) {
496 if (program
->SamplersUsed
& (1 << i
)) {
497 t
->samplers
[i
] = ureg_DECL_sampler(ureg
, i
);
498 /* the texture target is still unknown, it will be fixed in the draw call */
499 ureg_DECL_sampler_view(ureg
, i
, TGSI_TEXTURE_2D
,
500 TGSI_RETURN_TYPE_FLOAT
,
501 TGSI_RETURN_TYPE_FLOAT
,
502 TGSI_RETURN_TYPE_FLOAT
,
503 TGSI_RETURN_TYPE_FLOAT
);
507 /* emit instructions */
508 for (pass
= 0; pass
< atifs
->NumPasses
; pass
++) {
509 t
->current_pass
= pass
;
510 for (r
= 0; r
< MAX_NUM_FRAGMENT_REGISTERS_ATI
; r
++) {
511 struct atifs_setupinst
*texinst
= &atifs
->SetupInst
[pass
][r
];
512 compile_setupinst(t
, r
, texinst
);
514 for (i
= 0; i
< atifs
->numArithInstr
[pass
]; i
++) {
515 struct atifs_instruction
*inst
= &atifs
->Instructions
[pass
][i
];
516 compile_instruction(t
, inst
);
520 finalize_shader(t
, atifs
->NumPasses
);
526 debug_printf("%s: translate error flag set\n", __func__
);
533 * Called in ProgramStringNotify, we need to fill the metadata of the
534 * gl_program attached to the ati_fragment_shader
537 st_init_atifs_prog(struct gl_context
*ctx
, struct gl_program
*prog
)
539 /* we know this is st_fragment_program, because of st_new_ati_fs() */
540 struct st_fragment_program
*stfp
= (struct st_fragment_program
*) prog
;
541 struct ati_fragment_shader
*atifs
= stfp
->ati_fs
;
543 unsigned pass
, i
, r
, optype
, arg
;
545 static const gl_state_index fog_params_state
[STATE_LENGTH
] =
546 {STATE_INTERNAL
, STATE_FOG_PARAMS_OPTIMIZED
, 0, 0, 0};
547 static const gl_state_index fog_color
[STATE_LENGTH
] =
548 {STATE_FOG_COLOR
, 0, 0, 0, 0};
550 prog
->info
.inputs_read
= 0;
551 prog
->OutputsWritten
= BITFIELD64_BIT(FRAG_RESULT_COLOR
);
552 prog
->SamplersUsed
= 0;
553 prog
->Parameters
= _mesa_new_parameter_list();
555 /* fill in inputs_read, SamplersUsed, TexturesUsed */
556 for (pass
= 0; pass
< atifs
->NumPasses
; pass
++) {
557 for (r
= 0; r
< MAX_NUM_FRAGMENT_REGISTERS_ATI
; r
++) {
558 struct atifs_setupinst
*texinst
= &atifs
->SetupInst
[pass
][r
];
559 GLuint pass_tex
= texinst
->src
;
561 if (texinst
->Opcode
== ATI_FRAGMENT_SHADER_SAMPLE_OP
) {
562 /* mark which texcoords are used */
563 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_TEX0
+ pass_tex
- GL_TEXTURE0_ARB
);
564 /* by default there is 1:1 mapping between samplers and textures */
565 prog
->SamplersUsed
|= (1 << r
);
566 /* the target is unknown here, it will be fixed in the draw call */
567 prog
->TexturesUsed
[r
] = TEXTURE_2D_BIT
;
568 } else if (texinst
->Opcode
== ATI_FRAGMENT_SHADER_PASS_OP
) {
569 if (pass_tex
>= GL_TEXTURE0_ARB
&& pass_tex
<= GL_TEXTURE7_ARB
) {
570 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_TEX0
+ pass_tex
- GL_TEXTURE0_ARB
);
575 for (pass
= 0; pass
< atifs
->NumPasses
; pass
++) {
576 for (i
= 0; i
< atifs
->numArithInstr
[pass
]; i
++) {
577 struct atifs_instruction
*inst
= &atifs
->Instructions
[pass
][i
];
579 for (optype
= 0; optype
< 2; optype
++) { /* color, alpha */
580 if (inst
->Opcode
[optype
]) {
581 for (arg
= 0; arg
< inst
->ArgCount
[optype
]; arg
++) {
582 GLint index
= inst
->SrcReg
[optype
][arg
].Index
;
583 if (index
== GL_PRIMARY_COLOR_EXT
) {
584 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_COL0
);
585 } else if (index
== GL_SECONDARY_INTERPOLATOR_ATI
) {
586 /* note: ATI_fragment_shader.txt never specifies what
587 * GL_SECONDARY_INTERPOLATOR_ATI is, swrast uses
588 * VARYING_SLOT_COL1 for this input */
589 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_COL1
);
596 /* we may need fog */
597 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_FOGC
);
599 /* we always have the ATI_fs constants, and the fog params */
600 for (i
= 0; i
< MAX_NUM_FRAGMENT_CONSTANTS_ATI
; i
++) {
601 _mesa_add_parameter(prog
->Parameters
, PROGRAM_UNIFORM
,
602 NULL
, 4, GL_FLOAT
, NULL
, NULL
);
604 _mesa_add_state_reference(prog
->Parameters
, fog_params_state
);
605 _mesa_add_state_reference(prog
->Parameters
, fog_color
);
607 prog
->NumInstructions
= 0;
608 prog
->NumTemporaries
= MAX_NUM_FRAGMENT_REGISTERS_ATI
+ 3; /* 3 input temps for arith ops */
609 prog
->NumParameters
= MAX_NUM_FRAGMENT_CONSTANTS_ATI
+ 2; /* 2 state variables for fog */
613 struct tgsi_atifs_transform
{
614 struct tgsi_transform_context base
;
615 struct tgsi_shader_info info
;
616 const struct st_fp_variant_key
*key
;
617 bool first_instruction_emitted
;
618 unsigned fog_factor_temp
;
619 unsigned fog_clamp_imm
;
622 static inline struct tgsi_atifs_transform
*
623 tgsi_atifs_transform(struct tgsi_transform_context
*tctx
)
625 return (struct tgsi_atifs_transform
*)tctx
;
628 /* copied from st_cb_drawpixels_shader.c */
630 set_src(struct tgsi_full_instruction
*inst
, unsigned i
, unsigned file
, unsigned index
,
631 unsigned x
, unsigned y
, unsigned z
, unsigned w
)
633 inst
->Src
[i
].Register
.File
= file
;
634 inst
->Src
[i
].Register
.Index
= index
;
635 inst
->Src
[i
].Register
.SwizzleX
= x
;
636 inst
->Src
[i
].Register
.SwizzleY
= y
;
637 inst
->Src
[i
].Register
.SwizzleZ
= z
;
638 inst
->Src
[i
].Register
.SwizzleW
= w
;
641 #define SET_SRC(inst, i, file, index, x, y, z, w) \
642 set_src(inst, i, file, index, TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, \
643 TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w)
646 transform_decl(struct tgsi_transform_context
*tctx
,
647 struct tgsi_full_declaration
*decl
)
649 struct tgsi_atifs_transform
*ctx
= tgsi_atifs_transform(tctx
);
651 if (decl
->Declaration
.File
== TGSI_FILE_SAMPLER_VIEW
) {
652 /* fix texture target */
653 unsigned newtarget
= ctx
->key
->texture_targets
[decl
->Range
.First
];
655 decl
->SamplerView
.Resource
= newtarget
;
658 tctx
->emit_declaration(tctx
, decl
);
662 transform_instr(struct tgsi_transform_context
*tctx
,
663 struct tgsi_full_instruction
*current_inst
)
665 struct tgsi_atifs_transform
*ctx
= tgsi_atifs_transform(tctx
);
667 if (ctx
->first_instruction_emitted
)
670 ctx
->first_instruction_emitted
= true;
673 /* add a new temp for the fog factor */
674 ctx
->fog_factor_temp
= ctx
->info
.file_max
[TGSI_FILE_TEMPORARY
] + 1;
675 tgsi_transform_temp_decl(tctx
, ctx
->fog_factor_temp
);
677 /* add immediates for clamp */
678 ctx
->fog_clamp_imm
= ctx
->info
.immediate_count
;
679 tgsi_transform_immediate_decl(tctx
, 1.0f
, 0.0f
, 0.0f
, 0.0f
);
683 if (current_inst
->Instruction
.Opcode
== TGSI_OPCODE_TEX
) {
684 /* fix texture target */
685 unsigned newtarget
= ctx
->key
->texture_targets
[current_inst
->Src
[1].Register
.Index
];
687 current_inst
->Texture
.Texture
= newtarget
;
689 } else if (ctx
->key
->fog
&& current_inst
->Instruction
.Opcode
== TGSI_OPCODE_MOV
&&
690 current_inst
->Dst
[0].Register
.File
== TGSI_FILE_OUTPUT
) {
691 struct tgsi_full_instruction inst
;
694 int reg0_index
= current_inst
->Src
[0].Register
.Index
;
696 /* find FOGC input */
697 for (i
= 0; i
< ctx
->info
.num_inputs
; i
++) {
698 if (ctx
->info
.input_semantic_name
[i
] == TGSI_SEMANTIC_FOG
) {
703 if (fogc_index
< 0) {
704 /* should never be reached, because fog coord input is always declared */
705 tctx
->emit_instruction(tctx
, current_inst
);
709 /* compute the 1 component fog factor f */
710 if (ctx
->key
->fog
== 1) {
711 /* LINEAR formula: f = (end - z) / (end - start)
712 * with optimized parameters:
713 * f = MAD(fogcoord, oparams.x, oparams.y)
715 inst
= tgsi_default_full_instruction();
716 inst
.Instruction
.Opcode
= TGSI_OPCODE_MAD
;
717 inst
.Instruction
.NumDstRegs
= 1;
718 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
719 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
720 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
721 inst
.Instruction
.NumSrcRegs
= 3;
722 SET_SRC(&inst
, 0, TGSI_FILE_INPUT
, fogc_index
, X
, Y
, Z
, W
);
723 SET_SRC(&inst
, 1, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
, X
, X
, X
, X
);
724 SET_SRC(&inst
, 2, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
, Y
, Y
, Y
, Y
);
725 tctx
->emit_instruction(tctx
, &inst
);
726 } else if (ctx
->key
->fog
== 2) {
727 /* EXP formula: f = exp(-dens * z)
728 * with optimized parameters:
729 * f = MUL(fogcoord, oparams.z); f= EX2(-f)
731 inst
= tgsi_default_full_instruction();
732 inst
.Instruction
.Opcode
= TGSI_OPCODE_MUL
;
733 inst
.Instruction
.NumDstRegs
= 1;
734 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
735 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
736 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
737 inst
.Instruction
.NumSrcRegs
= 2;
738 SET_SRC(&inst
, 0, TGSI_FILE_INPUT
, fogc_index
, X
, Y
, Z
, W
);
739 SET_SRC(&inst
, 1, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
, Z
, Z
, Z
, Z
);
740 tctx
->emit_instruction(tctx
, &inst
);
742 inst
= tgsi_default_full_instruction();
743 inst
.Instruction
.Opcode
= TGSI_OPCODE_EX2
;
744 inst
.Instruction
.NumDstRegs
= 1;
745 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
746 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
747 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
748 inst
.Instruction
.NumSrcRegs
= 1;
749 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
750 inst
.Src
[0].Register
.Negate
= 1;
751 tctx
->emit_instruction(tctx
, &inst
);
752 } else if (ctx
->key
->fog
== 3) {
753 /* EXP2 formula: f = exp(-(dens * z)^2)
754 * with optimized parameters:
755 * f = MUL(fogcoord, oparams.w); f=MUL(f, f); f= EX2(-f)
757 inst
= tgsi_default_full_instruction();
758 inst
.Instruction
.Opcode
= TGSI_OPCODE_MUL
;
759 inst
.Instruction
.NumDstRegs
= 1;
760 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
761 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
762 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
763 inst
.Instruction
.NumSrcRegs
= 2;
764 SET_SRC(&inst
, 0, TGSI_FILE_INPUT
, fogc_index
, X
, Y
, Z
, W
);
765 SET_SRC(&inst
, 1, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
, W
, W
, W
, W
);
766 tctx
->emit_instruction(tctx
, &inst
);
768 inst
= tgsi_default_full_instruction();
769 inst
.Instruction
.Opcode
= TGSI_OPCODE_MUL
;
770 inst
.Instruction
.NumDstRegs
= 1;
771 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
772 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
773 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
774 inst
.Instruction
.NumSrcRegs
= 2;
775 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
776 SET_SRC(&inst
, 1, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
777 tctx
->emit_instruction(tctx
, &inst
);
779 inst
= tgsi_default_full_instruction();
780 inst
.Instruction
.Opcode
= TGSI_OPCODE_EX2
;
781 inst
.Instruction
.NumDstRegs
= 1;
782 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
783 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
784 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
785 inst
.Instruction
.NumSrcRegs
= 1;
786 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
787 inst
.Src
[0].Register
.Negate
^= 1;
788 tctx
->emit_instruction(tctx
, &inst
);
790 /* f = CLAMP(f, 0.0, 1.0) */
791 inst
= tgsi_default_full_instruction();
792 inst
.Instruction
.Opcode
= TGSI_OPCODE_CLAMP
;
793 inst
.Instruction
.NumDstRegs
= 1;
794 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
795 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
796 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
797 inst
.Instruction
.NumSrcRegs
= 3;
798 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
799 SET_SRC(&inst
, 1, TGSI_FILE_IMMEDIATE
, ctx
->fog_clamp_imm
, Y
, Y
, Y
, Y
); // 0.0
800 SET_SRC(&inst
, 2, TGSI_FILE_IMMEDIATE
, ctx
->fog_clamp_imm
, X
, X
, X
, X
); // 1.0
801 tctx
->emit_instruction(tctx
, &inst
);
803 /* REG0 = LRP(f, REG0, fogcolor) */
804 inst
= tgsi_default_full_instruction();
805 inst
.Instruction
.Opcode
= TGSI_OPCODE_LRP
;
806 inst
.Instruction
.NumDstRegs
= 1;
807 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
808 inst
.Dst
[0].Register
.Index
= reg0_index
;
809 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
810 inst
.Instruction
.NumSrcRegs
= 3;
811 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, X
, X
, Y
);
812 SET_SRC(&inst
, 1, TGSI_FILE_TEMPORARY
, reg0_index
, X
, Y
, Z
, W
);
813 SET_SRC(&inst
, 2, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
+ 1, X
, Y
, Z
, W
);
814 tctx
->emit_instruction(tctx
, &inst
);
817 tctx
->emit_instruction(tctx
, current_inst
);
821 * A post-process step in the draw call to fix texture targets and
822 * insert code for fog.
824 const struct tgsi_token
*
825 st_fixup_atifs(const struct tgsi_token
*tokens
,
826 const struct st_fp_variant_key
*key
)
828 struct tgsi_atifs_transform ctx
;
829 struct tgsi_token
*newtoks
;
832 memset(&ctx
, 0, sizeof(ctx
));
833 ctx
.base
.transform_declaration
= transform_decl
;
834 ctx
.base
.transform_instruction
= transform_instr
;
836 tgsi_scan_shader(tokens
, &ctx
.info
);
838 newlen
= tgsi_num_tokens(tokens
) + 30;
839 newtoks
= tgsi_alloc_tokens(newlen
);
843 tgsi_transform_shader(tokens
, newtoks
, newlen
, &ctx
.base
);