/* * Copyright (c) 2014 Scott Mansell * Copyright © 2014 Broadcom * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include #include #include "pipe/p_state.h" #include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "vc4_context.h" #include "vc4_qpu.h" static void vc4_dump_program(const uint64_t *insts, uint count) { for (int i = 0; i < count; i++) { fprintf(stderr, "0x%016"PRIx64" ", insts[i]); vc4_qpu_disasm(&insts[i], 1); fprintf(stderr, "\n"); } } static struct vc4_shader_state * vc4_shader_state_create(struct pipe_context *pctx, const struct pipe_shader_state *cso) { struct vc4_shader_state *so = CALLOC_STRUCT(vc4_shader_state); if (!so) return NULL; so->base.tokens = tgsi_dup_tokens(cso->tokens); return so; } static void * vc4_fs_state_create(struct pipe_context *pctx, const struct pipe_shader_state *cso) { struct vc4_context *vc4 = vc4_context(pctx); struct vc4_shader_state *so = vc4_shader_state_create(pctx, cso); if (!so) return NULL; uint64_t gen_fsc[100]; uint64_t cur_inst; int gen_fsc_len = 0; #if 1 cur_inst = qpu_load_imm_f(qpu_r5(), 0.0f); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_MOV(qpu_r0(), qpu_vary()), qpu_m_MOV(qpu_r3(), qpu_r5())); cur_inst |= QPU_PM; cur_inst |= QPU_SET_FIELD(QPU_PACK_MUL_8D, QPU_PACK); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_FADD(qpu_r0(), qpu_r0(), qpu_r5()), qpu_m_MOV(qpu_r1(), qpu_vary())); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_FADD(qpu_r1(), qpu_r1(), qpu_r5()), qpu_m_MOV(qpu_r2(), qpu_vary())); cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_WAIT_FOR_SCOREBOARD, QPU_SIG); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_FADD(qpu_r2(), qpu_r2(), qpu_r5()), qpu_m_MOV(qpu_r3(), qpu_r0())); cur_inst |= QPU_PM; cur_inst |= QPU_SET_FIELD(QPU_PACK_MUL_8A, QPU_PACK); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_MOV(qpu_r3(), qpu_r1())); cur_inst |= QPU_PM; cur_inst |= QPU_SET_FIELD(QPU_PACK_MUL_8B, QPU_PACK); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_MOV(qpu_r3(), qpu_r2())); cur_inst |= QPU_PM; cur_inst |= QPU_SET_FIELD(QPU_PACK_MUL_8C, QPU_PACK); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_MOV(qpu_tlbc(), qpu_r3()), qpu_m_NOP()); cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_PROG_END, QPU_SIG); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP()); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP()); cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_SCOREBOARD_UNLOCK, QPU_SIG); gen_fsc[gen_fsc_len++] = cur_inst; #else /* drain the varyings. */ for (int i = 0; i < 3; i++) { cur_inst = qpu_inst(qpu_a_MOV(qpu_ra(QPU_W_NOP), qpu_rb(QPU_R_NOP)), qpu_m_NOP()); if (i == 1) cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_WAIT_FOR_SCOREBOARD, QPU_SIG); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP()); gen_fsc[gen_fsc_len++] = cur_inst; } /* some colors */ #if 1 for (int i = 0; i < 4; i++) { cur_inst = qpu_load_imm_f(qpu_rn(i), .2 + i / 4.0); gen_fsc[gen_fsc_len++] = cur_inst; } for (int i = 0; i < 4; i++) { cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_FMUL(qpu_ra(1), qpu_rn(i), qpu_rn(i))); cur_inst |= QPU_PM; cur_inst |= QPU_SET_FIELD(QPU_PACK_A_8A + i, QPU_PACK); gen_fsc[gen_fsc_len++] = cur_inst; } #else cur_inst = qpu_load_imm_ui(qpu_ra(1), 0x22446688); gen_fsc[gen_fsc_len++] = cur_inst; #endif cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP()); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_MOV(qpu_tlbc(), qpu_ra(1)), qpu_m_NOP()); cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_PROG_END, QPU_SIG); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP()); gen_fsc[gen_fsc_len++] = cur_inst; cur_inst = qpu_inst(qpu_a_NOP(), qpu_m_NOP()); cur_inst = (cur_inst & ~QPU_SIG_MASK) | QPU_SET_FIELD(QPU_SIG_SCOREBOARD_UNLOCK, QPU_SIG); gen_fsc[gen_fsc_len++] = cur_inst; #endif if (1) vc4_dump_program(gen_fsc, gen_fsc_len); vc4_qpu_validate(gen_fsc, gen_fsc_len); so->bo = vc4_bo_alloc_mem(vc4->screen, gen_fsc, gen_fsc_len * sizeof(uint64_t), "fs_code"); return so; } static void * vc4_vs_state_create(struct pipe_context *pctx, const struct pipe_shader_state *cso) { struct vc4_shader_state *so = vc4_shader_state_create(pctx, cso); if (!so) return NULL; return so; } static void vc4_shader_state_delete(struct pipe_context *pctx, void *hwcso) { struct pipe_shader_state *so = hwcso; free((void *)so->tokens); free(so); } static void vc4_fp_state_bind(struct pipe_context *pctx, void *hwcso) { struct vc4_context *vc4 = vc4_context(pctx); vc4->prog.fs = hwcso; vc4->prog.dirty |= VC4_SHADER_DIRTY_FP; vc4->dirty |= VC4_DIRTY_PROG; } static void vc4_vp_state_bind(struct pipe_context *pctx, void *hwcso) { struct vc4_context *vc4 = vc4_context(pctx); vc4->prog.vs = hwcso; vc4->prog.dirty |= VC4_SHADER_DIRTY_VP; vc4->dirty |= VC4_DIRTY_PROG; } void vc4_program_init(struct pipe_context *pctx) { pctx->create_vs_state = vc4_vs_state_create; pctx->delete_vs_state = vc4_shader_state_delete; pctx->create_fs_state = vc4_fs_state_create; pctx->delete_fs_state = vc4_shader_state_delete; pctx->bind_fs_state = vc4_fp_state_bind; pctx->bind_vs_state = vc4_vp_state_bind; }