From b21dad41cdd6d2bdc646a907d529850893c33baf Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Tue, 21 Mar 2023 14:18:59 +0000 Subject: [PATCH] Choose depth buffer format; Log GPU memory usage --- include/gfx_device.hpp | 2 ++ src/application.cpp | 1 + src/gfx_device_vulkan.cpp | 38 +++++++++++++++++++++++++++++++++--- src/vulkan/gpu_allocator.cpp | 13 ++++++++---- src/vulkan/gpu_allocator.h | 4 +++- src/vulkan/swapchain.cpp | 17 ++++++++++++++-- src/vulkan/swapchain.h | 2 +- test/src/game.cpp | 2 +- 8 files changed, 67 insertions(+), 12 deletions(-) diff --git a/include/gfx_device.hpp b/include/gfx_device.hpp index 67e774d..c1d0dd6 100644 --- a/include/gfx_device.hpp +++ b/include/gfx_device.hpp @@ -62,6 +62,8 @@ namespace engine { uint64_t getFrameCount(); + void logPerformanceInfo(); + // wait until all the active GPU queues have finished working void waitIdle(); diff --git a/src/application.cpp b/src/application.cpp index fd467b0..4c545bd 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -166,6 +166,7 @@ namespace engine { if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] { lastTick = now; LOG_INFO("fps: {}", m_window->getAvgFPS()); + gfx()->logPerformanceInfo(); m_window->resetAvgFPS(); } diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp index 934b063..d19bc2f 100644 --- a/src/gfx_device_vulkan.cpp +++ b/src/gfx_device_vulkan.cpp @@ -3,9 +3,13 @@ /* IMPORTANT INFORMATION * * When allocating memory with VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, always set a memory priority. - * This feature uses the device extension VK_EXT_memory_priority. Depth buffers have a priority of 0.9f. + * This feature uses the device extension VK_EXT_memory_priority. Depth buffers have a priority of 1.0f. * Other, non-essential allocations will have a priority of 0.5f. * + * Call vkResetCommandPool before reusing it in another frame. + * Otherwise, the pool will keep on growing until you run out of memory. + * - NVIDIA Vulkan Dos and Don'ts + * */ #include @@ -333,7 +337,7 @@ namespace engine { }; DeviceRequirements deviceRequirements{}; - deviceRequirements.requiredExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; + deviceRequirements.requiredExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME }; deviceRequirements.optionalExtensions = { VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME }; deviceRequirements.requiredFeatures.samplerAnisotropy = VK_TRUE; deviceRequirements.requiredFeatures.fillModeNonSolid = VK_TRUE; @@ -390,7 +394,7 @@ namespace engine { pimpl->device = createDevice(pimpl->instance.instance, deviceRequirements, pimpl->surface); - pimpl->allocator = createAllocator(pimpl->instance.instance, pimpl->device.device, pimpl->device.physicalDevice); + pimpl->allocator = createAllocator(pimpl->instance.instance, pimpl->device); pimpl->swapchainInfo.device = pimpl->device.device; pimpl->swapchainInfo.allocator = pimpl->allocator; @@ -512,6 +516,8 @@ namespace engine { const uint32_t currentFrameIndex = pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT; const FrameData frameData = pimpl->frameData[currentFrameIndex]; + vmaSetCurrentFrameIndex(pimpl->allocator, (uint32_t)pimpl->FRAMECOUNT); + /* wait until the previous frame RENDERING has finished */ res = vkWaitForFences(pimpl->device.device, 1, &frameData.renderFence, VK_TRUE, 1000000000LL); VKCHECK(res); @@ -1252,6 +1258,32 @@ namespace engine { (void)texture; } + void GFXDevice::logPerformanceInfo() + { + VmaTotalStatistics pStats{}; + vmaCalculateStatistics(pimpl->allocator, &pStats); + + VkPhysicalDeviceMemoryProperties2 memProps{}; + memProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; + vkGetPhysicalDeviceMemoryProperties2(pimpl->device.physicalDevice, &memProps); + + LOG_INFO("GPU Memory Statistics:"); + + for (uint32_t i = 0; i < memProps.memoryProperties.memoryHeapCount; i++) { + const VmaStatistics& statistics = pStats.memoryType[i].statistics; + VkMemoryHeap heap = memProps.memoryProperties.memoryHeaps[i]; + if (statistics.allocationCount > 0) { + LOG_INFO("Memory heap {}", i); + LOG_INFO(" Memory blocks allocated: {} ({} MiB)", statistics.blockCount, statistics.allocationBytes / (1024 * 1024)); + LOG_INFO(" Number of allocations: {} ({} MiB)", statistics.allocationCount, statistics.allocationBytes / (1024 * 1024)); + LOG_INFO(" Max size: {} MiB", heap.size / (1024 * 1024)); + if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { + LOG_INFO(" DEVICE_LOCAL"); + } + } + } + } + uint64_t GFXDevice::getFrameCount() { return pimpl->FRAMECOUNT; diff --git a/src/vulkan/gpu_allocator.cpp b/src/vulkan/gpu_allocator.cpp index 2bf7fed..bcfddf3 100644 --- a/src/vulkan/gpu_allocator.cpp +++ b/src/vulkan/gpu_allocator.cpp @@ -12,7 +12,7 @@ namespace engine { - VmaAllocator createAllocator(VkInstance instance, VkDevice device, VkPhysicalDevice physicalDevice) + VmaAllocator createAllocator(VkInstance instance, const Device& device) { VmaVulkanFunctions functions{ .vkGetInstanceProcAddr = nullptr, @@ -44,9 +44,9 @@ namespace engine { }; VmaAllocatorCreateInfo createInfo{ - .flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT, - .physicalDevice = physicalDevice, - .device = device, + .flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT, + .physicalDevice = device.physicalDevice, + .device = device.device, .preferredLargeHeapBlockSize = 0, .pAllocationCallbacks = nullptr, .pDeviceMemoryCallbacks = nullptr, @@ -57,6 +57,11 @@ namespace engine { .pTypeExternalMemoryHandleTypes = nullptr }; + if (std::find(device.enabledExtensions.begin(), device.enabledExtensions.end(), + std::string(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME)) != device.enabledExtensions.end()) { + createInfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT; + } + [[maybe_unused]] VkResult res; VmaAllocator allocator; res = vmaCreateAllocator(&createInfo, &allocator); diff --git a/src/vulkan/gpu_allocator.h b/src/vulkan/gpu_allocator.h index e6a673b..87dc3a3 100644 --- a/src/vulkan/gpu_allocator.h +++ b/src/vulkan/gpu_allocator.h @@ -1,9 +1,11 @@ #pragma once #include +#include "device.h" + namespace engine { - VmaAllocator createAllocator(VkInstance instance, VkDevice device, VkPhysicalDevice physicalDevice); + VmaAllocator createAllocator(VkInstance instance, const Device& device); void destroyAllocator(VmaAllocator allocator); } diff --git a/src/vulkan/swapchain.cpp b/src/vulkan/swapchain.cpp index adbb386..be6f690 100644 --- a/src/vulkan/swapchain.cpp +++ b/src/vulkan/swapchain.cpp @@ -98,7 +98,20 @@ namespace engine { sc->extent = oldExtent; } - /* TODO: delete old framebuffers and image views */ + /* find depth stencil format to use */ + VkFormatProperties2 formatProperties{}; + formatProperties.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + vkGetPhysicalDeviceFormatProperties2(info.physicalDevice, VK_FORMAT_D24_UNORM_S8_UINT, &formatProperties); + if (formatProperties.formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { + sc->depthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; + } else { + vkGetPhysicalDeviceFormatProperties2(info.physicalDevice, VK_FORMAT_D16_UNORM, &formatProperties); + if (formatProperties.formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { + sc->depthStencilFormat = VK_FORMAT_D16_UNORM; + } else { + throw std::runtime_error("Failed to find suitable depth-buffer image format!"); + } + } /* create swapchain */ @@ -286,7 +299,7 @@ namespace engine { VmaAllocationCreateInfo depthAllocInfo{}; depthAllocInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; depthAllocInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - depthAllocInfo.priority = 0.9f; + depthAllocInfo.priority = 1.0f; res = vmaCreateImage(sc->allocator, &depthImageInfo, &depthAllocInfo, &depthImage, &depthAllocation, nullptr); if (res != VK_SUCCESS) throw std::runtime_error("Failed to create depth buffer image! Code: " + std::to_string(res)); diff --git a/src/vulkan/swapchain.h b/src/vulkan/swapchain.h index 5835ba7..7b7c983 100644 --- a/src/vulkan/swapchain.h +++ b/src/vulkan/swapchain.h @@ -26,7 +26,7 @@ namespace engine { VkPresentModeKHR presentMode{}; VkExtent2D extent{}; VkRenderPass renderpass = VK_NULL_HANDLE; - const VkFormat depthStencilFormat = VK_FORMAT_D16_UNORM; + VkFormat depthStencilFormat; std::vector> swapchainImages{}; std::vector depthImages{}; std::vector framebuffers{}; diff --git a/test/src/game.cpp b/test/src/game.cpp index 839e8b6..1364b45 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -56,7 +56,7 @@ void playGame(GameSettings settings) app.setFrameLimiter(settings.enableFrameLimiter); // configure window - //app.window()->setRelativeMouseMode(true); + app.window()->setRelativeMouseMode(true); configureInputs(app.inputManager());