rename to projects (DOES NOT COMPILE)

This commit is contained in:
Gregory Wells
2025-06-24 12:04:16 -04:00
parent 7a80d0fd61
commit d66f470a52
148 changed files with 2 additions and 4 deletions

View File

@@ -0,0 +1,28 @@
set(CMAKE_EXPORT_COMPILE_COMMANDS on)
set(CMAKE_CXX_STANDARD 17)
project(GryphnMetalImpl)
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS
"src/*.c" "src/*.h" "src/*.m"
)
add_library(GryphnMetalImpl STATIC ${SOURCE_FILES})
target_include_directories(GryphnMetalImpl PUBLIC
${CMAKE_SOURCE_DIR}/gryphn/include/
${CMAKE_SOURCE_DIR}/gryphn/src/
${CMAKE_SOURCE_DIR}/gryphn/src/utils/
src/
depends/SPIRV-Cross/
)
add_compile_definitions(GN_REVEAL_IMPL)
add_subdirectory(depends/SPIRV-Cross)
target_link_libraries(GryphnMetalImpl spirv-cross-core spirv-cross-msl spirv-cross-c)
target_link_libraries(GryphnMetalImpl
"-framework IOKit"
"-framework CoreFoundation"
"-framework CoreGraphics"
"-framework Foundation"
"-framework Metal"
"-framework QuartzCore"
)

View File

@@ -0,0 +1,7 @@
#pragma once
#import <Metal/Metal.h>
struct gnPlatformBuffer_t {
id<MTLBuffer> buffer, stagingBuffer;
bool useStagingBuffer;
};

View File

@@ -0,0 +1,40 @@
#include "metal_buffer.h"
#include "core/buffers/gryphn_buffer.h"
#include "core/output_device/gryphn_output_device.h"
#include "core/devices/metal_output_devices.h"
gnReturnCode gnCreateBufferFn(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info) {
buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t));
MTLResourceOptions option;
buffer->buffer->useStagingBuffer = (info.usage == GN_DYNAMIC_DRAW) ? NO : YES;
if (info.usage == GN_DYNAMIC_DRAW)
option = MTLResourceStorageModeShared;
else {
option = MTLResourceStorageModePrivate;
buffer->buffer->stagingBuffer = [device->outputDevice->device newBufferWithLength:info.size options:MTLResourceStorageModeShared];
}
buffer->buffer->buffer = [device->outputDevice->device newBufferWithLength:info.size options:option];
return GN_SUCCESS;
}
void gnBufferDataFn(gnBufferHandle buffer, size_t dataSize, void* data) {
void* bufferData;
if (buffer->buffer->useStagingBuffer) {
memcpy(buffer->buffer->stagingBuffer.contents, data, dataSize);
id<MTLCommandBuffer> commandBuffer = [buffer->device->outputDevice->transferQueue commandBuffer];
id<MTLBlitCommandEncoder> encoder = [commandBuffer blitCommandEncoder];
[encoder copyFromBuffer:buffer->buffer->stagingBuffer sourceOffset:0 toBuffer:buffer->buffer->buffer destinationOffset:0 size:dataSize];
[encoder endEncoding];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
} else
memcpy(buffer->buffer->buffer.contents, data, dataSize);
}
void* gnMapBufferFn(gnBufferHandle buffer) {
return buffer->buffer->buffer.contents;
}
void gnDestroyBufferFn(gnBufferHandle buffer) {
if (buffer->buffer->useStagingBuffer)
[buffer->buffer->stagingBuffer release];
[buffer->buffer->buffer release];
free(buffer->buffer);
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include "core/command/command_buffer/gryphn_command_buffer.h"
#include "core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h"
#import <Metal/MTLCommandBuffer.h>
#import <Metal/MTLCommandEncoder.h>
typedef struct gnPlatformCommandBuffer_t {
id<MTLCommandBuffer> commandBuffer;
id<MTLCommandEncoder> encoder;
struct gnGraphicsPipeline_t* boundGraphcisPipeline;
gnBufferHandle indexBuffer;
} gnPlatformCommandBuffer;

View File

@@ -0,0 +1,24 @@
#include "metal_command_buffer.h"
#include "core/commands/command_pool/metal_command_pool.h"
#import <Metal/Metal.h>
gnReturnCode gnCommandPoolAllocateCommandBuffersFn(gnCommandBufferHandle* commandBuffers, uint32_t count, struct gnCommandPool_t* pool) {
for (int i = 0; i < count; i++) {
commandBuffers[i]->commandBuffer = malloc(sizeof(gnPlatformCommandBuffer));
}
return GN_SUCCESS;
}
void gnResetCommandBufferFn(struct gnCommandBuffer_t *commandBuffer) {
// do nothing
}
gnReturnCode gnBeginCommandBufferFn(struct gnCommandBuffer_t* commandBuffer) {
commandBuffer->commandBuffer->boundGraphcisPipeline = NULL;
commandBuffer->commandBuffer->commandBuffer = [commandBuffer->commandPool->commandPool->commandQueue commandBuffer];
return GN_SUCCESS;
}
gnReturnCode gnEndCommandBufferFn(struct gnCommandBuffer_t* commandBuffer) {
// [commandBuffer->commandBuffer->commandBuffer commit];
return GN_SUCCESS;
}

View File

@@ -0,0 +1,7 @@
#pragma once
#import <Metal/Metal.h>
#include "core/command/command_pool/gryphn_command_pool.h"
typedef struct gnPlatformCommandPool_t {
id<MTLCommandQueue> commandQueue;
} gnPlatformCommandPool;

View File

@@ -0,0 +1,14 @@
#include "metal_command_pool.h"
#include "core/devices/metal_output_devices.h"
gnReturnCode gnCreateCommandPoolFn(struct gnCommandPool_t* commandPool, struct gnOutputDevice_t* device, struct gnCommandPoolInfo_t info) {
commandPool->commandPool = malloc(sizeof(struct gnPlatformCommandPool_t));
commandPool->commandPool->commandQueue = [device->outputDevice->device newCommandQueue];
return GN_SUCCESS;
}
void gnDestroyCommandPoolFn(struct gnCommandPool_t* commandPool) {
[commandPool->commandPool->commandQueue release];
free(commandPool->commandPool);
}

View File

@@ -0,0 +1,127 @@
#include "core/command/commands/gryphn_command.h"
#include "core/framebuffers/metal_framebuffer.h"
#include "core/commands/command_buffer/metal_command_buffer.h"
#include "core/pipelines/graphics_pipeline/metal_graphics_pipeline.h"
#include "core/buffer/metal_buffer.h"
#include "core/uniforms/metal_uniform.h"
#import <Metal/MTLRenderCommandEncoder.h>
void gnCommandBeginRenderPassFn(struct gnCommandBuffer_t* buffer, struct gnRenderPassInfo_t passInfo) {
int currentColorAttachment = 0;
for (int i = 0; i < passInfo.clearValueCount; i++) {
gnBool wasDepthStencil = gnFalse;
if (isDepthFormat(passInfo.renderPassDescriptor->info.attachmentInfos[i].format)) {
wasDepthStencil = gnTrue;
}
if (isStencilFormat(passInfo.renderPassDescriptor->info.attachmentInfos[i].format)) {
wasDepthStencil = gnTrue;
}
if(!wasDepthStencil) {
MTLRenderPassColorAttachmentDescriptor* color = passInfo.framebuffer->framebuffer->framebuffer.colorAttachments[i];
color.clearColor = MTLClearColorMake(
passInfo.clearValues[i].red,
passInfo.clearValues[i].green,
passInfo.clearValues[i].blue,
passInfo.clearValues[i].alpha
);
}
}
buffer->commandBuffer->encoder = [buffer->commandBuffer->commandBuffer renderCommandEncoderWithDescriptor:passInfo.framebuffer->framebuffer->framebuffer];
MTLViewport vp = {(double)passInfo.offset.x, (double)passInfo.offset.y, (double)passInfo.size.x, (double)passInfo.size.y, 0.0f, 1.0f};
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
[encoder setViewport:vp];
}
void gnCommandEndRenderPassFn(struct gnCommandBuffer_t* buffer) {
[buffer->commandBuffer->encoder endEncoding];
}
void gnCommandBindGraphicsPipelineFn(struct gnCommandBuffer_t* buffer, struct gnGraphicsPipeline_t* graphicsPipeline) {
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
[encoder setRenderPipelineState:graphicsPipeline->graphicsPipeline->graphicsPipeline];
if (graphicsPipeline->info.cullMode.face == GN_CULL_FACE_BACK)
[encoder setCullMode:MTLCullModeBack];
else if (graphicsPipeline->info.cullMode.face == GN_CULL_FACE_FRONT)
[encoder setCullMode:MTLCullModeFront];
else if (graphicsPipeline->info.cullMode.face == GN_CULL_FACE_NONE)
[encoder setCullMode:MTLCullModeNone];
if (graphicsPipeline->info.cullMode.direction == GN_DIRECTION_CLOCK_WISE)
[encoder setFrontFacingWinding:MTLWindingCounterClockwise];
if (graphicsPipeline->info.cullMode.direction == GN_DIRECTION_COUNTER_CLOCK_WISE)
[encoder setFrontFacingWinding:MTLWindingClockwise];
if (graphicsPipeline->info.fillMode == GN_FILL_MODE_POINT)
[encoder setTriangleFillMode:MTLTriangleFillModeFill];
if (graphicsPipeline->info.fillMode == GN_FILL_MODE_LINE)
[encoder setTriangleFillMode:MTLTriangleFillModeLines];
if (graphicsPipeline->info.fillMode == GN_FILL_MODE_FILL)
[encoder setTriangleFillMode:MTLTriangleFillModeFill];
buffer->commandBuffer->boundGraphcisPipeline = graphicsPipeline;
}
void gnCommandSetViewportFn(struct gnCommandBuffer_t* buffer, struct gnViewport_t viewport) {
MTLViewport vp = {(double)viewport.position.x, (double)viewport.position.y, (double)viewport.size.x, (double)viewport.size.y, viewport.minDepth, viewport.maxDepth};
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
[encoder setViewport:vp];
}
void gnCommandSetScissorFn(struct gnCommandBuffer_t* buffer, struct gnScissor_t scissor) {
MTLScissorRect scissorRect = { scissor.position.x, scissor.position.y, scissor.size.x, scissor.size.y };
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
[encoder setScissorRect:scissorRect];
}
void gnCommandBindBufferFn(gnCommandBufferHandle buffer, gnBufferHandle bufferToBind, gnBufferType type) {
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
if (type == GN_VERTEX_BUFFER)
[encoder setVertexBuffer:bufferToBind->buffer->buffer offset:0 atIndex:0];
else if (type == GN_INDEX_BUFFER)
buffer->commandBuffer->indexBuffer = bufferToBind;
}
void gnCommandDrawFn(struct gnCommandBuffer_t* buffer, int vertexCount, int firstVertex, int instanceCount, int firstInstance) {
if (buffer->commandBuffer->boundGraphcisPipeline != NULL) {
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_POINTS)
[encoder drawPrimitives:MTLPrimitiveTypePoint vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance];
else if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_LINES)
[encoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance];
else if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_LINE_STRIP)
[encoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance];
else if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_TRIANGLES)
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance];
else if (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType == GN_PRIMITIVE_TRIANGLE_STRIP)
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:firstVertex vertexCount:vertexCount instanceCount:instanceCount baseInstance:firstInstance];
}
}
void gnCommandDrawIndexedFn(gnCommandBufferHandle buffer, gnIndexType type, int indexCount, int firstIndex, int vertexOffset, int instanceCount, int firstInstance) {
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
MTLPrimitiveType primative;
switch (buffer->commandBuffer->boundGraphcisPipeline->info.primitiveType) {
case GN_PRIMITIVE_POINTS: primative = MTLPrimitiveTypePoint; break;
case GN_PRIMITIVE_LINE_STRIP: primative = MTLPrimitiveTypeLineStrip; break;
case GN_PRIMITIVE_LINES: primative = MTLPrimitiveTypeLine; break;
case GN_PRIMITIVE_TRIANGLE_STRIP: primative = MTLPrimitiveTypeTriangleStrip; break;
case GN_PRIMITIVE_TRIANGLES: primative = MTLPrimitiveTypeTriangle; break;
}
[encoder
drawIndexedPrimitives:primative
indexCount:indexCount
indexType:((type == GN_UINT32) ? MTLIndexTypeUInt32 : MTLIndexTypeUInt16)
indexBuffer:buffer->commandBuffer->indexBuffer->buffer->buffer
indexBufferOffset:0
instanceCount:instanceCount
baseVertex:vertexOffset
baseInstance:firstInstance
];
}
void gnCommandBindUniformFn(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t set) {
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
if (uniform->uniform->type == GN_UNIFORM_BUFFER_DESCRIPTOR) {
gnBufferUniformInfo info = *(gnBufferUniformInfo*)uniform->uniform->data;
[encoder setVertexBuffer:info.buffer->buffer->buffer
offset:info.offset
atIndex:(info.binding + 1)
];
}
}

View File

@@ -0,0 +1,9 @@
#include <core/debugger/gryphn_debugger.h>
// these do nothing because I am too lazy to write a debugger for metal at this point in time
gnReturnCode gnCreateDebuggerFn(gnDebuggerHandle debugger, gnInstanceHandle instance, const struct gnDebuggerInfo_t info) {
return GN_SUCCESS;
}
void gnDestroyDebuggerFn(gnDebuggerHandle instance) {
}

View File

@@ -0,0 +1,37 @@
#include <core/output_device/gryphn_physical_output_device.h>
#include <Metal/Metal.h>
#include "metal_output_devices.h"
#include "core/instance/metal_instance.h"
#include "core/instance/gryphn_instance.h"
#include <core/debugger/gryphn_debugger.h>
gnReturnCode gnCreateOutputDeviceFn(gnOutputDeviceHandle outputDevice, gnInstanceHandle instance, struct gnOutputDeviceInfo_t deviceInfo) {
outputDevice->outputDevice = malloc(sizeof(gnPlatformOutputDevice));
outputDevice->outputDevice->device = deviceInfo.physicalDevice.physicalDevice->device.retain;
outputDevice->outputDevice->transferQueue = outputDevice->outputDevice->device.newCommandQueue;
// outputDevice->outputDevice->queueCount = deviceInfo.queueInfoCount;
// outputDevice->outputDevice->queues = malloc(sizeof(id<MTLCommandQueue>) * deviceInfo.queueInfoCount);
// for (int i = 0; i < deviceInfo.queueInfoCount; i++) {
// outputDevice->outputDevice->queues[i] = outputDevice->outputDevice->device.newCommandQueue;
// }
return GN_SUCCESS;
}
void gnWaitForDeviceFn(gnOutputDeviceHandle device) {
[device->outputDevice->executingCommandBuffer waitUntilCompleted];
}
void gnDestroyOutputDeviceFn(gnOutputDeviceHandle device) {
// for (int i = 0; i < device->outputDevice->queueCount; i++) {
// [device->outputDevice->queues[i] release];
// }
[device->outputDevice->transferQueue release];
[device->outputDevice->device release];
free(device->outputDevice);
}
// struct mtlFramebufferVertex {
// float x, y;
// float u, v;
// };

View File

@@ -0,0 +1,18 @@
#pragma once
#include "core/instance/gryphn_instance.h"
#include "core/output_device/gryphn_output_device.h"
#include <Metal/Metal.h>
#include <MetalKit/MetalKit.h>
struct gnPlatformPhysicalDevice_t {
id<MTLDevice> device;
} gnPlatformPhysicalDevice;
struct gnPlatformOutputDevice_t {
id<MTLDevice> device;
MTKView* contentView;
id<MTLCommandBuffer> executingCommandBuffer;
id<MTLCommandQueue> transferQueue;
// id<MTLRenderPipelineState> framebuffer;
} gnPlatformOutputDevice;

View File

@@ -0,0 +1,39 @@
#include <core/output_device/gryphn_physical_output_device.h>
#include <Metal/Metal.h>
#include "metal_output_devices.h"
#include "core/window_surface/gryphn_surface.h"
gnPhysicalDevice* gnGetPhysicalDevicesFn(gnInstanceHandle instance, uint32_t* deviceCount) {
NSArray *devices = MTLCopyAllDevices();
*deviceCount = [devices count];
gnPhysicalDevice* devicesList = (gnPhysicalDevice*)malloc(sizeof(gnPhysicalDevice) * *deviceCount);
for (int i = 0; i < *deviceCount; i++) {
devicesList[i].physicalDevice = malloc(sizeof(gnPlatformPhysicalDevice));
devicesList[i].physicalDevice->device = [devices objectAtIndex:0];
id<MTLDevice> device = [devices objectAtIndex:0];
devicesList[i].properties.name = gnCreateString([[device name] cStringUsingEncoding:NSUTF8StringEncoding]);
MTLDeviceLocation deviceLocation = device.locationNumber;
if (deviceLocation == MTLDeviceLocationBuiltIn)
devicesList[i].properties.deviceType = GN_INTEGRATED_DEVICE;
else if (deviceLocation == MTLDeviceLocationSlot)
devicesList[i].properties.deviceType = GN_DEDICATED_DEVICE;
else if (deviceLocation == MTLDeviceLocationExternal)
devicesList[i].properties.deviceType = GN_EXTERNAL_DEVICE;
// below I am going to fake that there is one queue that can support graphics, compute, and transfer queues
devicesList[i].queueProperties.queueCount = 1;
devicesList[i].queueProperties.queueProperties = malloc(sizeof(gnQueueProperties));
devicesList[i].queueProperties.queueProperties[0] = (gnQueueProperties){
.queueCount = 1,
.queueType = GN_QUEUE_GRAPHICS | GN_QUEUE_COMPUTE | GN_QUEUE_TRANSFER
};
}
[devices release];
return devicesList;
}
gnBool gnQueueCanPresentToSurfaceFn(const struct gnPhysicalDevice_t device, uint32_t queueIndex, const struct gnWindowSurface_t windowSurface) {
return gnTrue; // I belive that a window should always be able to present to a surface in metal
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "core/framebuffer/gryphn_framebuffer.h"
#include "utils/gryphn_bool.h"
#include "utils/gryphn_image_format.h"
#import <Metal/Metal.h>
#import <Metal/MTLRenderPass.h>
typedef struct gnPlatformFramebuffer_t {
MTLRenderPassDescriptor* framebuffer;
} gnPlatformFramebuffer;
gnBool isDepthFormat(gnImageFormat format);
gnBool isStencilFormat(gnImageFormat format);

View File

@@ -0,0 +1,79 @@
#include "metal_framebuffer.h"
#include "core/debugger/gryphn_debugger.h"
#include "core/texture/metal_texture.h"
#include "core/renderpass/gryphn_render_pass_descriptor.h"
#include "core/instance/gryphn_instance.h"
gnBool isDepthFormat(gnImageFormat format) {
return gnFalse;
}
gnBool isStencilFormat(gnImageFormat format) {
return gnFalse;
}
MTLLoadAction mtlGryphnLoadOperation(enum gnLoadOperation_e loadOperation) {
switch(loadOperation) {
case GN_LOAD_OPERATION_LOAD: return MTLLoadActionLoad;
case GN_LOAD_OPERATION_CLEAR: return MTLLoadActionClear;
case GN_LOAD_OPERATION_DONT_CARE: return MTLLoadActionDontCare;
}
}
MTLStoreAction mtlGryphnStoreOperation(enum gnStoreOperation_e storeOperation) {
switch (storeOperation) {
case GN_STORE_OPERATION_STORE: return MTLStoreActionStore;
case GN_STORE_OPERATION_DONT_CARE: return MTLStoreActionDontCare;
}
}
gnReturnCode gnCreateFramebufferFn(struct gnFramebuffer_t* framebuffer, struct gnOutputDevice_t* device, struct gnFramebufferInfo_t info) {
framebuffer->framebuffer = malloc(sizeof(struct gnPlatformFramebuffer_t));
if (info.attachmentCount != info.renderPassDescriptor->info.attachmentCount) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString("Attachment count on framebuffer does not equal attachment count on render pass descriptor")
});
return GN_DIVERGENT_RENDERPASS;
}
framebuffer->framebuffer->framebuffer = [[MTLRenderPassDescriptor alloc] init];
[framebuffer->framebuffer->framebuffer setRenderTargetWidth:info.size.x];
[framebuffer->framebuffer->framebuffer setRenderTargetHeight:info.size.y];
int colorAttachment = 0;
for (int i = 0; i < info.renderPassDescriptor->info.attachmentCount; i++) {
gnBool wasDepthStencil = gnFalse;
if (isDepthFormat(info.renderPassDescriptor->info.attachmentInfos[i].format)) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString("Depth attachments are not currently supported in metal (get on this)")
});
wasDepthStencil = gnTrue;
}
if (isStencilFormat(info.renderPassDescriptor->info.attachmentInfos[i].format)) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString("Stencil attachments are not currently supported in metal (get on this)")
});
wasDepthStencil = gnTrue;
}
if(!wasDepthStencil) {
MTLRenderPassColorAttachmentDescriptor* color = framebuffer->framebuffer->framebuffer.colorAttachments[colorAttachment];
color.texture = info.attachments[i]->texture->texture;
color.loadAction = mtlGryphnLoadOperation(info.renderPassDescriptor->info.attachmentInfos[i].loadOperation);
color.storeAction = mtlGryphnStoreOperation(info.renderPassDescriptor->info.attachmentInfos[i].storeOperation);
if (color.loadAction == MTLLoadActionClear)
color.clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
colorAttachment++;
}
}
return GN_SUCCESS;
}
void gnDestroyFramebufferFn(struct gnFramebuffer_t* framebuffer) {
[framebuffer->framebuffer->framebuffer release];
free(framebuffer->framebuffer);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <Metal/MTLRenderPipeline.h>
#include <AppKit/AppKit.h>
typedef struct gnPlatformInstance_t {
NSView* metalContentView;
} gnPlatformInstance;

View File

@@ -0,0 +1,14 @@
#include <gryphn/gryphn.h>
#include <gryphn/gryphn_utils.h>
#include "metal_instance.h"
// #include "bridge/metal_bridge.h"
gnReturnCode gnCreateInstanceFn(gnInstanceHandle instance, gnInstanceInfo instanceInfo) {
if (instance->instance == NULL) instance->instance = malloc(sizeof(gnPlatformInstance));
return GN_SUCCESS;
}
void gnDestroyInstanceFn(gnInstanceHandle instance) {
free(instance->instance);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h"
#import <Metal/Metal.h>
typedef struct gnPlatformGraphicsPipeline_t {
id<MTLRenderPipelineState> graphicsPipeline;
} gnPlatformGraphicsPipeline;

View File

@@ -0,0 +1,103 @@
#include "metal_graphics_pipeline.h"
#include "core/devices/metal_output_devices.h"
#include "core/debugger/gryphn_debugger.h"
#include "core/shader_module/metal_shader_module.h"
#include "core/surface/metal_surface.h"
MTLBlendFactor vkGryphnBlendFactor(enum gnBlendFactor_e factor) {
switch (factor) {
case GN_BLEND_FACTOR_ZERO: return MTLBlendFactorZero;
case GN_BLEND_FACTOR_ONE: return MTLBlendFactorOne;
case GN_BLEND_FACTOR_SRC_ALPHA: return MTLBlendFactorSourceAlpha;
case GN_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return MTLBlendFactorOneMinusSourceAlpha;
}
}
MTLBlendOperation vkGryphnBlendOperation(enum gnBlendOperation_e operation) {
switch(operation) {
case GN_OPERATION_ADD: return MTLBlendOperationAdd;
}
}
MTLVertexFormat mtlGryphnVertexFormat(gnVertexFormat format) {
switch (format) {
case GN_FLOAT2: return MTLVertexFormatFloat2;
case GN_FLOAT3: return MTLVertexFormatFloat3;
}
}
gnReturnCode gnCreateGraphicsPipelineFn(struct gnGraphicsPipeline_t* graphicsPipeline, struct gnOutputDevice_t* device, struct gnGraphicsPipelineInfo_t info) {
graphicsPipeline->graphicsPipeline = malloc(sizeof(struct gnPlatformGraphicsPipeline_t));
MTLRenderPipelineDescriptor* descriptor = [[MTLRenderPipelineDescriptor alloc] init];
if (info.subpassIndex >= info.renderPassDescriptor->info.subpassCount) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString("Subpass index is larger then the subpass count in render pass descriptor")
});
return GN_UNKNOWN_SUBPASS;
}
struct gnSubpassInfo_t subpass = info.renderPassDescriptor->info.subpassInfos[info.subpassIndex];
for (uint32_t i = 0; i < subpass.colorAttachmentCount; i++) {
gnSubpassAttachmentInfo subpassAtt = subpass.colorAttachments[i];
gnRenderPassAttachmentInfo attInfo = info.renderPassDescriptor->info.attachmentInfos[subpassAtt.index];
descriptor.colorAttachments[i].pixelFormat = mtlGryphnFormatToVulkanFormat(attInfo.format);
if (info.colorBlending.enable == gnTrue) {
[descriptor.colorAttachments objectAtIndexedSubscript:i].blendingEnabled = YES;
[descriptor.colorAttachments objectAtIndexedSubscript:i].rgbBlendOperation = vkGryphnBlendOperation(info.colorBlending.colorBlendOperation);
[descriptor.colorAttachments objectAtIndexedSubscript:i].alphaBlendOperation = vkGryphnBlendOperation(info.colorBlending.alphaBlendOperation);
[descriptor.colorAttachments objectAtIndexedSubscript:i].sourceRGBBlendFactor = vkGryphnBlendFactor(info.colorBlending.sourceColorBlendFactor);
[descriptor.colorAttachments objectAtIndexedSubscript:i].sourceAlphaBlendFactor = vkGryphnBlendFactor(info.colorBlending.sourceAlphaBlendFactor);
[descriptor.colorAttachments objectAtIndexedSubscript:i].destinationRGBBlendFactor = vkGryphnBlendFactor(info.colorBlending.destinationColorBlendFactor);
[descriptor.colorAttachments objectAtIndexedSubscript:i].destinationAlphaBlendFactor = vkGryphnBlendFactor(info.colorBlending.destinationAlphaBlendFactor);
} else {
[descriptor.colorAttachments objectAtIndexedSubscript:i].blendingEnabled = FALSE;
}
}
for (int i = 0; i < info.shaderModuleCount; i++) {
if (info.shaderModules[i]->info.stage == GN_VERTEX_SHADER_MODULE) {
[descriptor setVertexFunction:info.shaderModules[i]->shaderModule->function];
} else if (info.shaderModules[i]->info.stage == GN_FRAGMENT_SHADER_MODULE) {
[descriptor setFragmentFunction:info.shaderModules[i]->shaderModule->function];
} else {
return GN_UNSUPPORTED_SHADER_MODULE;
}
}
MTLVertexDescriptor* vertexDescriptor = [[MTLVertexDescriptor alloc] init];
MTLVertexAttributeDescriptorArray* attributes = vertexDescriptor.attributes;
MTLVertexBufferLayoutDescriptorArray* buffers = vertexDescriptor.layouts;
int k = 0;
for (int i = 0; i < info.shaderInputLayout.bufferCount; i++) {
[[buffers objectAtIndexedSubscript:info.shaderInputLayout.bufferAttributes[i].binding] setStride:info.shaderInputLayout.bufferAttributes[i].size];
for (int j = 0; j < info.shaderInputLayout.bufferAttributes[i].attributeCount; j++) {
attributes[k].bufferIndex = i;
attributes[k].offset = info.shaderInputLayout.bufferAttributes[i].attributes[j].offset;
attributes[k].format = mtlGryphnVertexFormat(info.shaderInputLayout.bufferAttributes[i].attributes[j].format);
k++;
}
}
[descriptor setVertexDescriptor:vertexDescriptor];
NSError* error = nil;
graphicsPipeline->graphicsPipeline->graphicsPipeline = [device->outputDevice->device newRenderPipelineStateWithDescriptor:descriptor error:&error];
if (graphicsPipeline->graphicsPipeline->graphicsPipeline == nil) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCombineStrings(gnCreateString("Failed to create metal render pipeline descriptor "), error.localizedDescription.UTF8String)
});
return GN_FAILED_TO_CREATE_GRAPHICS_PIPELINE;
}
[descriptor release];
[vertexDescriptor release];
[error release];
return GN_SUCCESS;
}
void gnDestroyGraphicsPipelineFn(struct gnGraphicsPipeline_t *graphicsPipeline) {
[graphicsPipeline->graphicsPipeline->graphicsPipeline release];
free(graphicsPipeline->graphicsPipeline);
}

