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.
This commit is contained in:
James Webb
2022-07-02 19:33:16 +01:00
committed by GitHub
parent b5c701f6b6
commit d4ee853c8a
3 changed files with 27 additions and 12 deletions
+1 -5
View File
@@ -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<float>(LUMINANCE_BUFFER_OFFSET_EXPOSURE);
}
exposure *= bindless_buffers[bloom.buffer_input_luminance].Load<float>(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)
+1 -5
View File
@@ -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<float>(LUMINANCE_BUFFER_OFFSET_EXPOSURE);
}
exposure *= bindless_buffers[tonemap_push.buffer_input_luminance].Load<float>(LUMINANCE_BUFFER_OFFSET_EXPOSURE);
hdr.rgb *= exposure;
[branch]
+25 -2
View File
@@ -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);