Vulkan: Allocate MAP_READ buffer on HOST_CACHED memory type
This patch tries to allocate MAP_READ buffer on the memory with
VK_MEMORY_PROPERTY_HOST_CACHED_BIT memory type to optimize the CPU
read-only access.
Bug: dawn:849
Change-Id: I4a96ad54f566fa7e744c14506165e5c84e55b9d9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/143720
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn/native/vulkan/BufferVk.cpp b/src/dawn/native/vulkan/BufferVk.cpp
index bfa2e51..fc1f150 100644
--- a/src/dawn/native/vulkan/BufferVk.cpp
+++ b/src/dawn/native/vulkan/BufferVk.cpp
@@ -203,8 +203,10 @@
device->fn.GetBufferMemoryRequirements(device->GetVkDevice(), mHandle, &requirements);
MemoryKind requestKind = MemoryKind::Linear;
- if (GetUsage() & kMappableBufferUsages) {
- requestKind = MemoryKind::LinearMappable;
+ if (GetUsage() & wgpu::BufferUsage::MapRead) {
+ requestKind = MemoryKind::LinearReadMappable;
+ } else if (GetUsage() & wgpu::BufferUsage::MapWrite) {
+ requestKind = MemoryKind::LinearWriteMappable;
}
DAWN_TRY_ASSIGN(mMemoryAllocation,
device->GetResourceMemoryAllocator()->Allocate(requirements, requestKind));
diff --git a/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.cpp b/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.cpp
index e8466a7..5db4ab2 100644
--- a/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.cpp
+++ b/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.cpp
@@ -38,6 +38,22 @@
// size
constexpr uint64_t kBuddyHeapsSize = 2 * kMaxSizeForSubAllocation;
+bool IsMemoryKindMappable(MemoryKind memoryKind) {
+ switch (memoryKind) {
+ case MemoryKind::LinearReadMappable:
+ case MemoryKind::LinearWriteMappable:
+ return true;
+
+ case MemoryKind::LazilyAllocated:
+ case MemoryKind::Linear:
+ case MemoryKind::Opaque:
+ return false;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
} // anonymous namespace
// SingleTypeAllocator is a combination of a BuddyMemoryAllocator and its client and can
@@ -136,7 +152,7 @@
// is part of the resource and not the heap, which doesn't match the Vulkan model.
// TODO(crbug.com/dawn/849): allow sub-allocating mappable resources, maybe.
if (!forceDisableSubAllocation && requirements.size < kMaxSizeForSubAllocation &&
- kind != MemoryKind::LinearMappable &&
+ !IsMemoryKindMappable(kind) &&
!mDevice->IsToggleEnabled(Toggle::DisableResourceSuballocation)) {
// When sub-allocating, Vulkan requires that we respect bufferImageGranularity. Some
// hardware puts information on the memory's page table entry and allocating a linear
@@ -166,7 +182,7 @@
DAWN_TRY_ASSIGN(resourceHeap, mAllocatorsPerType[memoryType]->AllocateResourceHeap(size));
void* mappedPointer = nullptr;
- if (kind == MemoryKind::LinearMappable) {
+ if (IsMemoryKindMappable(kind)) {
DAWN_TRY_WITH_CLEANUP(
CheckVkSuccess(mDevice->fn.MapMemory(mDevice->GetVkDevice(),
ToBackend(resourceHeap.get())->GetMemory(), 0,
@@ -230,7 +246,7 @@
int ResourceMemoryAllocator::FindBestTypeIndex(VkMemoryRequirements requirements, MemoryKind kind) {
const VulkanDeviceInfo& info = mDevice->GetDeviceInfo();
- bool mappable = kind == MemoryKind::LinearMappable;
+ bool mappable = IsMemoryKindMappable(kind);
// Find a suitable memory type for this allocation
int bestType = -1;
@@ -286,6 +302,19 @@
continue;
}
+ // Cached memory is optimal for read-only access from CPU as host memory accesses to
+ // uncached memory are slower than to cached memory.
+ bool currentHostCached =
+ info.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ bool bestHostCached =
+ info.memoryTypes[bestType].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ if (kind == MemoryKind::LinearReadMappable && currentHostCached != bestHostCached) {
+ if (currentHostCached) {
+ bestType = static_cast<int>(i);
+ }
+ continue;
+ }
+
// All things equal favor the memory in the biggest heap
VkDeviceSize bestTypeHeapSize = info.memoryHeaps[info.memoryTypes[bestType].heapIndex].size;
VkDeviceSize candidateHeapSize = info.memoryHeaps[info.memoryTypes[i].heapIndex].size;
diff --git a/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h b/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h
index 452819c..d870c1b 100644
--- a/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h
+++ b/src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h
@@ -34,7 +34,8 @@
enum class MemoryKind {
LazilyAllocated,
Linear,
- LinearMappable,
+ LinearReadMappable,
+ LinearWriteMappable,
Opaque,
};