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) {
|
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++) {
|
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];
|
id<CAMetalDrawable> drawable = [info.presentationQueues[i]->info.surface->windowSurface->layer nextDrawable];
|
||||||
if (drawable == nil) return GN_FAILED_TO_CREATE_FRAMEBUFFER;
|
if (drawable == nil) return GN_FAILED_TO_CREATE_FRAMEBUFFER;
|
||||||
|
|
||||||
__block gnPresentationQueue presentationQueue = info.presentationQueues[i];
|
__block gnPresentationQueue presentationQueue = info.presentationQueues[i];
|
||||||
__block uint32_t imageIndex = info.imageIndices[i];
|
__block uint32_t imageIndex = info.imageIndices[i];
|
||||||
|
|
||||||
id<MTLCommandBuffer> commandBuffer = [device->outputDevice->transferQueue commandBuffer];
|
id<MTLCommandBuffer> commandBuffer = [device->outputDevice->transferQueue commandBuffer];
|
||||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
|
|
||||||
mtlAddImageBackToQueue(presentationQueue, imageIndex);
|
|
||||||
}];
|
|
||||||
|
|
||||||
id<MTLBlitCommandEncoder> blit = [commandBuffer blitCommandEncoder];
|
for (int c = 0; c < info.waitCount; c++) mtlWaitSemaphore(info.waitSemaphores[c], commandBuffer);
|
||||||
[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}];
|
|
||||||
|
|
||||||
[blit endEncoding];
|
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
|
||||||
|
mtlAddImageBackToQueue(presentationQueue, imageIndex);
|
||||||
|
}];
|
||||||
|
|
||||||
[commandBuffer presentDrawable:drawable];
|
id<MTLBlitCommandEncoder> blit = [commandBuffer blitCommandEncoder];
|
||||||
[commandBuffer commit];
|
[blit copyFromTexture:info.presentationQueues[i]->images[info.imageIndices[i]]->texture->texture
|
||||||
device->outputDevice->executingCommandBuffer = commandBuffer;
|
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++) {
|
[commandBuffer presentDrawable:drawable];
|
||||||
if (info.presentationQueues[i]->info.imageSize.x != info.presentationQueues[i]->info.surface->windowSurface->layer.drawableSize.width ||
|
[commandBuffer commit];
|
||||||
info.presentationQueues[i]->info.imageSize.y != info.presentationQueues[i]->info.surface->windowSurface->layer.drawableSize.height) {
|
device->outputDevice->executingCommandBuffer = commandBuffer;
|
||||||
return GN_SUBOPTIMAL_PRESENTATION_QUEUE;
|
}
|
||||||
}
|
|
||||||
|
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;
|
return GN_SUCCESS;
|
||||||
|
@@ -51,12 +51,19 @@ gnReturnCode createMetalPresentationQueue(gnPresentationQueueHandle presentation
|
|||||||
void mtlTakeImageFromQueue(uint32_t* whereToPut, gnPresentationQueue queue, gnSemaphore semaphore) {
|
void mtlTakeImageFromQueue(uint32_t* whereToPut, gnPresentationQueue queue, gnSemaphore semaphore) {
|
||||||
*whereToPut = queue->presentationQueue->avaliableTextures.data[0];
|
*whereToPut = queue->presentationQueue->avaliableTextures.data[0];
|
||||||
uint32_tArrayListPopHead(&queue->presentationQueue->avaliableTextures);
|
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) {
|
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);
|
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
|
else
|
||||||
uint32_tArrayListAdd(&queue->presentationQueue->avaliableTextures, index);
|
uint32_tArrayListAdd(&queue->presentationQueue->avaliableTextures, index);
|
||||||
}
|
}
|
||||||
|
@@ -2,29 +2,27 @@
|
|||||||
#include "synchronization/fence/gryphn_fence.h"
|
#include "synchronization/fence/gryphn_fence.h"
|
||||||
|
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "time.h"
|
|
||||||
|
|
||||||
|
|
||||||
gnReturnCode metalSyncSubmit(gnOutputDevice device, gnSubmitSyncInfo info) {
|
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 gnFence fenceToSignal = info.fence;
|
||||||
|
__block atomic_int buffersLeft;
|
||||||
|
atomic_init(&buffersLeft, info.commandBufferCount);
|
||||||
|
|
||||||
for (int i = 0; i < info.commandBufferCount; i++) {
|
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;
|
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) {
|
[info.commandBuffers[i]->commandBuffer->commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
|
||||||
for (int c = 0; c < semsToSignalCount; c++) {
|
if (atomic_fetch_sub_explicit(&buffersLeft, 1, memory_order_acq_rel) == 1) {
|
||||||
semsToSignal[c]->semaphore->eventTriggered = gnTrue;
|
fenceToSignal->signaled = gnTrue;
|
||||||
}
|
}
|
||||||
fenceToSignal->signaled = gnTrue;
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[commandBuffer commit];
|
[commandBuffer commit];
|
||||||
|
@@ -1,11 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "synchronization/semaphore/gryphn_semaphore.h"
|
#include "synchronization/semaphore/gryphn_semaphore.h"
|
||||||
#import <Metal/MTLEvent.h>
|
#import <Metal/MTLEvent.h>
|
||||||
|
#import <Metal/MTLCommandBuffer.h>
|
||||||
|
#import <stdatomic.h>
|
||||||
|
|
||||||
typedef struct gnPlatformSemaphore_t {
|
typedef struct gnPlatformSemaphore_t {
|
||||||
id<MTLEvent> event;
|
id<MTLEvent> event;
|
||||||
bool eventTriggered;
|
atomic_uint_fast64_t currentValue;
|
||||||
} gnPlatformSemaphore;
|
} gnPlatformSemaphore;
|
||||||
|
|
||||||
gnReturnCode createMetalSemaphore(gnSemaphore semaphore, gnOutputDevice device);
|
gnReturnCode createMetalSemaphore(gnSemaphore semaphore, gnOutputDevice device);
|
||||||
void destroyMetalSemaphore(gnSemaphore semaphore);
|
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) {
|
gnReturnCode createMetalSemaphore(gnSemaphore semaphore, gnOutputDevice device) {
|
||||||
semaphore->semaphore = malloc(sizeof(gnPlatformSemaphore));
|
semaphore->semaphore = malloc(sizeof(gnPlatformSemaphore));
|
||||||
semaphore->semaphore->event = [device->outputDevice->device newEvent];
|
semaphore->semaphore->event = [device->outputDevice->device newEvent];
|
||||||
|
semaphore->semaphore->currentValue = 0;
|
||||||
return GN_SUCCESS;
|
return GN_SUCCESS;
|
||||||
}
|
}
|
||||||
void destroyMetalSemaphore(gnSemaphore semaphore) {
|
void destroyMetalSemaphore(gnSemaphore semaphore) {
|
||||||
[semaphore->semaphore->event release];
|
[semaphore->semaphore->event release];
|
||||||
free(semaphore->semaphore);
|
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