diff --git a/projects/apis/metal/src/framebuffers/metal_framebuffer.h b/projects/apis/metal/src/framebuffers/metal_framebuffer.h index 46a4e65..f91acaa 100644 --- a/projects/apis/metal/src/framebuffers/metal_framebuffer.h +++ b/projects/apis/metal/src/framebuffers/metal_framebuffer.h @@ -3,11 +3,10 @@ #include "utils/gryphn_bool.h" #include "utils/gryphn_image_format.h" #include "utils/lists/gryphn_array_list.h" +#include "renderpass/metal_render_pass.h" #import #import -typedef MTLRenderPassDescriptor* mtlSubpass; - typedef struct gnPlatformFramebuffer_t { uint32_t subpassCount; mtlSubpass* subpasses; diff --git a/projects/apis/metal/src/framebuffers/metal_framebuffer.m b/projects/apis/metal/src/framebuffers/metal_framebuffer.m index 276c591..d66f7c5 100644 --- a/projects/apis/metal/src/framebuffers/metal_framebuffer.m +++ b/projects/apis/metal/src/framebuffers/metal_framebuffer.m @@ -3,83 +3,33 @@ #include "renderpass/gryphn_render_pass_descriptor.h" #include "instance/gryphn_instance.h" #include "output_device/gryphn_output_device.h" - -gnBool isDepthFormat(gnImageFormat format) { - return (format == GN_FORMAT_D24S8_UINT) || (format == GN_FORMAT_D32S8_UINT); -} - -gnBool isStencilFormat(gnImageFormat format) { - return (format == GN_FORMAT_D24S8_UINT) || (format == GN_FORMAT_D32S8_UINT); -} - -MTLLoadAction mtlGryphnLoadOperation(gnLoadOperation loadOperation) { - switch(loadOperation) { - case GN_LOAD_OPERATION_LOAD: return MTLLoadActionLoad; - case GN_LOAD_OPERATION_CLEAR: return MTLLoadActionClear; - case GN_LOAD_OPERATION_DONT_CARE: return MTLLoadActionDontCare; - } -} - -MTLStoreAction mtlGryphnStoreOperation(gnStoreOperation storeOperation) { - switch (storeOperation) { - case GN_STORE_OPERATION_STORE: return MTLStoreActionStore; - case GN_STORE_OPERATION_DONT_CARE: return MTLStoreActionDontCare; - } -} - -MTLStoreAction mtlGryphnStoreOperationResolve(gnStoreOperation storeOperation) { - switch (storeOperation) { - case GN_STORE_OPERATION_STORE: return MTLStoreActionStoreAndMultisampleResolve; - case GN_STORE_OPERATION_DONT_CARE: return MTLStoreActionDontCare; - } -} - +#include "utils/gryphn_image_format.h" gnReturnCode createMetalFramebuffer(gnFramebuffer framebuffer, gnOutputDevice device, gnFramebufferInfo info) { framebuffer->framebuffer = malloc(sizeof(struct gnPlatformFramebuffer_t)); - if (info.attachmentCount != info.renderPassDescriptor->info.attachmentCount) { - gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){ - .message = gnCreateString("Attachment count on framebuffer does not equal attachment count on render pass descriptor") - }); - return GN_DIVERGENT_RENDERPASS; - } - framebuffer->framebuffer->subpassCount = info.renderPassDescriptor->info.subpassCount; + framebuffer->framebuffer->subpassCount = info.renderPassDescriptor->renderPassDescriptor->subpassCount; framebuffer->framebuffer->subpasses = malloc(sizeof(mtlSubpass) * framebuffer->framebuffer->subpassCount); - for (int i = 0; i < info.renderPassDescriptor->info.subpassCount; i++) { - framebuffer->framebuffer->subpasses[i] = [[MTLRenderPassDescriptor alloc] init]; - [framebuffer->framebuffer->subpasses[i] setRenderTargetWidth:info.size.x]; - [framebuffer->framebuffer->subpasses[i] setRenderTargetHeight:info.size.y]; - gnBool resolve = !(info.renderPassDescriptor->info.subpassInfos[i].resolveAttachments == NULL); + 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]; + [pass setRenderTargetWidth:info.size.x]; + [pass setRenderTargetHeight:info.size.y]; - for (int c = 0; c < info.renderPassDescriptor->info.subpassInfos[i].colorAttachmentCount; c++) { - uint32_t attachmentIndex = info.renderPassDescriptor->info.subpassInfos[i].colorAttachments[c].index, resolveAttachemntIndex = 0; - MTLRenderPassColorAttachmentDescriptor* color = framebuffer->framebuffer->subpasses[i].colorAttachments[c]; - color.texture = info.attachments[attachmentIndex]->texture->texture; - if (resolve) { - resolveAttachemntIndex = info.renderPassDescriptor->info.subpassInfos[i].resolveAttachments[c].index; - color.resolveTexture = info.attachments[resolveAttachemntIndex]->texture->texture; - color.storeAction = mtlGryphnStoreOperationResolve(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].storeOperation); - } else { - color.storeAction = mtlGryphnStoreOperation(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].storeOperation); - } - color.loadAction = mtlGryphnLoadOperation(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].loadOperation); - - if (color.loadAction == MTLLoadActionClear) - color.clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0); + for (int c = 0; c < info.renderPassDescriptor->renderPassDescriptor->copyInfos[i].colorAttachmentCount; c++) { + MTLRenderPassColorAttachmentDescriptor* colorPass = pass.colorAttachments[c]; + 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; } - if (info.renderPassDescriptor->info.subpassInfos[i].depthAttachment != NULL) { - MTLRenderPassDepthAttachmentDescriptor* depthAttachment = framebuffer->framebuffer->subpasses[i].depthAttachment; - uint32_t attachmentIndex = info.renderPassDescriptor->info.subpassInfos[i].depthAttachment->index; - depthAttachment.texture = info.attachments[attachmentIndex]->texture->texture; - depthAttachment.loadAction = mtlGryphnLoadOperation(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].loadOperation); - depthAttachment.storeAction = mtlGryphnStoreOperation(info.renderPassDescriptor->info.attachmentInfos[attachmentIndex].storeOperation); - depthAttachment.clearDepth = 1.0f; - MTLRenderPassStencilAttachmentDescriptor* stencilAttachment = framebuffer->framebuffer->subpasses[attachmentIndex].stencilAttachment; - stencilAttachment.texture = info.attachments[attachmentIndex]->texture->texture; + if (info.attachments[i]->info.format == GN_FORMAT_D24S8_UINT || info.attachments[i]->info.format == GN_FORMAT_D32S8_UINT) { + 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; } } 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 dd296aa..954b486 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 @@ -3,6 +3,7 @@ #include "shader_module/metal_shader_module.h" #include "surface/metal_surface.h" #include "texture/metal_texture.h" +#include "renderpass/metal_render_pass.h" #include "utils/math/gryphn_vec3.h" @@ -65,8 +66,9 @@ gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gn } if (subpass.depthAttachment != NULL) { - descriptor.depthAttachmentPixelFormat = mtlGryphnFormatToMetalFormat(info.renderPassDescriptor->info.attachmentInfos[subpass.depthAttachment->index].format); - // descriptor.stencilAttachmentPixelFormat = mtlGryphnFormatToMetalFormat(info.renderPassDescriptor->info.attachmentInfos[subpass.depthAttachment->index].format); + descriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8; + descriptor.depthAttachmentPixelFormat = info.renderPassDescriptor->renderPassDescriptor->subpasses[info.subpassIndex].depthAttachment.texture.pixelFormat; + descriptor.stencilAttachmentPixelFormat = info.renderPassDescriptor->renderPassDescriptor->subpasses[info.subpassIndex].stencilAttachment.texture.pixelFormat; } } diff --git a/projects/apis/metal/src/renderpass/metal_render_pass.h b/projects/apis/metal/src/renderpass/metal_render_pass.h index 70be445..342f2d9 100644 --- a/projects/apis/metal/src/renderpass/metal_render_pass.h +++ b/projects/apis/metal/src/renderpass/metal_render_pass.h @@ -2,8 +2,24 @@ #include "renderpass/gryphn_render_pass_descriptor.h" #import +typedef MTLRenderPassDescriptor* mtlSubpass; + +typedef struct mtlColorAttachmentCopyInfo { + uint32_t attachmentIndex; + int resolveAttachmentIndex; // -1 means no resolve attachment +} mtlColorAttachmentCopyInfo; + +typedef struct mtlSubpassCopyInfo { + uint32_t colorAttachmentCount; + mtlColorAttachmentCopyInfo* colorAttachments; +} mtlSubpassCopyInfo; + typedef struct gnPlatformRenderPassDescriptor_t { - MTLRenderPassDescriptor* passDescriptor; + uint32_t subpassCount; + mtlSubpass* subpasses; + mtlSubpassCopyInfo* copyInfos; + + } gnPlatformRenderPassDescriptor; gnReturnCode createMetalRenderPass(gnRenderPassDescriptor renderPass, gnDevice device, gnRenderPassDescriptorInfo info); diff --git a/projects/apis/metal/src/renderpass/metal_render_pass.m b/projects/apis/metal/src/renderpass/metal_render_pass.m index 99c0d34..1fb5a54 100644 --- a/projects/apis/metal/src/renderpass/metal_render_pass.m +++ b/projects/apis/metal/src/renderpass/metal_render_pass.m @@ -1,13 +1,83 @@ #include "metal_render_pass.h" +gnBool isDepthFormat(gnImageFormat format) { + return (format == GN_FORMAT_D24S8_UINT) || (format == GN_FORMAT_D32S8_UINT); +} + +gnBool isStencilFormat(gnImageFormat format) { + return (format == GN_FORMAT_D24S8_UINT) || (format == GN_FORMAT_D32S8_UINT); +} + +MTLLoadAction mtlGryphnLoadOperation(gnLoadOperation loadOperation) { + switch(loadOperation) { + case GN_LOAD_OPERATION_LOAD: return MTLLoadActionLoad; + case GN_LOAD_OPERATION_CLEAR: return MTLLoadActionClear; + case GN_LOAD_OPERATION_DONT_CARE: return MTLLoadActionDontCare; + } +} + +MTLStoreAction mtlGryphnStoreOperation(gnStoreOperation storeOperation) { + switch (storeOperation) { + case GN_STORE_OPERATION_STORE: return MTLStoreActionStore; + case GN_STORE_OPERATION_DONT_CARE: return MTLStoreActionDontCare; + } +} + +MTLStoreAction mtlGryphnStoreOperationResolve(gnStoreOperation storeOperation) { + switch (storeOperation) { + case GN_STORE_OPERATION_STORE: return MTLStoreActionStoreAndMultisampleResolve; + case GN_STORE_OPERATION_DONT_CARE: return MTLStoreActionDontCare; + } +} + gnReturnCode createMetalRenderPass(gnRenderPassDescriptor renderPass, gnDevice device, gnRenderPassDescriptorInfo info) { renderPass->renderPassDescriptor = malloc(sizeof(gnPlatformRenderPassDescriptor)); - renderPass->renderPassDescriptor->passDescriptor = [[MTLRenderPassDescriptor alloc] init]; + renderPass->renderPassDescriptor->subpassCount = info.subpassCount; + renderPass->renderPassDescriptor->subpasses = malloc(sizeof(mtlSubpass) * info.subpassCount); + renderPass->renderPassDescriptor->copyInfos = malloc(sizeof(mtlSubpassCopyInfo) * info.subpassCount); + for (int i = 0; i < info.subpassCount; i++) { + renderPass->renderPassDescriptor->subpasses[i] = [[MTLRenderPassDescriptor alloc] init]; + gnBool resolve = !(info.subpassInfos[i].resolveAttachments == NULL); + renderPass->renderPassDescriptor->copyInfos[i].colorAttachmentCount = info.subpassInfos[i].colorAttachmentCount; + renderPass->renderPassDescriptor->copyInfos[i].colorAttachments = malloc(sizeof(mtlColorAttachmentCopyInfo) * info.subpassInfos[i].colorAttachmentCount); + for (int c = 0; c < info.subpassInfos[i].colorAttachmentCount; c++) { + uint32_t attachmentIndex = info.subpassInfos[i].colorAttachments[c].index; + int resolveAttachmentIndex = -1; + + 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 { + color.storeAction = mtlGryphnStoreOperation(info.attachmentInfos[attachmentIndex].storeOperation); + } + color.loadAction = mtlGryphnLoadOperation(info.attachmentInfos[attachmentIndex].loadOperation); + + 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; + } + + 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; + } + } return GN_SUCCESS; } void destroyMetalRenderPass(gnRenderPassDescriptor renderPass) { - [renderPass->renderPassDescriptor->passDescriptor release]; + for (int i = 0; i < renderPass->renderPassDescriptor->subpassCount; i++) { + [renderPass->renderPassDescriptor->subpasses[i] release]; + for (int c = 0; c < renderPass->renderPassDescriptor->copyInfos[i].colorAttachmentCount; c++) + free(renderPass->renderPassDescriptor->copyInfos[i].colorAttachments); + } + free(renderPass->renderPassDescriptor->copyInfos); free(renderPass->renderPassDescriptor); }