// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Core/Delegate.h" #include "Engine/Graphics/GPUResourceState.h" #include "../IncludeDirectXHeaders.h" #if GRAPHICS_API_DIRECTX12 class GPUResource; class GPUContextDX12; class GPUAsyncContextDX12; /// /// Default amount of frames to wait until resource delete. /// #define DX12_RESOURCE_DELETE_SAFE_FRAMES_COUNT 100 /// /// Custom resource state used to indicate invalid state (useful for debugging resource tracking issues). /// #define D3D12_RESOURCE_STATE_CORRUPT (D3D12_RESOURCE_STATES)-1 /// /// Tracking of per-resource or per-subresource state for D3D12 resources that require to issue resource access barriers during rendering. /// class ResourceStateDX12 : public GPUResourceState { public: /// /// Returns true if resource state transition is needed in order to use resource in given state. /// /// The current resource state. /// the destination resource state. /// True if need to perform a transition, otherwise false. FORCE_INLINE static bool IsTransitionNeeded(D3D12_RESOURCE_STATES before, D3D12_RESOURCE_STATES& after) { if (before == D3D12_RESOURCE_STATE_DEPTH_WRITE && after == D3D12_RESOURCE_STATE_DEPTH_READ) return false; if (after == D3D12_RESOURCE_STATE_COMMON) return before != D3D12_RESOURCE_STATE_COMMON; if (after == D3D12_RESOURCE_STATE_DEPTH_READ) return ~(before & (D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)) == 0; const D3D12_RESOURCE_STATES combined = before | after; if ((combined & (D3D12_RESOURCE_STATE_GENERIC_READ | D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT)) == combined) after = combined; return before != after; } }; /// /// Base class for objects in DirectX 12 layer that can own a resource /// class ResourceOwnerDX12 { friend GPUContextDX12; friend GPUAsyncContextDX12; protected: ID3D12Resource* _resource; uint32 _subresourcesCount; ResourceOwnerDX12() : _resource(nullptr) , _subresourcesCount(0) { } ~ResourceOwnerDX12() { } public: /// /// Action called on resource release event. /// Delegate OnRelease; /// /// The resource state tracking helper. Used for resource barriers. /// ResourceStateDX12 State; public: /// /// Gets the subresources count. /// FORCE_INLINE uint32 GetSubresourcesCount() const { return _subresourcesCount; } /// /// Gets DirectX 12 resource object handle /// FORCE_INLINE ID3D12Resource* GetResource() const { return _resource; } /// /// Gets resource owner object as a GPUResource type or returns null if cannot perform cast. /// virtual GPUResource* AsGPUResource() const = 0; protected: FORCE_INLINE void initResource(ID3D12Resource* resource, const D3D12_RESOURCE_STATES initialState, const D3D12_RESOURCE_DESC& desc, bool usePerSubresourceTracking = false) { initResource(resource, initialState, desc.DepthOrArraySize * desc.MipLevels, usePerSubresourceTracking); } void initResource(ID3D12Resource* resource, const D3D12_RESOURCE_STATES initialState, const uint32 subresourceCount, bool usePerSubresourceTracking = false); void initResource(const D3D12_RESOURCE_STATES initialState, const uint32 subresourceCount, bool usePerSubresourceTracking = false); void releaseResource(uint32 safeFrameCount = DX12_RESOURCE_DELETE_SAFE_FRAMES_COUNT); }; #endif