// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Collections/Array.h"
#include "Engine/Graphics/Textures/GPUTexture.h"
#include "GPUDeviceDX12.h"
#include "IShaderResourceDX12.h"
#if GRAPHICS_API_DIRECTX12
///
/// The texture view for DirectX 12 backend.
///
class GPUTextureViewDX12 : public GPUTextureView, public IShaderResourceDX12
{
private:
GPUDeviceDX12* _device = nullptr;
ResourceOwnerDX12* _owner = nullptr;
DescriptorHeapWithSlotsDX12::Slot _rtv, _srv, _dsv, _uav;
public:
///
/// Initializes a new instance of the class.
///
GPUTextureViewDX12()
{
}
GPUTextureViewDX12(const GPUTextureViewDX12& other)
: GPUTextureViewDX12()
{
#if !BUILD_RELEASE
CRASH; // Not used
#endif
}
GPUTextureViewDX12& operator=(const GPUTextureViewDX12& other)
{
#if !BUILD_RELEASE
CRASH; // Not used
#endif
return *this;
}
///
/// Finalizes an instance of the class.
///
~GPUTextureViewDX12()
{
Release();
}
public:
///
/// Init
///
/// Parent resource
/// Graphics Device
/// Resource owner
/// Parent texture format
/// Parent texture multi-sample level
/// Used subresource index or -1 to cover whole resource.
void Init(GPUResource* parent, GPUDeviceDX12* device, ResourceOwnerDX12* owner, PixelFormat format, MSAALevel msaa, int32 subresourceIndex = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)
{
GPUTextureView::Init(parent, format, msaa);
SubresourceIndex = subresourceIndex;
_device = device;
_owner = owner;
}
///
/// Releases the view.
///
void Release()
{
_rtv.Release();
_srv.Release();
_dsv.Release();
_uav.Release();
}
public:
///
/// Sets the render target view.
///
/// The RTV desc.
void SetRTV(D3D12_RENDER_TARGET_VIEW_DESC* rtvDesc)
{
if (rtvDesc)
{
_rtv.CreateRTV(_device, _owner->GetResource(), rtvDesc);
}
else
{
_rtv.Release();
}
}
///
/// Sets the shader resource view.
///
/// The SRV desc.
void SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC* srvDesc)
{
if (srvDesc)
{
_srv.CreateSRV(_device, _owner->GetResource(), srvDesc);
}
else
{
_srv.Release();
}
}
///
/// Sets the depth stencil view.
///
/// The DSV desc.
void SetDSV(D3D12_DEPTH_STENCIL_VIEW_DESC* dsvDesc)
{
if (dsvDesc)
{
_dsv.CreateDSV(_device, _owner->GetResource(), dsvDesc);
}
else
{
_dsv.Release();
}
}
///
/// Sets the unordered access view.
///
/// The UAV desc.
/// The counter buffer resource.
void SetUAV(D3D12_UNORDERED_ACCESS_VIEW_DESC* uavDesc, ID3D12Resource* counterResource = nullptr)
{
if (uavDesc)
{
_uav.CreateUAV(_device, _owner->GetResource(), uavDesc, counterResource);
}
else
{
_uav.Release();
}
}
public:
///
/// Gets the CPU handle to the render target view descriptor.
///
/// The CPU handle to the render target view descriptor.
D3D12_CPU_DESCRIPTOR_HANDLE RTV() const
{
return _rtv.CPU();
}
///
/// Gets the CPU handle to the depth stencil view descriptor.
///
/// The CPU handle to the depth stencil view descriptor.
D3D12_CPU_DESCRIPTOR_HANDLE DSV() const
{
return _dsv.CPU();
}
public:
// [GPUResourceView]
void* GetNativePtr() const override
{
return (void*)(IShaderResourceDX12*)this;
}
// [IShaderResourceDX12]
bool IsDepthStencilResource() const override
{
return _dsv.IsValid();
}
D3D12_CPU_DESCRIPTOR_HANDLE SRV() const override
{
return _srv.CPU();
}
D3D12_CPU_DESCRIPTOR_HANDLE UAV() const override
{
return _uav.CPU();
}
ResourceOwnerDX12* GetResourceOwner() const override
{
return _owner;
}
};
///
/// Texture object for DirectX 12 backend.
///
class GPUTextureDX12 : public GPUResourceDX12, public ResourceOwnerDX12, public IShaderResourceDX12
{
private:
GPUTextureViewDX12 _handleArray;
GPUTextureViewDX12 _handleVolume;
GPUTextureViewDX12 _handleReadOnlyDepth;
Array _handlesPerSlice; // [slice]
Array> _handlesPerMip; // [slice][mip]
DescriptorHeapWithSlotsDX12::Slot _srv;
DescriptorHeapWithSlotsDX12::Slot _uav;
DXGI_FORMAT _dxgiFormatDSV;
DXGI_FORMAT _dxgiFormatSRV;
DXGI_FORMAT _dxgiFormatRTV;
DXGI_FORMAT _dxgiFormatUAV;
public:
///
/// Initializes a new instance of the class.
///
/// The device.
/// The name.
GPUTextureDX12(GPUDeviceDX12* device, const StringView& name)
: GPUResourceDX12(device, name)
{
}
private:
void initHandles();
public:
// [GPUTexture]
GPUTextureView* View(int32 arrayOrDepthIndex) const override
{
return (GPUTextureView*)&_handlesPerSlice[arrayOrDepthIndex];
}
GPUTextureView* View(int32 arrayOrDepthIndex, int32 mipMapIndex) const override
{
return (GPUTextureView*)&_handlesPerMip[arrayOrDepthIndex][mipMapIndex];
}
GPUTextureView* ViewArray() const override
{
ASSERT(ArraySize() > 1);
return (GPUTextureView*)&_handleArray;
}
GPUTextureView* ViewVolume() const override
{
ASSERT(IsVolume());
return (GPUTextureView*)&_handleVolume;
}
GPUTextureView* ViewReadOnlyDepth() const override
{
ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView);
return (GPUTextureView*)&_handleReadOnlyDepth;
}
void* GetNativePtr() const override
{
return (void*)nullptr;
}
bool GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override;
// [ResourceOwnerDX12]
GPUResource* AsGPUResource() const override
{
return (GPUResource*)this;
}
// [IShaderResourceDX12]
bool IsDepthStencilResource() const override
{
return (_desc.Flags & GPUTextureFlags::DepthStencil) != 0;
}
D3D12_CPU_DESCRIPTOR_HANDLE SRV() const override
{
return _srv.CPU();
}
D3D12_CPU_DESCRIPTOR_HANDLE UAV() const override
{
return _uav.CPU();
}
ResourceOwnerDX12* GetResourceOwner() const override
{
return (ResourceOwnerDX12*)this;
}
protected:
// [GPUTexture]
bool OnInit() override;
void onResidentMipsChanged() override;
void OnReleaseGPU() override;
};
#endif