View File

@@ -0,0 +1,62 @@
#include "core/present/gryphn_present.h"
#include "core/instance/metal_instance.h"
#include "core/surface/metal_surface.h"
#include "core/devices/metal_output_devices.h"
#include "core/sync/semaphore/metal_semaphore.h"
#include "core/presentation_queue/metal_presentation_queue.h"
#include "core/debugger/gryphn_debugger.h"
#include "core/texture/metal_texture.h"
#import <QuartzCore/CAMetalLayer.h>
gnReturnCode gnPresentFn(gnOutputDeviceHandle device, struct gnPresentInfo_t info) {
for (int i = 0; i < info.waitCount; i++) {
while (!info.waitSemaphores[i]->semaphore->eventTriggered) {}
}
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;
}
id<MTLCommandBuffer> commandBuffer = [device->outputDevice->transferQueue commandBuffer];
MTLRenderPassDescriptor* passDesc = [MTLRenderPassDescriptor renderPassDescriptor];
passDesc.colorAttachments[0].texture = drawable.texture;
passDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
passDesc.colorAttachments[0].storeAction = MTLStoreActionStore;
passDesc.colorAttachments[0].clearColor = MTLClearColorMake(1.0f, 0, 0, 1.0f);
id<MTLRenderCommandEncoder> render = [commandBuffer renderCommandEncoderWithDescriptor:passDesc];
[render endEncoding];
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}];
[blit endEncoding];
[commandBuffer presentDrawable:drawable];
[commandBuffer commit];
device->outputDevice->executingCommandBuffer = commandBuffer;
}
[device->outputDevice->executingCommandBuffer waitUntilScheduled];
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;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#import <Metal/Metal.h>
#include "core/presentation_queue/gryphn_presentation_queue.h"
typedef struct gnPlatformPresentationQueue_t {
int textureCount;
id<MTLTexture>* textures;
uint32_t currentImage;
} gnPlatformPresentationQueue;

