nvc0: fix unitialized variable in TGSI sysval decl processing
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_program.c
1 /*
2 * Copyright 2010 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "pipe/p_shader_tokens.h"
24 #include "pipe/p_defines.h"
25
26 #define NOUVEAU_DEBUG
27
28 #include "tgsi/tgsi_parse.h"
29 #include "tgsi/tgsi_util.h"
30 #include "tgsi/tgsi_dump.h"
31
32 #include "nvc0_context.h"
33 #include "nvc0_pc.h"
34
35 static unsigned
36 nvc0_tgsi_src_mask(const struct tgsi_full_instruction *inst, int c)
37 {
38 unsigned mask = inst->Dst[0].Register.WriteMask;
39
40 switch (inst->Instruction.Opcode) {
41 case TGSI_OPCODE_COS:
42 case TGSI_OPCODE_SIN:
43 return (mask & 0x8) | ((mask & 0x7) ? 0x1 : 0x0);
44 case TGSI_OPCODE_DP3:
45 return 0x7;
46 case TGSI_OPCODE_DP4:
47 case TGSI_OPCODE_DPH:
48 case TGSI_OPCODE_KIL: /* WriteMask ignored */
49 return 0xf;
50 case TGSI_OPCODE_DST:
51 return mask & (c ? 0xa : 0x6);
52 case TGSI_OPCODE_EX2:
53 case TGSI_OPCODE_EXP:
54 case TGSI_OPCODE_LG2:
55 case TGSI_OPCODE_LOG:
56 case TGSI_OPCODE_POW:
57 case TGSI_OPCODE_RCP:
58 case TGSI_OPCODE_RSQ:
59 case TGSI_OPCODE_SCS:
60 return 0x1;
61 case TGSI_OPCODE_IF:
62 return 0x1;
63 case TGSI_OPCODE_LIT:
64 return 0xb;
65 case TGSI_OPCODE_TEX:
66 case TGSI_OPCODE_TXB:
67 case TGSI_OPCODE_TXL:
68 case TGSI_OPCODE_TXP:
69 {
70 const struct tgsi_instruction_texture *tex;
71
72 assert(inst->Instruction.Texture);
73 tex = &inst->Texture;
74
75 mask = 0x7;
76 if (inst->Instruction.Opcode != TGSI_OPCODE_TEX &&
77 inst->Instruction.Opcode != TGSI_OPCODE_TXD)
78 mask |= 0x8; /* bias, lod or proj */
79
80 switch (tex->Texture) {
81 case TGSI_TEXTURE_1D:
82 mask &= 0x9;
83 break;
84 case TGSI_TEXTURE_SHADOW1D:
85 mask &= 0x5;
86 break;
87 case TGSI_TEXTURE_2D:
88 mask &= 0xb;
89 break;
90 default:
91 break;
92 }
93 }
94 return mask;
95 case TGSI_OPCODE_XPD:
96 {
97 unsigned x = 0;
98 if (mask & 1) x |= 0x6;
99 if (mask & 2) x |= 0x5;
100 if (mask & 4) x |= 0x3;
101 return x;
102 }
103 default:
104 break;
105 }
106
107 return mask;
108 }
109
110 static void
111 nvc0_indirect_inputs(struct nvc0_translation_info *ti, int id)
112 {
113 int i, c;
114
115 for (i = 0; i < PIPE_MAX_SHADER_INPUTS; ++i)
116 for (c = 0; c < 4; ++c)
117 ti->input_access[i][c] = id;
118
119 ti->indirect_inputs = TRUE;
120 }
121
122 static void
123 nvc0_indirect_outputs(struct nvc0_translation_info *ti, int id)
124 {
125 int i, c;
126
127 for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i)
128 for (c = 0; c < 4; ++c)
129 ti->output_access[i][c] = id;
130
131 ti->indirect_outputs = TRUE;
132 }
133
134 static INLINE unsigned
135 nvc0_system_value_location(unsigned sn, unsigned si, boolean *is_input)
136 {
137 /* NOTE: locations 0xfxx indicate special regs */
138 switch (sn) {
139 /*
140 case TGSI_SEMANTIC_VERTEXID:
141 *is_input = TRUE;
142 return 0x2fc;
143 */
144 case TGSI_SEMANTIC_PRIMID:
145 *is_input = TRUE;
146 return 0x60;
147 /*
148 case TGSI_SEMANTIC_LAYER_INDEX:
149 return 0x64;
150 case TGSI_SEMANTIC_VIEWPORT_INDEX:
151 return 0x68;
152 */
153 case TGSI_SEMANTIC_INSTANCEID:
154 *is_input = TRUE;
155 return 0x2f8;
156 case TGSI_SEMANTIC_FACE:
157 *is_input = TRUE;
158 return 0x3fc;
159 /*
160 case TGSI_SEMANTIC_INVOCATIONID:
161 return 0xf11;
162 */
163 default:
164 assert(0);
165 return 0x000;
166 }
167 }
168
169 static INLINE unsigned
170 nvc0_varying_location(unsigned sn, unsigned si)
171 {
172 switch (sn) {
173 case TGSI_SEMANTIC_POSITION:
174 return 0x70;
175 case TGSI_SEMANTIC_COLOR:
176 return 0x280 + (si * 16); /* are these hard-wired ? */
177 case TGSI_SEMANTIC_BCOLOR:
178 return 0x2a0 + (si * 16);
179 case TGSI_SEMANTIC_FOG:
180 return 0x270;
181 case TGSI_SEMANTIC_PSIZE:
182 return 0x6c;
183 /*
184 case TGSI_SEMANTIC_PNTC:
185 return 0x2e0;
186 */
187 case TGSI_SEMANTIC_GENERIC:
188 /* We'd really like to distinguish between TEXCOORD and GENERIC here,
189 * since only 0x300 to 0x37c can be replaced by sprite coordinates.
190 * Also, gl_PointCoord should be a system value and must be assigned to
191 * address 0x2e0. For now, let's cheat:
192 */
193 assert(si < 31);
194 if (si <= 7)
195 return 0x300 + si * 16;
196 if (si == 9)
197 return 0x2e0;
198 return 0x80 + ((si - 8) * 16);
199 case TGSI_SEMANTIC_NORMAL:
200 return 0x360;
201 case TGSI_SEMANTIC_PRIMID:
202 return 0x40;
203 case TGSI_SEMANTIC_FACE:
204 return 0x3fc;
205 /*
206 case TGSI_SEMANTIC_CLIP_DISTANCE:
207 return 0x2c0 + (si * 4);
208 */
209 default:
210 assert(0);
211 return 0x000;
212 }
213 }
214
215 static INLINE unsigned
216 nvc0_interp_mode(const struct tgsi_full_declaration *decl)
217 {
218 unsigned mode;
219
220 if (decl->Declaration.Interpolate == TGSI_INTERPOLATE_CONSTANT)
221 mode = NVC0_INTERP_FLAT;
222 else
223 if (decl->Declaration.Interpolate == TGSI_INTERPOLATE_PERSPECTIVE)
224 mode = NVC0_INTERP_PERSPECTIVE;
225 else
226 mode = NVC0_INTERP_LINEAR;
227
228 if (decl->Declaration.Centroid)
229 mode |= NVC0_INTERP_CENTROID;
230
231 return mode;
232 }
233
234 static void
235 prog_immediate(struct nvc0_translation_info *ti,
236 const struct tgsi_full_immediate *imm)
237 {
238 int c;
239 unsigned n = ti->immd32_nr++;
240
241 assert(ti->immd32_nr <= ti->scan.immediate_count);
242
243 for (c = 0; c < 4; ++c)
244 ti->immd32[n * 4 + c] = imm->u[c].Uint;
245
246 ti->immd32_ty[n] = imm->Immediate.DataType;
247 }
248
249 static boolean
250 prog_decl(struct nvc0_translation_info *ti,
251 const struct tgsi_full_declaration *decl)
252 {
253 unsigned i, c;
254 unsigned sn = TGSI_SEMANTIC_GENERIC;
255 unsigned si = 0;
256 const unsigned first = decl->Range.First;
257 const unsigned last = decl->Range.Last;
258
259 if (decl->Declaration.Semantic) {
260 sn = decl->Semantic.Name;
261 si = decl->Semantic.Index;
262 }
263
264 switch (decl->Declaration.File) {
265 case TGSI_FILE_INPUT:
266 for (i = first; i <= last; ++i) {
267 if (ti->prog->type == PIPE_SHADER_VERTEX) {
268 for (c = 0; c < 4; ++c)
269 ti->input_loc[i][c] = 0x80 + i * 16 + c * 4;
270 } else {
271 for (c = 0; c < 4; ++c)
272 ti->input_loc[i][c] = nvc0_varying_location(sn, si) + c * 4;
273 /* for sprite coordinates: */
274 ti->prog->fp.in_pos[i] = ti->input_loc[i][0] / 4;
275 }
276 if (ti->prog->type == PIPE_SHADER_FRAGMENT)
277 ti->interp_mode[i] = nvc0_interp_mode(decl);
278 }
279 break;
280 case TGSI_FILE_OUTPUT:
281 for (i = first; i <= last; ++i, ++si) {
282 if (ti->prog->type == PIPE_SHADER_FRAGMENT) {
283 si = i;
284 if (i == ti->fp_depth_output) {
285 ti->output_loc[i][2] = (ti->scan.num_outputs - 1) * 4;
286 } else {
287 if (i > ti->fp_depth_output)
288 si -= 1;
289 for (c = 0; c < 4; ++c)
290 ti->output_loc[i][c] = si * 4 + c;
291 }
292 } else {
293 for (c = 0; c < 4; ++c)
294 ti->output_loc[i][c] = nvc0_varying_location(sn, si) + c * 4;
295 /* for TFB_VARYING_LOCS: */
296 ti->prog->vp.out_pos[i] = ti->output_loc[i][0] / 4;
297 }
298 }
299 break;
300 case TGSI_FILE_SYSTEM_VALUE:
301 i = first;
302 ti->sysval_loc[i] = nvc0_system_value_location(sn, si, &ti->sysval_in[i]);
303 assert(first == last);
304 break;
305 case TGSI_FILE_TEMPORARY:
306 ti->temp128_nr = MAX2(ti->temp128_nr, last + 1);
307 break;
308 case TGSI_FILE_NULL:
309 case TGSI_FILE_CONSTANT:
310 case TGSI_FILE_SAMPLER:
311 case TGSI_FILE_ADDRESS:
312 case TGSI_FILE_IMMEDIATE:
313 case TGSI_FILE_PREDICATE:
314 break;
315 default:
316 NOUVEAU_ERR("unhandled TGSI_FILE %d\n", decl->Declaration.File);
317 return FALSE;
318 }
319 return TRUE;
320 }
321
322 static void
323 prog_inst(struct nvc0_translation_info *ti,
324 const struct tgsi_full_instruction *inst, int id)
325 {
326 const struct tgsi_dst_register *dst;
327 const struct tgsi_src_register *src;
328 int s, c, k;
329 unsigned mask;
330
331 if (inst->Instruction.Opcode == TGSI_OPCODE_BGNSUB) {
332 ti->subr[ti->num_subrs].first_insn = id - 1;
333 ti->subr[ti->num_subrs].id = ti->num_subrs + 1; /* id 0 is main program */
334 ++ti->num_subrs;
335 }
336
337 if (inst->Dst[0].Register.File == TGSI_FILE_OUTPUT) {
338 dst = &inst->Dst[0].Register;
339
340 for (c = 0; c < 4; ++c) {
341 if (dst->Indirect)
342 nvc0_indirect_outputs(ti, id);
343 if (!(dst->WriteMask & (1 << c)))
344 continue;
345 ti->output_access[dst->Index][c] = id;
346 }
347
348 if (inst->Instruction.Opcode == TGSI_OPCODE_MOV &&
349 inst->Src[0].Register.File == TGSI_FILE_INPUT &&
350 dst->Index == ti->edgeflag_out)
351 ti->prog->vp.edgeflag = inst->Src[0].Register.Index;
352 } else
353 if (inst->Dst[0].Register.File == TGSI_FILE_TEMPORARY) {
354 if (inst->Dst[0].Register.Indirect)
355 ti->require_stores = TRUE;
356 }
357
358 for (s = 0; s < inst->Instruction.NumSrcRegs; ++s) {
359 src = &inst->Src[s].Register;
360 if (src->File == TGSI_FILE_TEMPORARY)
361 if (inst->Src[s].Register.Indirect)
362 ti->require_stores = TRUE;
363 if (src->File != TGSI_FILE_INPUT)
364 continue;
365 mask = nvc0_tgsi_src_mask(inst, s);
366
367 if (inst->Src[s].Register.Indirect)
368 nvc0_indirect_inputs(ti, id);
369
370 for (c = 0; c < 4; ++c) {
371 if (!(mask & (1 << c)))
372 continue;
373 k = tgsi_util_get_full_src_register_swizzle(&inst->Src[s], c);
374 if (k <= TGSI_SWIZZLE_W)
375 ti->input_access[src->Index][k] = id;
376 }
377 }
378 }
379
380 /* Probably should introduce something like struct tgsi_function_declaration
381 * instead of trying to guess inputs/outputs.
382 */
383 static void
384 prog_subroutine_inst(struct nvc0_subroutine *subr,
385 const struct tgsi_full_instruction *inst)
386 {
387 const struct tgsi_dst_register *dst;
388 const struct tgsi_src_register *src;
389 int s, c, k;
390 unsigned mask;
391
392 for (s = 0; s < inst->Instruction.NumSrcRegs; ++s) {
393 src = &inst->Src[s].Register;
394 if (src->File != TGSI_FILE_TEMPORARY)
395 continue;
396 mask = nvc0_tgsi_src_mask(inst, s);
397
398 for (c = 0; c < 4; ++c) {
399 k = tgsi_util_get_full_src_register_swizzle(&inst->Src[s], c);
400
401 if ((mask & (1 << c)) && k < TGSI_SWIZZLE_W)
402 if (!(subr->retv[src->Index / 32][k] & (1 << (src->Index % 32))))
403 subr->argv[src->Index / 32][k] |= 1 << (src->Index % 32);
404 }
405 }
406
407 if (inst->Dst[0].Register.File == TGSI_FILE_TEMPORARY) {
408 dst = &inst->Dst[0].Register;
409
410 for (c = 0; c < 4; ++c)
411 if (dst->WriteMask & (1 << c))
412 subr->retv[dst->Index / 32][c] |= 1 << (dst->Index % 32);
413 }
414 }
415
416 static int
417 nvc0_vp_gp_gen_header(struct nvc0_program *vp, struct nvc0_translation_info *ti)
418 {
419 int i, c;
420 unsigned a;
421
422 for (a = 0x80/4, i = 0; i <= ti->scan.file_max[TGSI_FILE_INPUT]; ++i) {
423 for (c = 0; c < 4; ++c, ++a)
424 if (ti->input_access[i][c])
425 vp->hdr[5 + a / 32] |= 1 << (a % 32); /* VP_ATTR_EN */
426 }
427
428 for (i = 0; i <= ti->scan.file_max[TGSI_FILE_OUTPUT]; ++i) {
429 a = (ti->output_loc[i][0] - 0x40) / 4;
430 for (c = 0; c < 4; ++c, ++a) {
431 if (!ti->output_access[i][c])
432 continue;
433 vp->hdr[13 + a / 32] |= 1 << (a % 32); /* VP_EXPORT_EN */
434 }
435 }
436
437 for (i = 0; i < TGSI_SEMANTIC_COUNT; ++i) {
438 a = ti->sysval_loc[i] / 4;
439 if (a > 0 && a < (0xf00 / 4))
440 vp->hdr[(ti->sysval_in[i] ? 5 : 13) + a / 32] |= 1 << (a % 32);
441 }
442
443 return 0;
444 }
445
446 static int
447 nvc0_vp_gen_header(struct nvc0_program *vp, struct nvc0_translation_info *ti)
448 {
449 vp->hdr[0] = 0x20461;
450 vp->hdr[4] = 0xff000;
451
452 vp->hdr[18] = (1 << vp->vp.num_ucps) - 1;
453
454 return nvc0_vp_gp_gen_header(vp, ti);
455 }
456
457 static int
458 nvc0_gp_gen_header(struct nvc0_program *gp, struct nvc0_translation_info *ti)
459 {
460 unsigned invocations = 1;
461 unsigned max_output_verts, output_prim;
462 unsigned i;
463
464 gp->hdr[0] = 0x21061;
465
466 for (i = 0; i < ti->scan.num_properties; ++i) {
467 switch (ti->scan.properties[i].name) {
468 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
469 output_prim = ti->scan.properties[i].data[0];
470 break;
471 case TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES:
472 max_output_verts = ti->scan.properties[i].data[0];
473 assert(max_output_verts < 512);
474 break;
475 /*
476 case TGSI_PROPERTY_GS_INVOCATIONS:
477 invocations = ti->scan.properties[i].data[0];
478 assert(invocations <= 32);
479 break;
480 */
481 default:
482 break;
483 }
484 }
485
486 gp->hdr[2] = MIN2(invocations, 32) << 24;
487
488 switch (output_prim) {
489 case PIPE_PRIM_POINTS:
490 gp->hdr[3] = 0x01000000;
491 gp->hdr[0] |= 0xf0000000;
492 break;
493 case PIPE_PRIM_LINE_STRIP:
494 gp->hdr[3] = 0x06000000;
495 gp->hdr[0] |= 0x10000000;
496 break;
497 case PIPE_PRIM_TRIANGLE_STRIP:
498 gp->hdr[3] = 0x07000000;
499 gp->hdr[0] |= 0x10000000;
500 break;
501 default:
502 assert(0);
503 break;
504 }
505
506 gp->hdr[4] = max_output_verts & 0x1ff;
507
508 return nvc0_vp_gp_gen_header(gp, ti);
509 }
510
511 static int
512 nvc0_fp_gen_header(struct nvc0_program *fp, struct nvc0_translation_info *ti)
513 {
514 int i, c;
515 unsigned a, m;
516
517 fp->hdr[0] = 0x21462;
518 fp->hdr[5] = 0x80000000; /* getting a trap if FRAG_COORD_UMASK.w = 0 */
519
520 if (ti->scan.uses_kill)
521 fp->hdr[0] |= 0x8000;
522 if (ti->scan.writes_z) {
523 fp->hdr[19] |= 0x2;
524 if (ti->scan.num_outputs > 2)
525 fp->hdr[0] |= 0x4000; /* FP_MULTIPLE_COLOR_OUTPUTS */
526 } else {
527 if (ti->scan.num_outputs > 1)
528 fp->hdr[0] |= 0x4000; /* FP_MULTIPLE_COLOR_OUTPUTS */
529 }
530
531 for (i = 0; i <= ti->scan.file_max[TGSI_FILE_INPUT]; ++i) {
532 m = ti->interp_mode[i];
533 for (c = 0; c < 4; ++c) {
534 if (!ti->input_access[i][c])
535 continue;
536 a = ti->input_loc[i][c] / 2;
537 if (ti->input_loc[i][c] >= 0x2c0)
538 a -= 32;
539 if (ti->input_loc[i][0] == 0x70)
540 fp->hdr[5] |= 1 << (28 + c); /* FRAG_COORD_UMASK */
541 else
542 if (ti->input_loc[i][0] == 0x2e0)
543 fp->hdr[14] |= 1 << (24 + c); /* POINT_COORD */
544 else
545 fp->hdr[4 + a / 32] |= m << (a % 32);
546 }
547 }
548
549 for (i = 0; i <= ti->scan.file_max[TGSI_FILE_OUTPUT]; ++i) {
550 if (i != ti->fp_depth_output)
551 fp->hdr[18] |= 0xf << ti->output_loc[i][0];
552 }
553
554 for (i = 0; i < TGSI_SEMANTIC_COUNT; ++i) {
555 a = ti->sysval_loc[i] / 2;
556 if ((a > 0) && (a < 0xf00 / 2))
557 fp->hdr[4 + a / 32] |= NVC0_INTERP_FLAT << (a % 32);
558 }
559
560 return 0;
561 }
562
563 static boolean
564 nvc0_prog_scan(struct nvc0_translation_info *ti)
565 {
566 struct nvc0_program *prog = ti->prog;
567 struct tgsi_parse_context parse;
568 int ret;
569 unsigned i;
570
571 #ifdef NOUVEAU_DEBUG
572 tgsi_dump(prog->pipe.tokens, 0);
573 #endif
574
575 tgsi_scan_shader(prog->pipe.tokens, &ti->scan);
576
577 if (ti->prog->type == PIPE_SHADER_FRAGMENT) {
578 ti->fp_depth_output = 255;
579 for (i = 0; i < ti->scan.num_outputs; ++i)
580 if (ti->scan.output_semantic_name[i] == TGSI_SEMANTIC_POSITION)
581 ti->fp_depth_output = i;
582 }
583
584 ti->subr =
585 CALLOC(ti->scan.opcode_count[TGSI_OPCODE_BGNSUB], sizeof(ti->subr[0]));
586
587 ti->immd32 = (uint32_t *)MALLOC(ti->scan.immediate_count * 16);
588 ti->immd32_ty = (ubyte *)MALLOC(ti->scan.immediate_count * sizeof(ubyte));
589
590 ti->insns = MALLOC(ti->scan.num_instructions * sizeof(ti->insns[0]));
591
592 tgsi_parse_init(&parse, prog->pipe.tokens);
593 while (!tgsi_parse_end_of_tokens(&parse)) {
594 tgsi_parse_token(&parse);
595
596 switch (parse.FullToken.Token.Type) {
597 case TGSI_TOKEN_TYPE_IMMEDIATE:
598 prog_immediate(ti, &parse.FullToken.FullImmediate);
599 break;
600 case TGSI_TOKEN_TYPE_DECLARATION:
601 prog_decl(ti, &parse.FullToken.FullDeclaration);
602 break;
603 case TGSI_TOKEN_TYPE_INSTRUCTION:
604 ti->insns[ti->num_insns] = parse.FullToken.FullInstruction;
605 prog_inst(ti, &parse.FullToken.FullInstruction, ++ti->num_insns);
606 break;
607 default:
608 break;
609 }
610 }
611
612 for (i = 0; i < ti->num_subrs; ++i) {
613 unsigned pc = ti->subr[i].id;
614 while (ti->insns[pc].Instruction.Opcode != TGSI_OPCODE_ENDSUB)
615 prog_subroutine_inst(&ti->subr[i], &ti->insns[pc++]);
616 }
617
618 switch (prog->type) {
619 case PIPE_SHADER_VERTEX:
620 ti->input_file = NV_FILE_MEM_A;
621 ti->output_file = NV_FILE_MEM_V;
622 ret = nvc0_vp_gen_header(prog, ti);
623 break;
624 /*
625 case PIPE_SHADER_TESSELLATION_CONTROL:
626 ret = nvc0_tcp_gen_header(ti);
627 break;
628 case PIPE_SHADER_TESSELLATION_EVALUATION:
629 ret = nvc0_tep_gen_header(ti);
630 break;
631 case PIPE_SHADER_GEOMETRY:
632 ret = nvc0_gp_gen_header(ti);
633 break;
634 */
635 case PIPE_SHADER_FRAGMENT:
636 ti->input_file = NV_FILE_MEM_V;
637 ti->output_file = NV_FILE_GPR;
638
639 if (ti->scan.writes_z)
640 prog->flags[0] = 0x11; /* ? */
641 else
642 if (!ti->scan.uses_kill && !ti->global_stores)
643 prog->fp.early_z = 1;
644
645 ret = nvc0_fp_gen_header(prog, ti);
646 break;
647 default:
648 assert(!"unsupported program type");
649 ret = -1;
650 break;
651 }
652
653 if (ti->require_stores) {
654 prog->hdr[0] |= 1 << 26;
655 prog->hdr[1] |= ti->temp128_nr * 16; /* l[] size */
656 }
657
658 assert(!ret);
659 return ret;
660 }
661
662 boolean
663 nvc0_program_translate(struct nvc0_program *prog)
664 {
665 struct nvc0_translation_info *ti;
666 int ret;
667
668 ti = CALLOC_STRUCT(nvc0_translation_info);
669 ti->prog = prog;
670
671 ti->edgeflag_out = PIPE_MAX_SHADER_OUTPUTS;
672
673 if (prog->type == PIPE_SHADER_VERTEX && prog->vp.num_ucps)
674 ti->append_ucp = TRUE;
675
676 ret = nvc0_prog_scan(ti);
677 if (ret) {
678 NOUVEAU_ERR("unsupported shader program\n");
679 goto out;
680 }
681
682 ret = nvc0_generate_code(ti);
683 if (ret)
684 NOUVEAU_ERR("shader translation failed\n");
685
686 {
687 unsigned i;
688 for (i = 0; i < sizeof(prog->hdr) / sizeof(prog->hdr[0]); ++i)
689 debug_printf("HDR[%02lx] = 0x%08x\n",
690 i * sizeof(prog->hdr[0]), prog->hdr[i]);
691 }
692
693 out:
694 if (ti->immd32)
695 FREE(ti->immd32);
696 if (ti->immd32_ty)
697 FREE(ti->immd32_ty);
698 if (ti->insns)
699 FREE(ti->insns);
700 if (ti->subr)
701 FREE(ti->subr);
702 FREE(ti);
703 return ret ? FALSE : TRUE;
704 }
705
706 void
707 nvc0_program_destroy(struct nvc0_context *nvc0, struct nvc0_program *prog)
708 {
709 if (prog->res)
710 nouveau_resource_free(&prog->res);
711
712 if (prog->code)
713 FREE(prog->code);
714 if (prog->relocs)
715 FREE(prog->relocs);
716
717 memset(prog->hdr, 0, sizeof(prog->hdr));
718
719 prog->translated = FALSE;
720 }