Fix iOS Metal shader base vertex translation

This commit is contained in:
aperezro 2026-06-08 02:31:54 -06:00
parent f532a8e73b
commit e7e617cf75

View file

@ -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<const MetalShader *>(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<const MetalShader *>(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<CA::MetalLayer*>(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<RenderDescriptorSet> 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();