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