aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/vc4/vc4_program.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_program.c')
-rw-r--r--src/gallium/drivers/vc4/vc4_program.c229
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;
+}