Fix descriptors bindings to shaders on D3D12

This commit is contained in:
Wojtek Figat
2021-06-07 13:08:39 +02:00
parent f4c8808d19
commit 39698c7694
11 changed files with 300 additions and 222 deletions

View File

@@ -128,25 +128,14 @@ void DescriptorHeapWithSlotsDX12::ReleaseSlot(uint32 index)
value &= ~mask;
}
DescriptorHeapPoolDX12::DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCount, bool shaderVisible)
DescriptorHeapPoolDX12::DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCountPerHeap, bool shaderVisible)
: _device(device)
, _type(type)
, _descriptorsCount(descriptorsCount)
, _descriptorsCountPerHeap(descriptorsCountPerHeap)
, _shaderVisible(shaderVisible)
{
}
void DescriptorHeapPoolDX12::Init()
{
// Allocate first page
auto heap = New<DescriptorHeapWithSlotsDX12>(_device);
if (heap->Create(_type, _descriptorsCount, _shaderVisible))
{
Platform::Fatal(TEXT("Failed to allocate descriptor heap."));
}
_heaps.Add(heap);
}
void DescriptorHeapPoolDX12::AllocateSlot(DescriptorHeapWithSlotsDX12*& heap, uint32& slot)
{
for (int32 i = 0; i < _heaps.Count(); i++)
@@ -159,7 +148,7 @@ void DescriptorHeapPoolDX12::AllocateSlot(DescriptorHeapWithSlotsDX12*& heap, ui
}
heap = New<DescriptorHeapWithSlotsDX12>(_device);
if (heap->Create(_type, _descriptorsCount, _shaderVisible))
if (heap->Create(_type, _descriptorsCountPerHeap, _shaderVisible))
{
Platform::Fatal(TEXT("Failed to allocate descriptor heap."));
}

View File

@@ -133,17 +133,16 @@ private:
GPUDeviceDX12* _device;
D3D12_DESCRIPTOR_HEAP_TYPE _type;
uint32 _descriptorsCount;
uint32 _descriptorsCountPerHeap;
bool _shaderVisible;
Array<DescriptorHeapWithSlotsDX12*> _heaps;
Array<DescriptorHeapWithSlotsDX12*, InlinedAllocation<32>> _heaps;
public:
DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCount, bool shaderVisible);
DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCountPerHeap, bool shaderVisible);
public:
void Init();
void AllocateSlot(DescriptorHeapWithSlotsDX12*& heap, uint32& slot);
void ReleaseGPU();
};

View File

@@ -9,6 +9,16 @@
#include "Engine/Graphics/RenderTask.h"
#include "Engine/Graphics/Async/Tasks/GPUUploadBufferTask.h"
void GPUBufferViewDX12::SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC& srvDesc)
{
_srv.CreateSRV(_device, _owner->GetResource(), &srvDesc);
}
void GPUBufferViewDX12::SetUAV(D3D12_UNORDERED_ACCESS_VIEW_DESC& uavDesc, ID3D12Resource* counterResource)
{
_uav.CreateUAV(_device, _owner->GetResource(), &uavDesc, counterResource);
}
uint64 GPUBufferDX12::GetSizeInBytes() const
{
return _memoryUsage;
@@ -201,7 +211,7 @@ bool GPUBufferDX12::OnInit()
}
if (_desc.Flags & GPUBufferFlags::RawBuffer)
srvDesc.Buffer.Flags |= D3D12_BUFFER_SRV_FLAG_RAW;
_view.SetSRV(&srvDesc);
_view.SetSRV(srvDesc);
}
if (useUAV)
{
@@ -220,7 +230,7 @@ bool GPUBufferDX12::OnInit()
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
else
uavDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindUnorderedAccessFormat(_desc.Format));
_view.SetUAV(&uavDesc, _counter ? _counter->GetResource() : nullptr);
_view.SetUAV(uavDesc, _counter ? _counter->GetResource() : nullptr);
}
return false;

View File

@@ -27,6 +27,7 @@ public:
/// </summary>
GPUBufferViewDX12()
{
SrvDimension = D3D12_SRV_DIMENSION_BUFFER;
}
/// <summary>
@@ -65,34 +66,14 @@ public:
/// Sets the shader resource view.
/// </summary>
/// <param name="srvDesc">The SRV desc.</param>
void SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC* srvDesc)
{
if (srvDesc)
{
_srv.CreateSRV(_device, _owner->GetResource(), srvDesc);
}
else
{
_srv.Release();
}
}
void SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC& srvDesc);
/// <summary>
/// Sets the unordered access view.
/// </summary>
/// <param name="uavDesc">The UAV desc.</param>
/// <param name="counterResource">The counter buffer resource.</param>
void SetUAV(D3D12_UNORDERED_ACCESS_VIEW_DESC* uavDesc, ID3D12Resource* counterResource = nullptr)
{
if (uavDesc)
{
_uav.CreateUAV(_device, _owner->GetResource(), uavDesc, counterResource);
}
else
{
_uav.Release();
}
}
void SetUAV(D3D12_UNORDERED_ACCESS_VIEW_DESC& uavDesc, ID3D12Resource* counterResource = nullptr);
public:

