Translate MESA GLSL opcodes to TGSI opcodes.
[mesa.git] / src / mesa / pipe / tgsi / mesa / mesa_to_tgsi.c
1 #include "tgsi_platform.h"
2 #include "tgsi_mesa.h"
3
4 /*
5 * Map mesa register file to SBIR register file.
6 */
7 static GLuint
8 map_register_file(
9 enum register_file file )
10 {
11 switch( file ) {
12 case PROGRAM_UNDEFINED:
13 return TGSI_FILE_NULL;
14 case PROGRAM_TEMPORARY:
15 return TGSI_FILE_TEMPORARY;
16 //case PROGRAM_LOCAL_PARAM:
17 //case PROGRAM_ENV_PARAM:
18 case PROGRAM_STATE_VAR:
19 case PROGRAM_NAMED_PARAM:
20 case PROGRAM_CONSTANT:
21 case PROGRAM_UNIFORM:
22 return TGSI_FILE_CONSTANT;
23 case PROGRAM_INPUT:
24 return TGSI_FILE_INPUT;
25 case PROGRAM_OUTPUT:
26 return TGSI_FILE_OUTPUT;
27 case PROGRAM_ADDRESS:
28 return TGSI_FILE_ADDRESS;
29 default:
30 assert( 0 );
31 return TGSI_FILE_NULL;
32 }
33 }
34
35 /**
36 * Map mesa register file index to SBIR index.
37 * Take special care when processing input and output indices.
38 * \param processor either TGSI_PROCESSOR_FRAGMENT or TGSI_PROCESSOR_VERTEX
39 * \param file one of TGSI_FILE_x
40 * \param index the mesa register file index
41 * \param usage_bitmask ???
42 */
43 static GLuint
44 map_register_file_index(
45 GLuint processor,
46 GLuint file,
47 GLuint index,
48 GLbitfield usage_bitmask )
49 {
50 GLuint mapped_index;
51 GLuint i;
52
53 switch( file ) {
54 case TGSI_FILE_INPUT:
55 /*
56 * The fragment/vertex program input indexes (FRAG/VERT_ATTRIB_x) get
57 * mapped to a packed sequence of integers.
58 * If a program uses one input attribute, the mapped index will be 1.
59 * If a program uses two input attribs, the mapped indexes will be 1,2.
60 * If a program uses 3 input attribs, the mapped indexes will be 1,2,3.
61 * etc.
62 */
63 assert( index < 32 );
64 assert( usage_bitmask & (1 << index) );
65 mapped_index = 0;
66 for( i = 0; i < index; i++ ) {
67 if( usage_bitmask & (1 << i) ) {
68 mapped_index++;
69 }
70 }
71 printf("Map input %d to %d\n", index, mapped_index);
72 break;
73
74 case TGSI_FILE_OUTPUT:
75 assert( usage_bitmask == 0x0 );
76 if( processor == TGSI_PROCESSOR_FRAGMENT ) {
77 /* depth result -> index 0
78 * color results -> index 1, 2, ...
79 */
80 if( index == FRAG_RESULT_DEPR ) {
81 mapped_index = 0;
82 }
83 else {
84 assert( index == FRAG_RESULT_COLR );
85 mapped_index = index + 1;
86 }
87 }
88 else {
89 /* mapped_index = VERT_RESULT_x */
90 mapped_index = index;
91 }
92 break;
93
94 default:
95 mapped_index = index;
96 }
97
98 return mapped_index;
99 }
100
101 /*
102 * Map mesa texture target to SBIR texture target.
103 */
104 static GLuint
105 map_texture_target(
106 GLuint textarget )
107 {
108 switch( textarget ) {
109 case TEXTURE_1D_INDEX:
110 return TGSI_TEXTURE_1D;
111 case TEXTURE_2D_INDEX:
112 return TGSI_TEXTURE_2D;
113 case TEXTURE_3D_INDEX:
114 return TGSI_TEXTURE_3D;
115 case TEXTURE_CUBE_INDEX:
116 return TGSI_TEXTURE_CUBE;
117 case TEXTURE_RECT_INDEX:
118 return TGSI_TEXTURE_RECT;
119 default:
120 assert( 0 );
121 }
122
123 return TGSI_TEXTURE_1D;
124 }
125
126 static GLuint
127 convert_sat(
128 GLuint sat )
129 {
130 switch( sat ) {
131 case SATURATE_OFF:
132 return TGSI_SAT_NONE;
133 case SATURATE_ZERO_ONE:
134 return TGSI_SAT_ZERO_ONE;
135 case SATURATE_PLUS_MINUS_ONE:
136 return TGSI_SAT_MINUS_PLUS_ONE;
137 default:
138 assert( 0 );
139 return TGSI_SAT_NONE;
140 }
141 }
142
143 static GLuint
144 convert_writemask(
145 GLuint writemask )
146 {
147 assert( WRITEMASK_X == TGSI_WRITEMASK_X );
148 assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
149 assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
150 assert( WRITEMASK_W == TGSI_WRITEMASK_W );
151 assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
152
153 return writemask;
154 }
155
156 static GLboolean
157 compile_instruction(
158 const struct prog_instruction *inst,
159 struct tgsi_full_instruction *fullinst,
160 GLuint inputs_read,
161 GLuint processor )
162 {
163 GLuint i;
164 struct tgsi_full_dst_register *fulldst;
165 struct tgsi_full_src_register *fullsrc;
166
167 *fullinst = tgsi_default_full_instruction();
168
169 fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
170 fullinst->Instruction.NumDstRegs = 1;
171 fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
172
173 fulldst = &fullinst->FullDstRegisters[0];
174 fulldst->DstRegister.File = map_register_file( inst->DstReg.File );
175 fulldst->DstRegister.Index = map_register_file_index(
176 processor,
177 fulldst->DstRegister.File,
178 inst->DstReg.Index,
179 0x0 );
180 fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
181
182 for( i = 0; i < fullinst->Instruction.NumSrcRegs; i++ ) {
183 GLuint j;
184
185 fullsrc = &fullinst->FullSrcRegisters[i];
186 fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File );
187 fullsrc->SrcRegister.Index = map_register_file_index(
188 processor,
189 fullsrc->SrcRegister.File,
190 inst->SrcReg[i].Index,
191 inputs_read );
192
193 for( j = 0; j < 4; j++ ) {
194 GLuint swz;
195
196 swz = GET_SWZ( inst->SrcReg[i].Swizzle, j );
197 if( swz > SWIZZLE_W ) {
198 tgsi_util_set_src_register_extswizzle(
199 &fullsrc->SrcRegisterExtSwz,
200 swz,
201 j );
202 }
203 else {
204 tgsi_util_set_src_register_swizzle(
205 &fullsrc->SrcRegister,
206 swz,
207 j );
208 }
209 }
210
211 if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {
212 fullsrc->SrcRegister.Negate = 1;
213 }
214 else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {
215 if( inst->SrcReg[i].NegateBase & NEGATE_X ) {
216 fullsrc->SrcRegisterExtSwz.NegateX = 1;
217 }
218 if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {
219 fullsrc->SrcRegisterExtSwz.NegateY = 1;
220 }
221 if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {
222 fullsrc->SrcRegisterExtSwz.NegateZ = 1;
223 }
224 if( inst->SrcReg[i].NegateBase & NEGATE_W ) {
225 fullsrc->SrcRegisterExtSwz.NegateW = 1;
226 }
227 }
228
229 if( inst->SrcReg[i].Abs ) {
230 fullsrc->SrcRegisterExtMod.Absolute = 1;
231 }
232
233 if( inst->SrcReg[i].NegateAbs ) {
234 fullsrc->SrcRegisterExtMod.Negate = 1;
235 }
236
237 if( inst->SrcReg[i].RelAddr ) {
238 fullsrc->SrcRegister.Indirect = 1;
239
240 fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
241 fullsrc->SrcRegisterInd.Index = 0;
242 }
243 }
244
245 switch( inst->Opcode ) {
246 case OPCODE_ARL:
247 fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
248 break;
249 case OPCODE_ABS:
250 fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
251 break;
252 case OPCODE_ADD:
253 fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
254 break;
255 case OPCODE_CMP:
256 fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
257 break;
258 case OPCODE_COS:
259 fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
260 break;
261 case OPCODE_DP3:
262 fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
263 break;
264 case OPCODE_DDX:
265 fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
266 break;
267 case OPCODE_DDY:
268 fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
269 break;
270 case OPCODE_DP4:
271 fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
272 break;
273 case OPCODE_DPH:
274 fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
275 break;
276 case OPCODE_DST:
277 fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
278 break;
279 case OPCODE_EX2:
280 fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
281 break;
282 case OPCODE_FLR:
283 fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
284 break;
285 case OPCODE_FRC:
286 fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
287 break;
288 case OPCODE_KIL:
289 fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
290 break;
291 case OPCODE_LG2:
292 fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
293 break;
294 case OPCODE_LIT:
295 fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
296 break;
297 case OPCODE_LRP:
298 fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
299 break;
300 case OPCODE_MAD:
301 fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
302 break;
303 case OPCODE_MAX:
304 fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
305 break;
306 case OPCODE_MIN:
307 fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
308 break;
309 case OPCODE_MOV:
310 fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
311 break;
312 case OPCODE_MUL:
313 fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
314 break;
315 case OPCODE_POW:
316 fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
317 break;
318 case OPCODE_RCP:
319 fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
320 break;
321 case OPCODE_RSQ:
322 fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
323 tgsi_util_set_full_src_register_sign_mode(
324 &fullinst->FullSrcRegisters[0],
325 TGSI_UTIL_SIGN_CLEAR );
326 break;
327 case OPCODE_SCS:
328 fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
329 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
330 break;
331 case OPCODE_SGE:
332 fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
333 break;
334 case OPCODE_SIN:
335 fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
336 break;
337 case OPCODE_SLT:
338 fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
339 break;
340 case OPCODE_SUB:
341 fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
342 break;
343 case OPCODE_SWZ:
344 fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
345 break;
346 case OPCODE_TEX:
347 fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
348 fullinst->Instruction.NumSrcRegs = 2;
349 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
350 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
351 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
352 break;
353 case OPCODE_TXB:
354 fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
355 fullinst->Instruction.NumSrcRegs = 2;
356 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
357 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
358 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
359 break;
360 case OPCODE_TXP:
361 fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
362 fullinst->Instruction.NumSrcRegs = 2;
363 fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
364 fullinst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide = TGSI_EXTSWIZZLE_W;
365 fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
366 fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
367 break;
368 case OPCODE_XPD:
369 fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
370 fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
371 break;
372 case OPCODE_NOP:
373 fullinst->Instruction.Opcode = TGSI_OPCODE_NOP;
374 break;
375 case OPCODE_BGNLOOP:
376 fullinst->Instruction.Opcode = TGSI_OPCODE_BGNLOOP2;
377 break;
378 case OPCODE_BGNSUB:
379 fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
380 break;
381 case OPCODE_ENDLOOP:
382 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDLOOP2;
383 break;
384 case OPCODE_ENDSUB:
385 fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
386 break;
387 case OPCODE_NOISE1:
388 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE1;
389 break;
390 case OPCODE_NOISE2:
391 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE2;
392 break;
393 case OPCODE_NOISE3:
394 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE3;
395 break;
396 case OPCODE_NOISE4:
397 fullinst->Instruction.Opcode = TGSI_OPCODE_NOISE4;
398 break;
399 case OPCODE_END:
400 return GL_TRUE;
401 default:
402 assert( 0 );
403 }
404
405 return GL_FALSE;
406 }
407
408 GLboolean
409 tgsi_mesa_compile_fp_program(
410 const struct gl_fragment_program *program,
411 struct tgsi_token *tokens,
412 GLuint maxTokens )
413 {
414 GLuint i, ti;
415 struct tgsi_header *header;
416 struct tgsi_full_declaration fulldecl;
417 struct tgsi_full_instruction fullinst;
418 struct tgsi_full_dst_register *fulldst;
419 struct tgsi_full_src_register *fullsrc;
420 GLuint inputs_read;
421
422 *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
423
424 header = (struct tgsi_header *) &tokens[1];
425 *header = tgsi_build_header();
426
427 ti = 2;
428
429 /*
430 * Input 0 is always read, at least implicitly by the instruction generated
431 * above, so mark it as used.
432 */
433 inputs_read = program->Base.InputsRead | 1;
434
435 /*
436 * Declare input attributes.
437 */
438 fulldecl = tgsi_default_full_declaration();
439
440 fulldecl.Declaration.File = TGSI_FILE_INPUT;
441 fulldecl.Declaration.Declare = TGSI_DECLARE_RANGE;
442 fulldecl.Declaration.Interpolate = 1;
443
444 /*
445 * Do not interpolate fragment position.
446 */
447 fulldecl.u.DeclarationRange.First = 0;
448 fulldecl.u.DeclarationRange.Last = 0;
449
450 fulldecl.Interpolation.Interpolate = TGSI_INTERPOLATE_CONSTANT;
451
452 ti += tgsi_build_full_declaration(
453 &fulldecl,
454 &tokens[ti],
455 header,
456 maxTokens - ti );
457
458 /*
459 * Interpolate generic attributes.
460 */
461 fulldecl.u.DeclarationRange.First = 1;
462 fulldecl.u.DeclarationRange.Last = 1;
463 for( i = 1; i < 32; i++ ) {
464 if( inputs_read & (1 << i) ) {
465 fulldecl.u.DeclarationRange.Last++;
466 }
467 }
468
469 fulldecl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR;
470
471 ti += tgsi_build_full_declaration(
472 &fulldecl,
473 &tokens[ti],
474 header,
475 maxTokens - ti );
476
477 /*
478 * Copy input fragment xyz to output xyz.
479 * If the shader writes depth, do not copy the z component.
480 */
481
482 fullinst = tgsi_default_full_instruction();
483
484 fullinst.Instruction.Opcode = TGSI_OPCODE_MOV;
485 fullinst.Instruction.NumDstRegs = 1;
486 fullinst.Instruction.NumSrcRegs = 1;
487
488 fulldst = &fullinst.FullDstRegisters[0];
489 fulldst->DstRegister.File = TGSI_FILE_OUTPUT;
490 fulldst->DstRegister.Index = 0;
491 if( program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR) ) {
492 fulldst->DstRegister.WriteMask = TGSI_WRITEMASK_XY;
493 }
494 else {
495 fulldst->DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;
496 }
497
498 fullsrc = &fullinst.FullSrcRegisters[0];
499 fullsrc->SrcRegister.File = TGSI_FILE_INPUT;
500 fullsrc->SrcRegister.Index = 0;
501
502 ti += tgsi_build_full_instruction(
503 &fullinst,
504 &tokens[ti],
505 header,
506 maxTokens - ti );
507
508 for( i = 0; i < program->Base.NumInstructions; i++ ) {
509 if( compile_instruction(
510 &program->Base.Instructions[i],
511 &fullinst,
512 inputs_read,
513 TGSI_PROCESSOR_FRAGMENT ) ) {
514 assert( i == program->Base.NumInstructions - 1 );
515 tgsi_dump(
516 tokens,
517 TGSI_DUMP_NO_IGNORED | TGSI_DUMP_NO_DEFAULT );
518 break;
519 }
520
521 ti += tgsi_build_full_instruction(
522 &fullinst,
523 &tokens[ti],
524 header,
525 maxTokens - ti );
526 }
527
528 return GL_TRUE;
529 }
530
531 GLboolean
532 tgsi_mesa_compile_vp_program(
533 const struct gl_vertex_program *program,
534 struct tgsi_token *tokens,
535 GLuint maxTokens )
536 {
537 GLuint ii, ti;
538 struct tgsi_header *header;
539 struct tgsi_processor *processor;
540 struct tgsi_full_instruction fullinst;
541 GLuint inputs_read = ~0;
542
543 *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
544
545 header = (struct tgsi_header *) &tokens[1];
546 *header = tgsi_build_header();
547
548 processor = (struct tgsi_processor *) &tokens[2];
549 *processor = tgsi_build_processor( TGSI_PROCESSOR_VERTEX, header );
550
551 ti = 3;
552
553 for( ii = 0; ii < program->Base.NumInstructions; ii++ ) {
554 if( compile_instruction(
555 &program->Base.Instructions[ii],
556 &fullinst,
557 inputs_read,
558 TGSI_PROCESSOR_VERTEX ) ) {
559 assert( ii == program->Base.NumInstructions - 1 );
560 tgsi_dump( tokens, TGSI_DUMP_NO_IGNORED | TGSI_DUMP_NO_DEFAULT );
561 break;
562 }
563
564 ti += tgsi_build_full_instruction(
565 &fullinst,
566 &tokens[ti],
567 header,
568 maxTokens - ti );
569 }
570
571 return GL_TRUE;
572 }
573