OSDN Git Service

4742c54772a70467ac5641d49fd70b15318243b6
[android-x86/external-mesa.git] / src / gallium / drivers / vc4 / vc4_program.c
1 /*
2  * Copyright (c) 2014 Scott Mansell
3  * Copyright © 2014 Broadcom
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24
25 #include <stdio.h>
26 #include <inttypes.h>
27 #include "pipe/p_state.h"
28 #include "util/u_memory.h"
29 #include "tgsi/tgsi_parse.h"
30 #include "tgsi/tgsi_dump.h"
31
32 #include "vc4_context.h"
33 #include "vc4_qpu.h"
34 #include "vc4_qir.h"
35
36 struct tgsi_to_qir {
37         struct tgsi_parse_context parser;
38         struct qcompile *c;
39         struct qreg *temps;
40         struct qreg *inputs;
41         struct qreg *outputs;
42         struct qreg *uniforms;
43         struct qreg *consts;
44         uint32_t num_consts;
45
46         uint32_t *uniform_data;
47         enum quniform_contents *uniform_contents;
48         uint32_t num_uniforms;
49 };
50
51 static struct qreg
52 get_temp_for_uniform(struct tgsi_to_qir *trans, uint32_t uniform)
53 {
54         struct qcompile *c = trans->c;
55         struct qreg u = { QFILE_UNIF, uniform };
56
57         struct qreg t = qir_MOV(c, u);
58         trans->uniforms[uniform] = t;
59         return t;
60 }
61
62 static struct qreg
63 qir_uniform_ui(struct tgsi_to_qir *trans, uint32_t ui)
64 {
65         for (int i = 0; i < trans->num_uniforms; i++) {
66                 if (trans->uniform_contents[i] == QUNIFORM_CONSTANT &&
67                     trans->uniform_data[i] == ui)
68                         return trans->uniforms[i];
69         }
70
71         trans->uniform_contents[trans->num_uniforms] = QUNIFORM_CONSTANT;
72         trans->uniform_data[trans->num_uniforms] = ui;
73         return get_temp_for_uniform(trans, trans->num_uniforms++);
74 }
75
76 static struct qreg
77 qir_uniform_f(struct tgsi_to_qir *trans, float f)
78 {
79         return qir_uniform_ui(trans, fui(f));
80 }
81
82 static struct qreg
83 qir_uniform(struct tgsi_to_qir *trans, uint32_t index)
84 {
85         for (int i = 0; i < trans->num_uniforms; i++) {
86                 if (trans->uniform_contents[i] == QUNIFORM_UNIFORM &&
87                     trans->uniform_data[i] == index)
88                         return trans->uniforms[i];
89         }
90
91         trans->uniform_contents[trans->num_uniforms] = QUNIFORM_UNIFORM;
92         trans->uniform_data[trans->num_uniforms] = index;
93         return get_temp_for_uniform(trans, trans->num_uniforms++);
94 }
95
96 static struct qreg
97 get_src(struct tgsi_to_qir *trans, struct tgsi_src_register *src, int i)
98 {
99         struct qcompile *c = trans->c;
100         struct qreg r = c->undef;
101
102         uint32_t s = i;
103         switch (i) {
104         case TGSI_SWIZZLE_X:
105                 s = src->SwizzleX;
106                 break;
107         case TGSI_SWIZZLE_Y:
108                 s = src->SwizzleY;
109                 break;
110         case TGSI_SWIZZLE_Z:
111                 s = src->SwizzleZ;
112                 break;
113         case TGSI_SWIZZLE_W:
114                 s = src->SwizzleW;
115                 break;
116         default:
117                 abort();
118         }
119
120         assert(!src->Indirect);
121
122         switch (src->File) {
123         case TGSI_FILE_NULL:
124                 return r;
125         case TGSI_FILE_TEMPORARY:
126                 r = trans->temps[src->Index * 4 + s];
127                 break;
128         case TGSI_FILE_IMMEDIATE:
129                 r = trans->consts[src->Index * 4 + s];
130                 break;
131         case TGSI_FILE_CONSTANT:
132                 r = qir_uniform(trans, src->Index * 4 + s);
133                 break;
134         case TGSI_FILE_INPUT:
135                 r = trans->inputs[src->Index * 4 + s];
136                 break;
137         default:
138                 fprintf(stderr, "unknown src file %d\n", src->File);
139                 abort();
140         }
141
142         if (src->Absolute)
143                 r = qir_FMAXABS(c, r, r);
144
145         if (src->Negate)
146                 r = qir_FSUB(c, qir_uniform_f(trans, 0), r);
147
148         return r;
149 };
150
151
152 static void
153 update_dst(struct tgsi_to_qir *trans, struct tgsi_full_instruction *tgsi_inst,
154            int i, struct qreg val)
155 {
156         struct tgsi_dst_register *tgsi_dst = &tgsi_inst->Dst[0].Register;
157
158         assert(!tgsi_dst->Indirect);
159
160         switch (tgsi_dst->File) {
161         case TGSI_FILE_TEMPORARY:
162                 trans->temps[tgsi_dst->Index * 4 + i] = val;
163                 break;
164         case TGSI_FILE_OUTPUT:
165                 trans->outputs[tgsi_dst->Index * 4 + i] = val;
166                 break;
167         default:
168                 fprintf(stderr, "unknown dst file %d\n", tgsi_dst->File);
169                 abort();
170         }
171 };
172
173 static struct qreg
174 tgsi_to_qir_alu(struct tgsi_to_qir *trans,
175                 struct tgsi_full_instruction *tgsi_inst,
176                 enum qop op, struct qreg *src, int i)
177 {
178         struct qcompile *c = trans->c;
179         struct qreg dst = qir_get_temp(c);
180         qir_emit(c, qir_inst(op, dst, src[0 * 4 + i], src[1 * 4 + i]));
181         return dst;
182 }
183
184 static struct qreg
185 tgsi_to_qir_mad(struct tgsi_to_qir *trans,
186                 struct tgsi_full_instruction *tgsi_inst,
187                 enum qop op, struct qreg *src, int i)
188 {
189         struct qcompile *c = trans->c;
190         return qir_FADD(c,
191                         qir_FMUL(c,
192                                  src[0 * 4 + i],
193                                  src[1 * 4 + i]),
194                         src[2 * 4 + i]);
195 }
196
197 static struct qreg
198 tgsi_to_qir_dp(struct tgsi_to_qir *trans,
199                struct tgsi_full_instruction *tgsi_inst,
200                int num, struct qreg *src, int i)
201 {
202         struct qcompile *c = trans->c;
203
204         struct qreg sum = qir_FMUL(c, src[0 * 4 + 0], src[1 * 4 + 0]);
205         for (int j = 1; j < num; j++) {
206                 sum = qir_FADD(c, sum, qir_FMUL(c,
207                                                 src[0 * 4 + j],
208                                                 src[1 * 4 + j]));
209         }
210         return sum;
211 }
212
213 static struct qreg
214 tgsi_to_qir_dp2(struct tgsi_to_qir *trans,
215                  struct tgsi_full_instruction *tgsi_inst,
216                  enum qop op, struct qreg *src, int i)
217 {
218         return tgsi_to_qir_dp(trans, tgsi_inst, 2, src, i);
219 }
220
221 static struct qreg
222 tgsi_to_qir_dp3(struct tgsi_to_qir *trans,
223                  struct tgsi_full_instruction *tgsi_inst,
224                  enum qop op, struct qreg *src, int i)
225 {
226         return tgsi_to_qir_dp(trans, tgsi_inst, 3, src, i);
227 }
228
229 static struct qreg
230 tgsi_to_qir_dp4(struct tgsi_to_qir *trans,
231                  struct tgsi_full_instruction *tgsi_inst,
232                  enum qop op, struct qreg *src, int i)
233 {
234         return tgsi_to_qir_dp(trans, tgsi_inst, 4, src, i);
235 }
236
237 static void
238 emit_tgsi_instruction(struct tgsi_to_qir *trans,
239                       struct tgsi_full_instruction *tgsi_inst)
240 {
241         struct qcompile *c = trans->c;
242         struct {
243                 enum qop op;
244                 struct qreg (*func)(struct tgsi_to_qir *trans,
245                                     struct tgsi_full_instruction *tgsi_inst,
246                                     enum qop op,
247                                     struct qreg *src, int i);
248         } op_trans[] = {
249                 [TGSI_OPCODE_MOV] = { QOP_MOV, tgsi_to_qir_alu },
250                 [TGSI_OPCODE_ABS] = { QOP_FMAXABS, tgsi_to_qir_alu },
251                 [TGSI_OPCODE_MUL] = { QOP_FMUL, tgsi_to_qir_alu },
252                 [TGSI_OPCODE_ADD] = { QOP_FADD, tgsi_to_qir_alu },
253                 [TGSI_OPCODE_SUB] = { QOP_FSUB, tgsi_to_qir_alu },
254                 [TGSI_OPCODE_MIN] = { QOP_FMIN, tgsi_to_qir_alu },
255                 [TGSI_OPCODE_MAX] = { QOP_FMAX, tgsi_to_qir_alu },
256                 [TGSI_OPCODE_RSQ] = { QOP_RSQ, tgsi_to_qir_alu },
257                 [TGSI_OPCODE_SEQ] = { QOP_SEQ, tgsi_to_qir_alu },
258                 [TGSI_OPCODE_SNE] = { QOP_SNE, tgsi_to_qir_alu },
259                 [TGSI_OPCODE_SGE] = { QOP_SGE, tgsi_to_qir_alu },
260                 [TGSI_OPCODE_SLT] = { QOP_SLT, tgsi_to_qir_alu },
261                 [TGSI_OPCODE_MAD] = { 0, tgsi_to_qir_mad },
262                 [TGSI_OPCODE_DP2] = { 0, tgsi_to_qir_dp2 },
263                 [TGSI_OPCODE_DP3] = { 0, tgsi_to_qir_dp3 },
264                 [TGSI_OPCODE_DP4] = { 0, tgsi_to_qir_dp4 },
265                 [TGSI_OPCODE_RCP] = { QOP_RCP, tgsi_to_qir_alu },
266                 [TGSI_OPCODE_RSQ] = { QOP_RSQ, tgsi_to_qir_alu },
267                 [TGSI_OPCODE_EX2] = { QOP_EXP2, tgsi_to_qir_alu },
268                 [TGSI_OPCODE_LG2] = { QOP_LOG2, tgsi_to_qir_alu },
269                 [TGSI_OPCODE_LIT] = { QOP_MOV, tgsi_to_qir_alu }, /* XXX */
270         };
271         static int asdf = 0;
272         uint32_t tgsi_op = tgsi_inst->Instruction.Opcode;
273
274         if (tgsi_op == TGSI_OPCODE_END)
275                 return;
276
277         tgsi_dump_instruction(tgsi_inst, asdf++);
278
279         if (tgsi_op > ARRAY_SIZE(op_trans) || !op_trans[tgsi_op].func) {
280                 fprintf(stderr, "unknown tgsi inst: ");
281                 tgsi_dump_instruction(tgsi_inst, asdf++);
282                 fprintf(stderr, "\n");
283                 abort();
284         }
285
286         struct qreg src_regs[12];
287         for (int s = 0; s < 3; s++) {
288                 for (int i = 0; i < 4; i++) {
289                         src_regs[4 * s + i] =
290                                 get_src(trans, &tgsi_inst->Src[s].Register, i);
291                 }
292         }
293
294         for (int i = 0; i < 4; i++) {
295                 if (!(tgsi_inst->Dst[0].Register.WriteMask & (1 << i)))
296                         continue;
297
298                 struct qreg result;
299
300                 result = op_trans[tgsi_op].func(trans, tgsi_inst,
301                                                 op_trans[tgsi_op].op,
302                                                 src_regs, i);
303
304                 if (tgsi_inst->Instruction.Saturate) {
305                         float low = (tgsi_inst->Instruction.Saturate ==
306                                      TGSI_SAT_MINUS_PLUS_ONE ? -1.0 : 0.0);
307                         result = qir_FMAX(c,
308                                           qir_FMIN(c,
309                                                    result,
310                                                    qir_uniform_f(trans, 1.0)),
311                                           qir_uniform_f(trans, low));
312                 }
313
314                 update_dst(trans, tgsi_inst, i, result);
315         }
316 }
317
318 static void
319 parse_tgsi_immediate(struct tgsi_to_qir *trans, struct tgsi_full_immediate *imm)
320 {
321         for (int i = 0; i < 4; i++) {
322                 unsigned n = trans->num_consts++;
323                 trans->consts[n] = qir_uniform_ui(trans, imm->u[i].Uint);
324         }
325 }
326
327 static void
328 emit_frag_init(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
329 {
330         /* XXX: lols */
331         for (int i = 0; i < 4; i++) {
332                 trans->inputs[i] = qir_uniform_ui(trans, fui(i / 4.0));
333         }
334
335 }
336
337 static void
338 emit_vert_init(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
339 {
340         struct qcompile *c = trans->c;
341
342         /* XXX: attribute type/size/count */
343         for (int i = 0; i < 4; i++) {
344                 trans->inputs[i] = qir_get_temp(c);
345                 qir_emit(c, qir_inst(QOP_VPM_READ, trans->inputs[i],
346                                      c->undef, c->undef));
347         }
348 }
349
350 static void
351 emit_coord_init(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
352 {
353         struct qcompile *c = trans->c;
354
355         /* XXX: attribute type/size/count */
356         for (int i = 0; i < 4; i++) {
357                 trans->inputs[i] = qir_get_temp(c);
358                 qir_emit(c, qir_inst(QOP_VPM_READ, trans->inputs[i],
359                                      c->undef, c->undef));
360         }
361 }
362
363 static void
364 emit_frag_end(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
365 {
366         struct qcompile *c = trans->c;
367
368         struct qreg t = qir_get_temp(c);
369         qir_emit(c, qir_inst4(QOP_PACK_COLORS, t,
370                               trans->outputs[0],
371                               trans->outputs[1],
372                               trans->outputs[2],
373                               trans->outputs[3]));
374         qir_emit(c, qir_inst(QOP_TLB_COLOR_WRITE, c->undef,
375                              t, c->undef));
376 }
377
378 static void
379 emit_scaled_viewport_write(struct tgsi_to_qir *trans)
380 {
381         struct qcompile *c = trans->c;
382         struct qreg xyi[2];
383
384         for (int i = 0; i < 2; i++) {
385                 trans->uniform_contents[trans->num_uniforms] =
386                         QUNIFORM_VIEWPORT_X_SCALE + i;
387                 struct qreg scale = { QFILE_UNIF, trans->num_uniforms++ };
388
389                 xyi[i] = qir_FTOI(c, qir_FMUL(c, trans->outputs[i], scale));
390         }
391
392         qir_VPM_WRITE(c, qir_PACK_SCALED(c, xyi[0], xyi[1]));
393 }
394
395 static void
396 emit_zs_write(struct tgsi_to_qir *trans)
397 {
398         struct qcompile *c = trans->c;
399
400         /* XXX: rescale */
401         qir_VPM_WRITE(c, trans->outputs[2]);
402 }
403
404 static void
405 emit_1_wc_write(struct tgsi_to_qir *trans)
406 {
407         struct qcompile *c = trans->c;
408
409         /* XXX: RCP */
410         qir_VPM_WRITE(c, trans->outputs[3]);
411 }
412
413 static void
414 emit_vert_end(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
415 {
416         emit_scaled_viewport_write(trans);
417         emit_zs_write(trans);
418         emit_1_wc_write(trans);
419         /* XXX: write varyings */
420 }
421
422 static void
423 emit_coord_end(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
424 {
425         struct qcompile *c = trans->c;
426
427         for (int i = 0; i < 4; i++)
428                 qir_VPM_WRITE(c, trans->outputs[i]);
429
430         emit_scaled_viewport_write(trans);
431         emit_zs_write(trans);
432         emit_1_wc_write(trans);
433 }
434
435 static struct tgsi_to_qir *
436 vc4_shader_tgsi_to_qir(struct vc4_shader_state *so, enum qstage stage)
437 {
438         struct tgsi_to_qir *trans = CALLOC_STRUCT(tgsi_to_qir);
439         struct qcompile *c;
440         int ret;
441
442         c = qir_compile_init();
443         c->stage = stage;
444
445         memset(trans, 0, sizeof(*trans));
446         /* XXX sizing */
447         trans->temps = calloc(sizeof(struct qreg), 1024);
448         trans->inputs = calloc(sizeof(struct qreg), 8 * 4);
449         trans->outputs = calloc(sizeof(struct qreg), 1024);
450         trans->uniforms = calloc(sizeof(struct qreg), 1024);
451         trans->consts = calloc(sizeof(struct qreg), 1024);
452
453         trans->uniform_data = calloc(sizeof(uint32_t), 1024);
454         trans->uniform_contents = calloc(sizeof(enum quniform_contents), 1024);
455
456         trans->c = c;
457         ret = tgsi_parse_init(&trans->parser, so->base.tokens);
458         assert(ret == TGSI_PARSE_OK);
459
460         fprintf(stderr, "TGSI:\n");
461         tgsi_dump(so->base.tokens, 0);
462
463         switch (stage) {
464         case QSTAGE_FRAG:
465                 emit_frag_init(trans, so);
466                 break;
467         case QSTAGE_VERT:
468                 emit_vert_init(trans, so);
469                 break;
470         case QSTAGE_COORD:
471                 emit_coord_init(trans, so);
472                 break;
473         }
474
475         while (!tgsi_parse_end_of_tokens(&trans->parser)) {
476                 tgsi_parse_token(&trans->parser);
477
478                 switch (trans->parser.FullToken.Token.Type) {
479                 case TGSI_TOKEN_TYPE_INSTRUCTION:
480                         emit_tgsi_instruction(trans,
481                                               &trans->parser.FullToken.FullInstruction);
482                         break;
483
484                 case TGSI_TOKEN_TYPE_IMMEDIATE:
485                         parse_tgsi_immediate(trans,
486                                              &trans->parser.FullToken.FullImmediate);
487                         break;
488                 }
489         }
490
491         switch (stage) {
492         case QSTAGE_FRAG:
493                 emit_frag_end(trans, so);
494                 break;
495         case QSTAGE_VERT:
496                 emit_vert_end(trans, so);
497                 break;
498         case QSTAGE_COORD:
499                 emit_coord_end(trans, so);
500                 break;
501         }
502
503         qir_dump(c);
504
505         tgsi_parse_free(&trans->parser);
506         free(trans->temps);
507
508         vc4_generate_code(c);
509
510         return trans;
511 }
512
513 static struct vc4_shader_state *
514 vc4_shader_state_create(struct pipe_context *pctx,
515                         const struct pipe_shader_state *cso)
516 {
517         struct vc4_shader_state *so = CALLOC_STRUCT(vc4_shader_state);
518         if (!so)
519                 return NULL;
520
521         so->base.tokens = tgsi_dup_tokens(cso->tokens);
522
523         return so;
524 }
525
526 static void
527 copy_uniform_state_to_shader(struct vc4_shader_state *so,
528                              int shader_index,
529                              struct tgsi_to_qir *trans)
530 {
531         int count = trans->num_uniforms;
532         struct vc4_shader_uniform_info *uinfo = &so->uniforms[shader_index];
533
534         uinfo->count = count;
535         uinfo->data = malloc(count * sizeof(*uinfo->data));
536         memcpy(uinfo->data, trans->uniform_data,
537                count * sizeof(*uinfo->data));
538         uinfo->contents = malloc(count * sizeof(*uinfo->contents));
539         memcpy(uinfo->contents, trans->uniform_contents,
540                count * sizeof(*uinfo->contents));
541 }
542
543 static void *
544 vc4_fs_state_create(struct pipe_context *pctx,
545                     const struct pipe_shader_state *cso)
546 {
547         struct vc4_context *vc4 = vc4_context(pctx);
548         struct vc4_shader_state *so = vc4_shader_state_create(pctx, cso);
549         if (!so)
550                 return NULL;
551
552         struct tgsi_to_qir *trans = vc4_shader_tgsi_to_qir(so, QSTAGE_FRAG);
553         copy_uniform_state_to_shader(so, 0, trans);
554
555         so->bo = vc4_bo_alloc_mem(vc4->screen, trans->c->qpu_insts,
556                                   trans->c->num_qpu_insts * sizeof(uint64_t),
557                                   "fs_code");
558
559         qir_compile_destroy(trans->c);
560         free(trans);
561
562         return so;
563 }
564
565 static void *
566 vc4_vs_state_create(struct pipe_context *pctx,
567                     const struct pipe_shader_state *cso)
568 {
569         struct vc4_context *vc4 = vc4_context(pctx);
570         struct vc4_shader_state *so = vc4_shader_state_create(pctx, cso);
571         if (!so)
572                 return NULL;
573
574         struct tgsi_to_qir *vs_trans = vc4_shader_tgsi_to_qir(so, QSTAGE_VERT);
575         copy_uniform_state_to_shader(so, 0, vs_trans);
576
577         struct tgsi_to_qir *cs_trans = vc4_shader_tgsi_to_qir(so, QSTAGE_COORD);
578         copy_uniform_state_to_shader(so, 1, cs_trans);
579
580         uint32_t vs_size = vs_trans->c->num_qpu_insts * sizeof(uint64_t);
581         uint32_t cs_size = cs_trans->c->num_qpu_insts * sizeof(uint64_t);
582         so->coord_shader_offset = vs_size; /* XXX: alignment? */
583         so->bo = vc4_bo_alloc(vc4->screen,
584                               so->coord_shader_offset + cs_size,
585                               "vs_code");
586
587         void *map = vc4_bo_map(so->bo);
588         memcpy(map, vs_trans->c->qpu_insts, vs_size);
589         memcpy(map + so->coord_shader_offset, cs_trans->c->qpu_insts, cs_size);
590
591         qir_compile_destroy(vs_trans->c);
592         qir_compile_destroy(cs_trans->c);
593
594         return so;
595 }
596
597 static void
598 vc4_shader_state_delete(struct pipe_context *pctx, void *hwcso)
599 {
600         struct pipe_shader_state *so = hwcso;
601
602         free((void *)so->tokens);
603         free(so);
604 }
605
606 void
607 vc4_get_uniform_bo(struct vc4_context *vc4, struct vc4_shader_state *shader,
608                    struct vc4_constbuf_stateobj *cb,
609                    int shader_index, struct vc4_bo **out_bo,
610                    uint32_t *out_offset)
611 {
612         struct vc4_shader_uniform_info *uinfo = &shader->uniforms[shader_index];
613         struct vc4_bo *ubo = vc4_bo_alloc(vc4->screen,
614                                           MAX2(1, uinfo->count * 4), "ubo");
615         uint32_t *map = vc4_bo_map(ubo);
616
617         for (int i = 0; i < uinfo->count; i++) {
618                 switch (uinfo->contents[i]) {
619                 case QUNIFORM_CONSTANT:
620                         map[i] = uinfo->data[i];
621                         break;
622                 case QUNIFORM_UNIFORM:
623                         map[i] = ((uint32_t *)cb->cb[0].user_buffer)[uinfo->data[i]];
624                         break;
625                 case QUNIFORM_VIEWPORT_X_SCALE:
626                         map[i] = fui(vc4->framebuffer.width * 16.0f / 2.0f);
627                         break;
628                 case QUNIFORM_VIEWPORT_Y_SCALE:
629                         map[i] = fui(vc4->framebuffer.height * -16.0f / 2.0f);
630                         break;
631                 }
632 #if 1
633                 fprintf(stderr, "%p/%d: %d: 0x%08x (%f)\n",
634                         shader, shader_index, i, map[i], uif(map[i]));
635 #endif
636         }
637
638         *out_bo = ubo;
639         *out_offset = 0;
640 }
641
642 static void
643 vc4_fp_state_bind(struct pipe_context *pctx, void *hwcso)
644 {
645         struct vc4_context *vc4 = vc4_context(pctx);
646         vc4->prog.fs = hwcso;
647         vc4->prog.dirty |= VC4_SHADER_DIRTY_FP;
648         vc4->dirty |= VC4_DIRTY_PROG;
649 }
650
651 static void
652 vc4_vp_state_bind(struct pipe_context *pctx, void *hwcso)
653 {
654         struct vc4_context *vc4 = vc4_context(pctx);
655         vc4->prog.vs = hwcso;
656         vc4->prog.dirty |= VC4_SHADER_DIRTY_VP;
657         vc4->dirty |= VC4_DIRTY_PROG;
658 }
659
660 void
661 vc4_program_init(struct pipe_context *pctx)
662 {
663         pctx->create_vs_state = vc4_vs_state_create;
664         pctx->delete_vs_state = vc4_shader_state_delete;
665
666         pctx->create_fs_state = vc4_fs_state_create;
667         pctx->delete_fs_state = vc4_shader_state_delete;
668
669         pctx->bind_fs_state = vc4_fp_state_bind;
670         pctx->bind_vs_state = vc4_vp_state_bind;
671 }