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 {
};

View File

@@ -0,0 +1,43 @@
set(CMAKE_EXPORT_COMPILE_COMMANDS on)
set(CMAKE_CXX_STANDARD 17)
project(GryphnVulkanImpl)
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS
"src/*.c" "src/*.h"
)
if (APPLE)
file(GLOB_RECURSE METAL_FILES CONFIGURE_DEPENDS
"src/*.m"
)
endif()
find_package(Vulkan REQUIRED)
add_library(GryphnVulkanImpl STATIC ${SOURCE_FILES} ${METAL_FILES})
target_include_directories(GryphnVulkanImpl PUBLIC
${Vulkan_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../../../include/
${CMAKE_CURRENT_SOURCE_DIR}/../../
${CMAKE_CURRENT_SOURCE_DIR}/../../utils/
src/
)
add_compile_definitions(GN_REVEAL_IMPL)
target_link_libraries(GryphnVulkanImpl ${Vulkan_LIBRARY})
if(WIN32)
add_compile_definitions(GN_PLATFORM_WIN32)
endif()
if(APPLE)
target_link_libraries(GryphnVulkanImpl
"-framework IOKit"
"-framework CoreFoundation"
"-framework CoreGraphics"
"-framework AppKit"
"-framework Metal"
"-framework QuartzCore"
)
add_compile_definitions(GN_PLATFORM_MACOS)
endif()
if(UNIX AND NOT APPLE)
add_compile_definitions(GN_PLATFORM_LINUX)
endif()

View File

@@ -0,0 +1,132 @@
#include "vulkan_buffer.h"
#include "core/buffers/gryphn_buffer.h"
#include "core/output_device/gryphn_output_device.h"
#include "output_device/vulkan_output_devices.h"
#include "output_device/vulkan_physical_device.h"
#include "commands/command_buffer/vulkan_command_buffer.h"
VkBufferUsageFlags vkGryphnBufferType(gnBufferType type) {
VkBufferUsageFlags usageFlags = 0;
switch (type) {
case GN_VERTEX_BUFFER: usageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; break;
case GN_INDEX_BUFFER: usageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; break;
case GN_UNIFORM_BUFFER: usageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break;
}
return usageFlags;
}
uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory) {
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(device, &memoryProperties);
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
if ((memoryType & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & flags) == flags) {
*foundMemory = gnTrue;
return i;
}
} // this whole thing was adapted from vulkan-tutorial.com
return 0;
}
gnReturnCode VkCreateBuffer(
VkGryphnBuffer* buffer, size_t size, gnDevice device,
VkMemoryPropertyFlags flags, VkBufferUsageFlags usage
) {
VkBufferCreateInfo bufferInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = size,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
};
if (vkCreateBuffer(device->outputDevice->device, &bufferInfo, NULL, &buffer->buffer) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_BUFFER;
VkMemoryRequirements bufferRequirements;
vkGetBufferMemoryRequirements(device->outputDevice->device, buffer->buffer, &bufferRequirements);
gnBool foundMemory = gnFalse;
VkMemoryAllocateInfo memoryAllocateInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = bufferRequirements.size,
.memoryTypeIndex = VkMemoryIndex(device->physicalDevice.physicalDevice->device, bufferRequirements.memoryTypeBits, flags, &foundMemory)
};
if (!foundMemory) return GN_FAILED_TO_ALLOCATE_MEMORY;
if (vkAllocateMemory(device->outputDevice->device, &memoryAllocateInfo, NULL, &buffer->memory) != VK_SUCCESS)
return GN_FAILED_TO_ALLOCATE_MEMORY;
vkBindBufferMemory(device->outputDevice->device, buffer->buffer, buffer->memory, 0);
return GN_SUCCESS;
}
void VkCopyBuffer(VkBuffer source, VkBuffer destination, size_t size, VkCommandPool pool, VkDevice device, VkQueue queue) {
VkCommandBuffer transferBuffer = VkBeginTransferOperation(device, pool);
VkBufferCopy copyRegion = {
.size = size
};
vkCmdCopyBuffer(transferBuffer, source, destination, 1, &copyRegion);
VkEndTransferOperation(transferBuffer, pool, queue, device);
}
gnReturnCode gnCreateBufferFn(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info) {
buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t));
VkBufferUsageFlags usage = vkGryphnBufferType(info.type);
buffer->buffer->useStagingBuffer = gnFalse;
if (info.usage == GN_STATIC_DRAW) {
buffer->buffer->useStagingBuffer = gnTrue;
VkCreateBuffer(
&buffer->buffer->stagingBuffer,
info.size, device,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT
);
return VkCreateBuffer(
&buffer->buffer->buffer,
info.size, device,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
vkGryphnBufferType(info.type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT
);
} else {
return VkCreateBuffer(
&buffer->buffer->buffer,
info.size, device,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
vkGryphnBufferType(info.type)
);
}
return GN_SUCCESS;
}
void gnBufferDataFn(gnBufferHandle buffer, size_t dataSize, void* data) {
void* bufferData;
if (buffer->buffer->useStagingBuffer) {
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory, 0, dataSize, 0, &bufferData);
memcpy(bufferData, data, dataSize);
vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory);
VkCopyBuffer(
buffer->buffer->stagingBuffer.buffer, buffer->buffer->buffer.buffer, dataSize,
buffer->device->outputDevice->transferCommandPool, buffer->device->outputDevice->device,
buffer->device->outputDevice->transferQueue);
} else {
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, dataSize, 0, &bufferData);
memcpy(bufferData, data, dataSize);
vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory);
}
}
void* gnMapBufferFn(gnBufferHandle buffer) {
void* data;
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, buffer->info.size, 0, &data);
return data;
}
void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device) {
vkDestroyBuffer(device, buffer->buffer, NULL);
vkFreeMemory(device, buffer->memory, NULL);
}
void gnDestroyBufferFn(gnBufferHandle buffer) {
if (buffer->buffer->useStagingBuffer == gnTrue) gnDestroyVulkanBuffer(&buffer->buffer->stagingBuffer, buffer->device->outputDevice->device);
gnDestroyVulkanBuffer(&buffer->buffer->buffer, buffer->device->outputDevice->device);
free(buffer->buffer);
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include <vulkan/vulkan.h>
#include "utils/gryphn_bool.h"
#include <core/buffers/gryphn_buffer.h>
typedef struct VkGryphnBuffer {
VkBuffer buffer;
VkDeviceMemory memory;
} VkGryphnBuffer;
void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device);
struct gnPlatformBuffer_t {
VkGryphnBuffer buffer;
// for if static draw
VkGryphnBuffer stagingBuffer;
gnBool useStagingBuffer;
};
gnReturnCode VkCreateBuffer(
VkGryphnBuffer* buffer, size_t size, gnDevice device,
VkMemoryPropertyFlags flags, VkBufferUsageFlags usage
);
uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory);

View File

