diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc
index 61a7586c28b..5651510a683 100644
--- a/src/freedreno/vulkan/tu_device.cc
+++ b/src/freedreno/vulkan/tu_device.cc
@@ -801,6 +801,7 @@ static const driOptionDescription tu_dri_options[] = {
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_DISABLE_CONSERVATIVE_LRZ(false)
DRI_CONF_TU_DONT_RESERVE_DESCRIPTOR_SET(false)
+ DRI_CONF_TU_ALLOW_OOB_INDIRECT_UBO_LOADS(false)
DRI_CONF_SECTION_END
};
@@ -819,6 +820,8 @@ tu_init_dri_options(struct tu_instance *instance)
!driQueryOptionb(&instance->dri_options, "disable_conservative_lrz");
instance->reserve_descriptor_set =
!driQueryOptionb(&instance->dri_options, "tu_dont_reserve_descriptor_set");
+ instance->allow_oob_indirect_ubo_loads =
+ driQueryOptionb(&instance->dri_options, "tu_allow_oob_indirect_ubo_loads");
}
VKAPI_ATTR VkResult VKAPI_CALL
diff --git a/src/freedreno/vulkan/tu_device.h b/src/freedreno/vulkan/tu_device.h
index 0bbbbf60883..22d8d6fdd19 100644
--- a/src/freedreno/vulkan/tu_device.h
+++ b/src/freedreno/vulkan/tu_device.h
@@ -166,6 +166,14 @@ struct tu_instance
* core, this is enabled by default.
*/
bool reserve_descriptor_set;
+
+ /* Allow out of bounds UBO access by disabling lowering of UBO loads for
+ * indirect access, which rely on the UBO bounds specified in the shader,
+ * rather than the bound UBO size which isn't known until draw time.
+ *
+ * See: https://github.com/doitsujin/dxvk/issues/3861
+ */
+ bool allow_oob_indirect_ubo_loads;
};
VK_DEFINE_HANDLE_CASTS(tu_instance, vk.base, VkInstance,
VK_OBJECT_TYPE_INSTANCE)
diff --git a/src/freedreno/vulkan/tu_shader.cc b/src/freedreno/vulkan/tu_shader.cc
index 5b511a1734c..7abf5c2a343 100644
--- a/src/freedreno/vulkan/tu_shader.cc
+++ b/src/freedreno/vulkan/tu_shader.cc
@@ -312,6 +312,14 @@ lower_ssbo_ubo_intrinsic(struct tu_device *dev,
nir_scalar scalar_idx = nir_scalar_resolved(intrin->src[buffer_src].ssa, 0);
nir_def *descriptor_idx = nir_channel(b, intrin->src[buffer_src].ssa, 1);
+ if (intrin->intrinsic == nir_intrinsic_load_ubo &&
+ dev->instance->allow_oob_indirect_ubo_loads) {
+ nir_scalar offset = nir_scalar_resolved(intrin->src[1].ssa, 0);
+ if (!nir_scalar_is_const(offset)) {
+ nir_intrinsic_set_range(intrin, ~0);
+ }
+ }
+
/* For isam, we need to use the appropriate descriptor if 16-bit storage is
* enabled. Descriptor 0 is the 16-bit one, descriptor 1 is the 32-bit one.
*/
diff --git a/src/util/00-mesa-defaults.conf b/src/util/00-mesa-defaults.conf
index e5a03cc7b47..6202f78ed3b 100644
--- a/src/util/00-mesa-defaults.conf
+++ b/src/util/00-mesa-defaults.conf
@@ -1327,4 +1327,16 @@ TODO: document the other workarounds.
+
+
+
+
+
+
+
+
diff --git a/src/util/driconf.h b/src/util/driconf.h
index 2156a0a3049..ded31db7de9 100644
--- a/src/util/driconf.h
+++ b/src/util/driconf.h
@@ -594,6 +594,10 @@
DRI_CONF_OPT_B(tu_dont_reserve_descriptor_set, def, \
"Don't internally reserve one of the HW descriptor sets for descriptor set dynamic offset support, this frees up an extra descriptor set at the cost of that feature")
+#define DRI_CONF_TU_ALLOW_OOB_INDIRECT_UBO_LOADS(def) \
+ DRI_CONF_OPT_B(tu_allow_oob_indirect_ubo_loads, def, \
+ "Some D3D11 games rely on out-of-bounds indirect UBO loads to return real values from underlying bound descriptor, this prevents us from lowering indirectly accessed UBOs to consts")
+
/**
* \brief venus specific configuration options
*/