Fix GPU synchronization on D3D12

This commit is contained in:
Wojtek Figat
2021-06-07 14:53:53 +02:00
parent 4b42e17372
commit f7957be3e7
8 changed files with 27 additions and 108 deletions

View File

@@ -3,7 +3,6 @@
#pragma once #pragma once
#include "Engine/Core/Types/BaseTypes.h" #include "Engine/Core/Types/BaseTypes.h"
#include "Engine/Platform/Platform.h"
#include "Engine/Platform/CriticalSection.h" #include "Engine/Platform/CriticalSection.h"
#include "CommandAllocatorPoolDX12.h" #include "CommandAllocatorPoolDX12.h"
#include "../IncludeDirectXHeaders.h" #include "../IncludeDirectXHeaders.h"
@@ -35,28 +34,16 @@ public:
public: public:
/// <summary>
/// Gets the current fence value.
/// </summary>
/// <returns>The current fence value.</returns>
FORCE_INLINE uint64 GetCurrentValue() const FORCE_INLINE uint64 GetCurrentValue() const
{ {
return _currentValue; return _currentValue;
} }
/// <summary>
/// Gets the last signaled fence value.
/// </summary>
/// <returns>The last signaled fence value.</returns>
FORCE_INLINE uint64 GetLastSignaledValue() const FORCE_INLINE uint64 GetLastSignaledValue() const
{ {
return _lastSignaledValue; return _lastSignaledValue;
} }
/// <summary>
/// Gets the last completed fence value.
/// </summary>
/// <returns>The last completed fence value.</returns>
FORCE_INLINE uint64 GetLastCompletedValue() const FORCE_INLINE uint64 GetLastCompletedValue() const
{ {
return _lastCompletedValue; return _lastCompletedValue;
@@ -146,42 +133,21 @@ private:
public: public:
/// <summary>
/// Init
/// </summary>
/// <param name="device">Graphics Device handle</param>
/// <param name="type">Command queue type</param>
CommandQueueDX12(GPUDeviceDX12* device, D3D12_COMMAND_LIST_TYPE type); CommandQueueDX12(GPUDeviceDX12* device, D3D12_COMMAND_LIST_TYPE type);
/// <summary>
/// Destructor
/// </summary>
~CommandQueueDX12(); ~CommandQueueDX12();
public: public:
/// <summary>
/// Checks if command queue is ready for work
/// </summary>
/// <returns>True if is ready for work</returns>
FORCE_INLINE bool IsReady() const FORCE_INLINE bool IsReady() const
{ {
return _commandQueue != nullptr; return _commandQueue != nullptr;
} }
/// <summary>
/// Gets DirectX 12 command queue object
/// </summary>
/// <returns>DirectX 12 command queue</returns>
FORCE_INLINE ID3D12CommandQueue* GetCommandQueue() const FORCE_INLINE ID3D12CommandQueue* GetCommandQueue() const
{ {
return _commandQueue; return _commandQueue;
} }
/// <summary>
/// Gets the command lists allocator pool.
/// </summary>
/// <returns>The allocator.</returns>
FORCE_INLINE CommandAllocatorPoolDX12& GetAllocatorPool() FORCE_INLINE CommandAllocatorPoolDX12& GetAllocatorPool()
{ {
return _allocatorPool; return _allocatorPool;

View File

@@ -128,6 +128,11 @@ void DescriptorHeapWithSlotsDX12::ReleaseSlot(uint32 index)
value &= ~mask; value &= ~mask;
} }
GPUResource::ResourceType DescriptorHeapWithSlotsDX12::GetResourceType() const
{
return ResourceType::Descriptor;
}
DescriptorHeapPoolDX12::DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCountPerHeap, bool shaderVisible) DescriptorHeapPoolDX12::DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCountPerHeap, bool shaderVisible)
: _device(device) : _device(device)
, _type(type) , _type(type)
@@ -184,14 +189,12 @@ DescriptorHeapRingBufferDX12::DescriptorHeapRingBufferDX12(GPUDeviceDX12* device
bool DescriptorHeapRingBufferDX12::Init() bool DescriptorHeapRingBufferDX12::Init()
{ {
// Create description // Create heap
D3D12_DESCRIPTOR_HEAP_DESC desc; D3D12_DESCRIPTOR_HEAP_DESC desc;
desc.Type = _type; desc.Type = _type;
desc.NumDescriptors = _descriptorsCount; desc.NumDescriptors = _descriptorsCount;
desc.Flags = _shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE; desc.Flags = _shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
desc.NodeMask = 0; desc.NodeMask = 0;
// Create heap
const HRESULT result = _device->GetDevice()->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&_heap)); const HRESULT result = _device->GetDevice()->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&_heap));
LOG_DIRECTX_RESULT_WITH_RETURN(result); LOG_DIRECTX_RESULT_WITH_RETURN(result);
@@ -203,7 +206,6 @@ bool DescriptorHeapRingBufferDX12::Init()
else else
_beginGPU.ptr = 0; _beginGPU.ptr = 0;
_incrementSize = _device->GetDevice()->GetDescriptorHandleIncrementSize(desc.Type); _incrementSize = _device->GetDevice()->GetDescriptorHandleIncrementSize(desc.Type);
_memoryUsage = 1; _memoryUsage = 1;
return false; return false;

