diff --git a/projects/apis/metal/src/present/metal_present.m b/projects/apis/metal/src/present/metal_present.m index d36d4b7..b902ab0 100644 --- a/projects/apis/metal/src/present/metal_present.m +++ b/projects/apis/metal/src/present/metal_present.m @@ -49,52 +49,45 @@ 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; - id drawable = [info.presentationQueues[i]->info.surface->windowSurface->layer nextDrawable]; - if (drawable == nil) return GN_FAILED_TO_CREATE_FRAMEBUFFER; + if (info.presentationQueues[i]->info.surface->windowSurface->layer.device == nil) info.presentationQueues[i]->info.surface->windowSurface->layer.device = device->outputDevice->device; + id drawable = [info.presentationQueues[i]->info.surface->windowSurface->layer nextDrawable]; + if (drawable == nil) return GN_FAILED_TO_CREATE_FRAMEBUFFER; - __block gnPresentationQueue presentationQueue = info.presentationQueues[i]; - __block uint32_t imageIndex = info.imageIndices[i]; + __block gnPresentationQueue presentationQueue = info.presentationQueues[i]; + __block uint32_t imageIndex = info.imageIndices[i]; - id commandBuffer = [device->outputDevice->transferQueue commandBuffer]; - [commandBuffer addCompletedHandler:^(id buffer) { - mtlAddImageBackToQueue(presentationQueue, imageIndex); - }]; + id commandBuffer = [device->outputDevice->transferQueue commandBuffer]; - id blit = [commandBuffer blitCommandEncoder]; - [blit copyFromTexture:info.presentationQueues[i]->images[info.imageIndices[i]]->texture->texture - sourceSlice:0 - sourceLevel:0 - sourceOrigin:(MTLOrigin){0, 0, 0} - sourceSize:(MTLSize){info.presentationQueues[i]->info.imageSize.x, info.presentationQueues[i]->info.imageSize.y, 1} - toTexture:drawable.texture - destinationSlice:0 - destinationLevel:0 - destinationOrigin:(MTLOrigin){0, 0, 0}]; + for (int c = 0; c < info.waitCount; c++) mtlWaitSemaphore(info.waitSemaphores[c], commandBuffer); - [blit endEncoding]; + [commandBuffer addCompletedHandler:^(id buffer) { + mtlAddImageBackToQueue(presentationQueue, imageIndex); + }]; - [commandBuffer presentDrawable:drawable]; - [commandBuffer commit]; - device->outputDevice->executingCommandBuffer = commandBuffer; - } + id blit = [commandBuffer blitCommandEncoder]; + [blit copyFromTexture:info.presentationQueues[i]->images[info.imageIndices[i]]->texture->texture + sourceSlice:0 + sourceLevel:0 + sourceOrigin:(MTLOrigin){0, 0, 0} + sourceSize:(MTLSize){info.presentationQueues[i]->info.imageSize.x, info.presentationQueues[i]->info.imageSize.y, 1} + toTexture:drawable.texture + destinationSlice:0 + destinationLevel:0 + destinationOrigin:(MTLOrigin){0, 0, 0}]; - // [device->outputDevice->executingCommandBuffer waitUntilScheduled]; + [blit endEncoding]; - 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) { - return GN_SUBOPTIMAL_PRESENTATION_QUEUE; - } + [commandBuffer presentDrawable:drawable]; + [commandBuffer commit]; + device->outputDevice->executingCommandBuffer = commandBuffer; + } + + 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) { + return GN_SUBOPTIMAL_PRESENTATION_QUEUE; + } } return GN_SUCCESS; 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 c7e135f..d512a90 100644 --- a/projects/apis/metal/src/presentation_queue/metal_presentation_queue.m +++ b/projects/apis/metal/src/presentation_queue/metal_presentation_queue.m @@ -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 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); } diff --git a/projects/apis/metal/src/submit/metal_submit.m b/projects/apis/metal/src/submit/metal_submit.m index 4cd54ab..d83a30d 100644 --- a/projects/apis/metal/src/submit/metal_submit.m +++ b/projects/apis/metal/src/submit/metal_submit.m @@ -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 buffer = [info.commandBuffers[i]->commandPool->commandPool->commandQueue commandBuffer]; + for (int 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++) + mtlSignalSemaphore(info.signalSemaphores[c], commandBuffer); + [info.commandBuffers[i]->commandBuffer->commandBuffer addCompletedHandler:^(id 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; } - fenceToSignal->signaled = gnTrue; }]; [commandBuffer commit]; diff --git a/projects/apis/metal/src/sync/semaphore/metal_semaphore.h b/projects/apis/metal/src/sync/semaphore/metal_semaphore.h index 6d587e4..10f2f83 100644 --- a/projects/apis/metal/src/sync/semaphore/metal_semaphore.h +++ b/projects/apis/metal/src/sync/semaphore/metal_semaphore.h @@ -1,11 +1,17 @@ #pragma once #include "synchronization/semaphore/gryphn_semaphore.h" #import +#import +#import typedef struct gnPlatformSemaphore_t { id event; - bool eventTriggered; + atomic_uint_fast64_t currentValue; } gnPlatformSemaphore; gnReturnCode createMetalSemaphore(gnSemaphore semaphore, gnOutputDevice device); void destroyMetalSemaphore(gnSemaphore semaphore); + + +void mtlSignalSemaphore(gnSemaphore semaphore, id cmdBuf); +void mtlWaitSemaphore(gnSemaphore semaphore, id cmdBuf); diff --git a/projects/apis/metal/src/sync/semaphore/metal_semaphore.m b/projects/apis/metal/src/sync/semaphore/metal_semaphore.m index bfa815e..e0c2234 100644 --- a/projects/apis/metal/src/sync/semaphore/metal_semaphore.m +++ b/projects/apis/metal/src/sync/semaphore/metal_semaphore.m @@ -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 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 cmdBuf) { + uint64_t val = atomic_load_explicit(&semaphore->semaphore->currentValue, memory_order_acquire); + [cmdBuf encodeWaitForEvent:semaphore->semaphore->event value:val]; +}