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_NOP
, "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_negate(ureg_src(arg
));
180 ureg_insn(t
->ureg
, TGSI_OPCODE_ADD
, &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_ADD
, &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
, "SUB")) {
215 ureg_ADD(t
->ureg
, *dst
, args
[0], ureg_negate(args
[1]));
216 } else if (!strcmp(desc
->name
, "CND")) {
217 tmp
[0] = get_temp(t
, MAX_NUM_FRAGMENT_REGISTERS_ATI
+ 2); /* re-purpose a3 */
218 src
[0] = ureg_imm1f(t
->ureg
, 0.5f
);
219 src
[1] = ureg_negate(args
[2]);
220 ureg_insn(t
->ureg
, TGSI_OPCODE_ADD
, tmp
, 1, src
, 2);
221 src
[0] = ureg_src(tmp
[0]);
224 ureg_insn(t
->ureg
, TGSI_OPCODE_CMP
, dst
, 1, src
, 3);
225 } else if (!strcmp(desc
->name
, "CND0")) {
229 ureg_insn(t
->ureg
, TGSI_OPCODE_CMP
, dst
, 1, src
, 3);
230 } else if (!strcmp(desc
->name
, "DOT2_ADD")) {
231 /* note: DP2A is not implemented in most pipe drivers */
232 tmp
[0] = get_temp(t
, MAX_NUM_FRAGMENT_REGISTERS_ATI
); /* re-purpose a1 */
235 ureg_insn(t
->ureg
, TGSI_OPCODE_DP2
, tmp
, 1, src
, 2);
236 src
[0] = ureg_src(tmp
[0]);
237 src
[1] = ureg_scalar(args
[2], TGSI_SWIZZLE_Z
);
238 ureg_insn(t
->ureg
, TGSI_OPCODE_ADD
, dst
, 1, src
, 2);
243 emit_arith_inst(struct st_translate
*t
,
244 const struct instruction_desc
*desc
,
245 struct ureg_dst
*dst
, struct ureg_src
*args
, unsigned argcount
)
247 if (desc
->TGSI_opcode
== TGSI_OPCODE_NOP
) {
248 emit_special_inst(t
, desc
, dst
, args
, argcount
);
252 ureg_insn(t
->ureg
, desc
->TGSI_opcode
, dst
, 1, args
, argcount
);
256 emit_dstmod(struct st_translate
*t
,
257 struct ureg_dst dst
, GLuint dstMod
)
260 struct ureg_src src
[3];
261 GLuint scale
= dstMod
& ~GL_SATURATE_BIT_ATI
;
263 if (dstMod
== GL_NONE
) {
277 case GL_HALF_BIT_ATI
:
280 case GL_QUARTER_BIT_ATI
:
283 case GL_EIGHTH_BIT_ATI
:
290 src
[0] = ureg_src(dst
);
291 src
[1] = ureg_imm1f(t
->ureg
, imm
);
292 if (dstMod
& GL_SATURATE_BIT_ATI
) {
293 dst
= ureg_saturate(dst
);
295 ureg_insn(t
->ureg
, TGSI_OPCODE_MUL
, &dst
, 1, src
, 2);
299 * Compile one setup instruction to TGSI instructions.
302 compile_setupinst(struct st_translate
*t
,
304 const struct atifs_setupinst
*texinst
)
306 struct ureg_dst dst
[1];
307 struct ureg_src src
[2];
309 if (!texinst
->Opcode
)
312 dst
[0] = get_temp(t
, r
);
314 GLuint pass_tex
= texinst
->src
;
316 if (pass_tex
>= GL_TEXTURE0_ARB
&& pass_tex
<= GL_TEXTURE7_ARB
) {
317 unsigned attr
= pass_tex
- GL_TEXTURE0_ARB
+ VARYING_SLOT_TEX0
;
319 src
[0] = t
->inputs
[t
->inputMapping
[attr
]];
320 } else if (pass_tex
>= GL_REG_0_ATI
&& pass_tex
<= GL_REG_5_ATI
) {
321 unsigned reg
= pass_tex
- GL_REG_0_ATI
;
323 /* the frontend already validated that REG is only allowed in second pass */
324 if (t
->regs_written
[0][reg
]) {
325 src
[0] = ureg_src(t
->temps
[reg
]);
327 src
[0] = ureg_imm1f(t
->ureg
, 0.0f
);
330 src
[0] = apply_swizzle(t
, src
[0], texinst
->swizzle
);
332 if (texinst
->Opcode
== ATI_FRAGMENT_SHADER_SAMPLE_OP
) {
333 /* by default texture and sampler indexes are the same */
334 src
[1] = t
->samplers
[r
];
335 /* the texture target is still unknown, it will be fixed in the draw call */
336 ureg_tex_insn(t
->ureg
, TGSI_OPCODE_TEX
, dst
, 1, TGSI_TEXTURE_2D
,
338 } else if (texinst
->Opcode
== ATI_FRAGMENT_SHADER_PASS_OP
) {
339 ureg_insn(t
->ureg
, TGSI_OPCODE_MOV
, dst
, 1, src
, 1);
342 t
->regs_written
[t
->current_pass
][r
] = true;
346 * Compile one arithmetic operation COLOR&ALPHA pair into TGSI instructions.
349 compile_instruction(struct st_translate
*t
,
350 const struct atifs_instruction
*inst
)
354 for (optype
= 0; optype
< 2; optype
++) { /* color, alpha */
355 const struct instruction_desc
*desc
;
356 struct ureg_dst dst
[1];
357 struct ureg_src args
[3]; /* arguments for the main operation */
359 unsigned dstreg
= inst
->DstReg
[optype
].Index
- GL_REG_0_ATI
;
361 if (!inst
->Opcode
[optype
])
364 desc
= &inst_desc
[inst
->Opcode
[optype
] - GL_MOV_ATI
];
366 /* prepare the arguments */
367 for (arg
= 0; arg
< desc
->arg_count
; arg
++) {
368 if (arg
>= inst
->ArgCount
[optype
]) {
369 _mesa_warning(0, "Using 0 for missing argument %d of %s\n",
371 args
[arg
] = ureg_imm1f(t
->ureg
, 0.0f
);
373 args
[arg
] = prepare_argument(t
, arg
,
374 &inst
->SrcReg
[optype
][arg
]);
379 dst
[0] = get_temp(t
, dstreg
);
382 dst
[0] = ureg_writemask(dst
[0], TGSI_WRITEMASK_W
);
384 GLuint dstMask
= inst
->DstReg
[optype
].dstMask
;
385 if (dstMask
== GL_NONE
) {
386 dst
[0] = ureg_writemask(dst
[0], TGSI_WRITEMASK_XYZ
);
388 dst
[0] = ureg_writemask(dst
[0], dstMask
); /* the enum values match */
392 /* emit the main instruction */
393 emit_arith_inst(t
, desc
, dst
, args
, arg
);
395 emit_dstmod(t
, *dst
, inst
->DstReg
[optype
].dstMod
);
397 t
->regs_written
[t
->current_pass
][dstreg
] = true;
402 finalize_shader(struct st_translate
*t
, unsigned numPasses
)
404 struct ureg_dst dst
[1] = { { 0 } };
405 struct ureg_src src
[1] = { { 0 } };
407 if (t
->regs_written
[numPasses
-1][0]) {
408 /* copy the result into the OUT slot */
409 dst
[0] = t
->outputs
[t
->outputMapping
[FRAG_RESULT_COLOR
]];
410 src
[0] = ureg_src(t
->temps
[0]);
411 ureg_insn(t
->ureg
, TGSI_OPCODE_MOV
, dst
, 1, src
, 1);
414 /* signal the end of the program */
415 ureg_insn(t
->ureg
, TGSI_OPCODE_END
, dst
, 0, src
, 0);
419 * Called when a new variant is needed, we need to translate
420 * the ATI fragment shader to TGSI
423 st_translate_atifs_program(
424 struct ureg_program
*ureg
,
425 struct ati_fragment_shader
*atifs
,
426 struct gl_program
*program
,
428 const GLuint inputMapping
[],
429 const ubyte inputSemanticName
[],
430 const ubyte inputSemanticIndex
[],
431 const GLuint interpMode
[],
433 const GLuint outputMapping
[],
434 const ubyte outputSemanticName
[],
435 const ubyte outputSemanticIndex
[])
437 enum pipe_error ret
= PIPE_OK
;
441 struct st_translate translate
, *t
;
443 memset(t
, 0, sizeof *t
);
445 t
->inputMapping
= inputMapping
;
446 t
->outputMapping
= outputMapping
;
451 * Declare input attributes.
453 for (i
= 0; i
< numInputs
; i
++) {
454 t
->inputs
[i
] = ureg_DECL_fs_input(ureg
,
455 inputSemanticName
[i
],
456 inputSemanticIndex
[i
],
461 * Declare output attributes:
462 * we always have numOutputs=1 and it's FRAG_RESULT_COLOR
464 t
->outputs
[0] = ureg_DECL_output(ureg
,
466 outputSemanticIndex
[0]);
468 /* Emit constants and immediates. Mesa uses a single index space
469 * for these, so we put all the translated regs in t->constants.
471 if (program
->Parameters
) {
472 t
->constants
= calloc(program
->Parameters
->NumParameters
,
473 sizeof t
->constants
[0]);
474 if (t
->constants
== NULL
) {
475 ret
= PIPE_ERROR_OUT_OF_MEMORY
;
479 for (i
= 0; i
< program
->Parameters
->NumParameters
; i
++) {
480 switch (program
->Parameters
->Parameters
[i
].Type
) {
481 case PROGRAM_STATE_VAR
:
482 case PROGRAM_UNIFORM
:
483 t
->constants
[i
] = ureg_DECL_constant(ureg
, i
);
485 case PROGRAM_CONSTANT
:
487 ureg_DECL_immediate(ureg
,
488 (const float*)program
->Parameters
->ParameterValues
[i
],
497 /* texture samplers */
498 for (i
= 0; i
< MAX_NUM_FRAGMENT_REGISTERS_ATI
; i
++) {
499 if (program
->SamplersUsed
& (1 << i
)) {
500 t
->samplers
[i
] = ureg_DECL_sampler(ureg
, i
);
501 /* the texture target is still unknown, it will be fixed in the draw call */
502 ureg_DECL_sampler_view(ureg
, i
, TGSI_TEXTURE_2D
,
503 TGSI_RETURN_TYPE_FLOAT
,
504 TGSI_RETURN_TYPE_FLOAT
,
505 TGSI_RETURN_TYPE_FLOAT
,
506 TGSI_RETURN_TYPE_FLOAT
);
510 /* emit instructions */
511 for (pass
= 0; pass
< atifs
->NumPasses
; pass
++) {
512 t
->current_pass
= pass
;
513 for (r
= 0; r
< MAX_NUM_FRAGMENT_REGISTERS_ATI
; r
++) {
514 struct atifs_setupinst
*texinst
= &atifs
->SetupInst
[pass
][r
];
515 compile_setupinst(t
, r
, texinst
);
517 for (i
= 0; i
< atifs
->numArithInstr
[pass
]; i
++) {
518 struct atifs_instruction
*inst
= &atifs
->Instructions
[pass
][i
];
519 compile_instruction(t
, inst
);
523 finalize_shader(t
, atifs
->NumPasses
);
529 debug_printf("%s: translate error flag set\n", __func__
);
536 * Called in ProgramStringNotify, we need to fill the metadata of the
537 * gl_program attached to the ati_fragment_shader
540 st_init_atifs_prog(struct gl_context
*ctx
, struct gl_program
*prog
)
542 /* we know this is st_fragment_program, because of st_new_ati_fs() */
543 struct st_fragment_program
*stfp
= (struct st_fragment_program
*) prog
;
544 struct ati_fragment_shader
*atifs
= stfp
->ati_fs
;
546 unsigned pass
, i
, r
, optype
, arg
;
548 static const gl_state_index fog_params_state
[STATE_LENGTH
] =
549 {STATE_INTERNAL
, STATE_FOG_PARAMS_OPTIMIZED
, 0, 0, 0};
550 static const gl_state_index fog_color
[STATE_LENGTH
] =
551 {STATE_FOG_COLOR
, 0, 0, 0, 0};
553 prog
->info
.inputs_read
= 0;
554 prog
->info
.outputs_written
= BITFIELD64_BIT(FRAG_RESULT_COLOR
);
555 prog
->SamplersUsed
= 0;
556 prog
->Parameters
= _mesa_new_parameter_list();
558 /* fill in inputs_read, SamplersUsed, TexturesUsed */
559 for (pass
= 0; pass
< atifs
->NumPasses
; pass
++) {
560 for (r
= 0; r
< MAX_NUM_FRAGMENT_REGISTERS_ATI
; r
++) {
561 struct atifs_setupinst
*texinst
= &atifs
->SetupInst
[pass
][r
];
562 GLuint pass_tex
= texinst
->src
;
564 if (texinst
->Opcode
== ATI_FRAGMENT_SHADER_SAMPLE_OP
) {
565 /* mark which texcoords are used */
566 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_TEX0
+ pass_tex
- GL_TEXTURE0_ARB
);
567 /* by default there is 1:1 mapping between samplers and textures */
568 prog
->SamplersUsed
|= (1 << r
);
569 /* the target is unknown here, it will be fixed in the draw call */
570 prog
->TexturesUsed
[r
] = TEXTURE_2D_BIT
;
571 } else if (texinst
->Opcode
== ATI_FRAGMENT_SHADER_PASS_OP
) {
572 if (pass_tex
>= GL_TEXTURE0_ARB
&& pass_tex
<= GL_TEXTURE7_ARB
) {
573 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_TEX0
+ pass_tex
- GL_TEXTURE0_ARB
);
578 for (pass
= 0; pass
< atifs
->NumPasses
; pass
++) {
579 for (i
= 0; i
< atifs
->numArithInstr
[pass
]; i
++) {
580 struct atifs_instruction
*inst
= &atifs
->Instructions
[pass
][i
];
582 for (optype
= 0; optype
< 2; optype
++) { /* color, alpha */
583 if (inst
->Opcode
[optype
]) {
584 for (arg
= 0; arg
< inst
->ArgCount
[optype
]; arg
++) {
585 GLint index
= inst
->SrcReg
[optype
][arg
].Index
;
586 if (index
== GL_PRIMARY_COLOR_EXT
) {
587 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_COL0
);
588 } else if (index
== GL_SECONDARY_INTERPOLATOR_ATI
) {
589 /* note: ATI_fragment_shader.txt never specifies what
590 * GL_SECONDARY_INTERPOLATOR_ATI is, swrast uses
591 * VARYING_SLOT_COL1 for this input */
592 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_COL1
);
599 /* we may need fog */
600 prog
->info
.inputs_read
|= BITFIELD64_BIT(VARYING_SLOT_FOGC
);
602 /* we always have the ATI_fs constants, and the fog params */
603 for (i
= 0; i
< MAX_NUM_FRAGMENT_CONSTANTS_ATI
; i
++) {
604 _mesa_add_parameter(prog
->Parameters
, PROGRAM_UNIFORM
,
605 NULL
, 4, GL_FLOAT
, NULL
, NULL
);
607 _mesa_add_state_reference(prog
->Parameters
, fog_params_state
);
608 _mesa_add_state_reference(prog
->Parameters
, fog_color
);
610 prog
->arb
.NumInstructions
= 0;
611 prog
->arb
.NumTemporaries
= MAX_NUM_FRAGMENT_REGISTERS_ATI
+ 3; /* 3 input temps for arith ops */
612 prog
->arb
.NumParameters
= MAX_NUM_FRAGMENT_CONSTANTS_ATI
+ 2; /* 2 state variables for fog */
616 struct tgsi_atifs_transform
{
617 struct tgsi_transform_context base
;
618 struct tgsi_shader_info info
;
619 const struct st_fp_variant_key
*key
;
620 bool first_instruction_emitted
;
621 unsigned fog_factor_temp
;
624 static inline struct tgsi_atifs_transform
*
625 tgsi_atifs_transform(struct tgsi_transform_context
*tctx
)
627 return (struct tgsi_atifs_transform
*)tctx
;
630 /* copied from st_cb_drawpixels_shader.c */
632 set_src(struct tgsi_full_instruction
*inst
, unsigned i
, unsigned file
, unsigned index
,
633 unsigned x
, unsigned y
, unsigned z
, unsigned w
)
635 inst
->Src
[i
].Register
.File
= file
;
636 inst
->Src
[i
].Register
.Index
= index
;
637 inst
->Src
[i
].Register
.SwizzleX
= x
;
638 inst
->Src
[i
].Register
.SwizzleY
= y
;
639 inst
->Src
[i
].Register
.SwizzleZ
= z
;
640 inst
->Src
[i
].Register
.SwizzleW
= w
;
643 #define SET_SRC(inst, i, file, index, x, y, z, w) \
644 set_src(inst, i, file, index, TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, \
645 TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w)
648 transform_decl(struct tgsi_transform_context
*tctx
,
649 struct tgsi_full_declaration
*decl
)
651 struct tgsi_atifs_transform
*ctx
= tgsi_atifs_transform(tctx
);
653 if (decl
->Declaration
.File
== TGSI_FILE_SAMPLER_VIEW
) {
654 /* fix texture target */
655 unsigned newtarget
= ctx
->key
->texture_targets
[decl
->Range
.First
];
657 decl
->SamplerView
.Resource
= newtarget
;
660 tctx
->emit_declaration(tctx
, decl
);
664 transform_instr(struct tgsi_transform_context
*tctx
,
665 struct tgsi_full_instruction
*current_inst
)
667 struct tgsi_atifs_transform
*ctx
= tgsi_atifs_transform(tctx
);
669 if (ctx
->first_instruction_emitted
)
672 ctx
->first_instruction_emitted
= true;
675 /* add a new temp for the fog factor */
676 ctx
->fog_factor_temp
= ctx
->info
.file_max
[TGSI_FILE_TEMPORARY
] + 1;
677 tgsi_transform_temp_decl(tctx
, ctx
->fog_factor_temp
);
681 if (current_inst
->Instruction
.Opcode
== TGSI_OPCODE_TEX
) {
682 /* fix texture target */
683 unsigned newtarget
= ctx
->key
->texture_targets
[current_inst
->Src
[1].Register
.Index
];
685 current_inst
->Texture
.Texture
= newtarget
;
687 } else if (ctx
->key
->fog
&& current_inst
->Instruction
.Opcode
== TGSI_OPCODE_MOV
&&
688 current_inst
->Dst
[0].Register
.File
== TGSI_FILE_OUTPUT
) {
689 struct tgsi_full_instruction inst
;
692 int reg0_index
= current_inst
->Src
[0].Register
.Index
;
694 /* find FOGC input */
695 for (i
= 0; i
< ctx
->info
.num_inputs
; i
++) {
696 if (ctx
->info
.input_semantic_name
[i
] == TGSI_SEMANTIC_FOG
) {
701 if (fogc_index
< 0) {
702 /* should never be reached, because fog coord input is always declared */
703 tctx
->emit_instruction(tctx
, current_inst
);
707 /* compute the 1 component fog factor f */
708 if (ctx
->key
->fog
== FOG_LINEAR
) {
709 /* LINEAR formula: f = (end - z) / (end - start)
710 * with optimized parameters:
711 * f = MAD(fogcoord, oparams.x, oparams.y)
713 inst
= tgsi_default_full_instruction();
714 inst
.Instruction
.Opcode
= TGSI_OPCODE_MAD
;
715 inst
.Instruction
.NumDstRegs
= 1;
716 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
717 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
718 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
719 inst
.Instruction
.NumSrcRegs
= 3;
720 SET_SRC(&inst
, 0, TGSI_FILE_INPUT
, fogc_index
, X
, Y
, Z
, W
);
721 SET_SRC(&inst
, 1, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
, X
, X
, X
, X
);
722 SET_SRC(&inst
, 2, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
, Y
, Y
, Y
, Y
);
723 tctx
->emit_instruction(tctx
, &inst
);
724 } else if (ctx
->key
->fog
== FOG_EXP
) {
725 /* EXP formula: f = exp(-dens * z)
726 * with optimized parameters:
727 * f = MUL(fogcoord, oparams.z); f= EX2(-f)
729 inst
= tgsi_default_full_instruction();
730 inst
.Instruction
.Opcode
= TGSI_OPCODE_MUL
;
731 inst
.Instruction
.NumDstRegs
= 1;
732 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
733 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
734 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
735 inst
.Instruction
.NumSrcRegs
= 2;
736 SET_SRC(&inst
, 0, TGSI_FILE_INPUT
, fogc_index
, X
, Y
, Z
, W
);
737 SET_SRC(&inst
, 1, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
, Z
, Z
, Z
, Z
);
738 tctx
->emit_instruction(tctx
, &inst
);
740 inst
= tgsi_default_full_instruction();
741 inst
.Instruction
.Opcode
= TGSI_OPCODE_EX2
;
742 inst
.Instruction
.NumDstRegs
= 1;
743 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
744 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
745 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
746 inst
.Instruction
.NumSrcRegs
= 1;
747 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
748 inst
.Src
[0].Register
.Negate
= 1;
749 tctx
->emit_instruction(tctx
, &inst
);
750 } else if (ctx
->key
->fog
== FOG_EXP2
) {
751 /* EXP2 formula: f = exp(-(dens * z)^2)
752 * with optimized parameters:
753 * f = MUL(fogcoord, oparams.w); f=MUL(f, f); f= EX2(-f)
755 inst
= tgsi_default_full_instruction();
756 inst
.Instruction
.Opcode
= TGSI_OPCODE_MUL
;
757 inst
.Instruction
.NumDstRegs
= 1;
758 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
759 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
760 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
761 inst
.Instruction
.NumSrcRegs
= 2;
762 SET_SRC(&inst
, 0, TGSI_FILE_INPUT
, fogc_index
, X
, Y
, Z
, W
);
763 SET_SRC(&inst
, 1, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
, W
, W
, W
, W
);
764 tctx
->emit_instruction(tctx
, &inst
);
766 inst
= tgsi_default_full_instruction();
767 inst
.Instruction
.Opcode
= TGSI_OPCODE_MUL
;
768 inst
.Instruction
.NumDstRegs
= 1;
769 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
770 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
771 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
772 inst
.Instruction
.NumSrcRegs
= 2;
773 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
774 SET_SRC(&inst
, 1, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
775 tctx
->emit_instruction(tctx
, &inst
);
777 inst
= tgsi_default_full_instruction();
778 inst
.Instruction
.Opcode
= TGSI_OPCODE_EX2
;
779 inst
.Instruction
.NumDstRegs
= 1;
780 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
781 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
782 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
783 inst
.Instruction
.NumSrcRegs
= 1;
784 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
785 inst
.Src
[0].Register
.Negate
^= 1;
786 tctx
->emit_instruction(tctx
, &inst
);
788 /* f = saturate(f) */
789 inst
= tgsi_default_full_instruction();
790 inst
.Instruction
.Opcode
= TGSI_OPCODE_MOV
;
791 inst
.Instruction
.NumDstRegs
= 1;
792 inst
.Instruction
.Saturate
= 1;
793 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
794 inst
.Dst
[0].Register
.Index
= ctx
->fog_factor_temp
;
795 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
796 inst
.Instruction
.NumSrcRegs
= 1;
797 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, Y
, Z
, W
);
798 tctx
->emit_instruction(tctx
, &inst
);
800 /* REG0 = LRP(f, REG0, fogcolor) */
801 inst
= tgsi_default_full_instruction();
802 inst
.Instruction
.Opcode
= TGSI_OPCODE_LRP
;
803 inst
.Instruction
.NumDstRegs
= 1;
804 inst
.Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
805 inst
.Dst
[0].Register
.Index
= reg0_index
;
806 inst
.Dst
[0].Register
.WriteMask
= TGSI_WRITEMASK_XYZW
;
807 inst
.Instruction
.NumSrcRegs
= 3;
808 SET_SRC(&inst
, 0, TGSI_FILE_TEMPORARY
, ctx
->fog_factor_temp
, X
, X
, X
, Y
);
809 SET_SRC(&inst
, 1, TGSI_FILE_TEMPORARY
, reg0_index
, X
, Y
, Z
, W
);
810 SET_SRC(&inst
, 2, TGSI_FILE_CONSTANT
, MAX_NUM_FRAGMENT_CONSTANTS_ATI
+ 1, X
, Y
, Z
, W
);
811 tctx
->emit_instruction(tctx
, &inst
);
814 tctx
->emit_instruction(tctx
, current_inst
);
818 * A post-process step in the draw call to fix texture targets and
819 * insert code for fog.
821 const struct tgsi_token
*
822 st_fixup_atifs(const struct tgsi_token
*tokens
,
823 const struct st_fp_variant_key
*key
)
825 struct tgsi_atifs_transform ctx
;
826 struct tgsi_token
*newtoks
;
829 memset(&ctx
, 0, sizeof(ctx
));
830 ctx
.base
.transform_declaration
= transform_decl
;
831 ctx
.base
.transform_instruction
= transform_instr
;
833 tgsi_scan_shader(tokens
, &ctx
.info
);
835 newlen
= tgsi_num_tokens(tokens
) + 30;
836 newtoks
= tgsi_alloc_tokens(newlen
);
840 tgsi_transform_shader(tokens
, newtoks
, newlen
, &ctx
.base
);