From d4ee853c8a65e5d589fcaa18954d2ddd3f542641 Mon Sep 17 00:00:00 2001 From: James Webb Date: Sat, 2 Jul 2022 19:33:16 +0100 Subject: [PATCH] Workaround for Nvidia driver bug #450 (#481) * Workaround for Nvidia driver bug where just testing if a bindless buffer descriptor is valid seems to require that it is valid (at least in the two compute shaders where the issue was noticed). Instead of testing if the luminance buffer is valid in the bloom/tonemap shaders, always provide a luminance buffer by using a dummy buffer when eye adaption is disabled. This bug was introduced with the 516.40 drivers. * Add assert that the exposure offset is at 0 else the dummy buffer is no longer valid. --- WickedEngine/shaders/bloomseparateCS.hlsl | 6 +---- WickedEngine/shaders/tonemapCS.hlsl | 6 +---- WickedEngine/wiRenderer.cpp | 27 +++++++++++++++++++++-- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/WickedEngine/shaders/bloomseparateCS.hlsl b/WickedEngine/shaders/bloomseparateCS.hlsl index 42c8d6c9c..39dbf8e63 100644 --- a/WickedEngine/shaders/bloomseparateCS.hlsl +++ b/WickedEngine/shaders/bloomseparateCS.hlsl @@ -20,11 +20,7 @@ void main(uint3 DTid : SV_DispatchThreadID) color /= 4.0f; float exposure = bloom.exposure; - [branch] - if (bloom.buffer_input_luminance >= 0) - { - exposure *= bindless_buffers[bloom.buffer_input_luminance].Load(LUMINANCE_BUFFER_OFFSET_EXPOSURE); - } + exposure *= bindless_buffers[bloom.buffer_input_luminance].Load(LUMINANCE_BUFFER_OFFSET_EXPOSURE); color *= exposure; color = min(color, 10); // clamp upper limit: avoid incredibly large values to overly dominate bloom (high speculars were causing problems) diff --git a/WickedEngine/shaders/tonemapCS.hlsl b/WickedEngine/shaders/tonemapCS.hlsl index 68b08b733..3dab04708 100644 --- a/WickedEngine/shaders/tonemapCS.hlsl +++ b/WickedEngine/shaders/tonemapCS.hlsl @@ -62,11 +62,7 @@ void main(uint3 DTid : SV_DispatchThreadID) hdr = bindless_textures[tonemap_push.texture_input].SampleLevel(sampler_linear_clamp, uv, 0); } - [branch] - if (tonemap_push.buffer_input_luminance >= 0) - { - exposure *= bindless_buffers[tonemap_push.buffer_input_luminance].Load(LUMINANCE_BUFFER_OFFSET_EXPOSURE); - } + exposure *= bindless_buffers[tonemap_push.buffer_input_luminance].Load(LUMINANCE_BUFFER_OFFSET_EXPOSURE); hdr.rgb *= exposure; [branch] diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 2abd1bf8b..d14447c88 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -144,6 +144,14 @@ Texture texture_detailNoise; Texture texture_curlNoise; Texture texture_weatherMap; +// A dummy luminance buffer with exposure set to 1. +// This avoids having to branch in shaders that consume the exposure value +// when eye adaption is disabled. +// It also works around an apparent bug in the drivers for certain GTX 10xx cards +// where just testing if a bindless buffer descriptor is valid requires that it is valid. +// See: https://github.com/turanszkij/WickedEngine/issues/450 +GPUBuffer luminance_dummy; + // Direct reference to a renderable instance: struct RenderBatch { @@ -1795,6 +1803,21 @@ void LoadBuffers() device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT]); device->SetName(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], "textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT]"); } + { + // the dummy buffer is read-only so only the first 'exposure' value is needed, + // not the luminance or histogram values in the full version of the buffer used + // when eye adaption is enabled. + float values[1] = { 1 }; + + GPUBufferDesc desc; + desc.size = sizeof(values); + desc.bind_flags = BindFlag::SHADER_RESOURCE; + desc.misc_flags = ResourceMiscFlag::BUFFER_RAW; + device->CreateBuffer(&desc, values, &luminance_dummy); + device->SetName(&luminance_dummy, "luminance_dummy"); + + static_assert(LUMINANCE_BUFFER_OFFSET_EXPOSURE == 0); + } } void SetUpStates() { @@ -7610,7 +7633,7 @@ void ComputeBloom( bloom.exposure = exposure; bloom.texture_input = device->GetDescriptorIndex(&input, SubresourceType::SRV); bloom.texture_output = device->GetDescriptorIndex(&res.texture_bloom, SubresourceType::UAV); - bloom.buffer_input_luminance = device->GetDescriptorIndex(buffer_luminance, SubresourceType::SRV); + bloom.buffer_input_luminance = device->GetDescriptorIndex((buffer_luminance == nullptr) ? &luminance_dummy : buffer_luminance, SubresourceType::SRV); device->PushConstants(&bloom, sizeof(bloom), cmd); { @@ -12319,7 +12342,7 @@ void Postprocess_Tonemap( tonemap_push.exposure = exposure; tonemap_push.dither = dither ? 1.0f : 0.0f; tonemap_push.texture_input = device->GetDescriptorIndex(&input, SubresourceType::SRV); - tonemap_push.buffer_input_luminance = device->GetDescriptorIndex(buffer_luminance, SubresourceType::SRV); + tonemap_push.buffer_input_luminance = device->GetDescriptorIndex((buffer_luminance == nullptr) ? &luminance_dummy : buffer_luminance, SubresourceType::SRV); tonemap_push.texture_input_distortion = device->GetDescriptorIndex(texture_distortion, SubresourceType::SRV); tonemap_push.texture_colorgrade_lookuptable = device->GetDescriptorIndex(texture_colorgradinglut, SubresourceType::SRV); tonemap_push.texture_bloom = device->GetDescriptorIndex(texture_bloom, SubresourceType::SRV);