#ifndef D3d12DescriptorHeap_h__ #define D3d12DescriptorHeap_h__ #include #include "d3d11_helper.h" #include "FatalError.h" #include #include "ForwardListItem.h" #include using namespace Microsoft::WRL; class D3d12DescriptorHeapAllocator { public: //Assuming that heap is EMPTY! D3d12DescriptorHeapAllocator(ComPtr heap):_heap(heap) { _descriptor = heap->GetDesc(); _heapStartAddress = heap->GetCPUDescriptorHandleForHeapStart().ptr; ID3D12DevicePtr device; heap->GetDevice(IID_PPV_ARGS(&device)); _itemSize = device->GetDescriptorHandleIncrementSize(_descriptor.Type); _items.resize(_descriptor.NumDescriptors); //init free items list for(size_t i = 0; i < _descriptor.NumDescriptors - 1; ++i){ _items[i].next = &_items[i + 1]; } _items[_descriptor.NumDescriptors - 1].next = nullptr; _listHead = &_items[0]; } D3D12_CPU_DESCRIPTOR_HANDLE alloc(){ if(_listHead == nullptr){ return {0}; } auto allocatedId = getItemIndex(_listHead); auto resultAddress = _heapStartAddress + (allocatedId * _itemSize); _listHead = _listHead->next; return{ resultAddress }; } void free(D3D12_CPU_DESCRIPTOR_HANDLE handle){ auto itemId = getDescriptorId(handle); if (itemId >= _items.size()) { throw std::exception("Invalid handle"); } auto freeItem = &_items[itemId]; freeItem->next = _listHead; _listHead = freeItem; } ComPtr getHeap() { return _heap; } size_t getItemSize() const { return _itemSize; } size_t getDescriptorId(D3D12_CPU_DESCRIPTOR_HANDLE handle) const { if (handle.ptr < _heapStartAddress) { throw std::exception("Invalid handle"); } return (handle.ptr - _heapStartAddress) / _itemSize; } size_t getDescriptorsCount() const { return _descriptor.NumDescriptors; } private: size_t getItemIndex(const ForwardListItem* item) const noexcept{ return (item - &_items[0]); } ComPtr _heap; ForwardListItem* _listHead = nullptr; std::vector _items; D3D12_DESCRIPTOR_HEAP_DESC _descriptor; size_t _itemSize; size_t _heapStartAddress; }; #endif // D3d12DescriptorHeap_h__