From 91f295c45e29f4f11a7225abb8d5e538e40def72 Mon Sep 17 00:00:00 2001 From: aperezro Date: Mon, 8 Jun 2026 09:06:13 -0600 Subject: [PATCH] Fix iOS Metal generated entry point patch --- tools/patches/plume-ios-metal.patch | 82 ++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/tools/patches/plume-ios-metal.patch b/tools/patches/plume-ios-metal.patch index db8b2141..61a2378d 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..970cb85 100644 +index ebbbaa3..0155004 100644 --- a/plume_metal.cpp +++ b/plume_metal.cpp @@ -14,8 +14,12 @@ @@ -258,7 +258,7 @@ index ebbbaa3..970cb85 100644 #include "plume_metal.h" -@@ -38,6 +42,232 @@ namespace plume { +@@ -38,6 +42,264 @@ namespace plume { return (n + alignment - 1) & ~(alignment - 1); } @@ -351,18 +351,50 @@ index ebbbaa3..970cb85 100644 + }; + +#if PLUME_IOS ++ size_t findMetalEntryPointOpenParen(const std::string& source, const std::string& entryPointName, const char* builtinName) { ++ if (!entryPointName.empty()) { ++ const std::string functionNeedle = entryPointName + "("; ++ const size_t functionNameOffset = source.find(functionNeedle); ++ if (functionNameOffset != std::string::npos) { ++ return functionNameOffset + entryPointName.size(); ++ } ++ } ++ ++ for (const char* stagePrefix : { "vertex ", "fragment ", "kernel " }) { ++ size_t searchOffset = 0; ++ while (true) { ++ const size_t stageOffset = source.find(stagePrefix, searchOffset); ++ if (stageOffset == std::string::npos) { ++ break; ++ } ++ ++ const size_t openParenOffset = source.find('(', stageOffset); ++ const size_t openBraceOffset = source.find('{', openParenOffset); ++ if (openParenOffset == std::string::npos || openBraceOffset == std::string::npos) { ++ break; ++ } ++ ++ if (source.find(builtinName, openBraceOffset) != std::string::npos) { ++ return openParenOffset; ++ } ++ ++ searchOffset = openBraceOffset + 1; ++ } ++ } ++ ++ return std::string::npos; ++ } ++ + void patchImplicitBaseBuiltinArgument(std::string& source, const std::string& entryPointName, const char* builtinName, const char* builtinAttribute) { + if (source.find(builtinName) == std::string::npos || source.find(builtinAttribute) != std::string::npos) { + return; + } + -+ const std::string functionNeedle = entryPointName + "("; -+ const size_t functionNameOffset = source.find(functionNeedle); -+ if (functionNameOffset == std::string::npos) { ++ const size_t openParenOffset = findMetalEntryPointOpenParen(source, entryPointName, builtinName); ++ if (openParenOffset == std::string::npos) { + return; + } + -+ const size_t openParenOffset = functionNameOffset + entryPointName.size(); + size_t closeParenOffset = std::string::npos; + int depth = 0; + @@ -491,7 +523,7 @@ index ebbbaa3..970cb85 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 +1363,7 @@ namespace plume { +@@ -1133,7 +1395,7 @@ namespace plume { } uint64_t MetalBuffer::getDeviceAddress() const { @@ -500,7 +532,7 @@ index ebbbaa3..970cb85 100644 return mtl->gpuAddress(); } -@@ -1278,24 +1508,46 @@ namespace plume { +@@ -1278,24 +1540,46 @@ namespace plume { assert(device != nullptr); assert(data != nullptr); assert(size > 0); @@ -553,7 +585,7 @@ index ebbbaa3..970cb85 100644 if (debugName) { debugName->release(); } -@@ -1306,10 +1558,16 @@ namespace plume { +@@ -1306,10 +1590,16 @@ namespace plume { debugName->release(); } debugName = NS::String::string(name.c_str(), NS::UTF8StringEncoding); @@ -571,7 +603,7 @@ index ebbbaa3..970cb85 100644 MTL::FunctionConstantValues *values = MTL::FunctionConstantValues::alloc()->init(); if (specConstants != nullptr) { for (uint32_t i = 0; i < specConstantsCount; i++) { -@@ -1437,6 +1695,13 @@ namespace plume { +@@ -1437,6 +1727,13 @@ namespace plume { const MetalShader *metalShader = static_cast(desc.vertexShader); MTL::Function *vertexFunction = metalShader->createFunction(desc.specConstants, desc.specConstantsCount); @@ -585,7 +617,7 @@ index ebbbaa3..970cb85 100644 descriptor->setVertexFunction(vertexFunction); MTL::VertexDescriptor *vertexDescriptor = MTL::VertexDescriptor::alloc()->init(); -@@ -1479,6 +1744,15 @@ namespace plume { +@@ -1479,6 +1776,15 @@ namespace plume { if (desc.pixelShader != nullptr) { const MetalShader *pixelShader = static_cast(desc.pixelShader); MTL::Function *fragmentFunction = pixelShader->createFunction(desc.specConstants, desc.specConstantsCount); @@ -601,7 +633,7 @@ index ebbbaa3..970cb85 100644 descriptor->setFragmentFunction(fragmentFunction); fragmentFunction->release(); } -@@ -1547,8 +1821,24 @@ namespace plume { +@@ -1547,8 +1853,24 @@ namespace plume { state.depthBiasSlopeFactor = desc.slopeScaledDepthBias; } @@ -628,7 +660,7 @@ index ebbbaa3..970cb85 100644 return; } -@@ -1793,6 +2083,11 @@ namespace plume { +@@ -1793,6 +2115,11 @@ namespace plume { MetalSwapChain::MetalSwapChain(MetalCommandQueue *commandQueue, const RenderWindow renderWindow, uint32_t textureCount, const RenderFormat format) { this->layer = static_cast(renderWindow.view); @@ -640,7 +672,7 @@ index ebbbaa3..970cb85 100644 layer->setDevice(commandQueue->device->mtl); layer->setPixelFormat(mapPixelFormat(format)); -@@ -1819,7 +2114,10 @@ namespace plume { +@@ -1819,7 +2146,10 @@ namespace plume { } bool MetalSwapChain::present(const uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, const uint32_t waitSemaphoreCount) { @@ -652,7 +684,7 @@ index ebbbaa3..970cb85 100644 NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init(); const MetalDrawable &drawable = drawables[textureIndex]; -@@ -1861,7 +2159,7 @@ namespace plume { +@@ -1861,7 +2191,7 @@ namespace plume { bool MetalSwapChain::resize() { getWindowSize(width, height); @@ -661,7 +693,7 @@ index ebbbaa3..970cb85 100644 return false; } -@@ -1886,11 +2184,29 @@ namespace plume { +@@ -1886,11 +2216,29 @@ namespace plume { } void MetalSwapChain::setVsyncEnabled(const bool vsyncEnabled) { @@ -691,7 +723,7 @@ index ebbbaa3..970cb85 100644 } uint32_t MetalSwapChain::getWidth() const { -@@ -1910,6 +2226,10 @@ namespace plume { +@@ -1910,6 +2258,10 @@ namespace plume { assert(textureIndex != nullptr); assert(*textureIndex < MAX_DRAWABLES); @@ -702,7 +734,7 @@ index ebbbaa3..970cb85 100644 NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init(); // Create a command buffer just to encode the signal -@@ -1923,6 +2243,7 @@ namespace plume { +@@ -1923,6 +2275,7 @@ namespace plume { CA::MetalDrawable *nextDrawable = layer->nextDrawable(); if (nextDrawable == nullptr) { fprintf(stderr, "No more drawables available for rendering.\n"); @@ -710,7 +742,7 @@ index ebbbaa3..970cb85 100644 return false; } -@@ -1954,10 +2275,20 @@ namespace plume { +@@ -1954,10 +2307,20 @@ namespace plume { } uint32_t MetalSwapChain::getRefreshRate() const { @@ -731,7 +763,7 @@ index ebbbaa3..970cb85 100644 CocoaWindowAttributes attributes; windowWrapper->getWindowAttributes(&attributes); dstWidth = attributes.width; -@@ -3308,6 +3639,9 @@ namespace plume { +@@ -3308,6 +3671,9 @@ namespace plume { this->renderInterface = renderInterface; // Device Selection @@ -741,7 +773,7 @@ index ebbbaa3..970cb85 100644 const NS::Array* devices = MTL::CopyAllDevices(); MTL::Device *preferredDevice = nullptr; for (NS::UInteger i = 0; i < devices->count(); i++) { -@@ -3320,12 +3654,31 @@ namespace plume { +@@ -3320,12 +3686,31 @@ namespace plume { } mtl = preferredDevice ? preferredDevice : MTL::CreateSystemDefaultDevice();; @@ -774,7 +806,7 @@ index ebbbaa3..970cb85 100644 // Setup blit, clear and resolve shaders / pipelines createClearShaderLibrary(); -@@ -3337,7 +3690,7 @@ namespace plume { +@@ -3337,7 +3722,7 @@ namespace plume { // TODO: Support Raytracing. // capabilities.raytracing = mtl->supportsRaytracing(); capabilities.maxTextureSize = mtl->supportsFamily(MTL::GPUFamilyApple3) ? 16384 : 8192; @@ -783,7 +815,7 @@ index ebbbaa3..970cb85 100644 capabilities.resolveModes = false; #if PLUME_IOS capabilities.descriptorIndexing = mtl->supportsFamily(MTL::GPUFamilyApple3); -@@ -3345,11 +3698,11 @@ namespace plume { +@@ -3345,11 +3730,11 @@ namespace plume { capabilities.descriptorIndexing = true; #endif capabilities.scalarBlockLayout = true; @@ -798,7 +830,7 @@ index ebbbaa3..970cb85 100644 capabilities.gpuUploadHeap = capabilities.uma; capabilities.queryPools = false; -@@ -3357,17 +3710,19 @@ namespace plume { +@@ -3357,17 +3742,19 @@ namespace plume { } MetalDevice::~MetalDevice() { @@ -824,7 +856,7 @@ index ebbbaa3..970cb85 100644 } std::unique_ptr MetalDevice::createDescriptorSet(const RenderDescriptorSetDesc &desc) { -@@ -3635,16 +3990,24 @@ namespace plume { +@@ -3635,16 +4022,24 @@ namespace plume { MetalInterface::MetalInterface() { NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init();