mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 02:58:05 +02:00
vc4: Add support for texturing (under simulation)
Only rgba8888 works, and only a single texture unit, and it's only under simulation because I haven't built the kernel interface yet. v2: Rebase on helpers. v3: Fold in the don't-break-the-arm-build fix.
This commit is contained in:
parent
d5a6e3dd9b
commit
66c6c40127
8 changed files with 277 additions and 13 deletions
|
|
@ -197,6 +197,7 @@ void *vc4_simulator_alloc(struct vc4_screen *screen, uint32_t size);
|
|||
void vc4_get_uniform_bo(struct vc4_context *vc4,
|
||||
struct vc4_compiled_shader *shader,
|
||||
struct vc4_constbuf_stateobj *cb,
|
||||
struct vc4_texture_stateobj *texstate,
|
||||
int shader_index, struct vc4_bo **out_bo,
|
||||
uint32_t *out_offset);
|
||||
|
||||
|
|
|
|||
|
|
@ -171,12 +171,15 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
|
|||
uint32_t fs_ubo_offset, vs_ubo_offset, cs_ubo_offset;
|
||||
vc4_get_uniform_bo(vc4, vc4->prog.fs,
|
||||
&vc4->constbuf[PIPE_SHADER_FRAGMENT],
|
||||
&vc4->fragtex,
|
||||
0, &fs_ubo, &fs_ubo_offset);
|
||||
vc4_get_uniform_bo(vc4, vc4->prog.vs,
|
||||
&vc4->constbuf[PIPE_SHADER_VERTEX],
|
||||
&vc4->verttex,
|
||||
0, &vs_ubo, &vs_ubo_offset);
|
||||
vc4_get_uniform_bo(vc4, vc4->prog.vs,
|
||||
&vc4->constbuf[PIPE_SHADER_VERTEX],
|
||||
&vc4->verttex,
|
||||
1, &cs_ubo, &cs_ubo_offset);
|
||||
|
||||
cl_start_shader_reloc(&vc4->shader_rec, 6 + vtx->num_elements);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@
|
|||
#include "vc4_context.h"
|
||||
#include "vc4_qpu.h"
|
||||
#include "vc4_qir.h"
|
||||
#ifdef USE_VC4_SIMULATOR
|
||||
#include "simpenrose/simpenrose.h"
|
||||
#endif
|
||||
|
||||
struct tgsi_to_qir {
|
||||
struct tgsi_parse_context parser;
|
||||
|
|
@ -157,6 +160,10 @@ get_src(struct tgsi_to_qir *trans, struct tgsi_src_register *src, int i)
|
|||
case TGSI_FILE_INPUT:
|
||||
r = trans->inputs[src->Index * 4 + s];
|
||||
break;
|
||||
case TGSI_FILE_SAMPLER:
|
||||
case TGSI_FILE_SAMPLER_VIEW:
|
||||
r = c->undef;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown src file %d\n", src->File);
|
||||
abort();
|
||||
|
|
@ -278,6 +285,51 @@ tgsi_to_qir_lrp(struct tgsi_to_qir *trans,
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
tgsi_to_qir_tex(struct tgsi_to_qir *trans,
|
||||
struct tgsi_full_instruction *tgsi_inst,
|
||||
enum qop op, struct qreg *src)
|
||||
{
|
||||
struct qcompile *c = trans->c;
|
||||
|
||||
assert(!tgsi_inst->Instruction.Saturate);
|
||||
|
||||
struct qreg s = src[0 * 4 + 0];
|
||||
struct qreg t = src[0 * 4 + 1];
|
||||
|
||||
if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXP) {
|
||||
struct qreg proj = qir_RCP(c, src[0 * 4 + 3]);
|
||||
s = qir_FMUL(c, s, proj);
|
||||
t = qir_FMUL(c, t, proj);
|
||||
}
|
||||
|
||||
uint32_t tex_and_sampler = 0; /* XXX */
|
||||
qir_TEX_T(c, t, add_uniform(trans, QUNIFORM_TEXTURE_CONFIG_P0,
|
||||
tex_and_sampler));
|
||||
|
||||
struct qreg sampler_p1 = add_uniform(trans, QUNIFORM_TEXTURE_CONFIG_P1,
|
||||
tex_and_sampler);
|
||||
if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXB) {
|
||||
qir_TEX_B(c, src[0 * 4 + 3], sampler_p1);
|
||||
qir_TEX_S(c, s, add_uniform(trans, QUNIFORM_CONSTANT, 0));
|
||||
} else {
|
||||
qir_TEX_S(c, s, sampler_p1);
|
||||
}
|
||||
|
||||
qir_emit(c, qir_inst(QOP_TEX_RESULT, c->undef, c->undef, c->undef));
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!(tgsi_inst->Dst[0].Register.WriteMask & (1 << i)))
|
||||
continue;
|
||||
|
||||
struct qreg dst = qir_get_temp(c);
|
||||
qir_emit(c, qir_inst(QOP_R4_UNPACK_A + i,
|
||||
dst,
|
||||
c->undef, c->undef));
|
||||
update_dst(trans, tgsi_inst, i, dst);
|
||||
}
|
||||
}
|
||||
|
||||
static struct qreg
|
||||
tgsi_to_qir_pow(struct tgsi_to_qir *trans,
|
||||
struct tgsi_full_instruction *tgsi_inst,
|
||||
|
|
@ -577,13 +629,6 @@ emit_tgsi_instruction(struct tgsi_to_qir *trans,
|
|||
if (tgsi_op == TGSI_OPCODE_END)
|
||||
return;
|
||||
|
||||
if (tgsi_op > ARRAY_SIZE(op_trans) || !op_trans[tgsi_op].func) {
|
||||
fprintf(stderr, "unknown tgsi inst: ");
|
||||
tgsi_dump_instruction(tgsi_inst, asdf++);
|
||||
fprintf(stderr, "\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
struct qreg src_regs[12];
|
||||
for (int s = 0; s < 3; s++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
|
@ -592,6 +637,24 @@ emit_tgsi_instruction(struct tgsi_to_qir *trans,
|
|||
}
|
||||
}
|
||||
|
||||
switch (tgsi_op) {
|
||||
case TGSI_OPCODE_TEX:
|
||||
case TGSI_OPCODE_TXP:
|
||||
case TGSI_OPCODE_TXB:
|
||||
tgsi_to_qir_tex(trans, tgsi_inst,
|
||||
op_trans[tgsi_op].op, src_regs);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (tgsi_op > ARRAY_SIZE(op_trans) || !(op_trans[tgsi_op].func)) {
|
||||
fprintf(stderr, "unknown tgsi inst: ");
|
||||
tgsi_dump_instruction(tgsi_inst, asdf++);
|
||||
fprintf(stderr, "\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!(tgsi_inst->Dst[0].Register.WriteMask & (1 << i)))
|
||||
continue;
|
||||
|
|
@ -1043,9 +1106,74 @@ vc4_shader_state_delete(struct pipe_context *pctx, void *hwcso)
|
|||
free(so);
|
||||
}
|
||||
|
||||
static uint32_t translate_wrap(uint32_t p_wrap)
|
||||
{
|
||||
switch (p_wrap) {
|
||||
case PIPE_TEX_WRAP_REPEAT:
|
||||
return 0;
|
||||
case PIPE_TEX_WRAP_CLAMP:
|
||||
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
|
||||
return 1;
|
||||
case PIPE_TEX_WRAP_MIRROR_REPEAT:
|
||||
return 2;
|
||||
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
|
||||
return 3;
|
||||
default:
|
||||
fprintf(stderr, "Unknown wrap mode %d\n", p_wrap);
|
||||
assert(!"not reached");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_texture_p0(struct vc4_texture_stateobj *texstate,
|
||||
uint32_t tex_and_sampler)
|
||||
{
|
||||
uint32_t texi = (tex_and_sampler >> 0) & 0xff;
|
||||
struct pipe_sampler_view *texture = texstate->textures[texi];
|
||||
struct vc4_resource *rsc = vc4_resource(texture->texture);
|
||||
|
||||
return (texture->u.tex.last_level |
|
||||
#if USE_VC4_SIMULATOR
|
||||
simpenrose_hw_addr(rsc->bo->map) /* XXX */
|
||||
#else
|
||||
0 /* XXX */
|
||||
#endif
|
||||
/* XXX: data type */);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_texture_p1(struct vc4_texture_stateobj *texstate,
|
||||
uint32_t tex_and_sampler)
|
||||
{
|
||||
uint32_t texi = (tex_and_sampler >> 0) & 0xff;
|
||||
uint32_t sampi = (tex_and_sampler >> 8) & 0xff;
|
||||
struct pipe_sampler_view *texture = texstate->textures[texi];
|
||||
struct pipe_sampler_state *sampler = texstate->samplers[sampi];
|
||||
static const uint32_t mipfilter_map[] = {
|
||||
[PIPE_TEX_MIPFILTER_NEAREST] = 2,
|
||||
[PIPE_TEX_MIPFILTER_LINEAR] = 4,
|
||||
[PIPE_TEX_MIPFILTER_NONE] = 0
|
||||
};
|
||||
static const uint32_t imgfilter_map[] = {
|
||||
[PIPE_TEX_FILTER_NEAREST] = 1,
|
||||
[PIPE_TEX_FILTER_LINEAR] = 0,
|
||||
};
|
||||
|
||||
return ((1 << 31) /* XXX: data type */|
|
||||
(texture->texture->height0 << 20) |
|
||||
(texture->texture->width0 << 8) |
|
||||
(imgfilter_map[sampler->mag_img_filter] << 7) |
|
||||
((imgfilter_map[sampler->min_img_filter] +
|
||||
mipfilter_map[sampler->min_mip_filter]) << 4) |
|
||||
(translate_wrap(sampler->wrap_t) << 2) |
|
||||
(translate_wrap(sampler->wrap_s) << 0));
|
||||
}
|
||||
|
||||
void
|
||||
vc4_get_uniform_bo(struct vc4_context *vc4, struct vc4_compiled_shader *shader,
|
||||
struct vc4_constbuf_stateobj *cb,
|
||||
struct vc4_texture_stateobj *texstate,
|
||||
int shader_index, struct vc4_bo **out_bo,
|
||||
uint32_t *out_offset)
|
||||
{
|
||||
|
|
@ -1055,6 +1183,7 @@ vc4_get_uniform_bo(struct vc4_context *vc4, struct vc4_compiled_shader *shader,
|
|||
uint32_t *map = vc4_bo_map(ubo);
|
||||
|
||||
for (int i = 0; i < uinfo->count; i++) {
|
||||
|
||||
switch (uinfo->contents[i]) {
|
||||
case QUNIFORM_CONSTANT:
|
||||
map[i] = uinfo->data[i];
|
||||
|
|
@ -1068,6 +1197,14 @@ vc4_get_uniform_bo(struct vc4_context *vc4, struct vc4_compiled_shader *shader,
|
|||
case QUNIFORM_VIEWPORT_Y_SCALE:
|
||||
map[i] = fui(vc4->framebuffer.height * -16.0f / 2.0f);
|
||||
break;
|
||||
|
||||
case QUNIFORM_TEXTURE_CONFIG_P0:
|
||||
map[i] = get_texture_p0(texstate, uinfo->data[i]);
|
||||
break;
|
||||
|
||||
case QUNIFORM_TEXTURE_CONFIG_P1:
|
||||
map[i] = get_texture_p1(texstate, uinfo->data[i]);
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
fprintf(stderr, "%p/%d: %d: 0x%08x (%f)\n",
|
||||
|
|
|
|||
|
|
@ -63,6 +63,16 @@ static const struct qir_op_info qir_op_info[] = {
|
|||
[QOP_VPM_READ] = { "vpm_read", 0, 1, true },
|
||||
[QOP_TLB_COLOR_WRITE] = { "tlb_color", 0, 1, true },
|
||||
[QOP_VARY_ADD_C] = { "vary_add_c", 1, 1 },
|
||||
|
||||
[QOP_TEX_S] = { "tex_s", 0, 2 },
|
||||
[QOP_TEX_T] = { "tex_t", 0, 2 },
|
||||
[QOP_TEX_R] = { "tex_r", 0, 2 },
|
||||
[QOP_TEX_B] = { "tex_b", 0, 2 },
|
||||
[QOP_TEX_RESULT] = { "tex_result", 0, 0 },
|
||||
[QOP_R4_UNPACK_A] = { "r4_unpack_a", 1, 0 },
|
||||
[QOP_R4_UNPACK_B] = { "r4_unpack_b", 1, 0 },
|
||||
[QOP_R4_UNPACK_C] = { "r4_unpack_c", 1, 0 },
|
||||
[QOP_R4_UNPACK_D] = { "r4_unpack_d", 1, 0 },
|
||||
};
|
||||
|
||||
static const char *
|
||||
|
|
|
|||
|
|
@ -72,6 +72,24 @@ enum qop {
|
|||
QOP_VPM_READ,
|
||||
QOP_TLB_COLOR_WRITE,
|
||||
QOP_VARY_ADD_C,
|
||||
|
||||
/** Texture x coordinate parameter write */
|
||||
QOP_TEX_S,
|
||||
/** Texture y coordinate parameter write */
|
||||
QOP_TEX_T,
|
||||
/** Texture border color parameter or cube map z coordinate write */
|
||||
QOP_TEX_R,
|
||||
/** Texture LOD bias parameter write */
|
||||
QOP_TEX_B,
|
||||
/**
|
||||
* Signal of texture read being necessary and then reading r4 into
|
||||
* the destination
|
||||
*/
|
||||
QOP_TEX_RESULT,
|
||||
QOP_R4_UNPACK_A,
|
||||
QOP_R4_UNPACK_B,
|
||||
QOP_R4_UNPACK_C,
|
||||
QOP_R4_UNPACK_D
|
||||
};
|
||||
|
||||
struct simple_node {
|
||||
|
|
@ -120,6 +138,25 @@ enum quniform_contents {
|
|||
QUNIFORM_VIEWPORT_X_SCALE,
|
||||
QUNIFORM_VIEWPORT_Y_SCALE,
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* A reference to a texture config parameter 0 uniform.
|
||||
*
|
||||
* This is a uniform implicitly loaded with a QPU_W_TMU* write, which
|
||||
* defines texture type, miplevels, and such. It will be found as a
|
||||
* parameter to the first QOP_TEX_[STRB] instruction in a sequence.
|
||||
*/
|
||||
QUNIFORM_TEXTURE_CONFIG_P0,
|
||||
|
||||
/**
|
||||
* A reference to a texture config parameter 1 uniform.
|
||||
*
|
||||
* This is a uniform implicitly loaded with a QPU_W_TMU* write, which
|
||||
* defines texture width, height, filters, and wrap modes. It will be
|
||||
* found as a parameter to the second QOP_TEX_[STRB] instruction in a
|
||||
* sequence.
|
||||
*/
|
||||
QUNIFORM_TEXTURE_CONFIG_P1,
|
||||
};
|
||||
|
||||
struct qcompile {
|
||||
|
|
@ -178,6 +215,20 @@ qir_##name(struct qcompile *c, struct qreg a, struct qreg b) \
|
|||
return t; \
|
||||
}
|
||||
|
||||
#define QIR_NODST_1(name) \
|
||||
static inline void \
|
||||
qir_##name(struct qcompile *c, struct qreg a) \
|
||||
{ \
|
||||
qir_emit(c, qir_inst(QOP_##name, c->undef, a, c->undef)); \
|
||||
}
|
||||
|
||||
#define QIR_NODST_2(name) \
|
||||
static inline void \
|
||||
qir_##name(struct qcompile *c, struct qreg a, struct qreg b) \
|
||||
{ \
|
||||
qir_emit(c, qir_inst(QOP_##name, c->undef, a, b)); \
|
||||
}
|
||||
|
||||
QIR_ALU1(MOV)
|
||||
QIR_ALU2(FADD)
|
||||
QIR_ALU2(FSUB)
|
||||
|
|
@ -194,12 +245,11 @@ QIR_ALU1(EXP2)
|
|||
QIR_ALU1(LOG2)
|
||||
QIR_ALU2(PACK_SCALED)
|
||||
QIR_ALU1(VARY_ADD_C)
|
||||
|
||||
static inline void
|
||||
qir_VPM_WRITE(struct qcompile *c, struct qreg a)
|
||||
{
|
||||
qir_emit(c, qir_inst(QOP_VPM_WRITE, c->undef, a, c->undef));
|
||||
}
|
||||
QIR_NODST_1(VPM_WRITE)
|
||||
QIR_NODST_2(TEX_S)
|
||||
QIR_NODST_2(TEX_T)
|
||||
QIR_NODST_2(TEX_R)
|
||||
QIR_NODST_2(TEX_B)
|
||||
|
||||
static inline struct qreg
|
||||
qir_CMP(struct qcompile *c, struct qreg cmp, struct qreg a, struct qreg b)
|
||||
|
|
|
|||
|
|
@ -195,6 +195,17 @@ enum qpu_pack_a {
|
|||
QPU_PACK_A_8D_SAT,
|
||||
};
|
||||
|
||||
enum qpu_unpack_r4 {
|
||||
QPU_UNPACK_R4_NOP,
|
||||
QPU_UNPACK_R4_F16A_TO_F32,
|
||||
QPU_UNPACK_R4_F16B_TO_F32,
|
||||
QPU_UNPACK_R4_8D_REP,
|
||||
QPU_UNPACK_R4_8A,
|
||||
QPU_UNPACK_R4_8B,
|
||||
QPU_UNPACK_R4_8C,
|
||||
QPU_UNPACK_R4_8D,
|
||||
};
|
||||
|
||||
#define QPU_MASK(high, low) ((((uint64_t)1<<((high)-(low)+1))-1)<<(low))
|
||||
/* Using the GNU statement expression extension */
|
||||
#define QPU_SET_FIELD(value, field) \
|
||||
|
|
@ -209,6 +220,9 @@ enum qpu_pack_a {
|
|||
#define QPU_SIG_SHIFT 60
|
||||
#define QPU_SIG_MASK QPU_MASK(63, 60)
|
||||
|
||||
#define QPU_UNPACK_SHIFT 57
|
||||
#define QPU_UNPACK_MASK QPU_MASK(59, 57)
|
||||
|
||||
/**
|
||||
* If set, the pack field means PACK_MUL or R4 packing, instead of normal
|
||||
* regfile a packing.
|
||||
|
|
|
|||
|
|
@ -93,6 +93,17 @@ static const char *qpu_pack_mul[] = {
|
|||
[QPU_PACK_MUL_8D] = "8d",
|
||||
};
|
||||
|
||||
static const char *qpu_unpack_r4[] = {
|
||||
[QPU_UNPACK_R4_NOP] = "",
|
||||
[QPU_UNPACK_R4_F16A_TO_F32] = "f16a",
|
||||
[QPU_UNPACK_R4_F16B_TO_F32] = "f16b",
|
||||
[QPU_UNPACK_R4_8D_REP] = "8d_rep",
|
||||
[QPU_UNPACK_R4_8A] = "8a",
|
||||
[QPU_UNPACK_R4_8B] = "8b",
|
||||
[QPU_UNPACK_R4_8C] = "8c",
|
||||
[QPU_UNPACK_R4_8D] = "8d",
|
||||
};
|
||||
|
||||
static const char *special_read_a[] = {
|
||||
"uni",
|
||||
NULL,
|
||||
|
|
@ -263,6 +274,7 @@ print_alu_src(uint64_t inst, uint32_t mux)
|
|||
uint32_t raddr = (is_a ?
|
||||
QPU_GET_FIELD(inst, QPU_RADDR_A) :
|
||||
QPU_GET_FIELD(inst, QPU_RADDR_B));
|
||||
uint32_t unpack = QPU_GET_FIELD(inst, QPU_UNPACK);
|
||||
|
||||
if (mux <= QPU_MUX_R5)
|
||||
fprintf(stderr, "r%d", mux);
|
||||
|
|
@ -287,6 +299,11 @@ print_alu_src(uint64_t inst, uint32_t mux)
|
|||
else
|
||||
fprintf(stderr, "%s", DESC(special_read_b, raddr - 32));
|
||||
}
|
||||
|
||||
if (mux == QPU_MUX_R4 && (inst & QPU_PM) &&
|
||||
unpack != QPU_UNPACK_R4_NOP) {
|
||||
fprintf(stderr, ".%s", DESC(qpu_unpack_r4, unpack));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -490,6 +490,38 @@ vc4_generate_code(struct qcompile *c)
|
|||
break;
|
||||
}
|
||||
|
||||
case QOP_TEX_S:
|
||||
case QOP_TEX_T:
|
||||
case QOP_TEX_R:
|
||||
case QOP_TEX_B:
|
||||
queue(c, qpu_inst(qpu_a_MOV(qpu_rb(QPU_W_TMU0_S +
|
||||
(qinst->op -
|
||||
QOP_TEX_S)),
|
||||
src[0]),
|
||||
qpu_m_NOP()));
|
||||
break;
|
||||
|
||||
case QOP_TEX_RESULT:
|
||||
queue(c, qpu_inst(qpu_a_NOP(), qpu_m_NOP()));
|
||||
*last_inst(c) = qpu_set_sig(*last_inst(c),
|
||||
QPU_SIG_LOAD_TMU0);
|
||||
|
||||
break;
|
||||
|
||||
case QOP_R4_UNPACK_A:
|
||||
case QOP_R4_UNPACK_B:
|
||||
case QOP_R4_UNPACK_C:
|
||||
case QOP_R4_UNPACK_D:
|
||||
queue(c, qpu_inst(qpu_a_MOV(dst, qpu_r4()),
|
||||
qpu_m_NOP()));
|
||||
*last_inst(c) |= QPU_PM;
|
||||
*last_inst(c) |= QPU_SET_FIELD(QPU_UNPACK_R4_8A +
|
||||
(qinst->op -
|
||||
QOP_R4_UNPACK_A),
|
||||
QPU_UNPACK);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(qinst->op < ARRAY_SIZE(translate));
|
||||
assert(translate[qinst->op].op != 0); /* NOPs */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue