redo semaphore impl on metal
This commit is contained in:
@@ -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<CAMetalDrawable> 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<CAMetalDrawable> 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<MTLCommandBuffer> commandBuffer = [device->outputDevice->transferQueue commandBuffer];
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
|
||||
mtlAddImageBackToQueue(presentationQueue, imageIndex);
|
||||
}];
|
||||
id<MTLCommandBuffer> commandBuffer = [device->outputDevice->transferQueue commandBuffer];
|
||||
|
||||
id<MTLBlitCommandEncoder> 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<MTLCommandBuffer> buffer) {
|
||||
mtlAddImageBackToQueue(presentationQueue, imageIndex);
|
||||
}];
|
||||
|
||||
[commandBuffer presentDrawable:drawable];
|
||||
[commandBuffer commit];
|
||||
device->outputDevice->executingCommandBuffer = commandBuffer;
|
||||
}
|
||||
id<MTLBlitCommandEncoder> 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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
fenceToSignal->signaled = gnTrue;
|
||||
}];
|
||||
|
||||
[commandBuffer commit];
|
||||
|
@@ -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);
|
||||
|
@@ -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];
|
||||
}
|
||||
|
Reference in New Issue
Block a user