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:
@@ -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 = {};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user