2 * Copyright (c) 2014 Scott Mansell
3 * Copyright © 2014 Broadcom
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:
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
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
27 #include "pipe/p_state.h"
28 #include "util/u_memory.h"
29 #include "tgsi/tgsi_parse.h"
30 #include "tgsi/tgsi_dump.h"
32 #include "vc4_context.h"
37 struct tgsi_parse_context parser;
42 struct qreg *uniforms;
46 uint32_t *uniform_data;
47 enum quniform_contents *uniform_contents;
48 uint32_t num_uniforms;
52 get_temp_for_uniform(struct tgsi_to_qir *trans, uint32_t uniform)
54 struct qcompile *c = trans->c;
55 struct qreg u = { QFILE_UNIF, uniform };
57 struct qreg t = qir_MOV(c, u);
58 trans->uniforms[uniform] = t;
63 qir_uniform_ui(struct tgsi_to_qir *trans, uint32_t ui)
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];
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++);
77 qir_uniform_f(struct tgsi_to_qir *trans, float f)
79 return qir_uniform_ui(trans, fui(f));
83 qir_uniform(struct tgsi_to_qir *trans, uint32_t index)
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];
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++);
97 get_src(struct tgsi_to_qir *trans, struct tgsi_src_register *src, int i)
99 struct qcompile *c = trans->c;
100 struct qreg r = c->undef;
120 assert(!src->Indirect);
125 case TGSI_FILE_TEMPORARY:
126 r = trans->temps[src->Index * 4 + s];
128 case TGSI_FILE_IMMEDIATE:
129 r = trans->consts[src->Index * 4 + s];
131 case TGSI_FILE_CONSTANT:
132 r = qir_uniform(trans, src->Index * 4 + s);
134 case TGSI_FILE_INPUT:
135 r = trans->inputs[src->Index * 4 + s];
138 fprintf(stderr, "unknown src file %d\n", src->File);
143 r = qir_FMAXABS(c, r, r);
146 r = qir_FSUB(c, qir_uniform_f(trans, 0), r);
153 update_dst(struct tgsi_to_qir *trans, struct tgsi_full_instruction *tgsi_inst,
154 int i, struct qreg val)
156 struct tgsi_dst_register *tgsi_dst = &tgsi_inst->Dst[0].Register;
158 assert(!tgsi_dst->Indirect);
160 switch (tgsi_dst->File) {
161 case TGSI_FILE_TEMPORARY:
162 trans->temps[tgsi_dst->Index * 4 + i] = val;
164 case TGSI_FILE_OUTPUT:
165 trans->outputs[tgsi_dst->Index * 4 + i] = val;
168 fprintf(stderr, "unknown dst file %d\n", tgsi_dst->File);
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)
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]));
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)
189 struct qcompile *c = trans->c;
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)
202 struct qcompile *c = trans->c;
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,
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)
218 return tgsi_to_qir_dp(trans, tgsi_inst, 2, src, i);
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)
226 return tgsi_to_qir_dp(trans, tgsi_inst, 3, src, i);
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)
234 return tgsi_to_qir_dp(trans, tgsi_inst, 4, src, i);
238 emit_tgsi_instruction(struct tgsi_to_qir *trans,
239 struct tgsi_full_instruction *tgsi_inst)
241 struct qcompile *c = trans->c;
244 struct qreg (*func)(struct tgsi_to_qir *trans,
245 struct tgsi_full_instruction *tgsi_inst,
247 struct qreg *src, int i);
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 */
272 uint32_t tgsi_op = tgsi_inst->Instruction.Opcode;
274 if (tgsi_op == TGSI_OPCODE_END)
277 tgsi_dump_instruction(tgsi_inst, asdf++);
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");
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);
294 for (int i = 0; i < 4; i++) {
295 if (!(tgsi_inst->Dst[0].Register.WriteMask & (1 << i)))
300 result = op_trans[tgsi_op].func(trans, tgsi_inst,
301 op_trans[tgsi_op].op,
304 if (tgsi_inst->Instruction.Saturate) {
305 float low = (tgsi_inst->Instruction.Saturate ==
306 TGSI_SAT_MINUS_PLUS_ONE ? -1.0 : 0.0);
310 qir_uniform_f(trans, 1.0)),
311 qir_uniform_f(trans, low));
314 update_dst(trans, tgsi_inst, i, result);
319 parse_tgsi_immediate(struct tgsi_to_qir *trans, struct tgsi_full_immediate *imm)
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);
328 emit_frag_init(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
331 for (int i = 0; i < 4; i++) {
332 trans->inputs[i] = qir_uniform_ui(trans, fui(i / 4.0));
338 emit_vert_init(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
340 struct qcompile *c = trans->c;
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));
351 emit_coord_init(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
353 struct qcompile *c = trans->c;
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));
364 emit_frag_end(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
366 struct qcompile *c = trans->c;
368 struct qreg t = qir_get_temp(c);
369 qir_emit(c, qir_inst4(QOP_PACK_COLORS, t,
374 qir_emit(c, qir_inst(QOP_TLB_COLOR_WRITE, c->undef,
379 emit_scaled_viewport_write(struct tgsi_to_qir *trans)
381 struct qcompile *c = trans->c;
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++ };
389 xyi[i] = qir_FTOI(c, qir_FMUL(c, trans->outputs[i], scale));
392 qir_VPM_WRITE(c, qir_PACK_SCALED(c, xyi[0], xyi[1]));
396 emit_zs_write(struct tgsi_to_qir *trans)
398 struct qcompile *c = trans->c;
401 qir_VPM_WRITE(c, trans->outputs[2]);
405 emit_1_wc_write(struct tgsi_to_qir *trans)
407 struct qcompile *c = trans->c;
410 qir_VPM_WRITE(c, trans->outputs[3]);
414 emit_vert_end(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
416 emit_scaled_viewport_write(trans);
417 emit_zs_write(trans);
418 emit_1_wc_write(trans);
419 /* XXX: write varyings */
423 emit_coord_end(struct tgsi_to_qir *trans, struct vc4_shader_state *so)
425 struct qcompile *c = trans->c;
427 for (int i = 0; i < 4; i++)
428 qir_VPM_WRITE(c, trans->outputs[i]);
430 emit_scaled_viewport_write(trans);
431 emit_zs_write(trans);
432 emit_1_wc_write(trans);
435 static struct tgsi_to_qir *
436 vc4_shader_tgsi_to_qir(struct vc4_shader_state *so, enum qstage stage)
438 struct tgsi_to_qir *trans = CALLOC_STRUCT(tgsi_to_qir);
442 c = qir_compile_init();
445 memset(trans, 0, sizeof(*trans));
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);
453 trans->uniform_data = calloc(sizeof(uint32_t), 1024);
454 trans->uniform_contents = calloc(sizeof(enum quniform_contents), 1024);
457 ret = tgsi_parse_init(&trans->parser, so->base.tokens);
458 assert(ret == TGSI_PARSE_OK);
460 fprintf(stderr, "TGSI:\n");
461 tgsi_dump(so->base.tokens, 0);
465 emit_frag_init(trans, so);
468 emit_vert_init(trans, so);
471 emit_coord_init(trans, so);
475 while (!tgsi_parse_end_of_tokens(&trans->parser)) {
476 tgsi_parse_token(&trans->parser);
478 switch (trans->parser.FullToken.Token.Type) {
479 case TGSI_TOKEN_TYPE_INSTRUCTION:
480 emit_tgsi_instruction(trans,
481 &trans->parser.FullToken.FullInstruction);
484 case TGSI_TOKEN_TYPE_IMMEDIATE:
485 parse_tgsi_immediate(trans,
486 &trans->parser.FullToken.FullImmediate);
493 emit_frag_end(trans, so);
496 emit_vert_end(trans, so);
499 emit_coord_end(trans, so);
505 tgsi_parse_free(&trans->parser);
508 vc4_generate_code(c);
513 static struct vc4_shader_state *
514 vc4_shader_state_create(struct pipe_context *pctx,
515 const struct pipe_shader_state *cso)
517 struct vc4_shader_state *so = CALLOC_STRUCT(vc4_shader_state);
521 so->base.tokens = tgsi_dup_tokens(cso->tokens);
527 copy_uniform_state_to_shader(struct vc4_shader_state *so,
529 struct tgsi_to_qir *trans)
531 int count = trans->num_uniforms;
532 struct vc4_shader_uniform_info *uinfo = &so->uniforms[shader_index];
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));
544 vc4_fs_state_create(struct pipe_context *pctx,
545 const struct pipe_shader_state *cso)
547 struct vc4_context *vc4 = vc4_context(pctx);
548 struct vc4_shader_state *so = vc4_shader_state_create(pctx, cso);
552 struct tgsi_to_qir *trans = vc4_shader_tgsi_to_qir(so, QSTAGE_FRAG);
553 copy_uniform_state_to_shader(so, 0, trans);
555 so->bo = vc4_bo_alloc_mem(vc4->screen, trans->c->qpu_insts,
556 trans->c->num_qpu_insts * sizeof(uint64_t),
559 qir_compile_destroy(trans->c);
566 vc4_vs_state_create(struct pipe_context *pctx,
567 const struct pipe_shader_state *cso)
569 struct vc4_context *vc4 = vc4_context(pctx);
570 struct vc4_shader_state *so = vc4_shader_state_create(pctx, cso);
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);
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);
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,
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);
591 qir_compile_destroy(vs_trans->c);
592 qir_compile_destroy(cs_trans->c);
598 vc4_shader_state_delete(struct pipe_context *pctx, void *hwcso)
600 struct pipe_shader_state *so = hwcso;
602 free((void *)so->tokens);
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)
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);
617 for (int i = 0; i < uinfo->count; i++) {
618 switch (uinfo->contents[i]) {
619 case QUNIFORM_CONSTANT:
620 map[i] = uinfo->data[i];
622 case QUNIFORM_UNIFORM:
623 map[i] = ((uint32_t *)cb->cb[0].user_buffer)[uinfo->data[i]];
625 case QUNIFORM_VIEWPORT_X_SCALE:
626 map[i] = fui(vc4->framebuffer.width * 16.0f / 2.0f);
628 case QUNIFORM_VIEWPORT_Y_SCALE:
629 map[i] = fui(vc4->framebuffer.height * -16.0f / 2.0f);
633 fprintf(stderr, "%p/%d: %d: 0x%08x (%f)\n",
634 shader, shader_index, i, map[i], uif(map[i]));
643 vc4_fp_state_bind(struct pipe_context *pctx, void *hwcso)
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;
652 vc4_vp_state_bind(struct pipe_context *pctx, void *hwcso)
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;
661 vc4_program_init(struct pipe_context *pctx)
663 pctx->create_vs_state = vc4_vs_state_create;
664 pctx->delete_vs_state = vc4_shader_state_delete;
666 pctx->create_fs_state = vc4_fs_state_create;
667 pctx->delete_fs_state = vc4_shader_state_delete;
669 pctx->bind_fs_state = vc4_fp_state_bind;
670 pctx->bind_vs_state = vc4_vp_state_bind;