From 1c82981bbecb48023d4955a0467e24c08eb756d1 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 16 Jan 2023 08:35:06 -0800 Subject: [PATCH] freedreno: Add driconf to disable conservative LRZ The problematic sequence of draws is pretty rare. But there are a small handful of games which do not exhibit the problematic sequence and for which invalidating LRZ on draws with blend plus depthwrite enabled hurts performance slightly. This driconf option enables opting in to the previous behavior. Signed-off-by: Rob Clark Part-of: --- src/freedreno/vulkan/tu_device.c | 7 +++++++ src/freedreno/vulkan/tu_device.h | 8 ++++++++ src/freedreno/vulkan/tu_lrz.c | 2 +- src/gallium/auxiliary/target-helpers/drm_helper.h | 13 +++++++++---- src/gallium/drivers/freedreno/a6xx/fd6_emit.c | 11 +---------- src/gallium/drivers/freedreno/driinfo_freedreno.h | 5 +++++ src/gallium/drivers/freedreno/freedreno_screen.c | 3 +++ src/gallium/drivers/freedreno/freedreno_screen.h | 8 ++++++++ src/gallium/drivers/freedreno/meson.build | 1 + src/gallium/drivers/virgl/virgl_driinfo.h.in | 8 ++++++++ src/util/driconf.h | 8 ++++++++ 11 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 src/gallium/drivers/freedreno/driinfo_freedreno.h diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index abe8515dfa8..9627e41b69d 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -436,6 +436,10 @@ static const driOptionDescription tu_dri_options[] = { DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST(false) DRI_CONF_VK_DONT_CARE_AS_LOAD(false) DRI_CONF_SECTION_END + + DRI_CONF_SECTION_MISCELLANEOUS + DRI_CONF_DISABLE_CONSERVATIVE_LRZ(false) + DRI_CONF_SECTION_END }; static void @@ -449,6 +453,9 @@ tu_init_dri_options(struct tu_instance *instance) if (driQueryOptionb(&instance->dri_options, "vk_dont_care_as_load")) instance->debug_flags |= TU_DEBUG_DONT_CARE_AS_LOAD; + + instance->conservative_lrz = + !driQueryOptionb(&instance->dri_options, "disable_conservative_lrz"); } VKAPI_ATTR VkResult VKAPI_CALL diff --git a/src/freedreno/vulkan/tu_device.h b/src/freedreno/vulkan/tu_device.h index f7dab0d29e4..51c7dfe9661 100644 --- a/src/freedreno/vulkan/tu_device.h +++ b/src/freedreno/vulkan/tu_device.h @@ -149,6 +149,14 @@ struct tu_instance struct driOptionCache available_dri_options; enum tu_debug_flags debug_flags; + + /* Conservative LRZ (default true) invalidates LRZ on draws with + * blend and depth-write enabled, because this can lead to incorrect + * rendering. Driconf can be used to disable conservative LRZ for + * games which do not have the problematic sequence of draws *and* + * suffer a performance loss with conservative LRZ. + */ + bool conservative_lrz; }; VK_DEFINE_HANDLE_CASTS(tu_instance, vk.base, VkInstance, VK_OBJECT_TYPE_INSTANCE) diff --git a/src/freedreno/vulkan/tu_lrz.c b/src/freedreno/vulkan/tu_lrz.c index 138b483368e..1553d7ec63f 100644 --- a/src/freedreno/vulkan/tu_lrz.c +++ b/src/freedreno/vulkan/tu_lrz.c @@ -812,7 +812,7 @@ tu6_calculate_lrz_state(struct tu_cmd_buffer *cmd, * enable LRZ write. But this would cause early-z/lrz to discard * fragments from draw A which should be visible due to draw B. */ - if (reads_dest && z_write_enable) { + if (reads_dest && z_write_enable && cmd->device->instance->conservative_lrz) { perf_debug(cmd->device, "Invalidating LRZ due to blend+depthwrite"); disable_lrz = true; } diff --git a/src/gallium/auxiliary/target-helpers/drm_helper.h b/src/gallium/auxiliary/target-helpers/drm_helper.h index 7dff0b66c18..b1524c192e5 100644 --- a/src/gallium/auxiliary/target-helpers/drm_helper.h +++ b/src/gallium/auxiliary/target-helpers/drm_helper.h @@ -267,11 +267,18 @@ pipe_msm_create_screen(int fd, const struct pipe_screen_config *config) screen = fd_drm_screen_create(fd, NULL, config); return screen ? debug_screen_wrap(screen) : NULL; } -DRM_DRIVER_DESCRIPTOR(msm, NULL, 0) + +const driOptionDescription msm_driconf[] = { +#ifdef GALLIUM_FREEDRENO + #include "freedreno/driinfo_freedreno.h" +#endif +}; +DRM_DRIVER_DESCRIPTOR(msm, msm_driconf, ARRAY_SIZE(msm_driconf)) +DRM_DRIVER_DESCRIPTOR_ALIAS(msm, kgsl, msm_driconf, ARRAY_SIZE(msm_driconf)) #else DRM_DRIVER_DESCRIPTOR_STUB(msm) +DRM_DRIVER_DESCRIPTOR_STUB(kgsl) #endif -DRM_DRIVER_DESCRIPTOR_ALIAS(msm, kgsl, NULL, 0) #if defined(GALLIUM_VIRGL) || (defined(GALLIUM_FREEDRENO) && !defined(PIPE_LOADER_DYNAMIC)) #include "virgl/drm/virgl_drm_public.h" @@ -295,9 +302,7 @@ pipe_virtio_gpu_create_screen(int fd, const struct pipe_screen_config *config) } const driOptionDescription virgl_driconf[] = { -#ifdef GALLIUM_VIRGL #include "virgl/virgl_driinfo.h.in" -#endif }; DRM_DRIVER_DESCRIPTOR(virtio_gpu, virgl_driconf, ARRAY_SIZE(virgl_driconf)) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c index 7dc9fcba543..c576b58c8cd 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c @@ -202,17 +202,8 @@ compute_lrz_state(struct fd6_emit *emit) assert_dt * Normally looking at the state in draw C, we'd assume we could * enable LRZ write. But this would cause early-z/lrz to discard * fragments from draw A which should be visible due to draw B. - * - * NOTE: So far invalid rendering due to this case has only been - * found in a single game (The Walking Dead: Season One - - * com.telltalegames.walkingdead100). But other Telltale Games - * use the same Telltale Tool engine, so they might also have the - * same issue. But blend+depthwrite is more common. Hopefully - * it only shows up late in the renderpass where invalidating LRZ - * would not be too costly, but if this is found to cause perf - * regressions, a driconf allowlist/denylist can be added. */ - if (reads_dest && zsa->writes_z) { + if (reads_dest && zsa->writes_z && ctx->screen->conservative_lrz) { if (!zsa->perf_warn_blend && rsc->lrz_valid) { perf_debug_ctx(ctx, "Invalidating LRZ due to blend+depthwrite"); zsa->perf_warn_blend = true; diff --git a/src/gallium/drivers/freedreno/driinfo_freedreno.h b/src/gallium/drivers/freedreno/driinfo_freedreno.h new file mode 100644 index 00000000000..a23b865ebd4 --- /dev/null +++ b/src/gallium/drivers/freedreno/driinfo_freedreno.h @@ -0,0 +1,5 @@ +// freedreno specific driconf options + +DRI_CONF_SECTION_MISCELLANEOUS + DRI_CONF_DISABLE_CONSERVATIVE_LRZ(false) +DRI_CONF_SECTION_END diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 308aa239cd5..9a7ad7e9452 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -1096,6 +1096,9 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro, driParseConfigFiles(config->options, config->options_info, 0, "msm", NULL, fd_dev_name(screen->dev_id), NULL, 0, NULL, 0); + screen->conservative_lrz = + !driQueryOptionb(config->options, "disable_conservative_lrz"); + struct sysinfo si; sysinfo(&si); screen->ram_size = si.totalram; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h index 0aa0e2357c4..0e2d5790989 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.h +++ b/src/gallium/drivers/freedreno/freedreno_screen.h @@ -94,6 +94,14 @@ struct fd_screen { bool has_robustness; bool has_syncobj; + /* Conservative LRZ (default true) invalidates LRZ on draws with + * blend and depth-write enabled, because this can lead to incorrect + * rendering. Driconf can be used to disable conservative LRZ for + * games which do not have the problematic sequence of draws *and* + * suffer a performance loss with conservative LRZ. + */ + bool conservative_lrz; + const struct fd_dev_info *info; uint32_t ccu_offset_gmem; uint32_t ccu_offset_bypass; diff --git a/src/gallium/drivers/freedreno/meson.build b/src/gallium/drivers/freedreno/meson.build index d2c33d6649f..00642b7a2ce 100644 --- a/src/gallium/drivers/freedreno/meson.build +++ b/src/gallium/drivers/freedreno/meson.build @@ -19,6 +19,7 @@ # SOFTWARE. files_libfreedreno = files( + 'driinfo_freedreno.h', 'freedreno_autotune.c', 'freedreno_autotune.h', 'freedreno_batch.c', diff --git a/src/gallium/drivers/virgl/virgl_driinfo.h.in b/src/gallium/drivers/virgl/virgl_driinfo.h.in index f57e5880965..301247b35ec 100644 --- a/src/gallium/drivers/virgl/virgl_driinfo.h.in +++ b/src/gallium/drivers/virgl/virgl_driinfo.h.in @@ -11,4 +11,12 @@ DRI_CONF_SECTION_MISCELLANEOUS DRI_CONF_GLES_EMULATE_BGRA(true) DRI_CONF_GLES_APPLY_BGRA_DEST_SWIZZLE(true) DRI_CONF_GLES_SAMPLES_PASSED_VALUE(1024, 1, 400000000) + + /* + * Native-context drivers also (can) bind to the some virtio_gpu guest + * kernel device. Because drm_helper ties the driconf config to the + * drm device name, we also need to include config options for any + * possible drm-native-context guest driver: + */ + DRI_CONF_DISABLE_CONSERVATIVE_LRZ(false) DRI_CONF_SECTION_END diff --git a/src/util/driconf.h b/src/util/driconf.h index bcc6d8190e4..899a6ae2bb8 100644 --- a/src/util/driconf.h +++ b/src/util/driconf.h @@ -515,6 +515,14 @@ DRI_CONF_OPT_B(format_l8_srgb_enable_readback, def, \ "Force-enable reading back L8_SRGB textures") +/** + * \brief freedreno specific configuration options + */ + +#define DRI_CONF_DISABLE_CONSERVATIVE_LRZ(def) \ + DRI_CONF_OPT_B(disable_conservative_lrz, def, \ + "Disable conservative LRZ") + /** * \brief venus specific configuration options */