// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #if GRAPHICS_API_DIRECTX12 #include "CommandAllocatorPoolDX12.h" #include "GPUDeviceDX12.h" #include "Engine/Threading/Threading.h" #include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h" CommandAllocatorPoolDX12::CommandAllocatorPoolDX12(GPUDeviceDX12* device, D3D12_COMMAND_LIST_TYPE type) : _type(type) , _device(device) { } CommandAllocatorPoolDX12::~CommandAllocatorPoolDX12() { Release(); } ID3D12CommandAllocator* CommandAllocatorPoolDX12::RequestAllocator(uint64 completedFenceValue) { ScopeLock lock(_locker); ID3D12CommandAllocator* allocator = nullptr; if (_ready.HasItems()) { PoolPair& firstPair = _ready.First(); if (firstPair.First <= completedFenceValue) { allocator = firstPair.Second; VALIDATE_DIRECTX_CALL(allocator->Reset()); _ready.RemoveAtKeepOrder(0); } } // If no allocators were ready to be reused, create a new one if (allocator == nullptr) { VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommandAllocator(_type, IID_PPV_ARGS(&allocator))); #if GPU_ENABLE_RESOURCE_NAMING Char name[32]; swprintf(name, 32, L"CommandAllocator %u", _pool.Count()); allocator->SetName(name); #endif _pool.Add(allocator); } return allocator; } void CommandAllocatorPoolDX12::DiscardAllocator(uint64 fenceValue, ID3D12CommandAllocator* allocator) { ScopeLock lock(_locker); // That fence value indicates we are free to reset the allocator _ready.Add(PoolPair(fenceValue, allocator)); } void CommandAllocatorPoolDX12::Release() { for (int32 i = 0; i < _pool.Count(); i++) { DX_SAFE_RELEASE_CHECK(_pool[i], 0); } _pool.Clear(); } #endif