Merge commit 'origin/master' into gallium-0.2
[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 "pipe/p_debug.h"
45
46 /*
47 * Map mesa register file to TGSI register file.
48 */
49 static GLuint
50 map_register_file(
51 enum 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 {
137 switch( textarget ) {
138 case TEXTURE_1D_INDEX:
139 return TGSI_TEXTURE_1D;
140 case TEXTURE_2D_INDEX:
141 return TGSI_TEXTURE_2D;
142 case TEXTURE_3D_INDEX:
143 return TGSI_TEXTURE_3D;
144 case TEXTURE_CUBE_INDEX:
145 return TGSI_TEXTURE_CUBE;
146 case TEXTURE_RECT_INDEX:
147 return TGSI_TEXTURE_RECT;
148 default:
149 assert( 0 );
150 }
151
152 return TGSI_TEXTURE_1D;
153 }
154
155 static GLuint
156 convert_sat(
157 GLuint sat )
158 {
159 switch( sat ) {
160 case SATURATE_OFF:
161 return TGSI_SAT_NONE;
162 case SATURATE_ZERO_ONE:
163 return TGSI_SAT_ZERO_ONE;
164 case SATURATE_PLUS_MINUS_ONE:
165 return TGSI_SAT_MINUS_PLUS_ONE;
166 default:
167 assert( 0 );
168 return TGSI_SAT_NONE;
169 }
170 }
171
172 static GLuint
173 convert_writemask(
174 GLuint writemask )
175 {
176 assert( WRITEMASK_X == TGSI_WRITEMASK_X );
177 assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
178 assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
179 assert( WRITEMASK_W == TGSI_WRITEMASK_W );
180 assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
181
182 return writemask;
183 }
184
185 static struct tgsi_full_immediate
186 make_immediate(const float *value, uint size)
187 {
188 struct tgsi_full_immediate imm;
189
190 imm = tgsi_default_full_immediate();
191 imm.Immediate.Size += size;
192 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
193 imm.u.Pointer = value;
194 return imm;
195 }
196
197 static void
198 compile_instruction(
199 const struct prog_instruction *inst,
200 struct tgsi_full_instruction *fullinst,
201 const GLuint inputMapping[],
202 const GLuint outputMapping[],
203 const GLuint immediateMapping[],
204 GLboolean indirectAccess,
205 GLuint preamble_size,
206 GLuint processor,
207 GLboolean *insideSubroutine)
208 {
209 GLuint i;
210 struct tgsi_full_dst_register *fulldst;
211 struct tgsi_full_src_register *fullsrc;
212
213 *fullinst = tgsi_default_full_instruction();
214
215 fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
216 fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode );
217 fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
218
219 fulldst = &fullinst->FullDstRegisters[0];
220 fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE );
221 fulldst->DstRegister.Index = map_register_file_index(
222 fulldst->DstRegister.File,
223 inst->DstReg.Index,
224 inputMapping,
225 outputMapping,
226 NULL,
227 GL_FALSE );
228 fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
229
230 for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
231 GLuint j;
232
233 fullsrc = &fullinst->FullSrcRegisters[i];
234 fullsrc->SrcRegister.File = map_register_file(
235 inst->SrcReg[i].File,
236 inst->SrcReg[i].Index,
237 immediateMapping,
238 indirectAccess );
239 fullsrc->SrcRegister.Index = map_register_file_index(
240 fullsrc->SrcRegister.File,
241 inst->SrcReg[i].Index,
242 inputMapping,
243 outputMapping,
244 immediateMapping,
245 indirectAccess );
246
247
248 /* swizzle (ext swizzle also depends on negation) */
249 {
250 GLuint swz[4];
251 GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE &&
252 inst->SrcReg[i].NegateBase != NEGATE_XYZW);
253 for( j = 0; j < 4; j++ ) {
254 swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j );
255 if (swz[j] > SWIZZLE_W)
256 extended = GL_TRUE;
257 }
258 if (extended) {
259 for (j = 0; j < 4; j++) {
260 tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz,
261 swz[j], j);
262 }
263 }
264 else {
265 for (j = 0; j < 4; j++) {
266 tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister,
267 swz[j], j);
268 }
269 }
270 }
271
272 if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {
273 fullsrc->SrcRegister.Negate = 1;
274 }
275 else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {
276 if( inst->SrcReg[i].NegateBase & NEGATE_X ) {
277 fullsrc->SrcRegisterExtSwz.NegateX = 1;
278 }
279 if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {
280 fullsrc->SrcRegisterExtSwz.NegateY = 1;
281 }
282 if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {
283 fullsrc->SrcRegisterExtSwz.NegateZ = 1;
284 }
285 if( inst->SrcReg[i].NegateBase & NEGATE_W ) {
286 fullsrc->SrcRegisterExtSwz.NegateW = 1;
287 }
288 }
289
290 if( inst->SrcReg[i].Abs ) {
291 fullsrc->SrcRegisterExtMod.Absolute = 1;
292 }
293
294 if( inst->SrcReg[i].NegateAbs ) {
295 fullsrc->SrcRegisterExtMod.Negate = 1;
296 }
297
298 if( inst->SrcReg[i].RelAddr ) {
299 fullsrc->SrcRegister.Indirect = 1;
300
301 fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
302 fullsrc->SrcRegisterInd.Index = 0;
303 }
304 }
305
306 switch( inst->Opcode ) {
307 case OPCODE_ARL:
308 fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
309 break;
310 case OPCODE_ABS:
311 fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
312 break;
313 case OPCODE_ADD:
314 fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
315 break;
316 case OPCODE_BGNLOOP:
317 fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2;
318 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
319 break;
320 case OPCODE_BGNSUB:
321 fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
322 *insideSubroutine = GL_TRUE;
323 break;
324 case OPCODE_BRA:
325 fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
326 break;
327 case OPCODE_BRK:
328 fullinst->Instruction.Opcode = TGSI_OPCODE_BRK;
329 break;
330 case OPCODE_CAL:
331 fullinst->Instruction.Opcode = TGSI_OPCODE_CAL;
332 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
333 break;
334 case OPCODE_CMP:
335 fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
336 break;
337 case OPCODE_CONT:
338 fullinst->Instruction.Opcode = TGSI_OPCODE_CONT;
339 break;
340 case OPCODE_COS:
341 fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
342 break;
343 case OPCODE_DDX:
344 fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
345 break;
346 case OPCODE_DDY:
347 fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
348 break;
349 case OPCODE_DP3:
350 fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
351 break;
352 case OPCODE_DP4:
353 fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
354 break;
355 case OPCODE_DPH:
356 fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
357 break;
358 case OPCODE_DST:
359 fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
360 break;
361 case OPCODE_ELSE:
362 fullinst->Instruction.Opcode = TGSI_OPCODE_ELSE;
363 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
364 break;
365 case OPCODE_ENDIF:
366 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDIF;
367 break;
368 case OPCODE_ENDLOOP:
369 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2;
370 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
371 break;
372 case OPCODE_ENDSUB:
373 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
374 *insideSubroutine = GL_FALSE;
375 break;
376 case OPCODE_EX2:
377 fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
378 break;
379 case OPCODE_EXP:
380 fullinst->Instruction.Opcode = TGSI_OPCODE_EXP;
381 break;
382 case OPCODE_FLR:
383 fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
384 break;
385 case OPCODE_FRC:
386 fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
387 break;
388 case OPCODE_IF:
389 fullinst->Instruction.Opcode = TGSI_OPCODE_IF;
390 fullinst->InstructionExtLabel.Label = inst->BranchTarget + preamble_size;
391 break;
392 case OPCODE_INT:
393 fullinst->Instruction.Opcode = TGSI_OPCODE_INT;
394 break;
395 case OPCODE_KIL:
396 /* conditional */
397 fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
398 break;
399 case OPCODE_KIL_NV:
400 /* predicated */
401 assert(inst->DstReg.CondMask == COND_TR);
402 fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
403 break;
404 case OPCODE_LG2:
405 fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
406 break;
407 case OPCODE_LOG:
408 fullinst->Instruction.Opcode = TGSI_OPCODE_LOG;
409 break;
410 case OPCODE_LIT:
411 fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
412 break;
413 case OPCODE_LRP:
414 fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
415 break;
416 case OPCODE_MAD:
417 fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
418 break;
419 case OPCODE_MAX:
420 fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
421 break;
422 case OPCODE_MIN:
423 fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
424 break;
425 case OPCODE_MOV:
426 fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
427 break;
428 case OPCODE_MUL:
429 fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
430 break;
431 case OPCODE_NOISE1:
432 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
433 break;
434 case OPCODE_NOISE2:
435 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
436 break;
437 case OPCODE_NOISE3:
438 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
439 break;
440 case OPCODE_NOISE4:
441 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
442 break;
443 case OPCODE_NOP:
444 fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
445 break;
446 case OPCODE_POW:
447 fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
448 break;
449 case OPCODE_RCP:
450 fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
451 break;
452 case OPCODE_RET:
453 /* If RET is used inside main (not a real subroutine) we may want
454 * to execute END instead of RET. TBD...
455 */
456 if (1 /* *insideSubroutine */) {
457 fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
458 }
459 else {
460 /* inside main() pseudo-function */
461 fullinst->Instruction.Opcode = TGSI_OPCODE_END;
462 }
463 break;
464 case OPCODE_RSQ:
465 fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
466 tgsi_util_set_full_src_register_sign_mode(
467 &fullinst->FullSrcRegisters[0],
468 TGSI_UTIL_SIGN_CLEAR );
469 break;
470 case OPCODE_SCS:
471 fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
472 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
473 break;
474 case OPCODE_SEQ:
475 fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
476 break;
477 case OPCODE_SGE:
478 fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
479 break;
480 case OPCODE_SGT:
481 fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
482 break;
483 case OPCODE_SIN:
484 fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
485 break;
486 case OPCODE_SLE:
487 fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
488 break;
489 case OPCODE_SLT:
490 fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
491 break;
492 case OPCODE_SNE:
493 fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
494 break;
495 case OPCODE_SUB:
496 fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
497 break;
498 case OPCODE_SWZ:
499 fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
500 break;
501 case OPCODE_TEX:
502 /* ordinary texture lookup */
503 fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
504 fullinst->Instruction.NumSrcRegs = 2;
505 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
506 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
507 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
508 break;
509 case OPCODE_TXB:
510 /* texture lookup with LOD bias */
511 fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
512 fullinst->Instruction.NumSrcRegs = 2;
513 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
514 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
515 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
516 break;
517 case OPCODE_TXD:
518 /* texture lookup with explicit partial derivatives */
519 fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
520 fullinst->Instruction.NumSrcRegs = 4;
521 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
522 /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
523 fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
524 fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
525 break;
526 case OPCODE_TXL:
527 /* texture lookup with explicit LOD */
528 fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
529 fullinst->Instruction.NumSrcRegs = 2;
530 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
531 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
532 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
533 break;
534 case OPCODE_TXP:
535 /* texture lookup with divide by Q component */
536 /* convert to TEX w/ special flag for division */
537 fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
538 fullinst->Instruction.NumSrcRegs = 2;
539 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
540 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
541 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
542 break;
543 case OPCODE_XPD:
544 fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
545 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
546 break;
547 case OPCODE_END:
548 fullinst->Instruction.Opcode = TGSI_OPCODE_END;
549 break;
550 default:
551 assert( 0 );
552 }
553 }
554
555 /**
556 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
557 */
558 static struct tgsi_full_declaration
559 make_input_decl(
560 GLuint index,
561 GLboolean interpolate_info,
562 GLuint interpolate,
563 GLuint usage_mask,
564 GLboolean semantic_info,
565 GLuint semantic_name,
566 GLbitfield semantic_index )
567 {
568 struct tgsi_full_declaration decl;
569
570 assert(semantic_name < TGSI_SEMANTIC_COUNT);
571
572 decl = tgsi_default_full_declaration();
573 decl.Declaration.File = TGSI_FILE_INPUT;
574 decl.Declaration.UsageMask = usage_mask;
575 decl.Declaration.Semantic = semantic_info;
576 decl.DeclarationRange.First = index;
577 decl.DeclarationRange.Last = index;
578 if (semantic_info) {
579 decl.Semantic.SemanticName = semantic_name;
580 decl.Semantic.SemanticIndex = semantic_index;
581 }
582 if (interpolate_info) {
583 decl.Declaration.Interpolate = interpolate;
584 }
585
586 return decl;
587 }
588
589 /**
590 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
591 */
592 static struct tgsi_full_declaration
593 make_output_decl(
594 GLuint index,
595 GLuint semantic_name,
596 GLuint semantic_index,
597 GLbitfield usage_mask )
598 {
599 struct tgsi_full_declaration decl;
600
601 assert(semantic_name < TGSI_SEMANTIC_COUNT);
602
603 decl = tgsi_default_full_declaration();
604 decl.Declaration.File = TGSI_FILE_OUTPUT;
605 decl.Declaration.UsageMask = usage_mask;
606 decl.Declaration.Semantic = 1;
607 decl.DeclarationRange.First = index;
608 decl.DeclarationRange.Last = index;
609 decl.Semantic.SemanticName = semantic_name;
610 decl.Semantic.SemanticIndex = semantic_index;
611
612 return decl;
613 }
614
615
616 static struct tgsi_full_declaration
617 make_temp_decl(
618 GLuint start_index,
619 GLuint end_index )
620 {
621 struct tgsi_full_declaration decl;
622 decl = tgsi_default_full_declaration();
623 decl.Declaration.File = TGSI_FILE_TEMPORARY;
624 decl.DeclarationRange.First = start_index;
625 decl.DeclarationRange.Last = end_index;
626 return decl;
627 }
628
629 static struct tgsi_full_declaration
630 make_addr_decl(
631 GLuint start_index,
632 GLuint end_index )
633 {
634 struct tgsi_full_declaration decl;
635
636 decl = tgsi_default_full_declaration();
637 decl.Declaration.File = TGSI_FILE_ADDRESS;
638 decl.DeclarationRange.First = start_index;
639 decl.DeclarationRange.Last = end_index;
640 return decl;
641 }
642
643 static struct tgsi_full_declaration
644 make_sampler_decl(GLuint index)
645 {
646 struct tgsi_full_declaration decl;
647 decl = tgsi_default_full_declaration();
648 decl.Declaration.File = TGSI_FILE_SAMPLER;
649 decl.DeclarationRange.First = index;
650 decl.DeclarationRange.Last = index;
651 return decl;
652 }
653
654 /** Reference into a constant buffer */
655 static struct tgsi_full_declaration
656 make_constant_decl(GLuint first, GLuint last)
657 {
658 struct tgsi_full_declaration decl;
659 decl = tgsi_default_full_declaration();
660 decl.Declaration.File = TGSI_FILE_CONSTANT;
661 decl.DeclarationRange.First = first;
662 decl.DeclarationRange.Last = last;
663 return decl;
664 }
665
666
667
668 /**
669 * Find the temporaries which are used in the given program.
670 */
671 static void
672 find_temporaries(const struct gl_program *program,
673 GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
674 {
675 GLuint i, j;
676
677 for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
678 tempsUsed[i] = GL_FALSE;
679
680 for (i = 0; i < program->NumInstructions; i++) {
681 const struct prog_instruction *inst = program->Instructions + i;
682 const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
683 for (j = 0; j < n; j++) {
684 if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
685 tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
686 if (inst->DstReg.File == PROGRAM_TEMPORARY)
687 tempsUsed[inst->DstReg.Index] = GL_TRUE;
688 }
689 }
690 }
691
692
693
694
695 /**
696 * Translate Mesa program to TGSI format.
697 * \param program the program to translate
698 * \param numInputs number of input registers used
699 * \param inputMapping maps Mesa fragment program inputs to TGSI generic
700 * input indexes
701 * \param inputSemanticName the TGSI_SEMANTIC flag for each input
702 * \param inputSemanticIndex the semantic index (ex: which texcoord) for each input
703 * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
704
705 * \param numOutputs number of output registers used
706 * \param outputMapping maps Mesa fragment program outputs to TGSI
707 * generic outputs
708 * \param outputSemanticName the TGSI_SEMANTIC flag for each output
709 * \param outputSemanticIndex the semantic index (ex: which texcoord) for each output
710 * \param tokens array to store translated tokens in
711 * \param maxTokens size of the tokens array
712 *
713 * \return number of tokens placed in 'tokens' buffer, or zero if error
714 */
715 GLuint
716 tgsi_translate_mesa_program(
717 uint procType,
718 const struct gl_program *program,
719 GLuint numInputs,
720 const GLuint inputMapping[],
721 const ubyte inputSemanticName[],
722 const ubyte inputSemanticIndex[],
723 const GLuint interpMode[],
724 GLuint numOutputs,
725 const GLuint outputMapping[],
726 const ubyte outputSemanticName[],
727 const ubyte outputSemanticIndex[],
728 struct tgsi_token *tokens,
729 GLuint maxTokens )
730 {
731 GLuint i;
732 GLuint ti; /* token index */
733 struct tgsi_header *header;
734 struct tgsi_processor *processor;
735 struct tgsi_full_instruction fullinst;
736 GLuint preamble_size = 0;
737 GLuint immediates[1000];
738 GLuint numImmediates = 0;
739 GLboolean insideSubroutine = GL_FALSE;
740 GLboolean indirectAccess = GL_FALSE;
741
742 assert(procType == TGSI_PROCESSOR_FRAGMENT ||
743 procType == TGSI_PROCESSOR_VERTEX);
744
745 *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
746
747 header = (struct tgsi_header *) &tokens[1];
748 *header = tgsi_build_header();
749
750 processor = (struct tgsi_processor *) &tokens[2];
751 *processor = tgsi_build_processor( procType, header );
752
753 ti = 3;
754
755 /*
756 * Declare input attributes.
757 */
758 if (procType == TGSI_PROCESSOR_FRAGMENT) {
759 for (i = 0; i < numInputs; i++) {
760 struct tgsi_full_declaration fulldecl;
761 fulldecl = make_input_decl(i,
762 GL_TRUE, interpMode[i],
763 TGSI_WRITEMASK_XYZW,
764 GL_TRUE, inputSemanticName[i],
765 inputSemanticIndex[i]);
766 ti += tgsi_build_full_declaration(&fulldecl,
767 &tokens[ti],
768 header,
769 maxTokens - ti );
770 }
771 }
772 else {
773 /* vertex prog */
774 /* XXX: this could probaby be merged with the clause above.
775 * the only difference is the semantic tags.
776 */
777 for (i = 0; i < numInputs; i++) {
778 struct tgsi_full_declaration fulldecl;
779 fulldecl = make_input_decl(i,
780 GL_FALSE, 0,
781 TGSI_WRITEMASK_XYZW,
782 GL_FALSE, 0, 0);
783 ti += tgsi_build_full_declaration(&fulldecl,
784 &tokens[ti],
785 header,
786 maxTokens - ti );
787 }
788 }
789
790 /*
791 * Declare output attributes.
792 */
793 if (procType == TGSI_PROCESSOR_FRAGMENT) {
794 for (i = 0; i < numOutputs; i++) {
795 struct tgsi_full_declaration fulldecl;
796 switch (outputSemanticName[i]) {
797 case TGSI_SEMANTIC_POSITION:
798 fulldecl = make_output_decl(i,
799 TGSI_SEMANTIC_POSITION, /* Z / Depth */
800 outputSemanticIndex[i],
801 TGSI_WRITEMASK_Z );
802 break;
803 case TGSI_SEMANTIC_COLOR:
804 fulldecl = make_output_decl(i,
805 TGSI_SEMANTIC_COLOR,
806 outputSemanticIndex[i],
807 TGSI_WRITEMASK_XYZW );
808 break;
809 default:
810 assert(0);
811 return 0;
812 }
813 ti += tgsi_build_full_declaration(&fulldecl,
814 &tokens[ti],
815 header,
816 maxTokens - ti );
817 }
818 }
819 else {
820 /* vertex prog */
821 for (i = 0; i < numOutputs; i++) {
822 struct tgsi_full_declaration fulldecl;
823 fulldecl = make_output_decl(i,
824 outputSemanticName[i],
825 outputSemanticIndex[i],
826 TGSI_WRITEMASK_XYZW );
827 ti += tgsi_build_full_declaration(&fulldecl,
828 &tokens[ti],
829 header,
830 maxTokens - ti );
831 }
832 }
833
834 /* temporary decls */
835 {
836 GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
837 GLboolean inside_range = GL_FALSE;
838 GLuint start_range = 0;
839
840 find_temporaries(program, tempsUsed);
841 tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
842 for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
843 if (tempsUsed[i] && !inside_range) {
844 inside_range = GL_TRUE;
845 start_range = i;
846 }
847 else if (!tempsUsed[i] && inside_range) {
848 struct tgsi_full_declaration fulldecl;
849
850 inside_range = GL_FALSE;
851 fulldecl = make_temp_decl( start_range, i - 1 );
852 ti += tgsi_build_full_declaration(
853 &fulldecl,
854 &tokens[ti],
855 header,
856 maxTokens - ti );
857 }
858 }
859 }
860
861 /* Declare address register.
862 */
863 if (program->NumAddressRegs > 0) {
864 struct tgsi_full_declaration fulldecl;
865
866 assert( program->NumAddressRegs == 1 );
867
868 fulldecl = make_addr_decl( 0, 0 );
869 ti += tgsi_build_full_declaration(
870 &fulldecl,
871 &tokens[ti],
872 header,
873 maxTokens - ti );
874
875 indirectAccess = GL_TRUE;
876 }
877
878 /* immediates/literals */
879 memset(immediates, ~0, sizeof(immediates));
880
881 /* Emit immediates only when there is no address register in use.
882 * FIXME: Be smarter and recognize param arrays -- indirect addressing is
883 * only valid within the referenced array.
884 */
885 if (program->Parameters && !indirectAccess) {
886 for (i = 0; i < program->Parameters->NumParameters; i++) {
887 if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
888 struct tgsi_full_immediate fullimm;
889
890 fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
891 ti += tgsi_build_full_immediate(
892 &fullimm,
893 &tokens[ti],
894 header,
895 maxTokens - ti );
896 immediates[i] = numImmediates;
897 numImmediates++;
898 }
899 }
900 }
901
902 /* constant buffer refs */
903 if (program->Parameters) {
904 GLint start = -1, end = -1;
905
906 for (i = 0; i < program->Parameters->NumParameters; i++) {
907 GLboolean emit = (i == program->Parameters->NumParameters - 1);
908 GLboolean matches;
909
910 switch (program->Parameters->Parameters[i].Type) {
911 case PROGRAM_ENV_PARAM:
912 case PROGRAM_STATE_VAR:
913 case PROGRAM_NAMED_PARAM:
914 case PROGRAM_UNIFORM:
915 matches = GL_TRUE;
916 break;
917 case PROGRAM_CONSTANT:
918 matches = indirectAccess;
919 break;
920 default:
921 matches = GL_FALSE;
922 }
923
924 if (matches) {
925 if (start == -1) {
926 /* begin a sequence */
927 start = i;
928 end = i;
929 }
930 else {
931 /* continue sequence */
932 end = i;
933 }
934 }
935 else {
936 if (start != -1) {
937 /* end of sequence */
938 emit = GL_TRUE;
939 }
940 }
941
942 if (emit && start >= 0) {
943 struct tgsi_full_declaration fulldecl;
944
945 fulldecl = make_constant_decl( start, end );
946 ti += tgsi_build_full_declaration(
947 &fulldecl,
948 &tokens[ti],
949 header,
950 maxTokens - ti );
951 start = end = -1;
952 }
953 }
954 }
955
956 /* texture samplers */
957 for (i = 0; i < 8; i++) {
958 if (program->SamplersUsed & (1 << i)) {
959 struct tgsi_full_declaration fulldecl;
960
961 fulldecl = make_sampler_decl( i );
962 ti += tgsi_build_full_declaration(
963 &fulldecl,
964 &tokens[ti],
965 header,
966 maxTokens - ti );
967 }
968 }
969
970 for (i = 0; i < program->NumInstructions; i++) {
971 compile_instruction(
972 &program->Instructions[i],
973 &fullinst,
974 inputMapping,
975 outputMapping,
976 immediates,
977 indirectAccess,
978 preamble_size,
979 procType,
980 &insideSubroutine );
981
982 ti += tgsi_build_full_instruction(
983 &fullinst,
984 &tokens[ti],
985 header,
986 maxTokens - ti );
987 }
988
989 #if DEBUG
990 if(!tgsi_sanity_check(tokens)) {
991 debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
992 debug_printf("\nOriginal program:\n%s", program->String);
993 debug_printf("\nMesa program:\n");
994 _mesa_print_program(program);
995 debug_printf("\nTGSI program:\n");
996 tgsi_dump(tokens, 0);
997 assert(0);
998 }
999 #endif
1000
1001 return ti;
1002 }