You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/RenderDll/XRenderD3D9/DX12/API/DX12Resource.hpp

252 lines
8.3 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#ifndef __DX12RESOURCE__
#define __DX12RESOURCE__
#include "DX12Base.hpp"
#include "DX12/API/DX12CommandListFence.hpp"
#include <AzCore/std/smart_ptr/unique_ptr.h>
namespace DX12
{
class CommandList;
class SwapChain;
struct ResourceStates
{
ResourceStates()
:m_CurrentState(static_cast<D3D12_RESOURCE_STATES>(-1)),
m_AnnouncedState(static_cast<D3D12_RESOURCE_STATES>(-1))
{}
ResourceStates(D3D12_RESOURCE_STATES currentState, D3D12_RESOURCE_STATES announcedState)
:m_CurrentState(currentState),
m_AnnouncedState(announcedState)
{}
bool operator ==(const ResourceStates& states) const
{
return m_CurrentState == states.m_CurrentState && m_AnnouncedState == states.m_AnnouncedState;
}
bool operator !=(const ResourceStates& states) const
{
return !(*this == states);
}
D3D12_RESOURCE_STATES m_CurrentState;
D3D12_RESOURCE_STATES m_AnnouncedState;
};
class Resource : public DeviceObject
{
public:
Resource(Device* pDevice);
virtual ~Resource();
Resource(Resource&& r);
Resource& operator=(Resource&& r);
void TryStagingUpload(CommandList* pCmdList);
bool Init(ID3D12Resource* pResource, D3D12_RESOURCE_STATES eInitialState, const D3D12_RESOURCE_DESC& desc);
bool Init(ID3D12Resource* pResource, D3D12_RESOURCE_STATES eInitialState)
{
return Init(pResource, eInitialState, pResource->GetDesc());
}
// Initialization of contents
struct InitialData
{
std::vector<D3D12_SUBRESOURCE_DATA> m_SubResourceData{};
UINT64 m_Size{0};
UINT64 m_UploadSize{0};
};
InitialData* GetOrCreateInitialData();
inline bool InitHasBeenDeferred() const
{
return m_InitialData != nullptr;
}
// Swap-chain associativity
inline void SetDX12SwapChain(SwapChain* pOwner)
{
m_pSwapChainOwner = pOwner;
}
inline SwapChain* GetDX12SwapChain() const
{
return m_pSwapChainOwner;
}
inline bool IsBackBuffer() const
{
return m_pSwapChainOwner != NULL;
}
inline bool IsOffCard() const
{
return m_HeapType == D3D12_HEAP_TYPE_READBACK || m_HeapType == D3D12_HEAP_TYPE_UPLOAD;
}
inline D3D12_RESOURCE_STATES GetRequiredResourceState() const
{
return m_HeapType == D3D12_HEAP_TYPE_READBACK ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_GENERIC_READ;
}
inline bool IsTarget() const
{
return !!(GetCurrentState() & (D3D12_RESOURCE_STATE_RENDER_TARGET | D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_DEPTH_WRITE));
}
inline bool IsGeneric() const
{
return !!(GetCurrentState() & (D3D12_RESOURCE_STATE_UNORDERED_ACCESS | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
}
inline D3D12_RESOURCE_DESC& GetDesc()
{
return m_Desc;
}
inline const D3D12_RESOURCE_DESC& GetDesc() const
{
return m_Desc;
}
UINT64 GetRequiredUploadSize(UINT FirstSubresource, UINT NumSubresources) const;
inline ID3D12Resource* GetD3D12Resource() const
{
return m_pD3D12Resource;
}
inline D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress() const
{
return m_GPUVirtualAddress;
}
// Get current known resource barrier state
inline D3D12_RESOURCE_STATES GetCurrentState() const
{
return m_States.m_CurrentState;
}
inline D3D12_RESOURCE_STATES GetAnnouncedState() const
{
return m_States.m_AnnouncedState;
}
inline void SetCurrentState(D3D12_RESOURCE_STATES state)
{
m_States.m_CurrentState = state;
}
inline void SetAnnouncedState(D3D12_RESOURCE_STATES state)
{
m_States.m_AnnouncedState = state;
}
UINT64 SetFenceValue(UINT64 fenceValue, const int id, const int type)
{
// Check submitted completed fence
UINT64 utilizedValue = fenceValue;
UINT64 previousValue = m_FenceValues[type][id];
#define DX12_FREETHREADED_RESOURCES
#ifndef DX12_FREETHREADED_RESOURCES
m_FenceValues[type][id] = (previousValue > fenceValue ? previousValue : fenceValue);
if (type == CMDTYPE_ANY)
{
m_FenceValues[CMDTYPE_READ ][id] =
m_FenceValues[CMDTYPE_WRITE][id] =
m_FenceValues[CMDTYPE_ANY][id];
}
else
{
m_FenceValues[CMDTYPE_ANY ][id] = std::max(
m_FenceValues[CMDTYPE_READ ][id],
m_FenceValues[CMDTYPE_WRITE][id]);
}
#else
// CLs may submit in any order. Is it higher than last known completed fence? If so, update it!
MaxFenceValue(m_FenceValues[type][id], fenceValue);
if (type == CMDTYPE_ANY)
{
MaxFenceValue(m_FenceValues[CMDTYPE_READ ][id], m_FenceValues[CMDTYPE_ANY][id]);
MaxFenceValue(m_FenceValues[CMDTYPE_WRITE][id], m_FenceValues[CMDTYPE_ANY][id]);
}
else
{
MaxFenceValue(m_FenceValues[CMDTYPE_ANY ][id], std::max(m_FenceValues[CMDTYPE_READ][id], m_FenceValues[CMDTYPE_WRITE][id]));
}
#endif // !NDEBUG
return previousValue;
}
inline UINT64 GetFenceValue(const int id, const int type)
{
return m_FenceValues[type][id];
}
inline const std::atomic<AZ::u64> (& GetFenceValues(const int type))[CMDQUEUE_NUM]
{
return m_FenceValues[type];
}
inline void MaxFenceValues(std::atomic<AZ::u64> (&rFenceValues)[CMDTYPE_NUM][CMDQUEUE_NUM], const int type)
{
if ((type == CMDTYPE_READ) || (type == CMDTYPE_ANY))
{
MaxFenceValue(rFenceValues[CMDTYPE_READ ][CMDQUEUE_COPY ], m_FenceValues[CMDTYPE_READ ][CMDQUEUE_COPY ]);
MaxFenceValue(rFenceValues[CMDTYPE_READ ][CMDQUEUE_GRAPHICS], m_FenceValues[CMDTYPE_READ ][CMDQUEUE_GRAPHICS]);
}
if ((type == CMDTYPE_WRITE) || (type == CMDTYPE_ANY))
{
MaxFenceValue(rFenceValues[CMDTYPE_WRITE][CMDQUEUE_COPY ], m_FenceValues[CMDTYPE_WRITE][CMDQUEUE_COPY ]);
MaxFenceValue(rFenceValues[CMDTYPE_WRITE][CMDQUEUE_GRAPHICS], m_FenceValues[CMDTYPE_WRITE][CMDQUEUE_GRAPHICS]);
}
}
bool IsUsed(CommandListPool& pCmdListPool, const int type = CMDTYPE_ANY);
void WaitForUnused(CommandListPool& pCmdListPool, const int type = CMDTYPE_ANY);
void MapDiscard(CommandList* pCmdList);
protected:
friend class CommandList;
void DiscardInitialData();
// Never changes after construction
D3D12_RESOURCE_DESC m_Desc;
D3D12_HEAP_TYPE m_HeapType;
D3D12_GPU_VIRTUAL_ADDRESS m_GPUVirtualAddress;
SmartPtr<ID3D12Resource> m_pD3D12Resource; // can be replaced by MAP_DISCARD, which is deprecated
SwapChain* m_pSwapChainOwner;
// Potentially changes on every resource-use
ResourceStates m_States;
mutable std::atomic<AZ::u64> m_FenceValues[CMDTYPE_NUM][CMDQUEUE_NUM];
// Used when using the resource the first time
AZStd::unique_ptr<InitialData> m_InitialData;
};
}
#endif // __DX12RESOURCE__