// Copyright (c) Wojciech Figat. All rights reserved.
#pragma once
#if GRAPHICS_API_DIRECTX12
#include "../GPUDeviceDX.h"
#include "Engine/Graphics/GPUResource.h"
#include "../IncludeDirectXHeaders.h"
#include "ResourceOwnerDX12.h"
#include "UploadBufferDX12.h"
#include "QueryHeapDX12.h"
#include "DescriptorHeapDX12.h"
#if PLATFORM_WINDOWS
#define DX12_BACK_BUFFER_COUNT 3
#else
#define DX12_BACK_BUFFER_COUNT 2
#endif
class Engine;
class WindowsWindow;
class GPUContextDX12;
class GPUSwapChainDX12;
class CommandQueueDX12;
class CommandSignatureDX12;
///
/// Implementation of Graphics Device for DirectX 12 rendering system
///
class GPUDeviceDX12 : public GPUDeviceDX
{
friend GPUContextDX12;
friend GPUSwapChainDX12;
private:
struct DisposeResourceEntry
{
IGraphicsUnknown* Resource;
uint64 TargetFrame;
};
private:
// Private Stuff
ID3D12Device* _device;
IDXGIFactory4* _factoryDXGI;
CriticalSection _res2DisposeLock;
Array _res2Dispose;
// Pipeline
ID3D12RootSignature* _rootSignature;
CommandQueueDX12* _commandQueue;
GPUContextDX12* _mainContext;
// Heaps
DescriptorHeapWithSlotsDX12::Slot _nullSrv[D3D12_SRV_DIMENSION_TEXTURECUBEARRAY + 1];
DescriptorHeapWithSlotsDX12::Slot _nullUav;
public:
static GPUDevice* Create();
GPUDeviceDX12(IDXGIFactory4* dxgiFactory, GPUAdapterDX* adapter);
~GPUDeviceDX12();
public:
///
/// Data uploading utility via pages.
///
UploadBufferDX12 UploadBuffer;
///
/// The timestamp queries heap.
///
QueryHeapDX12 TimestampQueryHeap;
bool AllowTearing = false;
CommandSignatureDX12* DispatchIndirectCommandSignature = nullptr;
CommandSignatureDX12* DrawIndexedIndirectCommandSignature = nullptr;
CommandSignatureDX12* DrawIndirectCommandSignature = nullptr;
GPUBuffer* DummyVB = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE NullSRV(D3D12_SRV_DIMENSION dimension) const;
D3D12_CPU_DESCRIPTOR_HANDLE NullUAV() const;
public:
///
/// Gets DX12 device.
///
FORCE_INLINE ID3D12Device* GetDevice() const
{
return _device;
}
///
/// Gets DXGI factory.
///
FORCE_INLINE IDXGIFactory4* GetDXGIFactory() const
{
return _factoryDXGI;
}
///
/// Gets DirectX 12 command list object
///
ID3D12GraphicsCommandList* GetCommandList() const;
///
/// Gets command queue.
///
FORCE_INLINE CommandQueueDX12* GetCommandQueue() const
{
return _commandQueue;
}
///
/// Gets DirectX 12 command queue object.
///
ID3D12CommandQueue* GetCommandQueueDX12() const;
///
/// Gets root signature of the graphics pipeline.
///
FORCE_INLINE ID3D12RootSignature* GetRootSignature() const
{
return _rootSignature;
}
///
/// Gets main commands context (for DirectX 12)
///
FORCE_INLINE GPUContextDX12* GetMainContextDX12() const
{
return _mainContext;
}
public:
DescriptorHeapPoolDX12 Heap_CBV_SRV_UAV;
DescriptorHeapPoolDX12 Heap_RTV;
DescriptorHeapPoolDX12 Heap_DSV;
DescriptorHeapPoolDX12 Heap_Sampler;
DescriptorHeapRingBufferDX12 RingHeap_CBV_SRV_UAV;
DescriptorHeapRingBufferDX12 RingHeap_Sampler;
public:
// Add resource to late release service (will be released after 'safeFrameCount' frames)
void AddResourceToLateRelease(IGraphicsUnknown* resource, uint32 safeFrameCount = DX12_RESOURCE_DELETE_SAFE_FRAMES_COUNT);
static FORCE_INLINE uint32 GetMaxMSAAQuality(uint32 sampleCount)
{
if (sampleCount <= 8)
return 0;
return 0xffffffff;
}
#if PLATFORM_XBOX_SCARLETT ||PLATFORM_XBOX_ONE
void OnSuspended();
void OnResumed();
#endif
private:
#if PLATFORM_XBOX_SCARLETT ||PLATFORM_XBOX_ONE
void updateFrameEvents();
#endif
void updateRes2Dispose();
public:
// [GPUDeviceDX]
GPUContext* GetMainContext() override
{
return reinterpret_cast(_mainContext);
}
void* GetNativePtr() const override
{
return _device;
}
bool Init() override;
void DrawBegin() override;
void RenderEnd() override;
void Dispose() final override;
void WaitForGPU() override;
GPUTexture* CreateTexture(const StringView& name) override;
GPUShader* CreateShader(const StringView& name) override;
GPUPipelineState* CreatePipelineState() override;
GPUTimerQuery* CreateTimerQuery() override;
GPUBuffer* CreateBuffer(const StringView& name) override;
GPUSampler* CreateSampler() override;
GPUVertexLayout* CreateVertexLayout(const VertexElements& elements, bool explicitOffsets) override;
GPUSwapChain* CreateSwapChain(Window* window) override;
GPUConstantBuffer* CreateConstantBuffer(uint32 size, const StringView& name) override;
};
///
/// GPU resource implementation for DirectX 12 backend.
///
template
class GPUResourceDX12 : public GPUResourceBase
{
public:
///
/// Initializes a new instance of the class.
///
/// The graphics device.
/// The resource name.
GPUResourceDX12(GPUDeviceDX12* device, const StringView& name)
: GPUResourceBase(device, name)
{
}
};
extern GPUDevice* CreateGPUDeviceDX12();
#endif