From e7e617cf75a6365e2416111c3217b0eeae245333 Mon Sep 17 00:00:00 2001 From: aperezro Date: Mon, 8 Jun 2026 02:31:54 -0600 Subject: [PATCH] Fix iOS Metal shader base vertex translation --- tools/patches/plume-ios-metal.patch | 97 +++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 18 deletions(-) diff --git a/tools/patches/plume-ios-metal.patch b/tools/patches/plume-ios-metal.patch index 6ad2d0dd..ae14b6b7 100644 --- a/tools/patches/plume-ios-metal.patch +++ b/tools/patches/plume-ios-metal.patch @@ -242,7 +242,7 @@ index 64e4dc9..1d14600 100644 } } diff --git a/plume_metal.cpp b/plume_metal.cpp -index ebbbaa3..854107a 100644 +index ebbbaa3..e4315c4 100644 --- a/plume_metal.cpp +++ b/plume_metal.cpp @@ -14,8 +14,12 @@ @@ -258,7 +258,7 @@ index ebbbaa3..854107a 100644 #include "plume_metal.h" -@@ -38,6 +42,186 @@ namespace plume { +@@ -38,6 +42,190 @@ namespace plume { return (n + alignment - 1) & ~(alignment - 1); } @@ -388,7 +388,11 @@ index ebbbaa3..854107a 100644 + options.set_msl_version(3, 0); + options.argument_buffers = true; + options.argument_buffers_tier = getArgumentBuffersTier(device->mtl); ++#if PLUME_IOS ++ options.enable_base_index_zero = false; ++#else + options.enable_base_index_zero = true; ++#endif + options.enable_decoration_binding = true; + options.force_active_argument_buffer_resources = true; + options.texture_buffer_native = true; @@ -445,7 +449,7 @@ index ebbbaa3..854107a 100644 uint64_t createClearPipelineKey(MTL::RenderPipelineDescriptor *pipelineDesc, bool depthWriteEnabled, bool stencilWriteEnabled) { auto colorFormat = [&](uint32_t index) { if (auto colorAttachment = pipelineDesc->colorAttachments()->object(index)) { -@@ -1133,7 +1317,7 @@ namespace plume { +@@ -1133,7 +1321,7 @@ namespace plume { } uint64_t MetalBuffer::getDeviceAddress() const { @@ -454,7 +458,7 @@ index ebbbaa3..854107a 100644 return mtl->gpuAddress(); } -@@ -1278,24 +1462,46 @@ namespace plume { +@@ -1278,24 +1466,46 @@ namespace plume { assert(device != nullptr); assert(data != nullptr); assert(size > 0); @@ -507,7 +511,7 @@ index ebbbaa3..854107a 100644 if (debugName) { debugName->release(); } -@@ -1306,10 +1512,16 @@ namespace plume { +@@ -1306,10 +1516,16 @@ namespace plume { debugName->release(); } debugName = NS::String::string(name.c_str(), NS::UTF8StringEncoding); @@ -525,7 +529,64 @@ index ebbbaa3..854107a 100644 MTL::FunctionConstantValues *values = MTL::FunctionConstantValues::alloc()->init(); if (specConstants != nullptr) { for (uint32_t i = 0; i < specConstantsCount; i++) { -@@ -1793,6 +2005,11 @@ namespace plume { +@@ -1437,6 +1653,13 @@ namespace plume { + const MetalShader *metalShader = static_cast(desc.vertexShader); + + MTL::Function *vertexFunction = metalShader->createFunction(desc.specConstants, desc.specConstantsCount); ++ if (vertexFunction == nullptr) { ++ fprintf(stderr, "Metal graphics pipeline creation failed: vertex shader function is null.\n"); ++ descriptor->release(); ++ releasePool->release(); ++ return; ++ } ++ + descriptor->setVertexFunction(vertexFunction); + + MTL::VertexDescriptor *vertexDescriptor = MTL::VertexDescriptor::alloc()->init(); +@@ -1479,6 +1702,15 @@ namespace plume { + if (desc.pixelShader != nullptr) { + const MetalShader *pixelShader = static_cast(desc.pixelShader); + MTL::Function *fragmentFunction = pixelShader->createFunction(desc.specConstants, desc.specConstantsCount); ++ if (fragmentFunction == nullptr) { ++ fprintf(stderr, "Metal graphics pipeline creation failed: fragment shader function is null.\n"); ++ vertexDescriptor->release(); ++ vertexFunction->release(); ++ descriptor->release(); ++ releasePool->release(); ++ return; ++ } ++ + descriptor->setFragmentFunction(fragmentFunction); + fragmentFunction->release(); + } +@@ -1547,8 +1779,24 @@ namespace plume { + state.depthBiasSlopeFactor = desc.slopeScaledDepthBias; + } + +- if (error != nullptr) { +- fprintf(stderr, "MTLDevice newRenderPipelineState: failed with error %s.\n", error->localizedDescription()->utf8String()); ++ if (error != nullptr || state.renderPipelineState == nullptr) { ++ if (error != nullptr) { ++ fprintf(stderr, "MTLDevice newRenderPipelineState: failed with error %s.\n", error->localizedDescription()->utf8String()); ++ } else { ++ fprintf(stderr, "MTLDevice newRenderPipelineState: failed without an error object.\n"); ++ } ++ ++ vertexDescriptor->release(); ++ vertexFunction->release(); ++ descriptor->release(); ++ depthStencilDescriptor->release(); ++ if (frontFaceStencilDescriptor) { ++ frontFaceStencilDescriptor->release(); ++ } ++ if (backFaceStencilDescriptor) { ++ backFaceStencilDescriptor->release(); ++ } ++ releasePool->release(); + return; + } + +@@ -1793,6 +2041,11 @@ namespace plume { MetalSwapChain::MetalSwapChain(MetalCommandQueue *commandQueue, const RenderWindow renderWindow, uint32_t textureCount, const RenderFormat format) { this->layer = static_cast(renderWindow.view); @@ -537,7 +598,7 @@ index ebbbaa3..854107a 100644 layer->setDevice(commandQueue->device->mtl); layer->setPixelFormat(mapPixelFormat(format)); -@@ -1819,7 +2036,10 @@ namespace plume { +@@ -1819,7 +2072,10 @@ namespace plume { } bool MetalSwapChain::present(const uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, const uint32_t waitSemaphoreCount) { @@ -549,7 +610,7 @@ index ebbbaa3..854107a 100644 NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init(); const MetalDrawable &drawable = drawables[textureIndex]; -@@ -1861,7 +2081,7 @@ namespace plume { +@@ -1861,7 +2117,7 @@ namespace plume { bool MetalSwapChain::resize() { getWindowSize(width, height); @@ -558,7 +619,7 @@ index ebbbaa3..854107a 100644 return false; } -@@ -1886,11 +2106,29 @@ namespace plume { +@@ -1886,11 +2142,29 @@ namespace plume { } void MetalSwapChain::setVsyncEnabled(const bool vsyncEnabled) { @@ -588,7 +649,7 @@ index ebbbaa3..854107a 100644 } uint32_t MetalSwapChain::getWidth() const { -@@ -1910,6 +2148,10 @@ namespace plume { +@@ -1910,6 +2184,10 @@ namespace plume { assert(textureIndex != nullptr); assert(*textureIndex < MAX_DRAWABLES); @@ -599,7 +660,7 @@ index ebbbaa3..854107a 100644 NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init(); // Create a command buffer just to encode the signal -@@ -1923,6 +2165,7 @@ namespace plume { +@@ -1923,6 +2201,7 @@ namespace plume { CA::MetalDrawable *nextDrawable = layer->nextDrawable(); if (nextDrawable == nullptr) { fprintf(stderr, "No more drawables available for rendering.\n"); @@ -607,7 +668,7 @@ index ebbbaa3..854107a 100644 return false; } -@@ -1954,10 +2197,20 @@ namespace plume { +@@ -1954,10 +2233,20 @@ namespace plume { } uint32_t MetalSwapChain::getRefreshRate() const { @@ -628,7 +689,7 @@ index ebbbaa3..854107a 100644 CocoaWindowAttributes attributes; windowWrapper->getWindowAttributes(&attributes); dstWidth = attributes.width; -@@ -3308,6 +3561,9 @@ namespace plume { +@@ -3308,6 +3597,9 @@ namespace plume { this->renderInterface = renderInterface; // Device Selection @@ -638,7 +699,7 @@ index ebbbaa3..854107a 100644 const NS::Array* devices = MTL::CopyAllDevices(); MTL::Device *preferredDevice = nullptr; for (NS::UInteger i = 0; i < devices->count(); i++) { -@@ -3320,12 +3576,31 @@ namespace plume { +@@ -3320,12 +3612,31 @@ namespace plume { } mtl = preferredDevice ? preferredDevice : MTL::CreateSystemDefaultDevice();; @@ -671,7 +732,7 @@ index ebbbaa3..854107a 100644 // Setup blit, clear and resolve shaders / pipelines createClearShaderLibrary(); -@@ -3337,7 +3612,7 @@ namespace plume { +@@ -3337,7 +3648,7 @@ namespace plume { // TODO: Support Raytracing. // capabilities.raytracing = mtl->supportsRaytracing(); capabilities.maxTextureSize = mtl->supportsFamily(MTL::GPUFamilyApple3) ? 16384 : 8192; @@ -680,7 +741,7 @@ index ebbbaa3..854107a 100644 capabilities.resolveModes = false; #if PLUME_IOS capabilities.descriptorIndexing = mtl->supportsFamily(MTL::GPUFamilyApple3); -@@ -3345,11 +3620,11 @@ namespace plume { +@@ -3345,11 +3656,11 @@ namespace plume { capabilities.descriptorIndexing = true; #endif capabilities.scalarBlockLayout = true; @@ -695,7 +756,7 @@ index ebbbaa3..854107a 100644 capabilities.gpuUploadHeap = capabilities.uma; capabilities.queryPools = false; -@@ -3357,17 +3632,19 @@ namespace plume { +@@ -3357,17 +3668,19 @@ namespace plume { } MetalDevice::~MetalDevice() { @@ -721,7 +782,7 @@ index ebbbaa3..854107a 100644 } std::unique_ptr MetalDevice::createDescriptorSet(const RenderDescriptorSetDesc &desc) { -@@ -3635,16 +3912,24 @@ namespace plume { +@@ -3635,16 +3948,24 @@ namespace plume { MetalInterface::MetalInterface() { NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init();