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