summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlyssa Rosenzweig <[email protected]>2019-06-20 15:51:31 -0700
committerAlyssa Rosenzweig <[email protected]>2019-06-24 12:57:40 -0700
commit5e2c3d40bd36af5ec4961f7ce8098d760ea347d0 (patch)
tree67d4fc9f864d723ba9367da8f7b028e25aef632c
parentf28e9e868b42d3df67dba76cb363e55ec4eee424 (diff)
panfrost/midgard: Implement UBO reads
UBOs and uniforms now use a common code path with an explicit `index` argument passed, enabling UBO reads. Signed-off-by: Alyssa Rosenzweig <[email protected]>
-rw-r--r--src/gallium/drivers/panfrost/midgard/midgard_compile.c65
1 files changed, 51 insertions, 14 deletions
diff --git a/src/gallium/drivers/panfrost/midgard/midgard_compile.c b/src/gallium/drivers/panfrost/midgard/midgard_compile.c
index baf637d666a..938872cc09e 100644
--- a/src/gallium/drivers/panfrost/midgard/midgard_compile.c
+++ b/src/gallium/drivers/panfrost/midgard/midgard_compile.c
@@ -1069,12 +1069,20 @@ emit_alu(compiler_context *ctx, nir_alu_instr *instr)
#undef ALU_CASE
+/* Uniforms and UBOs use a shared code path, as uniforms are just (slightly
+ * optimized) versions of UBO #0 */
+
static void
-emit_uniform_read(compiler_context *ctx, unsigned dest, unsigned offset, nir_src *indirect_offset)
+emit_ubo_read(
+ compiler_context *ctx,
+ unsigned dest,
+ unsigned offset,
+ nir_src *indirect_offset,
+ unsigned index)
{
/* TODO: half-floats */
- if (!indirect_offset && offset < ctx->uniform_cutoff) {
+ if (!indirect_offset && offset < ctx->uniform_cutoff && index == 0) {
/* Fast path: For the first 16 uniforms, direct accesses are
* 0-cycle, since they're just a register fetch in the usual
* case. So, we alias the registers while we're still in
@@ -1095,11 +1103,13 @@ emit_uniform_read(compiler_context *ctx, unsigned dest, unsigned offset, nir_src
if (indirect_offset) {
emit_indirect_offset(ctx, indirect_offset);
- ins.load_store.unknown = 0x8700; /* xxx: what is this? */
+ ins.load_store.unknown = 0x8700 | index; /* xxx: what is this? */
} else {
- ins.load_store.unknown = 0x1E00; /* xxx: what is this? */
+ ins.load_store.unknown = 0x1E00 | index; /* xxx: what is this? */
}
+ /* TODO respect index */
+
emit_mir_instruction(ctx, ins);
}
}
@@ -1152,7 +1162,7 @@ emit_sysval_read(compiler_context *ctx, nir_instr *instr)
unsigned uniform = ((uintptr_t) val) - 1;
/* Emit the read itself -- this is never indirect */
- emit_uniform_read(ctx, dest, uniform, NULL);
+ emit_ubo_read(ctx, dest, uniform, NULL, 0);
}
/* Reads RGBA8888 value from the tilebuffer and converts to a RGBA32F register,
@@ -1231,7 +1241,7 @@ emit_fb_read_blend_scalar(compiler_context *ctx, unsigned reg)
static void
emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
{
- unsigned offset, reg;
+ unsigned offset = 0, reg;
switch (instr->intrinsic) {
case nir_intrinsic_discard_if:
@@ -1250,23 +1260,49 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
}
case nir_intrinsic_load_uniform:
- case nir_intrinsic_load_input:
- offset = nir_intrinsic_base(instr);
+ case nir_intrinsic_load_ubo:
+ case nir_intrinsic_load_input: {
+ bool is_uniform = instr->intrinsic == nir_intrinsic_load_uniform;
+ bool is_ubo = instr->intrinsic == nir_intrinsic_load_ubo;
+
+ if (!is_ubo) {
+ offset = nir_intrinsic_base(instr);
+ }
unsigned nr_comp = nir_intrinsic_dest_components(instr);
- bool direct = nir_src_is_const(instr->src[0]);
- if (direct) {
- offset += nir_src_as_uint(instr->src[0]);
- }
+ nir_src *src_offset = nir_get_io_offset_src(instr);
+
+ bool direct = nir_src_is_const(*src_offset);
+
+ if (direct)
+ offset += nir_src_as_uint(*src_offset);
/* We may need to apply a fractional offset */
int component = instr->intrinsic == nir_intrinsic_load_input ?
nir_intrinsic_component(instr) : 0;
reg = nir_dest_index(ctx, &instr->dest);
- if (instr->intrinsic == nir_intrinsic_load_uniform && !ctx->is_blend) {
- emit_uniform_read(ctx, reg, ctx->sysval_count + offset, !direct ? &instr->src[0] : NULL);
+ if (is_uniform && !ctx->is_blend) {
+ emit_ubo_read(ctx, reg, ctx->sysval_count + offset, !direct ? &instr->src[0] : NULL, 0);
+ } else if (is_ubo) {
+ nir_src index = instr->src[0];
+
+ /* We don't yet support indirect UBOs. For indirect
+ * block numbers (if that's possible), we don't know
+ * enough about the hardware yet. For indirect sources,
+ * we know what we need but we need to add some NIR
+ * support for lowering correctly with respect to
+ * 128-bit reads */
+
+ assert(nir_src_is_const(index));
+ assert(nir_src_is_const(*src_offset));
+
+ /* TODO: Alignment */
+ assert((offset & 0xF) == 0);
+
+ uint32_t uindex = nir_src_as_uint(index) + 1;
+ emit_ubo_read(ctx, reg, offset / 16, NULL, uindex);
} else if (ctx->stage == MESA_SHADER_FRAGMENT && !ctx->is_blend) {
emit_varying_read(ctx, reg, offset, nr_comp, component, !direct ? &instr->src[0] : NULL);
} else if (ctx->is_blend) {
@@ -1286,6 +1322,7 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
}
break;
+ }
case nir_intrinsic_load_output:
assert(nir_src_is_const(instr->src[0]));