// Copyright 2017 The Dawn 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 "dawn_native/d3d12/DescriptorHeapAllocator.h" #include "common/Assert.h" #include "dawn_native/d3d12/DeviceD3D12.h" namespace dawn_native { namespace d3d12 { DescriptorHeapHandle::DescriptorHeapHandle() : mDescriptorHeap(nullptr), mSizeIncrement(0), mOffset(0) { } DescriptorHeapHandle::DescriptorHeapHandle(ComPtr descriptorHeap, uint32_t sizeIncrement, uint32_t offset) : mDescriptorHeap(descriptorHeap), mSizeIncrement(sizeIncrement), mOffset(offset) { } ID3D12DescriptorHeap* DescriptorHeapHandle::Get() const { return mDescriptorHeap.Get(); } D3D12_CPU_DESCRIPTOR_HANDLE DescriptorHeapHandle::GetCPUHandle(uint32_t index) const { ASSERT(mDescriptorHeap); auto handle = mDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); handle.ptr += mSizeIncrement * (index + mOffset); return handle; } D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeapHandle::GetGPUHandle(uint32_t index) const { ASSERT(mDescriptorHeap); auto handle = mDescriptorHeap->GetGPUDescriptorHandleForHeapStart(); handle.ptr += mSizeIncrement * (index + mOffset); return handle; } DescriptorHeapAllocator::DescriptorHeapAllocator(Device* device) : mDevice(device), mSizeIncrements{ 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), } { } ResultOrError DescriptorHeapAllocator::Allocate( D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count, uint32_t allocationSize, DescriptorHeapInfo* heapInfo, D3D12_DESCRIPTOR_HEAP_FLAGS flags) { const Serial pendingSerial = mDevice->GetPendingCommandSerial(); size_t startOffset = (heapInfo->heap == nullptr) ? RingBufferAllocator::kInvalidOffset : heapInfo->allocator.Allocate(count, pendingSerial); if (startOffset != RingBufferAllocator::kInvalidOffset) { return DescriptorHeapHandle{heapInfo->heap, mSizeIncrements[type], static_cast(startOffset)}; } // If the pool has no more space, replace the pool with a new one of the specified size D3D12_DESCRIPTOR_HEAP_DESC heapDescriptor; heapDescriptor.Type = type; heapDescriptor.NumDescriptors = allocationSize; heapDescriptor.Flags = flags; heapDescriptor.NodeMask = 0; ComPtr heap; if (FAILED(mDevice->GetD3D12Device()->CreateDescriptorHeap(&heapDescriptor, IID_PPV_ARGS(&heap)))) { return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate heap"); } mDevice->ReferenceUntilUnused(heap); *heapInfo = {heap, RingBufferAllocator(allocationSize)}; startOffset = heapInfo->allocator.Allocate(count, pendingSerial); ASSERT(startOffset != RingBufferAllocator::kInvalidOffset); return DescriptorHeapHandle(heap, mSizeIncrements[type], startOffset); } ResultOrError DescriptorHeapAllocator::AllocateCPUHeap( D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count) { return Allocate(type, count, count, &mCpuDescriptorHeapInfos[type], D3D12_DESCRIPTOR_HEAP_FLAG_NONE); } ResultOrError DescriptorHeapAllocator::AllocateGPUHeap( D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count) { ASSERT(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); unsigned int heapSize = (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1 : D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE); return Allocate(type, count, heapSize, &mGpuDescriptorHeapInfos[type], D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); } void DescriptorHeapAllocator::Deallocate(uint64_t lastCompletedSerial) { for (uint32_t i = 0; i < mCpuDescriptorHeapInfos.size(); i++) { if (mCpuDescriptorHeapInfos[i].heap != nullptr) { mCpuDescriptorHeapInfos[i].allocator.Deallocate(lastCompletedSerial); } } for (uint32_t i = 0; i < mGpuDescriptorHeapInfos.size(); i++) { if (mGpuDescriptorHeapInfos[i].heap != nullptr) { mGpuDescriptorHeapInfos[i].allocator.Deallocate(lastCompletedSerial); } } } }} // namespace dawn_native::d3d12