Preliminary changes to Vulkan memory suballocation
This mostly makes the MemoryAllocator not owned by the BuddyResourceAllocator so that we don't need an extra class for the dependency injection in the Vulkan backend. (the container for the BuddyMemoryAllocator can be it's MemoryAllocator at the same time). Also renames methods of MemoryAllocator to be more explicit. Also renames the constructor parameter of BuddyMemoryAllocator to be (subjectively) closer to what the represent. BUG=dawn:27 Change-Id: I37355ad5b3cded143956f0adc4742fa1b717e9bc Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/12661 Reviewed-by: Bryan Bernhart <bryan.bernhart@intel.com> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
60a04dd18c
commit
ca35435716
2
BUILD.gn
2
BUILD.gn
|
@ -197,7 +197,6 @@ source_set("libdawn_native_sources") {
|
|||
"src/dawn_native/Forward.h",
|
||||
"src/dawn_native/Instance.cpp",
|
||||
"src/dawn_native/Instance.h",
|
||||
"src/dawn_native/MemoryAllocator.h",
|
||||
"src/dawn_native/ObjectBase.cpp",
|
||||
"src/dawn_native/ObjectBase.h",
|
||||
"src/dawn_native/PassResourceUsage.h",
|
||||
|
@ -226,6 +225,7 @@ source_set("libdawn_native_sources") {
|
|||
"src/dawn_native/RenderPipeline.cpp",
|
||||
"src/dawn_native/RenderPipeline.h",
|
||||
"src/dawn_native/ResourceHeap.h",
|
||||
"src/dawn_native/ResourceHeapAllocator.h",
|
||||
"src/dawn_native/ResourceMemoryAllocation.cpp",
|
||||
"src/dawn_native/ResourceMemoryAllocation.h",
|
||||
"src/dawn_native/RingBufferAllocator.cpp",
|
||||
|
|
|
@ -11,26 +11,30 @@
|
|||
// 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/BuddyMemoryAllocator.h"
|
||||
|
||||
#include "common/Math.h"
|
||||
#include "dawn_native/ResourceHeapAllocator.h"
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
BuddyMemoryAllocator::BuddyMemoryAllocator(uint64_t maxBlockSize,
|
||||
uint64_t memorySize,
|
||||
std::unique_ptr<MemoryAllocator> client)
|
||||
: mMemorySize(memorySize), mBuddyBlockAllocator(maxBlockSize), mClient(std::move(client)) {
|
||||
ASSERT(memorySize <= maxBlockSize);
|
||||
ASSERT(IsPowerOfTwo(mMemorySize));
|
||||
ASSERT(maxBlockSize % mMemorySize == 0);
|
||||
BuddyMemoryAllocator::BuddyMemoryAllocator(uint64_t maxSystemSize,
|
||||
uint64_t memoryBlockSize,
|
||||
ResourceHeapAllocator* heapAllocator)
|
||||
: mMemoryBlockSize(memoryBlockSize),
|
||||
mBuddyBlockAllocator(maxSystemSize),
|
||||
mHeapAllocator(heapAllocator) {
|
||||
ASSERT(memoryBlockSize <= maxSystemSize);
|
||||
ASSERT(IsPowerOfTwo(mMemoryBlockSize));
|
||||
ASSERT(maxSystemSize % mMemoryBlockSize == 0);
|
||||
|
||||
mTrackedSubAllocations.resize(maxBlockSize / mMemorySize);
|
||||
mTrackedSubAllocations.resize(maxSystemSize / mMemoryBlockSize);
|
||||
}
|
||||
|
||||
uint64_t BuddyMemoryAllocator::GetMemoryIndex(uint64_t offset) const {
|
||||
ASSERT(offset != BuddyAllocator::kInvalidOffset);
|
||||
return offset / mMemorySize;
|
||||
return offset / mMemoryBlockSize;
|
||||
}
|
||||
|
||||
ResultOrError<ResourceMemoryAllocation> BuddyMemoryAllocator::Allocate(uint64_t allocationSize,
|
||||
|
@ -45,7 +49,7 @@ namespace dawn_native {
|
|||
allocationSize = NextPowerOfTwo(allocationSize);
|
||||
|
||||
// Allocation cannot exceed the memory size.
|
||||
if (allocationSize > mMemorySize) {
|
||||
if (allocationSize > mMemoryBlockSize) {
|
||||
return invalidAllocation;
|
||||
}
|
||||
|
||||
|
@ -59,7 +63,7 @@ namespace dawn_native {
|
|||
if (mTrackedSubAllocations[memoryIndex].refcount == 0) {
|
||||
// Transfer ownership to this allocator
|
||||
std::unique_ptr<ResourceHeapBase> memory;
|
||||
DAWN_TRY_ASSIGN(memory, mClient->Allocate(mMemorySize));
|
||||
DAWN_TRY_ASSIGN(memory, mHeapAllocator->AllocateResourceHeap(mMemoryBlockSize));
|
||||
mTrackedSubAllocations[memoryIndex] = {/*refcount*/ 0, std::move(memory)};
|
||||
}
|
||||
|
||||
|
@ -70,11 +74,11 @@ namespace dawn_native {
|
|||
info.mMethod = AllocationMethod::kSubAllocated;
|
||||
|
||||
// Allocation offset is always local to the memory.
|
||||
const uint64_t memoryOffset = blockOffset % mMemorySize;
|
||||
const uint64_t memoryOffset = blockOffset % mMemoryBlockSize;
|
||||
|
||||
return ResourceMemoryAllocation{
|
||||
info, memoryOffset, mTrackedSubAllocations[memoryIndex].mMemoryAllocation.get()};
|
||||
} // namespace dawn_native
|
||||
}
|
||||
|
||||
void BuddyMemoryAllocator::Deallocate(const ResourceMemoryAllocation& allocation) {
|
||||
const AllocationInfo info = allocation.GetInfo();
|
||||
|
@ -84,18 +88,18 @@ namespace dawn_native {
|
|||
const uint64_t memoryIndex = GetMemoryIndex(info.mBlockOffset);
|
||||
|
||||
ASSERT(mTrackedSubAllocations[memoryIndex].refcount > 0);
|
||||
|
||||
mTrackedSubAllocations[memoryIndex].refcount--;
|
||||
|
||||
if (mTrackedSubAllocations[memoryIndex].refcount == 0) {
|
||||
mClient->Deallocate(std::move(mTrackedSubAllocations[memoryIndex].mMemoryAllocation));
|
||||
mHeapAllocator->DeallocateResourceHeap(
|
||||
std::move(mTrackedSubAllocations[memoryIndex].mMemoryAllocation));
|
||||
}
|
||||
|
||||
mBuddyBlockAllocator.Deallocate(info.mBlockOffset);
|
||||
}
|
||||
|
||||
uint64_t BuddyMemoryAllocator::GetMemorySize() const {
|
||||
return mMemorySize;
|
||||
uint64_t BuddyMemoryAllocator::GetMemoryBlockSize() const {
|
||||
return mMemoryBlockSize;
|
||||
}
|
||||
|
||||
uint64_t BuddyMemoryAllocator::ComputeTotalNumOfHeapsForTesting() const {
|
||||
|
@ -107,4 +111,5 @@ namespace dawn_native {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
} // namespace dawn_native
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -15,13 +15,16 @@
|
|||
#ifndef DAWNNATIVE_BUDDYMEMORYALLOCATOR_H_
|
||||
#define DAWNNATIVE_BUDDYMEMORYALLOCATOR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "dawn_native/BuddyAllocator.h"
|
||||
#include "dawn_native/MemoryAllocator.h"
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/ResourceMemoryAllocation.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
class ResourceHeapAllocator;
|
||||
|
||||
// BuddyMemoryAllocator uses the buddy allocator to sub-allocate blocks of device
|
||||
// memory created by MemoryAllocator clients. It creates a very large buddy system
|
||||
// where backing device memory blocks equal a specified level in the system.
|
||||
|
@ -31,23 +34,20 @@ namespace dawn_native {
|
|||
// same memory index, the memory refcount is incremented to ensure de-allocating one doesn't
|
||||
// release the other prematurely.
|
||||
//
|
||||
// The device will only create up to Log2(kMaxResourceSize) allocators and can prefer speed
|
||||
// over memory footprint by selecting an allocator with a higher memory threshold which results
|
||||
// in pre-allocating more memory.
|
||||
//
|
||||
// The resource allocation is guaranteed by the device to have compatible memory flags.
|
||||
// The MemoryAllocator should return ResourceHeaps that are all compatible with each other.
|
||||
// It should also outlive all the resources that are in the buddy allocator.
|
||||
class BuddyMemoryAllocator {
|
||||
public:
|
||||
BuddyMemoryAllocator(uint64_t maxBlockSize,
|
||||
uint64_t memorySize,
|
||||
std::unique_ptr<MemoryAllocator> client);
|
||||
BuddyMemoryAllocator(uint64_t maxSystemSize,
|
||||
uint64_t memoryBlockSize,
|
||||
ResourceHeapAllocator* heapAllocator);
|
||||
~BuddyMemoryAllocator() = default;
|
||||
|
||||
ResultOrError<ResourceMemoryAllocation> Allocate(uint64_t allocationSize,
|
||||
uint64_t alignment);
|
||||
void Deallocate(const ResourceMemoryAllocation& allocation);
|
||||
|
||||
uint64_t GetMemorySize() const;
|
||||
uint64_t GetMemoryBlockSize() const;
|
||||
|
||||
// For testing purposes.
|
||||
uint64_t ComputeTotalNumOfHeapsForTesting() const;
|
||||
|
@ -55,10 +55,10 @@ namespace dawn_native {
|
|||
private:
|
||||
uint64_t GetMemoryIndex(uint64_t offset) const;
|
||||
|
||||
uint64_t mMemorySize = 0;
|
||||
uint64_t mMemoryBlockSize = 0;
|
||||
|
||||
BuddyAllocator mBuddyBlockAllocator;
|
||||
std::unique_ptr<MemoryAllocator> mClient;
|
||||
ResourceHeapAllocator* mHeapAllocator;
|
||||
|
||||
struct TrackedSubAllocations {
|
||||
size_t refcount = 0;
|
||||
|
@ -67,6 +67,7 @@ namespace dawn_native {
|
|||
|
||||
std::vector<TrackedSubAllocations> mTrackedSubAllocations;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
||||
#endif // DAWNNATIVE_BUDDYMEMORYALLOCATOR_H_
|
||||
|
|
|
@ -12,21 +12,24 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef DAWNNATIVE_MEMORYALLOCATOR_H_
|
||||
#define DAWNNATIVE_MEMORYALLOCATOR_H_
|
||||
#ifndef DAWNNATIVE_RESOURCEHEAPALLOCATOR_H_
|
||||
#define DAWNNATIVE_RESOURCEHEAPALLOCATOR_H_
|
||||
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/ResourceHeap.h"
|
||||
|
||||
namespace dawn_native {
|
||||
// Interface for backend allocators that create physical device memory.
|
||||
class MemoryAllocator {
|
||||
public:
|
||||
virtual ~MemoryAllocator() = default;
|
||||
|
||||
virtual ResultOrError<std::unique_ptr<ResourceHeapBase>> Allocate(uint64_t size) = 0;
|
||||
virtual void Deallocate(std::unique_ptr<ResourceHeapBase> allocation) = 0;
|
||||
// Interface for backend allocators that create memory heaps resoruces can be suballocated in.
|
||||
class ResourceHeapAllocator {
|
||||
public:
|
||||
virtual ~ResourceHeapAllocator() = default;
|
||||
|
||||
virtual ResultOrError<std::unique_ptr<ResourceHeapBase>> AllocateResourceHeap(
|
||||
uint64_t size) = 0;
|
||||
virtual void DeallocateResourceHeap(std::unique_ptr<ResourceHeapBase> allocation) = 0;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
||||
#endif // DAWNNATIVE_MEMORYALLOCATOR_H_
|
||||
#endif // DAWNNATIVE_RESOURCEHEAPALLOCATOR_H_
|
|
@ -71,4 +71,4 @@ namespace dawn_native {
|
|||
};
|
||||
} // namespace dawn_native
|
||||
|
||||
#endif // DAWNNATIVE_RESOURCEMEMORYALLOCATION_H_
|
||||
#endif // DAWNNATIVE_RESOURCEMEMORYALLOCATION_H_
|
||||
|
|
|
@ -24,7 +24,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
: mDevice(device), mHeapType(heapType), mHeapFlags(heapFlags) {
|
||||
}
|
||||
|
||||
ResultOrError<std::unique_ptr<ResourceHeapBase>> HeapAllocator::Allocate(uint64_t size) {
|
||||
ResultOrError<std::unique_ptr<ResourceHeapBase>> HeapAllocator::AllocateResourceHeap(
|
||||
uint64_t size) {
|
||||
D3D12_HEAP_DESC heapDesc;
|
||||
heapDesc.SizeInBytes = size;
|
||||
heapDesc.Properties.Type = mHeapType;
|
||||
|
@ -47,8 +48,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
return {std::make_unique<Heap>(std::move(heap))};
|
||||
}
|
||||
|
||||
void HeapAllocator::Deallocate(std::unique_ptr<ResourceHeapBase> heap) {
|
||||
void HeapAllocator::DeallocateResourceHeap(std::unique_ptr<ResourceHeapBase> heap) {
|
||||
mDevice->ReferenceUntilUnused(static_cast<Heap*>(heap.get())->GetD3D12Heap());
|
||||
}
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#ifndef DAWNNATIVE_D3D12_HEAPALLOCATORD3D12_H_
|
||||
#define DAWNNATIVE_D3D12_HEAPALLOCATORD3D12_H_
|
||||
|
||||
#include "dawn_native/MemoryAllocator.h"
|
||||
#include "dawn_native/ResourceHeapAllocator.h"
|
||||
#include "dawn_native/d3d12/d3d12_platform.h"
|
||||
|
||||
namespace dawn_native { namespace d3d12 {
|
||||
|
@ -23,13 +23,14 @@ namespace dawn_native { namespace d3d12 {
|
|||
class Device;
|
||||
|
||||
// Wrapper to allocate a D3D12 heap.
|
||||
class HeapAllocator : public MemoryAllocator {
|
||||
class HeapAllocator : public ResourceHeapAllocator {
|
||||
public:
|
||||
HeapAllocator(Device* device, D3D12_HEAP_TYPE heapType, D3D12_HEAP_FLAGS heapFlags);
|
||||
~HeapAllocator() override = default;
|
||||
|
||||
ResultOrError<std::unique_ptr<ResourceHeapBase>> Allocate(uint64_t size) override;
|
||||
void Deallocate(std::unique_ptr<ResourceHeapBase> allocation) override;
|
||||
ResultOrError<std::unique_ptr<ResourceHeapBase>> AllocateResourceHeap(
|
||||
uint64_t size) override;
|
||||
void DeallocateResourceHeap(std::unique_ptr<ResourceHeapBase> allocation) override;
|
||||
|
||||
private:
|
||||
Device* mDevice;
|
||||
|
@ -39,4 +40,4 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
||||
#endif // DAWNNATIVE_D3D12_HEAPALLOCATORD3D12_H_
|
||||
#endif // DAWNNATIVE_D3D12_HEAPALLOCATORD3D12_H_
|
||||
|
|
|
@ -91,10 +91,10 @@ namespace dawn_native { namespace d3d12 {
|
|||
ResourceAllocatorManager::ResourceAllocatorManager(Device* device) : mDevice(device) {
|
||||
for (uint32_t i = 0; i < ResourceHeapKind::EnumCount; i++) {
|
||||
const ResourceHeapKind resourceHeapKind = static_cast<ResourceHeapKind>(i);
|
||||
mHeapAllocators[i] = std::make_unique<HeapAllocator>(
|
||||
mDevice, GetD3D12HeapType(resourceHeapKind), GetD3D12HeapFlags(resourceHeapKind));
|
||||
mSubAllocatedResourceAllocators[i] = std::make_unique<BuddyMemoryAllocator>(
|
||||
kMaxHeapSize, kMinHeapSize,
|
||||
std::make_unique<HeapAllocator>(mDevice, GetD3D12HeapType(resourceHeapKind),
|
||||
GetD3D12HeapFlags(resourceHeapKind)));
|
||||
kMaxHeapSize, kMinHeapSize, mHeapAllocators[i].get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#define DAWNNATIVE_D3D12_RESOURCEALLOCATORMANAGERD3D12_H_
|
||||
|
||||
#include "common/SerialQueue.h"
|
||||
|
||||
#include "dawn_native/BuddyMemoryAllocator.h"
|
||||
#include "dawn_native/d3d12/HeapAllocatorD3D12.h"
|
||||
#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
|
||||
|
||||
#include <array>
|
||||
|
@ -76,10 +76,11 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
std::array<std::unique_ptr<BuddyMemoryAllocator>, ResourceHeapKind::EnumCount>
|
||||
mSubAllocatedResourceAllocators;
|
||||
std::array<std::unique_ptr<HeapAllocator>, ResourceHeapKind::EnumCount> mHeapAllocators;
|
||||
|
||||
SerialQueue<ResourceHeapAllocation> mAllocationsToDelete;
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
||||
#endif // DAWNNATIVE_D3D12_RESOURCEALLOCATORMANAGERD3D12_H_
|
||||
#endif // DAWNNATIVE_D3D12_RESOURCEALLOCATORMANAGERD3D12_H_
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
private:
|
||||
ComPtr<ID3D12Resource> mResource;
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
||||
#endif // DAWNNATIVE_D3D12_RESOURCEHEAPALLOCATIOND3D12_H_
|
||||
#endif // DAWNNATIVE_D3D12_RESOURCEHEAPALLOCATIOND3D12_H_
|
||||
|
|
|
@ -15,22 +15,23 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include "dawn_native/BuddyMemoryAllocator.h"
|
||||
#include "dawn_native/ResourceHeapAllocator.h"
|
||||
|
||||
using namespace dawn_native;
|
||||
|
||||
class DummyMemoryAllocator : public MemoryAllocator {
|
||||
class DummyResourceHeapAllocator : public ResourceHeapAllocator {
|
||||
public:
|
||||
ResultOrError<std::unique_ptr<ResourceHeapBase>> Allocate(uint64_t size) override {
|
||||
ResultOrError<std::unique_ptr<ResourceHeapBase>> AllocateResourceHeap(uint64_t size) override {
|
||||
return std::make_unique<ResourceHeapBase>();
|
||||
}
|
||||
void Deallocate(std::unique_ptr<ResourceHeapBase> allocation) override {
|
||||
void DeallocateResourceHeap(std::unique_ptr<ResourceHeapBase> allocation) override {
|
||||
}
|
||||
};
|
||||
|
||||
class DummyBuddyResourceAllocator {
|
||||
public:
|
||||
DummyBuddyResourceAllocator(uint64_t maxBlockSize, uint64_t memorySize)
|
||||
: mAllocator(maxBlockSize, memorySize, std::make_unique<DummyMemoryAllocator>()) {
|
||||
: mAllocator(maxBlockSize, memorySize, &mHeapAllocator) {
|
||||
}
|
||||
|
||||
ResourceMemoryAllocation Allocate(uint64_t allocationSize, uint64_t alignment = 1) {
|
||||
|
@ -48,6 +49,7 @@ class DummyBuddyResourceAllocator {
|
|||
}
|
||||
|
||||
private:
|
||||
DummyResourceHeapAllocator mHeapAllocator;
|
||||
BuddyMemoryAllocator mAllocator;
|
||||
};
|
||||
|
||||
|
@ -342,4 +344,4 @@ TEST(BuddyMemoryAllocatorTests, VariousSizeSameAlignment) {
|
|||
ASSERT_EQ(allocation4.GetInfo().mMethod, AllocationMethod::kSubAllocated);
|
||||
|
||||
ASSERT_EQ(allocator.ComputeTotalNumOfHeapsForTesting(), 3u);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue