DirectXTK12/Src/DescriptorHeap.cpp

231 строка
6.6 KiB
C++

//--------------------------------------------------------------------------------------
// File: DescriptorHeap.cpp
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
// http://go.microsoft.com/fwlink/?LinkID=615561
//--------------------------------------------------------------------------------------
#include "pch.h"
#include "PlatformHelpers.h"
#include "DirectXHelpers.h"
#include "DescriptorHeap.h"
using namespace DirectX;
using Microsoft::WRL::ComPtr;
namespace
{
struct DescriptorHeapDesc
{
D3D12_DESCRIPTOR_HEAP_TYPE Type;
D3D12_DESCRIPTOR_HEAP_FLAGS Flags;
};
static const DescriptorHeapDesc c_DescriptorHeapDescs[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES] =
{
{ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE },
{ D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE },
{ D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE },
{ D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE }
};
}
_Use_decl_annotations_
DescriptorHeap::DescriptorHeap(
ID3D12DescriptorHeap* pExistingHeap) noexcept
: m_pHeap(pExistingHeap)
{
#if defined(_MSC_VER) || !defined(_WIN32)
m_hCPU = pExistingHeap->GetCPUDescriptorHandleForHeapStart();
m_hGPU = pExistingHeap->GetGPUDescriptorHandleForHeapStart();
m_desc = pExistingHeap->GetDesc();
#else
std::ignore = pExistingHeap->GetCPUDescriptorHandleForHeapStart(&m_hCPU);
std::ignore = pExistingHeap->GetGPUDescriptorHandleForHeapStart(&m_hGPU);
std::ignore = pExistingHeap->GetDesc(&m_desc);
#endif
ComPtr<ID3D12Device> device;
pExistingHeap->GetDevice(IID_GRAPHICS_PPV_ARGS(device.GetAddressOf()));
m_increment = device->GetDescriptorHandleIncrementSize(m_desc.Type);
}
_Use_decl_annotations_
DescriptorHeap::DescriptorHeap(
ID3D12Device* device,
const D3D12_DESCRIPTOR_HEAP_DESC* pDesc) noexcept(false) :
m_desc{},
m_hCPU{},
m_hGPU{},
m_increment(0)
{
Create(device, pDesc);
}
_Use_decl_annotations_
DescriptorHeap::DescriptorHeap(
ID3D12Device* device,
D3D12_DESCRIPTOR_HEAP_TYPE type,
D3D12_DESCRIPTOR_HEAP_FLAGS flags,
size_t count) noexcept(false) :
m_desc{},
m_hCPU{},
m_hGPU{},
m_increment(0)
{
if (count > UINT32_MAX)
throw std::invalid_argument("Too many descriptors");
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
desc.Flags = flags;
desc.NumDescriptors = static_cast<UINT>(count);
desc.Type = type;
Create(device, &desc);
}
_Use_decl_annotations_
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::WriteDescriptors(
ID3D12Device* device,
uint32_t offsetIntoHeap,
uint32_t totalDescriptorCount,
const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptorRangeStarts,
const uint32_t* pDescriptorRangeSizes,
uint32_t descriptorRangeCount)
{
assert((size_t(offsetIntoHeap) + size_t(totalDescriptorCount)) <= size_t(m_desc.NumDescriptors));
const D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = GetCpuHandle(offsetIntoHeap);
device->CopyDescriptors(
1,
&cpuHandle,
&totalDescriptorCount,
descriptorRangeCount,
pDescriptorRangeStarts,
pDescriptorRangeSizes,
m_desc.Type);
auto gpuHandle = GetGpuHandle(offsetIntoHeap);
return gpuHandle;
}
_Use_decl_annotations_
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::WriteDescriptors(
ID3D12Device* device,
uint32_t offsetIntoHeap,
const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptorRangeStarts,
const uint32_t* pDescriptorRangeSizes,
uint32_t descriptorRangeCount)
{
uint32_t totalDescriptorCount = 0;
for (uint32_t i = 0; i < descriptorRangeCount; ++i)
totalDescriptorCount += pDescriptorRangeSizes[i];
return WriteDescriptors(
device,
offsetIntoHeap,
totalDescriptorCount,
pDescriptorRangeStarts,
pDescriptorRangeSizes,
descriptorRangeCount);
}
_Use_decl_annotations_
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::WriteDescriptors(
ID3D12Device* device,
uint32_t offsetIntoHeap,
const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptors,
uint32_t descriptorCount)
{
return WriteDescriptors(
device,
offsetIntoHeap,
descriptorCount,
pDescriptors,
&descriptorCount,
1);
}
_Use_decl_annotations_
void DescriptorHeap::Create(
ID3D12Device* pDevice,
const D3D12_DESCRIPTOR_HEAP_DESC* pDesc)
{
assert(pDesc != nullptr);
m_desc = *pDesc;
m_increment = pDevice->GetDescriptorHandleIncrementSize(pDesc->Type);
if (pDesc->NumDescriptors == 0)
{
m_pHeap.Reset();
m_hCPU.ptr = 0;
m_hGPU.ptr = 0;
}
else
{
ThrowIfFailed(pDevice->CreateDescriptorHeap(
pDesc,
IID_GRAPHICS_PPV_ARGS(m_pHeap.ReleaseAndGetAddressOf())));
SetDebugObjectName(m_pHeap.Get(), L"DescriptorHeap");
#if defined(_MSC_VER) || !defined(_WIN32)
m_hCPU = m_pHeap->GetCPUDescriptorHandleForHeapStart();
if (pDesc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
{
m_hGPU = m_pHeap->GetGPUDescriptorHandleForHeapStart();
}
#else
std::ignore = m_pHeap->GetCPUDescriptorHandleForHeapStart(&m_hCPU);
if (pDesc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
{
std::ignore = m_pHeap->GetGPUDescriptorHandleForHeapStart(&m_hGPU);
}
#endif
}
}
_Use_decl_annotations_
void DescriptorHeap::DefaultDesc(
D3D12_DESCRIPTOR_HEAP_TYPE type,
D3D12_DESCRIPTOR_HEAP_DESC* pDesc) noexcept
{
assert(c_DescriptorHeapDescs[type].Type == type);
pDesc->Flags = c_DescriptorHeapDescs[type].Flags;
pDesc->NumDescriptors = 0;
pDesc->Type = type;
}
//======================================================================================
// DescriptorPile
//======================================================================================
void DescriptorPile::AllocateRange(size_t numDescriptors, _Out_ IndexType& start, _Out_ IndexType& end)
{
// make sure we didn't allocate zero
if (numDescriptors == 0)
{
throw std::invalid_argument("Can't allocate zero descriptors");
}
// get the current top
start = m_top;
// increment top with new request
m_top += numDescriptors;
end = m_top;
// make sure we have enough room
if (m_top > Count())
{
DebugTrace("DescriptorPile has %zu of %zu descriptors; failed request for %zu more\n", start, Count(), numDescriptors);
throw std::runtime_error("Can't allocate more descriptors");
}
}