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