#include "metal_present.h" #include #include "time.h" gnReturnCode metalPresent(gnOutputDeviceHandle device, gnPresentInfo info) { for (uint32_t 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_UNKNOWN_ERROR; __block gnPresentationQueue presentationQueue = info.presentationQueues[i]; __block uint32_t imageIndex = info.imageIndices[i]; id commandBuffer = [device->outputDevice->transferQueue commandBuffer]; [commandBuffer addCompletedHandler:^(id buffer) { if (buffer == nil) return; uint32_tArrayListAdd(presentationQueue->presentationQueue->avaliableTextures, imageIndex); }]; 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}]; [blit endEncoding]; [drawable texture]; [commandBuffer presentDrawable:drawable]; [commandBuffer commit]; device->outputDevice->executingCommandBuffer = commandBuffer; } [device->outputDevice->executingCommandBuffer waitUntilCompleted]; for (uint32_t 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; } gnReturnCode metalPresentSync(gnOutputDeviceHandle device, gnPresentSyncInfo info) { for (uint32_t i = 0; i < info.presentationQueueCount; i++) { 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_UNKNOWN_ERROR; __block gnPresentationQueue presentationQueue = info.presentationQueues[i]; __block uint32_t imageIndex = info.imageIndices[i]; id commandBuffer = [device->outputDevice->transferQueue commandBuffer]; for (uint32_t c = 0; c < info.waitCount; c++) mtlWaitSemaphore(info.waitSemaphores[c], commandBuffer); [commandBuffer addCompletedHandler:^(id buffer) { if (buffer == nil) return; mtlAddImageBackToQueue(presentationQueue, imageIndex); }]; 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}]; [blit endEncoding]; [commandBuffer presentDrawable:drawable]; [commandBuffer commit]; device->outputDevice->executingCommandBuffer = commandBuffer; } for (uint32_t 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; }