View File

@@ -0,0 +1,64 @@
#include "metal_presentation_queue.h"
#include "core/surface/metal_surface.h"
#include "core/devices/metal_output_devices.h"
#include "core/debugger/gryphn_debugger.h"
#include "core/texture/metal_texture.h"
#include "core/sync/semaphore/metal_semaphore.h"
gnReturnCode gnCreatePresentationQueueFn(gnPresentationQueueHandle presentationQueue, const gnOutputDeviceHandle device, struct gnPresentationQueueInfo_t presentationInfo) {
if (presentationInfo.minImageCount > 3) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString("On Metal you cannot have more than 3 images in a presentation queue")
});
return GN_UNSUPPORTED_IMAGE_COUNT;
}
if (presentationInfo.minImageCount < 2) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString("On Metal you cannot have less than 2 images in a presentation queue")
});
return GN_UNSUPPORTED_IMAGE_COUNT;
}
presentationQueue->presentationQueue = malloc(sizeof(struct gnPlatformPresentationQueue_t));
MTLPixelFormat convertedFormat = mtlGryphnFormatToVulkanFormat(presentationInfo.format.format);
CGColorSpaceRef convertedColorSpace = mtlGryphnColorSpaceToVulkanColorSpace(presentationInfo.format.colorSpace);
presentationQueue->presentationQueue->textureCount = presentationInfo.minImageCount;
presentationQueue->presentationQueue->textures = malloc(sizeof(id<MTLTexture>) * presentationInfo.minImageCount);
MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init];
textureDescriptor.pixelFormat = convertedFormat;
textureDescriptor.width = presentationInfo.imageSize.x;
textureDescriptor.height = presentationInfo.imageSize.y;
textureDescriptor.usage = MTLTextureUsageRenderTarget;
textureDescriptor.textureType = MTLTextureType2D;
presentationQueue->imageCount = presentationInfo.minImageCount;
presentationQueue->images = malloc(sizeof(gnTexture) * presentationInfo.minImageCount);
for (int i = 0; i < presentationInfo.minImageCount; i++) {
presentationQueue->presentationQueue->textures[i] = [device->outputDevice->device newTextureWithDescriptor:textureDescriptor];
presentationQueue->images[i] = malloc(sizeof(struct gnTexture_t));
presentationQueue->images[i]->texture = malloc(sizeof(gnPlatformTexture));
presentationQueue->images[i]->texture->texture = presentationQueue->presentationQueue->textures[i];
}
return GN_SUCCESS;
}
gnReturnCode gnPresentationQueueGetImageFn(gnPresentationQueueHandle presentationQueue, uint64_t timeout, struct gnSemaphore_t* semaphore, uint32_t* imageIndex) {
semaphore->semaphore->eventTriggered = gnFalse;
*imageIndex = presentationQueue->presentationQueue->currentImage;
presentationQueue->presentationQueue->currentImage++;
presentationQueue->presentationQueue->currentImage %= presentationQueue->imageCount;
semaphore->semaphore->eventTriggered = gnTrue;
return GN_SUCCESS;
}
void gnDestroyPresentationQueueFn(gnPresentationQueueHandle presentationQueue) {
for (int i = 0; i < presentationQueue->imageCount; i++) {
[presentationQueue->presentationQueue->textures[i] release];
}
free(presentationQueue->presentationQueue);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "core/renderpass/gryphn_render_pass_descriptor.h"
#import <Metal/MTLRenderPass.h>
typedef struct gnPlatformRenderPassDescriptor_t {
MTLRenderPassDescriptor* passDescriptor;
} gnPlatformRenderPassDescriptor;

View File

@@ -0,0 +1,13 @@
#include "metal_render_pass.h"
gnReturnCode gnCreateRenderPassDescriptorFn(struct gnRenderPassDescriptor_t* renderPass, struct gnOutputDevice_t* device, struct gnRenderPassDescriptorInfo_t info) {
renderPass->renderPassDescriptor = malloc(sizeof(gnPlatformRenderPassDescriptor));
renderPass->renderPassDescriptor->passDescriptor = [[MTLRenderPassDescriptor alloc] init];
return GN_SUCCESS;
}
void gnDestroyRenderPassDescriptorFn(struct gnRenderPassDescriptor_t* renderPass) {
[renderPass->renderPassDescriptor->passDescriptor release];
free(renderPass->renderPassDescriptor);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "core/shader_module/gryphn_shader_module.h"
#import <Metal/Metal.h>
typedef struct gnPlatformShaderModule_t {
id<MTLFunction> function;
} gnPlatformShaderModule;

View File

@@ -0,0 +1,101 @@
#include "metal_shader_module.h"
#include "spirv_cross_c.h"
#include "core/debugger/gryphn_debugger.h"
#include "core/devices/metal_output_devices.h"
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
void mtlSpirVErrorCallback(void *userdata, const char *error) {
struct gnDebugger_t* debugger = (struct gnDebugger_t*)userdata;
gnDebuggerSetErrorMessage(debugger, (gnMessageData){
.message = gnCreateString(error)
});
}
gnReturnCode gnCreateShaderModuleFn(struct gnShaderModule_t *module, struct gnOutputDevice_t *device, struct gnShaderModuleInfo_t shaderModuleInfo) {
module->shaderModule = malloc(sizeof(struct gnPlatformShaderModule_t));
spvc_context context = NULL;
spvc_parsed_ir ir = NULL;
spvc_compiler compiler = NULL;
const char *result = NULL;
spvc_resources resources = NULL;
const spvc_reflected_resource *list = NULL;
spvc_compiler_options options = NULL;
size_t count;
spvc_context_create(&context);
spvc_context_set_error_callback(context, mtlSpirVErrorCallback, module->device->instance->debugger);
spvc_context_parse_spirv(context, shaderModuleInfo.code, shaderModuleInfo.size / 4, &ir);
spvc_context_create_compiler(context, SPVC_BACKEND_MSL, ir, SPVC_CAPTURE_MODE_COPY, &compiler);
spvc_compiler_create_shader_resources(compiler, &resources);
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count);
for (int i = 0; i < count; i++){
uint32_t set = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationDescriptorSet),
binding = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationBinding);
if ((shaderModuleInfo.stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE)
binding += 1;
spvc_compiler_unset_decoration(compiler, list[i].id, SpvDecorationBinding);
spvc_compiler_set_decoration(compiler, list[i].id, SpvDecorationBinding, binding);
}
spvc_compiler_create_compiler_options(compiler, &options);
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_MSL_VERSION, 200);
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_MSL_ENABLE_DECORATION_BINDING, true);
spvc_compiler_install_compiler_options(compiler, options);
SpvExecutionModel executionModel = SpvExecutionModelVertex;
if (shaderModuleInfo.stage == GN_FRAGMENT_SHADER_MODULE) executionModel = SpvExecutionModelFragment;
spvc_compiler_set_entry_point(compiler, shaderModuleInfo.entryPoint.value, executionModel);
spvc_result res = spvc_compiler_compile(compiler, &result);
if (res != SPVC_SUCCESS)
return GN_FAILED_TO_CONVERT_SHADER_CODE;
NSError* error = nil;
MTLCompileOptions* mtloptions = nil;
NSString* sourceCode = [NSString stringWithCString:result encoding:NSUTF8StringEncoding];
id<MTLLibrary> shaderLib = [device->outputDevice->device newLibraryWithSource:sourceCode options:mtloptions error:&error];
if (!shaderLib) {
const char* errorString = error.localizedDescription.UTF8String;
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCombineStrings(gnCreateString("Failed to compile metal library "), errorString)
});
return GN_FAILED_TO_CREATE_SHADER_MODULE;
}
const char* name = shaderModuleInfo.entryPoint.value;
if (strcmp(name, "main") == 0) {
name = "main0";
}
gnBool foundFunction = false;
for (int i = 0; i < shaderLib.functionNames.count; i++) {
if (strcmp([shaderLib.functionNames objectAtIndex:0].UTF8String, name) == 0) {
foundFunction = true;
}
}
if (!foundFunction) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCombineStrings(gnCreateString("Failed to find specified entry point "), name)
});
return GN_FAILED_TO_FIND_ENTRY_POINT;
}
NSString* functionName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
module->shaderModule->function = [shaderLib newFunctionWithName:functionName];
[shaderLib release];
spvc_context_destroy(context);
return GN_SUCCESS;
}
void gnDestroyShaderModuleFn(struct gnShaderModule_t* module) {
free(module->shaderModule);
}