@@ -0,0 +1,80 @@
#include "vulkan_command_buffer.h"
#include "commands/command_pool/vulkan_command_pool.h"
#include "output_device/vulkan_output_devices.h"
gnReturnCode gnCommandPoolAllocateCommandBuffersFn(gnCommandBufferHandle* commandBuffers, uint32_t count, struct gnCommandPool_t* pool) {
VkCommandBufferAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = pool->commandPool->commandPool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = count,
};
VkCommandBuffer* buffers = malloc(sizeof(VkCommandBuffer) * count);
if (vkAllocateCommandBuffers(pool->device->outputDevice->device, &allocInfo, buffers) != VK_SUCCESS)
return GN_FAILED_TO_ALLOCATE_COMMAND_BUFFERS;
for (int i = 0; i < count; i++) {
commandBuffers[i]->commandBuffer = malloc(sizeof(gnPlatformCommandBuffer));
commandBuffers[i]->commandBuffer->buffer = buffers[i];
}
return GN_SUCCESS;
}
void gnResetCommandBufferFn(struct gnCommandBuffer_t* commandBuffer) {
vkResetCommandBuffer(commandBuffer->commandBuffer->buffer, 0);
}
gnReturnCode gnBeginCommandBufferFn(struct gnCommandBuffer_t* commandBuffer) {
VkCommandBufferBeginInfo beginInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
};
if (vkBeginCommandBuffer(commandBuffer->commandBuffer->buffer, &beginInfo) != VK_SUCCESS) {
return GN_FAILED_TO_BEGIN_RECORDING;
}
return GN_SUCCESS;
}
gnReturnCode gnEndCommandBufferFn(struct gnCommandBuffer_t* commandBuffer) {
if (vkEndCommandBuffer(commandBuffer->commandBuffer->buffer) != VK_SUCCESS)
return GN_FAIELD_TO_END_RECORDING;
return GN_SUCCESS;
}
VkCommandBuffer VkBeginTransferOperation(VkDevice device, VkCommandPool pool) {
VkCommandBufferAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandPool = pool,
.commandBufferCount = 1
};
VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
VkCommandBufferBeginInfo beginInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
};
vkBeginCommandBuffer(commandBuffer, &beginInfo);
return commandBuffer;
}
void VkEndTransferOperation(VkCommandBuffer transferBuffer, VkCommandPool pool, VkQueue syncQueue, VkDevice device) {
vkEndCommandBuffer(transferBuffer);
VkSubmitInfo submitInfo = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &transferBuffer
};
vkQueueSubmit(syncQueue, 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(syncQueue);
vkFreeCommandBuffers(device, pool, 1, &transferBuffer);
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "core/command/command_buffer/gryphn_command_buffer.h"
#include "utils/gryphn_bool.h"
#include <vulkan/vulkan.h>
typedef struct gnPlatformCommandBuffer_t {
VkCommandBuffer buffer;
gnBool changedBuffer;
gnBufferHandle boundIndexBuffer;
gnGraphicsPipeline boundGraphicsPipeline;
} gnPlatformCommandBuffer;
VkCommandBuffer VkBeginTransferOperation(VkDevice device, VkCommandPool pool);
void VkEndTransferOperation(VkCommandBuffer transferBuffer, VkCommandPool pool, VkQueue syncQueue, VkDevice device);

View File

@@ -0,0 +1,23 @@
#include "vulkan_command_pool.h"
#include "output_device/vulkan_output_devices.h"
gnReturnCode gnCreateCommandPoolFn(struct gnCommandPool_t* commandPool, struct gnOutputDevice_t* device, struct gnCommandPoolInfo_t info) {
commandPool->commandPool = malloc(sizeof(gnPlatformCommandPool));
VkCommandPoolCreateInfo poolInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = info.queueIndex,
};
if (vkCreateCommandPool(device->outputDevice->device, &poolInfo, NULL, &commandPool->commandPool->commandPool) != VK_SUCCESS) {
return GN_FAILED_TO_CREATE_COMMAND_POOL;
}
return GN_SUCCESS;
}
void gnDestroyCommandPoolFn(struct gnCommandPool_t* commandPool) {
vkDestroyCommandPool(commandPool->device->outputDevice->device, commandPool->commandPool->commandPool, NULL);
free(commandPool->commandPool);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <vulkan/vulkan.h>
#include "core/command/command_pool/gryphn_command_pool.h"
typedef struct gnPlatformCommandPool_t {
VkCommandPool commandPool;
} gnPlatformCommandPool;

View File

@@ -0,0 +1,97 @@
#include <vulkan/vulkan.h>
#include "core/command/commands/gryphn_command.h"
#include <renderpass/vulkan_render_pass_descriptor.h>
#include "framebuffers/vulkan_framebuffer.h"
#include "commands/command_buffer/vulkan_command_buffer.h"
#include "pipelines/graphics_pipeline/vulkan_graphics_pipeline.h"
#include "buffers/vulkan_buffer.h"
#include "uniforms/vulkan_uniform.h"
#include "shader_module/vulkan_shader_module.h"
void gnCommandBeginRenderPassFn(gnCommandBuffer buffer, struct gnRenderPassInfo_t passInfo) {
VkClearValue* values = malloc(sizeof(VkClearValue) * passInfo.clearValueCount);
for (int i = 0; i < passInfo.clearValueCount; i++) {
values[i] = (VkClearValue){{{
passInfo.clearValues[i].red,
passInfo.clearValues[i].green,
passInfo.clearValues[i].blue,
passInfo.clearValues[i].alpha
}}};
}
VkRenderPassBeginInfo renderPassInfo ={
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = passInfo.renderPassDescriptor->renderPassDescriptor->renderPass,
.framebuffer = passInfo.framebuffer->framebuffer->framebuffer,
.renderArea = {
.extent = { passInfo.size.x, passInfo.size.y },
.offset = { passInfo.offset.x, passInfo.offset.y }
},
.clearValueCount = passInfo.clearValueCount,
.pClearValues = values,
};
vkCmdBeginRenderPass(buffer->commandBuffer->buffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
}
void gnCommandEndRenderPassFn(gnCommandBuffer buffer) {
vkCmdEndRenderPass(buffer->commandBuffer->buffer);
}
void gnCommandBindGraphicsPipelineFn(gnCommandBuffer buffer, gnGraphicsPipeline graphicsPipeline) {
buffer->commandBuffer->boundGraphicsPipeline = graphicsPipeline;
vkCmdBindPipeline(buffer->commandBuffer->buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->graphicsPipeline->graphicsPipeline);
}
void gnCommandSetViewportFn(gnCommandBuffer buffer, gnViewport viewport) {
VkViewport vkViewport = {
.x = viewport.position.x,
.y = viewport.size.y,
.width = viewport.size.x,
.height = -viewport.size.y,
.minDepth = viewport.minDepth,
.maxDepth = viewport.maxDepth
};
vkCmdSetViewport(buffer->commandBuffer->buffer, 0, 1, &vkViewport);
}
void gnCommandSetScissorFn(gnCommandBuffer buffer, struct gnScissor_t scissor) {
VkRect2D vkScissor = {
.extent = { scissor.size.x, scissor.size.y },
.offset = { scissor.position.x, scissor.position.y }
};
vkCmdSetScissor(buffer->commandBuffer->buffer, 0, 1, &vkScissor);
}
VkDeviceSize offsets[] = {0};
void gnCommandBindBufferFn(gnCommandBufferHandle buffer, gnBufferHandle bufferToBind, gnBufferType type) {
if (type == GN_VERTEX_BUFFER)
vkCmdBindVertexBuffers(buffer->commandBuffer->buffer, 0, 1, &bufferToBind->buffer->buffer.buffer, offsets);
else if (type == GN_INDEX_BUFFER) {
buffer->commandBuffer->changedBuffer = gnTrue;
buffer->commandBuffer->boundIndexBuffer = bufferToBind;
}
}
void gnCommandDrawFn(gnCommandBuffer buffer, int vertexCount, int firstVertex, int instanceCount, int firstInstance) {
vkCmdDraw(buffer->commandBuffer->buffer, vertexCount, instanceCount, firstVertex, firstInstance);
}
void gnCommandDrawIndexedFn(gnCommandBufferHandle buffer, gnIndexType type, int indexCount, int firstIndex, int vertexOffset, int instanceCount, int firstInstance) {
if (buffer->commandBuffer->changedBuffer) vkCmdBindIndexBuffer(buffer->commandBuffer->buffer, buffer->commandBuffer->boundIndexBuffer->buffer->buffer.buffer, 0, (type == GN_UINT32) ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
vkCmdDrawIndexed(buffer->commandBuffer->buffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
buffer->commandBuffer->changedBuffer = gnFalse;
}
void gnCommandBindUniformFn(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t set) {
vkCmdBindDescriptorSets(
buffer->commandBuffer->buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->pipelineLayout, set, 1,
&uniform->uniform->set, 0, NULL
);
}
void gnCommandPushConstantFn(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data) {
vkCmdPushConstants(
buffer->commandBuffer->buffer,
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->pipelineLayout,
vkGryphnShaderModuleStage(layout.stage),
layout.offset,
layout.size,
data
);
}

View File

@@ -0,0 +1,158 @@
#include "vulkan_debugger.h"
#include <instance/vulkan_instance.h>
void vkPopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT* createInfo) {
createInfo->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo->messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo->messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
}
// gnBool vkCheckValidationLayerSupport(uint32_t count, const char** layers) {
// uint32_t layerCount;
// vkEnumerateInstanceLayerProperties(&layerCount, NULL);
// if (layerCount == 0) return gnFalse;
// VkLayerProperties* properties = malloc(sizeof(VkLayerProperties) * layerCount);
// vkEnumerateInstanceLayerProperties(&layerCount, properties);
// for (int i = 0; i < count; i++) {
// gnBool layerFound = gnFalse;
// for (int c = 0; c < layerCount; c++) {
// if (strcmp(layers[i], properties[c].layerName) == 0) {
// layerFound = gnTrue;
// break;
// }
// }
// if (layerFound == gnFalse)
// return gnFalse;
// }
// return gnTrue;
// }
// typedef struct vk_userData_t {
// gnDebuggerCallback debuggerCallback;
// void* userData;
// } vkUserData;
// static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debuggerDebugCallback(
// VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
// VkDebugUtilsMessageTypeFlagsEXT messageType,
// const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
// void* pUserData) {
// struct vk_userData_t userData = *(struct vk_userData_t*)pUserData;
// gnMessageSeverity severity;
// gnMessageType type;
// gnMessageData data = {
// .message = gnCreateString(pCallbackData->pMessage)
// };
// switch (messageSeverity) {
// default: break;
// case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: severity = GN_MESSAGE_VERBOSE; break;
// case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: severity = GN_MESSAGE_INFO; break;
// case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: severity = GN_MESSAGE_WARNING; break;
// case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: severity = GN_MESSAGE_ERROR; break;
// }
// switch (messageType) {
// default: break;
// case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: type = GN_DEBUG_MESSAGE_GENERAL; break;
// case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: type = GN_DEBUG_MESSAGE_VALIDATION; break;
// case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: type = GN_DEBUG_MESSAGE_PERFORMANCE; break;
// }
// gnDebuggerCallback callback = *userData.debuggerCallback;
// gnBool result = callback(severity, type, data, userData.userData);
// if (result == gnFalse) return VK_FALSE;
// return VK_TRUE;
// }
// VkResult vk_createDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) {
// PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
// if (vkCreateDebugUtilsMessengerEXT != NULL) {
// return vkCreateDebugUtilsMessengerEXT(instance, pCreateInfo, NULL, pDebugMessenger);
// }else
// return VK_ERROR_EXTENSION_NOT_PRESENT;
// return VK_SUCCESS;
// }
// void vk_destroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) {
// PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
// if (vkDestroyDebugUtilsMessengerEXT != NULL) {
// vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, pAllocator);
// }
// }
// gnReturnCode gnCreateDebuggerFn(gnDebuggerHandle debugger, gnInstanceHandle instance, const struct gnDebuggerInfo_t info) {
// debugger->debugger = malloc(sizeof(gnPlatformDebugger));
// if (instance->valid == gnFalse) {
// for (int i = 0; i < instance->instance->instanceMessageCount; i++) {
// info.callback(
// instance->instance->instanceMessages[i].severity,
// instance->instance->instanceMessages[i].type,
// instance->instance->instanceMessages[i].data,
// info.userData
// );
// }
// return GN_INVALID_INSTANCE;
// } else {
// for (int i = 0; i < instance->instance->instanceMessageCount; i++) {
// info.callback(
// instance->instance->instanceMessages[i].severity,
// instance->instance->instanceMessages[i].type,
// instance->instance->instanceMessages[i].data,
// info.userData
// );
// }
// }
// if (instance->instance->instanceMessageCount > 0) free(instance->instance->instanceMessages);
// instance->instance->instanceMessageCount = 0;
// const char* layers[] = {
// "VK_LAYER_KHRONOS_validation"
// };
// if (!checkValidationLayerSupport(1, layers))
// return GN_FAILED_TO_CREATE_DEBUGGER;
// struct vk_userData_t* userData = (struct vk_userData_t*)malloc(sizeof(struct vk_userData_t));
// userData->debuggerCallback = info.callback;
// userData->userData = info.userData;
// VkDebugUtilsMessengerCreateInfoEXT createInfo = {};
// createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
// createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
// createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
// createInfo.pUserData = (void*)userData;
// createInfo.pfnUserCallback = vk_debuggerDebugCallback;
// VkResult result = vk_createDebugUtilsMessengerEXT(instance->instance->vk_instance, &createInfo, NULL, &debugger->debugger->debugMessenger); if (result != VK_SUCCESS) {
// gnMessageSeverity severity = GN_MESSAGE_ERROR;
// gnMessageType type = GN_DEBUG_MESSAGE_VALIDATION;
// gnMessageData data = {
// .message = gnCombineStrings(
// gnCreateString("Failed to create gnDebuggerObject with api vulkan\n"),
// gnCombineStrings(gnCreateString("Returned with a vulkan error code of: (please do this)"), "")
// )
// };
// info.callback(
// severity,
// type,
// data,
// info.userData
// );
// return GN_FAILED_TO_CREATE_DEBUGGER;
// }
// return GN_SUCCESS;
// }
// void gnDestroyDebuggerFn(gnDebuggerHandle debugger) {
// vk_destroyDebugUtilsMessengerEXT(debugger->instance->instance->vk_instance, debugger->debugger->debugMessenger, NULL);
// }

View File

@@ -0,0 +1,9 @@
#pragma once
#include <vulkan/vulkan.h>
#include <core/debugger/gryphn_debugger.h>
typedef struct gnPlatformDebugger_t {
VkDebugUtilsMessengerEXT debugMessenger;
} gnPlatformDebugger;
void vkPopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT* createInfo);

View File

@@ -0,0 +1,34 @@
#include "vulkan_framebuffer.h"
#include "textures/vulkan_texture.h"
#include "renderpass/vulkan_render_pass_descriptor.h"
#include "output_device/vulkan_output_devices.h"
gnReturnCode gnCreateFramebufferFn(struct gnFramebuffer_t* framebuffer, struct gnOutputDevice_t* device, struct gnFramebufferInfo_t info) {
framebuffer->framebuffer = malloc(sizeof(struct gnPlatformFramebuffer_t));
VkImageView* attachments = malloc(sizeof(VkImageView) * info.attachmentCount);
for (int i = 0; i < info.attachmentCount; i++)
attachments[i] = info.attachments[i]->texture->image.imageView;
VkFramebufferCreateInfo framebufferInfo = {
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.renderPass = info.renderPassDescriptor->renderPassDescriptor->renderPass,
.attachmentCount = info.attachmentCount,
.pAttachments = attachments,
.width = info.size.x,
.height = info.size.y,
.layers = 1
};
if (vkCreateFramebuffer(device->outputDevice->device, &framebufferInfo, NULL, &framebuffer->framebuffer->framebuffer) != VK_SUCCESS) {
return GN_FAILED_TO_CREATE_FRAMEBUFFER;
}
free(attachments);
return GN_SUCCESS;
}
void gnDestroyFramebufferFn(struct gnFramebuffer_t* framebuffer) {
vkDestroyFramebuffer(framebuffer->device->outputDevice->device, framebuffer->framebuffer->framebuffer, NULL);
free(framebuffer->framebuffer);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "core/framebuffer/gryphn_framebuffer.h"
#include <vulkan/vulkan.h>
typedef struct gnPlatformFramebuffer_t {
VkFramebuffer framebuffer;
} gnPlatformFramebuffer;

View File

@@ -0,0 +1,136 @@
#include "vulkan_instance.h"
#include <debugger/vulkan_debugger.h>
#include <stdio.h>
typedef struct vkUserData {
gnDebuggerCallback debuggerCallback;
void* userData;
} vkUserData;
static VKAPI_ATTR VkBool32 VKAPI_CALL vk_debuggerDebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData) {
gnMessageSeverity severity;
gnMessageType type;
gnMessageData data = {
.message = gnCreateString(pCallbackData->pMessage)
};
switch (messageSeverity) {
default: break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: severity = GN_MESSAGE_VERBOSE; break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: severity = GN_MESSAGE_INFO; break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: severity = GN_MESSAGE_WARNING; break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: severity = GN_MESSAGE_ERROR; break;
}
switch (messageType) {
default: break;
case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT: type = GN_DEBUG_MESSAGE_GENERAL; break;
case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT: type = GN_DEBUG_MESSAGE_VALIDATION; break;
case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT: type = GN_DEBUG_MESSAGE_PERFORMANCE; break;
}
vkUserData* userData = (vkUserData*)pUserData;
gnDebuggerCallback callback = userData->debuggerCallback;
gnBool result = callback(severity, type, data, userData->userData);
if (result == gnFalse) return VK_FALSE;
return VK_TRUE;
}
gnReturnCode gnCreateInstanceFn(gnInstanceHandle instance, gnInstanceInfo instanceInfo) {
instance->instance = malloc(sizeof(gnPlatformInstance));
instance->instance->instanceMessageCount = 0;
#ifdef GN_PLATFORM_LINUX
gnBool isX11 = gnTrue;
uint32_t extensionCount = 3;
const char* extensions[3];
if (isX11) {
extensions[0] = "VK_KHR_xlib_surface";
extensions[1] = "VK_KHR_surface";
extensions[2] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
} else {
extensions[0] = "VK_KHR_wayland_surface";
extensions[1] = "VK_KHR_surface";
extensions[2] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
}
#endif
#ifdef GN_PLATFORM_WINDOWS
uint32_t extensionCount = 3;
const char* extensions[] = {
"VK_KHR_win32_surface",
"VK_KHR_surface",
VK_EXT_DEBUG_UTILS_EXTENSION_NAME
};
#endif
#ifdef GN_PLATFORM_MACOS
uint32_t extensionCount = 4;
const char* extensions[] = {
"VK_KHR_portability_enumeration",
"VK_EXT_metal_surface",
"VK_KHR_surface",
VK_EXT_DEBUG_UTILS_EXTENSION_NAME
};
#endif
VkApplicationInfo appInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = gnToCString(instanceInfo.applicationName),
.applicationVersion = instanceInfo.applicationVersion,
.pEngineName = gnToCString(instanceInfo.engineName),
.engineVersion = instanceInfo.engineVersion,
.apiVersion = VK_API_VERSION_1_3,
};
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
VkInstanceCreateFlags createFlags = 0;
#ifdef GN_PLATFORM_MACOS
createFlags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
#endif
createInfo.flags = createFlags;
if (instanceInfo.debugger != NULL) {
for (int i = 0; i < instanceInfo.debugger->info.layerCount; i++) {
if (instanceInfo.debugger->info.layers[i] == GN_DEBUGGER_LAYER_PLATFORM) {
const char* validation_layers[1] = { "VK_LAYER_KHRONOS_validation" };
createInfo.enabledLayerCount = 1;
createInfo.ppEnabledLayerNames = (const char*[]){ "VK_LAYER_KHRONOS_validation" };
vkUserData* userData = malloc(sizeof(vkUserData));
userData->debuggerCallback = instanceInfo.debugger->info.callback;
userData->userData = instanceInfo.debugger->info.userData;
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = {};
vkPopulateDebugMessengerCreateInfo(&debugCreateInfo);
debugCreateInfo.pfnUserCallback = vk_debuggerDebugCallback;
debugCreateInfo.pUserData = userData;
createInfo.pNext = &debugCreateInfo;
}
}
}
createInfo.enabledExtensionCount = extensionCount;
createInfo.ppEnabledExtensionNames = extensions;
VkResult result = vkCreateInstance(&createInfo, NULL, &instance->instance->vk_instance);
if (result != VK_SUCCESS)
return GN_FAILED_CREATE_INSTANCE;
instance->valid = gnTrue;
return GN_SUCCESS;
}
void gnDestroyInstanceFn(gnInstanceHandle instance) {
instance->valid = gnFalse;
vkDestroyInstance(instance->instance->vk_instance, NULL);
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include <vulkan/vulkan.h>
#include "core/debugger/gryphn_debugger.h"
#include "core/instance/gryphn_instance.h"
struct gnInstanceMessage {
gnMessageSeverity severity;
gnMessageType type;
gnMessageData data;
};
typedef struct gnPlatformInstance_t {
VkInstance vk_instance;
VkApplicationInfo appInfo;
uint16_t instanceMessageCount;
struct gnInstanceMessage* instanceMessages;
} gnPlatformInstance;

View File

@@ -0,0 +1,41 @@
#include "vulkan_device_extensions.h"
#include "utils/gryphn_bool.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
const char* *vkGetGryphnDeviceExtensions(uint32_t* outCount, VkPhysicalDevice device) {
uint32_t count = 1;
const char* *extensiosns = malloc(sizeof(const char*) * count);
extensiosns[count-1] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
#ifdef GN_PLATFORM_MACOS
count++;
extensiosns = realloc(extensiosns, sizeof(const char*) * count);
extensiosns[(count - 1)] = "VK_KHR_portability_subset";
#endif
uint32_t extensionCount = 0;
vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, NULL);
VkExtensionProperties* vkExtensions = malloc(sizeof(VkExtensionProperties) * extensionCount);
vkEnumerateDeviceExtensionProperties(device, NULL, &extensionCount, vkExtensions);
gnBool supportsDescriptorPoolOverallocation = gnFalse;
for (uint32_t i = 0; i < extensionCount; i++) {
if (strcmp(VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME, vkExtensions[i].extensionName) == 0) {
supportsDescriptorPoolOverallocation = gnTrue;
break;
}
}
free(vkExtensions);
if (supportsDescriptorPoolOverallocation) {
count++;
extensiosns = realloc(extensiosns, sizeof(const char*) * count);
extensiosns[(count - 1)] = VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME;
}
*outCount = count;
return extensiosns;
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include <vulkan/vulkan.h>
const char* *vkGetGryphnDeviceExtensions(uint32_t* count, VkPhysicalDevice device);

View File

@@ -0,0 +1,109 @@
#include <vulkan/vulkan.h>
#include <output_device/vulkan_physical_device.h>
#include <output_device/vulkan_output_devices.h>
#include "vulkan_device_extensions.h"
#include "core/instance/gryphn_instance.h"
#include "commands/command_buffer/vulkan_command_buffer.h"
gnReturnCode gnCreateOutputDeviceFn(gnOutputDeviceHandle outputDevice, gnInstanceHandle instance, gnOutputDeviceInfo deviceInfo) {
outputDevice->outputDevice = malloc(sizeof(gnPlatformOutputDevice));
VkDeviceQueueCreateInfo* queueCreateInfos = malloc(sizeof(VkDeviceQueueCreateInfo) * deviceInfo.queueInfoCount);
float queuePriority = 1.0f;
for (int i = 0; i < deviceInfo.queueInfoCount; i++) {
queueCreateInfos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfos[i].flags = 0;
queueCreateInfos[i].queueFamilyIndex = deviceInfo.queueInfos[i].queueIndex;
queueCreateInfos[i].queueCount = deviceInfo.queueInfos[i].queueCount;
queueCreateInfos[i].pQueuePriorities = &queuePriority;
}
VkPhysicalDeviceFeatures deviceFeatures = {
.samplerAnisotropy = VK_TRUE
};
VkDeviceCreateInfo deviceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = deviceInfo.queueInfoCount,
.pQueueCreateInfos = queueCreateInfos,
.pEnabledFeatures = &deviceFeatures
};
deviceCreateInfo.ppEnabledExtensionNames = vkGetGryphnDeviceExtensions(&deviceCreateInfo.enabledExtensionCount, deviceInfo.physicalDevice.physicalDevice->device);
outputDevice->outputDevice->enabledOversizedDescriptorPools = gnFalse;
for (int i = 0; i < deviceCreateInfo.enabledExtensionCount; i++)
if (strcmp(deviceCreateInfo.ppEnabledExtensionNames[i], VK_NV_DESCRIPTOR_POOL_OVERALLOCATION_EXTENSION_NAME) == 0) outputDevice->outputDevice->enabledOversizedDescriptorPools = gnTrue;
if (instance->debugger == NULL)
deviceCreateInfo.enabledLayerCount = 0;
else {
const char* validation_layers[1] = { "VK_LAYER_KHRONOS_validation" };
deviceCreateInfo.enabledLayerCount = 1;
deviceCreateInfo.ppEnabledLayerNames = validation_layers;
}
if (vkCreateDevice(deviceInfo.physicalDevice.physicalDevice->device, &deviceCreateInfo, NULL, &outputDevice->outputDevice->device) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_DEVICE;
outputDevice->outputDevice->queues = malloc(sizeof(VkQueue) * deviceInfo.queueInfoCount);
for (int i = 0; i < deviceInfo.queueInfoCount; i++) {
vkGetDeviceQueue(outputDevice->outputDevice->device, deviceInfo.queueInfos[i].queueIndex, 0, &outputDevice->outputDevice->queues[i]);
}
uint32_t queueCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(
deviceInfo.physicalDevice.physicalDevice->device,
&queueCount,
NULL
);
VkQueueFamilyProperties* queueFamilies = malloc(sizeof(VkQueueFamilyProperties) * queueCount);
vkGetPhysicalDeviceQueueFamilyProperties(
deviceInfo.physicalDevice.physicalDevice->device,
&queueCount,
queueFamilies
);
uint32_t transferQueueIndex = 0;
for (int i = 0; i < queueCount; i++) {
if ((queueFamilies[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT) {
transferQueueIndex = i;
vkGetDeviceQueue(outputDevice->outputDevice->device, deviceInfo.queueInfos[i].queueIndex, 0, &outputDevice->outputDevice->transferQueue);
break;
}
}
VkCommandPoolCreateInfo poolInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = transferQueueIndex
};
if (vkCreateCommandPool(outputDevice->outputDevice->device, &poolInfo, NULL, &outputDevice->outputDevice->transferCommandPool) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_COMMAND_POOL;
free(queueCreateInfos);
free(queueFamilies);
return GN_SUCCESS;
}
void gnWaitForDeviceFn(const gnOutputDeviceHandle device) {
vkDeviceWaitIdle(device->outputDevice->device);
}
void gnDestroyOutputDeviceFn(gnOutputDeviceHandle device) {
vkDestroyCommandPool(device->outputDevice->device, device->outputDevice->transferCommandPool, NULL);
vkDestroyDevice(device->outputDevice->device, NULL);
free(device->outputDevice);
}
VkCommandBuffer gnBeginVulkanTransferOperation(gnDevice device) {
return VkBeginTransferOperation(device->outputDevice->device, device->outputDevice->transferCommandPool);
}
void gnEndVulkanTransferOperation(gnDevice device, VkCommandBuffer buffer) {
VkEndTransferOperation(buffer, device->outputDevice->transferCommandPool, device->outputDevice->transferQueue, device->outputDevice->device);
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <vulkan/vulkan.h>
#include <core/output_device/gryphn_output_device.h>
typedef struct gnPlatformOutputDevice_t {
VkDevice device;
uint32_t queueCount;
VkQueue* queues;
VkQueue transferQueue;
VkCommandPool transferCommandPool;
gnBool enabledOversizedDescriptorPools;
} gnPlatformOutputDevice;
VkCommandBuffer gnBeginVulkanTransferOperation(gnDevice device);
void gnEndVulkanTransferOperation(gnDevice device, VkCommandBuffer commandBuffer);

View File

@@ -0,0 +1,58 @@
#include "vulkan_physical_device.h"
#include <instance/vulkan_instance.h>
#include <output_device/vulkan_device_extensions.h>
#include <vulkan_surface/vulkan_surface.h>
gnPhysicalDevice* gnGetPhysicalDevicesFn(gnInstanceHandle instance, uint32_t* deviceCount) {
vkEnumeratePhysicalDevices(instance->instance->vk_instance, deviceCount, NULL);
if (deviceCount == 0)
return NULL;
VkPhysicalDevice* physicalDevices = malloc(sizeof(VkPhysicalDevice) * *deviceCount);
vkEnumeratePhysicalDevices(instance->instance->vk_instance, deviceCount, physicalDevices);
gnPhysicalDevice* outputDevices = (gnPhysicalDevice*)malloc(sizeof(gnPhysicalDevice) * *deviceCount);
for (int i = 0; i < *deviceCount; i++) {
outputDevices[i].physicalDevice = malloc(sizeof(struct gnPlatformPhysicalDevice_t));
outputDevices[i].physicalDevice->device = physicalDevices[i];
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(physicalDevices[i], &deviceProperties);
outputDevices[i].properties.name = gnCreateString(deviceProperties.deviceName);
switch(deviceProperties.deviceType) {
case VK_PHYSICAL_DEVICE_TYPE_OTHER: outputDevices[i].properties.deviceType = GN_EXTERNAL_DEVICE;
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: outputDevices[i].properties.deviceType = GN_INTEGRATED_DEVICE;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: outputDevices[i].properties.deviceType = GN_DEDICATED_DEVICE;
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: outputDevices[i].properties.deviceType = GN_INTEGRATED_DEVICE;
case VK_PHYSICAL_DEVICE_TYPE_CPU: outputDevices[i].properties.deviceType = GN_INTEGRATED_DEVICE;
case VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM: outputDevices[i].properties.deviceType = GN_INTEGRATED_DEVICE;
}
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[i], &outputDevices[i].queueProperties.queueCount, NULL);
VkQueueFamilyProperties* queueFamilies = malloc(sizeof(VkQueueFamilyProperties) * outputDevices[i].queueProperties.queueCount);
outputDevices[i].queueProperties.queueProperties = malloc(sizeof(gnQueueProperties) * outputDevices[i].queueProperties.queueCount);
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevices[i], &outputDevices[i].queueProperties.queueCount, queueFamilies);
for (int c = 0; c < outputDevices[i].queueProperties.queueCount; c++) {
outputDevices[i].queueProperties.queueProperties[i].queueCount = queueFamilies[i].queueCount;
gnQueueTypeFlags finalQueueType = 0;
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) finalQueueType |= GN_QUEUE_GRAPHICS;
if (queueFamilies[i].queueFlags & VK_QUEUE_COMPUTE_BIT) finalQueueType |= GN_QUEUE_COMPUTE;
if (queueFamilies[i].queueFlags & VK_QUEUE_TRANSFER_BIT) finalQueueType |= GN_QUEUE_TRANSFER;
if (queueFamilies[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) finalQueueType |= GN_QUEUE_SPARSE_BINDING;
outputDevices[i].queueProperties.queueProperties[i].queueType = finalQueueType;
}
}
free(physicalDevices);
return outputDevices;
}
gnBool gnQueueCanPresentToSurfaceFn(const struct gnPhysicalDevice_t device, uint32_t queueIndex, gnWindowSurfaceHandle windowSurface) {
VkBool32 supportsPresent = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(device.physicalDevice->device, queueIndex, windowSurface->windowSurface->surface, &supportsPresent);
if (supportsPresent)
return gnTrue;
return gnFalse;
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <vulkan/vulkan.h>
#include <core/output_device/gryphn_physical_output_device.h>
typedef struct gnPlatformPhysicalDevice_t {
VkPhysicalDevice device;
} gnPlatformPhysicalDevice;

View File

@@ -0,0 +1,306 @@
#include "vulkan_graphics_pipeline.h"
#include "output_device/vulkan_output_devices.h"
#include "shader_module/vulkan_shader_module.h"
#include "renderpass/vulkan_render_pass_descriptor.h"
#include "uniforms/vulkan_uniform_layout.h"
#include "stdio.h"
VkDynamicState vkGryphnDynamicStateToVulkanDynamicState(enum gnDynamicState_e state) {
switch (state) {
case GN_DYNAMIC_VIEWPORT: return VK_DYNAMIC_STATE_VIEWPORT;
case GN_DYNAMIC_SCISSOR: return VK_DYNAMIC_STATE_SCISSOR;
case GN_DYNAMIC_STATE_MAX: return VK_DYNAMIC_STATE_MAX_ENUM;
}
}
VkPrimitiveTopology vkGryphnPrimitiveType(gnPrimitiveType primitiveType) {
switch (primitiveType) {
case GN_PRIMITIVE_POINTS: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
case GN_PRIMITIVE_LINES: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
case GN_PRIMITIVE_LINE_STRIP: return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case GN_PRIMITIVE_TRIANGLES: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
case GN_PRIMITIVE_TRIANGLE_STRIP: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
}
}
VkPolygonMode vkGryphnPolygonMode(enum gnFillMode_e fillMode) {
switch (fillMode) {
case GN_FILL_MODE_FILL: return VK_POLYGON_MODE_FILL;
case GN_FILL_MODE_LINE: return VK_POLYGON_MODE_LINE;
case GN_FILL_MODE_POINT: return VK_POLYGON_MODE_POINT;
}
}
VkCullModeFlags vkGryphnCullMode(enum gnCullFace_e face) {
switch (face) {
case GN_CULL_FACE_NONE: return VK_CULL_MODE_NONE;
case GN_CULL_FACE_BACK: return VK_CULL_MODE_BACK_BIT;
case GN_CULL_FACE_FRONT: return VK_CULL_MODE_FRONT_BIT;
}
}
VkBlendFactor vkGryphnBlendFactor(enum gnBlendFactor_e factor) {
switch (factor) {
case GN_BLEND_FACTOR_ZERO: return VK_BLEND_FACTOR_ZERO;
case GN_BLEND_FACTOR_ONE: return VK_BLEND_FACTOR_ONE;
case GN_BLEND_FACTOR_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA;
case GN_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
}
}
VkBlendOp vkGryphnBlendOperation(enum gnBlendOperation_e operation) {
switch(operation) {
case GN_OPERATION_ADD: return VK_BLEND_OP_ADD;
}
}
VkFormat vkGryphnVertexFormat(gnVertexFormat format) {
switch (format) {
case GN_FLOAT2: return VK_FORMAT_R32G32_SFLOAT;
case GN_FLOAT3: return VK_FORMAT_R32G32B32_SFLOAT;
}
}
VkCompareOp vkGrypnCompareOperation(gnCompareOperation operation) {
switch(operation) {
case GN_COMPARE_NEVER: return VK_COMPARE_OP_NEVER;
case GN_COMPARE_LESS: return VK_COMPARE_OP_LESS;
case GN_COMPARE_EQUAL: return VK_COMPARE_OP_EQUAL;
case GN_COMPARE_LESS_OR_EQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;
case GN_COMPARE_GREATER: return VK_COMPARE_OP_GREATER;
case GN_COMPARE_NOT_EQUAL: return VK_COMPARE_OP_NOT_EQUAL;
case GN_COMPARE_GREATER_OR_EQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
case GN_COMPARE_ALWAYS: return VK_COMPARE_OP_ALWAYS;
}
}
VkStencilOp vkGryphnStencilOperation(gnStencilOperation operation) {
switch(operation) {
case GN_STENCIL_KEEP: return VK_STENCIL_OP_KEEP;
case GN_STENCIL_ZERO: return VK_STENCIL_OP_ZERO;
case GN_STENCIL_REPLACE: return VK_STENCIL_OP_REPLACE;
case GN_STENCIL_INCREMENT_AND_CLAMP: return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
case GN_STENCIL_DECREMENT_AND_CLAMP: return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
case GN_STENCIL_INVERT: return VK_STENCIL_OP_INVERT;
case GN_STENCIL_INCREMENT_AND_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP;
case GN_STENCIL_DECREMENT_AND_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP;
}
}
gnReturnCode gnCreateGraphicsPipelineFn(gnGraphicsPipeline graphicsPipeline, gnDevice device, gnGraphicsPipelineInfo info) {
graphicsPipeline->graphicsPipeline = malloc(sizeof(gnPlatformGraphicsPipeline));
for (int i = 0; i < GN_DYNAMIC_STATE_MAX; i++) graphicsPipeline->graphicsPipeline->isDynamic[i] = gnFalse;
graphicsPipeline->graphicsPipeline->dynamicStates = malloc(sizeof(VkDynamicState) * info.dynamicState.dynamicStateCount);
for (int i = 0; i < info.dynamicState.dynamicStateCount; i++) {
graphicsPipeline->graphicsPipeline->isDynamic[info.dynamicState.dynamicStates[i]] = gnTrue;
graphicsPipeline->graphicsPipeline->dynamicStates[i] = vkGryphnDynamicStateToVulkanDynamicState(info.dynamicState.dynamicStates[i]);
}
graphicsPipeline->graphicsPipeline->dynamicState = (VkPipelineDynamicStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = info.dynamicState.dynamicStateCount,
.pDynamicStates = graphicsPipeline->graphicsPipeline->dynamicStates
};
int vertexAttributeCount = 0;
graphicsPipeline->graphicsPipeline->bindingDescriptions = malloc(sizeof(VkVertexInputBindingDescription) * info.shaderInputLayout.bufferCount);
for (int i = 0; i < info.shaderInputLayout.bufferCount; i++) {
graphicsPipeline->graphicsPipeline->bindingDescriptions[i].binding = info.shaderInputLayout.bufferAttributes[i].binding;
graphicsPipeline->graphicsPipeline->bindingDescriptions[i].stride = info.shaderInputLayout.bufferAttributes[i].size;
graphicsPipeline->graphicsPipeline->bindingDescriptions[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
vertexAttributeCount += info.shaderInputLayout.bufferAttributes[i].attributeCount;
}
graphicsPipeline->graphicsPipeline->attributeDescriptions = malloc(sizeof(VkVertexInputAttributeDescription) * vertexAttributeCount);
for (int i = 0, j = 0; j < info.shaderInputLayout.bufferCount; j++) {
for (int k = 0; k < info.shaderInputLayout.bufferAttributes[j].attributeCount; k++) {
graphicsPipeline->graphicsPipeline->attributeDescriptions[i].binding = j;
graphicsPipeline->graphicsPipeline->attributeDescriptions[i].location = info.shaderInputLayout.bufferAttributes[j].attributes[k].location;
graphicsPipeline->graphicsPipeline->attributeDescriptions[i].offset = info.shaderInputLayout.bufferAttributes[j].attributes[k].offset;
graphicsPipeline->graphicsPipeline->attributeDescriptions[i].format = vkGryphnVertexFormat(info.shaderInputLayout.bufferAttributes[j].attributes[k].format);
i++;
}
}
graphicsPipeline->graphicsPipeline->vertexInfo = (VkPipelineVertexInputStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = info.shaderInputLayout.bufferCount,
.pVertexBindingDescriptions = graphicsPipeline->graphicsPipeline->bindingDescriptions,
.vertexAttributeDescriptionCount = vertexAttributeCount,
.pVertexAttributeDescriptions = graphicsPipeline->graphicsPipeline->attributeDescriptions
};
graphicsPipeline->graphicsPipeline->inputAssembly = (VkPipelineInputAssemblyStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = vkGryphnPrimitiveType(info.primitiveType),
.primitiveRestartEnable = VK_FALSE
};
graphicsPipeline->graphicsPipeline->viewportState = (VkPipelineViewportStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.viewportCount = 1,
.scissorCount = 1
};
if (!graphicsPipeline->graphicsPipeline->isDynamic[GN_DYNAMIC_VIEWPORT]) {
graphicsPipeline->graphicsPipeline->viewport = (VkViewport) {
.x = info.viewport.position.x,
.y = info.viewport.position.y,
.width = info.viewport.size.x,
.height = info.viewport.size.y,
.minDepth = info.viewport.minDepth,
.maxDepth = info.viewport.maxDepth
};
graphicsPipeline->graphicsPipeline->viewportState.pViewports = &graphicsPipeline->graphicsPipeline->viewport;
}
if (!graphicsPipeline->graphicsPipeline->isDynamic[GN_DYNAMIC_SCISSOR]) {
graphicsPipeline->graphicsPipeline->scissor = (VkRect2D){
.offset = { info.scissor.position.x, info.scissor.position.y },
.extent = { info.scissor.size.x, info.scissor.size.y }
};
graphicsPipeline->graphicsPipeline->viewportState.pScissors = &graphicsPipeline->graphicsPipeline->scissor;
}
graphicsPipeline->graphicsPipeline->rasterizer = (VkPipelineRasterizationStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.polygonMode = vkGryphnPolygonMode(info.fillMode),
.lineWidth = 1.0f,
.frontFace = ( info.cullMode.direction == GN_DIRECTION_CLOCK_WISE ) ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE,
.cullMode = vkGryphnCullMode(info.cullMode.face),
.depthBiasEnable = VK_FALSE,
.depthBiasConstantFactor = 0.0f,
.depthBiasClamp = 0.0f,
.depthBiasSlopeFactor = 0.0f
};
VkPipelineMultisampleStateCreateInfo multisampling = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.sampleShadingEnable = VK_FALSE,
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
};
graphicsPipeline->graphicsPipeline->colorBlendAttachment = (VkPipelineColorBlendAttachmentState){
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
.blendEnable = ( info.colorBlending.enable == gnTrue ) ? VK_TRUE : VK_FALSE,
.srcColorBlendFactor = vkGryphnBlendFactor(info.colorBlending.sourceColorBlendFactor),
.dstColorBlendFactor = vkGryphnBlendFactor(info.colorBlending.destinationColorBlendFactor),
.colorBlendOp = vkGryphnBlendOperation(info.colorBlending.colorBlendOperation),
.srcAlphaBlendFactor = vkGryphnBlendFactor(info.colorBlending.sourceAlphaBlendFactor),
.dstAlphaBlendFactor = vkGryphnBlendFactor(info.colorBlending.destinationAlphaBlendFactor),
.alphaBlendOp = vkGryphnBlendOperation(info.colorBlending.alphaBlendOperation),
};
graphicsPipeline->graphicsPipeline->colorBlending = (VkPipelineColorBlendStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_COPY,
.attachmentCount = 1,
.pAttachments = &graphicsPipeline->graphicsPipeline->colorBlendAttachment,
.blendConstants[0] = 0.0f,
.blendConstants[1] = 0.0f,
.blendConstants[2] = 0.0f,
.blendConstants[3] = 0.0f
};
graphicsPipeline->graphicsPipeline->depthStencil = (VkPipelineDepthStencilStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthWriteEnable = info.depthStencil.depthWriteEnable,
.depthTestEnable = info.depthStencil.depthWriteEnable,
.depthCompareOp = vkGrypnCompareOperation(info.depthStencil.operation),
.depthBoundsTestEnable = VK_FALSE,
.stencilTestEnable = info.depthStencil.stencilTestEnable,
};
if (info.depthStencil.stencilTestEnable) {
graphicsPipeline->graphicsPipeline->depthStencil.front = (VkStencilOpState){
.failOp = vkGryphnStencilOperation(info.depthStencil.front.failOperation),
.passOp = vkGryphnStencilOperation(info.depthStencil.front.passOperation),
.depthFailOp = vkGryphnStencilOperation(info.depthStencil.front.depthFailOperation),
.compareOp = vkGrypnCompareOperation(info.depthStencil.front.compareOperation),
.compareMask = info.depthStencil.front.compareMask,
.writeMask = info.depthStencil.front.writeMask,
.reference = info.depthStencil.front.reference,
};
graphicsPipeline->graphicsPipeline->depthStencil.back = (VkStencilOpState){
.failOp = vkGryphnStencilOperation(info.depthStencil.back.failOperation),
.passOp = vkGryphnStencilOperation(info.depthStencil.back.passOperation),
.depthFailOp = vkGryphnStencilOperation(info.depthStencil.back.depthFailOperation),
.compareOp = vkGrypnCompareOperation(info.depthStencil.back.compareOperation),
.compareMask = info.depthStencil.back.compareMask,
.writeMask = info.depthStencil.back.writeMask,
.reference = info.depthStencil.back.reference,
};
}
graphicsPipeline->graphicsPipeline->setCount = info.uniformLayout.setCount;
graphicsPipeline->graphicsPipeline->sets = malloc(sizeof(VkDescriptorSetLayout) * info.uniformLayout.setCount);
for (int i = 0; i < info.uniformLayout.setCount; i++) graphicsPipeline->graphicsPipeline->sets[i] = vkGryphnCreateSetLayouts(&info.uniformLayout.sets[i], device->outputDevice->device);
graphicsPipeline->graphicsPipeline->ranges = malloc(sizeof(VkPushConstantRange) * info.uniformLayout.pushConstantCount);
for (int i = 0; i < info.uniformLayout.pushConstantCount; i++) {
graphicsPipeline->graphicsPipeline->ranges[i] = (VkPushConstantRange) {
.offset = info.uniformLayout.pushConstants[i].offset,
.size = info.uniformLayout.pushConstants[i].size,
.stageFlags = vkGryphnShaderModuleStage(info.uniformLayout.pushConstants[i].stage)
};
}
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = graphicsPipeline->graphicsPipeline->setCount,
pipelineLayoutInfo.pSetLayouts = graphicsPipeline->graphicsPipeline->sets,
pipelineLayoutInfo.pushConstantRangeCount = info.uniformLayout.pushConstantCount,
pipelineLayoutInfo.pPushConstantRanges = graphicsPipeline->graphicsPipeline->ranges
};
if (vkCreatePipelineLayout(device->outputDevice->device, &pipelineLayoutInfo, NULL, &graphicsPipeline->graphicsPipeline->pipelineLayout) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_UNIFORM_LAYOUT;
graphicsPipeline->graphicsPipeline->modules = malloc(sizeof(VkPipelineShaderStageCreateInfo) * info.shaderModuleCount);
for (int i = 0; i < info.shaderModuleCount; i++) {
graphicsPipeline->graphicsPipeline->modules[i] = info.shaderModules[i]->shaderModule->shaderStageInfo;
}
VkGraphicsPipelineCreateInfo pipelineInfo = {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.stageCount = info.shaderModuleCount,
.pStages = graphicsPipeline->graphicsPipeline->modules,
.pVertexInputState = &graphicsPipeline->graphicsPipeline->vertexInfo,
.pInputAssemblyState = &graphicsPipeline->graphicsPipeline->inputAssembly,
.pViewportState = &graphicsPipeline->graphicsPipeline->viewportState,
.pRasterizationState = &graphicsPipeline->graphicsPipeline->rasterizer,
.pMultisampleState = &multisampling,
.pDepthStencilState = &graphicsPipeline->graphicsPipeline->depthStencil,
.pColorBlendState = &graphicsPipeline->graphicsPipeline->colorBlending,
.pDynamicState = &graphicsPipeline->graphicsPipeline->dynamicState,
.layout = graphicsPipeline->graphicsPipeline->pipelineLayout,
.renderPass = info.renderPassDescriptor->renderPassDescriptor->renderPass,
.subpass = info.subpassIndex,
.basePipelineHandle = VK_NULL_HANDLE,
.basePipelineIndex = -1,
};
if (vkCreateGraphicsPipelines(device->outputDevice->device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &graphicsPipeline->graphicsPipeline->graphicsPipeline) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_GRAPHICS_PIPELINE;
return GN_SUCCESS;
}
void gnDestroyGraphicsPipelineFn(struct gnGraphicsPipeline_t *graphicsPipeline) {
free(graphicsPipeline->graphicsPipeline->dynamicStates);
free(graphicsPipeline->graphicsPipeline->bindingDescriptions);
free(graphicsPipeline->graphicsPipeline->attributeDescriptions);
free(graphicsPipeline->graphicsPipeline->ranges);
for (int i = 0; i < graphicsPipeline->graphicsPipeline->setCount; i++)
vkDestroyDescriptorSetLayout(graphicsPipeline->device->outputDevice->device, graphicsPipeline->graphicsPipeline->sets[i], NULL);
free(graphicsPipeline->graphicsPipeline->modules);
vkDestroyPipeline(graphicsPipeline->device->outputDevice->device, graphicsPipeline->graphicsPipeline->graphicsPipeline, NULL);
vkDestroyPipelineLayout(graphicsPipeline->device->outputDevice->device, graphicsPipeline->graphicsPipeline->pipelineLayout, NULL);
free(graphicsPipeline->graphicsPipeline);
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include <core/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h>
#include <vulkan/vulkan.h>
typedef struct gnPlatformGraphicsPipeline_t {
VkPipelineDynamicStateCreateInfo dynamicState;
gnBool isDynamic[GN_DYNAMIC_STATE_MAX];
VkPipelineVertexInputStateCreateInfo vertexInfo;
VkPipelineInputAssemblyStateCreateInfo inputAssembly;
VkViewport viewport;
VkRect2D scissor;
VkPipelineViewportStateCreateInfo viewportState;
VkPipelineRasterizationStateCreateInfo rasterizer;
VkPipelineColorBlendAttachmentState colorBlendAttachment;
VkPipelineColorBlendStateCreateInfo colorBlending;
VkPipelineDepthStencilStateCreateInfo depthStencil;
// gnBool createdPipelineLayout;
uint32_t setCount;
VkDescriptorSetLayout* sets;
VkPipelineLayout pipelineLayout;
VkPipeline graphicsPipeline;
// memory that needs to be freeed
VkDynamicState* dynamicStates;
VkVertexInputBindingDescription* bindingDescriptions;
VkVertexInputAttributeDescription* attributeDescriptions;
VkPipelineShaderStageCreateInfo* modules;
VkPushConstantRange* ranges;
} gnPlatformGraphicsPipeline;

View File

@@ -0,0 +1,29 @@
#include "core/present/gryphn_present.h"
#include "sync/semaphore/vulkan_semaphore.h"
#include "presentation_queue/vulkan_presentation_queue.h"
#include "output_device/vulkan_output_devices.h"
gnReturnCode gnPresentFn(struct gnOutputDevice_t* device, struct gnPresentInfo_t info) {
VkSemaphore* waitSemaphores = malloc(sizeof(VkSemaphore) * info.waitCount);
for (int i = 0; i < info.waitCount; i++) waitSemaphores[i] = info.waitSemaphores[i]->semaphore->semaphore;
VkSwapchainKHR* swapchains = malloc(sizeof(VkSwapchainKHR) * info.presentationQueueCount);
for (int i = 0; i < info.presentationQueueCount; i++) swapchains[i] = info.presentationQueues[i]->presentationQueue->swapChain;
VkPresentInfoKHR presentInfo = {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.waitSemaphoreCount = info.waitCount,
.pWaitSemaphores = waitSemaphores,
.swapchainCount = info.presentationQueueCount,
.pSwapchains = swapchains,
.pImageIndices = info.imageIndices
};
VkQueue queue;
vkGetDeviceQueue(device->outputDevice->device, info.queueIndex, 0, &queue);
VkResult result = vkQueuePresentKHR(queue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR) return GN_OUT_OF_DATE_PRESENTATION_QUEUE;
if (result == VK_SUBOPTIMAL_KHR) return GN_SUBOPTIMAL_PRESENTATION_QUEUE;
return GN_SUCCESS;
}

View File

@@ -0,0 +1,145 @@
#include <presentation_queue/vulkan_presentation_queue.h>
#include "vulkan_swapchain_support.h"
#include <output_device/vulkan_physical_device.h>
#include "vulkan_surface/vulkan_surface.h"
#include "core/debugger/gryphn_debugger.h"
#include "textures/vulkan_texture.h"
#include "sync/semaphore/vulkan_semaphore.h"
#include "stdio.h"
gnReturnCode gnCreatePresentationQueueFn(gnPresentationQueueHandle presentationQueue, const gnOutputDeviceHandle device, struct gnPresentationQueueInfo_t presentationInfo) {
presentationQueue->presentationQueue = malloc(sizeof(struct gnPlatformPresentationQueue_t));
vkSwapchainSupportDetails details = vkGetSwapchainSupport(device->physicalDevice.physicalDevice->device, presentationInfo.surface->windowSurface->surface);
if (details.capabilities.currentExtent.width != presentationInfo.imageSize.x || details.capabilities.currentExtent.height != presentationInfo.imageSize.y) {
gnDebuggerSetErrorMessage(device->instance->debugger,
(gnMessageData){
.message = gnCreateString("Image size is unsupposed for presentation queue")
}
);
presentationInfo.imageSize = (gnUInt2){ details.capabilities.currentExtent.width, details.capabilities.currentExtent.height };
}
if (details.formatCount == 0) {
gnDebuggerSetErrorMessage(device->instance->debugger,
(gnMessageData){
.message = gnCreateString("Format count for presentation queue is zero")
}
);
return GN_NO_SUPPORTED_FORMATS;
}
if (details.presentModeCount == 0) {
gnDebuggerSetErrorMessage(device->instance->debugger,
(gnMessageData){
.message = gnCreateString("Present mode count for presentation queue is zero")
}
);
return GN_NO_SUPPORTED_PRESENT_MODES;
}
int index = -1;
VkFormat convertedFormat = vkGryphnFormatToVulkanFormat(presentationInfo.format.format);
VkColorSpaceKHR convertedColorSpace = vkGryphnColorSpaceToVulkanColorSpace(presentationInfo.format.colorSpace);
for (int i = 0; i < details.formatCount; i++) {
if (details.formats[i].format == convertedFormat && details.formats[i].colorSpace == convertedColorSpace) {
index = i;
break;
}
}
if (index == -1) {
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString("Unsupported color format passed to Gryphn")
});
return GN_UNKNOWN_IMAGE_FORMAT;
}
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
VkExtent2D extent = {
.width = presentationInfo.imageSize.x,
.height = presentationInfo.imageSize.y
};
VkSwapchainCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = presentationInfo.surface->windowSurface->surface;
createInfo.minImageCount = presentationInfo.minImageCount;
createInfo.imageFormat = details.formats[index].format;
createInfo.imageColorSpace = details.formats[index].colorSpace;
createInfo.imageExtent = extent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
if (presentationInfo.imageSharingMode == GN_SHARING_MODE_EXCLUSIVE)
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
else
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
createInfo.queueFamilyIndexCount = presentationInfo.queueFamilyCount;
createInfo.pQueueFamilyIndices = presentationInfo.queueFamilies;
createInfo.preTransform = details.capabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
VkResult result = vkCreateSwapchainKHR(device->outputDevice->device, &createInfo, NULL, &presentationQueue->presentationQueue->swapChain);
if (result == VK_ERROR_NATIVE_WINDOW_IN_USE_KHR) return GN_WINDOW_IN_USE;
if (result != VK_SUCCESS)
return GN_FAILED_TO_CREATE_PRESENTATION_QUEUE;
vkGetSwapchainImagesKHR(device->outputDevice->device, presentationQueue->presentationQueue->swapChain, &presentationQueue->imageCount, NULL);
presentationQueue->presentationQueue->swapChainImages = malloc(sizeof(VkImage) * presentationQueue->imageCount);
presentationQueue->presentationQueue->swapChainImageViews = malloc(sizeof(VkImageView) * presentationQueue->imageCount);
vkGetSwapchainImagesKHR(device->outputDevice->device, presentationQueue->presentationQueue->swapChain, &presentationQueue->imageCount, presentationQueue->presentationQueue->swapChainImages);
VkImageViewCreateInfo imageViewCreateInfo = {};
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCreateInfo.format = convertedFormat;
imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
imageViewCreateInfo.subresourceRange.levelCount = 1;
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
imageViewCreateInfo.subresourceRange.layerCount = 1;
presentationQueue->images = malloc(sizeof(gnTextureHandle) * presentationQueue->imageCount);
for (int i = 0; i < presentationQueue->imageCount; i++) {
presentationQueue->images[i] = malloc(sizeof(struct gnTexture_t));
presentationQueue->images[i]->texture = malloc(sizeof(gnPlatformTexture));
imageViewCreateInfo.image = presentationQueue->presentationQueue->swapChainImages[i];
if (vkCreateImageView(device->outputDevice->device, &imageViewCreateInfo, NULL, &presentationQueue->presentationQueue->swapChainImageViews[i]) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_IMAGE_VIEW;
presentationQueue->images[i]->texture->image.image = presentationQueue->presentationQueue->swapChainImages[i];
presentationQueue->images[i]->texture->image.imageView = presentationQueue->presentationQueue->swapChainImageViews[i];
}
return GN_SUCCESS;
}
gnReturnCode gnPresentationQueueGetImageFn(gnPresentationQueueHandle presentationQueue, uint64_t timeout, struct gnSemaphore_t* semaphore, uint32_t* imageIndex) {
VkResult result = vkAcquireNextImageKHR(
presentationQueue->outputDevice->outputDevice->device,
presentationQueue->presentationQueue->swapChain,
timeout, semaphore->semaphore->semaphore, VK_NULL_HANDLE, imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR) return GN_OUT_OF_DATE_PRESENTATION_QUEUE;
if (result == VK_SUBOPTIMAL_KHR) return GN_SUBOPTIMAL_PRESENTATION_QUEUE;
return GN_SUCCESS;
}
void gnDestroyPresentationQueueFn(gnPresentationQueueHandle queue) {
for (int i = 0; i < queue->imageCount; i++)
vkDestroyImageView(queue->outputDevice->outputDevice->device, queue->presentationQueue->swapChainImageViews[i], NULL);
vkDestroySwapchainKHR(queue->outputDevice->outputDevice->device, queue->presentationQueue->swapChain, NULL);
free(queue->presentationQueue->swapChainImageViews);
free(queue->presentationQueue->swapChainImages);
free(queue->presentationQueue);
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "core/presentation_queue/gryphn_presentation_queue.h"
#include <vulkan/vulkan.h>
typedef struct gnPlatformPresentationQueue_t {
VkSwapchainKHR swapChain;
VkImage* swapChainImages;
VkImageView* swapChainImageViews;
} gnPlatformPresentationQueue;

View File

@@ -0,0 +1,35 @@
#include "vulkan_swapchain_support.h"
struct vkSwapchainSupportDetails_t vkGetSwapchainSupport(
const VkPhysicalDevice device,
const VkSurfaceKHR surface
) {
struct vkSwapchainSupportDetails_t details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &details.formatCount, NULL);
if (details.formatCount > 0) {
details.formats = malloc(sizeof(VkSurfaceFormatKHR) * details.formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &details.formatCount, details.formats);
}
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &details.presentModeCount, NULL);
if (details.presentModeCount > 0) {
details.presentModes = malloc(sizeof(VkPresentModeKHR) * details.presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &details.presentModeCount, details.presentModes);
}
return details;
}
struct vkSwapchainDetails_t vkGetSwapchainDetails(
const struct vkSwapchainSupportDetails_t supportDetails
) {
struct vkSwapchainDetails_t details;
for (int i = 0; i < supportDetails.formatCount; i++) {
// if (supportDetails.)
}
return details;
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <vulkan/vulkan.h>
#include <output_device/vulkan_output_devices.h>
typedef struct vkSwapchainSupportDetails_t {
VkSurfaceCapabilitiesKHR capabilities;
uint32_t formatCount;
VkSurfaceFormatKHR* formats;
uint32_t presentModeCount;
VkPresentModeKHR* presentModes;
} vkSwapchainSupportDetails;
typedef struct vkSwapchainDetails_t {
VkSurfaceFormatKHR surfaceFormat;
} vkSwapchainDetails;
struct vkSwapchainSupportDetails_t vkGetSwapchainSupport(
const VkPhysicalDevice device,
const VkSurfaceKHR surface
);
struct vkSwapchainDetails_t vkGetSwapchainDetails(
const struct vkSwapchainSupportDetails_t supportDetails
);

View File

@@ -0,0 +1,135 @@
#include "vulkan_render_pass_descriptor.h"
#include "vulkan_surface/vulkan_surface.h"
#include "output_device/vulkan_output_devices.h"
#include "stdio.h"
VkAttachmentLoadOp vkGryphnLoadOperation(gnLoadOperation loadOperation) {
switch(loadOperation) {
case GN_LOAD_OPERATION_LOAD: return VK_ATTACHMENT_LOAD_OP_LOAD;
case GN_LOAD_OPERATION_CLEAR: return VK_ATTACHMENT_LOAD_OP_CLEAR;
case GN_LOAD_OPERATION_DONT_CARE: return VK_ATTACHMENT_LOAD_OP_DONT_CARE;
}
}
VkAttachmentStoreOp vkGryphnStoreOperation(gnStoreOperation storeOperation) {
switch (storeOperation) {
case GN_STORE_OPERATION_STORE: return VK_ATTACHMENT_STORE_OP_STORE;
case GN_STORE_OPERATION_DONT_CARE: return VK_ATTACHMENT_STORE_OP_DONT_CARE;
}
}
VkImageLayout vkGryphnImageLayout(gnImageLayout layout) {
switch(layout) {
case GN_LAYOUT_UNDEFINED: return VK_IMAGE_LAYOUT_UNDEFINED;
case GN_LAYOUT_PRESENTATION_QUEUE_IMAGE: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
case GN_LAYOUT_TRANSFER_DESTINATION: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case GN_LAYOUT_COLOR_ATTACHMENT: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
case GN_LAYOUT_DEPTH_STENCIL: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
}
VkPipelineStageFlags vkGryphnRenderPassStage(gnRenderPassStage stage) {
VkPipelineStageFlags flags = 0;
if ((stage & GN_COLOR_ATTACHMENT_OUTPUT) == GN_COLOR_ATTACHMENT_OUTPUT) flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
if ((stage & GN_EARLY_FRAGMENT_TEST) == GN_EARLY_FRAGMENT_TEST) flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
return flags;
}
VkAccessFlags vkGryphnRenderPassAccess(gnRenderPassAccess access) {
VkAccessFlags flags = 0;
if ((flags & GN_COLOR_ATTACHMENT_WRITE) == GN_COLOR_ATTACHMENT_WRITE) flags |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
if ((flags & GN_DEPTH_STENCIL_WRITE) == GN_DEPTH_STENCIL_WRITE) flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
return flags;
}
gnReturnCode gnCreateRenderPassDescriptorFn(struct gnRenderPassDescriptor_t* renderPass, struct gnOutputDevice_t* device, gnRenderPassDescriptorInfo info) {
renderPass->renderPassDescriptor = malloc(sizeof(gnPlatformRenderPassDescriptor));
renderPass->renderPassDescriptor->attachmentCount = info.attachmentCount;
renderPass->renderPassDescriptor->attachments = malloc(sizeof(VkAttachmentDescription) * info.attachmentCount);
for (int i = 0; i < info.attachmentCount; i++) {
renderPass->renderPassDescriptor->attachments[i].format = vkGryphnFormatToVulkanFormat(info.attachmentInfos[i].format);
renderPass->renderPassDescriptor->attachments[i].flags = 0;
renderPass->renderPassDescriptor->attachments[i].samples = VK_SAMPLE_COUNT_1_BIT;
renderPass->renderPassDescriptor->attachments[i].loadOp = vkGryphnLoadOperation(info.attachmentInfos[i].loadOperation);
renderPass->renderPassDescriptor->attachments[i].storeOp = vkGryphnStoreOperation(info.attachmentInfos[i].storeOperation);
renderPass->renderPassDescriptor->attachments[i].stencilLoadOp = vkGryphnLoadOperation(info.attachmentInfos[i].stencilLoadOperation);
renderPass->renderPassDescriptor->attachments[i].stencilStoreOp = vkGryphnStoreOperation(info.attachmentInfos[i].stencilStoreOperation);
renderPass->renderPassDescriptor->attachments[i].initialLayout = vkGryphnImageLayout(info.attachmentInfos[i].initialLayout);
renderPass->renderPassDescriptor->attachments[i].finalLayout = vkGryphnImageLayout(info.attachmentInfos[i].finalLayout);
}
renderPass->renderPassDescriptor->subpassCount = info.subpassCount;
renderPass->renderPassDescriptor->subpasses = malloc(sizeof(VkSubpassDescription) * info.subpassCount);
renderPass->renderPassDescriptor->colorAttachments = malloc(sizeof(VkAttachmentReference*) * info.subpassCount);
renderPass->renderPassDescriptor->depthAttachments = malloc(sizeof(VkAttachmentReference) * info.subpassCount);
for (int i = 0; i < info.subpassCount; i++) {
renderPass->renderPassDescriptor->colorAttachments[i] = malloc(sizeof(VkAttachmentReference) * info.subpassInfos[i].colorAttachmentCount);
for (int c = 0; c < info.subpassInfos[i].colorAttachmentCount; c++) {
renderPass->renderPassDescriptor->colorAttachments[i][c] = (VkAttachmentReference){
.attachment = info.subpassInfos[i].colorAttachments[c].index,
.layout = vkGryphnImageLayout(info.subpassInfos[i].colorAttachments[c].imageLayout)
};
}
renderPass->renderPassDescriptor->subpasses[i] = (VkSubpassDescription){
.flags = 0,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.colorAttachmentCount = info.subpassInfos[i].colorAttachmentCount,
.pColorAttachments = renderPass->renderPassDescriptor->colorAttachments[i]
};
if (info.subpassInfos[i].depthAttachment != NULL) {
renderPass->renderPassDescriptor->depthAttachments[i] = (VkAttachmentReference){
.attachment = info.subpassInfos[i].depthAttachment->index,
.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
};
renderPass->renderPassDescriptor->subpasses[i].pDepthStencilAttachment = &renderPass->renderPassDescriptor->depthAttachments[i];
}
}
renderPass->renderPassDescriptor->dependencies = malloc(sizeof(VkSubpassDependency) * info.dependencyCount);
for (int i = 0; i < info.dependencyCount; i++) {
renderPass->renderPassDescriptor->dependencies[i] = (VkSubpassDependency) {
.srcSubpass = (info.dependencies[i].source == GN_SUBPASS_EXTERNAL) ? VK_SUBPASS_EXTERNAL : info.dependencies[i].source,
.dstSubpass = (info.dependencies[i].destination == GN_SUBPASS_EXTERNAL) ? VK_SUBPASS_EXTERNAL : info.dependencies[i].destination,
.srcStageMask = vkGryphnRenderPassStage(info.dependencies[i].soruceStageMask),
.srcAccessMask = vkGryphnRenderPassAccess(info.dependencies[i].sourceAccessMask),
.dstStageMask = vkGryphnRenderPassStage(info.dependencies[i].destinationStageMask),
.dstAccessMask = vkGryphnRenderPassAccess(info.dependencies[i].destinationAccessMask)
};
}
VkRenderPassCreateInfo renderPassInfo = (VkRenderPassCreateInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.attachmentCount = info.attachmentCount,
.pAttachments = renderPass->renderPassDescriptor->attachments,
.subpassCount = info.subpassCount,
.pSubpasses = renderPass->renderPassDescriptor->subpasses,
.dependencyCount = info.dependencyCount,
.pDependencies = renderPass->renderPassDescriptor->dependencies,
};
if (vkCreateRenderPass(device->outputDevice->device, &renderPassInfo, NULL, &renderPass->renderPassDescriptor->renderPass) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_RENDER_PASS;
return GN_SUCCESS;
}
void gnDestroyRenderPassDescriptorFn(gnRenderPassDescriptor renderPass) {
vkDestroyRenderPass(renderPass->device->outputDevice->device, renderPass->renderPassDescriptor->renderPass, NULL);
free(renderPass->renderPassDescriptor->attachments);
free(renderPass->renderPassDescriptor->subpasses);
free(renderPass->renderPassDescriptor->dependencies);
free(renderPass->renderPassDescriptor->depthAttachments);
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include "core/renderpass/gryphn_render_pass_descriptor.h"
#include <vulkan/vulkan.h>
typedef struct gnPlatformRenderPassDescriptor_t {
VkRenderPass renderPass;
uint32_t attachmentCount;
VkAttachmentDescription* attachments;
uint32_t subpassCount;
VkSubpassDescription* subpasses;
VkSubpassDependency* dependencies;
VkAttachmentReference** colorAttachments;
VkAttachmentReference* depthAttachments;
} gnPlatformRenderPassDescriptor;
VkPipelineStageFlags vkGryphnRenderPassStage(gnRenderPassStage stage);

View File

@@ -0,0 +1,39 @@
#include "vulkan_shader_module.h"
#include "output_device/vulkan_output_devices.h"
#include "stdio.h"
VkShaderStageFlagBits vkGryphnShaderModuleStage(gnShaderModuleStage stage) {
VkShaderStageFlagBits outStage = 0;
if ((stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) outStage |= VK_SHADER_STAGE_VERTEX_BIT;
if ((stage & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) outStage |= VK_SHADER_STAGE_FRAGMENT_BIT;
if ((stage & GN_ALL_SHADER_MODULE) == GN_ALL_SHADER_MODULE) return VK_SHADER_STAGE_ALL_GRAPHICS;
return outStage;
}
gnReturnCode gnCreateShaderModuleFn(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo) {
module->shaderModule = malloc(sizeof(struct gnPlatformShaderModule_t));
VkShaderModuleCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = shaderModuleInfo.size,
.pCode = shaderModuleInfo.code
};
if (vkCreateShaderModule(device->outputDevice->device, &createInfo, NULL, &module->shaderModule->shaderModule) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_SHADER_MODULE;
module->shaderModule->shaderStageInfo = (VkPipelineShaderStageCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = vkGryphnShaderModuleStage(shaderModuleInfo.stage),
.module = module->shaderModule->shaderModule,
.pName = shaderModuleInfo.entryPoint.value
};
return GN_SUCCESS;
}
void gnDestroyShaderModuleFn(struct gnShaderModule_t* module) {
vkDestroyShaderModule(module->device->outputDevice->device, module->shaderModule->shaderModule, NULL);
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <core/shader_module/gryphn_shader_module.h>
#include <vulkan/vulkan.h>
typedef struct gnPlatformShaderModule_t {
VkShaderModule shaderModule;
VkPipelineShaderStageCreateInfo shaderStageInfo;
} gnPlatformShaderModule;
VkShaderStageFlagBits vkGryphnShaderModuleStage(gnShaderModuleStage stage);

View File

@@ -0,0 +1,50 @@
#include <vulkan/vulkan.h>
#include "core/submit/gryphn_submit.h"
#include "sync/semaphore/vulkan_semaphore.h"
#include "sync/fence/vulkan_fence.h"
#include "commands/command_buffer/vulkan_command_buffer.h"
#include "output_device/vulkan_output_devices.h"
#include "renderpass/vulkan_render_pass_descriptor.h"
gnReturnCode gnSubmitFn(struct gnOutputDevice_t* device, struct gnSubmitInfo_t info) {
VK_SUBPASS_EXTERNAL;
VkSemaphore* waitSemaphores = malloc(sizeof(VkSemaphore) * info.waitCount);
VkPipelineStageFlags* waitStages = malloc(sizeof(VkPipelineStageFlags) * info.waitCount);
for (int i = 0; i < info.waitCount; i++) waitSemaphores[i] = info.waitSemaphores[i]->semaphore->semaphore;
for (int i = 0; i < info.waitCount; i++) waitStages[i] = vkGryphnRenderPassStage(info.waitStages[i]);
VkCommandBuffer* commandBuffers = malloc(sizeof(VkCommandBuffer) * info.commandBufferCount);
for (int i = 0; i < info.commandBufferCount; i++) commandBuffers[i] = info.commandBuffers[i]->commandBuffer->buffer;
VkSemaphore* signalSemaphores = malloc(sizeof(VkSemaphore) * info.signalCount);
for (int i = 0; i < info.signalCount; i++) signalSemaphores[i] = info.signalSemaphores[i]->semaphore->semaphore;
VkSubmitInfo submitInfo = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = info.waitCount,
.pWaitSemaphores = waitSemaphores,
.pWaitDstStageMask = waitStages,
.commandBufferCount = info.commandBufferCount,
.pCommandBuffers = commandBuffers,
.signalSemaphoreCount = info.signalCount,
.pSignalSemaphores = signalSemaphores
};
VkQueue queue;
vkGetDeviceQueue(device->outputDevice->device, info.queueIndex, 0, &queue);
if (vkQueueSubmit(queue, 1, &submitInfo, info.fence->fence->fence) != VK_SUCCESS) {
free(waitSemaphores);
free(waitStages);
free(commandBuffers);
free(signalSemaphores);
return GN_FAILED_TO_SUBMIT_COMMAND_BUFFER;
}
free(waitSemaphores);
free(waitStages);
free(commandBuffers);
free(signalSemaphores);
return GN_SUCCESS;
}

View File

@@ -0,0 +1,23 @@
#include "vulkan_fence.h"
#include "output_device/vulkan_output_devices.h"
gnReturnCode gnCreateFenceFn(struct gnFence_t* fence, struct gnOutputDevice_t* device) {
fence->fence = malloc(sizeof(gnPlatformFence));
VkFenceCreateInfo fenceInfo = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
};
if (vkCreateFence(device->outputDevice->device, &fenceInfo, NULL, &fence->fence->fence) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_FENCE;
return GN_SUCCESS;
}
void gnSignalFenceFn(struct gnFence_t* fence) {}
void gnWaitForFenceFn(struct gnFence_t* fence, uint64_t timeout) {
vkWaitForFences(fence->device->outputDevice->device, 1, &fence->fence->fence, VK_TRUE, timeout);
}
void gnResetFenceFn(struct gnFence_t* fence) {
vkResetFences(fence->device->outputDevice->device, 1, &fence->fence->fence);
}
void gnDestroyFenceFn(struct gnFence_t* fence) {
vkDestroyFence(fence->device->outputDevice->device, fence->fence->fence, NULL);
free(fence->fence);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <vulkan/vulkan.h>
#include "core/sync/fence/gryphn_fence.h"
typedef struct gnPlatformFence_t {
VkFence fence;
} gnPlatformFence;

View File

@@ -0,0 +1,17 @@
#include "vulkan_semaphore.h"
#include "output_device/vulkan_output_devices.h"
gnReturnCode gnCreateSemaphoreFn(struct gnSemaphore_t* semaphore, struct gnOutputDevice_t* device) {
semaphore->semaphore = malloc(sizeof(gnPlatformSemaphore));
VkSemaphoreCreateInfo semaphoreInfo = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
};
if (vkCreateSemaphore(device->outputDevice->device, &semaphoreInfo, NULL, &semaphore->semaphore->semaphore))
return GN_FAILED_TO_CREATE_SEMAPHORE;
return GN_SUCCESS;
}
void gnDestroySemaphoreFn(struct gnSemaphore_t* semaphore) {
vkDestroySemaphore(semaphore->device->outputDevice->device, semaphore->semaphore->semaphore, NULL);
free(semaphore->semaphore);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <vulkan/vulkan.h>
#include "core/sync/semaphore/gryphn_semaphore.h"
typedef struct gnPlatformSemaphore_t {
VkSemaphore semaphore;
} gnPlatformSemaphore;

View File

@@ -0,0 +1,273 @@
#include "vulkan_surface/vulkan_surface.h"
#include "vulkan_texture.h"
#include "output_device/vulkan_output_devices.h"
#include "output_device/vulkan_physical_device.h"
#include "core/debugger/gryphn_debugger.h"
VkImageType vkGryphnTextureType(gnTextureType type) {
switch(type) {
case GN_TEXTURE_2D: return VK_IMAGE_TYPE_2D;
}
}
VkImageViewType vkGryphnTextureTypeView(gnTextureType type) {
switch(type) {
case GN_TEXTURE_2D: return VK_IMAGE_VIEW_TYPE_2D;
}
}
VkSamplerAddressMode vkGryphnTextureWrap(gnTextureWrap wrap) {
switch(wrap) {
case GN_REPEAT: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case GN_MIRRORED_REPEAT: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case GN_CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case GN_CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
}
}
VkImageAspectFlags vkGryphnGetAspectFlags(gnImageFormat format) {
VkImageAspectFlags aspectMask = 0;
if (format == GN_FORMAT_D32S8_UINT || format == GN_FORMAT_D24S8_UINT) aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
else { aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; }
return aspectMask;
}
gnBool vkGryphnIsDepthStencil(gnImageFormat format) { return (format == GN_FORMAT_D32S8_UINT || format == GN_FORMAT_D24S8_UINT); }
void VkTransitionImageLayout(gnDevice device, VkImage image, gnImageFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) {
VkCommandBuffer transferBuffer = gnBeginVulkanTransferOperation(device);
VkPipelineStageFlags sourceStage, destinationStage;
VkAccessFlags sourceAccessMask, destinationAccessMask;
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
sourceAccessMask = 0;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
sourceAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
destinationAccessMask = VK_ACCESS_SHADER_READ_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
sourceAccessMask = 0;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
}
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.image = image,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.srcAccessMask = sourceAccessMask,
.oldLayout = oldLayout,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstAccessMask = destinationAccessMask,
.newLayout = newLayout,
.subresourceRange.aspectMask = vkGryphnGetAspectFlags(format),
.subresourceRange.baseMipLevel = 0,
.subresourceRange.levelCount = 1,
.subresourceRange.baseArrayLayer = 0,
.subresourceRange.layerCount = 1,
};
vkCmdPipelineBarrier(
transferBuffer,
sourceStage, destinationStage,
0,
0, NULL,
0, NULL,
1, &barrier
);
gnEndVulkanTransferOperation(device, transferBuffer);
}
void VkCopyBufferToImage(VkGryphnBuffer buffer, VkGryphnImage image, uint32_t width, uint32_t height, gnDevice device) {
VkCommandBuffer transferBuffer = gnBeginVulkanTransferOperation(device);
VkBufferImageCopy region = {
.bufferOffset = 0,
.bufferRowLength = 0,
.bufferImageHeight = 0,
.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.imageSubresource.mipLevel = 0,
.imageSubresource.baseArrayLayer = 0,
.imageSubresource.layerCount = 1,
.imageOffset = (VkOffset3D){0, 0, 0},
.imageExtent = (VkExtent3D){
width,
height,
1
}
};
vkCmdCopyBufferToImage(
transferBuffer,
buffer.buffer, image.image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &region
);
gnEndVulkanTransferOperation(device, transferBuffer);
}
#include "stdio.h"
gnReturnCode gnCreateTextureFn(gnTexture texture, gnDevice device, const gnTextureInfo info) {
texture->texture = malloc(sizeof(struct gnPlatformTexture_t));
size_t imageSize = info.width * info.height;
if (info.format == GN_FORMAT_BGRA8_SRGB) { imageSize *= 4; }
if (info.format == GN_FORMAT_RGBA8_SRGB) { imageSize *= 4; }
gnReturnCode staginBufferCreateCode = VkCreateBuffer(
&texture->texture->buffer, imageSize, device,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT
);
if (staginBufferCreateCode != GN_SUCCESS) return GN_FAILED_TO_CREATE_BUFFER;
texture->texture->size = imageSize;
VkImageCreateInfo imageInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.samples = VK_SAMPLE_COUNT_1_BIT,
.extent = {
.width = info.width,
.height = info.height,
.depth = 1
},
.mipLevels = 1,
.arrayLayers = 1,
.imageType = vkGryphnTextureType(info.type),
.format = vkGryphnFormatToVulkanFormat(info.format)
};
if (vkGryphnIsDepthStencil(info.format))
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
else
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (vkCreateImage(device->outputDevice->device, &imageInfo, NULL, &texture->texture->image.image) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_IMAGE;
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(device->outputDevice->device, texture->texture->image.image, &memRequirements);
gnBool foundMemory = gnFalse;
VkMemoryAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = memRequirements.size,
.memoryTypeIndex = VkMemoryIndex(device->physicalDevice.physicalDevice->device, memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &foundMemory)
};
if (!foundMemory) return GN_FAILED_TO_ALLOCATE_MEMORY;
if (vkAllocateMemory(device->outputDevice->device, &allocInfo, NULL, &texture->texture->image.memory) != VK_SUCCESS)
return GN_FAILED_TO_ALLOCATE_MEMORY;
vkBindImageMemory(device->outputDevice->device, texture->texture->image.image, texture->texture->image.memory, 0);
texture->texture->width = info.width;
texture->texture->height = info.height;
texture->texture->beenWrittenToo = gnFalse;
VkImageViewCreateInfo viewInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = texture->texture->image.image,
.viewType = vkGryphnTextureTypeView(info.type),
.format = vkGryphnFormatToVulkanFormat(info.format),
.subresourceRange.aspectMask = vkGryphnGetAspectFlags(info.format),
.subresourceRange.baseMipLevel = 0,
.subresourceRange.levelCount = 1,
.subresourceRange.baseArrayLayer = 0,
.subresourceRange.layerCount = 1,
};
if (vkCreateImageView(device->outputDevice->device, &viewInfo, NULL, &texture->texture->image.imageView) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_IMAGE_VIEW;
VkPhysicalDeviceProperties properties = {};
vkGetPhysicalDeviceProperties(device->physicalDevice.physicalDevice->device, &properties);
VkSamplerCreateInfo samplerInfo = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.minFilter = (info.minFilter == GN_FILTER_LINEAR) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
.magFilter = (info.magFilter == GN_FILTER_LINEAR) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
.addressModeU = vkGryphnTextureWrap(info.wrapU),
.addressModeV = vkGryphnTextureWrap(info.wrapV),
.addressModeW = vkGryphnTextureWrap(info.wrapW),
.anisotropyEnable = VK_TRUE,
.maxAnisotropy = properties.limits.maxSamplerAnisotropy,
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
.unnormalizedCoordinates = VK_FALSE,
.compareEnable = VK_FALSE,
.compareOp = VK_COMPARE_OP_ALWAYS,
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
.mipLodBias = 0.0f,
.minLod = 0.0f,
.maxLod = 0.0f,
};
if (vkCreateSampler(device->outputDevice->device, &samplerInfo, NULL, &texture->texture->sampler) != VK_SUCCESS)
return GN_FAILED_TO_CREATE_SAMPLER;
if (vkGryphnIsDepthStencil(info.format))
VkTransitionImageLayout(texture->device, texture->texture->image.image, texture->info.format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
return GN_SUCCESS;
}
void gnTextureDataFn(gnTextureHandle texture, void* pixelData) {
void* data;
vkMapMemory(texture->device->outputDevice->device, texture->texture->buffer.memory, 0, texture->texture->size, 0, &data);
memcpy(data, pixelData, texture->texture->size);
vkUnmapMemory(texture->device->outputDevice->device, texture->texture->buffer.memory);
if (texture->texture->beenWrittenToo) {
gnDebuggerSetErrorMessage(texture->device->instance->debugger, (gnMessageData){
.message = gnCreateString("this texture has alreay been written too with gnTextureData (vulkan) i need to implement the functionality to write to it multible times")
});
}
//gnDevice device, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout
VkTransitionImageLayout(texture->device, texture->texture->image.image, texture->info.format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkCopyBufferToImage(texture->texture->buffer, texture->texture->image, texture->texture->width, texture->texture->height, texture->device);
VkTransitionImageLayout(texture->device, texture->texture->image.image, texture->info.format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
texture->texture->beenWrittenToo = gnTrue;
}
void gnDestroyVulkanImage(VkGryphnImage* image, VkDevice device) {
vkDestroyImage(device, image->image, NULL);
vkDestroyImageView(device, image->imageView, NULL);
vkFreeMemory(device, image->memory, NULL);
}
void gnDestroyTextureFn(gnTexture texture) {
vkDestroySampler(texture->device->outputDevice->device, texture->texture->sampler, NULL);
gnDestroyVulkanBuffer(&texture->texture->buffer, texture->device->outputDevice->device);
gnDestroyVulkanImage(&texture->texture->image, texture->device->outputDevice->device);
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <vulkan/vulkan.h>
#include "core/textures/gryphn_texture.h"
#include "buffers/vulkan_buffer.h"
typedef struct VkGryphnImage {
VkImage image;
VkDeviceMemory memory;
VkImageView imageView;
} VkGryphnImage;
void gnDestroyVulkanImage(VkGryphnImage* image, VkDevice device);
typedef struct gnPlatformTexture_t {
VkGryphnBuffer buffer;
VkGryphnImage image;
VkSampler sampler;
size_t size;
uint32_t width, height;
gnBool beenWrittenToo;
} gnPlatformTexture;

View File

@@ -0,0 +1,45 @@
#include "vulkan_uniform.h"
#include "buffers/vulkan_buffer.h"
#include "output_device/vulkan_output_devices.h"
#include "core/uniforms/gryphn_uniform_pool.h"
#include "textures/vulkan_texture.h"
void gnUpdateBufferUniformFn(gnUniform uniform, gnBufferUniformInfo* info) {
VkDescriptorBufferInfo bufferInfo = {
.buffer = info->buffer->buffer->buffer.buffer,
.offset = info->offset,
.range = info->size
};
VkWriteDescriptorSet write = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.pBufferInfo = &bufferInfo,
.dstSet = uniform->uniform->set,
.dstBinding = info->binding,
.dstArrayElement = 0
};
vkUpdateDescriptorSets(uniform->pool->device->outputDevice->device, 1, &write, 0, NULL);
}
void gnUpdateImageUniformFn(gnUniform uniform, gnImageUniformInfo* info) {
VkDescriptorImageInfo imageInfo = {
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
.imageView = info->texture->texture->image.imageView,
.sampler = info->texture->texture->sampler
};
VkWriteDescriptorSet write = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 1,
.pImageInfo = &imageInfo,
.dstSet = uniform->uniform->set,
.dstBinding = info->binding,
.dstArrayElement = 0
};
vkUpdateDescriptorSets(uniform->pool->device->outputDevice->device, 1, &write, 0, NULL);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <vulkan/vulkan.h>
#include "core/uniforms/gryphn_uniform.h"
typedef struct gnPlatformUniform_t {
VkDescriptorSet set;
} gnPlatformUniform;

View File

@@ -0,0 +1,39 @@
#include "vulkan_uniform_layout.h"
#include <shader_module/vulkan_shader_module.h>
VkDescriptorType vkGryphnUniformType(gnUniformType type) {
switch(type) {
case GN_UNIFORM_BUFFER_DESCRIPTOR: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
case GN_IMAGE_DESCRIPTOR: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
case GN_UNIFORM_TYPE_MAX: return VK_DESCRIPTOR_TYPE_MAX_ENUM;
}
}
VkDescriptorSetLayout vkGryphnCreateSetLayouts(
const gnUniformSet* set,
VkDevice device
) {
VkDescriptorSetLayout vkLayout;
gnUniformSet uniformSet = *set;
VkDescriptorSetLayoutBinding* bindings = malloc(sizeof(VkDescriptorSetLayoutBinding) * uniformSet.uniformBindingCount);
for (int i = 0; i < uniformSet.uniformBindingCount; i++) {
bindings[i] = (VkDescriptorSetLayoutBinding){
.binding = uniformSet.uniformBindings[i].binding,
.descriptorCount = 1,
.descriptorType = vkGryphnUniformType(uniformSet.uniformBindings[i].type),
.stageFlags = vkGryphnShaderModuleStage(uniformSet.uniformBindings[i].stage)
};
}
VkDescriptorSetLayoutCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = uniformSet.uniformBindingCount,
.pBindings = bindings
};
if (vkCreateDescriptorSetLayout(device, &info, NULL, &vkLayout) != VK_SUCCESS)
return NULL;
return vkLayout;
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <vulkan/vulkan.h>
#include <core/uniforms/gryphn_uniform_layout.h>
VkDescriptorSetLayout vkGryphnCreateSetLayouts(const gnUniformSet* set, VkDevice device);
VkDescriptorType vkGryphnUniformType(gnUniformType type);

View File

@@ -0,0 +1,136 @@
#include "vulkan_uniform_pool.h"
#include "vulkan_uniform_layout.h"
#include "stdlib.h"
#include "output_device/vulkan_output_devices.h"
#include "core/uniforms/gryphn_uniform.h"
#include "vulkan_uniform.h"
#include "stdio.h"
VkGryphnUniformPool* GetLastUniformPool(VkGryphnUniformPoolArrayList* list) { return &list->data[list->count - 1]; }
gnReturnCode gnCreateUniformPoolFn(gnUniformPool pool, gnDeviceHandle device) {
pool->uniformPool = malloc(sizeof(struct gnPlatformUniformPool_t));
pool->uniformPool->pools = VkGryphnUniformPoolArrayListCreate();
if (device->outputDevice->enabledOversizedDescriptorPools == gnTrue) {
{
VkGryphnUniformPool firstPool = {
.pool = VK_NULL_HANDLE,
.layouts = VkDescriptorSetLayoutArrayListCreate()
};
VkGryphnUniformPoolArrayListAdd(&pool->uniformPool->pools, firstPool);
} // scopped because the add function copies and I don't want it lying around
VkGryphnUniformPool* currentPool = GetLastUniformPool(&pool->uniformPool->pools);
VkDescriptorPoolCreateInfo poolInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV,
.poolSizeCount = 0,
.pPoolSizes = NULL,
.maxSets = 0
};
if (vkCreateDescriptorPool(
pool->device->outputDevice->device, &poolInfo, NULL,
&currentPool->pool
) != VK_SUCCESS)
return GN_FAILED_TO_ALLOCATE_MEMORY;
}
return GN_SUCCESS;
}
gnUniform* gnUniformPoolAllocateUniformsFn(gnUniformPool pool, gnUniformAllocationInfo allocInfo) {
gnBool fixedAllocation = !pool->device->outputDevice->enabledOversizedDescriptorPools;
if (fixedAllocation) {
VkGryphnUniformPool newPool = {
.pool = VK_NULL_HANDLE,
.layouts = VkDescriptorSetLayoutArrayListCreate()
};
// TODO: redo this, its not warning me IDK why cuz its totally wrong
VkDescriptorPoolSize uniformBufferSize = {
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 0
};
VkDescriptorPoolSize imageSize = {
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 0
};
for (int i = 0; i < allocInfo.setCount; i++) {
for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) {
if (allocInfo.sets[i].uniformBindings[i].type == GN_UNIFORM_BUFFER_DESCRIPTOR) uniformBufferSize.descriptorCount++;
if (allocInfo.sets[i].uniformBindings[i].type == GN_IMAGE_DESCRIPTOR) imageSize.descriptorCount++;
}
}
uint32_t count = 0;
VkDescriptorPoolSize poolSizes[2] = {};
if (uniformBufferSize.descriptorCount > 0) {
poolSizes[count] = uniformBufferSize;
count++;
}
if (imageSize.descriptorCount > 0) {
poolSizes[count] = imageSize;
count++;
}
VkDescriptorPoolCreateInfo poolInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = count,
.pPoolSizes = poolSizes,
.maxSets = allocInfo.setCount
};
if (vkCreateDescriptorPool(
pool->device->outputDevice->device, &poolInfo, NULL,
&newPool.pool
) != VK_SUCCESS)
return NULL;
VkGryphnUniformPoolArrayListAdd(&pool->uniformPool->pools, newPool);
} // scopped for same reasons as before
VkGryphnUniformPool* currentPool = GetLastUniformPool(&pool->uniformPool->pools);
uint32_t startingCount = currentPool->layouts.count;
VkDescriptorSetLayoutArrayListExpand(&currentPool->layouts, allocInfo.setCount);
for (int i = 0; i < allocInfo.setCount; i++) {
VkDescriptorSetLayoutArrayListAdd(
&currentPool->layouts,
vkGryphnCreateSetLayouts(&allocInfo.sets[i], pool->device->outputDevice->device)
);
}
VkDescriptorSetAllocateInfo vkAllocInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = currentPool->pool,
.descriptorSetCount = allocInfo.setCount,
.pSetLayouts = &currentPool->layouts.data[startingCount]
};
VkDescriptorSet* sets = malloc(sizeof(VkDescriptorSet) * allocInfo.setCount);
if (vkAllocateDescriptorSets(pool->device->outputDevice->device, &vkAllocInfo, sets) != VK_SUCCESS)
return NULL;
gnUniform* uniforms = malloc(sizeof(gnUniform) * allocInfo.setCount);
for (int i = 0; i < allocInfo.setCount; i++) {
uniforms[i] = malloc(sizeof(struct gnUniform_t));
uniforms[i]->uniform = malloc(sizeof(struct gnPlatformUniform_t));
uniforms[i]->uniform->set = sets[i];
}
return uniforms;
}
void gnDestroyUniformPoolFn(gnUniformPool pool) {
for (int k = 0; k < pool->uniformPool->pools.count; k++) {
vkDestroyDescriptorPool(pool->device->outputDevice->device, pool->uniformPool->pools.data[k].pool, NULL);
for (int i = 0; i < pool->uniformPool->pools.data[k].layouts.count; i++)
vkDestroyDescriptorSetLayout(pool->device->outputDevice->device, pool->uniformPool->pools.data[k].layouts.data[i], NULL);
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <vulkan/vulkan.h>
#include <core/uniforms/gryphn_uniform_pool.h>
GN_ARRAY_LIST(VkDescriptorSetLayout);
typedef struct VkGryphnUniformPool {
VkDescriptorPool pool;
VkDescriptorSetLayoutArrayList layouts;
} VkGryphnUniformPool;
GN_ARRAY_LIST(VkGryphnUniformPool);
struct gnPlatformUniformPool_t {
VkGryphnUniformPoolArrayList pools;
};

View File

@@ -0,0 +1,124 @@
#include <core/window_surface/gryphn_surface_create_functions.h>
#include <instance/vulkan_instance.h>
#include "vulkan_surface.h"
#include <output_device/vulkan_physical_device.h>
#include <stdio.h>
#ifdef GN_PLATFORM_LINUX
#ifdef GN_WINDOW_X11
#include <vulkan/vulkan_xlib.h>
#include <X11/Xlib.h>
gnReturnCode gnCreateX11WindowSurfaceFn(gnWindowSurfaceHandle windowSurface, gnInstanceHandle instance, gnX11WindowSurfaceInfo createInfo) {
windowSurface->windowSurface = malloc(sizeof(struct gnPlatformWindowSurface_t));
VkXlibSurfaceCreateInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
info.dpy = createInfo.display;
info.window = createInfo.window;
VkResult result = vkCreateXlibSurfaceKHR(instance->instance->vk_instance, &info, NULL, &windowSurface->windowSurface->surface);
if (result != VK_SUCCESS)
return GN_FAILED_TO_ATTACH_WINDOW;
return GN_SUCCESS;
}
#endif
#ifdef GN_WINFDOW_WAYLAND
#include <vulkan/vulkan_wayland.h>
gnReturnCode gnCreateWaylandWindowSurface(struct gnWindowSurface_t* windowSurface, gnInstanceHandle instance, struct gnWaylandWindowSurfaceInfo_t createInfo) {
windowSurface->windowSurface = malloc(sizeof(struct gnPlatformWindowSurface_t));
VkWaylandSurfaceCreateInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
info.display = createInfo.display;
info.surface = createInfo.surface;
VkResult result = vkCreateWaylandSurfaceKHR(instance->instance->vk_instance, &info, NULL, &windowSurface->windowSurface->surface);
if (result != VK_SUCCESS)
return GN_FAILED_TO_ATTACH_WINDOW;
return GN_SUCCESS;
}
#endif
#endif
#ifdef GN_PLATFORM_WINDOWS
#include "vulkan/vulkan_win32.h"
gnReturnCode gnCreateWin32WindowSurface(struct gnWindowSurface_t* windowSurface, gnInstanceHandle instance, struct gnWin32WindowSurfaceInfo_t createInfo) {
windowSurface->windowSurface = malloc(sizeof(struct gnPlatformWindowSurface_t));
VkWin32SurfaceCreateInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
info.hwnd = createInfo.window;
info.hinstance = createInfo.instance;
VkResult result = vkCreateWin32SurfaceKHR(instance->instance->vk_instance, &info, NULL, &windowSurface->windowSurface->surface);
if (result != VK_SUCCESS)
return GN_FAILED_TO_ATTACH_WINDOW;
return GN_SUCCESS;
}
#endif
void gnDestroyWindowSurfaceFn(struct gnWindowSurface_t* windowSurface) {
vkDestroySurfaceKHR(windowSurface->instance->instance->vk_instance, windowSurface->windowSurface->surface, NULL);
}
struct gnSurfaceFormat_t* vkGetSurfaceFormats(
struct gnWindowSurface_t* windowSurface, struct gnPhysicalDevice_t device, uint32_t* formatCount
) {
struct gnSurfaceFormat_t* formats = NULL;
vkGetPhysicalDeviceSurfaceFormatsKHR(device.physicalDevice->device, windowSurface->windowSurface->surface, formatCount, NULL);
formats = malloc(sizeof(struct gnSurfaceFormat_t) * *formatCount);
VkSurfaceFormatKHR* vkFormats = malloc(sizeof(VkSurfaceFormatKHR) * *formatCount);;
if (*formatCount > 0) {
vkGetPhysicalDeviceSurfaceFormatsKHR(device.physicalDevice->device, windowSurface->windowSurface->surface, formatCount, vkFormats);
for (int i = 0; i < *formatCount; i++) {
switch (vkFormats[i].format) {
case VK_FORMAT_B8G8R8A8_SRGB: { formats[i].format = GN_FORMAT_BGRA8_SRGB; break; }
default: break;
}
switch (vkFormats[i].colorSpace) {
case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: { formats[i].colorSpace = GN_COLOR_SPACE_SRGB_NONLINEAR; break; }
default: break;
}
}
}
return formats;
}
gnSurfaceDetails gnGetSurfaceDetailsFn(
gnWindowSurfaceHandle windowSurface, gnPhysicalDevice device
) {
gnSurfaceDetails surfaceDetails;
surfaceDetails.formats = vkGetSurfaceFormats(windowSurface, device, &surfaceDetails.formatCount);
VkSurfaceCapabilitiesKHR details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device.physicalDevice->device, windowSurface->windowSurface->surface, &details);
surfaceDetails.minImageCount = details.minImageCount;
surfaceDetails.maxImageCount = details.maxImageCount;
surfaceDetails.minImageSize = (gnUInt2){ details.minImageExtent.width, details.minImageExtent.height };
surfaceDetails.maxImageSize = (gnUInt2){ details.maxImageExtent.width, details.maxImageExtent.height };
surfaceDetails.currentSize = (gnUInt2){ details.currentExtent.width, details.currentExtent.height };
return surfaceDetails;
}
VkFormat vkGryphnFormatToVulkanFormat(gnImageFormat format) {
switch (format) {
case GN_FORMAT_NONE: return VK_FORMAT_UNDEFINED;
case GN_FORMAT_BGRA8_SRGB: return VK_FORMAT_B8G8R8A8_SRGB;
case GN_FORMAT_RGBA8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB;
case GN_FORMAT_D32S8_UINT: return VK_FORMAT_D32_SFLOAT_S8_UINT;
case GN_FORMAT_D24S8_UINT: return VK_FORMAT_D24_UNORM_S8_UINT;
}
}
VkColorSpaceKHR vkGryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace) {
switch (colorSpace) {
case GN_COLOR_SPACE_SRGB_NONLINEAR: { return VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; }
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <core/window_surface/gryphn_surface.h>
#include <vulkan/vulkan.h>
typedef struct gnPlatformWindowSurface_t {
VkSurfaceKHR surface;
} gnPlatformWindowSurface;
VkFormat vkGryphnFormatToVulkanFormat(gnImageFormat format);
VkColorSpaceKHR vkGryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace);

View File

@@ -0,0 +1,27 @@
#ifdef GN_PLATFORM_MACOS
#include "vulkan_surface.h"
#include "core/window_surface/gryphn_surface_create_functions.h"
#include "../instance/vulkan_instance.h"
#include <AppKit/AppKit.h>
#include <vulkan/vulkan_metal.h>
#import <Cocoa/Cocoa.h>
#import <QuartzCore/CAMetalLayer.h>
#import <QuartzCore/QuartzCore.h>
#import <Metal/Metal.h>
#include "vulkan/vulkan_metal.h"
gnReturnCode gnCreateMacOSWindowSurfaceFn(gnWindowSurfaceHandle windowSurface, gnInstanceHandle instance, struct gnMacOSWindowSurfaceInfo_t createInfo) {
windowSurface->windowSurface = malloc(sizeof(gnPlatformWindowSurface));
VkMetalSurfaceCreateInfoEXT surfaceCreateInfo = {};
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
surfaceCreateInfo.pNext = NULL;
surfaceCreateInfo.flags = 0;
surfaceCreateInfo.pLayer = createInfo.layer;
VkResult result = vkCreateMetalSurfaceEXT(instance->instance->vk_instance, &surfaceCreateInfo, NULL, &windowSurface->windowSurface->surface);
if (result != VK_SUCCESS)
return GN_FAILED_TO_ATTACH_WINDOW;
return GN_SUCCESS;
}
#endif