diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index bc7120abc2..648b588d7d 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -719,7 +719,9 @@ VkResult VulkanContext::CreateDevice() { allocatorInfo.physicalDevice = physical_devices_[physical_device_]; allocatorInfo.device = device_; allocatorInfo.instance = instance_; - vmaCreateAllocator(&allocatorInfo, &allocator_); + VkResult result = vmaCreateAllocator(&allocatorInfo, &allocator_); + _assert_(result == VK_SUCCESS); + _assert_(allocator_ != VK_NULL_HANDLE); // Examine the physical device to figure out super rough performance grade. // Basically all we want to do is to identify low performance mobile devices diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index b781784e77..fb92a7a7fa 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -37,6 +37,13 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan, VkRenderPass compatibleR } } + // Sanity check. + // Seen in crash reports from PowerVR GE8320, presumably we failed creating some shader modules. + if (!desc->vertexShader || !desc->fragmentShader) { + ERROR_LOG(G3D, "Failed creating graphics pipeline - missing vs/fs shader module pointers!"); + return false; + } + // Fill in the last part of the desc since now it's time to block. VkShaderModule vs = desc->vertexShader->BlockUntilReady(); VkShaderModule fs = desc->fragmentShader->BlockUntilReady(); @@ -527,8 +534,12 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() { VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc, PipelineFlags pipelineFlags, uint32_t variantBitmask, VkSampleCountFlagBits sampleCount, const char *tag) { VKRGraphicsPipeline *pipeline = new VKRGraphicsPipeline(pipelineFlags, tag); - _dbg_assert_(desc->vertexShader); - _dbg_assert_(desc->fragmentShader); + + if (!desc->vertexShader || !desc->fragmentShader) { + ERROR_LOG(G3D, "Can't create graphics pipeline with missing vs/ps: %p %p", desc->vertexShader, desc->fragmentShader); + return nullptr; + } + pipeline->desc = desc; pipeline->desc->AddRef(); if (curRenderStep_) { @@ -634,6 +645,10 @@ void VulkanRenderManager::EndCurRenderStep() { compileMutex_.lock(); bool needsCompile = false; for (VKRGraphicsPipeline *pipeline : pipelinesToCheck_) { + if (!pipeline) { + // Not good, but let's try not to crash. + continue; + } if (!pipeline->pipeline[(size_t)rpType]) { pipeline->pipeline[(size_t)rpType] = Promise::CreateEmpty(); _assert_(renderPass); diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index e8ae8d9db6..1d097e9f32 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -180,11 +180,25 @@ static std::string CutFromMain(std::string str) { static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, VkPipelineCache pipelineCache, VkPipelineLayout layout, PipelineFlags pipelineFlags, VkSampleCountFlagBits sampleCount, const VulkanPipelineRasterStateKey &key, const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, VulkanGeometryShader *gs, bool useHwTransform, u32 variantBitmask) { + + if (!fs->GetModule()) { + ERROR_LOG(G3D, "Fragment shader missing in CreateVulkanPipeline"); + return nullptr; + } + if (!vs->GetModule()) { + ERROR_LOG(G3D, "Vertex shader missing in CreateVulkanPipeline"); + return nullptr; + } + VulkanPipeline *vulkanPipeline = new VulkanPipeline(); vulkanPipeline->desc = new VKRGraphicsPipelineDesc(); VKRGraphicsPipelineDesc *desc = vulkanPipeline->desc; desc->pipelineCache = pipelineCache; + desc->fragmentShader = fs->GetModule(); + desc->vertexShader = vs->GetModule(); + desc->geometryShader = gs ? gs->GetModule() : nullptr; + PROFILE_THIS_SCOPE("pipelinebuild"); bool useBlendConstant = false; @@ -257,9 +271,6 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, rs.polygonMode = VK_POLYGON_MODE_FILL; rs.depthClampEnable = key.depthClampEnable; - desc->fragmentShader = fs->GetModule(); - desc->vertexShader = vs->GetModule(); - desc->geometryShader = gs ? gs->GetModule() : nullptr; desc->fragmentShaderSource = fs->GetShaderString(SHADER_STRING_SOURCE_CODE); desc->vertexShaderSource = vs->GetShaderString(SHADER_STRING_SOURCE_CODE); if (gs) { @@ -360,6 +371,8 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VulkanRenderManager * VulkanPipeline *pipeline = CreateVulkanPipeline( renderManager, pipelineCache_, layout, pipelineFlags, sampleCount, rasterKey, decFmt, vs, fs, gs, useHwTransform, variantBitmask); + + // If the above failed, we got a null pipeline. We still insert it to keep track. pipelines_.Insert(key, pipeline); // Don't return placeholder null pipelines. diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 8c87421a94..9cae5d6486 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -152,7 +152,9 @@ VulkanVertexShader::VulkanVertexShader(VulkanContext *vulkan, VShaderID id, Vert VulkanVertexShader::~VulkanVertexShader() { if (module_) { VkShaderModule shaderModule = module_->BlockUntilReady(); - vulkan_->Delete().QueueDeleteShaderModule(shaderModule); + if (shaderModule) { + vulkan_->Delete().QueueDeleteShaderModule(shaderModule); + } vulkan_->Delete().QueueCallback([](void *m) { auto module = (Promise *)m; delete module; @@ -185,7 +187,9 @@ VulkanGeometryShader::VulkanGeometryShader(VulkanContext *vulkan, GShaderID id, VulkanGeometryShader::~VulkanGeometryShader() { if (module_) { VkShaderModule shaderModule = module_->BlockUntilReady(); - vulkan_->Delete().QueueDeleteShaderModule(shaderModule); + if (shaderModule) { + vulkan_->Delete().QueueDeleteShaderModule(shaderModule); + } vulkan_->Delete().QueueCallback([](void *m) { auto module = (Promise *)m; delete module;