View File

@@ -0,0 +1,30 @@
#include "core/submit/gryphn_submit.h"
#include "core/sync/semaphore/metal_semaphore.h"
#include "core/commands/command_buffer/metal_command_buffer.h"
#include "core/debugger/gryphn_debugger.h"
#include "core/commands/command_pool/metal_command_pool.h"
gnReturnCode gnSubmitFn(struct gnOutputDevice_t* device, struct gnSubmitInfo_t info) {
for (int i = 0; i < info.waitCount; i++) {
while (!info.waitSemaphores[i]->semaphore->eventTriggered) {}
}
__block gnSemaphore* semsToSignal = info.signalSemaphores;
__block int semsToSignalCount = info.signalCount;
__block gnFence fenceToSignal = info.fence;
for (int i = 0; i < info.commandBufferCount; i++) {
id<MTLCommandBuffer> commandBuffer = info.commandBuffers[i]->commandBuffer->commandBuffer;
[info.commandBuffers[i]->commandBuffer->commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
for (int c = 0; c < semsToSignalCount; c++) {
semsToSignal[c]->semaphore->eventTriggered = gnTrue;
}
}];
fenceToSignal->signaled = gnTrue;
[commandBuffer commit];
}
return GN_SUCCESS;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "core/window_surface/gryphn_surface.h"
#import <QuartzCore/QuartzCore.h>
typedef struct gnPlatformWindowSurface_t {
CAMetalLayer* layer;
} gnPlatformWindowSurface;
MTLPixelFormat mtlGryphnFormatToVulkanFormat(gnImageFormat format);
CGColorSpaceRef mtlGryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace);

View File

