diff options
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_program.c')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_program.c | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c new file mode 100644 index 00000000000..2fe7c216838 --- /dev/null +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -0,0 +1,229 @@ +/* + * 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 <stdio.h> +#include <inttypes.h> +#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; +} |