summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/vc4/vc4_program.c
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2014-07-15 12:29:32 -0700
committerEric Anholt <[email protected]>2014-08-11 14:40:45 -0700
commit66c6c401279aa4152a24681f64d0e101aa004593 (patch)
tree8707e885b36cc7a3b522637823eb5dbf83bdd3a2 /src/gallium/drivers/vc4/vc4_program.c
parentd5a6e3dd9b094a427c7842817227db25fbece134 (diff)
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.
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_program.c')
-rw-r--r--src/gallium/drivers/vc4/vc4_program.c151
1 files changed, 144 insertions, 7 deletions
diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c
index 0b26f5adf5b..b45507d154d 100644
--- a/src/gallium/drivers/vc4/vc4_program.c
+++ b/src/gallium/drivers/vc4/vc4_program.c
@@ -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",