@@ -0,0 +1,43 @@
#include "metal_surface.h"
#include "core/window_surface/gryphn_surface_create_functions.h"
#import <AppKit/AppKit.h>
#import <Cocoa/Cocoa.h>
#import <QuartzCore/CAMetalLayer.h>
#import <QuartzCore/QuartzCore.h>
#import <Metal/Metal.h>
#import <CoreGraphics/CoreGraphics.h>
gnReturnCode gnCreateMacOSWindowSurfaceFn(struct gnWindowSurface_t* windowSurface, gnInstanceHandle instance, struct gnMacOSWindowSurfaceInfo_t createInfo) {
windowSurface->windowSurface = malloc(sizeof(gnPlatformWindowSurface));
windowSurface->windowSurface->layer = createInfo.layer;
return GN_SUCCESS;
}
void gnDestroyWindowSurfaceFn(struct gnWindowSurface_t *windowSurface) {
free(windowSurface->windowSurface);
}
struct gnSurfaceDetails_t gnGetSurfaceDetailsFn(
struct gnWindowSurface_t* windowSurface, struct gnPhysicalDevice_t device
) {
struct gnSurfaceDetails_t surfaceDetails;
surfaceDetails.formatCount = 1;
surfaceDetails.formats = (struct gnSurfaceFormat_t[1]){ { GN_FORMAT_BGRA8_SRGB, GN_COLOR_SPACE_SRGB_NONLINEAR } };
surfaceDetails.minImageCount = 2;
surfaceDetails.maxImageCount = 3;
return surfaceDetails;
}
MTLPixelFormat mtlGryphnFormatToVulkanFormat(gnImageFormat format) {
switch (format) {
case GN_FORMAT_BGRA8_SRGB: { return MTLPixelFormatBGRA8Unorm_sRGB; }
default: return MTLPixelFormatInvalid;
}
}
CGColorSpaceRef mtlGryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace) {
switch (colorSpace) {
case GN_COLOR_SPACE_SRGB_NONLINEAR: { return CGColorSpaceCreateWithName(kCGColorSpaceSRGB); }
}
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "core/sync/fence/gryphn_fence.h"
#import <Metal/Metal.h>
#import <Metal/MTLEvent.h>
typedef struct gnPlatformFence_t {
} gnPlatformFence;

View File

@@ -0,0 +1,33 @@
#include "metal_fence.h"
#include "core/devices/metal_output_devices.h"
gnReturnCode gnCreateFenceFn(struct gnFence_t* fence, struct gnOutputDevice_t* device) {
// fence->fence = malloc(sizeof(gnPlatformFence));
// fence->fence->fence = [device->outputDevice->device newSharedEvent];
// fence->fence->listener = [[MTLSharedEventListener alloc] init];
// fence->fence->semaphore = dispatch_semaphore_create(1);
return GN_SUCCESS;
}
void gnSignalFenceFn(struct gnFence_t* fence) {
// dispatch_semaphore_signal(fence->fence->semaphore);
}
void gnWaitForFenceFn(struct gnFence_t* fence, uint64_t timeout) {
// dispatch_semaphore_wait(fence->fence->semaphore, timeout);
while (fence->signaled == gnFalse) {}
}
void gnResetFenceFn(struct gnFence_t* fence) {
// dispatch_semaphore_signal(fence->fence->semaphore);
// [fence->fence->fence setSignaledValue:0];
// [fence->fence->fence notifyListener:fence->fence->listener
// atValue:1
// block:^(id<MTLSharedEvent> ev, uint64_t val) {
// dispatch_semaphore_signal(fence->fence->semaphore);
// }];
}
void gnDestroyFenceFn(struct gnFence_t* fence) {
// [fence->fence->fence release];
// [fence->fence->listener release];
// free(fence->fence);
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "core/sync/semaphore/gryphn_semaphore.h"
#import <Metal/MTLEvent.h>
typedef struct gnPlatformSemaphore_t {
id<MTLEvent> event;
bool eventTriggered;
} gnPlatformSemaphore;

View File

@@ -0,0 +1,13 @@
#include "metal_semaphore.h"
#include "core/devices/metal_output_devices.h"
gnReturnCode gnCreateSemaphoreFn(struct gnSemaphore_t* semaphore, struct gnOutputDevice_t* device) {
semaphore->semaphore = malloc(sizeof(gnPlatformSemaphore));
semaphore->semaphore->event = [device->outputDevice->device newEvent];
return GN_SUCCESS;
}
void gnDestroySemaphoreFn(struct gnSemaphore_t* semaphore) {
[semaphore->semaphore->event release];
free(semaphore->semaphore);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "core/textures/gryphn_texture.h"
#import <Metal/MTLTexture.h>
typedef struct gnPlatformTexture_t {
id<MTLTexture> texture;
} gnPlatformTexture;

View File

@@ -0,0 +1,7 @@
#include <core/uniforms/gryphn_uniform.h>
#include "metal_uniform.h"
void gnUpdateBufferUniformFn(gnUniform uniform, gnBufferUniformInfo* info) {
uniform->uniform->data = malloc(sizeof(gnBufferUniformInfo));
memcpy(uniform->uniform->data, info, sizeof(gnBufferUniformInfo));
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "core/uniforms/gryphn_uniform.h"
#include <core/uniforms/gryphn_uniform_pool.h>
typedef struct gnPlatformUniform_t {
gnUniformType type;
void* data;
} gnPlatformUniform;

View File

@@ -0,0 +1,19 @@
#include <core/uniforms/gryphn_uniform_pool.h>
#include <core/uniforms/gryphn_uniform.h>
#include "metal_uniform.h"
gnReturnCode gnCreateUniformPoolFn(gnUniformPool pool, gnDeviceHandle device) {
return GN_SUCCESS;
}
gnUniform* gnUniformPoolAllocateUniformsFn(gnUniformPool pool, const gnUniformLayout layout) {
gnUniform* uniforms = malloc(sizeof(gnUniform) * layout.uniformBindingCount);
for (int i = 0; i < layout.uniformBindingCount; i++) {
uniforms[i] = malloc(sizeof(struct gnUniform_t));
uniforms[i]->uniform = malloc(sizeof(struct gnPlatformUniform_t));
uniforms[i]->uniform->type = layout.uniformBindings[i].type;
}
return uniforms;
}
void gnDestroyUniformPoolFn(gnUniformPool pool) { }

View File

@@ -0,0 +1,6 @@
#pragma once
#include <vulkan/vulkan.h>
#include <core/uniforms/gryphn_uniform_pool.h>
struct gnPlatformUniformPool_t {
};