summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConnor Abbott <cwabbott0@gmail.com>2020-07-13 19:27:53 +0200
committerMarge Bot <eric+marge@anholt.net>2020-08-20 19:21:18 +0000
commitc884afc6f71d5c0d30d1edc49026ed9d3c32542e (patch)
tree56e554255a44ddc3405f36836f08019ddfdc9889
parent7b53ac1c1f46046d31577fbc866931ec54a5c4eb (diff)
tu: Add multiview lowering pass
For now this only handles an a630 quirk where PC_MULTIVIEW_MASK doesn't exist. However in the future it will also handle multi-position output. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5720>
-rw-r--r--src/freedreno/vulkan/meson.build1
-rw-r--r--src/freedreno/vulkan/tu_device.c3
-rw-r--r--src/freedreno/vulkan/tu_nir_lower_multiview.c76
-rw-r--r--src/freedreno/vulkan/tu_private.h4
4 files changed, 84 insertions, 0 deletions
diff --git a/src/freedreno/vulkan/meson.build b/src/freedreno/vulkan/meson.build
index 8696f246da0..9c258170615 100644
--- a/src/freedreno/vulkan/meson.build
+++ b/src/freedreno/vulkan/meson.build
@@ -51,6 +51,7 @@ libtu_files = files(
'tu_fence.c',
'tu_formats.c',
'tu_image.c',
+ 'tu_nir_lower_multiview.c',
'tu_pass.c',
'tu_pipeline.c',
'tu_pipeline_cache.c',
diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c
index 0ab94e2bf6e..9a6085f96d3 100644
--- a/src/freedreno/vulkan/tu_device.c
+++ b/src/freedreno/vulkan/tu_device.c
@@ -78,6 +78,7 @@ tu_physical_device_init(struct tu_physical_device *device,
device->tile_align_w = 32;
device->magic.PC_UNKNOWN_9805 = 0x0;
device->magic.SP_UNKNOWN_A0F8 = 0x0;
+ device->supports_multiview_mask = false; /* TODO */
break;
case 630:
case 640:
@@ -86,6 +87,7 @@ tu_physical_device_init(struct tu_physical_device *device,
device->tile_align_w = 32;
device->magic.PC_UNKNOWN_9805 = 0x1;
device->magic.SP_UNKNOWN_A0F8 = 0x1;
+ device->supports_multiview_mask = device->gpu_id != 630;
break;
case 650:
device->ccu_offset_gmem = 0x114000;
@@ -93,6 +95,7 @@ tu_physical_device_init(struct tu_physical_device *device,
device->tile_align_w = 96;
device->magic.PC_UNKNOWN_9805 = 0x2;
device->magic.SP_UNKNOWN_A0F8 = 0x2;
+ device->supports_multiview_mask = true;
break;
default:
result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
diff --git a/src/freedreno/vulkan/tu_nir_lower_multiview.c b/src/freedreno/vulkan/tu_nir_lower_multiview.c
new file mode 100644
index 00000000000..4402798d4d8
--- /dev/null
+++ b/src/freedreno/vulkan/tu_nir_lower_multiview.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2020 Valve Corporation
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "tu_private.h"
+#include "nir_builder.h"
+
+/* Some a6xx variants cannot support a non-contiguous multiview mask. Instead,
+ * inside the shader something like this needs to be inserted:
+ *
+ * gl_Position = ((1ull << gl_ViewIndex) & view_mask) ? gl_Position : vec4(0.);
+ *
+ * Scan backwards until we find the gl_Position write (there should only be
+ * one).
+ */
+static bool
+lower_multiview_mask(nir_function_impl *impl, uint32_t mask)
+{
+ nir_builder b;
+ nir_builder_init(&b, impl);
+
+ nir_foreach_block_reverse(block, impl) {
+ nir_foreach_instr_reverse(instr, block) {
+ if (instr->type != nir_instr_type_intrinsic)
+ continue;
+
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+ if (intrin->intrinsic != nir_intrinsic_store_deref)
+ continue;
+
+ nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
+ if (deref->mode != nir_var_shader_out)
+ continue;
+
+ nir_variable *var = nir_deref_instr_get_variable(deref);
+ if (var->data.location != VARYING_SLOT_POS)
+ continue;
+
+ assert(intrin->src[1].is_ssa);
+ nir_ssa_def *orig_src = intrin->src[1].ssa;
+ b.cursor = nir_before_instr(instr);
+
+ /* ((1ull << gl_ViewIndex) & mask) != 0 */
+ nir_ssa_def *cmp =
+ nir_i2b(&b, nir_iand(&b, nir_imm_int(&b, mask),
+ nir_ishl(&b, nir_imm_int(&b, 1),
+ nir_load_view_index(&b))));
+
+ nir_ssa_def *src = nir_bcsel(&b, cmp, orig_src, nir_imm_float(&b, 0.));
+ nir_instr_rewrite_src(instr, &intrin->src[1], nir_src_for_ssa(src));
+
+ nir_metadata_preserve(impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+ return true;
+ }
+ }
+
+ nir_metadata_preserve(impl, nir_metadata_all);
+ return false;
+}
+
+bool
+tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev)
+{
+ nir_function_impl *entrypoint = nir_shader_get_entrypoint(nir);
+
+ if (!dev->physical_device->supports_multiview_mask &&
+ !util_is_power_of_two_or_zero(mask + 1)) {
+ return lower_multiview_mask(entrypoint, mask);
+ }
+
+ nir_metadata_preserve(entrypoint, nir_metadata_all);
+ return false;
+}
+
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index 584931dc534..b466227e941 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -200,6 +200,7 @@ struct tu_physical_device
/* gmem store/load granularity */
#define GMEM_ALIGN_W 16
#define GMEM_ALIGN_H 4
+ bool supports_multiview_mask;
struct {
uint32_t PC_UNKNOWN_9805;
@@ -1078,6 +1079,9 @@ struct tu_shader
uint8_t active_desc_sets;
};
+bool
+tu_nir_lower_multiview(nir_shader *nir, uint32_t mask, struct tu_device *dev);
+
struct tu_shader *
tu_shader_create(struct tu_device *dev,
gl_shader_stage stage,