// 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