summaryrefslogtreecommitdiffstats
path: root/src/broadcom
diff options
context:
space:
mode:
authorIago Toral Quiroga <[email protected]>2019-07-03 09:30:43 +0200
committerIago Toral Quiroga <[email protected]>2019-07-12 09:16:38 +0200
commit47d7c80dc788a7354a706d3fe0862a1c21ecb566 (patch)
tree5b68722cc217a9755aa6fc6d297cdda7f876d07f /src/broadcom
parentb0eec9e27d753af11f82d64bd329234a3291339c (diff)
v3d: implement tile buffer color read intrinsic
We will be emitting this intrinsic to signal TLB color loads when we implement OpenGL logic operations, where we need to blend the fragment shader color output with the existing color in the render target. Per-sample TLB reads are not supported yet. v2: fix the offset into the color_reads array (Eric). Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src/broadcom')
-rw-r--r--src/broadcom/compiler/nir_to_vir.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/broadcom/compiler/nir_to_vir.c b/src/broadcom/compiler/nir_to_vir.c
index b05c892bba6..75622338aa2 100644
--- a/src/broadcom/compiler/nir_to_vir.c
+++ b/src/broadcom/compiler/nir_to_vir.c
@@ -1633,6 +1633,102 @@ ntq_emit_image_size(struct v3d_compile *c, nir_intrinsic_instr *instr)
}
static void
+vir_emit_tlb_color_read(struct v3d_compile *c, nir_intrinsic_instr *instr)
+{
+ assert(c->s->info.stage == MESA_SHADER_FRAGMENT);
+
+ int rt = nir_src_as_uint(instr->src[0]);
+ assert(rt < V3D_MAX_DRAW_BUFFERS);
+
+ int sample_index = nir_intrinsic_base(instr) ;
+ assert(sample_index == 0); /* XXX: multisample */
+
+ int component = nir_intrinsic_component(instr);
+ assert(component < 4);
+
+ struct qreg *color_reads =
+ &c->color_reads[(rt * V3D_MAX_SAMPLES + sample_index) * 4];
+
+ if (color_reads[component].file == QFILE_NULL) {
+ enum pipe_format rt_format = c->fs_key->color_fmt[rt].format;
+ int num_components =
+ util_format_get_nr_components(rt_format);
+
+ const bool swap_rb = c->fs_key->swap_color_rb & (1 << rt);
+ if (swap_rb)
+ num_components = MAX2(num_components, 3);
+
+ bool is_int_format = (c->fs_key->int_color_rb & (1 << rt)) ||
+ (c->fs_key->uint_color_rb & (1 << rt));
+
+ bool is_32b_tlb_format = is_int_format ||
+ (c->fs_key->f32_color_rb & (1 << rt));
+
+ uint32_t conf = 0xffffff00;
+ conf |= TLB_SAMPLE_MODE_PER_PIXEL; /* XXX: multisample */
+ conf |= (7 - rt) << TLB_RENDER_TARGET_SHIFT;
+
+ if (is_32b_tlb_format) {
+ /* The F32 vs I32 distinction was dropped in 4.2. */
+ conf |= (c->devinfo->ver < 42 && is_int_format) ?
+ TLB_TYPE_I32_COLOR : TLB_TYPE_F32_COLOR;
+
+ conf |= ((num_components - 1) <<
+ TLB_VEC_SIZE_MINUS_1_SHIFT);
+ } else {
+ conf |= TLB_TYPE_F16_COLOR;
+ conf |= TLB_F16_SWAP_HI_LO;
+
+ if (num_components >= 3)
+ conf |= TLB_VEC_SIZE_4_F16;
+ else
+ conf |= TLB_VEC_SIZE_2_F16;
+ }
+
+ struct qreg r, g, b, a;
+ if (is_32b_tlb_format) {
+ r = conf != 0xffffffff ? vir_TLBU_COLOR_READ(c, conf) :
+ vir_TLB_COLOR_READ(c);
+ if (num_components >= 2)
+ g = vir_TLB_COLOR_READ(c);
+ if (num_components >= 3)
+ b = vir_TLB_COLOR_READ(c);
+ if (num_components >= 4)
+ a = vir_TLB_COLOR_READ(c);
+ } else {
+ struct qreg rg = conf != 0xffffffff ?
+ vir_TLBU_COLOR_READ(c, conf) :
+ vir_TLB_COLOR_READ(c);
+ r = vir_FMOV(c, rg);
+ vir_set_unpack(c->defs[r.index], 0, V3D_QPU_UNPACK_L);
+ g = vir_FMOV(c, rg);
+ vir_set_unpack(c->defs[g.index], 0, V3D_QPU_UNPACK_H);
+
+ if (num_components > 2) {
+ struct qreg ba = vir_TLB_COLOR_READ(c);
+ b = vir_FMOV(c, ba);
+ vir_set_unpack(c->defs[b.index], 0,
+ V3D_QPU_UNPACK_L);
+ a = vir_FMOV(c, ba);
+ vir_set_unpack(c->defs[a.index], 0,
+ V3D_QPU_UNPACK_H);
+ }
+ }
+
+ color_reads[0] = swap_rb ? b : r;
+ if (num_components >= 2)
+ color_reads[1] = g;
+ if (num_components >= 3)
+ color_reads[2] = swap_rb ? r : b;
+ if (num_components >= 4)
+ color_reads[3] = a;
+ }
+
+ assert(color_reads[component].file != QFILE_NULL);
+ ntq_store_dest(c, &instr->dest, 0, vir_MOV(c, color_reads[component]));
+}
+
+static void
ntq_emit_intrinsic(struct v3d_compile *c, nir_intrinsic_instr *instr)
{
unsigned offset;
@@ -1774,6 +1870,10 @@ ntq_emit_intrinsic(struct v3d_compile *c, nir_intrinsic_instr *instr)
ntq_store_dest(c, &instr->dest, 0, vir_MOV(c, c->vid));
break;
+ case nir_intrinsic_load_tlb_color_v3d:
+ vir_emit_tlb_color_read(c, instr);
+ break;
+
case nir_intrinsic_load_input:
/* Use ldvpmv (uniform offset) or ldvpmd (non-uniform offset)
* and enable PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR.