FIX: position swapchain to RGBA32F(RT shadow quality in far dist), memory allocation errors
This commit is contained in:
@@ -255,15 +255,20 @@ void IBLManager::unload()
|
|||||||
if (_spec.image)
|
if (_spec.image)
|
||||||
{
|
{
|
||||||
rm->destroy_image(_spec);
|
rm->destroy_image(_spec);
|
||||||
_spec = {};
|
|
||||||
}
|
}
|
||||||
if (_diff.image && _diff.image != _spec.image) { rm->destroy_image(_diff); }
|
// Handle potential aliasing: _diff may have been set to _spec in load().
|
||||||
_diff = {};
|
if (_diff.image && _diff.image != _spec.image)
|
||||||
|
{
|
||||||
|
rm->destroy_image(_diff);
|
||||||
|
}
|
||||||
if (_brdf.image)
|
if (_brdf.image)
|
||||||
{
|
{
|
||||||
rm->destroy_image(_brdf);
|
rm->destroy_image(_brdf);
|
||||||
_brdf = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_spec = {};
|
||||||
|
_diff = {};
|
||||||
|
_brdf = {};
|
||||||
if (_iblSetLayout && _ctx && _ctx->getDevice())
|
if (_iblSetLayout && _ctx && _ctx->getDevice())
|
||||||
{
|
{
|
||||||
vkDestroyDescriptorSetLayout(_ctx->getDevice()->device(), _iblSetLayout, nullptr);
|
vkDestroyDescriptorSetLayout(_ctx->getDevice()->device(), _iblSetLayout, nullptr);
|
||||||
|
|||||||
@@ -121,18 +121,30 @@ void DeviceManager::init_vulkan(SDL_Window *window)
|
|||||||
|
|
||||||
void DeviceManager::cleanup()
|
void DeviceManager::cleanup()
|
||||||
{
|
{
|
||||||
// Optional VMA stats print
|
// Always query VMA stats once before destroying the allocator so we can
|
||||||
if (_allocator && vmaDebugEnabled())
|
// spot leaks that would trigger the vk_mem_alloc.h assertion:
|
||||||
|
// "Some allocations were not freed before destruction of this memory block!"
|
||||||
|
if (_allocator)
|
||||||
{
|
{
|
||||||
VmaTotalStatistics stats{};
|
VmaTotalStatistics stats{};
|
||||||
vmaCalculateStatistics(_allocator, &stats);
|
vmaCalculateStatistics(_allocator, &stats);
|
||||||
const VmaStatistics& s = stats.total.statistics;
|
const VmaStatistics &s = stats.total.statistics;
|
||||||
|
|
||||||
|
if (s.allocationCount != 0)
|
||||||
|
{
|
||||||
|
fmt::print("[VMA] WARNING: {} live allocations ({} bytes) remain before allocator destruction – this will trip vk_mem_alloc.h assertion: \"Some allocations were not freed before destruction of this memory block!\"\n",
|
||||||
|
(size_t)s.allocationCount,
|
||||||
|
(unsigned long long)s.allocationBytes);
|
||||||
|
}
|
||||||
|
else if (vmaDebugEnabled())
|
||||||
|
{
|
||||||
fmt::print("[VMA] Blocks: {} | Allocations: {} | BlockBytes: {} | AllocationBytes: {}\n",
|
fmt::print("[VMA] Blocks: {} | Allocations: {} | BlockBytes: {} | AllocationBytes: {}\n",
|
||||||
(size_t)s.blockCount,
|
(size_t)s.blockCount,
|
||||||
(size_t)s.allocationCount,
|
(size_t)s.allocationCount,
|
||||||
(unsigned long long)s.blockBytes,
|
(unsigned long long)s.blockBytes,
|
||||||
(unsigned long long)s.allocationBytes);
|
(unsigned long long)s.allocationBytes);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
vkDestroySurfaceKHR(_instance, _surface, nullptr);
|
vkDestroySurfaceKHR(_instance, _surface, nullptr);
|
||||||
_deletionQueue.flush();
|
_deletionQueue.flush();
|
||||||
vkDestroyDevice(_device, nullptr);
|
vkDestroyDevice(_device, nullptr);
|
||||||
|
|||||||
@@ -420,6 +420,14 @@ void VulkanEngine::cleanup()
|
|||||||
print_vma_stats(_deviceManager.get(), "after AssetManager");
|
print_vma_stats(_deviceManager.get(), "after AssetManager");
|
||||||
dump_vma_json(_deviceManager.get(), "after_AssetManager");
|
dump_vma_json(_deviceManager.get(), "after_AssetManager");
|
||||||
|
|
||||||
|
// Release IBL GPU resources (spec/diffuse cubes + BRDF LUT)
|
||||||
|
if (_iblManager)
|
||||||
|
{
|
||||||
|
_iblManager->unload();
|
||||||
|
}
|
||||||
|
print_vma_stats(_deviceManager.get(), "after IBLManager");
|
||||||
|
dump_vma_json(_deviceManager.get(), "after_IBLManager");
|
||||||
|
|
||||||
// Ensure ray tracing resources (BLAS/TLAS/instance buffers) are freed before VMA is destroyed
|
// Ensure ray tracing resources (BLAS/TLAS/instance buffers) are freed before VMA is destroyed
|
||||||
if (_rayManager) { _rayManager->cleanup(); }
|
if (_rayManager) { _rayManager->cleanup(); }
|
||||||
print_vma_stats(_deviceManager.get(), "after RTManager");
|
print_vma_stats(_deviceManager.get(), "after RTManager");
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ void SwapchainManager::init_swapchain()
|
|||||||
VK_CHECK(vkCreateImageView(_deviceManager->device(), &dview_info, nullptr, &_depthImage.imageView));
|
VK_CHECK(vkCreateImageView(_deviceManager->device(), &dview_info, nullptr, &_depthImage.imageView));
|
||||||
|
|
||||||
// GBuffer (SRGB not used to keep linear lighting)
|
// GBuffer (SRGB not used to keep linear lighting)
|
||||||
_gBufferPosition = _resourceManager->create_image(drawImageExtent, VK_FORMAT_R16G16B16A16_SFLOAT,
|
_gBufferPosition = _resourceManager->create_image(drawImageExtent, VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
_gBufferNormal = _resourceManager->create_image(drawImageExtent, VK_FORMAT_R16G16B16A16_SFLOAT,
|
_gBufferNormal = _resourceManager->create_image(drawImageExtent, VK_FORMAT_R16G16B16A16_SFLOAT,
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
|||||||
@@ -310,6 +310,20 @@ void LightingPass::draw_lighting(VkCommandBuffer cmd,
|
|||||||
|
|
||||||
void LightingPass::cleanup()
|
void LightingPass::cleanup()
|
||||||
{
|
{
|
||||||
|
if (_context && _context->getResources())
|
||||||
|
{
|
||||||
|
if (_fallbackIbl2D.image)
|
||||||
|
{
|
||||||
|
_context->getResources()->destroy_image(_fallbackIbl2D);
|
||||||
|
_fallbackIbl2D = {};
|
||||||
|
}
|
||||||
|
if (_fallbackBrdfLut2D.image)
|
||||||
|
{
|
||||||
|
_context->getResources()->destroy_image(_fallbackBrdfLut2D);
|
||||||
|
_fallbackBrdfLut2D = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_deletionQueue.flush();
|
_deletionQueue.flush();
|
||||||
fmt::print("LightingPass::cleanup()\n");
|
fmt::print("LightingPass::cleanup()\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,6 +317,16 @@ void SceneManager::cleanup()
|
|||||||
clearMeshInstances();
|
clearMeshInstances();
|
||||||
clearGLTFInstances();
|
clearGLTFInstances();
|
||||||
|
|
||||||
|
// On engine shutdown we know VulkanEngine::cleanup() has already called
|
||||||
|
// vkDeviceWaitIdle(), so it is safe to destroy all remaining GLTF scenes
|
||||||
|
// immediately instead of deferring them through pendingGLTFRelease.
|
||||||
|
if (!pendingGLTFRelease.empty())
|
||||||
|
{
|
||||||
|
fmt::println("[SceneManager] cleanup: forcing {} pending GLTF releases before shutdown",
|
||||||
|
pendingGLTFRelease.size());
|
||||||
|
pendingGLTFRelease.clear(); // drop strong refs → ~LoadedGLTF::clearAll() runs
|
||||||
|
}
|
||||||
|
|
||||||
// Drop our references to GLTF scenes. Their destructors call clearAll()
|
// Drop our references to GLTF scenes. Their destructors call clearAll()
|
||||||
// exactly once to release GPU resources.
|
// exactly once to release GPU resources.
|
||||||
loadedScenes.clear();
|
loadedScenes.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user