From c114de2bc4edc6b5836010edfb17469baf76821d Mon Sep 17 00:00:00 2001 From: Gregory Wells Date: Sun, 3 Aug 2025 17:49:45 -0400 Subject: [PATCH] redo metal fence model --- .../metal/src/renderpass/metal_render_pass.m | 10 ++++--- projects/apis/metal/src/submit/metal_submit.m | 15 ++++++---- .../apis/metal/src/surface/metal_surface.m | 4 ++- .../apis/metal/src/sync/fence/metal_fence.h | 6 ++-- .../apis/metal/src/sync/fence/metal_fence.m | 30 +++++-------------- 5 files changed, 31 insertions(+), 34 deletions(-) diff --git a/projects/apis/metal/src/renderpass/metal_render_pass.m b/projects/apis/metal/src/renderpass/metal_render_pass.m index bc1d0e1..c588ffb 100644 --- a/projects/apis/metal/src/renderpass/metal_render_pass.m +++ b/projects/apis/metal/src/renderpass/metal_render_pass.m @@ -31,17 +31,19 @@ MTLStoreAction mtlGryphnStoreOperationResolve(gnStoreOperation storeOperation) { } gnReturnCode createMetalRenderPass(gnRenderPassDescriptor renderPass, gnDevice device, gnRenderPassDescriptorInfo info) { + if (device == GN_NULL_HANDLE) return GN_INVALID_HANDLE; + renderPass->renderPassDescriptor = malloc(sizeof(gnPlatformRenderPassDescriptor)); 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++) { + for (uint32_t 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++) { + for (uint32_t c = 0; c < info.subpassInfos[i].colorAttachmentCount; c++) { uint32_t attachmentIndex = info.subpassInfos[i].colorAttachments[c].index; int resolveAttachmentIndex = -1; @@ -77,9 +79,9 @@ gnReturnCode createMetalRenderPass(gnRenderPassDescriptor renderPass, gnDevice d } void destroyMetalRenderPass(gnRenderPassDescriptor renderPass) { - for (int i = 0; i < renderPass->renderPassDescriptor->subpassCount; i++) { + for (uint32_t i = 0; i < renderPass->renderPassDescriptor->subpassCount; i++) { [renderPass->renderPassDescriptor->subpasses[i] release]; - for (int c = 0; c < renderPass->renderPassDescriptor->copyInfos[i].colorAttachmentCount; c++) + for (uint32_t c = 0; c < renderPass->renderPassDescriptor->copyInfos[i].colorAttachmentCount; c++) free(renderPass->renderPassDescriptor->copyInfos[i].colorAttachments); } free(renderPass->renderPassDescriptor->copyInfos); diff --git a/projects/apis/metal/src/submit/metal_submit.m b/projects/apis/metal/src/submit/metal_submit.m index 65b5829..dab2ac7 100644 --- a/projects/apis/metal/src/submit/metal_submit.m +++ b/projects/apis/metal/src/submit/metal_submit.m @@ -1,20 +1,23 @@ #include "metal_submit.h" #include "synchronization/fence/gryphn_fence.h" +#include "sync/fence/metal_fence.h" gnReturnCode metalSyncSubmit(gnOutputDevice device, gnSubmitSyncInfo info) { + if (device == GN_NULL_HANDLE) return GN_INVALID_HANDLE; + __block gnFence fenceToSignal = info.fence; __block atomic_int buffersLeft; atomic_init(&buffersLeft, info.commandBufferCount); - for (int i = 0; i < info.commandBufferCount; i++) { + for (uint32_t i = 0; i < info.commandBufferCount; i++) { id buffer = [info.commandBuffers[i]->commandPool->commandPool->commandQueue commandBuffer]; - for (int c = 0; c < info.waitCount; c++) + for (uint32_t c = 0; c < info.waitCount; c++) mtlWaitSemaphore(info.waitSemaphores[c], buffer); [buffer commit]; id commandBuffer = info.commandBuffers[i]->commandBuffer->commandBuffer; - for (int c = 0; c < info.signalCount; c++) + for (uint32_t c = 0; c < info.signalCount; c++) mtlSignalSemaphore(info.signalSemaphores[c], commandBuffer); [info.commandBuffers[i]->commandBuffer->commandBuffer addCompletedHandler:^(id buffer) { @@ -22,7 +25,7 @@ gnReturnCode metalSyncSubmit(gnOutputDevice device, gnSubmitSyncInfo info) { NSLog(@"Command buffer error: %s", buffer.error.localizedDescription.UTF8String); } if (atomic_fetch_sub_explicit(&buffersLeft, 1, memory_order_acq_rel) == 1) { - fenceToSignal->signaled = GN_TRUE; + [fenceToSignal->fence->event setSignaledValue:fenceToSignal->fence->currentValue]; } }]; @@ -33,7 +36,9 @@ gnReturnCode metalSyncSubmit(gnOutputDevice device, gnSubmitSyncInfo info) { } gnReturnCode metalSubmit(gnOutputDevice device, gnSubmitInfo info) { - for (int i = 0; i < info.commandBufferCount; i++) { + if (device == GN_NULL_HANDLE) return GN_INVALID_HANDLE; + + for (uint32_t i = 0; i < info.commandBufferCount; i++) { id commandBuffer = info.commandBuffers[i]->commandBuffer->commandBuffer; [commandBuffer commit]; } diff --git a/projects/apis/metal/src/surface/metal_surface.m b/projects/apis/metal/src/surface/metal_surface.m index 2b50fe4..a90de06 100644 --- a/projects/apis/metal/src/surface/metal_surface.m +++ b/projects/apis/metal/src/surface/metal_surface.m @@ -9,6 +9,7 @@ #import gnReturnCode createMetalSurface(gnWindowSurface windowSurface, gnInstanceHandle instance, gnMacOSWindowSurfaceInfo createInfo) { + if (instance == GN_NULL_HANDLE) return GN_INVALID_HANDLE; windowSurface->windowSurface = malloc(sizeof(gnPlatformWindowSurface)); windowSurface->windowSurface->layer = createInfo.layer; return GN_SUCCESS; @@ -26,13 +27,14 @@ gnImageFormat mtlMetalFormatToGryphn(MTLPixelFormat format) { gnSurfaceDetails getMetalSurfaceDetails( gnWindowSurface windowSurface, gnPhysicalDevice device ) { + if (device == GN_NULL_HANDLE) return (gnSurfaceDetails){ .formatCount = 0 }; gnSurfaceDetails surfaceDetails; surfaceDetails.formatCount = 1; surfaceDetails.formats = (gnSurfaceFormat[]){ { GN_FORMAT_BGRA8_SRGB, GN_COLOR_SPACE_SRGB_NONLINEAR } }; surfaceDetails.minImageCount = 2; surfaceDetails.maxImageCount = 3; CGSize size = windowSurface->windowSurface->layer.drawableSize; - surfaceDetails.minImageSize = surfaceDetails.maxImageSize = surfaceDetails.currentSize = (gnUInt2){size.width, size.height}; + surfaceDetails.minImageSize = surfaceDetails.maxImageSize = surfaceDetails.currentSize = (gnUInt2){.x = size.width, .y = size.height}; return surfaceDetails; } diff --git a/projects/apis/metal/src/sync/fence/metal_fence.h b/projects/apis/metal/src/sync/fence/metal_fence.h index fda644c..3ab14f3 100644 --- a/projects/apis/metal/src/sync/fence/metal_fence.h +++ b/projects/apis/metal/src/sync/fence/metal_fence.h @@ -3,10 +3,12 @@ #import #import -typedef struct gnPlatformFence_t {} gnPlatformFence; +typedef struct gnPlatformFence_t { + uint32_t currentValue; + id event; +} gnPlatformFence; gnReturnCode createMetalFence(gnFence fence, gnDevice device); -void singalMetalFence(gnFence fence); void waitForMetalFence(gnFence fence, uint64_t timeout); void resetMetalFence(gnFence fence); void destroyMetalFence(gnFence fence); diff --git a/projects/apis/metal/src/sync/fence/metal_fence.m b/projects/apis/metal/src/sync/fence/metal_fence.m index ad7009f..42111dc 100644 --- a/projects/apis/metal/src/sync/fence/metal_fence.m +++ b/projects/apis/metal/src/sync/fence/metal_fence.m @@ -1,33 +1,19 @@ #include "metal_fence.h" #include "devices/metal_output_devices.h" -gnReturnCode createMetalFence(gnFence fence, struct gnOutputDevice_t* device) { - // fence->fence = malloc(sizeof(gnPlatformFence)); - - // fence->fence->fence = [device->outputDevice->device newSharedEvent]; - // fence->fence->listener = [[MTLSharedEventListener alloc] init]; - // fence->fence->semaphore = dispatch_semaphore_create(1); - +gnReturnCode createMetalFence(gnFence fence, gnDevice device) { + fence->fence = malloc(sizeof(gnPlatformFence)); + fence->fence->event = [device->outputDevice->device newSharedEvent]; + fence->fence->currentValue = 0; return GN_SUCCESS; } -void singalMetalFence(gnFence fence) { - // dispatch_semaphore_signal(fence->fence->semaphore); -} void waitForMetalFence(gnFence fence, uint64_t timeout) { - // dispatch_semaphore_wait(fence->fence->semaphore, timeout); - while (fence->signaled == GN_FALSE) {} + [fence->fence->event waitUntilSignaledValue:fence->fence->currentValue timeoutMS:timeout]; } void resetMetalFence(gnFence fence) { - // dispatch_semaphore_signal(fence->fence->semaphore); - // [fence->fence->fence setSignaledValue:0]; - // [fence->fence->fence notifyListener:fence->fence->listener - // atValue:1 - // block:^(id ev, uint64_t val) { - // dispatch_semaphore_signal(fence->fence->semaphore); - // }]; + fence->fence->currentValue++; } void destroyMetalFence(gnFence fence) { - // [fence->fence->fence release]; - // [fence->fence->listener release]; - // free(fence->fence); + [fence->fence->event release]; + free(fence->fence); }