From 8a78d24a31f62f372fc7948b1fdef589570dbaea Mon Sep 17 00:00:00 2001 From: Laura Hermanns Date: Tue, 21 May 2024 20:47:15 -0400 Subject: [PATCH] [Metal] Fixed crash in Metal PSO creation when invalid shaders are provided. LLGL should no longer throw an exception on PSO creation failure. This replaces the old behavior in the Metal backend with the error report like in the other baackends. --- .../Metal/RenderState/MTComputePSO.mm | 10 +++++++-- .../Metal/RenderState/MTGraphicsPSO.h | 2 +- .../Metal/RenderState/MTGraphicsPSO.mm | 21 +++++++++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/sources/Renderer/Metal/RenderState/MTComputePSO.mm b/sources/Renderer/Metal/RenderState/MTComputePSO.mm index a3236d5f0e..15f0ddc4dd 100644 --- a/sources/Renderer/Metal/RenderState/MTComputePSO.mm +++ b/sources/Renderer/Metal/RenderState/MTComputePSO.mm @@ -25,11 +25,17 @@ /* Get native shader functions */ computeShader_ = LLGL_CAST(const MTShader*, desc.computeShader); if (!computeShader_) - throw std::invalid_argument("cannot create Metal compute pipeline without compute shader"); + { + GetMutableReport().Errorf("cannot create Metal compute pipeline without compute shader"); + return; + } id kernelFunc = computeShader_->GetNative(); if (!kernelFunc) - throw std::invalid_argument("cannot create Metal compute pipeline without valid compute kernel function"); + { + GetMutableReport().Errorf("cannot create Metal compute pipeline without valid compute kernel function"); + return; + } /* Create native compute pipeline state */ NSError* error = nullptr; diff --git a/sources/Renderer/Metal/RenderState/MTGraphicsPSO.h b/sources/Renderer/Metal/RenderState/MTGraphicsPSO.h index 459c8a4a0d..9d8249cf82 100644 --- a/sources/Renderer/Metal/RenderState/MTGraphicsPSO.h +++ b/sources/Renderer/Metal/RenderState/MTGraphicsPSO.h @@ -91,7 +91,7 @@ class MTGraphicsPSO final : public MTPipelineState private: - void CreateRenderPipelineState( + bool CreateRenderPipelineState( id device, const GraphicsPipelineDescriptor& desc, const MTRenderPass* defaultRenderPass diff --git a/sources/Renderer/Metal/RenderState/MTGraphicsPSO.mm b/sources/Renderer/Metal/RenderState/MTGraphicsPSO.mm index e82f17a14c..cec2c7e9f4 100644 --- a/sources/Renderer/Metal/RenderState/MTGraphicsPSO.mm +++ b/sources/Renderer/Metal/RenderState/MTGraphicsPSO.mm @@ -74,9 +74,11 @@ static void FillDefaultMTStencilDesc(MTLStencilDescriptor* dst) blendColor_[3] = desc.blend.blendFactor[3]; /* Create render pipeline and depth-stencil states */ - CreateRenderPipelineState(device, desc, defaultRenderPass); - CreateDepthStencilState(device, desc); - BuildStaticStateBuffer(desc); + if (CreateRenderPipelineState(device, desc, defaultRenderPass)) + { + CreateDepthStencilState(device, desc); + BuildStaticStateBuffer(desc); + } } void MTGraphicsPSO::Bind(id renderEncoder) @@ -202,7 +204,7 @@ static void FillColorAttachmentDesc( return vertexShaderMT; } -void MTGraphicsPSO::CreateRenderPipelineState( +bool MTGraphicsPSO::CreateRenderPipelineState( id device, const GraphicsPipelineDescriptor& desc, const MTRenderPass* defaultRenderPass) @@ -214,7 +216,16 @@ static void FillColorAttachmentDesc( numPatchControlPoints_ = vertexShaderMT->GetNumPatchControlPoints(); if (id vertexFunc = vertexShaderMT->GetNative()) + { + /* Cache patch type of vertex function */ patchType_ = [vertexFunc patchType]; + } + else + { + /* Error: Every graphics PSO needs a valid vertex function */ + GetMutableReport().Errorf("cannot create Metal graphics PSO without valid vertex function"); + return false; + } /* Get render pass object */ const MTRenderPass* renderPassMT = nullptr; @@ -288,6 +299,8 @@ static void FillColorAttachmentDesc( else throw std::invalid_argument("cannot create Metal tessellation pipeline without tessellation compute shader"); } + + return true; } id MTGraphicsPSO::CreateNativeRenderPipelineState(