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