From 1d23dd0b804332899110a5655449a8f96b4176fd Mon Sep 17 00:00:00 2001 From: Gregory Wells Date: Thu, 24 Jul 2025 08:29:05 -0400 Subject: [PATCH] kinda start to fix render pass descriptors in metal --- .../src/commands/commands/metal_commands.m | 21 ++++++---------- .../src/framebuffers/metal_framebuffer.h | 9 +++++++ .../src/framebuffers/metal_framebuffer.m | 24 +++++++++++++------ .../metal_graphics_pipeline.m | 15 ++++++------ .../apis/metal/src/present/metal_present.m | 2 ++ .../metal_presentation_queue.m | 1 + .../metal/src/renderpass/metal_render_pass.h | 4 ++++ .../metal/src/renderpass/metal_render_pass.m | 12 ++++++---- .../apis/metal/src/texture/metal_texture.m | 7 ++---- .../gryphn_render_pass_descriptor.c | 4 +++- .../gryphn_render_pass_descriptor.h | 1 - 11 files changed, 61 insertions(+), 39 deletions(-) diff --git a/projects/apis/metal/src/commands/commands/metal_commands.m b/projects/apis/metal/src/commands/commands/metal_commands.m index da2ea2a..5571b9b 100644 --- a/projects/apis/metal/src/commands/commands/metal_commands.m +++ b/projects/apis/metal/src/commands/commands/metal_commands.m @@ -6,22 +6,15 @@ void metelBeginRenderPass(gnCommandBuffer buffer, gnRenderPassInfo passInfo) { int currentColorAttachment = 0; for (int i = 0; i < passInfo.clearValueCount; i++) { - gnBool wasDepthStencil = gnFalse; - if (isDepthFormat(passInfo.renderPassDescriptor->info.attachmentInfos[i].format)) { - wasDepthStencil = gnTrue; - } - if (isStencilFormat(passInfo.renderPassDescriptor->info.attachmentInfos[i].format)) { - wasDepthStencil = gnTrue; - } - - if(!wasDepthStencil) { - MTLRenderPassColorAttachmentDescriptor* color = passInfo.framebuffer->framebuffer->subpasses[i].colorAttachments[i]; + if (passInfo.framebuffer->framebuffer->clearCopies[i].clear) { + MTLRenderPassColorAttachmentDescriptor* color = passInfo.framebuffer->framebuffer->clearCopies[i].descriptor; color.clearColor = MTLClearColorMake( - passInfo.clearValues[i].red, - passInfo.clearValues[i].green, - passInfo.clearValues[i].blue, - passInfo.clearValues[i].alpha + passInfo.clearValues[i].r, + passInfo.clearValues[i].g, + passInfo.clearValues[i].b, + passInfo.clearValues[i].a ); + currentColorAttachment++; } } buffer->commandBuffer->encoder = [buffer->commandBuffer->commandBuffer renderCommandEncoderWithDescriptor:passInfo.framebuffer->framebuffer->subpasses[0]]; diff --git a/projects/apis/metal/src/framebuffers/metal_framebuffer.h b/projects/apis/metal/src/framebuffers/metal_framebuffer.h index f91acaa..00d3929 100644 --- a/projects/apis/metal/src/framebuffers/metal_framebuffer.h +++ b/projects/apis/metal/src/framebuffers/metal_framebuffer.h @@ -7,9 +7,18 @@ #import #import +typedef struct mtlClearCopy { + gnBool clear; + MTLRenderPassColorAttachmentDescriptor* descriptor; +} mtlClearCopy; + typedef struct gnPlatformFramebuffer_t { uint32_t subpassCount; mtlSubpass* subpasses; + uint32_t* depthAttachmentIndicies; + + uint32_t clearCopyCount; + mtlClearCopy* clearCopies; } gnPlatformFramebuffer; gnBool isDepthFormat(gnImageFormat format); diff --git a/projects/apis/metal/src/framebuffers/metal_framebuffer.m b/projects/apis/metal/src/framebuffers/metal_framebuffer.m index d66f7c5..354a444 100644 --- a/projects/apis/metal/src/framebuffers/metal_framebuffer.m +++ b/projects/apis/metal/src/framebuffers/metal_framebuffer.m @@ -7,10 +7,15 @@ gnReturnCode createMetalFramebuffer(gnFramebuffer framebuffer, gnOutputDevice device, gnFramebufferInfo info) { framebuffer->framebuffer = malloc(sizeof(struct gnPlatformFramebuffer_t)); + framebuffer->framebuffer->clearCopyCount = info.attachmentCount; + framebuffer->framebuffer->clearCopies = malloc(sizeof(mtlClearCopy) * info.attachmentCount); + for (int i = 0; i < info.attachmentCount; i++) { + framebuffer->framebuffer->clearCopies[i].clear = gnFalse; + } + framebuffer->framebuffer->subpassCount = info.renderPassDescriptor->renderPassDescriptor->subpassCount; framebuffer->framebuffer->subpasses = malloc(sizeof(mtlSubpass) * framebuffer->framebuffer->subpassCount); - - + framebuffer->framebuffer->depthAttachmentIndicies = malloc(sizeof(uint32_t) * framebuffer->framebuffer->subpassCount); for (int i = 0; i < framebuffer->framebuffer->subpassCount; i++) { framebuffer->framebuffer->subpasses[i] = [info.renderPassDescriptor->renderPassDescriptor->subpasses[i] copy]; MTLRenderPassDescriptor* pass = framebuffer->framebuffer->subpasses[i]; @@ -22,15 +27,20 @@ gnReturnCode createMetalFramebuffer(gnFramebuffer framebuffer, gnOutputDevice de colorPass.texture = info.attachments[info.renderPassDescriptor->renderPassDescriptor->copyInfos[i].colorAttachments[c].attachmentIndex]->texture->texture; if (info.renderPassDescriptor->renderPassDescriptor->copyInfos[i].colorAttachments[c].resolveAttachmentIndex >= 0) colorPass.resolveTexture = info.attachments[info.renderPassDescriptor->renderPassDescriptor->copyInfos[i].colorAttachments[c].resolveAttachmentIndex]->texture->texture; + framebuffer->framebuffer->clearCopies[info.renderPassDescriptor->renderPassDescriptor->copyInfos[i].colorAttachments[c].attachmentIndex].clear = gnTrue; + framebuffer->framebuffer->clearCopies[info.renderPassDescriptor->renderPassDescriptor->copyInfos[i].colorAttachments[c].attachmentIndex].descriptor = colorPass; } - - if (info.attachments[i]->info.format == GN_FORMAT_D24S8_UINT || info.attachments[i]->info.format == GN_FORMAT_D32S8_UINT) { + if (info.renderPassDescriptor->renderPassDescriptor->copyInfos[i].depthAttachmentIndex >= 0) { MTLRenderPassDepthAttachmentDescriptor* depthAttachment = framebuffer->framebuffer->subpasses[i].depthAttachment; - depthAttachment.texture = info.attachments[i]->texture->texture; - MTLRenderPassStencilAttachmentDescriptor* stencilAttachment = framebuffer->framebuffer->subpasses[i].stencilAttachment; - stencilAttachment.texture = info.attachments[i]->texture->texture; + depthAttachment.texture = info.attachments[info.renderPassDescriptor->renderPassDescriptor->copyInfos[i].depthAttachmentIndex]->texture->texture; } + + // if (info.attachments[i]->info.format == GN_FORMAT_D24S8_UINT || info.attachments[i]->info.format == GN_FORMAT_D32S8_UINT) { + // framebuffer->framebuffer->depthAttachmentIndicies[i] = i; + // MTLRenderPassStencilAttachmentDescriptor* stencilAttachment = framebuffer->framebuffer->subpasses[i].stencilAttachment; + // stencilAttachment.texture = info.attachments[i]->texture->texture; + // } } return GN_SUCCESS; diff --git a/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.m b/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.m index 954b486..051b100 100644 --- a/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.m +++ b/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.m @@ -45,14 +45,15 @@ MTLCompareFunction mtlGrypnCompareOperation(gnCompareOperation operation) { gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gnOutputDevice device, gnGraphicsPipelineInfo info) { graphicsPipeline->graphicsPipeline = malloc(sizeof(struct gnPlatformGraphicsPipeline_t)); MTLRenderPipelineDescriptor* descriptor = [[MTLRenderPipelineDescriptor alloc] init]; - descriptor.rasterSampleCount = mtlSampleCount(info.multisample.samples); - struct gnSubpassInfo_t subpass = info.renderPassDescriptor->info.subpassInfos[info.subpassIndex]; + // descriptor.rasterSampleCount = mtlSampleCount(info.multisample.samples); + descriptor.rasterSampleCount = 1; + descriptor.rasterizationEnabled = YES; + mtlSubpass subpass = info.renderPassDescriptor->renderPassDescriptor->subpasses[info.subpassIndex]; + mtlSubpassCopyInfo copyInfo = info.renderPassDescriptor->renderPassDescriptor->copyInfos[info.subpassIndex]; + for (uint32_t i = 0; i < copyInfo.colorAttachmentCount; i++) { + MTLRenderPassColorAttachmentDescriptor* colorPass = subpass.colorAttachments[i]; - for (uint32_t i = 0; i < subpass.colorAttachmentCount; i++) { - gnSubpassAttachmentInfo subpassAtt = subpass.colorAttachments[i]; - - gnRenderPassAttachmentInfo attInfo = info.renderPassDescriptor->info.attachmentInfos[subpassAtt.index]; - descriptor.colorAttachments[i].pixelFormat = mtlGryphnFormatToMetalFormat(attInfo.format); + descriptor.colorAttachments[i].pixelFormat = copyInfo.colorAttachments[i].format; if (info.colorBlending.enable == gnTrue) { [descriptor.colorAttachments objectAtIndexedSubscript:i].blendingEnabled = YES; [descriptor.colorAttachments objectAtIndexedSubscript:i].rgbBlendOperation = mtlGryphnBlendOperation(info.colorBlending.colorBlendOperation); diff --git a/projects/apis/metal/src/present/metal_present.m b/projects/apis/metal/src/present/metal_present.m index b902ab0..54e3fc2 100644 --- a/projects/apis/metal/src/present/metal_present.m +++ b/projects/apis/metal/src/present/metal_present.m @@ -31,6 +31,8 @@ gnReturnCode metalPresent(gnOutputDeviceHandle device, gnPresentInfo info) { [blit endEncoding]; + [drawable texture]; + [commandBuffer presentDrawable:drawable]; [commandBuffer commit]; device->outputDevice->executingCommandBuffer = commandBuffer; diff --git a/projects/apis/metal/src/presentation_queue/metal_presentation_queue.m b/projects/apis/metal/src/presentation_queue/metal_presentation_queue.m index d575ea9..8bfd306 100644 --- a/projects/apis/metal/src/presentation_queue/metal_presentation_queue.m +++ b/projects/apis/metal/src/presentation_queue/metal_presentation_queue.m @@ -30,6 +30,7 @@ gnReturnCode createMetalPresentationQueue(gnPresentationQueueHandle presentation textureDescriptor.width = presentationInfo.imageSize.x; textureDescriptor.height = presentationInfo.imageSize.y; textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; + textureDescriptor.sampleCount = 1; textureDescriptor.textureType = MTLTextureType2D; presentationQueue->imageCount = presentationInfo.minImageCount; diff --git a/projects/apis/metal/src/renderpass/metal_render_pass.h b/projects/apis/metal/src/renderpass/metal_render_pass.h index 342f2d9..ed874db 100644 --- a/projects/apis/metal/src/renderpass/metal_render_pass.h +++ b/projects/apis/metal/src/renderpass/metal_render_pass.h @@ -1,10 +1,13 @@ #pragma once #include "renderpass/gryphn_render_pass_descriptor.h" #import +#import typedef MTLRenderPassDescriptor* mtlSubpass; typedef struct mtlColorAttachmentCopyInfo { + MTLPixelFormat format; + uint32_t attachmentIndex; int resolveAttachmentIndex; // -1 means no resolve attachment } mtlColorAttachmentCopyInfo; @@ -12,6 +15,7 @@ typedef struct mtlColorAttachmentCopyInfo { typedef struct mtlSubpassCopyInfo { uint32_t colorAttachmentCount; mtlColorAttachmentCopyInfo* colorAttachments; + int depthAttachmentIndex; // -1 means no depth attachment } mtlSubpassCopyInfo; typedef struct gnPlatformRenderPassDescriptor_t { diff --git a/projects/apis/metal/src/renderpass/metal_render_pass.m b/projects/apis/metal/src/renderpass/metal_render_pass.m index 1fb5a54..bc1d0e1 100644 --- a/projects/apis/metal/src/renderpass/metal_render_pass.m +++ b/projects/apis/metal/src/renderpass/metal_render_pass.m @@ -45,28 +45,32 @@ gnReturnCode createMetalRenderPass(gnRenderPassDescriptor renderPass, gnDevice d uint32_t attachmentIndex = info.subpassInfos[i].colorAttachments[c].index; int resolveAttachmentIndex = -1; + renderPass->renderPassDescriptor->subpasses[i].colorAttachments[c] = [[MTLRenderPassColorAttachmentDescriptor alloc] init]; MTLRenderPassColorAttachmentDescriptor* color = renderPass->renderPassDescriptor->subpasses[i].colorAttachments[c]; if (resolve) { resolveAttachmentIndex = info.subpassInfos[i].resolveAttachments[c].index; color.storeAction = mtlGryphnStoreOperationResolve(info.attachmentInfos[attachmentIndex].storeOperation); - } else { + } else color.storeAction = mtlGryphnStoreOperation(info.attachmentInfos[attachmentIndex].storeOperation); - } color.loadAction = mtlGryphnLoadOperation(info.attachmentInfos[attachmentIndex].loadOperation); + color.storeAction = MTLStoreActionStoreAndMultisampleResolve; if (color.loadAction == MTLLoadActionClear) color.clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0); - renderPass->renderPassDescriptor->copyInfos[i].colorAttachments[i].attachmentIndex = attachmentIndex; - renderPass->renderPassDescriptor->copyInfos[i].colorAttachments[i].resolveAttachmentIndex = resolveAttachmentIndex; + renderPass->renderPassDescriptor->copyInfos[i].colorAttachments[c].format = MTLPixelFormatBGRA8Unorm_sRGB; + renderPass->renderPassDescriptor->copyInfos[i].colorAttachments[c].attachmentIndex = attachmentIndex; + renderPass->renderPassDescriptor->copyInfos[i].colorAttachments[c].resolveAttachmentIndex = resolveAttachmentIndex; } + renderPass->renderPassDescriptor->copyInfos[i].depthAttachmentIndex = -1; if (info.subpassInfos[i].depthAttachment != NULL) { MTLRenderPassDepthAttachmentDescriptor* depthAttachment = renderPass->renderPassDescriptor->subpasses[i].depthAttachment; uint32_t attachmentIndex = info.subpassInfos[i].depthAttachment->index; depthAttachment.loadAction = mtlGryphnLoadOperation(info.attachmentInfos[attachmentIndex].loadOperation); depthAttachment.storeAction = mtlGryphnStoreOperation(info.attachmentInfos[attachmentIndex].storeOperation); depthAttachment.clearDepth = 1.0f; + renderPass->renderPassDescriptor->copyInfos[i].depthAttachmentIndex = attachmentIndex; } } return GN_SUCCESS; diff --git a/projects/apis/metal/src/texture/metal_texture.m b/projects/apis/metal/src/texture/metal_texture.m index 5fbdc1b..2dbf5ce 100644 --- a/projects/apis/metal/src/texture/metal_texture.m +++ b/projects/apis/metal/src/texture/metal_texture.m @@ -24,13 +24,10 @@ gnReturnCode createMetalTexture(gnTexture texture, gnDevice device, const gnText textureDescriptor.height = info.extent.height; textureDescriptor.pixelFormat = mtlGryphnFormatToMetalFormat(info.format); - if (textureDescriptor.sampleCount >= 2) { - textureDescriptor.storageMode = MTLStorageModeShared; + if (textureDescriptor.sampleCount >= 2) textureDescriptor.textureType = MTLTextureType2DMultisample; - } - else { + else textureDescriptor.textureType = MTLTextureType2D; - } MTLSamplerDescriptor *samplerDesc = [[MTLSamplerDescriptor alloc] init]; samplerDesc.minFilter = (info.minFilter == GN_FILTER_NEAREST) ? MTLSamplerMinMagFilterNearest : MTLSamplerMinMagFilterLinear; diff --git a/projects/core/src/renderpass/gryphn_render_pass_descriptor.c b/projects/core/src/renderpass/gryphn_render_pass_descriptor.c index c34bf69..fcc19f3 100644 --- a/projects/core/src/renderpass/gryphn_render_pass_descriptor.c +++ b/projects/core/src/renderpass/gryphn_render_pass_descriptor.c @@ -2,10 +2,12 @@ #include "output_device/gryphn_output_device.h" #include "instance/gryphn_instance.h" +#include "stdio.h" + gnReturnCode gnCreateRenderPassDescriptor(gnRenderPassDescriptorHandle* renderPass, gnOutputDeviceHandle device, gnRenderPassDescriptorInfo info) { *renderPass = malloc(sizeof(struct gnRenderPassDescriptor_t)); (*renderPass)->device = device; - (*renderPass)->info = info; + return device->instance->callingLayer->deviceFunctions._gnCreateRenderPassDescriptor(*renderPass, device, info); } diff --git a/projects/core/src/renderpass/gryphn_render_pass_descriptor.h b/projects/core/src/renderpass/gryphn_render_pass_descriptor.h index da3180a..0c2914d 100644 --- a/projects/core/src/renderpass/gryphn_render_pass_descriptor.h +++ b/projects/core/src/renderpass/gryphn_render_pass_descriptor.h @@ -76,7 +76,6 @@ typedef struct gnRenderPassDescriptorInfo { #ifdef GN_REVEAL_IMPL struct gnRenderPassDescriptor_t { struct gnPlatformRenderPassDescriptor_t* renderPassDescriptor; - gnRenderPassDescriptorInfo info; gnDeviceHandle device; }; #endif