redo metal presentation
This commit is contained in:
@@ -4,12 +4,60 @@
|
||||
#include "instance/metal_instance.h"
|
||||
#include "instance/gryphn_instance.h"
|
||||
|
||||
#include "metal_shader.msl"
|
||||
|
||||
gnReturnCode createMetalOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle outputDevice, gnOutputDeviceInfo deviceInfo) {
|
||||
if (instance == GN_NULL_HANDLE) return GN_INVALID_HANDLE;
|
||||
|
||||
outputDevice->outputDevice = malloc(sizeof(gnPlatformOutputDevice));
|
||||
outputDevice->outputDevice->device = deviceInfo.physicalDevice->physicalDevice->device.retain;
|
||||
outputDevice->outputDevice->transferQueue = outputDevice->outputDevice->device.newCommandQueue;
|
||||
|
||||
// create full screen quad
|
||||
float verticies[] = {
|
||||
-1.0f, -1.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 1.0f, 0.0f,
|
||||
};
|
||||
outputDevice->outputDevice->fullScreenQuadBuffer =
|
||||
[outputDevice->outputDevice->device
|
||||
newBufferWithBytes:verticies
|
||||
length:sizeof(verticies)
|
||||
options:MTLResourceStorageModeShared
|
||||
];
|
||||
|
||||
NSError *error = nil;
|
||||
outputDevice->outputDevice->fullScreenShader = [outputDevice->outputDevice->device
|
||||
newLibraryWithSource:@(shader_source)
|
||||
options:nil
|
||||
error:&error
|
||||
];
|
||||
if (!outputDevice->outputDevice->fullScreenShader) {
|
||||
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
|
||||
.message = gnCombineStrings(gnCreateString("Failed to create shader for output device: \n"), error.localizedDescription.UTF8String)
|
||||
});
|
||||
return GN_DEVICE_LOST;
|
||||
}
|
||||
|
||||
outputDevice->outputDevice->fullScreenVertex = [outputDevice->outputDevice->fullScreenShader newFunctionWithName:@"fullscreen_vertex"];
|
||||
outputDevice->outputDevice->fullScreenFragment = [outputDevice->outputDevice->fullScreenShader newFunctionWithName:@"fullscreen_fragment"];
|
||||
|
||||
MTLRenderPipelineDescriptor *pipelineDesc = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
pipelineDesc.vertexFunction = outputDevice->outputDevice->fullScreenVertex;
|
||||
pipelineDesc.fragmentFunction = outputDevice->outputDevice->fullScreenFragment;
|
||||
pipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
|
||||
pipelineDesc.depthAttachmentPixelFormat = MTLPixelFormatInvalid;
|
||||
pipelineDesc.stencilAttachmentPixelFormat = MTLPixelFormatInvalid;
|
||||
|
||||
outputDevice->outputDevice->fullScreenPipeline = [outputDevice->outputDevice->device newRenderPipelineStateWithDescriptor:pipelineDesc error:&error];
|
||||
if (!outputDevice->outputDevice->fullScreenPipeline) {
|
||||
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
|
||||
.message = gnCombineStrings(gnCreateString("Failed to create graphics pipeline for output device: \n"), error.localizedDescription.UTF8String)
|
||||
});
|
||||
return GN_DEVICE_LOST;
|
||||
}
|
||||
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -20,6 +68,13 @@ void waitForMetalDevice(gnOutputDeviceHandle device) {
|
||||
void destroyMetalOutputDevice(gnOutputDeviceHandle device) {
|
||||
[device->outputDevice->transferQueue release];
|
||||
[device->outputDevice->device release];
|
||||
|
||||
[device->outputDevice->fullScreenQuadBuffer release];
|
||||
[device->outputDevice->fullScreenShader release];
|
||||
[device->outputDevice->fullScreenVertex release];
|
||||
[device->outputDevice->fullScreenFragment release];
|
||||
[device->outputDevice->fullScreenPipeline release];
|
||||
|
||||
free(device->outputDevice);
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,11 @@ struct gnPlatformOutputDevice_t {
|
||||
|
||||
id<MTLCommandBuffer> executingCommandBuffer;
|
||||
id<MTLCommandQueue> transferQueue;
|
||||
|
||||
id<MTLBuffer> fullScreenQuadBuffer;
|
||||
id<MTLLibrary> fullScreenShader;
|
||||
id<MTLFunction> fullScreenVertex, fullScreenFragment;
|
||||
id<MTLRenderPipelineState> fullScreenPipeline;
|
||||
} gnPlatformOutputDevice;
|
||||
|
||||
gnPhysicalDevice* getMetalDevices(gnInstanceHandle instance, uint32_t* deviceCount);
|
||||
|
26
projects/apis/metal/src/devices/metal_shader.msl
Normal file
26
projects/apis/metal/src/devices/metal_shader.msl
Normal file
@@ -0,0 +1,26 @@
|
||||
const char* shader_source =
|
||||
"using namespace metal;"
|
||||
""
|
||||
"struct Vertex {"
|
||||
" float2 position;"
|
||||
" float2 texcoord;"
|
||||
"};"
|
||||
""
|
||||
"struct VertexOut {"
|
||||
" float4 position [[position]];"
|
||||
" float2 texcoord;"
|
||||
"};"
|
||||
""
|
||||
"vertex VertexOut fullscreen_vertex(const device Vertex* vertices [[buffer(0)]],"
|
||||
" uint vid [[vertex_id]]) {"
|
||||
" VertexOut out;"
|
||||
" out.position = float4(vertices[vid].position, 0.0, 1.0);"
|
||||
" out.texcoord = vertices[vid].texcoord;"
|
||||
" return out;"
|
||||
"}"
|
||||
""
|
||||
"fragment float4 fullscreen_fragment(VertexOut in [[stage_in]],"
|
||||
" texture2d<float> tex [[texture(0)]]) {"
|
||||
" constexpr sampler s(address::clamp_to_edge, filter::linear);"
|
||||
" return tex.sample(s, in.texcoord);"
|
||||
"}";
|
@@ -65,8 +65,9 @@ gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gn
|
||||
|
||||
if (subpass.depthAttachment != NULL) {
|
||||
descriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
descriptor.depthAttachmentPixelFormat = info.renderPassDescriptor->renderPassDescriptor->subpasses[info.subpassIndex].depthAttachment.texture.pixelFormat;
|
||||
descriptor.stencilAttachmentPixelFormat = info.renderPassDescriptor->renderPassDescriptor->subpasses[info.subpassIndex].stencilAttachment.texture.pixelFormat;
|
||||
descriptor.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
// descriptor.depthAttachmentPixelFormat = info.renderPassDescriptor->renderPassDescriptor->subpasses[info.subpassIndex].depthAttachment.texture.pixelFormat;
|
||||
// descriptor.stencilAttachmentPixelFormat = info.renderPassDescriptor->renderPassDescriptor->subpasses[info.subpassIndex].stencilAttachment.texture.pixelFormat;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -53,6 +53,7 @@ gnReturnCode metalPresent(gnOutputDeviceHandle device, gnPresentInfo info) {
|
||||
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;
|
||||
info.presentationQueues[i]->info.surface->windowSurface->layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
|
||||
id<CAMetalDrawable> drawable = [info.presentationQueues[i]->info.surface->windowSurface->layer nextDrawable];
|
||||
if (drawable == nil) return GN_UNKNOWN_ERROR;
|
||||
|
||||
@@ -68,18 +69,19 @@ gnReturnCode metalPresentSync(gnOutputDeviceHandle device, gnPresentSyncInfo inf
|
||||
mtlAddImageBackToQueue(presentationQueue, imageIndex);
|
||||
}];
|
||||
|
||||
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}];
|
||||
MTLRenderPassDescriptor *desc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
desc.colorAttachments[0].texture = drawable.texture;
|
||||
desc.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||
desc.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||
desc.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
[blit endEncoding];
|
||||
id<MTLRenderCommandEncoder> enc = [commandBuffer renderCommandEncoderWithDescriptor:desc];
|
||||
|
||||
[enc setRenderPipelineState:device->outputDevice->fullScreenPipeline];
|
||||
[enc setVertexBuffer:device->outputDevice->fullScreenQuadBuffer offset:0 atIndex:0];
|
||||
[enc setFragmentTexture:info.presentationQueues[i]->images[info.imageIndices[i]]->texture->texture atIndex:0];
|
||||
[enc drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
|
||||
[enc endEncoding];
|
||||
|
||||
[commandBuffer presentDrawable:drawable];
|
||||
[commandBuffer commit];
|
||||
|
Reference in New Issue
Block a user