Various vulkan fixes (#732)

* vulkan: no need to explicitly enable VK_KHR_get_physical_device_properties2

It has been promoted to core Vulkan 1.1

* vulkan: fix creating and destroying swapchains

We can't reuse a semaphore if it is signalled. There is no
easy way to wait on the swapchain semaphore without some ugly hacks,
so instead we just create a new one.
We also need make sure we only destroy old swapchains once they are
(probably) not used anymore. The recent VK_EXT_swapchain_maintenance1
extension would make all of this much easier, but as of now, it's not yet
widely supported.

* cleanup: reduce amount of copy-paste in AllocationHandler::Update()

Using a lambda allows us to remove the copy-pasted loop and increase legibility
by reducing the code by almost two thirds with no performance impact: both GCC
and MSVC generate almost the same code as in the old version, the differences
being often due to slightly different register allocations.

* vulkan: ensure render area is not greater than color attachments

swapchain->desc.width/height can differ from the swapChainExtent,
for example if a VK_KHR_SUBOPTIMAL happened before we received the
"window size changed" event, or if it is not between the minimal
or maximal extents.

Ensure we don't use a render area larger than the color attachments,
as this violates VUID-VkRenderingInfo-pNext-06079 and 06080.
This commit is contained in:
Dennis Brakhane
2023-08-18 17:20:30 +02:00
committed by GitHub
parent dd37d813a5
commit c8cfac5678
2 changed files with 118 additions and 350 deletions
+21 -11
View File
@@ -1170,7 +1170,10 @@ namespace vulkan_internal
// the color space change will not be applied
res = vkDeviceWaitIdle(device);
assert(res == VK_SUCCESS);
vkDestroySwapchainKHR(device, internal_state->swapChain, nullptr);
{
std::scoped_lock lock(allocationhandler->destroylocker);
allocationhandler->destroyer_swapchains.emplace_back(internal_state->swapChain, allocationhandler->framecount);
}
internal_state->swapChain = nullptr;
}
}
@@ -1230,7 +1233,8 @@ namespace vulkan_internal
if (createInfo.oldSwapchain != VK_NULL_HANDLE)
{
vkDestroySwapchainKHR(device, createInfo.oldSwapchain, nullptr);
std::scoped_lock lock(allocationhandler->destroylocker);
allocationhandler->destroyer_swapchains.emplace_back(createInfo.oldSwapchain, allocationhandler->framecount);
}
res = vkGetSwapchainImagesKHR(device, internal_state->swapChain, &imageCount, nullptr);
@@ -2373,16 +2377,12 @@ using namespace vulkan_internal;
debugUtils = true;
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
else if (strcmp(availableExtension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
{
instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
}
else if (strcmp(availableExtension.extensionName, VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME) == 0)
{
instanceExtensions.push_back(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
}
}
instanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
#if defined(VK_USE_PLATFORM_WIN32_KHR)
@@ -7404,13 +7404,12 @@ using namespace vulkan_internal;
commandlist.renderpass_barriers_begin.clear();
commandlist.renderpass_barriers_end.clear();
auto internal_state = to_internal(swapchain);
commandlist.prev_swapchains.push_back(*swapchain);
internal_state->locker.lock();
VkResult res = vkAcquireNextImageKHR(
device,
internal_state->swapChain,
0xFFFFFFFFFFFFFFFF,
UINT64_MAX,
internal_state->swapchainAcquireSemaphore,
VK_NULL_HANDLE,
&internal_state->swapChainImageIndex
@@ -7422,6 +7421,16 @@ using namespace vulkan_internal;
// Handle outdated error in acquire:
if (res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR)
{
// we need to create a new semaphore or jump through a few hoops to
// wait for the current one to be unsignalled before we can use it again
// creating a new one is easiest. See also:
// https://github.com/KhronosGroup/Vulkan-Docs/issues/152
// https://www.khronos.org/blog/resolving-longstanding-issues-with-wsi
{
std::scoped_lock lock(allocationhandler->destroylocker);
allocationhandler->destroyer_semaphores.emplace_back(internal_state->swapchainAcquireSemaphore, allocationhandler->framecount);
}
internal_state->swapchainAcquireSemaphore = VK_NULL_HANDLE;
if (CreateSwapChainInternal(internal_state, physicalDevice, device, allocationhandler))
{
RenderPassBegin(swapchain, cmd);
@@ -7430,13 +7439,14 @@ using namespace vulkan_internal;
}
assert(0);
}
commandlist.prev_swapchains.push_back(*swapchain);
VkRenderingInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
info.renderArea.offset.x = 0;
info.renderArea.offset.y = 0;
info.renderArea.extent.width = swapchain->desc.width;
info.renderArea.extent.height = swapchain->desc.height;
info.renderArea.extent.width = std::min(swapchain->desc.width, internal_state->swapChainExtent.width);
info.renderArea.extent.height = std::min(swapchain->desc.height, internal_state->swapChainExtent.height);
info.layerCount = 1;
VkRenderingAttachmentInfo color_attachment = {};
+97 -339
View File
@@ -595,346 +595,104 @@ namespace wi::graphics
// Deferred destroy of resources that the GPU is already finished with:
void Update(uint64_t FRAMECOUNT, uint32_t BUFFERCOUNT)
{
destroylocker.lock();
const auto destroy = [&](auto&& queue, auto&& handler) {
while (!queue.empty()) {
if (queue.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = queue.front();
queue.pop_front();
handler(item.first);
}
else
{
break;
}
}
};
framecount = FRAMECOUNT;
while (!destroyer_allocations.empty())
{
if (destroyer_allocations.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_allocations.front();
destroyer_allocations.pop_front();
vmaFreeMemory(allocator, item.first);
}
else
{
break;
}
}
while (!destroyer_images.empty())
{
if (destroyer_images.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_images.front();
destroyer_images.pop_front();
vmaDestroyImage(allocator, item.first.first, item.first.second);
}
else
{
break;
}
}
while (!destroyer_imageviews.empty())
{
if (destroyer_imageviews.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_imageviews.front();
destroyer_imageviews.pop_front();
vkDestroyImageView(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_buffers.empty())
{
if (destroyer_buffers.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_buffers.front();
destroyer_buffers.pop_front();
vmaDestroyBuffer(allocator, item.first.first, item.first.second);
}
else
{
break;
}
}
while (!destroyer_bufferviews.empty())
{
if (destroyer_bufferviews.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_bufferviews.front();
destroyer_bufferviews.pop_front();
vkDestroyBufferView(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_bvhs.empty())
{
if (destroyer_bvhs.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_bvhs.front();
destroyer_bvhs.pop_front();
vkDestroyAccelerationStructureKHR(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_samplers.empty())
{
if (destroyer_samplers.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_samplers.front();
destroyer_samplers.pop_front();
vkDestroySampler(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_descriptorPools.empty())
{
if (destroyer_descriptorPools.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_descriptorPools.front();
destroyer_descriptorPools.pop_front();
vkDestroyDescriptorPool(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_descriptorSetLayouts.empty())
{
if (destroyer_descriptorSetLayouts.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_descriptorSetLayouts.front();
destroyer_descriptorSetLayouts.pop_front();
vkDestroyDescriptorSetLayout(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_descriptorUpdateTemplates.empty())
{
if (destroyer_descriptorUpdateTemplates.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_descriptorUpdateTemplates.front();
destroyer_descriptorUpdateTemplates.pop_front();
vkDestroyDescriptorUpdateTemplate(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_shadermodules.empty())
{
if (destroyer_shadermodules.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_shadermodules.front();
destroyer_shadermodules.pop_front();
vkDestroyShaderModule(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_pipelineLayouts.empty())
{
if (destroyer_pipelineLayouts.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_pipelineLayouts.front();
destroyer_pipelineLayouts.pop_front();
vkDestroyPipelineLayout(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_pipelines.empty())
{
if (destroyer_pipelines.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_pipelines.front();
destroyer_pipelines.pop_front();
vkDestroyPipeline(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_querypools.empty())
{
if (destroyer_querypools.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_querypools.front();
destroyer_querypools.pop_front();
vkDestroyQueryPool(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_swapchains.empty())
{
if (destroyer_swapchains.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_swapchains.front();
destroyer_swapchains.pop_front();
vkDestroySwapchainKHR(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_surfaces.empty())
{
if (destroyer_surfaces.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_surfaces.front();
destroyer_surfaces.pop_front();
vkDestroySurfaceKHR(instance, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_semaphores.empty())
{
if (destroyer_semaphores.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_semaphores.front();
destroyer_semaphores.pop_front();
vkDestroySemaphore(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_video_sessions.empty())
{
if (destroyer_video_sessions.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_video_sessions.front();
destroyer_video_sessions.pop_front();
vkDestroyVideoSessionKHR(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_video_session_parameters.empty())
{
if (destroyer_video_session_parameters.front().second + BUFFERCOUNT < FRAMECOUNT)
{
auto item = destroyer_video_session_parameters.front();
destroyer_video_session_parameters.pop_front();
vkDestroyVideoSessionParametersKHR(device, item.first, nullptr);
}
else
{
break;
}
}
while (!destroyer_bindlessSampledImages.empty())
{
if (destroyer_bindlessSampledImages.front().second + BUFFERCOUNT < FRAMECOUNT)
{
int index = destroyer_bindlessSampledImages.front().first;
destroyer_bindlessSampledImages.pop_front();
bindlessSampledImages.free(index);
}
else
{
break;
}
}
while (!destroyer_bindlessUniformTexelBuffers.empty())
{
if (destroyer_bindlessUniformTexelBuffers.front().second + BUFFERCOUNT < FRAMECOUNT)
{
int index = destroyer_bindlessUniformTexelBuffers.front().first;
destroyer_bindlessUniformTexelBuffers.pop_front();
bindlessUniformTexelBuffers.free(index);
}
else
{
break;
}
}
while (!destroyer_bindlessStorageBuffers.empty())
{
if (destroyer_bindlessStorageBuffers.front().second + BUFFERCOUNT < FRAMECOUNT)
{
int index = destroyer_bindlessStorageBuffers.front().first;
destroyer_bindlessStorageBuffers.pop_front();
bindlessStorageBuffers.free(index);
}
else
{
break;
}
}
while (!destroyer_bindlessStorageImages.empty())
{
if (destroyer_bindlessStorageImages.front().second + BUFFERCOUNT < FRAMECOUNT)
{
int index = destroyer_bindlessStorageImages.front().first;
destroyer_bindlessStorageImages.pop_front();
bindlessStorageImages.free(index);
}
else
{
break;
}
}
while (!destroyer_bindlessStorageTexelBuffers.empty())
{
if (destroyer_bindlessStorageTexelBuffers.front().second + BUFFERCOUNT < FRAMECOUNT)
{
int index = destroyer_bindlessStorageTexelBuffers.front().first;
destroyer_bindlessStorageTexelBuffers.pop_front();
bindlessStorageTexelBuffers.free(index);
}
else
{
break;
}
}
while (!destroyer_bindlessSamplers.empty())
{
if (destroyer_bindlessSamplers.front().second + BUFFERCOUNT < FRAMECOUNT)
{
int index = destroyer_bindlessSamplers.front().first;
destroyer_bindlessSamplers.pop_front();
bindlessSamplers.free(index);
}
else
{
break;
}
}
while (!destroyer_bindlessAccelerationStructures.empty())
{
if (destroyer_bindlessAccelerationStructures.front().second + BUFFERCOUNT < FRAMECOUNT)
{
int index = destroyer_bindlessAccelerationStructures.front().first;
destroyer_bindlessAccelerationStructures.pop_front();
bindlessAccelerationStructures.free(index);
}
else
{
break;
}
}
destroylocker.lock();
destroy(destroyer_allocations, [&](auto& item) {
vmaFreeMemory(allocator, item);
});
destroy(destroyer_images, [&](auto& item) {
vmaDestroyImage(allocator, item.first, item.second);
});
destroy(destroyer_imageviews, [&](auto& item) {
vkDestroyImageView(device, item, nullptr);
});
destroy(destroyer_buffers, [&](auto& item) {
vmaDestroyBuffer(allocator, item.first, item.second);
});
destroy(destroyer_bufferviews, [&](auto& item) {
vkDestroyBufferView(device, item, nullptr);
});
destroy(destroyer_bvhs, [&](auto& item) {
vkDestroyAccelerationStructureKHR(device, item, nullptr);
});
destroy(destroyer_samplers, [&](auto& item) {
vkDestroySampler(device, item, nullptr);
});
destroy(destroyer_descriptorPools, [&](auto& item) {
vkDestroyDescriptorPool(device, item, nullptr);
});
destroy(destroyer_descriptorSetLayouts, [&](auto& item) {
vkDestroyDescriptorSetLayout(device, item, nullptr);
});
destroy(destroyer_descriptorUpdateTemplates, [&](auto& item) {
vkDestroyDescriptorUpdateTemplate(device, item, nullptr);
});
destroy(destroyer_shadermodules, [&](auto& item) {
vkDestroyShaderModule(device, item, nullptr);
});
destroy(destroyer_pipelineLayouts, [&](auto& item) {
vkDestroyPipelineLayout(device, item, nullptr);
});
destroy(destroyer_pipelines, [&](auto& item) {
vkDestroyPipeline(device, item, nullptr);
});
destroy(destroyer_querypools, [&](auto& item) {
vkDestroyQueryPool(device, item, nullptr);
});
destroy(destroyer_swapchains, [&](auto& item) {
vkDestroySwapchainKHR(device, item, nullptr);
});
destroy(destroyer_surfaces, [&](auto& item) {
vkDestroySurfaceKHR(instance, item, nullptr);
});
destroy(destroyer_semaphores, [&](auto& item) {
vkDestroySemaphore(device, item, nullptr);
});
destroy(destroyer_video_sessions, [&](auto& item) {
vkDestroyVideoSessionKHR(device, item, nullptr);
});
destroy(destroyer_video_session_parameters, [&](auto& item) {
vkDestroyVideoSessionParametersKHR(device, item, nullptr);
});
destroy(destroyer_bindlessSampledImages, [&](auto& item) {
bindlessSampledImages.free(item);
});
destroy(destroyer_bindlessUniformTexelBuffers, [&](auto& item) {
bindlessUniformTexelBuffers.free(item);
});
destroy(destroyer_bindlessStorageBuffers, [&](auto& item) {
bindlessStorageBuffers.free(item);
});
destroy(destroyer_bindlessStorageImages, [&](auto& item) {
bindlessStorageImages.free(item);
});
destroy(destroyer_bindlessStorageTexelBuffers, [&](auto& item) {
bindlessStorageTexelBuffers.free(item);
});
destroy(destroyer_bindlessSamplers, [&](auto& item) {
bindlessSamplers.free(item);
});
destroy(destroyer_bindlessAccelerationStructures, [&](auto& item) {
bindlessAccelerationStructures.free(item);
});
destroylocker.unlock();
}
};