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