blob: e38a65a953754c77d999e2ca6bc6f2a1d76899c2 [file] [log] [blame]
// Copyright 2017 The NXT Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "DescriptorHeapAllocator.h"
#include "D3D12Backend.h"
namespace backend {
namespace d3d12 {
DescriptorHeapHandle::DescriptorHeapHandle() {
}
DescriptorHeapHandle::DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap, uint32_t sizeIncrement, uint32_t offset)
: device(device), descriptorHeap(descriptorHeap), sizeIncrement(sizeIncrement), offset(offset) {
}
ID3D12DescriptorHeap* DescriptorHeapHandle::Get() const {
return descriptorHeap.Get();
}
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorHeapHandle::GetCPUHandle(uint32_t index) const {
ASSERT(descriptorHeap);
auto handle = descriptorHeap->GetCPUDescriptorHandleForHeapStart();
handle.ptr += sizeIncrement * (index + offset);
return handle;
}
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeapHandle::GetGPUHandle(uint32_t index) const {
ASSERT(descriptorHeap);
auto handle = descriptorHeap->GetGPUDescriptorHandleForHeapStart();
handle.ptr += sizeIncrement * (index + offset);
return handle;
}
DescriptorHeapAllocator::DescriptorHeapAllocator(Device* device)
: device(device),
sizeIncrements {
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER),
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV),
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV),
} {
}
DescriptorHeapHandle DescriptorHeapAllocator::Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count) {
if (count == 0) {
return DescriptorHeapHandle();
}
auto& pools = descriptorHeapPools[type];
for (auto it : pools) {
auto& allocationInfo = it.second;
if (allocationInfo.remaining >= count) {
DescriptorHeapHandle handle(it.first, sizeIncrements[type], allocationInfo.size - allocationInfo.remaining);
allocationInfo.remaining -= count;
Release(handle);
return handle;
}
}
ASSERT(count <= 2048); // TODO(enga@google.com): Have a very large CPU heap that's copied to GPU-visible heaps
uint32_t descriptorHeapSize = 2048; // TODO(enga@google.com): Allocate much more and use this as a pool
D3D12_DESCRIPTOR_HEAP_DESC heapDescriptor;
heapDescriptor.Type = type;
heapDescriptor.NumDescriptors = descriptorHeapSize;
heapDescriptor.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
heapDescriptor.NodeMask = 0;
ComPtr<ID3D12DescriptorHeap> heap;
ASSERT_SUCCESS(device->GetD3D12Device()->CreateDescriptorHeap(&heapDescriptor, IID_PPV_ARGS(&heap)));
AllocationInfo allocationInfo = { descriptorHeapSize, descriptorHeapSize - count };
pools.emplace_back(std::make_pair(heap, allocationInfo));
DescriptorHeapHandle handle(heap, sizeIncrements[type], 0);
Release(handle);
return handle;
}
void DescriptorHeapAllocator::FreeDescriptorHeaps(uint64_t lastCompletedSerial) {
releasedHandles.ClearUpTo(lastCompletedSerial);
}
void DescriptorHeapAllocator::Release(DescriptorHeapHandle handle) {
releasedHandles.Enqueue(handle, device->GetSerial());
}
}
}