View File

@@ -136,26 +136,36 @@ void GPUContextDX12::AddTransitionBarrier(ResourceOwnerDX12* resource, const D3D
void GPUContextDX12::SetResourceState(ResourceOwnerDX12* resource, D3D12_RESOURCE_STATES after, int32 subresourceIndex)
{
// Check if resource is missing
auto nativeResource = resource->GetResource();
if (nativeResource == nullptr)
return;
auto& state = resource->State;
if (subresourceIndex == D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES && !state.AreAllSubresourcesSame())
if (subresourceIndex == -1)
{
// Slow path because we have to transition the entire resource with multiple subresources that aren't in the same state
const uint32 subresourceCount = resource->GetSubresourcesCount();
for (uint32 i = 0; i < subresourceCount; i++)
if (state.AreAllSubresourcesSame())
{
const D3D12_RESOURCE_STATES before = state.GetSubresourceState(i);
if (before != after)
// Transition entire resource at once
const D3D12_RESOURCE_STATES before = state.GetSubresourceState(subresourceIndex);
if (ResourceStateDX12::IsTransitionNeeded(before, after))
{
AddTransitionBarrier(resource, before, after, i);
state.SetSubresourceState(i, after);
AddTransitionBarrier(resource, before, after, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES);
state.SetSubresourceState(subresourceIndex, after);
}
}
ASSERT(state.CheckResourceState(after));
else
{
// Slow path to transition each subresource
for (int32 i = 0; i < state.GetSubresourcesCount(); i++)
{
const D3D12_RESOURCE_STATES before = state.GetSubresourceState(i);
if (ResourceStateDX12::IsTransitionNeeded(before, after))
{
AddTransitionBarrier(resource, before, after, i);
state.SetSubresourceState(i, after);
}
}
ASSERT(state.CheckResourceState(after));
}
state.SetResourceState(after);
}
else
@@ -163,6 +173,7 @@ void GPUContextDX12::SetResourceState(ResourceOwnerDX12* resource, D3D12_RESOURC
const D3D12_RESOURCE_STATES before = state.GetSubresourceState(subresourceIndex);
if (ResourceStateDX12::IsTransitionNeeded(before, after))
{
// Transition a single subresource
AddTransitionBarrier(resource, before, after, subresourceIndex);
state.SetSubresourceState(subresourceIndex, after);
}
@@ -282,23 +293,25 @@ void GPUContextDX12::flushSRVs()
ASSERT(srCount <= GPU_MAX_SR_BINDED);
// Fill table with source descriptors
DxShaderHeader& header = _currentCompute ? ((GPUShaderProgramCSDX12*)_currentCompute)->Header : _currentState->Header;
D3D12_CPU_DESCRIPTOR_HANDLE srcDescriptorRangeStarts[GPU_MAX_SR_BINDED];
for (uint32 i = 0; i < srCount; i++)
{
const auto handle = _srHandles[i];
if (handle != nullptr)
const auto dimensions = (D3D12_SRV_DIMENSION)header.SrDimensions[i];
if (handle != nullptr && dimensions)
{
ASSERT(handle->SrvDimension == dimensions);
srcDescriptorRangeStarts[i] = handle->SRV();
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
// TODO: for setup states based on binding mode
D3D12_RESOURCE_STATES states = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
if (handle->IsDepthStencilResource())
state |= D3D12_RESOURCE_STATE_DEPTH_READ;
SetResourceState(handle->GetResourceOwner(), state, handle->SubresourceIndex);
states |= D3D12_RESOURCE_STATE_DEPTH_READ;
SetResourceState(handle->GetResourceOwner(), states, handle->SubresourceIndex);
}
else
{
srcDescriptorRangeStarts[i] = _device->NullSRV();
srcDescriptorRangeStarts[i] = _device->NullSRV(dimensions);
}
}
@@ -306,10 +319,7 @@ void GPUContextDX12::flushSRVs()
auto allocation = _device->RingHeap_CBV_SRV_UAV.AllocateTable(srCount);
// Copy descriptors
_device->GetDevice()->CopyDescriptors(
1, &allocation.CPU, &srCount,
srCount, srcDescriptorRangeStarts, nullptr,
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
_device->GetDevice()->CopyDescriptors(1, &allocation.CPU, &srCount, srCount, srcDescriptorRangeStarts, nullptr, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
// Flush SRV descriptors table
if (_isCompute)
@@ -400,10 +410,7 @@ void GPUContextDX12::flushUAVs()
auto allocation = _device->RingHeap_CBV_SRV_UAV.AllocateTable(uaCount);
// Copy descriptors
_device->GetDevice()->CopyDescriptors(
1, &allocation.CPU, &uaCount,
uaCount, srcDescriptorRangeStarts, nullptr,
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
_device->GetDevice()->CopyDescriptors(1, &allocation.CPU, &uaCount, uaCount, srcDescriptorRangeStarts, nullptr, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
// Flush UAV descriptors table
if (_isCompute)
@@ -444,8 +451,8 @@ void GPUContextDX12::flushRBs()
if (_rbBufferSize > 0)
{
#if DX12_ENABLE_RESOURCE_BARRIERS_DEBUGGING
const auto info = String::Format(TEXT("[DX12 Resource Barrier]: Flush {0} barriers"), _rbBufferSize);
Log::Logger::Write(LogType::Info, info);
const auto info = String::Format(TEXT("[DX12 Resource Barrier]: Flush {0} barriers"), _rbBufferSize);
Log::Logger::Write(LogType::Info, info);
#endif
// Flush resource barriers
@@ -490,6 +497,32 @@ void GPUContextDX12::onDrawCall()
SetResourceState(_ibHandle, D3D12_RESOURCE_STATE_INDEX_BUFFER);
}
// If SRV resource is not binded to RTV then transition it to the whole state (GPU-BASED VALIDATION complains about it)
for (uint32 i = 0; i < GPU_MAX_SR_BINDED; i++)
{
const auto handle = _srHandles[i];
if (handle != nullptr && handle->GetResourceOwner())
{
const auto resourceOwner = handle->GetResourceOwner();
bool isRtv = false;
for (int32 j = 0; j < _rtCount; j++)
{
if (_rtHandles[j] && _rtHandles[j]->GetResourceOwner() == resourceOwner)
{
isRtv = true;
break;
}
}
if (!isRtv)
{
D3D12_RESOURCE_STATES states = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
if (handle->IsDepthStencilResource())
states |= D3D12_RESOURCE_STATE_DEPTH_READ;
SetResourceState(handle->GetResourceOwner(), states);
}
}
}
// Flush
flushSRVs();
flushRTVs();
@@ -497,6 +530,43 @@ void GPUContextDX12::onDrawCall()
flushRBs();
flushPS();
flushCBs();
#if BUILD_DEBUG
// Additional verification of the state
for (int32 i = 0; i < _rtCount; i++)
{
const auto handle = _rtHandles[i];
if (handle != nullptr && handle->GetResourceOwner())
{
const auto& state = handle->GetResourceOwner()->State;
ASSERT((state.GetSubresourceState(handle->SubresourceIndex) & D3D12_RESOURCE_STATE_RENDER_TARGET) != 0);
}
}
const uint32 srMask = _currentState->GetUsedSRsMask();
const uint32 srCount = Math::FloorLog2(srMask) + 1;
for (uint32 i = 0; i < srCount; i++)
{
const auto handle = _srHandles[i];
if (handle != nullptr && handle->GetResourceOwner())
{
const auto& state = handle->GetResourceOwner()->State;
bool isRtv = false;
for (int32 j = 0; j < _rtCount; j++)
{
if (_rtHandles[j] && _rtHandles[j]->GetResourceOwner() == handle->GetResourceOwner())
{
isRtv = true;
break;
}
}
ASSERT((state.GetSubresourceState(handle->SubresourceIndex) & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) != 0);
if (!isRtv)
{
ASSERT(state.AreAllSubresourcesSame());
}
}
}
#endif
}
void GPUContextDX12::FrameBegin()
@@ -722,10 +792,8 @@ void GPUContextDX12::BindCB(int32 slot, GPUConstantBuffer* cb)
void GPUContextDX12::BindSR(int32 slot, GPUResourceView* view)
{
ASSERT(slot >= 0 && slot < GPU_MAX_SR_BINDED);
auto handle = view ? (IShaderResourceDX12*)view->GetNativePtr() : nullptr;
if (_srHandles[slot] != handle)
if (_srHandles[slot] != handle || !handle)
{
_srMaskDirtyGraphics |= 1 << slot;
_srMaskDirtyCompute |= 1 << slot;
@@ -736,10 +804,8 @@ void GPUContextDX12::BindSR(int32 slot, GPUResourceView* view)
void GPUContextDX12::BindUA(int32 slot, GPUResourceView* view)
{
ASSERT(slot >= 0 && slot < GPU_MAX_UA_BINDED);
auto handle = view ? (IShaderResourceDX12*)view->GetNativePtr() : nullptr;
if (_uaHandles[slot] != handle)
if (_uaHandles[slot] != handle || !handle)
{
_uaMaskDirtyGraphics |= 1 << slot;
_uaMaskDirtyCompute |= 1 << slot;

View File

@@ -350,32 +350,78 @@ bool GPUDeviceDX12::Init()
_device->SetStablePowerState(TRUE);
#endif
// Create commands queue
// Setup resources
_commandQueue = New<CommandQueueDX12>(this, D3D12_COMMAND_LIST_TYPE_DIRECT);
if (_commandQueue->Init())
return true;
// Create rendering main context
_mainContext = New<GPUContextDX12>(this, D3D12_COMMAND_LIST_TYPE_DIRECT);
// Create descriptors heaps
Heap_CBV_SRV_UAV.Init();
Heap_RTV.Init();
Heap_DSV.Init();
if (RingHeap_CBV_SRV_UAV.Init())
return true;
// Create empty views
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
for (int32 i = 0; i < ARRAY_COUNT(_nullSrv); i++)
{
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
srvDesc.Texture2D.PlaneSlice = 0;
srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
_nullSrv.CreateSRV(this, nullptr, &srvDesc);
srvDesc.ViewDimension = (D3D12_SRV_DIMENSION)i;
switch (srvDesc.ViewDimension)
{
case D3D12_SRV_DIMENSION_BUFFER:
srvDesc.Buffer.FirstElement = 0;
srvDesc.Buffer.NumElements = 0;
srvDesc.Buffer.StructureByteStride = 0;
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
break;
case D3D12_SRV_DIMENSION_TEXTURE1D:
srvDesc.Texture1D.MostDetailedMip = 0;
srvDesc.Texture1D.MipLevels = 1;
srvDesc.Texture1D.ResourceMinLODClamp = 0.0f;
break;
case D3D12_SRV_DIMENSION_TEXTURE1DARRAY:
srvDesc.Texture1DArray.MostDetailedMip = 0;
srvDesc.Texture1DArray.MipLevels = 1;
srvDesc.Texture1DArray.FirstArraySlice = 0;
srvDesc.Texture1DArray.ArraySize = 1;
srvDesc.Texture1DArray.ResourceMinLODClamp = 0.0f;
break;
case D3D12_SRV_DIMENSION_UNKNOWN: // Map Unknown into Texture2D
case D3D12_SRV_DIMENSION_TEXTURE2D:
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
srvDesc.Texture2D.PlaneSlice = 0;
srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
break;
case D3D12_SRV_DIMENSION_TEXTURE2DARRAY:
srvDesc.Texture2DArray.MostDetailedMip = 0;
srvDesc.Texture2DArray.MipLevels = 1;
srvDesc.Texture2DArray.FirstArraySlice = 0;
srvDesc.Texture2DArray.ArraySize = 0;
srvDesc.Texture2DArray.PlaneSlice = 0;
srvDesc.Texture2DArray.ResourceMinLODClamp = 0.0f;
break;
case D3D12_SRV_DIMENSION_TEXTURE3D:
srvDesc.Texture3D.MostDetailedMip = 0;
srvDesc.Texture3D.MipLevels = 1;
srvDesc.Texture3D.ResourceMinLODClamp = 0.0f;
break;
case D3D12_SRV_DIMENSION_TEXTURECUBE:
srvDesc.TextureCube.MostDetailedMip = 0;
srvDesc.TextureCube.MipLevels = 1;
srvDesc.TextureCube.ResourceMinLODClamp = 0.0f;
break;
case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY:
srvDesc.TextureCubeArray.MostDetailedMip = 0;
srvDesc.TextureCubeArray.MipLevels = 1;
srvDesc.TextureCubeArray.First2DArrayFace = 0;
srvDesc.TextureCubeArray.NumCubes = 0;
srvDesc.TextureCubeArray.ResourceMinLODClamp = 0.0f;
break;
default:
continue;
}
_nullSrv[i].CreateSRV(this, nullptr, &srvDesc);
}
{
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
@@ -574,14 +620,9 @@ bool GPUDeviceDX12::Init()
void GPUDeviceDX12::DrawBegin()
{
// Wait for the GPU to have at least one backbuffer to render to
/*{
PROFILE_CPU_NAMED("Wait For Fence");
const uint64 nextFenceValue = _commandQueue->GetNextFenceValue();
if (nextFenceValue >= DX12_BACK_BUFFER_COUNT)
{
_commandQueue->WaitForFence(nextFenceValue - DX12_BACK_BUFFER_COUNT);
}
PROFILE_CPU_NAMED("Wait For GPU");
_commandQueue->WaitForGPU();
}*/
// Base
@@ -606,9 +647,9 @@ GPUDeviceDX12::~GPUDeviceDX12()
Dispose();
}
D3D12_CPU_DESCRIPTOR_HANDLE GPUDeviceDX12::NullSRV() const
D3D12_CPU_DESCRIPTOR_HANDLE GPUDeviceDX12::NullSRV(D3D12_SRV_DIMENSION dimension) const
{
return _nullSrv.CPU();
return _nullSrv[dimension].CPU();
}
D3D12_CPU_DESCRIPTOR_HANDLE GPUDeviceDX12::NullUAV() const
@@ -647,7 +688,8 @@ void GPUDeviceDX12::Dispose()
updateRes2Dispose();
// Clear pipeline objects
_nullSrv.Release();
for (auto& srv : _nullSrv)
srv.Release();
_nullUav.Release();
TimestampQueryHeap.Destroy();
DX_SAFE_RELEASE_CHECK(_rootSignature, 0);
@@ -709,7 +751,6 @@ GPUSwapChain* GPUDeviceDX12::CreateSwapChain(Window* window)
void GPUDeviceDX12::AddResourceToLateRelease(IGraphicsUnknown* resource, uint32 safeFrameCount)
{
ASSERT(safeFrameCount < 32);
if (resource == nullptr)
return;
@@ -735,7 +776,6 @@ void GPUDeviceDX12::updateRes2Dispose()
for (int32 i = _res2Dispose.Count() - 1; i >= 0 && i < _res2Dispose.Count(); i--)
{
const DisposeResourceEntry& entry = _res2Dispose[i];
if (entry.TargetFrame <= currentFrame)
{
auto refs = entry.Resource->Release();

View File

@@ -55,7 +55,7 @@ private:
GPUContextDX12* _mainContext;
// Heaps
DescriptorHeapWithSlotsDX12::Slot _nullSrv;
DescriptorHeapWithSlotsDX12::Slot _nullSrv[D3D12_SRV_DIMENSION_TEXTURECUBEARRAY + 1];
DescriptorHeapWithSlotsDX12::Slot _nullUav;
public:
@@ -93,8 +93,7 @@ public:
CommandSignatureDX12* DrawIndexedIndirectCommandSignature = nullptr;
CommandSignatureDX12* DrawIndirectCommandSignature = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE NullSRV() const;
D3D12_CPU_DESCRIPTOR_HANDLE NullSRV(D3D12_SRV_DIMENSION dimension) const;
D3D12_CPU_DESCRIPTOR_HANDLE NullUAV() const;
public:

View File

@@ -21,7 +21,7 @@ void BackBufferDX12::Setup(GPUSwapChainDX12* window, ID3D12Resource* backbuffer)
rtDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtDesc.Texture2D.MipSlice = 0;
rtDesc.Texture2D.PlaneSlice = 0;
Handle.SetRTV(&rtDesc);
Handle.SetRTV(rtDesc);
}
#if GPU_USE_WINDOW_SRV
@@ -35,7 +35,7 @@ void BackBufferDX12::Setup(GPUSwapChainDX12* window, ID3D12Resource* backbuffer)
srDesc.Texture2D.MipLevels = 1;
srDesc.Texture2D.ResourceMinLODClamp = 0;
srDesc.Texture2D.PlaneSlice = 0;
Handle.SetSRV(&srDesc);
Handle.SetSRV(srDesc);
}
#endif
}

View File

@@ -237,7 +237,7 @@ void GPUTextureDX12::onResidentMipsChanged()
// Change view
if (_handlesPerSlice[0].GetParent() == nullptr)
_handlesPerSlice[0].Init(this, _device, this, Format(), MultiSampleLevel());
_handlesPerSlice[0].SetSRV(&srDesc);
_handlesPerSlice[0].SetSRV(srDesc);
}
void GPUTextureDX12::OnReleaseGPU()
@@ -254,6 +254,35 @@ void GPUTextureDX12::OnReleaseGPU()
GPUTexture::OnReleaseGPU();
}
void GPUTextureViewDX12::Release()
{
_rtv.Release();
_srv.Release();
_dsv.Release();
_uav.Release();
}
void GPUTextureViewDX12::SetRTV(D3D12_RENDER_TARGET_VIEW_DESC& rtvDesc)
{
_rtv.CreateRTV(_device, _owner->GetResource(), &rtvDesc);
}
void GPUTextureViewDX12::SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC& srvDesc)
{
SrvDimension = srvDesc.ViewDimension;
_srv.CreateSRV(_device, _owner->GetResource(), &srvDesc);
}
void GPUTextureViewDX12::SetDSV(D3D12_DEPTH_STENCIL_VIEW_DESC& dsvDesc)
{
_dsv.CreateDSV(_device, _owner->GetResource(), &dsvDesc);
}
void GPUTextureViewDX12::SetUAV(D3D12_UNORDERED_ACCESS_VIEW_DESC& uavDesc, ID3D12Resource* counterResource)
{
_uav.CreateUAV(_device, _owner->GetResource(), &uavDesc, counterResource);
}
void GPUTextureDX12::initHandles()
{
D3D12_RENDER_TARGET_VIEW_DESC rtDesc;
@@ -318,7 +347,7 @@ void GPUTextureDX12::initHandles()
srDesc.Texture3D.MostDetailedMip = 0;
srDesc.Texture3D.MipLevels = MipLevels();
srDesc.Texture3D.ResourceMinLODClamp = 0;
_handleVolume.SetSRV(&srDesc);
_handleVolume.SetSRV(srDesc);
}
if (useRTV)
{
@@ -326,14 +355,14 @@ void GPUTextureDX12::initHandles()
rtDesc.Texture3D.MipSlice = 0;
rtDesc.Texture3D.FirstWSlice = 0;
rtDesc.Texture3D.WSize = Depth();
_handleVolume.SetRTV(&rtDesc);
_handleVolume.SetRTV(rtDesc);
}
if (useUAV)
{
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
uavDesc.Texture2D.MipSlice = 0;
uavDesc.Texture2D.PlaneSlice = 0;
_handleVolume.SetUAV(&uavDesc);
_handleVolume.SetUAV(uavDesc);
}
// Init per slice views
@@ -348,7 +377,7 @@ void GPUTextureDX12::initHandles()
{
rtDesc.Texture3D.FirstWSlice = sliceIndex;
_handlesPerSlice[sliceIndex].Init(this, _device, this, format, msaa);
_handlesPerSlice[sliceIndex].SetRTV(&rtDesc);
_handlesPerSlice[sliceIndex].SetRTV(rtDesc);
}
}
}
@@ -378,7 +407,7 @@ void GPUTextureDX12::initHandles()
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex;
dsDesc.Texture2DArray.MipSlice = 0;
}
_handlesPerSlice[arrayIndex].SetDSV(&dsDesc);
_handlesPerSlice[arrayIndex].SetDSV(dsDesc);
}
if (useRTV)
{
@@ -398,7 +427,7 @@ void GPUTextureDX12::initHandles()
rtDesc.Texture2DArray.MipSlice = 0;
rtDesc.Texture2DArray.PlaneSlice = 0;
}
_handlesPerSlice[arrayIndex].SetRTV(&rtDesc);
_handlesPerSlice[arrayIndex].SetRTV(rtDesc);
}
if (useSRV)
{
@@ -420,7 +449,7 @@ void GPUTextureDX12::initHandles()
srDesc.Texture2DArray.PlaneSlice = 0;
srDesc.Texture2DArray.ResourceMinLODClamp = 0;
}
_handlesPerSlice[arrayIndex].SetSRV(&srDesc);
_handlesPerSlice[arrayIndex].SetSRV(srDesc);
}
if (useUAV)
{
@@ -429,7 +458,7 @@ void GPUTextureDX12::initHandles()
uavDesc.Texture2DArray.FirstArraySlice = arrayIndex;
uavDesc.Texture2DArray.MipSlice = 0;
uavDesc.Texture2DArray.PlaneSlice = 0;
_handlesPerSlice[arrayIndex].SetSRV(&srDesc);
_handlesPerSlice[arrayIndex].SetSRV(srDesc);
}
}
@@ -442,7 +471,7 @@ void GPUTextureDX12::initHandles()
dsDesc.Texture2DArray.ArraySize = arraySize;
dsDesc.Texture2DArray.FirstArraySlice = 0;
dsDesc.Texture2DArray.MipSlice = 0;
_handleArray.SetDSV(&dsDesc);
_handleArray.SetDSV(dsDesc);
}
if (useRTV)
{
@@ -451,7 +480,7 @@ void GPUTextureDX12::initHandles()
rtDesc.Texture2DArray.FirstArraySlice = 0;
rtDesc.Texture2DArray.MipSlice = 0;
rtDesc.Texture2DArray.PlaneSlice = 0;
_handleArray.SetRTV(&rtDesc);
_handleArray.SetRTV(rtDesc);
}
if (useSRV)
{
@@ -472,7 +501,7 @@ void GPUTextureDX12::initHandles()
srDesc.Texture2DArray.ResourceMinLODClamp = 0;
srDesc.Texture2DArray.PlaneSlice = 0;
}
_handleArray.SetSRV(&srDesc);
_handleArray.SetSRV(srDesc);
}
if (useUAV)
{
@@ -481,7 +510,7 @@ void GPUTextureDX12::initHandles()
uavDesc.Texture2DArray.FirstArraySlice = 0;
uavDesc.Texture2DArray.MipSlice = 0;
uavDesc.Texture2DArray.PlaneSlice = 0;
_handleArray.SetUAV(&uavDesc);
_handleArray.SetUAV(uavDesc);
}
}
}
@@ -508,7 +537,7 @@ void GPUTextureDX12::initHandles()
dsDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsDesc.Texture2D.MipSlice = 0;
}
_handlesPerSlice[0].SetDSV(&dsDesc);
_handlesPerSlice[0].SetDSV(dsDesc);
}
if (useRTV)
{
@@ -530,7 +559,7 @@ void GPUTextureDX12::initHandles()
rtDesc.Texture2D.MipSlice = 0;
rtDesc.Texture2D.PlaneSlice = 0;
}
_handlesPerSlice[0].SetRTV(&rtDesc);
_handlesPerSlice[0].SetRTV(rtDesc);
}
if (useSRV)
{
@@ -553,7 +582,7 @@ void GPUTextureDX12::initHandles()
srDesc.Texture2D.ResourceMinLODClamp = 0;
srDesc.Texture2D.PlaneSlice = 0;
}
_handlesPerSlice[0].SetSRV(&srDesc);
_handlesPerSlice[0].SetSRV(srDesc);
}
if (useUAV)
{
@@ -571,7 +600,7 @@ void GPUTextureDX12::initHandles()
uavDesc.Texture2D.MipSlice = 0;
uavDesc.Texture2D.PlaneSlice = 0;
}
_handlesPerSlice[0].SetUAV(&uavDesc);
_handlesPerSlice[0].SetUAV(uavDesc);
}
}
@@ -593,35 +622,63 @@ void GPUTextureDX12::initHandles()
// DSV
if (useDSV)
{
dsDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
dsDesc.Texture2DArray.ArraySize = 1;
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex;
dsDesc.Texture2DArray.MipSlice = mipIndex;
slice[mipIndex].SetDSV(&dsDesc);
if (isArray)
{
dsDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
dsDesc.Texture2DArray.ArraySize = 1;
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex;
dsDesc.Texture2DArray.MipSlice = mipIndex;
}
else
{
dsDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsDesc.Texture2D.MipSlice = mipIndex;
}
slice[mipIndex].SetDSV(dsDesc);
}
// RTV
if (useRTV)
{
rtDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
rtDesc.Texture2DArray.ArraySize = 1;
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex;
rtDesc.Texture2DArray.MipSlice = mipIndex;
rtDesc.Texture2DArray.PlaneSlice = 0;
slice[mipIndex].SetRTV(&rtDesc);
if (isArray)
{
rtDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
rtDesc.Texture2DArray.ArraySize = 1;
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex;
rtDesc.Texture2DArray.MipSlice = mipIndex;
rtDesc.Texture2DArray.PlaneSlice = 0;
}
else
{
rtDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtDesc.Texture2D.MipSlice = mipIndex;
rtDesc.Texture2D.PlaneSlice = 0;
}
slice[mipIndex].SetRTV(rtDesc);
}
// SRV
if (useSRV)
{
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
srDesc.Texture2DArray.ArraySize = 1;
srDesc.Texture2DArray.FirstArraySlice = arrayIndex;
srDesc.Texture2DArray.MipLevels = 1;
srDesc.Texture2DArray.MostDetailedMip = mipIndex;
srDesc.Texture2DArray.ResourceMinLODClamp = 0;
srDesc.Texture2DArray.PlaneSlice = 0;
slice[mipIndex].SetSRV(&srDesc);
if (isArray)
{
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
srDesc.Texture2DArray.ArraySize = 1;
srDesc.Texture2DArray.FirstArraySlice = arrayIndex;
srDesc.Texture2DArray.MipLevels = 1;
srDesc.Texture2DArray.MostDetailedMip = mipIndex;
srDesc.Texture2DArray.ResourceMinLODClamp = 0;
srDesc.Texture2DArray.PlaneSlice = 0;
}
else
{
srDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srDesc.Texture2D.MipLevels = 1;
srDesc.Texture2D.MostDetailedMip = mipIndex;
srDesc.Texture2D.ResourceMinLODClamp = 0;
srDesc.Texture2D.PlaneSlice = 0;
}
slice[mipIndex].SetSRV(srDesc);
}
}
}
@@ -652,7 +709,7 @@ void GPUTextureDX12::initHandles()
dsDesc.Flags = D3D12_DSV_FLAG_READ_ONLY_DEPTH;
if (PixelFormatExtensions::HasStencil(format))
dsDesc.Flags |= D3D12_DSV_FLAG_READ_ONLY_STENCIL;
_handleReadOnlyDepth.SetDSV(&dsDesc);
_handleReadOnlyDepth.SetDSV(dsDesc);
}
ASSERT(!useRTV);
if (useSRV)
@@ -676,7 +733,7 @@ void GPUTextureDX12::initHandles()
srDesc.Texture2D.ResourceMinLODClamp = 0;
srDesc.Texture2D.PlaneSlice = 0;
}
_handleReadOnlyDepth.SetSRV(&srDesc);
_handleReadOnlyDepth.SetSRV(srDesc);
}
}
}

