blob: 2fe7c2168383e995a8c65430d5827d88fe9d52f4 [file] [log] [blame]
/*
* 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;
}