Skip to content

Commit

Permalink
Fix GPU crash when switching depth buffers in D3D12 because not all d…
Browse files Browse the repository at this point in the history
…escriptors were updated
  • Loading branch information
crosire committed Jan 9, 2021
1 parent d39cb46 commit da6e5bf
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 36 deletions.
29 changes: 13 additions & 16 deletions source/d3d12/runtime_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace reshade::d3d12
D3D12_CPU_DESCRIPTOR_HANDLE sampler_cpu_base;
D3D12_GPU_DESCRIPTOR_HANDLE sampler_gpu_base;
#if RESHADE_DEPTH
D3D12_CPU_DESCRIPTOR_HANDLE depth_texture_binding = {};
std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> depth_texture_bindings;
#endif
};

Expand Down Expand Up @@ -400,7 +400,7 @@ void reshade::d3d12::runtime_d3d12::on_present()
return;

#if RESHADE_DEPTH
update_depth_texture_bindings(_state_tracking.update_depth_texture(_commandqueue.get(), _cmd_list.get(), _width, _height, _depth_texture_override));
update_depth_texture_bindings(_state_tracking.update_depth_texture(_cmd_list.get(), _width, _height, _depth_texture_override));

// Potentially have to restart command list here because depth texture binding update may have done a wait for idle
if (!begin_command_list())
Expand Down Expand Up @@ -1020,8 +1020,8 @@ bool reshade::d3d12::runtime_d3d12::init_effect(size_t index)
if (texture.semantic == "DEPTH")
{
resource = _depth_texture; // Note: This can be a "nullptr"
// Keep track of the depth buffer texture descriptor to simplify updating it
effect_data.depth_texture_binding = srv_handle;
// Keep track of the depth buffer texture descriptors of each pass to simplify updating it
effect_data.depth_texture_bindings.push_back(srv_handle);
}
#endif

Expand Down Expand Up @@ -1101,7 +1101,7 @@ void reshade::d3d12::runtime_d3d12::unload_effect(size_t index)
effect_data.srv_uav_heap.reset();
effect_data.sampler_heap.reset();
#if RESHADE_DEPTH
effect_data.depth_texture_binding = { 0 };
effect_data.depth_texture_bindings.clear();
#endif
}
}
Expand Down Expand Up @@ -1905,6 +1905,10 @@ void reshade::d3d12::runtime_d3d12::update_depth_texture_bindings(com_ptr<ID3D12
if (depth_texture == _depth_texture)
return;

// Descriptors may be currently in use, so make sure all previous frames have finished before updating them
wait_for_command_queue();

// This potentially destroys the previous resource, so it must not be in use on the GPU at this point anymore!
_depth_texture = std::move(depth_texture);

D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {};
Expand Down Expand Up @@ -1934,16 +1938,9 @@ void reshade::d3d12::runtime_d3d12::update_depth_texture_bindings(com_ptr<ID3D12
_has_depth_texture = false;
}

// Descriptors may be currently in use, so make sure all previous frames have finished before updating them
wait_for_command_queue();

for (effect_data &effect_data : _effect_data)
{
if (effect_data.depth_texture_binding.ptr == 0)
continue; // Skip effects that do not have a depth buffer binding

// Either create a shader resource view or a null descriptor
_device->CreateShaderResourceView(_depth_texture.get(), &srv_desc, effect_data.depth_texture_binding);
}
// Either create a shader resource view or set a null descriptor
for (const effect_data &effect_data : _effect_data)
for (D3D12_CPU_DESCRIPTOR_HANDLE binding : effect_data.depth_texture_bindings)
_device->CreateShaderResourceView(_depth_texture.get(), &srv_desc, binding);
}
#endif
22 changes: 4 additions & 18 deletions source/d3d12/state_tracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ com_ptr<ID3D12Resource> reshade::d3d12::state_tracking_context::resource_from_ha
return nullptr;
}

bool reshade::d3d12::state_tracking_context::update_depthstencil_clear_texture(ID3D12CommandQueue *queue, D3D12_RESOURCE_DESC desc)
bool reshade::d3d12::state_tracking_context::update_depthstencil_clear_texture(D3D12_RESOURCE_DESC desc)
{
assert(_device != nullptr);

Expand All @@ -272,21 +272,7 @@ bool reshade::d3d12::state_tracking_context::update_depthstencil_clear_texture(I
if (desc.Width == existing_desc.Width && desc.Height == existing_desc.Height && desc.Format == existing_desc.Format)
return true; // Texture already matches dimensions, so can re-use

// Texture may still be in use on device, so wait for all operations to finish before destroying it
{ com_ptr<ID3D12Fence> fence;
if (FAILED(_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence))))
return false;
const HANDLE fence_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (fence_event == nullptr)
return false;

assert(queue != nullptr);
queue->Signal(fence.get(), 1);
fence->SetEventOnCompletion(1, fence_event);
WaitForSingleObject(fence_event, INFINITE);
CloseHandle(fence_event);
}

// Runtime using this texture should have added its own reference, so can safely release this one here
_depthstencil_clear_texture.reset();
}

Expand All @@ -305,7 +291,7 @@ bool reshade::d3d12::state_tracking_context::update_depthstencil_clear_texture(I
return true;
}

com_ptr<ID3D12Resource> reshade::d3d12::state_tracking_context::update_depth_texture(ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *list, UINT width, UINT height, ID3D12Resource *override)
com_ptr<ID3D12Resource> reshade::d3d12::state_tracking_context::update_depth_texture(ID3D12GraphicsCommandList *list, UINT width, UINT height, ID3D12Resource *override)
{
depthstencil_info best_snapshot;
com_ptr<ID3D12Resource> best_match = override;
Expand Down Expand Up @@ -354,7 +340,7 @@ com_ptr<ID3D12Resource> reshade::d3d12::state_tracking_context::update_depth_tex
const bool has_changed = depthstencil_clear_index.first != best_match;
depthstencil_clear_index.first = best_match.get();

if (best_match == nullptr || !update_depthstencil_clear_texture(queue, best_match->GetDesc()))
if (best_match == nullptr || !update_depthstencil_clear_texture(best_match->GetDesc()))
return nullptr;

if (preserve_depth_buffers)
Expand Down
4 changes: 2 additions & 2 deletions source/d3d12/state_tracking.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ namespace reshade::d3d12

const auto &depth_buffer_counters() const { return _counters_per_used_depth_texture; }

com_ptr<ID3D12Resource> update_depth_texture(ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *list,
com_ptr<ID3D12Resource> update_depth_texture(ID3D12GraphicsCommandList *list,
UINT width, UINT height,
ID3D12Resource *override = nullptr);
#endif
Expand All @@ -89,7 +89,7 @@ namespace reshade::d3d12
#if RESHADE_DEPTH
com_ptr<ID3D12Resource> resource_from_handle(D3D12_CPU_DESCRIPTOR_HANDLE handle) const;

bool update_depthstencil_clear_texture(ID3D12CommandQueue *queue, D3D12_RESOURCE_DESC desc);
bool update_depthstencil_clear_texture(D3D12_RESOURCE_DESC desc);

draw_stats _previous_stats;
com_ptr<ID3D12Resource> _depthstencil_clear_texture;
Expand Down

0 comments on commit da6e5bf

Please sign in to comment.