mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-20 18:29:23 +00:00
D3D12: Stage BindGroups on CPU descriptor heaps.
Instead of directly populating GPU heaps, pre-encoded BindGroups are staged on CPU heaps then copied over to the GPU. Non-shader visible allocators are stored on the BGL, which hands out fixed-size chunks to simplify memory managment. To enable memory re-use, CPU allocations are tied to the lifetime of BindGroup objects. BUG=dawn:155 Change-Id: I402e6686c96f7450a077c627c8499600979e426c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/18100 Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
c00163ba09
commit
2479860e4b
@@ -82,7 +82,7 @@ TEST(Math, AlignPtr) {
|
||||
|
||||
ASSERT_GE(aligned - unaligned, 0);
|
||||
ASSERT_LT(static_cast<size_t>(aligned - unaligned), kTestAlignment);
|
||||
ASSERT_EQ(reinterpret_cast<uintptr_t>(aligned) & (kTestAlignment -1), 0u);
|
||||
ASSERT_EQ(reinterpret_cast<uintptr_t>(aligned) & (kTestAlignment - 1), 0u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,3 +191,21 @@ TEST(Math, SRGBToLinear) {
|
||||
|
||||
ASSERT_FLOAT_EQ(SRGBToLinear(0.5f), 0.21404114f);
|
||||
}
|
||||
|
||||
// Tests for RoundUp
|
||||
TEST(Math, RoundUp) {
|
||||
ASSERT_EQ(RoundUp(2, 2), 2u);
|
||||
ASSERT_EQ(RoundUp(2, 4), 4u);
|
||||
ASSERT_EQ(RoundUp(6, 2), 6u);
|
||||
ASSERT_EQ(RoundUp(8, 4), 8u);
|
||||
ASSERT_EQ(RoundUp(12, 6), 12u);
|
||||
|
||||
ASSERT_EQ(RoundUp(3, 3), 3u);
|
||||
ASSERT_EQ(RoundUp(3, 5), 5u);
|
||||
ASSERT_EQ(RoundUp(5, 3), 6u);
|
||||
ASSERT_EQ(RoundUp(9, 5), 10u);
|
||||
|
||||
// Test extrema
|
||||
ASSERT_EQ(RoundUp(0x7FFFFFFFFFFFFFFFull, 0x8000000000000000ull), 0x8000000000000000ull);
|
||||
ASSERT_EQ(RoundUp(1, 1), 1u);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
#include "tests/DawnTest.h"
|
||||
|
||||
#include "dawn_native/Toggles.h"
|
||||
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
|
||||
#include "dawn_native/d3d12/DeviceD3D12.h"
|
||||
#include "dawn_native/d3d12/NonShaderVisibleDescriptorAllocatorD3D12.h"
|
||||
#include "dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.h"
|
||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||
#include "utils/WGPUHelpers.h"
|
||||
@@ -93,6 +95,31 @@ class D3D12DescriptorHeapTests : public DawnTest {
|
||||
wgpu::ShaderModule mSimpleFSModule;
|
||||
};
|
||||
|
||||
class DummyNonShaderVisibleDescriptorAllocator {
|
||||
public:
|
||||
DummyNonShaderVisibleDescriptorAllocator(Device* device,
|
||||
uint32_t descriptorCount,
|
||||
uint32_t allocationsPerHeap)
|
||||
: mAllocator(device,
|
||||
descriptorCount,
|
||||
allocationsPerHeap * descriptorCount,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {
|
||||
}
|
||||
|
||||
CPUDescriptorHeapAllocation AllocateCPUDescriptors() {
|
||||
dawn_native::ResultOrError<CPUDescriptorHeapAllocation> result =
|
||||
mAllocator.AllocateCPUDescriptors();
|
||||
return (result.IsSuccess()) ? result.AcquireSuccess() : CPUDescriptorHeapAllocation{};
|
||||
}
|
||||
|
||||
void Deallocate(CPUDescriptorHeapAllocation& allocation) {
|
||||
mAllocator.Deallocate(&allocation);
|
||||
}
|
||||
|
||||
private:
|
||||
NonShaderVisibleDescriptorAllocator mAllocator;
|
||||
};
|
||||
|
||||
// Verify the shader visible heaps switch over within a single submit.
|
||||
TEST_P(D3D12DescriptorHeapTests, SwitchOverHeaps) {
|
||||
utils::ComboRenderPipelineDescriptor renderPipelineDescriptor(device);
|
||||
@@ -688,6 +715,157 @@ TEST_P(D3D12DescriptorHeapTests, EncodeManyUBOAndSamplers) {
|
||||
}
|
||||
}
|
||||
|
||||
// Verify a single allocate/deallocate.
|
||||
// One non-shader visible heap will be created.
|
||||
TEST_P(D3D12DescriptorHeapTests, Single) {
|
||||
constexpr uint32_t kDescriptorCount = 4;
|
||||
constexpr uint32_t kAllocationsPerHeap = 3;
|
||||
DummyNonShaderVisibleDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
||||
kAllocationsPerHeap);
|
||||
|
||||
CPUDescriptorHeapAllocation allocation = allocator.AllocateCPUDescriptors();
|
||||
EXPECT_EQ(allocation.GetHeapIndex(), 0u);
|
||||
EXPECT_NE(allocation.OffsetFrom(0, 0).ptr, 0u);
|
||||
|
||||
allocator.Deallocate(allocation);
|
||||
EXPECT_FALSE(allocation.IsValid());
|
||||
}
|
||||
|
||||
// Verify allocating many times causes the pool to increase in size.
|
||||
// Creates |kNumOfHeaps| non-shader visible heaps.
|
||||
TEST_P(D3D12DescriptorHeapTests, Sequential) {
|
||||
constexpr uint32_t kDescriptorCount = 4;
|
||||
constexpr uint32_t kAllocationsPerHeap = 3;
|
||||
DummyNonShaderVisibleDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
||||
kAllocationsPerHeap);
|
||||
|
||||
// Allocate |kNumOfHeaps| worth.
|
||||
constexpr uint32_t kNumOfHeaps = 2;
|
||||
|
||||
std::set<uint32_t> allocatedHeaps;
|
||||
|
||||
std::vector<CPUDescriptorHeapAllocation> allocations;
|
||||
for (uint32_t i = 0; i < kAllocationsPerHeap * kNumOfHeaps; i++) {
|
||||
CPUDescriptorHeapAllocation allocation = allocator.AllocateCPUDescriptors();
|
||||
EXPECT_EQ(allocation.GetHeapIndex(), i / kAllocationsPerHeap);
|
||||
EXPECT_NE(allocation.OffsetFrom(0, 0).ptr, 0u);
|
||||
allocations.push_back(allocation);
|
||||
allocatedHeaps.insert(allocation.GetHeapIndex());
|
||||
}
|
||||
|
||||
EXPECT_EQ(allocatedHeaps.size(), kNumOfHeaps);
|
||||
|
||||
// Deallocate all.
|
||||
for (CPUDescriptorHeapAllocation& allocation : allocations) {
|
||||
allocator.Deallocate(allocation);
|
||||
EXPECT_FALSE(allocation.IsValid());
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that re-allocating a number of allocations < pool size, all heaps are reused.
|
||||
// Creates and reuses |kNumofHeaps| non-shader visible heaps.
|
||||
TEST_P(D3D12DescriptorHeapTests, ReuseFreedHeaps) {
|
||||
constexpr uint32_t kDescriptorCount = 4;
|
||||
constexpr uint32_t kAllocationsPerHeap = 25;
|
||||
DummyNonShaderVisibleDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
||||
kAllocationsPerHeap);
|
||||
|
||||
constexpr uint32_t kNumofHeaps = 10;
|
||||
|
||||
std::list<CPUDescriptorHeapAllocation> allocations;
|
||||
std::set<size_t> allocationPtrs;
|
||||
|
||||
// Allocate |kNumofHeaps| heaps worth.
|
||||
for (uint32_t i = 0; i < kAllocationsPerHeap * kNumofHeaps; i++) {
|
||||
CPUDescriptorHeapAllocation allocation = allocator.AllocateCPUDescriptors();
|
||||
allocations.push_back(allocation);
|
||||
EXPECT_TRUE(allocationPtrs.insert(allocation.OffsetFrom(0, 0).ptr).second);
|
||||
}
|
||||
|
||||
// Deallocate all.
|
||||
for (CPUDescriptorHeapAllocation& allocation : allocations) {
|
||||
allocator.Deallocate(allocation);
|
||||
EXPECT_FALSE(allocation.IsValid());
|
||||
}
|
||||
|
||||
allocations.clear();
|
||||
|
||||
// Re-allocate all again.
|
||||
std::set<size_t> reallocatedPtrs;
|
||||
for (uint32_t i = 0; i < kAllocationsPerHeap * kNumofHeaps; i++) {
|
||||
CPUDescriptorHeapAllocation allocation = allocator.AllocateCPUDescriptors();
|
||||
allocations.push_back(allocation);
|
||||
EXPECT_TRUE(reallocatedPtrs.insert(allocation.OffsetFrom(0, 0).ptr).second);
|
||||
EXPECT_TRUE(std::find(allocationPtrs.begin(), allocationPtrs.end(),
|
||||
allocation.OffsetFrom(0, 0).ptr) != allocationPtrs.end());
|
||||
}
|
||||
|
||||
// Deallocate all again.
|
||||
for (CPUDescriptorHeapAllocation& allocation : allocations) {
|
||||
allocator.Deallocate(allocation);
|
||||
EXPECT_FALSE(allocation.IsValid());
|
||||
}
|
||||
}
|
||||
|
||||
// Verify allocating then deallocating many times.
|
||||
TEST_P(D3D12DescriptorHeapTests, AllocateDeallocateMany) {
|
||||
constexpr uint32_t kDescriptorCount = 4;
|
||||
constexpr uint32_t kAllocationsPerHeap = 25;
|
||||
DummyNonShaderVisibleDescriptorAllocator allocator(mD3DDevice, kDescriptorCount,
|
||||
kAllocationsPerHeap);
|
||||
|
||||
std::list<CPUDescriptorHeapAllocation> list3;
|
||||
std::list<CPUDescriptorHeapAllocation> list5;
|
||||
std::list<CPUDescriptorHeapAllocation> allocations;
|
||||
|
||||
constexpr uint32_t kNumofHeaps = 2;
|
||||
|
||||
// Allocate |kNumofHeaps| heaps worth.
|
||||
for (uint32_t i = 0; i < kAllocationsPerHeap * kNumofHeaps; i++) {
|
||||
CPUDescriptorHeapAllocation allocation = allocator.AllocateCPUDescriptors();
|
||||
EXPECT_NE(allocation.OffsetFrom(0, 0).ptr, 0u);
|
||||
if (i % 3 == 0) {
|
||||
list3.push_back(allocation);
|
||||
} else {
|
||||
allocations.push_back(allocation);
|
||||
}
|
||||
}
|
||||
|
||||
// Deallocate every 3rd allocation.
|
||||
for (auto it = list3.begin(); it != list3.end(); it = list3.erase(it)) {
|
||||
allocator.Deallocate(*it);
|
||||
}
|
||||
|
||||
// Allocate again.
|
||||
for (uint32_t i = 0; i < kAllocationsPerHeap * kNumofHeaps; i++) {
|
||||
CPUDescriptorHeapAllocation allocation = allocator.AllocateCPUDescriptors();
|
||||
EXPECT_NE(allocation.OffsetFrom(0, 0).ptr, 0u);
|
||||
if (i % 5 == 0) {
|
||||
list5.push_back(allocation);
|
||||
} else {
|
||||
allocations.push_back(allocation);
|
||||
}
|
||||
}
|
||||
|
||||
// Deallocate every 5th allocation.
|
||||
for (auto it = list5.begin(); it != list5.end(); it = list5.erase(it)) {
|
||||
allocator.Deallocate(*it);
|
||||
}
|
||||
|
||||
// Allocate again.
|
||||
for (uint32_t i = 0; i < kAllocationsPerHeap * kNumofHeaps; i++) {
|
||||
CPUDescriptorHeapAllocation allocation = allocator.AllocateCPUDescriptors();
|
||||
EXPECT_NE(allocation.OffsetFrom(0, 0).ptr, 0u);
|
||||
allocations.push_back(allocation);
|
||||
}
|
||||
|
||||
// Deallocate remaining.
|
||||
for (CPUDescriptorHeapAllocation& allocation : allocations) {
|
||||
allocator.Deallocate(allocation);
|
||||
EXPECT_FALSE(allocation.IsValid());
|
||||
}
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(D3D12DescriptorHeapTests,
|
||||
D3D12Backend(),
|
||||
D3D12Backend({"use_d3d12_small_shader_visible_heap"}));
|
||||
|
||||
Reference in New Issue
Block a user