View File

@@ -63,36 +63,6 @@ public:
public: public:
// Get heap
FORCE_INLINE operator ID3D12DescriptorHeap*() const
{
return _heap;
}
public:
// Create heap data
// @param type Heap data type
// @param descriptorsCount Amount of descriptors to use
// @param shaderVisible True if allow shaders to access heap data
bool Create(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCount, bool shaderVisible = false);
public:
// Tries to find free descriptor slot
// @param index Result index to use
// @returns True if can assign descriptor to the heap
bool TryToGetUnusedSlot(uint32& index);
// Release descriptor slot
// @param index Descriptor index in the heap
void ReleaseSlot(uint32 index);
public:
// Get handle to the CPU view at given index
// @param index Descriptor index
// @returns CPU address
FORCE_INLINE D3D12_CPU_DESCRIPTOR_HANDLE CPU(uint32 index) FORCE_INLINE D3D12_CPU_DESCRIPTOR_HANDLE CPU(uint32 index)
{ {
D3D12_CPU_DESCRIPTOR_HANDLE handle; D3D12_CPU_DESCRIPTOR_HANDLE handle;
@@ -100,9 +70,6 @@ public:
return handle; return handle;
} }
// Get handle to the GPU view at given index
// @param index Descriptor index
// @returns GPU address
FORCE_INLINE D3D12_GPU_DESCRIPTOR_HANDLE GPU(uint32 index) FORCE_INLINE D3D12_GPU_DESCRIPTOR_HANDLE GPU(uint32 index)
{ {
D3D12_GPU_DESCRIPTOR_HANDLE handle; D3D12_GPU_DESCRIPTOR_HANDLE handle;
@@ -110,13 +77,16 @@ public:
return handle; return handle;
} }
public:
bool Create(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCount, bool shaderVisible = false);
bool TryToGetUnusedSlot(uint32& index);
void ReleaseSlot(uint32 index);
public: public:
// [GPUResourceDX12] // [GPUResourceDX12]
ResourceType GetResourceType() const final override ResourceType GetResourceType() const final override;
{
return ResourceType::Descriptor;
}
protected: protected:
@@ -188,24 +158,12 @@ public:
public: public:
/// <summary>
/// Gets DirectX 12 heap object
/// </summary>
/// <returns>Heap object</returns>
FORCE_INLINE ID3D12DescriptorHeap* GetHeap() const FORCE_INLINE ID3D12DescriptorHeap* GetHeap() const
{ {
return _heap; return _heap;
} }
public:
// Setup heap
// @returns True if cannot setup heap, otherwise false
bool Init(); bool Init();
// Allocate memory for descriptors table
// @param numDesc Amount of descriptors in table
// @returns Allocated data (GPU param is valid only for shader visible heaps)
Allocation AllocateTable(uint32 numDesc); Allocation AllocateTable(uint32 numDesc);
public: public:

View File

