gallium/tgsi: add helper tgsi_get_interp_mode
[mesa.git] / src / mesa / state_tracker / st_mesa_to_tgsi.c
1 /**************************************************************************
2 *
3 * Copyright 2007-2008 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /*
29 * \author
30 * Michal Krol,
31 * Keith Whitwell
32 */
33
34 #include "pipe/p_compiler.h"
35 #include "pipe/p_context.h"
36 #include "pipe/p_screen.h"
37 #include "pipe/p_shader_tokens.h"
38 #include "pipe/p_state.h"
39 #include "tgsi/tgsi_ureg.h"
40 #include "tgsi/tgsi_from_mesa.h"
41 #include "st_mesa_to_tgsi.h"
42 #include "st_context.h"
43 #include "program/prog_instruction.h"
44 #include "program/prog_parameter.h"
45 #include "util/u_debug.h"
46 #include "util/u_math.h"
47 #include "util/u_memory.h"
48 #include "st_glsl_to_tgsi.h" /* for _mesa_sysval_to_semantic */
49
50
51 #define PROGRAM_ANY_CONST ((1 << PROGRAM_STATE_VAR) | \
52 (1 << PROGRAM_CONSTANT) | \
53 (1 << PROGRAM_UNIFORM))
54
55 /**
56 * Intermediate state used during shader translation.
57 */
58 struct st_translate {
59 struct ureg_program *ureg;
60
61 struct ureg_dst temps[MAX_PROGRAM_TEMPS];
62 struct ureg_src *constants;
63 struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS];
64 struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
65 struct ureg_dst address[1];
66 struct ureg_src samplers[PIPE_MAX_SAMPLERS];
67 struct ureg_src systemValues[SYSTEM_VALUE_MAX];
68
69 const ubyte *inputMapping;
70 const ubyte *outputMapping;
71
72 unsigned procType; /**< PIPE_SHADER_VERTEX/FRAGMENT */
73 };
74
75
76 /**
77 * Map a Mesa dst register to a TGSI ureg_dst register.
78 */
79 static struct ureg_dst
80 dst_register(struct st_translate *t, gl_register_file file, GLuint index)
81 {
82 switch(file) {
83 case PROGRAM_UNDEFINED:
84 return ureg_dst_undef();
85
86 case PROGRAM_TEMPORARY:
87 if (ureg_dst_is_undef(t->temps[index]))
88 t->temps[index] = ureg_DECL_temporary(t->ureg);
89
90 return t->temps[index];
91
92 case PROGRAM_OUTPUT:
93 if (t->procType == PIPE_SHADER_VERTEX)
94 assert(index < VARYING_SLOT_MAX);
95 else if (t->procType == PIPE_SHADER_FRAGMENT)
96 assert(index < FRAG_RESULT_MAX);
97 else
98 assert(index < VARYING_SLOT_MAX);
99
100 if (t->outputMapping[index] < ARRAY_SIZE(t->outputs))
101 return t->outputs[t->outputMapping[index]];
102 else {
103 assert(t->procType == PIPE_SHADER_VERTEX);
104 return ureg_dst(ureg_DECL_constant(t->ureg, 0));
105 }
106
107 case PROGRAM_ADDRESS:
108 return t->address[index];
109
110 default:
111 debug_assert(0);
112 return ureg_dst_undef();
113 }
114 }
115
116
117 /**
118 * Map a Mesa src register to a TGSI ureg_src register.
119 */
120 static struct ureg_src
121 src_register(struct st_translate *t,
122 gl_register_file file,
123 GLint index)
124 {
125 switch(file) {
126 case PROGRAM_UNDEFINED:
127 return ureg_src_undef();
128
129 case PROGRAM_TEMPORARY:
130 assert(index >= 0);
131 assert(index < ARRAY_SIZE(t->temps));
132 if (ureg_dst_is_undef(t->temps[index]))
133 t->temps[index] = ureg_DECL_temporary(t->ureg);
134 return ureg_src(t->temps[index]);
135
136 case PROGRAM_UNIFORM:
137 assert(index >= 0);
138 return t->constants[index];
139 case PROGRAM_STATE_VAR:
140 case PROGRAM_CONSTANT: /* ie, immediate */
141 if (index < 0)
142 return ureg_DECL_constant(t->ureg, 0);
143 else
144 return t->constants[index];
145
146 case PROGRAM_INPUT:
147 if (t->inputMapping[index] < ARRAY_SIZE(t->inputs))
148 return t->inputs[t->inputMapping[index]];
149 else {
150 assert(t->procType == PIPE_SHADER_VERTEX);
151 return ureg_DECL_constant(t->ureg, 0);
152 }
153
154 case PROGRAM_OUTPUT:
155 if (t->outputMapping[index] < ARRAY_SIZE(t->outputs))
156 return ureg_src(t->outputs[t->outputMapping[index]]);
157 else {
158 assert(t->procType == PIPE_SHADER_VERTEX);
159 return ureg_DECL_constant(t->ureg, 0);
160 }
161
162 case PROGRAM_ADDRESS:
163 return ureg_src(t->address[index]);
164
165 case PROGRAM_SYSTEM_VALUE:
166 assert(index < ARRAY_SIZE(t->systemValues));
167 return t->systemValues[index];
168
169 default:
170 debug_assert(0);
171 return ureg_src_undef();
172 }
173 }
174
175
176 /**
177 * Map mesa texture target to TGSI texture target.
178 */
179 enum tgsi_texture_type
180 st_translate_texture_target(gl_texture_index textarget, GLboolean shadow)
181 {
182 if (shadow) {
183 switch (textarget) {
184 case TEXTURE_1D_INDEX:
185 return TGSI_TEXTURE_SHADOW1D;
186 case TEXTURE_2D_INDEX:
187 return TGSI_TEXTURE_SHADOW2D;
188 case TEXTURE_RECT_INDEX:
189 return TGSI_TEXTURE_SHADOWRECT;
190 case TEXTURE_1D_ARRAY_INDEX:
191 return TGSI_TEXTURE_SHADOW1D_ARRAY;
192 case TEXTURE_2D_ARRAY_INDEX:
193 return TGSI_TEXTURE_SHADOW2D_ARRAY;
194 case TEXTURE_CUBE_INDEX:
195 return TGSI_TEXTURE_SHADOWCUBE;
196 case TEXTURE_CUBE_ARRAY_INDEX:
197 return TGSI_TEXTURE_SHADOWCUBE_ARRAY;
198 default:
199 break;
200 }
201 }
202
203 switch (textarget) {
204 case TEXTURE_2D_MULTISAMPLE_INDEX:
205 return TGSI_TEXTURE_2D_MSAA;
206 case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX:
207 return TGSI_TEXTURE_2D_ARRAY_MSAA;
208 case TEXTURE_BUFFER_INDEX:
209 return TGSI_TEXTURE_BUFFER;
210 case TEXTURE_1D_INDEX:
211 return TGSI_TEXTURE_1D;
212 case TEXTURE_2D_INDEX:
213 return TGSI_TEXTURE_2D;
214 case TEXTURE_3D_INDEX:
215 return TGSI_TEXTURE_3D;
216 case TEXTURE_CUBE_INDEX:
217 return TGSI_TEXTURE_CUBE;
218 case TEXTURE_CUBE_ARRAY_INDEX:
219 return TGSI_TEXTURE_CUBE_ARRAY;
220 case TEXTURE_RECT_INDEX:
221 return TGSI_TEXTURE_RECT;
222 case TEXTURE_1D_ARRAY_INDEX:
223 return TGSI_TEXTURE_1D_ARRAY;
224 case TEXTURE_2D_ARRAY_INDEX:
225 return TGSI_TEXTURE_2D_ARRAY;
226 case TEXTURE_EXTERNAL_INDEX:
227 return TGSI_TEXTURE_2D;
228 default:
229 debug_assert(!"unexpected texture target index");
230 return TGSI_TEXTURE_1D;
231 }
232 }
233
234
235 /**
236 * Map GLSL base type to TGSI return type.
237 */
238 enum tgsi_return_type
239 st_translate_texture_type(enum glsl_base_type type)
240 {
241 switch (type) {
242 case GLSL_TYPE_INT:
243 return TGSI_RETURN_TYPE_SINT;
244 case GLSL_TYPE_UINT:
245 return TGSI_RETURN_TYPE_UINT;
246 case GLSL_TYPE_FLOAT:
247 return TGSI_RETURN_TYPE_FLOAT;
248 default:
249 assert(!"unexpected texture type");
250 return TGSI_RETURN_TYPE_UNKNOWN;
251 }
252 }
253
254
255 /**
256 * Translate a (1 << TEXTURE_x_INDEX) bit into a TGSI_TEXTURE_x enum.
257 */
258 static unsigned
259 translate_texture_index(GLbitfield texBit, bool shadow)
260 {
261 int index = ffs(texBit);
262 assert(index > 0);
263 assert(index - 1 < NUM_TEXTURE_TARGETS);
264 return st_translate_texture_target(index - 1, shadow);
265 }
266
267
268 /**
269 * Create a TGSI ureg_dst register from a Mesa dest register.
270 */
271 static struct ureg_dst
272 translate_dst(struct st_translate *t,
273 const struct prog_dst_register *DstReg,
274 boolean saturate)
275 {
276 struct ureg_dst dst = dst_register(t, DstReg->File, DstReg->Index);
277
278 dst = ureg_writemask(dst, DstReg->WriteMask);
279
280 if (saturate)
281 dst = ureg_saturate(dst);
282
283 if (DstReg->RelAddr)
284 dst = ureg_dst_indirect(dst, ureg_src(t->address[0]));
285
286 return dst;
287 }
288
289
290 /**
291 * Create a TGSI ureg_src register from a Mesa src register.
292 */
293 static struct ureg_src
294 translate_src(struct st_translate *t,
295 const struct prog_src_register *SrcReg)
296 {
297 struct ureg_src src = src_register(t, SrcReg->File, SrcReg->Index);
298
299 src = ureg_swizzle(src,
300 GET_SWZ(SrcReg->Swizzle, 0) & 0x3,
301 GET_SWZ(SrcReg->Swizzle, 1) & 0x3,
302 GET_SWZ(SrcReg->Swizzle, 2) & 0x3,
303 GET_SWZ(SrcReg->Swizzle, 3) & 0x3);
304
305 if (SrcReg->Negate == NEGATE_XYZW)
306 src = ureg_negate(src);
307
308 if (SrcReg->RelAddr) {
309 src = ureg_src_indirect(src, ureg_src(t->address[0]));
310 if (SrcReg->File != PROGRAM_INPUT &&
311 SrcReg->File != PROGRAM_OUTPUT) {
312 /* If SrcReg->Index was negative, it was set to zero in
313 * src_register(). Reassign it now. But don't do this
314 * for input/output regs since they get remapped while
315 * const buffers don't.
316 */
317 src.Index = SrcReg->Index;
318 }
319 }
320
321 return src;
322 }
323
324
325 static struct ureg_src
326 swizzle_4v(struct ureg_src src, const unsigned *swz)
327 {
328 return ureg_swizzle(src, swz[0], swz[1], swz[2], swz[3]);
329 }
330
331
332 /**
333 * Translate a SWZ instruction into a MOV, MUL or MAD instruction. EG:
334 *
335 * SWZ dst, src.x-y10
336 *
337 * becomes:
338 *
339 * MAD dst {1,-1,0,0}, src.xyxx, {0,0,1,0}
340 */
341 static void
342 emit_swz(struct st_translate *t,
343 struct ureg_dst dst,
344 const struct prog_src_register *SrcReg)
345 {
346 struct ureg_program *ureg = t->ureg;
347 struct ureg_src src = src_register(t, SrcReg->File, SrcReg->Index);
348
349 unsigned negate_mask = SrcReg->Negate;
350
351 unsigned one_mask = ((GET_SWZ(SrcReg->Swizzle, 0) == SWIZZLE_ONE) << 0 |
352 (GET_SWZ(SrcReg->Swizzle, 1) == SWIZZLE_ONE) << 1 |
353 (GET_SWZ(SrcReg->Swizzle, 2) == SWIZZLE_ONE) << 2 |
354 (GET_SWZ(SrcReg->Swizzle, 3) == SWIZZLE_ONE) << 3);
355
356 unsigned zero_mask = ((GET_SWZ(SrcReg->Swizzle, 0) == SWIZZLE_ZERO) << 0 |
357 (GET_SWZ(SrcReg->Swizzle, 1) == SWIZZLE_ZERO) << 1 |
358 (GET_SWZ(SrcReg->Swizzle, 2) == SWIZZLE_ZERO) << 2 |
359 (GET_SWZ(SrcReg->Swizzle, 3) == SWIZZLE_ZERO) << 3);
360
361 unsigned negative_one_mask = one_mask & negate_mask;
362 unsigned positive_one_mask = one_mask & ~negate_mask;
363
364 struct ureg_src imm;
365 unsigned i;
366 unsigned mul_swizzle[4] = {0,0,0,0};
367 unsigned add_swizzle[4] = {0,0,0,0};
368 unsigned src_swizzle[4] = {0,0,0,0};
369 boolean need_add = FALSE;
370 boolean need_mul = FALSE;
371
372 if (dst.WriteMask == 0)
373 return;
374
375 /* Is this just a MOV?
376 */
377 if (zero_mask == 0 &&
378 one_mask == 0 &&
379 (negate_mask == 0 || negate_mask == TGSI_WRITEMASK_XYZW)) {
380 ureg_MOV(ureg, dst, translate_src(t, SrcReg));
381 return;
382 }
383
384 #define IMM_ZERO 0
385 #define IMM_ONE 1
386 #define IMM_NEG_ONE 2
387
388 imm = ureg_imm3f(ureg, 0, 1, -1);
389
390 for (i = 0; i < 4; i++) {
391 unsigned bit = 1 << i;
392
393 if (dst.WriteMask & bit) {
394 if (positive_one_mask & bit) {
395 mul_swizzle[i] = IMM_ZERO;
396 add_swizzle[i] = IMM_ONE;
397 need_add = TRUE;
398 }
399 else if (negative_one_mask & bit) {
400 mul_swizzle[i] = IMM_ZERO;
401 add_swizzle[i] = IMM_NEG_ONE;
402 need_add = TRUE;
403 }
404 else if (zero_mask & bit) {
405 mul_swizzle[i] = IMM_ZERO;
406 add_swizzle[i] = IMM_ZERO;
407 need_add = TRUE;
408 }
409 else {
410 add_swizzle[i] = IMM_ZERO;
411 src_swizzle[i] = GET_SWZ(SrcReg->Swizzle, i);
412 need_mul = TRUE;
413 if (negate_mask & bit) {
414 mul_swizzle[i] = IMM_NEG_ONE;
415 }
416 else {
417 mul_swizzle[i] = IMM_ONE;
418 }
419 }
420 }
421 }
422
423 if (need_mul && need_add) {
424 ureg_MAD(ureg,
425 dst,
426 swizzle_4v(src, src_swizzle),
427 swizzle_4v(imm, mul_swizzle),
428 swizzle_4v(imm, add_swizzle));
429 }
430 else if (need_mul) {
431 ureg_MUL(ureg,
432 dst,
433 swizzle_4v(src, src_swizzle),
434 swizzle_4v(imm, mul_swizzle));
435 }
436 else if (need_add) {
437 ureg_MOV(ureg,
438 dst,
439 swizzle_4v(imm, add_swizzle));
440 }
441 else {
442 debug_assert(0);
443 }
444
445 #undef IMM_ZERO
446 #undef IMM_ONE
447 #undef IMM_NEG_ONE
448 }
449
450
451 static unsigned
452 translate_opcode(unsigned op)
453 {
454 switch(op) {
455 case OPCODE_ARL:
456 return TGSI_OPCODE_ARL;
457 case OPCODE_ADD:
458 return TGSI_OPCODE_ADD;
459 case OPCODE_CMP:
460 return TGSI_OPCODE_CMP;
461 case OPCODE_COS:
462 return TGSI_OPCODE_COS;
463 case OPCODE_DP3:
464 return TGSI_OPCODE_DP3;
465 case OPCODE_DP4:
466 return TGSI_OPCODE_DP4;
467 case OPCODE_DST:
468 return TGSI_OPCODE_DST;
469 case OPCODE_EX2:
470 return TGSI_OPCODE_EX2;
471 case OPCODE_EXP:
472 return TGSI_OPCODE_EXP;
473 case OPCODE_FLR:
474 return TGSI_OPCODE_FLR;
475 case OPCODE_FRC:
476 return TGSI_OPCODE_FRC;
477 case OPCODE_KIL:
478 return TGSI_OPCODE_KILL_IF;
479 case OPCODE_LG2:
480 return TGSI_OPCODE_LG2;
481 case OPCODE_LOG:
482 return TGSI_OPCODE_LOG;
483 case OPCODE_LIT:
484 return TGSI_OPCODE_LIT;
485 case OPCODE_LRP:
486 return TGSI_OPCODE_LRP;
487 case OPCODE_MAD:
488 return TGSI_OPCODE_MAD;
489 case OPCODE_MAX:
490 return TGSI_OPCODE_MAX;
491 case OPCODE_MIN:
492 return TGSI_OPCODE_MIN;
493 case OPCODE_MOV:
494 return TGSI_OPCODE_MOV;
495 case OPCODE_MUL:
496 return TGSI_OPCODE_MUL;
497 case OPCODE_POW:
498 return TGSI_OPCODE_POW;
499 case OPCODE_RCP:
500 return TGSI_OPCODE_RCP;
501 case OPCODE_SGE:
502 return TGSI_OPCODE_SGE;
503 case OPCODE_SIN:
504 return TGSI_OPCODE_SIN;
505 case OPCODE_SLT:
506 return TGSI_OPCODE_SLT;
507 case OPCODE_TEX:
508 return TGSI_OPCODE_TEX;
509 case OPCODE_TXB:
510 return TGSI_OPCODE_TXB;
511 case OPCODE_TXP:
512 return TGSI_OPCODE_TXP;
513 case OPCODE_END:
514 return TGSI_OPCODE_END;
515 default:
516 debug_assert(0);
517 return TGSI_OPCODE_NOP;
518 }
519 }
520
521
522 static void
523 compile_instruction(struct gl_context *ctx,
524 struct st_translate *t,
525 const struct prog_instruction *inst)
526 {
527 struct ureg_program *ureg = t->ureg;
528 GLuint i;
529 struct ureg_dst dst[1] = { { 0 } };
530 struct ureg_src src[4];
531 unsigned num_dst;
532 unsigned num_src;
533
534 num_dst = _mesa_num_inst_dst_regs(inst->Opcode);
535 num_src = _mesa_num_inst_src_regs(inst->Opcode);
536
537 if (num_dst)
538 dst[0] = translate_dst(t, &inst->DstReg, inst->Saturate);
539
540 for (i = 0; i < num_src; i++)
541 src[i] = translate_src(t, &inst->SrcReg[i]);
542
543 switch(inst->Opcode) {
544 case OPCODE_SWZ:
545 emit_swz(t, dst[0], &inst->SrcReg[0]);
546 return;
547
548 case OPCODE_TEX:
549 case OPCODE_TXB:
550 case OPCODE_TXP:
551 src[num_src++] = t->samplers[inst->TexSrcUnit];
552 ureg_tex_insn(ureg,
553 translate_opcode(inst->Opcode),
554 dst, num_dst,
555 st_translate_texture_target(inst->TexSrcTarget,
556 inst->TexShadow),
557 TGSI_RETURN_TYPE_FLOAT,
558 NULL, 0,
559 src, num_src);
560 return;
561
562 case OPCODE_SCS:
563 ureg_COS(ureg, ureg_writemask(dst[0], TGSI_WRITEMASK_X),
564 ureg_scalar(src[0], TGSI_SWIZZLE_X));
565 ureg_SIN(ureg, ureg_writemask(dst[0], TGSI_WRITEMASK_Y),
566 ureg_scalar(src[0], TGSI_SWIZZLE_X));
567 break;
568
569 case OPCODE_XPD: {
570 struct ureg_dst tmp = ureg_DECL_temporary(ureg);
571
572 ureg_MUL(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ),
573 ureg_swizzle(src[0], TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z,
574 TGSI_SWIZZLE_X, 0),
575 ureg_swizzle(src[1], TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X,
576 TGSI_SWIZZLE_Y, 0));
577 ureg_MAD(ureg, ureg_writemask(dst[0], TGSI_WRITEMASK_XYZ),
578 ureg_swizzle(src[0], TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X,
579 TGSI_SWIZZLE_Y, 0),
580 ureg_negate(ureg_swizzle(src[1], TGSI_SWIZZLE_Y,
581 TGSI_SWIZZLE_Z, TGSI_SWIZZLE_X, 0)),
582 ureg_src(tmp));
583 break;
584 }
585
586 case OPCODE_RSQ:
587 ureg_RSQ(ureg, dst[0], ureg_abs(src[0]));
588 break;
589
590 case OPCODE_ABS:
591 ureg_MOV(ureg, dst[0], ureg_abs(src[0]));
592 break;
593
594 case OPCODE_SUB:
595 ureg_ADD(ureg, dst[0], src[0], ureg_negate(src[1]));
596 break;
597
598 case OPCODE_DPH: {
599 struct ureg_dst temp = ureg_DECL_temporary(ureg);
600
601 /* DPH = DP4(src0, src1) where src0.w = 1. */
602 ureg_MOV(ureg, ureg_writemask(temp, TGSI_WRITEMASK_XYZ), src[0]);
603 ureg_MOV(ureg, ureg_writemask(temp, TGSI_WRITEMASK_W),
604 ureg_imm1f(ureg, 1));
605 ureg_DP4(ureg, dst[0], ureg_src(temp), src[1]);
606 break;
607 }
608
609 default:
610 ureg_insn(ureg,
611 translate_opcode(inst->Opcode),
612 dst, num_dst,
613 src, num_src, 0);
614 break;
615 }
616 }
617
618
619 /**
620 * Emit the TGSI instructions for inverting and adjusting WPOS.
621 * This code is unavoidable because it also depends on whether
622 * a FBO is bound (STATE_FB_WPOS_Y_TRANSFORM).
623 */
624 static void
625 emit_wpos_adjustment(struct gl_context *ctx,
626 struct st_translate *t,
627 const struct gl_program *program,
628 boolean invert,
629 GLfloat adjX, GLfloat adjY[2])
630 {
631 struct ureg_program *ureg = t->ureg;
632
633 /* Fragment program uses fragment position input.
634 * Need to replace instances of INPUT[WPOS] with temp T
635 * where T = INPUT[WPOS] by y is inverted.
636 */
637 static const gl_state_index16 wposTransformState[STATE_LENGTH]
638 = { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM, 0, 0, 0 };
639
640 /* XXX: note we are modifying the incoming shader here! Need to
641 * do this before emitting the constant decls below, or this
642 * will be missed:
643 */
644 unsigned wposTransConst = _mesa_add_state_reference(program->Parameters,
645 wposTransformState);
646
647 struct ureg_src wpostrans = ureg_DECL_constant(ureg, wposTransConst);
648 struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg);
649 struct ureg_src *wpos =
650 ctx->Const.GLSLFragCoordIsSysVal ?
651 &t->systemValues[SYSTEM_VALUE_FRAG_COORD] :
652 &t->inputs[t->inputMapping[VARYING_SLOT_POS]];
653 struct ureg_src wpos_input = *wpos;
654
655 /* First, apply the coordinate shift: */
656 if (adjX || adjY[0] || adjY[1]) {
657 if (adjY[0] != adjY[1]) {
658 /* Adjust the y coordinate by adjY[1] or adjY[0] respectively
659 * depending on whether inversion is actually going to be applied
660 * or not, which is determined by testing against the inversion
661 * state variable used below, which will be either +1 or -1.
662 */
663 struct ureg_dst adj_temp = ureg_DECL_temporary(ureg);
664
665 ureg_CMP(ureg, adj_temp,
666 ureg_scalar(wpostrans, invert ? 2 : 0),
667 ureg_imm4f(ureg, adjX, adjY[0], 0.0f, 0.0f),
668 ureg_imm4f(ureg, adjX, adjY[1], 0.0f, 0.0f));
669 ureg_ADD(ureg, wpos_temp, wpos_input, ureg_src(adj_temp));
670 } else {
671 ureg_ADD(ureg, wpos_temp, wpos_input,
672 ureg_imm4f(ureg, adjX, adjY[0], 0.0f, 0.0f));
673 }
674 wpos_input = ureg_src(wpos_temp);
675 } else {
676 /* MOV wpos_temp, input[wpos]
677 */
678 ureg_MOV(ureg, wpos_temp, wpos_input);
679 }
680
681 /* Now the conditional y flip: STATE_FB_WPOS_Y_TRANSFORM.xy/zw will be
682 * inversion/identity, or the other way around if we're drawing to an FBO.
683 */
684 if (invert) {
685 /* MAD wpos_temp.y, wpos_input, wpostrans.xxxx, wpostrans.yyyy
686 */
687 ureg_MAD(ureg,
688 ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y),
689 wpos_input,
690 ureg_scalar(wpostrans, 0),
691 ureg_scalar(wpostrans, 1));
692 } else {
693 /* MAD wpos_temp.y, wpos_input, wpostrans.zzzz, wpostrans.wwww
694 */
695 ureg_MAD(ureg,
696 ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y),
697 wpos_input,
698 ureg_scalar(wpostrans, 2),
699 ureg_scalar(wpostrans, 3));
700 }
701
702 /* Use wpos_temp as position input from here on:
703 */
704 *wpos = ureg_src(wpos_temp);
705 }
706
707
708 /**
709 * Emit fragment position/coordinate code.
710 */
711 static void
712 emit_wpos(struct st_context *st,
713 struct st_translate *t,
714 const struct gl_program *program,
715 struct ureg_program *ureg)
716 {
717 struct pipe_screen *pscreen = st->pipe->screen;
718 GLfloat adjX = 0.0f;
719 GLfloat adjY[2] = { 0.0f, 0.0f };
720 boolean invert = FALSE;
721
722 /* Query the pixel center conventions supported by the pipe driver and set
723 * adjX, adjY to help out if it cannot handle the requested one internally.
724 *
725 * The bias of the y-coordinate depends on whether y-inversion takes place
726 * (adjY[1]) or not (adjY[0]), which is in turn dependent on whether we are
727 * drawing to an FBO (causes additional inversion), and whether the pipe
728 * driver origin and the requested origin differ (the latter condition is
729 * stored in the 'invert' variable).
730 *
731 * For height = 100 (i = integer, h = half-integer, l = lower, u = upper):
732 *
733 * center shift only:
734 * i -> h: +0.5
735 * h -> i: -0.5
736 *
737 * inversion only:
738 * l,i -> u,i: ( 0.0 + 1.0) * -1 + 100 = 99
739 * l,h -> u,h: ( 0.5 + 0.0) * -1 + 100 = 99.5
740 * u,i -> l,i: (99.0 + 1.0) * -1 + 100 = 0
741 * u,h -> l,h: (99.5 + 0.0) * -1 + 100 = 0.5
742 *
743 * inversion and center shift:
744 * l,i -> u,h: ( 0.0 + 0.5) * -1 + 100 = 99.5
745 * l,h -> u,i: ( 0.5 + 0.5) * -1 + 100 = 99
746 * u,i -> l,h: (99.0 + 0.5) * -1 + 100 = 0.5
747 * u,h -> l,i: (99.5 + 0.5) * -1 + 100 = 0
748 */
749 if (program->info.fs.origin_upper_left) {
750 /* Fragment shader wants origin in upper-left */
751 if (pscreen->get_param(pscreen,
752 PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) {
753 /* the driver supports upper-left origin */
754 }
755 else if (pscreen->get_param(pscreen,
756 PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) {
757 /* the driver supports lower-left origin, need to invert Y */
758 ureg_property(ureg, TGSI_PROPERTY_FS_COORD_ORIGIN,
759 TGSI_FS_COORD_ORIGIN_LOWER_LEFT);
760 invert = TRUE;
761 }
762 else
763 assert(0);
764 }
765 else {
766 /* Fragment shader wants origin in lower-left */
767 if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT))
768 /* the driver supports lower-left origin */
769 ureg_property(ureg, TGSI_PROPERTY_FS_COORD_ORIGIN,
770 TGSI_FS_COORD_ORIGIN_LOWER_LEFT);
771 else if (pscreen->get_param(pscreen,
772 PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT))
773 /* the driver supports upper-left origin, need to invert Y */
774 invert = TRUE;
775 else
776 assert(0);
777 }
778
779 if (program->info.fs.pixel_center_integer) {
780 /* Fragment shader wants pixel center integer */
781 if (pscreen->get_param(pscreen,
782 PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) {
783 /* the driver supports pixel center integer */
784 adjY[1] = 1.0f;
785 ureg_property(ureg, TGSI_PROPERTY_FS_COORD_PIXEL_CENTER,
786 TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
787 }
788 else if (pscreen->get_param(pscreen,
789 PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) {
790 /* the driver supports pixel center half integer, need to bias X,Y */
791 adjX = -0.5f;
792 adjY[0] = -0.5f;
793 adjY[1] = 0.5f;
794 }
795 else
796 assert(0);
797 }
798 else {
799 /* Fragment shader wants pixel center half integer */
800 if (pscreen->get_param(pscreen,
801 PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) {
802 /* the driver supports pixel center half integer */
803 }
804 else if (pscreen->get_param(pscreen,
805 PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) {
806 /* the driver supports pixel center integer, need to bias X,Y */
807 adjX = adjY[0] = adjY[1] = 0.5f;
808 ureg_property(ureg, TGSI_PROPERTY_FS_COORD_PIXEL_CENTER,
809 TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
810 }
811 else
812 assert(0);
813 }
814
815 /* we invert after adjustment so that we avoid the MOV to temporary,
816 * and reuse the adjustment ADD instead */
817 emit_wpos_adjustment(st->ctx, t, program, invert, adjX, adjY);
818 }
819
820
821 /**
822 * Translate Mesa program to TGSI format.
823 * \param program the program to translate
824 * \param numInputs number of input registers used
825 * \param inputMapping maps Mesa fragment program inputs to TGSI generic
826 * input indexes
827 * \param inputSemanticName the TGSI_SEMANTIC flag for each input
828 * \param inputSemanticIndex the semantic index (ex: which texcoord) for
829 * each input
830 * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
831 * \param numOutputs number of output registers used
832 * \param outputMapping maps Mesa fragment program outputs to TGSI
833 * generic outputs
834 * \param outputSemanticName the TGSI_SEMANTIC flag for each output
835 * \param outputSemanticIndex the semantic index (ex: which texcoord) for
836 * each output
837 *
838 * \return PIPE_OK or PIPE_ERROR_OUT_OF_MEMORY
839 */
840 enum pipe_error
841 st_translate_mesa_program(struct gl_context *ctx,
842 uint procType,
843 struct ureg_program *ureg,
844 const struct gl_program *program,
845 GLuint numInputs,
846 const ubyte inputMapping[],
847 const ubyte inputSemanticName[],
848 const ubyte inputSemanticIndex[],
849 const ubyte interpMode[],
850 GLuint numOutputs,
851 const ubyte outputMapping[],
852 const ubyte outputSemanticName[],
853 const ubyte outputSemanticIndex[])
854 {
855 struct st_translate translate, *t;
856 unsigned i;
857 enum pipe_error ret = PIPE_OK;
858
859 assert(numInputs <= ARRAY_SIZE(t->inputs));
860 assert(numOutputs <= ARRAY_SIZE(t->outputs));
861
862 t = &translate;
863 memset(t, 0, sizeof *t);
864
865 t->procType = procType;
866 t->inputMapping = inputMapping;
867 t->outputMapping = outputMapping;
868 t->ureg = ureg;
869
870 /*_mesa_print_program(program);*/
871
872 /*
873 * Declare input attributes.
874 */
875 if (procType == PIPE_SHADER_FRAGMENT) {
876 for (i = 0; i < numInputs; i++) {
877 t->inputs[i] = ureg_DECL_fs_input(ureg,
878 inputSemanticName[i],
879 inputSemanticIndex[i],
880 interpMode[i]);
881 }
882
883 if (program->info.inputs_read & VARYING_BIT_POS) {
884 /* Must do this after setting up t->inputs, and before
885 * emitting constant references, below:
886 */
887 emit_wpos(st_context(ctx), t, program, ureg);
888 }
889
890 /*
891 * Declare output attributes.
892 */
893 for (i = 0; i < numOutputs; i++) {
894 switch (outputSemanticName[i]) {
895 case TGSI_SEMANTIC_POSITION:
896 t->outputs[i] = ureg_DECL_output(ureg,
897 TGSI_SEMANTIC_POSITION, /* Z / Depth */
898 outputSemanticIndex[i]);
899
900 t->outputs[i] = ureg_writemask(t->outputs[i],
901 TGSI_WRITEMASK_Z);
902 break;
903 case TGSI_SEMANTIC_STENCIL:
904 t->outputs[i] = ureg_DECL_output(ureg,
905 TGSI_SEMANTIC_STENCIL, /* Stencil */
906 outputSemanticIndex[i]);
907 t->outputs[i] = ureg_writemask(t->outputs[i],
908 TGSI_WRITEMASK_Y);
909 break;
910 case TGSI_SEMANTIC_COLOR:
911 t->outputs[i] = ureg_DECL_output(ureg,
912 TGSI_SEMANTIC_COLOR,
913 outputSemanticIndex[i]);
914 break;
915 default:
916 debug_assert(0);
917 return 0;
918 }
919 }
920 }
921 else if (procType == PIPE_SHADER_GEOMETRY) {
922 for (i = 0; i < numInputs; i++) {
923 t->inputs[i] = ureg_DECL_input(ureg,
924 inputSemanticName[i],
925 inputSemanticIndex[i], 0, 1);
926 }
927
928 for (i = 0; i < numOutputs; i++) {
929 t->outputs[i] = ureg_DECL_output(ureg,
930 outputSemanticName[i],
931 outputSemanticIndex[i]);
932 }
933 }
934 else {
935 assert(procType == PIPE_SHADER_VERTEX);
936
937 for (i = 0; i < numInputs; i++) {
938 t->inputs[i] = ureg_DECL_vs_input(ureg, i);
939 }
940
941 for (i = 0; i < numOutputs; i++) {
942 t->outputs[i] = ureg_DECL_output(ureg,
943 outputSemanticName[i],
944 outputSemanticIndex[i]);
945 if (outputSemanticName[i] == TGSI_SEMANTIC_FOG) {
946 /* force register to contain a fog coordinate in the
947 * form (F, 0, 0, 1).
948 */
949 ureg_MOV(ureg,
950 ureg_writemask(t->outputs[i], TGSI_WRITEMASK_YZW),
951 ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 1.0f));
952 t->outputs[i] = ureg_writemask(t->outputs[i], TGSI_WRITEMASK_X);
953 }
954 }
955 }
956
957 /* Declare address register.
958 */
959 if (program->arb.NumAddressRegs > 0) {
960 debug_assert(program->arb.NumAddressRegs == 1);
961 t->address[0] = ureg_DECL_address(ureg);
962 }
963
964 /* Declare misc input registers
965 */
966 GLbitfield64 sysInputs = program->info.system_values_read;
967 for (i = 0; sysInputs; i++) {
968 if (sysInputs & (1ull << i)) {
969 unsigned semName = tgsi_get_sysval_semantic(i);
970
971 t->systemValues[i] = ureg_DECL_system_value(ureg, semName, 0);
972
973 if (semName == TGSI_SEMANTIC_INSTANCEID ||
974 semName == TGSI_SEMANTIC_VERTEXID) {
975 /* From Gallium perspective, these system values are always
976 * integer, and require native integer support. However, if
977 * native integer is supported on the vertex stage but not the
978 * pixel stage (e.g, i915g + draw), Mesa will generate IR that
979 * assumes these system values are floats. To resolve the
980 * inconsistency, we insert a U2F.
981 */
982 struct st_context *st = st_context(ctx);
983 struct pipe_screen *pscreen = st->pipe->screen;
984 assert(procType == PIPE_SHADER_VERTEX);
985 assert(pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX,
986 PIPE_SHADER_CAP_INTEGERS));
987 (void) pscreen; /* silence non-debug build warnings */
988 if (!ctx->Const.NativeIntegers) {
989 struct ureg_dst temp = ureg_DECL_local_temporary(t->ureg);
990 ureg_U2F(t->ureg, ureg_writemask(temp, TGSI_WRITEMASK_X),
991 t->systemValues[i]);
992 t->systemValues[i] = ureg_scalar(ureg_src(temp), 0);
993 }
994 }
995
996 if (procType == PIPE_SHADER_FRAGMENT &&
997 semName == TGSI_SEMANTIC_POSITION)
998 emit_wpos(st_context(ctx), t, program, ureg);
999
1000 sysInputs &= ~(1ull << i);
1001 }
1002 }
1003
1004 if (program->arb.IndirectRegisterFiles & (1 << PROGRAM_TEMPORARY)) {
1005 /* If temps are accessed with indirect addressing, declare temporaries
1006 * in sequential order. Else, we declare them on demand elsewhere.
1007 */
1008 for (i = 0; i < program->arb.NumTemporaries; i++) {
1009 /* XXX use TGSI_FILE_TEMPORARY_ARRAY when it's supported by ureg */
1010 t->temps[i] = ureg_DECL_temporary(t->ureg);
1011 }
1012 }
1013
1014 /* Emit constants and immediates. Mesa uses a single index space
1015 * for these, so we put all the translated regs in t->constants.
1016 */
1017 if (program->Parameters) {
1018 t->constants = calloc(program->Parameters->NumParameters,
1019 sizeof t->constants[0]);
1020 if (t->constants == NULL) {
1021 ret = PIPE_ERROR_OUT_OF_MEMORY;
1022 goto out;
1023 }
1024
1025 for (i = 0; i < program->Parameters->NumParameters; i++) {
1026 unsigned pvo = program->Parameters->ParameterValueOffset[i];
1027
1028 switch (program->Parameters->Parameters[i].Type) {
1029 case PROGRAM_STATE_VAR:
1030 case PROGRAM_UNIFORM:
1031 t->constants[i] = ureg_DECL_constant(ureg, i);
1032 break;
1033
1034 /* Emit immediates only when there's no indirect addressing of
1035 * the const buffer.
1036 * FIXME: Be smarter and recognize param arrays:
1037 * indirect addressing is only valid within the referenced
1038 * array.
1039 */
1040 case PROGRAM_CONSTANT:
1041 if (program->arb.IndirectRegisterFiles & PROGRAM_ANY_CONST)
1042 t->constants[i] = ureg_DECL_constant( ureg, i );
1043 else
1044 t->constants[i] =
1045 ureg_DECL_immediate(ureg,
1046 (const float *)
1047 program->Parameters->ParameterValues + pvo,
1048 4);
1049 break;
1050 default:
1051 break;
1052 }
1053 }
1054 }
1055
1056 /* texture samplers */
1057 for (i = 0;
1058 i < ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; i++) {
1059 if (program->SamplersUsed & (1u << i)) {
1060 unsigned target =
1061 translate_texture_index(program->TexturesUsed[i],
1062 !!(program->ShadowSamplers & (1 << i)));
1063 t->samplers[i] = ureg_DECL_sampler(ureg, i);
1064 ureg_DECL_sampler_view(ureg, i, target,
1065 TGSI_RETURN_TYPE_FLOAT,
1066 TGSI_RETURN_TYPE_FLOAT,
1067 TGSI_RETURN_TYPE_FLOAT,
1068 TGSI_RETURN_TYPE_FLOAT);
1069
1070 }
1071 }
1072
1073 /* Emit each instruction in turn:
1074 */
1075 for (i = 0; i < program->arb.NumInstructions; i++)
1076 compile_instruction(ctx, t, &program->arb.Instructions[i]);
1077
1078 out:
1079 free(t->constants);
1080 return ret;
1081 }