| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "NvCoDx12CircularResourceHeap.h" |
| |
|
| | namespace nvidia { |
| | namespace Common { |
| |
|
| | Dx12CircularResourceHeap::Dx12CircularResourceHeap(): |
| | m_fence(nullptr), |
| | m_device(nullptr), |
| | m_blockFreeList(sizeof(Block), __alignof(Block), 16), |
| | m_blocks(nullptr) |
| | { |
| | m_back.m_block = nullptr; |
| | m_back.m_position = nullptr; |
| | m_front.m_block = nullptr; |
| | m_front.m_position = nullptr; |
| | } |
| |
|
| | Dx12CircularResourceHeap::~Dx12CircularResourceHeap() |
| | { |
| | _freeBlockListResources(m_blocks); |
| | } |
| |
|
| | void Dx12CircularResourceHeap::_freeBlockListResources(const Block* start) |
| | { |
| | if (start) |
| | { |
| | { |
| | ID3D12Resource* resource = start->m_resource; |
| | resource->Unmap(0, nullptr); |
| | resource->Release(); |
| | } |
| | for (Block* block = start->m_next; block != start; block = block->m_next) |
| | { |
| | ID3D12Resource* resource = block->m_resource; |
| | resource->Unmap(0, nullptr); |
| | resource->Release(); |
| | } |
| | } |
| | } |
| |
|
| | int Dx12CircularResourceHeap::init(ID3D12Device* device, const Desc& desc, Dx12CounterFence* fence) |
| | { |
| | assert(m_blocks == nullptr); |
| | assert(desc.m_blockSize > 0); |
| |
|
| | m_fence = fence; |
| | m_desc = desc; |
| | m_device = device; |
| |
|
| | return NV_OK; |
| | } |
| |
|
| | void Dx12CircularResourceHeap::addSync(uint64_t signalValue) |
| | { |
| | assert(signalValue == m_fence->getCurrentValue()); |
| | PendingEntry entry; |
| | entry.m_completedValue = signalValue; |
| | entry.m_cursor = m_front; |
| | m_pendingQueue.push_back(entry); |
| | } |
| |
|
| | void Dx12CircularResourceHeap::updateCompleted() |
| | { |
| | const uint64_t completedValue = m_fence->getCompletedValue(); |
| | while (!m_pendingQueue.empty()) |
| | { |
| | const PendingEntry& entry = m_pendingQueue.front(); |
| | if (entry.m_completedValue <= completedValue) |
| | { |
| | m_back = entry.m_cursor; |
| | m_pendingQueue.pop_front(); |
| | } |
| | else |
| | { |
| | break; |
| | } |
| | } |
| | } |
| |
|
| | Dx12CircularResourceHeap::Block* Dx12CircularResourceHeap::_newBlock() |
| | { |
| | D3D12_RESOURCE_DESC desc; |
| |
|
| | desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; |
| | desc.Alignment = 0; |
| | desc.Width = m_desc.m_blockSize; |
| | desc.Height = 1; |
| | desc.DepthOrArraySize = 1; |
| | desc.MipLevels = 1; |
| | desc.Format = DXGI_FORMAT_UNKNOWN; |
| | desc.SampleDesc.Count = 1; |
| | desc.SampleDesc.Quality = 0; |
| | desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; |
| | desc.Flags = D3D12_RESOURCE_FLAG_NONE; |
| |
|
| | ComPtr<ID3D12Resource> resource; |
| | int res = m_device->CreateCommittedResource(&m_desc.m_heapProperties, m_desc.m_heapFlags, &desc, m_desc.m_initialState, nullptr, IID_PPV_ARGS(&resource)); |
| | if (NV_FAILED(res)) |
| | { |
| | printf("Resource allocation failed"); |
| | return nullptr; |
| | } |
| |
|
| | uint8_t* data = nullptr; |
| | if (m_desc.m_heapProperties.Type == D3D12_HEAP_TYPE_READBACK) |
| | { |
| | } |
| | else |
| | { |
| | |
| | resource->Map(0, nullptr, (void**)&data); |
| | } |
| |
|
| | |
| | Block* block = (Block*)m_blockFreeList.allocate(); |
| | block->m_next = nullptr; |
| |
|
| | block->m_resource = resource.Detach(); |
| | block->m_start = data; |
| | return block; |
| | } |
| |
|
| | Dx12CircularResourceHeap::Cursor Dx12CircularResourceHeap::allocate(size_t size, size_t alignment) |
| | { |
| | const size_t blockSize = getBlockSize(); |
| |
|
| | assert(size <= blockSize); |
| |
|
| | |
| | if (m_blocks == nullptr) |
| | { |
| | Block* block = _newBlock(); |
| | if (!block) |
| | { |
| | Cursor cursor = {}; |
| | return cursor; |
| | } |
| | m_blocks = block; |
| | |
| | block->m_next = block; |
| |
|
| | |
| | m_back = { block, block->m_start }; |
| | m_front = m_back; |
| | } |
| |
|
| | |
| | |
| | Block* block = m_front.m_block; |
| |
|
| | |
| | assert(block != m_back.m_block || m_front.m_position >= m_back.m_position); |
| |
|
| | { |
| | uint8_t* cur = (uint8_t*)((size_t(m_front.m_position) + alignment - 1) & ~(alignment - 1)); |
| | |
| | if (cur + size <= block->m_start + blockSize) |
| | { |
| | |
| | |
| | m_front.m_position = cur + size; |
| | Cursor cursor = { block, cur }; |
| | return cursor; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | if (block->m_next == m_back.m_block) |
| | { |
| | Block* newBlock = _newBlock(); |
| | |
| | newBlock->m_next = block->m_next; |
| | block->m_next = newBlock; |
| | } |
| | |
| | |
| | block = block->m_next; |
| | uint8_t* cur = (uint8_t*)((size_t(block->m_start) + alignment - 1) & ~(alignment - 1)); |
| | |
| | if (cur + size > block->m_start + blockSize) |
| | { |
| | printf("Couldn't fit into a free block(!) Alignment breaks it?"); |
| | Cursor cursor = {}; |
| | return cursor; |
| | } |
| | |
| | |
| | m_front.m_block = block; |
| | m_front.m_position = cur + size; |
| | Cursor cursor = { block, cur }; |
| | return cursor; |
| | } |
| |
|
| | } |
| | } |
| |
|