Choose depth buffer format; Log GPU memory usage

This commit is contained in:
Bailey Harrison 2023-03-21 14:18:59 +00:00
parent c462e873bc
commit b21dad41cd
8 changed files with 67 additions and 12 deletions

View File

@ -62,6 +62,8 @@ namespace engine {
uint64_t getFrameCount();
void logPerformanceInfo();
// wait until all the active GPU queues have finished working
void waitIdle();

View File

@ -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();
}

View File

@ -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 <assert.h>
@ -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;

View File

@ -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);

View File

@ -1,9 +1,11 @@
#pragma once
#include <vk_mem_alloc.h>
#include "device.h"
namespace engine {
VmaAllocator createAllocator(VkInstance instance, VkDevice device, VkPhysicalDevice physicalDevice);
VmaAllocator createAllocator(VkInstance instance, const Device& device);
void destroyAllocator(VmaAllocator allocator);
}

View File

@ -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));

View File

@ -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<std::pair<VkImage, VkImageView>> swapchainImages{};
std::vector<DepthStencil> depthImages{};
std::vector<VkFramebuffer> framebuffers{};

View File

@ -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());