View File

@@ -58,7 +58,7 @@ public:
/// <param name="format">Parent texture format</param>
/// <param name="msaa">Parent texture multi-sample level</param>
/// <param name="subresourceIndex">Used subresource index or -1 to cover whole resource.</param>
void Init(GPUResource* parent, GPUDeviceDX12* device, ResourceOwnerDX12* owner, PixelFormat format, MSAALevel msaa, int32 subresourceIndex = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)
void Init(GPUResource* parent, GPUDeviceDX12* device, ResourceOwnerDX12* owner, PixelFormat format, MSAALevel msaa, int32 subresourceIndex = -1)
{
GPUTextureView::Init(parent, format, msaa);
SubresourceIndex = subresourceIndex;
@@ -69,80 +69,14 @@ public:
/// <summary>
/// Releases the view.
/// </summary>
void Release()
{
_rtv.Release();
_srv.Release();
_dsv.Release();
_uav.Release();
}
void Release();
public:
/// <summary>
/// Sets the render target view.
/// </summary>
/// <param name="rtvDesc">The RTV desc.</param>
void SetRTV(D3D12_RENDER_TARGET_VIEW_DESC* rtvDesc)
{
if (rtvDesc)
{
_rtv.CreateRTV(_device, _owner->GetResource(), rtvDesc);
}
else
{
_rtv.Release();
}
}
/// <summary>
/// Sets the shader resource view.
/// </summary>
/// <param name="srvDesc">The SRV desc.</param>
void SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC* srvDesc)
{
if (srvDesc)
{
_srv.CreateSRV(_device, _owner->GetResource(), srvDesc);
}
else
{
_srv.Release();
}
}
/// <summary>
/// Sets the depth stencil view.
/// </summary>
/// <param name="dsvDesc">The DSV desc.</param>
void SetDSV(D3D12_DEPTH_STENCIL_VIEW_DESC* dsvDesc)
{
if (dsvDesc)
{
_dsv.CreateDSV(_device, _owner->GetResource(), dsvDesc);
}
else
{
_dsv.Release();
}
}
/// <summary>
/// Sets the unordered access view.
/// </summary>
/// <param name="uavDesc">The UAV desc.</param>
/// <param name="counterResource">The counter buffer resource.</param>
void SetUAV(D3D12_UNORDERED_ACCESS_VIEW_DESC* uavDesc, ID3D12Resource* counterResource = nullptr)
{
if (uavDesc)
{
_uav.CreateUAV(_device, _owner->GetResource(), uavDesc, counterResource);
}
else
{
_uav.Release();
}
}
void SetRTV(D3D12_RENDER_TARGET_VIEW_DESC& rtvDesc);
void SetSRV(D3D12_SHADER_RESOURCE_VIEW_DESC& srvDesc);
void SetDSV(D3D12_DEPTH_STENCIL_VIEW_DESC& dsvDesc);
void SetUAV(D3D12_UNORDERED_ACCESS_VIEW_DESC& uavDesc, ID3D12Resource* counterResource = nullptr);
public:

View File

@@ -15,7 +15,7 @@ class IShaderResourceDX12
public:
IShaderResourceDX12()
: SubresourceIndex(D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)
: SubresourceIndex(-1)
{
}
@@ -28,8 +28,11 @@ public:
/// <summary>
/// Affected subresource index or -1 if use whole resource.
/// This solves only resource states tracking per single subresource, not subresources range, if need to here should be range of subresources (for texture arrays, volume textures and cubemaps).
/// </summary>
int32 SubresourceIndex; // Note: this solves only resource states tracking per single subresource, not subresources range, if need to here should be range of subresources (for texture arrays, volume textures and cubemaps)
int32 SubresourceIndex;
D3D12_SRV_DIMENSION SrvDimension = D3D12_SRV_DIMENSION_UNKNOWN;
public: