Merge commit 'origin/gallium-0.1' 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_DP2:
350 fullinst->Instruction.Opcode = TGSI_OPCODE_DP2;
351 break;
352 case OPCODE_DP2A:
353 fullinst->Instruction.Opcode = TGSI_OPCODE_DP2A;
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_TRUNC:
399 fullinst->Instruction.Opcode = TGSI_OPCODE_TRUNC;
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_NRM3:
453 fullinst->Instruction.Opcode = TGSI_OPCODE_NRM;
454 break;
455 case OPCODE_NRM4:
456 fullinst->Instruction.Opcode = TGSI_OPCODE_NRM4;
457 break;
458 case OPCODE_POW:
459 fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
460 break;
461 case OPCODE_RCP:
462 fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
463 break;
464 case OPCODE_RET:
465 /* If RET is used inside main (not a real subroutine) we may want
466 * to execute END instead of RET. TBD...
467 */
468 if (1 /* *insideSubroutine */) {
469 fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
470 }
471 else {
472 /* inside main() pseudo-function */
473 fullinst->Instruction.Opcode = TGSI_OPCODE_END;
474 }
475 break;
476 case OPCODE_RSQ:
477 fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
478 tgsi_util_set_full_src_register_sign_mode(
479 &fullinst->FullSrcRegisters[0],
480 TGSI_UTIL_SIGN_CLEAR );
481 break;
482 case OPCODE_SCS:
483 fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
484 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
485 break;
486 case OPCODE_SEQ:
487 fullinst->Instruction.Opcode = TGSI_OPCODE_SEQ;
488 break;
489 case OPCODE_SGE:
490 fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
491 break;
492 case OPCODE_SGT:
493 fullinst->Instruction.Opcode = TGSI_OPCODE_SGT;
494 break;
495 case OPCODE_SIN:
496 fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
497 break;
498 case OPCODE_SLE:
499 fullinst->Instruction.Opcode = TGSI_OPCODE_SLE;
500 break;
501 case OPCODE_SLT:
502 fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
503 break;
504 case OPCODE_SNE:
505 fullinst->Instruction.Opcode = TGSI_OPCODE_SNE;
506 break;
507 case OPCODE_SSG:
508 fullinst->Instruction.Opcode = TGSI_OPCODE_SSG;
509 break;
510 case OPCODE_SUB:
511 fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
512 break;
513 case OPCODE_SWZ:
514 fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
515 break;
516 case OPCODE_TEX:
517 /* ordinary texture lookup */
518 fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
519 fullinst->Instruction.NumSrcRegs = 2;
520 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
521 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
522 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
523 break;
524 case OPCODE_TXB:
525 /* texture lookup with LOD bias */
526 fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
527 fullinst->Instruction.NumSrcRegs = 2;
528 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
529 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
530 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
531 break;
532 case OPCODE_TXD:
533 /* texture lookup with explicit partial derivatives */
534 fullinst->Instruction.Opcode = TGSI_OPCODE_TXD;
535 fullinst->Instruction.NumSrcRegs = 4;
536 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
537 /* src[0] = coord, src[1] = d[strq]/dx, src[2] = d[strq]/dy */
538 fullinst->FullSrcRegisters[3].SrcRegister.File = TGSI_FILE_SAMPLER;
539 fullinst->FullSrcRegisters[3].SrcRegister.Index = inst->TexSrcUnit;
540 break;
541 case OPCODE_TXL:
542 /* texture lookup with explicit LOD */
543 fullinst->Instruction.Opcode = TGSI_OPCODE_TXL;
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_TXP:
550 /* texture lookup with divide by Q component */
551 /* convert to TEX w/ special flag for division */
552 fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
553 fullinst->Instruction.NumSrcRegs = 2;
554 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
555 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
556 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
557 break;
558 case OPCODE_XPD:
559 fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
560 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
561 break;
562 case OPCODE_END:
563 fullinst->Instruction.Opcode = TGSI_OPCODE_END;
564 break;
565 default:
566 assert( 0 );
567 }
568 }
569
570 /**
571 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
572 */
573 static struct tgsi_full_declaration
574 make_input_decl(
575 GLuint index,
576 GLboolean interpolate_info,
577 GLuint interpolate,
578 GLuint usage_mask,
579 GLboolean semantic_info,
580 GLuint semantic_name,
581 GLbitfield semantic_index )
582 {
583 struct tgsi_full_declaration decl;
584
585 assert(semantic_name < TGSI_SEMANTIC_COUNT);
586
587 decl = tgsi_default_full_declaration();
588 decl.Declaration.File = TGSI_FILE_INPUT;
589 decl.Declaration.UsageMask = usage_mask;
590 decl.Declaration.Semantic = semantic_info;
591 decl.DeclarationRange.First = index;
592 decl.DeclarationRange.Last = index;
593 if (semantic_info) {
594 decl.Semantic.SemanticName = semantic_name;
595 decl.Semantic.SemanticIndex = semantic_index;
596 }
597 if (interpolate_info) {
598 decl.Declaration.Interpolate = interpolate;
599 }
600
601 return decl;
602 }
603
604 /**
605 * \param usage_mask bitfield of TGSI_WRITEMASK_{XYZW} tokens
606 */
607 static struct tgsi_full_declaration
608 make_output_decl(
609 GLuint index,
610 GLuint semantic_name,
611 GLuint semantic_index,
612 GLbitfield usage_mask )
613 {
614 struct tgsi_full_declaration decl;
615
616 assert(semantic_name < TGSI_SEMANTIC_COUNT);
617
618 decl = tgsi_default_full_declaration();
619 decl.Declaration.File = TGSI_FILE_OUTPUT;
620 decl.Declaration.UsageMask = usage_mask;
621 decl.Declaration.Semantic = 1;
622 decl.DeclarationRange.First = index;
623 decl.DeclarationRange.Last = index;
624 decl.Semantic.SemanticName = semantic_name;
625 decl.Semantic.SemanticIndex = semantic_index;
626
627 return decl;
628 }
629
630
631 static struct tgsi_full_declaration
632 make_temp_decl(
633 GLuint start_index,
634 GLuint end_index )
635 {
636 struct tgsi_full_declaration decl;
637 decl = tgsi_default_full_declaration();
638 decl.Declaration.File = TGSI_FILE_TEMPORARY;
639 decl.DeclarationRange.First = start_index;
640 decl.DeclarationRange.Last = end_index;
641 return decl;
642 }
643
644 static struct tgsi_full_declaration
645 make_addr_decl(
646 GLuint start_index,
647 GLuint end_index )
648 {
649 struct tgsi_full_declaration decl;
650
651 decl = tgsi_default_full_declaration();
652 decl.Declaration.File = TGSI_FILE_ADDRESS;
653 decl.DeclarationRange.First = start_index;
654 decl.DeclarationRange.Last = end_index;
655 return decl;
656 }
657
658 static struct tgsi_full_declaration
659 make_sampler_decl(GLuint index)
660 {
661 struct tgsi_full_declaration decl;
662 decl = tgsi_default_full_declaration();
663 decl.Declaration.File = TGSI_FILE_SAMPLER;
664 decl.DeclarationRange.First = index;
665 decl.DeclarationRange.Last = index;
666 return decl;
667 }
668
669 /** Reference into a constant buffer */
670 static struct tgsi_full_declaration
671 make_constant_decl(GLuint first, GLuint last)
672 {
673 struct tgsi_full_declaration decl;
674 decl = tgsi_default_full_declaration();
675 decl.Declaration.File = TGSI_FILE_CONSTANT;
676 decl.DeclarationRange.First = first;
677 decl.DeclarationRange.Last = last;
678 return decl;
679 }
680
681
682
683 /**
684 * Find the temporaries which are used in the given program.
685 */
686 static void
687 find_temporaries(const struct gl_program *program,
688 GLboolean tempsUsed[MAX_PROGRAM_TEMPS])
689 {
690 GLuint i, j;
691
692 for (i = 0; i < MAX_PROGRAM_TEMPS; i++)
693 tempsUsed[i] = GL_FALSE;
694
695 for (i = 0; i < program->NumInstructions; i++) {
696 const struct prog_instruction *inst = program->Instructions + i;
697 const GLuint n = _mesa_num_inst_src_regs( inst->Opcode );
698 for (j = 0; j < n; j++) {
699 if (inst->SrcReg[j].File == PROGRAM_TEMPORARY)
700 tempsUsed[inst->SrcReg[j].Index] = GL_TRUE;
701 if (inst->DstReg.File == PROGRAM_TEMPORARY)
702 tempsUsed[inst->DstReg.Index] = GL_TRUE;
703 }
704 }
705 }
706
707
708
709
710 /**
711 * Translate Mesa program to TGSI format.
712 * \param program the program to translate
713 * \param numInputs number of input registers used
714 * \param inputMapping maps Mesa fragment program inputs to TGSI generic
715 * input indexes
716 * \param inputSemanticName the TGSI_SEMANTIC flag for each input
717 * \param inputSemanticIndex the semantic index (ex: which texcoord) for each input
718 * \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
719
720 * \param numOutputs number of output registers used
721 * \param outputMapping maps Mesa fragment program outputs to TGSI
722 * generic outputs
723 * \param outputSemanticName the TGSI_SEMANTIC flag for each output
724 * \param outputSemanticIndex the semantic index (ex: which texcoord) for each output
725 * \param tokens array to store translated tokens in
726 * \param maxTokens size of the tokens array
727 *
728 * \return number of tokens placed in 'tokens' buffer, or zero if error
729 */
730 GLuint
731 st_translate_mesa_program(
732 uint procType,
733 const struct gl_program *program,
734 GLuint numInputs,
735 const GLuint inputMapping[],
736 const ubyte inputSemanticName[],
737 const ubyte inputSemanticIndex[],
738 const GLuint interpMode[],
739 GLuint numOutputs,
740 const GLuint outputMapping[],
741 const ubyte outputSemanticName[],
742 const ubyte outputSemanticIndex[],
743 struct tgsi_token *tokens,
744 GLuint maxTokens )
745 {
746 GLuint i;
747 GLuint ti; /* token index */
748 struct tgsi_header *header;
749 struct tgsi_processor *processor;
750 struct tgsi_full_instruction fullinst;
751 GLuint preamble_size = 0;
752 GLuint immediates[1000];
753 GLuint numImmediates = 0;
754 GLboolean insideSubroutine = GL_FALSE;
755 GLboolean indirectAccess = GL_FALSE;
756
757 assert(procType == TGSI_PROCESSOR_FRAGMENT ||
758 procType == TGSI_PROCESSOR_VERTEX);
759
760 *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
761
762 header = (struct tgsi_header *) &tokens[1];
763 *header = tgsi_build_header();
764
765 processor = (struct tgsi_processor *) &tokens[2];
766 *processor = tgsi_build_processor( procType, header );
767
768 ti = 3;
769
770 /*
771 * Declare input attributes.
772 */
773 if (procType == TGSI_PROCESSOR_FRAGMENT) {
774 for (i = 0; i < numInputs; i++) {
775 struct tgsi_full_declaration fulldecl;
776 fulldecl = make_input_decl(i,
777 GL_TRUE, interpMode[i],
778 TGSI_WRITEMASK_XYZW,
779 GL_TRUE, inputSemanticName[i],
780 inputSemanticIndex[i]);
781 ti += tgsi_build_full_declaration(&fulldecl,
782 &tokens[ti],
783 header,
784 maxTokens - ti );
785 }
786 }
787 else {
788 /* vertex prog */
789 /* XXX: this could probaby be merged with the clause above.
790 * the only difference is the semantic tags.
791 */
792 for (i = 0; i < numInputs; i++) {
793 struct tgsi_full_declaration fulldecl;
794 fulldecl = make_input_decl(i,
795 GL_FALSE, 0,
796 TGSI_WRITEMASK_XYZW,
797 GL_FALSE, 0, 0);
798 ti += tgsi_build_full_declaration(&fulldecl,
799 &tokens[ti],
800 header,
801 maxTokens - ti );
802 }
803 }
804
805 /*
806 * Declare output attributes.
807 */
808 if (procType == TGSI_PROCESSOR_FRAGMENT) {
809 for (i = 0; i < numOutputs; i++) {
810 struct tgsi_full_declaration fulldecl;
811 switch (outputSemanticName[i]) {
812 case TGSI_SEMANTIC_POSITION:
813 fulldecl = make_output_decl(i,
814 TGSI_SEMANTIC_POSITION, /* Z / Depth */
815 outputSemanticIndex[i],
816 TGSI_WRITEMASK_Z );
817 break;
818 case TGSI_SEMANTIC_COLOR:
819 fulldecl = make_output_decl(i,
820 TGSI_SEMANTIC_COLOR,
821 outputSemanticIndex[i],
822 TGSI_WRITEMASK_XYZW );
823 break;
824 default:
825 assert(0);
826 return 0;
827 }
828 ti += tgsi_build_full_declaration(&fulldecl,
829 &tokens[ti],
830 header,
831 maxTokens - ti );
832 }
833 }
834 else {
835 /* vertex prog */
836 for (i = 0; i < numOutputs; i++) {
837 struct tgsi_full_declaration fulldecl;
838 fulldecl = make_output_decl(i,
839 outputSemanticName[i],
840 outputSemanticIndex[i],
841 TGSI_WRITEMASK_XYZW );
842 ti += tgsi_build_full_declaration(&fulldecl,
843 &tokens[ti],
844 header,
845 maxTokens - ti );
846 }
847 }
848
849 /* temporary decls */
850 {
851 GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
852 GLboolean inside_range = GL_FALSE;
853 GLuint start_range = 0;
854
855 find_temporaries(program, tempsUsed);
856 tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
857 for (i = 0; i < MAX_PROGRAM_TEMPS + 1; i++) {
858 if (tempsUsed[i] && !inside_range) {
859 inside_range = GL_TRUE;
860 start_range = i;
861 }
862 else if (!tempsUsed[i] && inside_range) {
863 struct tgsi_full_declaration fulldecl;
864
865 inside_range = GL_FALSE;
866 fulldecl = make_temp_decl( start_range, i - 1 );
867 ti += tgsi_build_full_declaration(
868 &fulldecl,
869 &tokens[ti],
870 header,
871 maxTokens - ti );
872 }
873 }
874 }
875
876 /* Declare address register.
877 */
878 if (program->NumAddressRegs > 0) {
879 struct tgsi_full_declaration fulldecl;
880
881 assert( program->NumAddressRegs == 1 );
882
883 fulldecl = make_addr_decl( 0, 0 );
884 ti += tgsi_build_full_declaration(
885 &fulldecl,
886 &tokens[ti],
887 header,
888 maxTokens - ti );
889
890 indirectAccess = GL_TRUE;
891 }
892
893 /* immediates/literals */
894 memset(immediates, ~0, sizeof(immediates));
895
896 /* Emit immediates only when there is no address register in use.
897 * FIXME: Be smarter and recognize param arrays -- indirect addressing is
898 * only valid within the referenced array.
899 */
900 if (program->Parameters && !indirectAccess) {
901 for (i = 0; i < program->Parameters->NumParameters; i++) {
902 if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
903 struct tgsi_full_immediate fullimm;
904
905 fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
906 ti += tgsi_build_full_immediate(
907 &fullimm,
908 &tokens[ti],
909 header,
910 maxTokens - ti );
911 immediates[i] = numImmediates;
912 numImmediates++;
913 }
914 }
915 }
916
917 /* constant buffer refs */
918 if (program->Parameters) {
919 GLint start = -1, end = -1;
920
921 for (i = 0; i < program->Parameters->NumParameters; i++) {
922 GLboolean emit = (i == program->Parameters->NumParameters - 1);
923 GLboolean matches;
924
925 switch (program->Parameters->Parameters[i].Type) {
926 case PROGRAM_ENV_PARAM:
927 case PROGRAM_STATE_VAR:
928 case PROGRAM_NAMED_PARAM:
929 case PROGRAM_UNIFORM:
930 matches = GL_TRUE;
931 break;
932 case PROGRAM_CONSTANT:
933 matches = indirectAccess;
934 break;
935 default:
936 matches = GL_FALSE;
937 }
938
939 if (matches) {
940 if (start == -1) {
941 /* begin a sequence */
942 start = i;
943 end = i;
944 }
945 else {
946 /* continue sequence */
947 end = i;
948 }
949 }
950 else {
951 if (start != -1) {
952 /* end of sequence */
953 emit = GL_TRUE;
954 }
955 }
956
957 if (emit && start >= 0) {
958 struct tgsi_full_declaration fulldecl;
959
960 fulldecl = make_constant_decl( start, end );
961 ti += tgsi_build_full_declaration(
962 &fulldecl,
963 &tokens[ti],
964 header,
965 maxTokens - ti );
966 start = end = -1;
967 }
968 }
969 }
970
971 /* texture samplers */
972 for (i = 0; i < 8; i++) {
973 if (program->SamplersUsed & (1 << i)) {
974 struct tgsi_full_declaration fulldecl;
975
976 fulldecl = make_sampler_decl( i );
977 ti += tgsi_build_full_declaration(
978 &fulldecl,
979 &tokens[ti],
980 header,
981 maxTokens - ti );
982 }
983 }
984
985 for (i = 0; i < program->NumInstructions; i++) {
986 compile_instruction(
987 &program->Instructions[i],
988 &fullinst,
989 inputMapping,
990 outputMapping,
991 immediates,
992 indirectAccess,
993 preamble_size,
994 procType,
995 &insideSubroutine );
996
997 ti += tgsi_build_full_instruction(
998 &fullinst,
999 &tokens[ti],
1000 header,
1001 maxTokens - ti );
1002 }
1003
1004 #if DEBUG
1005 if(!tgsi_sanity_check(tokens)) {
1006 debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
1007 debug_printf("\nOriginal program:\n%s", program->String);
1008 debug_printf("\nMesa program:\n");
1009 _mesa_print_program(program);
1010 debug_printf("\nTGSI program:\n");
1011 tgsi_dump(tokens, 0);
1012 assert(0);
1013 }
1014 #endif
1015
1016 return ti;
1017 }