@@ -242,7 +242,7 @@ index 64e4dc9..1d14600 100644
242242 }
243243 }
244244diff --git a/plume_metal.cpp b/plume_metal.cpp
245- index ebbbaa3..0155004 100644
245+ index ebbbaa3..c72adf6 100644
246246--- a/plume_metal.cpp
247247+++ b/plume_metal.cpp
248248@@ -14,8 +14,12 @@
@@ -258,7 +258,7 @@ index ebbbaa3..0155004 100644
258258
259259 #include "plume_metal.h"
260260
261- @@ -38,6 +42,264 @@ namespace plume {
261+ @@ -38,6 +42,304 @@ namespace plume {
262262 return (n + alignment - 1) & ~(alignment - 1);
263263 }
264264
@@ -351,6 +351,45 @@ index ebbbaa3..0155004 100644
351351+ };
352352+
353353+ #if PLUME_IOS
354+ + bool isMetalIdentifierChar(const char c) {
355+ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
356+ + }
357+ +
358+ + std::string findMetalEntryPointName(const std::string& source, const std::string& fallbackName) {
359+ + for (const char* stagePrefix : { "vertex ", "fragment ", "kernel " }) {
360+ + size_t searchOffset = 0;
361+ + while (true) {
362+ + const size_t stageOffset = source.find(stagePrefix, searchOffset);
363+ + if (stageOffset == std::string::npos) {
364+ + break;
365+ + }
366+ +
367+ + const size_t openParenOffset = source.find('(', stageOffset);
368+ + if (openParenOffset == std::string::npos) {
369+ + break;
370+ + }
371+ +
372+ + size_t nameEnd = openParenOffset;
373+ + while (nameEnd > stageOffset && (source[nameEnd - 1] == ' ' || source[nameEnd - 1] == '\t' || source[nameEnd - 1] == '\r' || source[nameEnd - 1] == '\n')) {
374+ + nameEnd--;
375+ + }
376+ +
377+ + size_t nameStart = nameEnd;
378+ + while (nameStart > stageOffset && isMetalIdentifierChar(source[nameStart - 1])) {
379+ + nameStart--;
380+ + }
381+ +
382+ + if (nameStart < nameEnd) {
383+ + return source.substr(nameStart, nameEnd - nameStart);
384+ + }
385+ +
386+ + searchOffset = openParenOffset + 1;
387+ + }
388+ + }
389+ +
390+ + return fallbackName;
391+ + }
392+ +
354393+ size_t findMetalEntryPointOpenParen(const std::string& source, const std::string& entryPointName, const char* builtinName) {
355394+ if (!entryPointName.empty()) {
356395+ const std::string functionNeedle = entryPointName + "(";
@@ -514,6 +553,7 @@ index ebbbaa3..0155004 100644
514553+ translatedSource.entryPointName = compiler.get_cleansed_entry_point_name(spirvEntryPointName, executionModel);
515554+ translatedSource.source = compiler.compile();
516555+ #if PLUME_IOS
556+ + translatedSource.entryPointName = findMetalEntryPointName(translatedSource.source, translatedSource.entryPointName);
517557+ patchImplicitBaseBuiltinArguments(translatedSource.source, translatedSource.entryPointName);
518558+ #endif
519559+
@@ -523,7 +563,7 @@ index ebbbaa3..0155004 100644
523563 uint64_t createClearPipelineKey(MTL::RenderPipelineDescriptor *pipelineDesc, bool depthWriteEnabled, bool stencilWriteEnabled) {
524564 auto colorFormat = [&](uint32_t index) {
525565 if (auto colorAttachment = pipelineDesc->colorAttachments()->object(index)) {
526- @@ -1133,7 +1395 ,7 @@ namespace plume {
566+ @@ -1133,7 +1435 ,7 @@ namespace plume {
527567 }
528568
529569 uint64_t MetalBuffer::getDeviceAddress() const {
@@ -532,7 +572,7 @@ index ebbbaa3..0155004 100644
532572 return mtl->gpuAddress();
533573 }
534574
535- @@ -1278,24 +1540 ,46 @@ namespace plume {
575+ @@ -1278,24 +1580 ,46 @@ namespace plume {
536576 assert(device != nullptr);
537577 assert(data != nullptr);
538578 assert(size > 0);
@@ -585,7 +625,7 @@ index ebbbaa3..0155004 100644
585625 if (debugName) {
586626 debugName->release();
587627 }
588- @@ -1306,10 +1590 ,16 @@ namespace plume {
628+ @@ -1306,10 +1630 ,16 @@ namespace plume {
589629 debugName->release();
590630 }
591631 debugName = NS::String::string(name.c_str(), NS::UTF8StringEncoding);
@@ -603,7 +643,30 @@ index ebbbaa3..0155004 100644
603643 MTL::FunctionConstantValues *values = MTL::FunctionConstantValues::alloc()->init();
604644 if (specConstants != nullptr) {
605645 for (uint32_t i = 0; i < specConstantsCount; i++) {
606- @@ -1437,6 +1727,13 @@ namespace plume {
646+ @@ -1325,6 +1655,10 @@ namespace plume {
647+ fprintf(stderr, "MTLLibrary newFunction: failed with error: %s.\n", error->localizedDescription()->utf8String());
648+ return nullptr;
649+ }
650+ + if (function == nullptr) {
651+ + fprintf(stderr, "MTLLibrary newFunction: failed without an error object.\n");
652+ + return nullptr;
653+ + }
654+
655+ if (debugName) {
656+ function->setLabel(debugName);
657+ @@ -1384,6 +1718,11 @@ namespace plume {
658+
659+ MTL::ComputePipelineDescriptor *descriptor = MTL::ComputePipelineDescriptor::alloc()->init();
660+ MTL::Function *function = computeShader->createFunction(desc.specConstants, desc.specConstantsCount);
661+ + if (function == nullptr) {
662+ + fprintf(stderr, "Metal compute pipeline creation failed: shader function is null.\n");
663+ + descriptor->release();
664+ + return;
665+ + }
666+ descriptor->setComputeFunction(function);
667+ descriptor->setLabel(computeShader->functionName);
668+
669+ @@ -1437,6 +1776,13 @@ namespace plume {
607670 const MetalShader *metalShader = static_cast<const MetalShader *>(desc.vertexShader);
608671
609672 MTL::Function *vertexFunction = metalShader->createFunction(desc.specConstants, desc.specConstantsCount);
@@ -617,7 +680,7 @@ index ebbbaa3..0155004 100644
617680 descriptor->setVertexFunction(vertexFunction);
618681
619682 MTL::VertexDescriptor *vertexDescriptor = MTL::VertexDescriptor::alloc()->init();
620- @@ -1479,6 +1776 ,15 @@ namespace plume {
683+ @@ -1479,6 +1825 ,15 @@ namespace plume {
621684 if (desc.pixelShader != nullptr) {
622685 const MetalShader *pixelShader = static_cast<const MetalShader *>(desc.pixelShader);
623686 MTL::Function *fragmentFunction = pixelShader->createFunction(desc.specConstants, desc.specConstantsCount);
@@ -633,7 +696,7 @@ index ebbbaa3..0155004 100644
633696 descriptor->setFragmentFunction(fragmentFunction);
634697 fragmentFunction->release();
635698 }
636- @@ -1547,8 +1853 ,24 @@ namespace plume {
699+ @@ -1547,8 +1902 ,24 @@ namespace plume {
637700 state.depthBiasSlopeFactor = desc.slopeScaledDepthBias;
638701 }
639702
@@ -660,7 +723,7 @@ index ebbbaa3..0155004 100644
660723 return;
661724 }
662725
663- @@ -1793,6 +2115 ,11 @@ namespace plume {
726+ @@ -1793,6 +2164 ,11 @@ namespace plume {
664727
665728 MetalSwapChain::MetalSwapChain(MetalCommandQueue *commandQueue, const RenderWindow renderWindow, uint32_t textureCount, const RenderFormat format) {
666729 this->layer = static_cast<CA::MetalLayer*>(renderWindow.view);
@@ -672,7 +735,7 @@ index ebbbaa3..0155004 100644
672735 layer->setDevice(commandQueue->device->mtl);
673736 layer->setPixelFormat(mapPixelFormat(format));
674737
675- @@ -1819,7 +2146 ,10 @@ namespace plume {
738+ @@ -1819,7 +2195 ,10 @@ namespace plume {
676739 }
677740
678741 bool MetalSwapChain::present(const uint32_t textureIndex, RenderCommandSemaphore **waitSemaphores, const uint32_t waitSemaphoreCount) {
@@ -684,7 +747,7 @@ index ebbbaa3..0155004 100644
684747 NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init();
685748
686749 const MetalDrawable &drawable = drawables[textureIndex];
687- @@ -1861,7 +2191 ,7 @@ namespace plume {
750+ @@ -1861,7 +2240 ,7 @@ namespace plume {
688751 bool MetalSwapChain::resize() {
689752 getWindowSize(width, height);
690753
@@ -693,7 +756,7 @@ index ebbbaa3..0155004 100644
693756 return false;
694757 }
695758
696- @@ -1886,11 +2216 ,29 @@ namespace plume {
759+ @@ -1886,11 +2265 ,29 @@ namespace plume {
697760 }
698761
699762 void MetalSwapChain::setVsyncEnabled(const bool vsyncEnabled) {
@@ -723,7 +786,7 @@ index ebbbaa3..0155004 100644
723786 }
724787
725788 uint32_t MetalSwapChain::getWidth() const {
726- @@ -1910,6 +2258 ,10 @@ namespace plume {
789+ @@ -1910,6 +2307 ,10 @@ namespace plume {
727790 assert(textureIndex != nullptr);
728791 assert(*textureIndex < MAX_DRAWABLES);
729792
@@ -734,15 +797,15 @@ index ebbbaa3..0155004 100644
734797 NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init();
735798
736799 // Create a command buffer just to encode the signal
737- @@ -1923,6 +2275 ,7 @@ namespace plume {
800+ @@ -1923,6 +2324 ,7 @@ namespace plume {
738801 CA::MetalDrawable *nextDrawable = layer->nextDrawable();
739802 if (nextDrawable == nullptr) {
740803 fprintf(stderr, "No more drawables available for rendering.\n");
741804+ releasePool->release();
742805 return false;
743806 }
744807
745- @@ -1954,10 +2307 ,20 @@ namespace plume {
808+ @@ -1954,10 +2356 ,20 @@ namespace plume {
746809 }
747810
748811 uint32_t MetalSwapChain::getRefreshRate() const {
@@ -763,7 +826,7 @@ index ebbbaa3..0155004 100644
763826 CocoaWindowAttributes attributes;
764827 windowWrapper->getWindowAttributes(&attributes);
765828 dstWidth = attributes.width;
766- @@ -3308,6 +3671 ,9 @@ namespace plume {
829+ @@ -3308,6 +3720 ,9 @@ namespace plume {
767830 this->renderInterface = renderInterface;
768831
769832 // Device Selection
@@ -773,7 +836,7 @@ index ebbbaa3..0155004 100644
773836 const NS::Array* devices = MTL::CopyAllDevices();
774837 MTL::Device *preferredDevice = nullptr;
775838 for (NS::UInteger i = 0; i < devices->count(); i++) {
776- @@ -3320,12 +3686 ,31 @@ namespace plume {
839+ @@ -3320,12 +3735 ,31 @@ namespace plume {
777840 }
778841
779842 mtl = preferredDevice ? preferredDevice : MTL::CreateSystemDefaultDevice();;
@@ -806,7 +869,7 @@ index ebbbaa3..0155004 100644
806869
807870 // Setup blit, clear and resolve shaders / pipelines
808871 createClearShaderLibrary();
809- @@ -3337,7 +3722 ,7 @@ namespace plume {
872+ @@ -3337,7 +3771 ,7 @@ namespace plume {
810873 // TODO: Support Raytracing.
811874 // capabilities.raytracing = mtl->supportsRaytracing();
812875 capabilities.maxTextureSize = mtl->supportsFamily(MTL::GPUFamilyApple3) ? 16384 : 8192;
@@ -815,7 +878,7 @@ index ebbbaa3..0155004 100644
815878 capabilities.resolveModes = false;
816879 #if PLUME_IOS
817880 capabilities.descriptorIndexing = mtl->supportsFamily(MTL::GPUFamilyApple3);
818- @@ -3345,11 +3730 ,11 @@ namespace plume {
881+ @@ -3345,11 +3779 ,11 @@ namespace plume {
819882 capabilities.descriptorIndexing = true;
820883 #endif
821884 capabilities.scalarBlockLayout = true;
@@ -830,7 +893,7 @@ index ebbbaa3..0155004 100644
830893 capabilities.gpuUploadHeap = capabilities.uma;
831894 capabilities.queryPools = false;
832895
833- @@ -3357,17 +3742 ,19 @@ namespace plume {
896+ @@ -3357,17 +3791 ,19 @@ namespace plume {
834897 }
835898
836899 MetalDevice::~MetalDevice() {
@@ -856,7 +919,7 @@ index ebbbaa3..0155004 100644
856919 }
857920
858921 std::unique_ptr<RenderDescriptorSet> MetalDevice::createDescriptorSet(const RenderDescriptorSetDesc &desc) {
859- @@ -3635,16 +4022 ,24 @@ namespace plume {
922+ @@ -3635,16 +4071 ,24 @@ namespace plume {
860923
861924 MetalInterface::MetalInterface() {
862925 NS::AutoreleasePool *releasePool = NS::AutoreleasePool::alloc()->init();
0 commit comments