@@ -79,6 +79,8 @@ GPUContextDX12::GPUContextDX12(GPUDeviceDX12* device, D3D12_COMMAND_LIST_TYPE ty
, _rtDepth(nullptr) , _rtDepth(nullptr)
, _ibHandle(nullptr) , _ibHandle(nullptr)
{ {
FrameFenceValues[0] = 0;
FrameFenceValues[1] = 0;
_currentAllocator = _device->GetCommandQueue()->RequestAllocator(); _currentAllocator = _device->GetCommandQueue()->RequestAllocator();
VALIDATE_DIRECTX_RESULT(device->GetDevice()->CreateCommandList(0, type, _currentAllocator, nullptr, IID_PPV_ARGS(&_commandList))); VALIDATE_DIRECTX_RESULT(device->GetDevice()->CreateCommandList(0, type, _currentAllocator, nullptr, IID_PPV_ARGS(&_commandList)));
#if GPU_ENABLE_RESOURCE_NAMING #if GPU_ENABLE_RESOURCE_NAMING
@@ -592,7 +594,8 @@ void GPUContextDX12::FrameEnd()
GPUContext::FrameEnd(); GPUContext::FrameEnd();
// Execute command (but don't wait for them) // Execute command (but don't wait for them)
Execute(false); FrameFenceValues[1] = FrameFenceValues[0];
FrameFenceValues[0] = Execute(false);
} }
#if GPU_ALLOW_PROFILE_EVENTS #if GPU_ALLOW_PROFILE_EVENTS
@@ -1080,7 +1083,7 @@ void GPUContextDX12::Flush()
return; return;
// Flush GPU commands // Flush GPU commands
Execute(); Execute(true);
Reset(); Reset();
} }

View File

@@ -68,29 +68,18 @@ private:
public: public:
/// <summary>
/// Init
/// </summary>
/// <param name="device">Graphics device</param>
/// <param name="type">Context type</param>
GPUContextDX12(GPUDeviceDX12* device, D3D12_COMMAND_LIST_TYPE type); GPUContextDX12(GPUDeviceDX12* device, D3D12_COMMAND_LIST_TYPE type);
/// <summary>
/// Destructor
/// </summary>
~GPUContextDX12(); ~GPUContextDX12();
public: public:
/// <summary>
/// Gets command list
/// </summary>
/// <returns>Command list to use</returns>
FORCE_INLINE ID3D12GraphicsCommandList* GetCommandList() const FORCE_INLINE ID3D12GraphicsCommandList* GetCommandList() const
{ {
return _commandList; return _commandList;
} }
uint64 FrameFenceValues[2];
public: public:
/// <summary> /// <summary>

View File

@@ -169,7 +169,7 @@ GPUDeviceDX12::GPUDeviceDX12(IDXGIFactory4* dxgiFactory, GPUAdapterDX* adapter)
, Heap_CBV_SRV_UAV(this, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 4 * 1024, false) , Heap_CBV_SRV_UAV(this, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 4 * 1024, false)
, Heap_RTV(this, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1 * 1024, false) , Heap_RTV(this, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1 * 1024, false)
, Heap_DSV(this, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 64, false) , Heap_DSV(this, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 64, false)
, RingHeap_CBV_SRV_UAV(this, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 64 * 1024, true) , RingHeap_CBV_SRV_UAV(this, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 512 * 1024, true)
{ {
} }
@@ -620,10 +620,11 @@ bool GPUDeviceDX12::Init()
void GPUDeviceDX12::DrawBegin() void GPUDeviceDX12::DrawBegin()
{ {
/*{ {
PROFILE_CPU_NAMED("Wait For GPU"); PROFILE_CPU_NAMED("Wait For GPU");
_commandQueue->WaitForGPU(); //_commandQueue->WaitForGPU();
}*/ _commandQueue->WaitForFence(_mainContext->FrameFenceValues[1]);
}
// Base // Base
GPUDeviceDX::DrawBegin(); GPUDeviceDX::DrawBegin();

View File

@@ -64,7 +64,7 @@ ID3D12PipelineState* GPUPipelineStateDX12::GetState(GPUTextureViewDX12* depth, i
LOG_DIRECTX_RESULT(result); LOG_DIRECTX_RESULT(result);
if (FAILED(result)) if (FAILED(result))
return nullptr; return nullptr;
#if GPU_ENABLE_RESOURCE_NAMING #if GPU_ENABLE_RESOURCE_NAMING && BUILD_DEBUG
char name[200]; char name[200];
int32 nameLen = 0; int32 nameLen = 0;
if (DebugDesc.VS) if (DebugDesc.VS)

View File

@@ -13,7 +13,7 @@
#define DX12_UPLOAD_PAGE_GEN_TIMEOUT DX12_BACK_BUFFER_COUNT #define DX12_UPLOAD_PAGE_GEN_TIMEOUT DX12_BACK_BUFFER_COUNT
// Upload buffer pages that are not used for a few frames are disposed // Upload buffer pages that are not used for a few frames are disposed
#define DX12_UPLOAD_PAGE_NOT_USED_FRAME_TIMEOUT 8 #define DX12_UPLOAD_PAGE_NOT_USED_FRAME_TIMEOUT 60
class GPUTextureDX12; class GPUTextureDX12;