417 lines
13 KiB
C++
417 lines
13 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "D3D12View.h"
|
|
#include "D3D12RHIPrivate.h"
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
//
|
|
// FD3D12ViewRange
|
|
//
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
FD3D12ViewRange::FD3D12ViewRange(D3D12_CONSTANT_BUFFER_VIEW_DESC const& ViewDesc)
|
|
: Array(0, 1)
|
|
, Plane(0, 1)
|
|
, Mip (0, 1)
|
|
{}
|
|
|
|
FD3D12ViewRange::FD3D12ViewRange(D3D12_RENDER_TARGET_VIEW_DESC const& ViewDesc)
|
|
{
|
|
uint32 FirstPlane = UE::DXGIUtilities::GetPlaneSliceFromViewFormat(ViewDesc.Format, ViewDesc.Format);
|
|
uint32 NumPlanes = UE::DXGIUtilities::GetPlaneCount(ViewDesc.Format);
|
|
Plane = { FirstPlane, NumPlanes - FirstPlane };
|
|
|
|
switch (ViewDesc.ViewDimension)
|
|
{
|
|
default: checkNoEntry(); return; // not implemented
|
|
|
|
case D3D12_RTV_DIMENSION_UNKNOWN:
|
|
Mip = { 0, 0 };
|
|
Plane = { 0, 0 };
|
|
Array = { 0, 0 };
|
|
break;
|
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE2D:
|
|
Mip = { ViewDesc.Texture2D.MipSlice , 1 };
|
|
Plane = { ViewDesc.Texture2D.PlaneSlice, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:
|
|
Mip = { ViewDesc.Texture2DArray.MipSlice , 1 };
|
|
Plane = { ViewDesc.Texture2DArray.PlaneSlice, 1 };
|
|
Array = { ViewDesc.Texture2DArray.FirstArraySlice, ViewDesc.Texture2DArray.ArraySize };
|
|
break;
|
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DMS:
|
|
Mip = { 0, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:
|
|
Mip = { 0, 1 };
|
|
Array = { ViewDesc.Texture2DMSArray.FirstArraySlice, ViewDesc.Texture2DMSArray.ArraySize };
|
|
break;
|
|
|
|
case D3D12_RTV_DIMENSION_TEXTURE3D:
|
|
Mip = { ViewDesc.Texture3D.MipSlice, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
}
|
|
}
|
|
|
|
FD3D12ViewRange::FD3D12ViewRange(D3D12_SHADER_RESOURCE_VIEW_DESC const& ViewDesc)
|
|
{
|
|
uint32 FirstPlane = UE::DXGIUtilities::GetPlaneSliceFromViewFormat(ViewDesc.Format, ViewDesc.Format);
|
|
uint32 NumPlanes = UE::DXGIUtilities::GetPlaneCount(ViewDesc.Format);
|
|
Plane = { FirstPlane, NumPlanes - FirstPlane };
|
|
|
|
switch (ViewDesc.ViewDimension)
|
|
{
|
|
default: checkNoEntry(); return; // not implemented
|
|
|
|
case D3D12_SRV_DIMENSION_UNKNOWN:
|
|
Mip = { 0, 0 };
|
|
Plane = { 0, 0 };
|
|
Array = { 0, 0 };
|
|
break;
|
|
|
|
#if D3D12_RHI_RAYTRACING
|
|
case D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE:
|
|
Mip = { 0, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
#endif
|
|
|
|
case D3D12_SRV_DIMENSION_BUFFER:
|
|
Mip = { 0, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2D:
|
|
Mip = { ViewDesc.Texture2D.MostDetailedMip, ViewDesc.Texture2D.MipLevels };
|
|
Plane = { ViewDesc.Texture2D.PlaneSlice, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DARRAY:
|
|
Mip = { ViewDesc.Texture2DArray.MostDetailedMip, ViewDesc.Texture2DArray.MipLevels };
|
|
Plane = { ViewDesc.Texture2DArray.PlaneSlice, 1 };
|
|
Array = { ViewDesc.Texture2DArray.FirstArraySlice, ViewDesc.Texture2DArray.ArraySize };
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DMS:
|
|
Mip = { 0, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY:
|
|
Mip = { 0, 1 };
|
|
Array = { ViewDesc.Texture2DMSArray.FirstArraySlice, ViewDesc.Texture2DMSArray.ArraySize };
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURE3D:
|
|
Mip = { ViewDesc.Texture3D.MostDetailedMip, ViewDesc.Texture3D.MipLevels };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURECUBE:
|
|
Mip = { ViewDesc.TextureCube.MostDetailedMip, ViewDesc.TextureCube.MipLevels };
|
|
Array = { 0, 6 };
|
|
break;
|
|
|
|
case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY:
|
|
Mip = { ViewDesc.TextureCubeArray.MostDetailedMip, ViewDesc.TextureCubeArray.MipLevels };
|
|
Array = { ViewDesc.TextureCubeArray.First2DArrayFace, ViewDesc.TextureCubeArray.NumCubes * 6 };
|
|
break;
|
|
}
|
|
}
|
|
|
|
FD3D12ViewRange::FD3D12ViewRange(D3D12_DEPTH_STENCIL_VIEW_DESC const& ViewDesc)
|
|
{
|
|
uint32 FirstPlane = UE::DXGIUtilities::GetPlaneSliceFromViewFormat(ViewDesc.Format, ViewDesc.Format);
|
|
uint32 NumPlanes = UE::DXGIUtilities::GetPlaneCount(ViewDesc.Format);
|
|
Plane = { FirstPlane, NumPlanes - FirstPlane };
|
|
|
|
switch (ViewDesc.ViewDimension)
|
|
{
|
|
default: checkNoEntry(); return; // not implemented
|
|
|
|
case D3D12_DSV_DIMENSION_UNKNOWN:
|
|
Mip = { 0, 0 };
|
|
Plane = { 0, 0 };
|
|
Array = { 0, 0 };
|
|
break;
|
|
|
|
case D3D12_DSV_DIMENSION_TEXTURE2D:
|
|
Mip = { ViewDesc.Texture2D.MipSlice, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:
|
|
Mip = { ViewDesc.Texture2DArray.MipSlice, 1 };
|
|
Array = { ViewDesc.Texture2DArray.FirstArraySlice, ViewDesc.Texture2DArray.ArraySize };
|
|
break;
|
|
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DMS:
|
|
Mip = { 0, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:
|
|
Mip = { 0, 1 };
|
|
Array = { ViewDesc.Texture2DMSArray.FirstArraySlice, ViewDesc.Texture2DMSArray.ArraySize };
|
|
break;
|
|
}
|
|
}
|
|
|
|
FD3D12ViewRange::FD3D12ViewRange(D3D12_UNORDERED_ACCESS_VIEW_DESC const& ViewDesc)
|
|
{
|
|
uint32 FirstPlane = UE::DXGIUtilities::GetPlaneSliceFromViewFormat(ViewDesc.Format, ViewDesc.Format);
|
|
uint32 NumPlanes = UE::DXGIUtilities::GetPlaneCount(ViewDesc.Format);
|
|
Plane = { FirstPlane, NumPlanes - FirstPlane };
|
|
|
|
switch (ViewDesc.ViewDimension)
|
|
{
|
|
default: checkNoEntry(); return; // not implemented
|
|
|
|
case D3D12_UAV_DIMENSION_UNKNOWN:
|
|
Mip = { 0, 0 };
|
|
Plane = { 0, 0 };
|
|
Array = { 0, 0 };
|
|
break;
|
|
|
|
case D3D12_UAV_DIMENSION_BUFFER:
|
|
Mip = { 0, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_UAV_DIMENSION_TEXTURE2D:
|
|
Mip = { ViewDesc.Texture2D.MipSlice , 1 };
|
|
Plane = { ViewDesc.Texture2D.PlaneSlice, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
|
|
case D3D12_UAV_DIMENSION_TEXTURE2DARRAY:
|
|
Mip = { ViewDesc.Texture2DArray.MipSlice , 1 };
|
|
Plane = { ViewDesc.Texture2DArray.PlaneSlice, 1 };
|
|
Array = { ViewDesc.Texture2DArray.FirstArraySlice, ViewDesc.Texture2DArray.ArraySize };
|
|
break;
|
|
|
|
case D3D12_UAV_DIMENSION_TEXTURE3D:
|
|
Mip = { ViewDesc.Texture3D.MipSlice, 1 };
|
|
Array = { 0, 1 };
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
//
|
|
// FD3D12View
|
|
//
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
|
|
inline bool ViewTypeSupportsBindless(ED3D12ViewType InViewType)
|
|
{
|
|
return (InViewType == ED3D12ViewType::ShaderResource || InViewType == ED3D12ViewType::UnorderedAccess);
|
|
}
|
|
#endif
|
|
|
|
FD3D12View::FD3D12View(FD3D12Device* InDevice, ED3D12ViewType InViewType, ERHIDescriptorHeapType InHeapType, FD3D12View* FirstLinkedObject)
|
|
: FD3D12DeviceChild(InDevice)
|
|
, OfflineCpuHandle(InDevice->GetOfflineDescriptorManager(InHeapType).AllocateHeapSlot())
|
|
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
|
|
, bFirstLinkedObject(FirstLinkedObject == nullptr) // If FirstLinkedObject is nullptr, this newly constructed object itself must be the first
|
|
#endif
|
|
, HeapType(InHeapType)
|
|
{
|
|
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
|
|
if (ViewTypeSupportsBindless(InViewType))
|
|
{
|
|
// Bindless handle is shared across linked objects, so pull the handle from the first object if available, or allocate if we are the first
|
|
BindlessHandle = FirstLinkedObject ? FirstLinkedObject->BindlessHandle : InDevice->GetBindlessDescriptorAllocator().AllocateResourceHandle();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
FD3D12View::~FD3D12View()
|
|
{
|
|
// Unregister this view from the underlying resource
|
|
if (ResourceInfo.BaseResource)
|
|
{
|
|
ResourceInfo.BaseResource->RemoveRenameListener(this);
|
|
}
|
|
|
|
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
|
|
if (BindlessHandle.IsValid())
|
|
{
|
|
// Bindless handle is shared, first linked object handles freeing
|
|
if (bFirstLinkedObject)
|
|
{
|
|
GetParentDevice()->GetBindlessDescriptorManager().DeferredFreeFromDestructor(BindlessHandle);
|
|
}
|
|
BindlessHandle = {};
|
|
}
|
|
#endif
|
|
|
|
// Free the descriptor heap slot and bindless handle
|
|
GetParentDevice()->GetOfflineDescriptorManager(HeapType).FreeHeapSlot(OfflineCpuHandle);
|
|
}
|
|
|
|
void FD3D12View::InitializeBindlessSlot()
|
|
{
|
|
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
|
|
if (BindlessHandle.IsValid())
|
|
{
|
|
GetParentDevice()->GetBindlessDescriptorManager().InitializeDescriptor(BindlessHandle, this);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void FD3D12View::UpdateBindlessSlot(FD3D12ContextArray const& Contexts)
|
|
{
|
|
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
|
|
if (BindlessHandle.IsValid())
|
|
{
|
|
check(BindlessHandle.GetType() == ERHIDescriptorHeapType::Standard);
|
|
GetParentDevice()->GetBindlessDescriptorManager().UpdateDescriptor(Contexts, BindlessHandle, this);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void FD3D12View::UpdateResourceInfo(FResourceInfo const& InResource, FNullDescPtr NullDescriptor)
|
|
{
|
|
if (ResourceInfo.BaseResource != InResource.BaseResource)
|
|
{
|
|
if (ResourceInfo.BaseResource)
|
|
ResourceInfo.BaseResource->RemoveRenameListener(this);
|
|
|
|
if (InResource.BaseResource)
|
|
InResource.BaseResource->AddRenameListener(this);
|
|
}
|
|
|
|
ResourceInfo = InResource;
|
|
|
|
if (ResourceInfo.Resource)
|
|
{
|
|
ViewSubset.Layout = ResourceInfo.Resource->GetDesc();
|
|
UpdateDescriptor();
|
|
}
|
|
else
|
|
{
|
|
ViewSubset.Layout = {};
|
|
|
|
// Set the offline descriptor to null by copying the view type's default null descriptor.
|
|
FD3D12Device* Device = GetParentDevice();
|
|
|
|
Device->GetDevice()->CopyDescriptorsSimple(
|
|
1,
|
|
OfflineCpuHandle,
|
|
Device->GetDefaultViews().*NullDescriptor,
|
|
Translate(HeapType)
|
|
);
|
|
|
|
OfflineCpuHandle.IncrementVersion();
|
|
}
|
|
}
|
|
|
|
void FD3D12View::CreateView(FResourceInfo const& InResource, FNullDescPtr NullDescriptor)
|
|
{
|
|
UpdateResourceInfo(InResource, NullDescriptor);
|
|
InitializeBindlessSlot();
|
|
}
|
|
|
|
void FD3D12View::UpdateView(FD3D12ContextArray const& Contexts, const FResourceInfo& InResource, FNullDescPtr NullDescriptor)
|
|
{
|
|
UpdateResourceInfo(InResource, NullDescriptor);
|
|
UpdateBindlessSlot(Contexts);
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
//
|
|
// FD3D12ConstantBufferView
|
|
//
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
FD3D12ConstantBufferView::FD3D12ConstantBufferView(FD3D12Device* InDevice, FD3D12ConstantBufferView* FirstLinkedObject)
|
|
: TD3D12View(InDevice, ED3D12ViewType::ConstantBuffer, ERHIDescriptorHeapType::Standard, FirstLinkedObject)
|
|
{
|
|
}
|
|
|
|
void FD3D12ConstantBufferView::CreateView(FResourceInfo const& InResource, uint32 InOffset, uint32 InAlignedSize)
|
|
{
|
|
Offset = InOffset;
|
|
|
|
D3D12_CONSTANT_BUFFER_VIEW_DESC CBVDesc = {};
|
|
CBVDesc.BufferLocation = InResource.ResourceLocation->GetGPUVirtualAddress() + Offset;
|
|
CBVDesc.SizeInBytes = InAlignedSize;
|
|
|
|
TD3D12View::CreateView(InResource, CBVDesc);
|
|
}
|
|
|
|
void FD3D12ConstantBufferView::ResourceRenamed(FD3D12ContextArray const& Contexts, FD3D12BaseShaderResource* InRenamedResource, FD3D12ResourceLocation* InNewResourceLocation)
|
|
{
|
|
D3DViewDesc.BufferLocation = InNewResourceLocation->GetGPUVirtualAddress() + Offset;
|
|
TD3D12View::ResourceRenamed(Contexts, InRenamedResource, InNewResourceLocation);
|
|
}
|
|
|
|
void FD3D12ConstantBufferView::UpdateDescriptor()
|
|
{
|
|
GetParentDevice()->GetDevice()->CreateConstantBufferView(&D3DViewDesc, OfflineCpuHandle);
|
|
|
|
OfflineCpuHandle.IncrementVersion();
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
//
|
|
// FD3D12RenderTargetView
|
|
//
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
FD3D12RenderTargetView::FD3D12RenderTargetView(FD3D12Device* InDevice, FD3D12RenderTargetView* FirstLinkedObject)
|
|
: TD3D12View(InDevice, ED3D12ViewType::RenderTarget, ERHIDescriptorHeapType::RenderTarget, FirstLinkedObject)
|
|
{
|
|
}
|
|
|
|
void FD3D12RenderTargetView::UpdateDescriptor()
|
|
{
|
|
GetParentDevice()->GetDevice()->CreateRenderTargetView(
|
|
ResourceInfo.Resource->GetResource(),
|
|
&D3DViewDesc,
|
|
OfflineCpuHandle
|
|
);
|
|
|
|
OfflineCpuHandle.IncrementVersion();
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------------
|
|
//
|
|
// FD3D12DepthStencilView
|
|
//
|
|
// -----------------------------------------------------------------------------------------------------
|
|
|
|
FD3D12DepthStencilView::FD3D12DepthStencilView(FD3D12Device* InDevice, FD3D12DepthStencilView* FirstLinkedObject)
|
|
: TD3D12View(InDevice, ED3D12ViewType::DepthStencil, ERHIDescriptorHeapType::DepthStencil, FirstLinkedObject)
|
|
{
|
|
}
|
|
|
|
void FD3D12DepthStencilView::UpdateDescriptor()
|
|
{
|
|
GetParentDevice()->GetDevice()->CreateDepthStencilView(
|
|
ResourceInfo.Resource->GetResource(),
|
|
&D3DViewDesc,
|
|
OfflineCpuHandle
|
|
);
|
|
|
|
OfflineCpuHandle.IncrementVersion();
|
|
}
|