From c7b3a08cf35bbb49878f506da59828aa525d1e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 20 Oct 2019 17:04:27 +0200 Subject: [PATCH] Vulkan: Add checks so we don't try to write NULL objects to a descriptor set. (Shouldn't happen, but bad rendering is better than a crash in descriptor writing) --- GPU/Vulkan/VulkanUtil.cpp | 4 +- ext/native/thin3d/thin3d_vulkan.cpp | 63 +++++++++++++++++------------ 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index ad91ec05c2..af4b1ecc96 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -197,7 +197,7 @@ VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1, int n = 0; VkDescriptorImageInfo image1{}; VkDescriptorImageInfo image2{}; - if (tex1) { + if (tex1 && sampler1) { #ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR image1.imageLayout = VK_IMAGE_LAYOUT_GENERAL; #else @@ -213,7 +213,7 @@ VkDescriptorSet Vulkan2D::GetDescriptorSet(VkImageView tex1, VkSampler sampler1, writes[n].dstSet = desc; n++; } - if (tex2) { + if (tex2 && sampler2) { // TODO: Also support LAYOUT_GENERAL to be able to texture from framebuffers without transitioning them? #ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR image2.imageLayout = VK_IMAGE_LAYOUT_GENERAL; diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 2504bdca12..3de9e59db4 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -912,36 +912,47 @@ VkDescriptorSet VKContext::GetOrCreateDescriptorSet(VkBuffer buf) { bufferDesc.range = curPipeline_->GetUBOSize(); VkDescriptorImageInfo imageDesc; - imageDesc.imageView = boundTextures_[0] ? boundTextures_[0]->GetImageView() : VK_NULL_HANDLE; - imageDesc.sampler = boundSamplers_[0] ? boundSamplers_[0]->GetSampler() : VK_NULL_HANDLE; -#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - imageDesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL; -#else - imageDesc.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -#endif VkWriteDescriptorSet writes[2] = {}; - writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[0].dstSet = descSet; - writes[0].dstArrayElement = 0; - writes[0].dstBinding = 0; - writes[0].pBufferInfo = &bufferDesc; - writes[0].pImageInfo = nullptr; - writes[0].pTexelBufferView = nullptr; - writes[0].descriptorCount = 1; - writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[1].dstSet = descSet; - writes[1].dstArrayElement = 0; - writes[1].dstBinding = 1; - writes[1].pBufferInfo = nullptr; - writes[1].pImageInfo = &imageDesc; - writes[1].pTexelBufferView = nullptr; - writes[1].descriptorCount = 1; - writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + // If handles are NULL for whatever buggy reason, it's best to leave the descriptors + // unwritten instead of trying to write a zero, which is not legal. - vkUpdateDescriptorSets(device_, 2, writes, 0, nullptr); + int numWrites = 0; + if (buf) { + writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[numWrites].dstSet = descSet; + writes[numWrites].dstArrayElement = 0; + writes[numWrites].dstBinding = 0; + writes[numWrites].pBufferInfo = &bufferDesc; + writes[numWrites].pImageInfo = nullptr; + writes[numWrites].pTexelBufferView = nullptr; + writes[numWrites].descriptorCount = 1; + writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + numWrites++; + } + + if (boundTextures_[0] && boundTextures_[0]->GetImageView() && boundSamplers_[0] && boundSamplers_[0]->GetSampler()) { + imageDesc.imageView = boundTextures_[0] ? boundTextures_[0]->GetImageView() : VK_NULL_HANDLE; + imageDesc.sampler = boundSamplers_[0] ? boundSamplers_[0]->GetSampler() : VK_NULL_HANDLE; +#ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR + imageDesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL; +#else + imageDesc.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +#endif + writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[numWrites].dstSet = descSet; + writes[numWrites].dstArrayElement = 0; + writes[numWrites].dstBinding = 1; + writes[numWrites].pBufferInfo = nullptr; + writes[numWrites].pImageInfo = &imageDesc; + writes[numWrites].pTexelBufferView = nullptr; + writes[numWrites].descriptorCount = 1; + writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + numWrites++; + } + + vkUpdateDescriptorSets(device_, numWrites, writes, 0, nullptr); frame->descSets_[key] = descSet; return descSet;