intel / DRI2: When available, use DRI2GetBuffersWithFormat
[mesa.git] / src / mesa / state_tracker / st_mesa_to_tgsi.c
1 /**************************************************************************
2 *
3 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 */
32
33 #include "pipe/p_compiler.h"
34 #include "pipe/p_shader_tokens.h"
35 #include "tgsi/tgsi_parse.h"
36 #include "tgsi/tgsi_build.h"
37 #include "tgsi/tgsi_util.h"
38 #include "tgsi/tgsi_dump.h"
39 #include "tgsi/tgsi_sanity.h"
40 #include "st_mesa_to_tgsi.h"
41 #include "shader/prog_instruction.h"
42 #include "shader/prog_parameter.h"
43 #include "shader/prog_print.h"
44 #include "util/u_debug.h"
45
46 /*
47 * Map mesa register file to TGSI register file.
48 */
49 static GLuint
50 map_register_file(
51 gl_register_file file,
52 GLuint index,
53 const GLuint immediateMapping[],
54 GLboolean indirectAccess )
55 {
56 switch( file ) {
57 case PROGRAM_UNDEFINED:
58 return TGSI_FILE_NULL;
59 case PROGRAM_TEMPORARY:
60 return TGSI_FILE_TEMPORARY;
61 /*case PROGRAM_LOCAL_PARAM:*/
62 /*case PROGRAM_ENV_PARAM:*/
63
64 /* Because of the longstanding problem with mesa arb shaders
65 * where constants, immediates and state variables are all
66 * bundled together as PROGRAM_STATE_VAR, we can't tell from the
67 * mesa register file whether this is a CONSTANT or an
68 * IMMEDIATE, hence we need all the other information.
69 */
70 case PROGRAM_STATE_VAR:
71 case PROGRAM_NAMED_PARAM:
72 case PROGRAM_UNIFORM:
73 if (!indirectAccess && immediateMapping && immediateMapping[index] != ~0)
74 return TGSI_FILE_IMMEDIATE;
75 else
76 return TGSI_FILE_CONSTANT;
77 case PROGRAM_CONSTANT:
78 if (indirectAccess)
79 return TGSI_FILE_CONSTANT;
80 assert(immediateMapping[index] != ~0);
81 return TGSI_FILE_IMMEDIATE;
82 case PROGRAM_INPUT:
83 return TGSI_FILE_INPUT;
84 case PROGRAM_OUTPUT:
85 return TGSI_FILE_OUTPUT;
86 case PROGRAM_ADDRESS:
87 return TGSI_FILE_ADDRESS;
88 default:
89 assert( 0 );
90 return TGSI_FILE_NULL;
91 }
92 }
93
94 /**
95 * Map mesa register file index to TGSI index.
96 * Take special care when processing input and output indices.
97 * \param file one of TGSI_FILE_x
98 * \param index the mesa register file index
99 * \param inputMapping maps Mesa input indexes to TGSI input indexes
100 * \param outputMapping maps Mesa output indexes to TGSI output indexes
101 */
102 static GLuint
103 map_register_file_index(
104 GLuint file,
105 GLuint index,
106 const GLuint inputMapping[],
107 const GLuint outputMapping[],
108 const GLuint immediateMapping[],
109 GLboolean indirectAccess )
110 {
111 switch( file ) {
112 case TGSI_FILE_INPUT:
113 /* inputs are mapped according to the user-defined map */
114 return inputMapping[index];
115
116 case TGSI_FILE_OUTPUT:
117 return outputMapping[index];
118
119 case TGSI_FILE_IMMEDIATE:
120 if (indirectAccess)
121 return index;
122 assert(immediateMapping[index] != ~0);
123 return immediateMapping[index];
124
125 default:
126 return index;
127 }
128 }
129
130 /*
131 * Map mesa texture target to TGSI texture target.
132 */
133 static GLuint
134 map_texture_target(
135 GLuint textarget,
136 GLboolean shadow )
137 {
138 #if 1
139 /* XXX remove this line after we've checked that the rest of gallium
140 * can handle the TGSI_TEXTURE_SHADOWx tokens.
141 */
142 shadow = GL_FALSE;
143 #endif
144 switch( textarget ) {
145 case TEXTURE_1D_INDEX:
146 if (shadow)
147 return TGSI_TEXTURE_SHADOW1D;
148 else
149 return TGSI_TEXTURE_1D;
150 case TEXTURE_2D_INDEX:
151 if (shadow)
152 return TGSI_TEXTURE_SHADOW2D;
153 else
154 return TGSI_TEXTURE_2D;
155 case TEXTURE_3D_INDEX:
156 return TGSI_TEXTURE_3D;
157 case TEXTURE_CUBE_INDEX:
158 return TGSI_TEXTURE_CUBE;
159 case TEXTURE_RECT_INDEX:
160 if (shadow)
161 return TGSI_TEXTURE_SHADOWRECT;
162 else
163 return TGSI_TEXTURE_RECT;
164 default:
165 assert( 0 );
166 }
167
168 return TGSI_TEXTURE_1D;
169 }
170
171 static GLuint
172 convert_sat(
173 GLuint sat )
174 {
175 switch( sat ) {
176 case SATURATE_OFF:
177 return TGSI_SAT_NONE;
178 case SATURATE_ZERO_ONE:
179 return TGSI_SAT_ZERO_ONE;
180 case SATURATE_PLUS_MINUS_ONE:
181 return TGSI_SAT_MINUS_PLUS_ONE;
182 default:
183 assert( 0 );
184 return TGSI_SAT_NONE;
185 }
186 }
187
188 static GLuint
189 convert_writemask(
190 GLuint writemask )
191 {
192 assert( WRITEMASK_X == TGSI_WRITEMASK_X );
193 assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
194 assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
195 assert( WRITEMASK_W == TGSI_WRITEMASK_W );
196 assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
197
198 return writemask;
199 }
200
201 static struct tgsi_full_immediate
202 make_immediate(const float *value, uint size)
203 {
204 struct tgsi_full_immediate imm;
205
206 imm = tgsi_default_full_immediate();
207 imm.Immediate.NrTokens += size;
208 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
209 imm.u.Pointer = value;
210 return imm;
211 }
212
213 static void
214 compile_instruction(
215 const struct prog_instruction *inst,
216 struct tgsi_full_instruction *fullinst,
217 const GLuint inputMapping[],
218 const GLuint outputMapping[],
219 const GLuint immediateMapping[],
220 GLboolean indirectAccess,
221 GLuint preamble_size,
222 GLuint procType,
223 GLboolean *insideSubroutine,
224 GLint wposTemp)
225 {
226 GLuint i;
227 struct tgsi_full_dst_register *fulldst;
228 struct tgsi_full_src_register *fullsrc;
229
230 *fullinst = tgsi_default_full_instruction();
231
232 fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
233 fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode );
234 fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
235
236 fulldst = &fullinst->FullDstRegisters[0];
237 fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE );
238 fulldst->DstRegister.Index = map_register_file_index(
239 fulldst->DstRegister.File,
240 inst->DstReg.Index,
241 inputMapping,
242 outputMapping,
243 NULL,
244 GL_FALSE );
245 fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
246
247 for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
248 GLuint j;
249
250 fullsrc = &fullinst->FullSrcRegisters[i];
251
252 if (procType == TGSI_PROCESSOR_FRAGMENT &&
253 inst->SrcReg[i].File == PROGRAM_INPUT &&
254 inst->SrcReg[i].Index == FRAG_ATTRIB_WPOS) {
255 /* special case of INPUT[WPOS] */
256 fullsrc->SrcRegister.File = TGSI_FILE_TEMPORARY;
257 fullsrc->SrcRegister.Index = wposTemp;
258 }
259 else {
260 /* any other src register */
261 fullsrc->SrcRegister.File = map_register_file(
262 inst->SrcReg[i].File,
263 inst->SrcReg[i].Index,
264 immediateMapping,
265 indirectAccess );
266 fullsrc->SrcRegister.Index = map_register_file_index(
267 fullsrc->SrcRegister.File,
268 inst->SrcReg[i].Index,
269 inputMapping,
270 outputMapping,
271 immediateMapping,
272 indirectAccess );
273 }
274
275 /* swizzle (ext swizzle also depends on negation) */
276 {
277 GLuint swz[4];
278 GLboolean extended = (inst->SrcReg[i].Negate != NEGATE_NONE &&
279 inst->SrcReg[i].Negate != NEGATE_XYZW);
280 for( j = 0; j < 4; j++ ) {
281 swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j );
282 if (swz[j] > SWIZZLE_W)
283 extended = GL_TRUE;
284 }
285 if (extended) {
286 for (j = 0; j < 4; j++) {
287 tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz,
288 swz[j], j);
289 }
290 }
291 else {
292 for (j = 0; j < 4; j++) {
293 tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister,
294 swz[j], j);
295 }
296 }
297 }
298
299 if( inst->SrcReg[i].Negate == NEGATE_XYZW ) {
300 fullsrc->SrcRegister.Negate = 1;
301 }
302 else if( inst->SrcReg[i].Negate != NEGATE_NONE ) {
303 if( inst->SrcReg[i].Negate & NEGATE_X ) {
304 fullsrc->SrcRegisterExtSwz.NegateX = 1;
305 }
306 if( inst->SrcReg[i].Negate & NEGATE_Y ) {
307 fullsrc->SrcRegisterExtSwz.NegateY = 1;
308 }
309 if( inst->SrcReg[i].Negate & NEGATE_Z ) {
310 fullsrc->SrcRegisterExtSwz.NegateZ = 1;
311 }
312 if( inst->SrcReg[i].Negate & NEGATE_W ) {
313 fullsrc->SrcRegisterExtSwz.NegateW = 1;
314 }
315 }
316
317 if( inst->SrcReg[i].Abs ) {
318 fullsrc->SrcRegisterExtMod.Absolute = 1;
319 }
320
321 if( inst->SrcReg[i].RelAddr ) {
322 fullsrc->SrcRegister.Indirect = 1;
323
324 fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
325 fullsrc->SrcRegisterInd.Index = 0;
326 }
327 }
328
329 switch( inst->Opcode ) {
330 case OPCODE_ARL:
331 fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
332 break;
333 case OPCODE_ABS:
334 fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
335 break;
336 case OPCODE_ADD:
337 fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
338 break;
339 case OPCODE_BGNLOOP:
340 fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2;
341 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
342 break;
343 case OPCODE_BGNSUB:
344 fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
345 *insideSubroutine = GL_TRUE;
346 break;
347 case OPCODE_BRA:
348 fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
349 break;
350 case OPCODE_BRK:
351 fullinst->Instruction.Opcode = TGSI_OPCODE_BRK;
352 break;
353 case OPCODE_CAL:
354 fullinst->Instruction.Opcode = TGSI_OPCODE_CAL;
355 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
356 break;
357 case OPCODE_CMP:
358 fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
359 break;
360 case OPCODE_CONT:
361 fullinst->Instruction.Opcode = TGSI_OPCODE_CONT;
362 break;
363 case OPCODE_COS:
364 fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
365 break;
366 case OPCODE_DDX:
367 fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
368 break;
369 case OPCODE_DDY:
370 fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
371 break;
372 case OPCODE_DP2:
373 fullinst->Instruction.Opcode = TGSI_OPCODE_DP2;
374 break;
375 case OPCODE_DP2A:
376 fullinst->Instruction.Opcode = TGSI_OPCODE_DP2A;
377 break;
378 case OPCODE_DP3:
379 fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
380 break;
381 case OPCODE_DP4:
382 fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
383 break;
384 case OPCODE_DPH:
385 fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
386 break;
387 case OPCODE_DST:
388 fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
389 break;
390 case OPCODE_ELSE:
391 fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE;
392 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
393 break;
394 case OPCODE_ENDIF:
395 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF;
396 break;
397 case OPCODE_ENDLOOP:
398 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2;
399 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
400 break;
401 case OPCODE_ENDSUB:
402 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
403 *insideSubroutine = GL_FALSE;
404 break;
405 case OPCODE_EX2:
406 fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
407 break;
408 case OPCODE_EXP:
409 fullinst->Instruction.Opcode = TGSI_OPCODE_EXP;
410 break;
411 case OPCODE_FLR:
412 fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
413 break;
414 case OPCODE_FRC:
415 fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
416 break;
417 case OPCODE_IF:
418 fullinst->Instruction.Opcode = TGSI_OPCODE_IF;
419 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
420 break;
421 case OPCODE_TRUNC:
422 fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC;
423 break;
424 case OPCODE_KIL:
425 /* conditional */
426 fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
427 break;
428 case OPCODE_KIL_NV:
429 /* predicated */
430 assert(inst->DstReg.CondMask == COND_TR);
431 fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
432 break;
433 case OPCODE_LG2:
434 fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
435 break;
436 case OPCODE_LOG:
437 fullinst->Instruction.Opcode = TGSI_OPCODE_LOG;
438 break;
439 case OPCODE_LIT:
440 fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
441 break;
442 case OPCODE_LRP:
443 fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
444 break;
445 case OPCODE_MAD:
446 fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
447 break;
448 case OPCODE_MAX:
449 fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
450 break;
451 case OPCODE_MIN:
452 fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
453 break;
454 case OPCODE_MOV:
455 fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
456 break;
457 case OPCODE_MUL:
458 fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
459 break;
460 case OPCODE_NOISE1:
461 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
462 break;
463 case OPCODE_NOISE2:
464 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
465 break;
466 case OPCODE_NOISE3:
467 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
468 break;
469 case OPCODE_NOISE4:
470 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
471 break;
472 case OPCODE_NOP:
473 fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
474 break;
475 case OPCODE_NRM3:
476 fullinst->Instruction.Opcode = TGSI_OPCODE_NRM;
477 break;
478 case OPCODE_NRM4:
479 fullinst->Instruction.Opcode = TGSI_OPCODE_NRM4;
480 break;
481 case OPCODE_POW:
482 fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
483 break;
484 case OPCODE_RCP:
485 fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
486 break;
487 case OPCODE_RET:
488 /* If RET is used inside main (not a real subroutine) we may want
489 * to execute END instead of RET. TBD...
490 */
491 if (1 /* *insideSubroutine */) {
492 fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
493 }
494 else {
495 /* inside main() pseudo-function */
496 fullinst->Instruction.Opcode = TGSI_OPCODE_END;
497 }
498 break;
499 case OPCODE_RSQ:
500 fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
501 break;
502 case OPCODE_SCS:
503 fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
504 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
505 break;
506 case OPCODE_SEQ:
507 fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
508 break;
509 case OPCODE_SGE:
510 fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
511 break;
512 case OPCODE_SGT:
513 fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
514 break;
515 case OPCODE_SIN:
516 fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
517 break;
518 case OPCODE_SLE:
519 fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
520 break;
521 case OPCODE_SLT:
522 fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
523 break;
524 case OPCODE_SNE:
525 fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
526 break;
527 case OPCODE_SSG:
528 fullinst->Instruction.Opcode = TGSI_OPCODE_SSG;
529 break;
530 case OPCODE_SUB:
531 fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
532 break;
533 case OPCODE_SWZ:
534 fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
535 break;
536 case OPCODE_TEX:
537 /* ordinary texture lookup */
538 fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
539 fullinst->Instruction.NumSrcRegs = 2;
540 fullinst->InstructionExtTexture.Texture =
541 map_texture_target( inst->TexSrcTarget, inst->TexShadow );
542 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
543 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
544 break;
545 case OPCODE_TXB:
546 /* texture lookup with LOD bias */
547 fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
548 fullinst->Instruction.NumSrcRegs = 2;
549 fullinst->InstructionExtTexture.Texture =
550 map_texture_target( inst->TexSrcTarget, inst->TexShadow );
551 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
552 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
553 break;
554 case OPCODE_TXD:
555 /* texture lookup with explicit partial derivatives */
556 fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
557 fullinst->Instruction.NumSrcRegs = 4;
558 fullinst->InstructionExtTexture.Texture =
559 map_texture_target( inst->TexSrcTarget, inst->TexShadow );
560 /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
561 fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
562 fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
563 break;
564 case OPCODE_TXL:
565 /* texture lookup with explicit LOD */
566 fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
567 fullinst->Instruction.NumSrcRegs = 2;
568 fullinst->InstructionExtTexture.Texture =
569 map_texture_target( inst->TexSrcTarget, inst->TexShadow );
570 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
571 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
572 break;
573 case OPCODE_TXP:
574 /* texture lookup with divide by Q component */
575 /* convert to TEX w/ special flag for division */
576 fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
577 fullinst->Instruction.NumSrcRegs = 2;
578 fullinst->InstructionExtTexture.Texture =
579 map_texture_target( inst->TexSrcTarget, inst->TexShadow );
580 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
581 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
582 break;
583 case OPCODE_XPD:
584 fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
585 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
586 break;
587 case OPCODE_END:
588 fullinst->Instruction.Opcode = TGSI_OPCODE_END;
589 break;
590 default:
591 assert( 0 );
592 }
593 }
594
595 /**
596 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
597 */
598 static struct tgsi_full_declaration
599 make_input_decl(
600 GLuint index,
601 GLboolean interpolate_info,
602 GLuint interpolate,
603 GLuint usage_mask,
604 GLboolean semantic_info,
605 GLuint semantic_name,
606 GLbitfield semantic_index,
607 GLbitfield input_flags)
608 {
609 struct tgsi_full_declaration decl;
610
611 assert(semantic_name < TGSI_SEMANTIC_COUNT);
612
613 decl = tgsi_default_full_declaration();
614 decl.Declaration.File = TGSI_FILE_INPUT;
615 decl.Declaration.UsageMask = usage_mask;
616 decl.Declaration.Semantic = semantic_info;
617 decl.DeclarationRange.First = index;
618 decl.DeclarationRange.Last = index;
619 if (semantic_info) {
620 decl.Semantic.SemanticName = semantic_name;
621 decl.Semantic.SemanticIndex = semantic_index;
622 }
623 if (interpolate_info) {
624 decl.Declaration.Interpolate = interpolate;
625 }
626 if (input_flags & PROG_PARAM_BIT_CENTROID)
627 decl.Declaration.Centroid = 1;
628 if (input_flags & PROG_PARAM_BIT_INVARIANT)
629 decl.Declaration.Invariant = 1;
630
631 return decl;
632 }
633
634 /**
635 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
636 */
637 static struct tgsi_full_declaration
638 make_output_decl(
639 GLuint index,
640 GLuint semantic_name,
641 GLuint semantic_index,
642 GLuint usage_mask,
643 GLbitfield output_flags)
644 {
645 struct tgsi_full_declaration decl;
646
647 assert(semantic_name < TGSI_SEMANTIC_COUNT);
648
649 decl = tgsi_default_full_declaration();
650 decl.Declaration.File = TGSI_FILE_OUTPUT;
651 decl.Declaration.UsageMask = usage_mask;
652 decl.Declaration.Semantic = 1;
653 decl.DeclarationRange.First = index;
654 decl.DeclarationRange.Last = index;
655 decl.Semantic.SemanticName = semantic_name;
656 decl.Semantic.SemanticIndex = semantic_index;
657 if (output_flags & PROG_PARAM_BIT_CENTROID)
658 decl.Declaration.Centroid = 1;
659 if (output_flags & PROG_PARAM_BIT_INVARIANT)
660 decl.Declaration.Invariant = 1;
661
662 return decl;
663 }
664
665
666 static struct tgsi_full_declaration
667 make_temp_decl(
668 GLuint start_index,
669 GLuint end_index )
670 {
671 struct tgsi_full_declaration decl;
672 decl = tgsi_default_full_declaration();
673 decl.Declaration.File = TGSI_FILE_TEMPORARY;
674 decl.DeclarationRange.First = start_index;
675 decl.DeclarationRange.Last = end_index;
676 return decl;
677 }
678
679 static struct tgsi_full_declaration
680 make_addr_decl(
681 GLuint start_index,
682 GLuint end_index )
683 {
684 struct tgsi_full_declaration decl;
685
686 decl = tgsi_default_full_declaration();
687 decl.Declaration.File = TGSI_FILE_ADDRESS;
688 decl.DeclarationRange.First = start_index;
689 decl.DeclarationRange.Last = end_index;
690 return decl;
691 }
692
693 static struct tgsi_full_declaration
694 make_sampler_decl(GLuint index)
695 {
696 struct tgsi_full_declaration decl;
697 decl = tgsi_default_full_declaration();
698 decl.Declaration.File = TGSI_FILE_SAMPLER;
699 decl.DeclarationRange.First = index;
700 decl.DeclarationRange.Last = index;
701 return decl;
702 }
703
704 /** Reference into a constant buffer */
705 static struct tgsi_full_declaration
706 make_constant_decl(GLuint first, GLuint last)
707 {
708 struct tgsi_full_declaration decl;
709 decl = tgsi_default_full_declaration();
710 decl.Declaration.File = TGSI_FILE_CONSTANT;
711 decl.DeclarationRange.First = first;
712 decl.DeclarationRange.Last = last;
713 return decl;
714 }
715
716
717
718 /**
719 * Find the temporaries which are used in the given program.
720 */
721 static void
722 find_temporaries(const struct gl_program *program,
723 GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
724 {
725 GLuint i, j;
726
727 for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
728 tempsUsed[i] = GL_FALSE;
729
730 for (i = 0; i < program->NumInstructions; i++) {
731 const struct prog_instruction *inst = program->Instructions + i;
732 const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
733 for (j = 0; j < n; j++) {
734 if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
735 tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
736 if (inst->DstReg.File == PROGRAM_TEMPORARY)
737 tempsUsed[inst->DstReg.Index] = GL_TRUE;
738 }
739 }
740 }
741
742
743 /**
744 * Find an unused temporary in the tempsUsed array.
745 */
746 static int
747 find_free_temporary(GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
748 {
749 int i;
750 for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
751 if (!tempsUsed[i]) {
752 tempsUsed[i] = GL_TRUE;
753 return i;
754 }
755 }
756 return -1;
757 }
758
759
760 /** helper for building simple TGSI instruction, one src register */
761 static void
762 build_tgsi_instruction1(struct tgsi_full_instruction *inst,
763 int opcode,
764 int dstFile, int dstIndex, int writemask,
765 int srcFile1, int srcIndex1)
766 {
767 *inst = tgsi_default_full_instruction();
768
769 inst->Instruction.Opcode = opcode;
770
771 inst->Instruction.NumDstRegs = 1;
772 inst->FullDstRegisters[0].DstRegister.File = dstFile;
773 inst->FullDstRegisters[0].DstRegister.Index = dstIndex;
774 inst->FullDstRegisters[0].DstRegister.WriteMask = writemask;
775
776 inst->Instruction.NumSrcRegs = 1;
777 inst->FullSrcRegisters[0].SrcRegister.File = srcFile1;
778 inst->FullSrcRegisters[0].SrcRegister.Index = srcIndex1;
779 }
780
781
782 /** helper for building simple TGSI instruction, two src registers */
783 static void
784 build_tgsi_instruction2(struct tgsi_full_instruction *inst,
785 int opcode,
786 int dstFile, int dstIndex, int writemask,
787 int srcFile1, int srcIndex1,
788 int srcFile2, int srcIndex2)
789 {
790 *inst = tgsi_default_full_instruction();
791
792 inst->Instruction.Opcode = opcode;
793
794 inst->Instruction.NumDstRegs = 1;
795 inst->FullDstRegisters[0].DstRegister.File = dstFile;
796 inst->FullDstRegisters[0].DstRegister.Index = dstIndex;
797 inst->FullDstRegisters[0].DstRegister.WriteMask = writemask;
798
799 inst->Instruction.NumSrcRegs = 2;
800 inst->FullSrcRegisters[0].SrcRegister.File = srcFile1;
801 inst->FullSrcRegisters[0].SrcRegister.Index = srcIndex1;
802 inst->FullSrcRegisters[1].SrcRegister.File = srcFile2;
803 inst->FullSrcRegisters[1].SrcRegister.Index = srcIndex2;
804 }
805
806
807
808 /**
809 * Emit the TGSI instructions for inverting the WPOS y coordinate.
810 */
811 static int
812 emit_inverted_wpos(struct tgsi_token *tokens,
813 int wpos_temp,
814 int winsize_const,
815 int wpos_input,
816 struct tgsi_header *header, int maxTokens)
817 {
818 struct tgsi_full_instruction fullinst;
819 int ti = 0;
820
821 /* MOV wpos_temp.xzw, input[wpos]; */
822 build_tgsi_instruction1(&fullinst,
823 TGSI_OPCODE_MOV,
824 TGSI_FILE_TEMPORARY, wpos_temp, WRITEMASK_XZW,
825 TGSI_FILE_INPUT, 0);
826
827 ti += tgsi_build_full_instruction(&fullinst,
828 &tokens[ti],
829 header,
830 maxTokens - ti);
831
832 /* SUB wpos_temp.y, const[winsize_const] - input[wpos_input]; */
833 build_tgsi_instruction2(&fullinst,
834 TGSI_OPCODE_SUB,
835 TGSI_FILE_TEMPORARY, wpos_temp, WRITEMASK_Y,
836 TGSI_FILE_CONSTANT, winsize_const,
837 TGSI_FILE_INPUT, wpos_input);
838
839 ti += tgsi_build_full_instruction(&fullinst,
840 &tokens[ti],
841 header,
842 maxTokens - ti);
843
844 return ti;
845 }
846
847
848
849
850 /**
851 * Translate Mesa program to TGSI format.
852 * \param program the program to translate
853 * \param numInputs number of input registers used
854 * \param inputMapping maps Mesa fragment program inputs to TGSI generic
855 * input indexes
856 * \param inputSemanticName the TGSI_SEMANTIC flag for each input
857 * \param inputSemanticIndex the semantic index (ex: which texcoord) for each input
858 * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
859
860 * \param numOutputs number of output registers used
861 * \param outputMapping maps Mesa fragment program outputs to TGSI
862 * generic outputs
863 * \param outputSemanticName the TGSI_SEMANTIC flag for each output
864 * \param outputSemanticIndex the semantic index (ex: which texcoord) for each output
865 * \param tokens array to store translated tokens in
866 * \param maxTokens size of the tokens array
867 *
868 * \return number of tokens placed in 'tokens' buffer, or zero if error
869 */
870 GLuint
871 st_translate_mesa_program(
872 GLcontext *ctx,
873 uint procType,
874 const struct gl_program *program,
875 GLuint numInputs,
876 const GLuint inputMapping[],
877 const ubyte inputSemanticName[],
878 const ubyte inputSemanticIndex[],
879 const GLuint interpMode[],
880 const GLbitfield inputFlags[],
881 GLuint numOutputs,
882 const GLuint outputMapping[],
883 const ubyte outputSemanticName[],
884 const ubyte outputSemanticIndex[],
885 const GLbitfield outputFlags[],
886 struct tgsi_token *tokens,
887 GLuint maxTokens )
888 {
889 GLuint i;
890 GLuint ti; /* token index */
891 struct tgsi_header *header;
892 struct tgsi_processor *processor;
893 GLuint preamble_size = 0;
894 GLuint immediates[1000];
895 GLuint numImmediates = 0;
896 GLboolean insideSubroutine = GL_FALSE;
897 GLboolean indirectAccess = GL_FALSE;
898 GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
899 GLint wposTemp = -1, winHeightConst = -1;
900
901 assert(procType == TGSI_PROCESSOR_FRAGMENT ||
902 procType == TGSI_PROCESSOR_VERTEX);
903
904 find_temporaries(program, tempsUsed);
905
906 if (procType == TGSI_PROCESSOR_FRAGMENT) {
907 if (program->InputsRead & FRAG_BIT_WPOS) {
908 /* Fragment program uses fragment position input.
909 * Need to replace instances of INPUT[WPOS] with temp T
910 * where T = INPUT[WPOS] by y is inverted.
911 */
912 static const gl_state_index winSizeState[STATE_LENGTH]
913 = { STATE_INTERNAL, STATE_FB_SIZE, 0, 0, 0 };
914 winHeightConst = _mesa_add_state_reference(program->Parameters,
915 winSizeState);
916 wposTemp = find_free_temporary(tempsUsed);
917 }
918 }
919
920
921 *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
922
923 header = (struct tgsi_header *) &tokens[1];
924 *header = tgsi_build_header();
925
926 processor = (struct tgsi_processor *) &tokens[2];
927 *processor = tgsi_build_processor( procType, header );
928
929 ti = 3;
930
931 /*
932 * Declare input attributes.
933 */
934 if (procType == TGSI_PROCESSOR_FRAGMENT) {
935 for (i = 0; i < numInputs; i++) {
936 struct tgsi_full_declaration fulldecl;
937 fulldecl = make_input_decl(i,
938 GL_TRUE, interpMode[i],
939 TGSI_WRITEMASK_XYZW,
940 GL_TRUE, inputSemanticName[i],
941 inputSemanticIndex[i],
942 inputFlags[i]);
943 ti += tgsi_build_full_declaration(&fulldecl,
944 &tokens[ti],
945 header,
946 maxTokens - ti );
947 }
948 }
949 else {
950 /* vertex prog */
951 /* XXX: this could probaby be merged with the clause above.
952 * the only difference is the semantic tags.
953 */
954 for (i = 0; i < numInputs; i++) {
955 struct tgsi_full_declaration fulldecl;
956 fulldecl = make_input_decl(i,
957 GL_FALSE, 0,
958 TGSI_WRITEMASK_XYZW,
959 GL_FALSE, 0, 0,
960 inputFlags[i]);
961 ti += tgsi_build_full_declaration(&fulldecl,
962 &tokens[ti],
963 header,
964 maxTokens - ti );
965 }
966 }
967
968 /*
969 * Declare output attributes.
970 */
971 if (procType == TGSI_PROCESSOR_FRAGMENT) {
972 for (i = 0; i < numOutputs; i++) {
973 struct tgsi_full_declaration fulldecl;
974 switch (outputSemanticName[i]) {
975 case TGSI_SEMANTIC_POSITION:
976 fulldecl = make_output_decl(i,
977 TGSI_SEMANTIC_POSITION, /* Z / Depth */
978 outputSemanticIndex[i],
979 TGSI_WRITEMASK_Z,
980 outputFlags[i]);
981 break;
982 case TGSI_SEMANTIC_COLOR:
983 fulldecl = make_output_decl(i,
984 TGSI_SEMANTIC_COLOR,
985 outputSemanticIndex[i],
986 TGSI_WRITEMASK_XYZW,
987 outputFlags[i]);
988 break;
989 default:
990 assert(0);
991 return 0;
992 }
993 ti += tgsi_build_full_declaration(&fulldecl,
994 &tokens[ti],
995 header,
996 maxTokens - ti );
997 }
998 }
999 else {
1000 /* vertex prog */
1001 for (i = 0; i < numOutputs; i++) {
1002 struct tgsi_full_declaration fulldecl;
1003 fulldecl = make_output_decl(i,
1004 outputSemanticName[i],
1005 outputSemanticIndex[i],
1006 TGSI_WRITEMASK_XYZW,
1007 outputFlags[i]);
1008 ti += tgsi_build_full_declaration(&fulldecl,
1009 &tokens[ti],
1010 header,
1011 maxTokens - ti );
1012 }
1013 }
1014
1015 /* temporary decls */
1016 {
1017 GLboolean inside_range = GL_FALSE;
1018 GLuint start_range = 0;
1019
1020 tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
1021 for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
1022 if (tempsUsed[i] && !inside_range) {
1023 inside_range = GL_TRUE;
1024 start_range = i;
1025 }
1026 else if (!tempsUsed[i] && inside_range) {
1027 struct tgsi_full_declaration fulldecl;
1028
1029 inside_range = GL_FALSE;
1030 fulldecl = make_temp_decl( start_range, i - 1 );
1031 ti += tgsi_build_full_declaration(
1032 &fulldecl,
1033 &tokens[ti],
1034 header,
1035 maxTokens - ti );
1036 }
1037 }
1038 }
1039
1040 /* Declare address register.
1041 */
1042 if (program->NumAddressRegs > 0) {
1043 struct tgsi_full_declaration fulldecl;
1044
1045 assert( program->NumAddressRegs == 1 );
1046
1047 fulldecl = make_addr_decl( 0, 0 );
1048 ti += tgsi_build_full_declaration(
1049 &fulldecl,
1050 &tokens[ti],
1051 header,
1052 maxTokens - ti );
1053
1054 indirectAccess = GL_TRUE;
1055 }
1056
1057 /* immediates/literals */
1058 memset(immediates, ~0, sizeof(immediates));
1059
1060 /* Emit immediates only when there is no address register in use.
1061 * FIXME: Be smarter and recognize param arrays -- indirect addressing is
1062 * only valid within the referenced array.
1063 */
1064 if (program->Parameters && !indirectAccess) {
1065 for (i = 0; i < program->Parameters->NumParameters; i++) {
1066 if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
1067 struct tgsi_full_immediate fullimm;
1068
1069 fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
1070 ti += tgsi_build_full_immediate(
1071 &fullimm,
1072 &tokens[ti],
1073 header,
1074 maxTokens - ti );
1075 immediates[i] = numImmediates;
1076 numImmediates++;
1077 }
1078 }
1079 }
1080
1081 /* constant buffer refs */
1082 if (program->Parameters) {
1083 GLint start = -1, end = -1;
1084
1085 for (i = 0; i < program->Parameters->NumParameters; i++) {
1086 GLboolean emit = (i == program->Parameters->NumParameters - 1);
1087 GLboolean matches;
1088
1089 switch (program->Parameters->Parameters[i].Type) {
1090 case PROGRAM_ENV_PARAM:
1091 case PROGRAM_STATE_VAR:
1092 case PROGRAM_NAMED_PARAM:
1093 case PROGRAM_UNIFORM:
1094 matches = GL_TRUE;
1095 break;
1096 case PROGRAM_CONSTANT:
1097 matches = indirectAccess;
1098 break;
1099 default:
1100 matches = GL_FALSE;
1101 }
1102
1103 if (matches) {
1104 if (start == -1) {
1105 /* begin a sequence */
1106 start = i;
1107 end = i;
1108 }
1109 else {
1110 /* continue sequence */
1111 end = i;
1112 }
1113 }
1114 else {
1115 if (start != -1) {
1116 /* end of sequence */
1117 emit = GL_TRUE;
1118 }
1119 }
1120
1121 if (emit && start >= 0) {
1122 struct tgsi_full_declaration fulldecl;
1123
1124 fulldecl = make_constant_decl( start, end );
1125 ti += tgsi_build_full_declaration(
1126 &fulldecl,
1127 &tokens[ti],
1128 header,
1129 maxTokens - ti );
1130 start = end = -1;
1131 }
1132 }
1133 }
1134
1135 /* texture samplers */
1136 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1137 if (program->SamplersUsed & (1 << i)) {
1138 struct tgsi_full_declaration fulldecl;
1139
1140 fulldecl = make_sampler_decl( i );
1141 ti += tgsi_build_full_declaration(
1142 &fulldecl,
1143 &tokens[ti],
1144 header,
1145 maxTokens - ti );
1146 }
1147 }
1148
1149 /* invert WPOS fragment input */
1150 if (wposTemp >= 0) {
1151 ti += emit_inverted_wpos(&tokens[ti], wposTemp, winHeightConst,
1152 inputMapping[FRAG_ATTRIB_WPOS],
1153 header, maxTokens - ti);
1154 preamble_size = 2; /* two instructions added */
1155 }
1156
1157 for (i = 0; i < program->NumInstructions; i++) {
1158 struct tgsi_full_instruction fullinst;
1159
1160 compile_instruction(
1161 &program->Instructions[i],
1162 &fullinst,
1163 inputMapping,
1164 outputMapping,
1165 immediates,
1166 indirectAccess,
1167 preamble_size,
1168 procType,
1169 &insideSubroutine,
1170 wposTemp);
1171
1172 ti += tgsi_build_full_instruction(
1173 &fullinst,
1174 &tokens[ti],
1175 header,
1176 maxTokens - ti );
1177 }
1178
1179 #if DEBUG
1180 if(!tgsi_sanity_check(tokens)) {
1181 debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
1182 debug_printf("\nOriginal program:\n%s", program->String);
1183 debug_printf("\nMesa program:\n");
1184 _mesa_print_program(program);
1185 debug_printf("\nTGSI program:\n");
1186 tgsi_dump(tokens, 0);
1187 assert(0);
1188 }
1189 #endif
1190
1191 return ti;
1192 }