From ab222ffa1fdb8d65d9e5aca9cea32ef26c720761 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Tue, 16 Jun 2026 20:10:23 +0200 Subject: [PATCH] cache directwrite --- implementations/Crafter.Graphics-Device.cpp | 19 ++++++++++++++----- interfaces/Crafter.Graphics-Device.cppm | 14 ++++++++++++++ tests/UploadStrategy/main.cpp | 4 ++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/implementations/Crafter.Graphics-Device.cpp b/implementations/Crafter.Graphics-Device.cpp index c4ca43f..25b18fb 100644 --- a/implementations/Crafter.Graphics-Device.cpp +++ b/implementations/Crafter.Graphics-Device.cpp @@ -780,6 +780,7 @@ void Device::Initialize() { CheckVkResult(vkCreateCommandPool(device, &commandPoolcreateInfo, NULL, &commandPool)); vkGetPhysicalDeviceMemoryProperties(physDevice, &memoryProperties); + CacheUploadStrategy(); vkGetAccelerationStructureBuildSizesKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetAccelerationStructureBuildSizesKHR")); vkCreateAccelerationStructureKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateAccelerationStructureKHR")); @@ -842,7 +843,7 @@ std::uint32_t Device::GetMemoryType(uint32_t typeBits, VkMemoryPropertyFlags req throw std::runtime_error("Could not find a matching memory type"); } -bool Device::PreferDirectDeviceWrite(VkDeviceSize size) { +void Device::CacheUploadStrategy() { constexpr VkMemoryPropertyFlags directFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; @@ -858,7 +859,8 @@ bool Device::PreferDirectDeviceWrite(VkDeviceSize size) { } } if (!haveDirectType) { - return false; + directWriteBudget = 0; + return; } // 2. Compare the host-visible device-local heap against the largest plain @@ -871,10 +873,11 @@ bool Device::PreferDirectDeviceWrite(VkDeviceSize size) { } } - // 3. ReBAR / UMA: the BAR heap covers (almost) all of VRAM -> direct. + // 3. ReBAR / UMA: the BAR heap covers (almost) all of VRAM -> map any size. // barHeap >= 0.9 * vram, written to dodge floating point / overflow. if (barHeap >= vram - vram / 10) { - return true; + directWriteBudget = std::numeric_limits::max(); + return; } // 4. Small BAR window: direct only for buffers small enough that several @@ -884,5 +887,11 @@ bool Device::PreferDirectDeviceWrite(VkDeviceSize size) { // both a 256 MiB and a 4 GiB window). VK_EXT_memory_budget would refine // this to the window's *remaining* space; see the header note. constexpr VkDeviceSize barWindowFraction = 8; - return size <= barHeap / barWindowFraction; + directWriteBudget = barHeap / barWindowFraction; +} + +bool Device::PreferDirectDeviceWrite(VkDeviceSize size) { + // directWriteBudget caches the size-independent decision (CacheUploadStrategy): + // 0 -> never direct, max -> ReBAR/UMA so any size, else the small-window cap. + return directWriteBudget != 0 && size <= directWriteBudget; } \ No newline at end of file diff --git a/interfaces/Crafter.Graphics-Device.cppm b/interfaces/Crafter.Graphics-Device.cppm index 8c79181..11853d2 100644 --- a/interfaces/Crafter.Graphics-Device.cppm +++ b/interfaces/Crafter.Graphics-Device.cppm @@ -232,8 +232,22 @@ export namespace Crafter { // small-window budget would consult VK_EXT_memory_budget for the // window's *remaining* space rather than its total size; that needs the // extension enabled and is a follow-up. + // + // Everything except the final size comparison depends only on + // memoryProperties, so it is derived once by CacheUploadStrategy (called + // at device creation) into the directWrite* members below; this leaves + // the per-allocation call a single bounds check. static bool PreferDirectDeviceWrite(VkDeviceSize size); + // Size-independent half of PreferDirectDeviceWrite, cached from + // memoryProperties. directWriteBudget is the largest buffer that may be + // written directly: 0 when no resizable BAR exists (always stage), + // VkDeviceSize max for ReBAR/UMA (always map), or the small-window + // per-buffer cap otherwise. Recompute via CacheUploadStrategy whenever + // memoryProperties changes (device creation does this once). + inline static VkDeviceSize directWriteBudget = 0; + static void CacheUploadStrategy(); + // ─── Wayland key repeat ──────────────────────────────────────── // TickKeyRepeats fires onRawKeyDown / onRawKeyHold / onTextInput on // the focused window for whichever key is currently repeating. diff --git a/tests/UploadStrategy/main.cpp b/tests/UploadStrategy/main.cpp index 442711d..ff81ee0 100644 --- a/tests/UploadStrategy/main.cpp +++ b/tests/UploadStrategy/main.cpp @@ -80,6 +80,10 @@ void SetMemory(std::initializer_list types, Device::memoryProperties.memoryHeaps[h].flags = s.flags; ++h; } + // PreferDirectDeviceWrite reads the cache CacheUploadStrategy derives from + // memoryProperties (device creation does this once); refresh it here since + // the test mutates the layout directly. + Device::CacheUploadStrategy(); } constexpr VkMemoryHeapFlags HEAP_DEVICE_LOCAL = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;