redo semaphore impl on metal

This commit is contained in:
Greg Wells
2025-07-11 17:08:28 -04:00
parent 2def510f69
commit 8445c0553b
5 changed files with 71 additions and 57 deletions

View File

@@ -49,16 +49,8 @@ gnReturnCode metalPresent(gnOutputDeviceHandle device, gnPresentInfo info) {
}
gnReturnCode metalPresentSync(gnOutputDeviceHandle device, gnPresentSyncInfo info) {
clock_t begin = clock();
for (int i = 0; i < info.waitCount; i++) {
while (!info.waitSemaphores[i]->semaphore->eventTriggered) {}
}
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("time spent waiting to present: %lf\n", time_spent);
for (int i =0 ; i < info.presentationQueueCount; i++) {
info.presentationQueues[i]->info.surface->windowSurface->layer.device = device->outputDevice->device;
if (info.presentationQueues[i]->info.surface->windowSurface->layer.device == nil) info.presentationQueues[i]->info.surface->windowSurface->layer.device = device->outputDevice->device;
id<CAMetalDrawable> drawable = [info.presentationQueues[i]->info.surface->windowSurface->layer nextDrawable];
if (drawable == nil) return GN_FAILED_TO_CREATE_FRAMEBUFFER;
@@ -66,6 +58,9 @@ gnReturnCode metalPresentSync(gnOutputDeviceHandle device, gnPresentSyncInfo inf
__block uint32_t imageIndex = info.imageIndices[i];
id<MTLCommandBuffer> commandBuffer = [device->outputDevice->transferQueue commandBuffer];
for (int c = 0; c < info.waitCount; c++) mtlWaitSemaphore(info.waitSemaphores[c], commandBuffer);
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
mtlAddImageBackToQueue(presentationQueue, imageIndex);
}];
@@ -88,8 +83,6 @@ gnReturnCode metalPresentSync(gnOutputDeviceHandle device, gnPresentSyncInfo inf
device->outputDevice->executingCommandBuffer = commandBuffer;
}
// [device->outputDevice->executingCommandBuffer waitUntilScheduled];
for (int i = 0; i < info.presentationQueueCount; i++) {
if (info.presentationQueues[i]->info.imageSize.x != info.presentationQueues[i]->info.surface->windowSurface->layer.drawableSize.width ||
info.presentationQueues[i]->info.imageSize.y != info.presentationQueues[i]->info.surface->windowSurface->layer.drawableSize.height) {

View File

@@ -51,12 +51,19 @@ gnReturnCode createMetalPresentationQueue(gnPresentationQueueHandle presentation
void mtlTakeImageFromQueue(uint32_t* whereToPut, gnPresentationQueue queue, gnSemaphore semaphore) {
*whereToPut = queue->presentationQueue->avaliableTextures.data[0];
uint32_tArrayListPopHead(&queue->presentationQueue->avaliableTextures);
if (semaphore) semaphore->semaphore->eventTriggered = gnTrue;
if (!semaphore) return;
id<MTLCommandBuffer> buffer = [queue->outputDevice->outputDevice->transferQueue commandBuffer];
mtlSignalSemaphore(semaphore, buffer);
[buffer commit];
}
void mtlAddImageBackToQueue(gnPresentationQueue queue, uint32_t index) {
if (queue->presentationQueue->neededImages.count > 0)
if (queue->presentationQueue->neededImages.count > 0) {
mtlTakeImageFromQueue(queue->presentationQueue->neededImages.data[queue->presentationQueue->neededImages.count - 1].whereToPut, queue, queue->presentationQueue->neededImages.data[queue->presentationQueue->neededImages.count - 1].semaphoreToSignal);
mtlImageNeededArrayListRemove(&queue->presentationQueue->neededImages);
}
else
uint32_tArrayListAdd(&queue->presentationQueue->avaliableTextures, index);
}

View File

@@ -2,29 +2,27 @@
#include "synchronization/fence/gryphn_fence.h"
#include "stdio.h"
#include "time.h"
gnReturnCode metalSyncSubmit(gnOutputDevice device, gnSubmitSyncInfo info) {
clock_t begin = clock();
for (int i = 0; i < info.waitCount; i++) {
while (!info.waitSemaphores[i]->semaphore->eventTriggered) {}
}
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("time spent waiting for image in submit: %lf\n", time_spent);
__block gnSemaphore* semsToSignal = info.signalSemaphores;
__block int semsToSignalCount = info.signalCount;
__block gnFence fenceToSignal = info.fence;
__block atomic_int buffersLeft;
atomic_init(&buffersLeft, info.commandBufferCount);
for (int i = 0; i < info.commandBufferCount; i++) {
id <MTLCommandBuffer> buffer = [info.commandBuffers[i]->commandPool->commandPool->commandQueue commandBuffer];
for (int c = 0; c < info.waitCount; c++)
mtlWaitSemaphore(info.waitSemaphores[c], buffer);
[buffer commit];
id<MTLCommandBuffer> commandBuffer = info.commandBuffers[i]->commandBuffer->commandBuffer;
for (int c = 0; c < info.signalCount; c++)
mtlSignalSemaphore(info.signalSemaphores[c], commandBuffer);
[info.commandBuffers[i]->commandBuffer->commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
for (int c = 0; c < semsToSignalCount; c++) {
semsToSignal[c]->semaphore->eventTriggered = gnTrue;
}
if (atomic_fetch_sub_explicit(&buffersLeft, 1, memory_order_acq_rel) == 1) {
fenceToSignal->signaled = gnTrue;
}
}];
[commandBuffer commit];

View File

@@ -1,11 +1,17 @@
#pragma once
#include "synchronization/semaphore/gryphn_semaphore.h"
#import <Metal/MTLEvent.h>
#import <Metal/MTLCommandBuffer.h>
#import <stdatomic.h>
typedef struct gnPlatformSemaphore_t {
id<MTLEvent> event;
bool eventTriggered;
atomic_uint_fast64_t currentValue;
} gnPlatformSemaphore;
gnReturnCode createMetalSemaphore(gnSemaphore semaphore, gnOutputDevice device);
void destroyMetalSemaphore(gnSemaphore semaphore);
void mtlSignalSemaphore(gnSemaphore semaphore, id<MTLCommandBuffer> cmdBuf);
void mtlWaitSemaphore(gnSemaphore semaphore, id<MTLCommandBuffer> cmdBuf);

View File

@@ -4,10 +4,20 @@
gnReturnCode createMetalSemaphore(gnSemaphore semaphore, gnOutputDevice device) {
semaphore->semaphore = malloc(sizeof(gnPlatformSemaphore));
semaphore->semaphore->event = [device->outputDevice->device newEvent];
semaphore->semaphore->currentValue = 0;
return GN_SUCCESS;
}
void destroyMetalSemaphore(gnSemaphore semaphore) {
[semaphore->semaphore->event release];
free(semaphore->semaphore);
}
void mtlSignalSemaphore(gnSemaphore semaphore, id<MTLCommandBuffer> cmdBuf) {
uint64_t val = atomic_fetch_add_explicit(&semaphore->semaphore->currentValue, 1, memory_order_acq_rel) + 1;
[cmdBuf encodeSignalEvent:semaphore->semaphore->event value:val];
}
void mtlWaitSemaphore(gnSemaphore semaphore, id<MTLCommandBuffer> cmdBuf) {
uint64_t val = atomic_load_explicit(&semaphore->semaphore->currentValue, memory_order_acquire);
[cmdBuf encodeWaitForEvent:semaphore->semaphore->event value:val];
}