Vulkan: Improve handling of shader compile failures (don't crash)

This commit is contained in:
Henrik Rydgård 2018-03-19 17:46:58 +01:00
parent 1888d828ec
commit f1359af0b0
3 changed files with 25 additions and 10 deletions

View File

@ -774,7 +774,7 @@ void DrawEngineVulkan::DoFlush() {
Draw::NativeObject object = g_Config.iRenderingMode != 0 ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS;
VkRenderPass renderPass = (VkRenderPass)draw_->GetNativeObject(object);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, &dec_->decFmt, vshader, fshader, true);
if (!pipeline) {
if (!pipeline || !pipeline->pipeline) {
// Already logged, let's bail out.
return;
}
@ -878,7 +878,7 @@ void DrawEngineVulkan::DoFlush() {
Draw::NativeObject object = g_Config.iRenderingMode != 0 ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS;
VkRenderPass renderPass = (VkRenderPass)draw_->GetNativeObject(object);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, &dec_->decFmt, vshader, fshader, false);
if (!pipeline) {
if (!pipeline || !pipeline->pipeline) {
// Already logged, let's bail out.
return;
}

View File

@ -28,7 +28,8 @@ void PipelineManagerVulkan::Clear() {
// store the keys.
pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) {
vulkan_->Delete().QueueDeletePipeline(value->pipeline);
if (value->pipeline)
vulkan_->Delete().QueueDeletePipeline(value->pipeline);
delete value;
});
@ -116,6 +117,7 @@ static bool UsesBlendConstant(int factor) {
static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pipelineCache,
VkPipelineLayout layout, VkRenderPass renderPass, const VulkanPipelineRasterStateKey &key,
const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform, float lineWidth) {
PROFILE_THIS_SCOPE("pipelinebuild");
bool useBlendConstant = false;
VkPipelineColorBlendAttachmentState blend0 = {};
@ -209,7 +211,11 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
if (!ss[0].module || !ss[1].module) {
ERROR_LOG(G3D, "Failed creating graphics pipeline - bad shaders");
return nullptr;
// Create a placeholder to avoid creating over and over if shader compiler broken.
VulkanPipeline *nullPipeline = new VulkanPipeline();
nullPipeline->pipeline = nullptr;
nullPipeline->flags = 0;
return nullPipeline;
}
VkPipelineInputAssemblyStateCreateInfo inputAssembly{ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
@ -277,7 +283,11 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
if (result != VK_SUCCESS) {
_assert_msg_(G3D, false, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
return nullptr;
// Create a placeholder to avoid creating over and over if something is broken.
VulkanPipeline *nullPipeline = new VulkanPipeline();
nullPipeline->pipeline = nullptr;
nullPipeline->flags = 0;
return nullPipeline;
}
VulkanPipeline *vulkanPipeline = new VulkanPipeline();
@ -311,14 +321,17 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo
if (iter)
return iter;
PROFILE_THIS_SCOPE("pipelinebuild");
VulkanPipeline *pipeline = CreateVulkanPipeline(
vulkan_->GetDevice(), pipelineCache_, layout, renderPass,
rasterKey, decFmt, vs, fs, useHwTransform, lineWidth_);
// Even if the result is nullptr, insert it so we don't try to create it repeatedly.
pipelines_.Insert(key, pipeline);
return pipeline;
// Don't return placeholder null pipelines.
if (pipeline && pipeline->pipeline) {
return pipeline;
} else {
return nullptr;
}
}
std::vector<std::string> PipelineManagerVulkan::DebugGetObjectIDs(DebugShaderType type) {
@ -510,7 +523,8 @@ void PipelineManagerVulkan::SetLineWidth(float lineWidth) {
// Wipe all line-drawing pipelines.
pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) {
if (value->UsesLines()) {
vulkan_->Delete().QueueDeletePipeline(value->pipeline);
if (value->pipeline)
vulkan_->Delete().QueueDeletePipeline(value->pipeline);
delete value;
pipelines_.Remove(key);
}

View File

@ -110,6 +110,7 @@ public:
void BindPipeline(VkPipeline pipeline) {
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER);
_dbg_assert_(G3D, pipeline != VK_NULL_HANDLE);
VkRenderData data{ VKRRenderCommand::BIND_PIPELINE };
data.pipeline.pipeline = pipeline;
curRenderStep_->commands.push_back(data);