rename to projects (DOES NOT COMPILE)
This commit is contained in:
28
projects/apis/metal/CMakeLists.txt
Normal file
28
projects/apis/metal/CMakeLists.txt
Normal 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"
|
||||
)
|
7
projects/apis/metal/src/buffer/metal_buffer.h
Normal file
7
projects/apis/metal/src/buffer/metal_buffer.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
struct gnPlatformBuffer_t {
|
||||
id<MTLBuffer> buffer, stagingBuffer;
|
||||
bool useStagingBuffer;
|
||||
};
|
40
projects/apis/metal/src/buffer/metal_buffer.m
Normal file
40
projects/apis/metal/src/buffer/metal_buffer.m
Normal 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);
|
||||
}
|
@@ -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;
|
@@ -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;
|
||||
}
|
@@ -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;
|
@@ -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);
|
||||
}
|
127
projects/apis/metal/src/commands/commands/metal_commands.m
Normal file
127
projects/apis/metal/src/commands/commands/metal_commands.m
Normal 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)
|
||||
];
|
||||
}
|
||||
}
|
9
projects/apis/metal/src/debugger/metal_debugger.m
Normal file
9
projects/apis/metal/src/debugger/metal_debugger.m
Normal 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) {
|
||||
|
||||
}
|
37
projects/apis/metal/src/devices/metal_output_device.m
Normal file
37
projects/apis/metal/src/devices/metal_output_device.m
Normal 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;
|
||||
// };
|
18
projects/apis/metal/src/devices/metal_output_devices.h
Normal file
18
projects/apis/metal/src/devices/metal_output_devices.h
Normal 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;
|
39
projects/apis/metal/src/devices/metal_physical_device.m
Normal file
39
projects/apis/metal/src/devices/metal_physical_device.m
Normal 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
|
||||
}
|
13
projects/apis/metal/src/framebuffers/metal_framebuffer.h
Normal file
13
projects/apis/metal/src/framebuffers/metal_framebuffer.h
Normal 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);
|
79
projects/apis/metal/src/framebuffers/metal_framebuffer.m
Normal file
79
projects/apis/metal/src/framebuffers/metal_framebuffer.m
Normal 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);
|
||||
}
|
7
projects/apis/metal/src/instance/metal_instance.h
Normal file
7
projects/apis/metal/src/instance/metal_instance.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <Metal/MTLRenderPipeline.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
typedef struct gnPlatformInstance_t {
|
||||
NSView* metalContentView;
|
||||
} gnPlatformInstance;
|
14
projects/apis/metal/src/instance/metal_instance.m
Normal file
14
projects/apis/metal/src/instance/metal_instance.m
Normal 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);
|
||||
}
|
@@ -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;
|
@@ -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);
|
||||
}
|
62
projects/apis/metal/src/present/metal_present.m
Normal file
62
projects/apis/metal/src/present/metal_present.m
Normal 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;
|
||||
}
|
@@ -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;
|
@@ -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);
|
||||
}
|
7
projects/apis/metal/src/renderpass/metal_render_pass.h
Normal file
7
projects/apis/metal/src/renderpass/metal_render_pass.h
Normal 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;
|
13
projects/apis/metal/src/renderpass/metal_render_pass.m
Normal file
13
projects/apis/metal/src/renderpass/metal_render_pass.m
Normal 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);
|
||||
}
|
@@ -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;
|
101
projects/apis/metal/src/shader_module/metal_shader_module.m
Normal file
101
projects/apis/metal/src/shader_module/metal_shader_module.m
Normal 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);
|
||||
}
|
30
projects/apis/metal/src/submit/metal_submit.m
Normal file
30
projects/apis/metal/src/submit/metal_submit.m
Normal 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;
|
||||
}
|
11
projects/apis/metal/src/surface/metal_surface.h
Normal file
11
projects/apis/metal/src/surface/metal_surface.h
Normal 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);
|
43
projects/apis/metal/src/surface/metal_surface.m
Normal file
43
projects/apis/metal/src/surface/metal_surface.m
Normal 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); }
|
||||
}
|
||||
}
|
8
projects/apis/metal/src/sync/fence/metal_fence.h
Normal file
8
projects/apis/metal/src/sync/fence/metal_fence.h
Normal 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;
|
33
projects/apis/metal/src/sync/fence/metal_fence.m
Normal file
33
projects/apis/metal/src/sync/fence/metal_fence.m
Normal 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);
|
||||
}
|
8
projects/apis/metal/src/sync/semaphore/metal_semaphore.h
Normal file
8
projects/apis/metal/src/sync/semaphore/metal_semaphore.h
Normal 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;
|
13
projects/apis/metal/src/sync/semaphore/metal_semaphore.m
Normal file
13
projects/apis/metal/src/sync/semaphore/metal_semaphore.m
Normal 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);
|
||||
}
|
7
projects/apis/metal/src/texture/metal_texture.h
Normal file
7
projects/apis/metal/src/texture/metal_texture.h
Normal 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;
|
7
projects/apis/metal/src/uniforms/metal_uniform.c
Normal file
7
projects/apis/metal/src/uniforms/metal_uniform.c
Normal 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));
|
||||
}
|
8
projects/apis/metal/src/uniforms/metal_uniform.h
Normal file
8
projects/apis/metal/src/uniforms/metal_uniform.h
Normal 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;
|
19
projects/apis/metal/src/uniforms/metal_uniform_pool.c
Normal file
19
projects/apis/metal/src/uniforms/metal_uniform_pool.c
Normal 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) { }
|
6
projects/apis/metal/src/uniforms/metal_uniform_pool.h
Normal file
6
projects/apis/metal/src/uniforms/metal_uniform_pool.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <core/uniforms/gryphn_uniform_pool.h>
|
||||
|
||||
struct gnPlatformUniformPool_t {
|
||||
};
|
43
projects/apis/vulkan/CMakeLists.txt
Normal file
43
projects/apis/vulkan/CMakeLists.txt
Normal 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()
|
132
projects/apis/vulkan/src/buffers/vulkan_buffer.c
Normal file
132
projects/apis/vulkan/src/buffers/vulkan_buffer.c
Normal 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, ©Region);
|
||||
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);
|
||||
}
|
24
projects/apis/vulkan/src/buffers/vulkan_buffer.h
Normal file
24
projects/apis/vulkan/src/buffers/vulkan_buffer.h
Normal 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);
|
@@ -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);
|
||||
}
|
@@ -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);
|
@@ -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);
|
||||
}
|
@@ -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;
|
97
projects/apis/vulkan/src/commands/commands/vulkan_commands.c
Normal file
97
projects/apis/vulkan/src/commands/commands/vulkan_commands.c
Normal 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
|
||||
);
|
||||
}
|
158
projects/apis/vulkan/src/debugger/vulkan_debugger.c
Normal file
158
projects/apis/vulkan/src/debugger/vulkan_debugger.c
Normal 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);
|
||||
// }
|
9
projects/apis/vulkan/src/debugger/vulkan_debugger.h
Normal file
9
projects/apis/vulkan/src/debugger/vulkan_debugger.h
Normal 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);
|
34
projects/apis/vulkan/src/framebuffers/vulkan_framebuffer.c
Normal file
34
projects/apis/vulkan/src/framebuffers/vulkan_framebuffer.c
Normal 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);
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "core/framebuffer/gryphn_framebuffer.h"
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct gnPlatformFramebuffer_t {
|
||||
VkFramebuffer framebuffer;
|
||||
} gnPlatformFramebuffer;
|
136
projects/apis/vulkan/src/instance/vulkan_instance.c
Normal file
136
projects/apis/vulkan/src/instance/vulkan_instance.c
Normal 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);
|
||||
}
|
18
projects/apis/vulkan/src/instance/vulkan_instance.h
Normal file
18
projects/apis/vulkan/src/instance/vulkan_instance.h
Normal 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;
|
@@ -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;
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
const char* *vkGetGryphnDeviceExtensions(uint32_t* count, VkPhysicalDevice device);
|
109
projects/apis/vulkan/src/output_device/vulkan_output_device.c
Normal file
109
projects/apis/vulkan/src/output_device/vulkan_output_device.c
Normal 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);
|
||||
}
|
@@ -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);
|
@@ -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;
|
||||
}
|
@@ -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;
|
@@ -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);
|
||||
}
|
@@ -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;
|
29
projects/apis/vulkan/src/present/vulkan_present.c
Normal file
29
projects/apis/vulkan/src/present/vulkan_present.c
Normal 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;
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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;
|
@@ -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;
|
||||
}
|
@@ -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
|
||||
);
|
@@ -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);
|
||||
}
|
@@ -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);
|
@@ -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);
|
||||
}
|
@@ -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);
|
50
projects/apis/vulkan/src/submit/vulkan_submit.c
Normal file
50
projects/apis/vulkan/src/submit/vulkan_submit.c
Normal 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;
|
||||
}
|
23
projects/apis/vulkan/src/sync/fence/vulkan_fence.c
Normal file
23
projects/apis/vulkan/src/sync/fence/vulkan_fence.c
Normal 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);
|
||||
}
|
7
projects/apis/vulkan/src/sync/fence/vulkan_fence.h
Normal file
7
projects/apis/vulkan/src/sync/fence/vulkan_fence.h
Normal 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;
|
17
projects/apis/vulkan/src/sync/semaphore/vulkan_semaphore.c
Normal file
17
projects/apis/vulkan/src/sync/semaphore/vulkan_semaphore.c
Normal 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);
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/sync/semaphore/gryphn_semaphore.h"
|
||||
|
||||
typedef struct gnPlatformSemaphore_t {
|
||||
VkSemaphore semaphore;
|
||||
} gnPlatformSemaphore;
|
273
projects/apis/vulkan/src/textures/vulkan_texture.c
Normal file
273
projects/apis/vulkan/src/textures/vulkan_texture.c
Normal 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, ®ion
|
||||
);
|
||||
|
||||
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);
|
||||
}
|
21
projects/apis/vulkan/src/textures/vulkan_texture.h
Normal file
21
projects/apis/vulkan/src/textures/vulkan_texture.h
Normal 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;
|
45
projects/apis/vulkan/src/uniforms/vulkan_uniform.c
Normal file
45
projects/apis/vulkan/src/uniforms/vulkan_uniform.c
Normal 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);
|
||||
}
|
7
projects/apis/vulkan/src/uniforms/vulkan_uniform.h
Normal file
7
projects/apis/vulkan/src/uniforms/vulkan_uniform.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "core/uniforms/gryphn_uniform.h"
|
||||
|
||||
typedef struct gnPlatformUniform_t {
|
||||
VkDescriptorSet set;
|
||||
} gnPlatformUniform;
|
39
projects/apis/vulkan/src/uniforms/vulkan_uniform_layout.c
Normal file
39
projects/apis/vulkan/src/uniforms/vulkan_uniform_layout.c
Normal 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;
|
||||
}
|
@@ -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);
|
136
projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.c
Normal file
136
projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.c
Normal 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,
|
||||
¤tPool->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(¤tPool->layouts, allocInfo.setCount);
|
||||
|
||||
for (int i = 0; i < allocInfo.setCount; i++) {
|
||||
VkDescriptorSetLayoutArrayListAdd(
|
||||
¤tPool->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 = ¤tPool->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);
|
||||
}
|
||||
}
|
15
projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.h
Normal file
15
projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.h
Normal 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;
|
||||
};
|
124
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.c
Normal file
124
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.c
Normal 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; }
|
||||
}
|
||||
}
|
10
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.h
Normal file
10
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.h
Normal 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);
|
27
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.m
Normal file
27
projects/apis/vulkan/src/vulkan_surface/vulkan_surface.m
Normal 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
|
15
projects/core/CMakeLists.txt
Normal file
15
projects/core/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS on)
|
||||
project(GryphnCore)
|
||||
add_compile_definitions(GN_REVEAL_IMPL)
|
||||
|
||||
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS "src/*.c")
|
||||
if(APPLE)
|
||||
file(GLOB_RECURSE METAL_FILES CONFIGURE_DEPENDS "src/*.m")
|
||||
endif()
|
||||
add_library(GryphnCore ${SOURCE_FILES} ${METAL_FILES})
|
||||
|
||||
target_include_directories(GryphnCore PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../)
|
||||
target_include_directories(GryphnCore PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/)
|
||||
target_include_directories(GryphnCore PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../include/)
|
||||
target_include_directories(GryphnCore PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../utils)
|
||||
target_include_directories(GryphnCore PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../utils)
|
20
projects/core/src/buffers/gryphn_buffer.c
Normal file
20
projects/core/src/buffers/gryphn_buffer.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "gryphn_buffer.h"
|
||||
#include "output_device/gryphn_output_device.h"
|
||||
#include "gryphn_platform_functions.h"
|
||||
|
||||
gnReturnCode gnCreateBuffer(gnBufferHandle* buffer, gnOutputDeviceHandle device, gnBufferInfo info) {
|
||||
*buffer = malloc(sizeof(struct gnBuffer_t));
|
||||
(*buffer)->device = device;
|
||||
(*buffer)->info = info;
|
||||
return device->deviceFunctions->_gnCreateBuffer(*buffer, device, info);
|
||||
}
|
||||
void gnBufferData(gnBufferHandle buffer, size_t dataSize, void* data) {
|
||||
buffer->device->deviceFunctions->_gnBufferData(buffer, dataSize, data);
|
||||
}
|
||||
void* gnMapBuffer(gnBufferHandle buffer) {
|
||||
if (buffer->info.usage == GN_STATIC_DRAW) return NULL;
|
||||
return buffer->device->deviceFunctions->_gnMapBuffer(buffer);
|
||||
}
|
||||
void gnDestroyBuffer(gnBufferHandle buffer) {
|
||||
buffer->device->deviceFunctions->_gnDestroyBuffer(buffer);
|
||||
}
|
41
projects/core/src/buffers/gryphn_buffer.h
Normal file
41
projects/core/src/buffers/gryphn_buffer.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include "stdlib.h"
|
||||
#include "utils/gryphn_error_code.h"
|
||||
#include "utils/lists/gryphn_array_list.h"
|
||||
#include <gryphn_handles.h>
|
||||
|
||||
typedef enum gnIndexType {
|
||||
GN_UINT16, GN_UINT32
|
||||
} gnIndexType;
|
||||
|
||||
typedef enum gnBufferType {
|
||||
GN_VERTEX_BUFFER = 0x00000001,
|
||||
GN_INDEX_BUFFER = 0x00000002,
|
||||
GN_UNIFORM_BUFFER = 0x00000004
|
||||
} gnBufferType;
|
||||
|
||||
typedef enum gnBufferUsage {
|
||||
GN_STATIC_DRAW, GN_DYNAMIC_DRAW
|
||||
} gnBufferUsage; // i love that OpenGL does this so im stealing it
|
||||
|
||||
typedef struct gnBufferInfo {
|
||||
size_t size;
|
||||
gnBufferType type;
|
||||
gnBufferUsage usage;
|
||||
} gnBufferInfo;
|
||||
|
||||
#ifdef GN_REVEAL_IMPL
|
||||
struct gnBuffer_t {
|
||||
struct gnPlatformBuffer_t* buffer;
|
||||
gnDeviceHandle device;
|
||||
gnBufferInfo info;
|
||||
};
|
||||
#endif
|
||||
typedef void* gnBufferMemory;
|
||||
GN_ARRAY_LIST(gnBuffer);
|
||||
GN_ARRAY_LIST(gnBufferMemory);
|
||||
|
||||
gnReturnCode gnCreateBuffer(gnBufferHandle* buffer, gnOutputDeviceHandle device, gnBufferInfo info);
|
||||
void gnBufferData(gnBufferHandle buffer, size_t dataSize, gnBufferMemory data);
|
||||
gnBufferMemory gnMapBuffer(gnBufferHandle buffer);
|
||||
void gnDestroyBuffer(gnBufferHandle buffer);
|
@@ -0,0 +1,30 @@
|
||||
#include "gryphn_command_buffer.h"
|
||||
#include "gryphn_platform_functions.h"
|
||||
|
||||
gnReturnCode gnCommandPoolAllocateCommandBuffersFromPointer(gnCommandBufferHandle* buffers, uint32_t count, gnCommandPoolHandle commandPool) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
buffers[i] = malloc(sizeof(struct gnCommandBuffer_t));
|
||||
buffers[i]->commandPool = commandPool;
|
||||
}
|
||||
return commandPool->commandFunctions->_gnCommandPoolAllocateCommandBuffers(buffers, count, commandPool);
|
||||
}
|
||||
|
||||
gnReturnCode gnCommandPoolAllocateCommandBuffersFromList(gnCommandBufferArrayList buffers, uint32_t count, gnCommandPoolHandle commandPool) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
buffers.data[i] = malloc(sizeof(struct gnCommandBuffer_t));
|
||||
buffers.data[i]->commandPool = commandPool;
|
||||
}
|
||||
return gnCommandPoolAllocateCommandBuffersFromPointer(buffers.data, count, commandPool);
|
||||
}
|
||||
|
||||
void gnResetCommandBuffer(gnCommandBufferHandle commandBuffer) {
|
||||
commandBuffer->commandPool->commandFunctions->_gnResetCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
gnReturnCode gnBeginCommandBuffer(gnCommandBufferHandle commandBuffer) {
|
||||
return commandBuffer->commandPool->commandFunctions->_gnBeginCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
gnReturnCode gnEndCommandBuffer(gnCommandBufferHandle commandBuffer) {
|
||||
return commandBuffer->commandPool->commandFunctions->_gnEndCommandBuffer(commandBuffer);
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "stdint.h"
|
||||
#include "utils/gryphn_error_code.h"
|
||||
#include "utils/lists/gryphn_array_list.h"
|
||||
#include "gryphn_handles.h"
|
||||
|
||||
#ifdef GN_REVEAL_IMPL
|
||||
struct gnCommandBuffer_t {
|
||||
struct gnPlatformCommandBuffer_t* commandBuffer;
|
||||
gnCommandPoolHandle commandPool;
|
||||
};
|
||||
#endif
|
||||
|
||||
GN_ARRAY_LIST(gnCommandBuffer);
|
||||
|
||||
gnReturnCode gnCommandPoolAllocateCommandBuffersFromPointer(gnCommandBufferHandle* buffers, uint32_t count, gnCommandPoolHandle commandPool);
|
||||
// will reserve the space for ${count} number of elements
|
||||
gnReturnCode gnCommandPoolAllocateCommandBuffersFromList(gnCommandBufferArrayList buffers, uint32_t count, gnCommandPoolHandle commandPool);
|
||||
|
||||
#define gnCommandPoolAllocateCommandBuffers(buffers, count, commandPool) \
|
||||
_Generic((buffers), \
|
||||
gnCommandBufferArrayList: gnCommandPoolAllocateCommandBuffersFromList, \
|
||||
default: gnCommandPoolAllocateCommandBuffersFromPointer \
|
||||
)(buffers, count, commandPool)
|
||||
|
||||
void gnResetCommandBuffer(gnCommandBufferHandle commandBuffer);
|
||||
gnReturnCode gnBeginCommandBuffer(gnCommandBufferHandle commandBuffer);
|
||||
gnReturnCode gnEndCommandBuffer(gnCommandBufferHandle commandBuffer);
|
20
projects/core/src/command/command_pool/gryphn_command_pool.c
Normal file
20
projects/core/src/command/command_pool/gryphn_command_pool.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "gryphn_command_pool.h"
|
||||
#include "gryphn_platform_functions.h"
|
||||
#include "instance/init/gryphn_init.h"
|
||||
|
||||
gnReturnCode gnCreateCommandPool(gnCommandPoolHandle* commandPool, gnOutputDeviceHandle device, struct gnCommandPoolInfo_t info) {
|
||||
*commandPool = malloc(sizeof(struct gnCommandPool_t));
|
||||
if (!device->instance->loadCommandFunctions) {
|
||||
device->instance->commandFunctions = malloc(sizeof(struct gnCommandFunctions_t));
|
||||
gnLoadCommandFunctions(device->instance->dynamicLib, device->instance->commandFunctions);
|
||||
device->instance->loadCommandFunctions = gnTrue;
|
||||
}
|
||||
(*commandPool)->commandFunctions = device->instance->commandFunctions;
|
||||
|
||||
(*commandPool)->device = device;
|
||||
return device->deviceFunctions->_gnCreateCommandPool((*commandPool), device, info);
|
||||
}
|
||||
|
||||
void gnDestroyCommandPool(gnCommandPoolHandle commandPool) {
|
||||
commandPool->device->deviceFunctions->_gnDestroyCommandPool(commandPool);
|
||||
}
|
19
projects/core/src/command/command_pool/gryphn_command_pool.h
Normal file
19
projects/core/src/command/command_pool/gryphn_command_pool.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "stdint.h"
|
||||
#include <utils/gryphn_error_code.h>
|
||||
#include "gryphn_handles.h"
|
||||
|
||||
typedef struct gnCommandPoolInfo_t {
|
||||
uint32_t queueIndex;
|
||||
} gnCommandPoolInfo;
|
||||
|
||||
#ifdef GN_REVEAL_IMPL
|
||||
struct gnCommandPool_t {
|
||||
struct gnPlatformCommandPool_t* commandPool;
|
||||
struct gnCommandFunctions_t* commandFunctions;
|
||||
struct gnOutputDevice_t* device;
|
||||
};
|
||||
#endif
|
||||
|
||||
gnReturnCode gnCreateCommandPool(gnCommandPoolHandle* commandPool, gnOutputDeviceHandle device, struct gnCommandPoolInfo_t info);
|
||||
void gnDestroyCommandPool(gnCommandPoolHandle commandPool);
|
36
projects/core/src/command/commands/gryphn_command.c
Normal file
36
projects/core/src/command/commands/gryphn_command.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "gryphn_command.h"
|
||||
#include "command/command_buffer/gryphn_command_buffer.h"
|
||||
#include "command/command_pool/gryphn_command_pool.h"
|
||||
#include "gryphn_platform_functions.h"
|
||||
|
||||
void gnCommandBeginRenderPass(struct gnCommandBuffer_t* buffer, struct gnRenderPassInfo_t passInfo) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandBeginRenderPass(buffer, passInfo);
|
||||
}
|
||||
void gnCommandEndRenderPass(struct gnCommandBuffer_t* buffer) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandEndRenderPass(buffer);
|
||||
}
|
||||
|
||||
void gnCommandBindGraphicsPipeline(struct gnCommandBuffer_t* buffer, struct gnGraphicsPipeline_t* graphicsPipeline) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandBindGraphicsPipeline(buffer, graphicsPipeline);
|
||||
}
|
||||
void gnCommandSetViewport(struct gnCommandBuffer_t* buffer, struct gnViewport_t viewport) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandSetViewport(buffer, viewport);
|
||||
}
|
||||
void gnCommandSetScissor(struct gnCommandBuffer_t* buffer, struct gnScissor_t scissor) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandSetScissor(buffer, scissor);
|
||||
}
|
||||
void gnCommandBindUniform(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t set) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandBindUniform(buffer, uniform, set);
|
||||
}
|
||||
void gnCommandBindBuffer(gnCommandBufferHandle buffer, gnBufferHandle bufferToBind, gnBufferType type) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandBindBuffer(buffer, bufferToBind, type);
|
||||
}
|
||||
void gnCommandPushConstant(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandPushConstant(buffer, layout, data);
|
||||
}
|
||||
void gnCommandDraw(struct gnCommandBuffer_t* buffer, int vertexCount, int firstVertex, int instanceCount, int firstInstance) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandDraw(buffer, vertexCount, firstVertex, instanceCount, firstInstance);
|
||||
}
|
||||
void gnCommandDrawIndexed(gnCommandBufferHandle buffer, gnIndexType type, int indexCount, int firstIndex, int vertexOffset, int instanceCount, int firstInstance) {
|
||||
buffer->commandPool->commandFunctions->_gnCommandDrawIndexed(buffer, type, indexCount, firstIndex, vertexOffset, instanceCount, firstInstance);
|
||||
}
|
18
projects/core/src/command/commands/gryphn_command.h
Normal file
18
projects/core/src/command/commands/gryphn_command.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "gryphn_handles.h"
|
||||
|
||||
#include "renderpass/gryphn_render_pass.h"
|
||||
void gnCommandBeginRenderPass(gnCommandBufferHandle buffer, gnRenderPassInfo passInfo);
|
||||
void gnCommandEndRenderPass(gnCommandBufferHandle buffer);
|
||||
|
||||
#include "pipelines/graphics_pipeline/gryphn_graphics_pipeline.h"
|
||||
void gnCommandBindGraphicsPipeline(gnCommandBufferHandle buffer, gnGraphicsPipelineHandle graphicsPipeline);
|
||||
void gnCommandSetViewport(gnCommandBufferHandle buffer, gnViewport viewport);
|
||||
void gnCommandSetScissor(gnCommandBufferHandle buffer, gnScissor scissor);
|
||||
void gnCommandBindUniform(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t set);
|
||||
void gnCommandPushConstant(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data);
|
||||
|
||||
#include "buffers/gryphn_buffer.h"
|
||||
void gnCommandBindBuffer(gnCommandBufferHandle buffer, gnBufferHandle bufferToBind, gnBufferType type);
|
||||
|
||||
void gnCommandDraw(gnCommandBufferHandle buffer, int vertexCount, int firstVertex, int instanceCount, int firstInstance);
|
||||
void gnCommandDrawIndexed(gnCommandBufferHandle buffer, gnIndexType type, int indexCount, int firstIndex, int vertexOffset, int instanceCount, int firstInstance);
|
9
projects/core/src/debugger/gryphn_debugger.c
Normal file
9
projects/core/src/debugger/gryphn_debugger.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "gryphn_debugger.h"
|
||||
#include <gryphn_platform_functions.h>
|
||||
|
||||
gnReturnCode gnCreateDebugger(gnDebuggerHandle* debugger, const gnDebuggerInfo info) {
|
||||
*debugger = malloc(sizeof(struct gnDebugger_t));
|
||||
(*debugger)->info = info;
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
void gnDestroyDebugger(gnDebuggerHandle debugger) {}
|
66
projects/core/src/debugger/gryphn_debugger.h
Normal file
66
projects/core/src/debugger/gryphn_debugger.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include "stdint.h"
|
||||
#include "utils/gryphn_string.h"
|
||||
#include "utils/gryphn_error_code.h"
|
||||
#include "gryphn_handles.h"
|
||||
|
||||
struct gnPlatformDebugger_t;
|
||||
|
||||
typedef enum gnMessageSeverity_e {
|
||||
GN_MESSAGE_VERBOSE = 0x00000001,
|
||||
GN_MESSAGE_INFO = 0x00000002,
|
||||
GN_MESSAGE_WARNING = 0x00000004,
|
||||
GN_MESSAGE_ERROR = 0x00000008,
|
||||
} gnMessageSeverity;
|
||||
|
||||
typedef enum gnMessageType_e {
|
||||
GN_DEBUG_MESSAGE_GENERAL = 0x00000001,
|
||||
GN_DEBUG_MESSAGE_VALIDATION = 0x00000002,
|
||||
GN_DEBUG_MESSAGE_PERFORMANCE = 0x00000004,
|
||||
} gnMessageType;
|
||||
|
||||
typedef struct gnMessageData {
|
||||
gnString message;
|
||||
} gnMessageData;
|
||||
|
||||
typedef gnBool (*gnDebuggerCallback)(
|
||||
gnMessageSeverity messageSeverity,
|
||||
gnMessageType messageType,
|
||||
gnMessageData messageData,
|
||||
void* userData);
|
||||
|
||||
typedef enum gnDebuggerLayer {
|
||||
GN_DEBUGGER_LAYER_PLATFORM, // enable platform (vulkan validation) layers
|
||||
GN_DEBUGGER_LAYER_FUNCTIONS // enable the checks on every function
|
||||
} gnDebuggerLayer;
|
||||
|
||||
typedef struct gnDebuggerInfo {
|
||||
gnDebuggerCallback callback;
|
||||
void* userData;
|
||||
|
||||
uint32_t layerCount;
|
||||
gnDebuggerLayer* layers;
|
||||
} gnDebuggerInfo;
|
||||
|
||||
#ifdef GN_REVEAL_IMPL
|
||||
|
||||
struct gnDebugger_t {
|
||||
gnDebuggerInfo info;
|
||||
};
|
||||
#endif
|
||||
|
||||
gnReturnCode gnCreateDebugger(gnDebuggerHandle* debugger, const gnDebuggerInfo info);
|
||||
void gnDestroyDebugger(gnDebuggerHandle debugger);
|
||||
|
||||
#ifdef GN_REVEAL_IMPL
|
||||
static void gnDebuggerSetErrorMessage(gnDebuggerHandle debugger, gnMessageData data) {
|
||||
if (debugger == NULL) return;
|
||||
|
||||
debugger->info.callback(
|
||||
GN_MESSAGE_ERROR,
|
||||
GN_DEBUG_MESSAGE_VALIDATION,
|
||||
data,
|
||||
debugger->info.userData
|
||||
);
|
||||
}
|
||||
#endif
|
12
projects/core/src/framebuffer/gryphn_framebuffer.c
Normal file
12
projects/core/src/framebuffer/gryphn_framebuffer.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "gryphn_framebuffer.h"
|
||||
#include "gryphn_platform_functions.h"
|
||||
|
||||
gnReturnCode gnCreateFramebuffer(gnFramebuffer* framebuffer, gnOutputDeviceHandle device, gnFramebufferInfo framebufferInfo) {
|
||||
*framebuffer = malloc(sizeof(struct gnFramebuffer_t));
|
||||
(*framebuffer)->device = device;
|
||||
return device->deviceFunctions->_gnCreateFramebuffer(*framebuffer, device, framebufferInfo);
|
||||
}
|
||||
|
||||
void gnDestroyFramebuffer(gnFramebuffer framebuffer) {
|
||||
framebuffer->device->deviceFunctions->_gnDestroyFramebuffer(framebuffer);
|
||||
}
|
21
projects/core/src/framebuffer/gryphn_framebuffer.h
Normal file
21
projects/core/src/framebuffer/gryphn_framebuffer.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "utils/math/gryphn_vec2.h"
|
||||
#include "utils/gryphn_error_code.h"
|
||||
#include "gryphn_handles.h"
|
||||
|
||||
typedef struct gnFramebufferInfo_t {
|
||||
gnRenderPassDescriptorHandle renderPassDescriptor;
|
||||
uint32_t attachmentCount;
|
||||
gnTextureHandle* attachments;
|
||||
gnUInt2 size;
|
||||
} gnFramebufferInfo;
|
||||
|
||||
#ifdef GN_REVEAL_IMPL
|
||||
struct gnFramebuffer_t {
|
||||
struct gnPlatformFramebuffer_t* framebuffer;
|
||||
gnOutputDeviceHandle device;
|
||||
};
|
||||
#endif
|
||||
|
||||
gnReturnCode gnCreateFramebuffer(gnFramebuffer* framebuffer, gnOutputDeviceHandle device, gnFramebufferInfo framebufferInfo);
|
||||
void gnDestroyFramebuffer(gnFramebuffer framebuffer);
|
28
projects/core/src/gryphn_handles.h
Normal file
28
projects/core/src/gryphn_handles.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#define GN_HANDLE(type) \
|
||||
typedef struct type##_t* type##Handle; \
|
||||
typedef struct type##_t* type
|
||||
|
||||
#define GN_HANDLE_ALIAS(handle, alias) \
|
||||
typedef struct handle##_t* alias##Handle; \
|
||||
typedef struct handle##_t* alias
|
||||
|
||||
GN_HANDLE(gnInstance);
|
||||
GN_HANDLE(gnDebugger);
|
||||
GN_HANDLE(gnWindowSurface);
|
||||
GN_HANDLE(gnPresentationQueue);
|
||||
GN_HANDLE(gnTexture);
|
||||
GN_HANDLE(gnRenderPassDescriptor);
|
||||
GN_HANDLE(gnOutputDevice);
|
||||
GN_HANDLE_ALIAS(gnOutputDevice, gnDevice);
|
||||
GN_HANDLE(gnShaderModule);
|
||||
GN_HANDLE(gnGraphicsPipeline);
|
||||
GN_HANDLE(gnCommandPool);
|
||||
GN_HANDLE(gnCommandBuffer);
|
||||
GN_HANDLE(gnSemaphore);
|
||||
GN_HANDLE(gnFence);
|
||||
GN_HANDLE(gnFramebuffer);
|
||||
GN_HANDLE(gnBuffer);
|
||||
GN_HANDLE(gnUniformPool);
|
||||
GN_HANDLE(gnUniform);
|
126
projects/core/src/gryphn_platform_functions.h
Normal file
126
projects/core/src/gryphn_platform_functions.h
Normal file
@@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
// theoretically you could have multible gryphn instances running in one application,
|
||||
// why I dont know
|
||||
#include "instance/gryphn_instance.h"
|
||||
#include <debugger/gryphn_debugger.h>
|
||||
#include "output_device/gryphn_physical_output_device.h"
|
||||
#include "output_device/gryphn_output_device.h"
|
||||
#include "window_surface/gryphn_surface.h"
|
||||
#include <window_surface/gryphn_surface_create_functions.h>
|
||||
#include "shader_module/gryphn_shader_module.h"
|
||||
#include "renderpass/gryphn_render_pass_descriptor.h"
|
||||
#include "pipelines/graphics_pipeline/gryphn_graphics_pipeline.h"
|
||||
#include "framebuffer/gryphn_framebuffer.h"
|
||||
#include "command/command_pool/gryphn_command_pool.h"
|
||||
#include "renderpass/gryphn_render_pass.h"
|
||||
#include "submit/gryphn_submit.h"
|
||||
#include "present/gryphn_present.h"
|
||||
#include "buffers/gryphn_buffer.h"
|
||||
#include "uniforms/gryphn_uniform.h"
|
||||
#include "textures/gryphn_texture.h"
|
||||
#include "uniforms/gryphn_uniform_pool.h"
|
||||
|
||||
typedef struct gnInstanceFunctions {
|
||||
gnReturnCode (*_gnCreateInstance)(gnInstanceHandle instance, gnInstanceInfo info);
|
||||
void (*_gnDestroyInstance)(gnInstanceHandle instance);
|
||||
|
||||
gnPhysicalDevice* (*_gnGetPhysicalDevices)(gnInstanceHandle instance, uint32_t* count);
|
||||
gnBool (*_gnQueueCanPresentToSurface)(const gnPhysicalDevice device, uint32_t queueIndex, const gnWindowSurfaceHandle windowSurface);
|
||||
|
||||
gnReturnCode (*_gnCreateOutputDevice)(gnOutputDeviceHandle device, gnInstanceHandle instance, struct gnOutputDeviceInfo_t deviceInfo);
|
||||
void (*_gnDestroyOutputDevice)(gnOutputDeviceHandle device);
|
||||
|
||||
|
||||
#ifdef GN_PLATFORM_LINUX
|
||||
#ifdef GN_WINDOW_X11
|
||||
gnReturnCode (*_gnCreateX11WindowSurface)(gnWindowSurfaceHandle windowSurface, gnInstanceHandle instance, gnX11WindowSurfaceInfo createInfo);
|
||||
#endif
|
||||
#ifdef GN_WINDOW_WAYLAND
|
||||
gnReturnCode (*_gnCreateWaylandWindowSurface)(gnWindowSurfaceHandle windowSurface, gnInstanceHandle instance, struct gnWaylandWindowSurfaceInfo_t createInfo);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GN_PLATFORM_WIN32
|
||||
gnReturnCode (*_gnCreateWin32WindowSurface)(gnWindowSurfaceHandle windowSurface, gnInstanceHandle instance, struct gnWin32WindowSurfaceInfo_t createInfo);
|
||||
#endif
|
||||
|
||||
#ifdef GN_PLATFORM_MACOS
|
||||
gnReturnCode (*_gnCreateMacOSWindowSurface)(gnWindowSurfaceHandle windowSurface, gnInstanceHandle instance, struct gnMacOSWindowSurfaceInfo_t createInfo);
|
||||
#endif
|
||||
|
||||
void (*_gnDestroyWindowSurface)(gnWindowSurfaceHandle windowSurface);
|
||||
gnSurfaceDetails (*_gnGetSurfaceDetails)(gnWindowSurfaceHandle windowSurface, struct gnPhysicalDevice_t device);
|
||||
} gnInstanceFunctions;
|
||||
|
||||
#include "presentation_queue/gryphn_presentation_queue.h"
|
||||
typedef struct gnDeviceFunctions_t {
|
||||
gnReturnCode (*_gnCreatePresentationQueue)(gnPresentationQueueHandle presentationQueue, const gnOutputDeviceHandle device, gnPresentationQueueInfo presentationInfo);
|
||||
gnReturnCode (*_gnPresentationQueueGetImage)(gnPresentationQueueHandle presentationQueue, uint64_t timeout, gnSemaphoreHandle semaphore, uint32_t* imageIndex);
|
||||
void (*_gnDestroyPresentationQueue)(gnPresentationQueueHandle presentationQueue);
|
||||
|
||||
gnReturnCode (*_gnCreateShaderModule)(gnShaderModuleHandle module, gnOutputDeviceHandle device, gnShaderModuleInfo shaderModuleInfo);
|
||||
void (*_gnDestroyShaderModule)(gnShaderModuleHandle module);
|
||||
|
||||
gnReturnCode (*_gnCreateRenderPassDescriptor)(gnRenderPassDescriptorHandle renderPass, gnOutputDeviceHandle device, gnRenderPassDescriptorInfo info);
|
||||
void (*_gnDestroyRenderPassDescriptor)(gnRenderPassDescriptorHandle renderPass);
|
||||
|
||||
gnReturnCode (*_gnCreateGraphicsPipeline)(gnGraphicsPipelineHandle pipeline, gnOutputDeviceHandle device, gnGraphicsPipelineInfo pipelineInfo);
|
||||
void (*_gnDestroyGraphicsPipeline)(gnGraphicsPipelineHandle pipeline);
|
||||
|
||||
gnReturnCode (*_gnCreateFramebuffer)(gnFramebuffer framebuffer, gnOutputDeviceHandle device, gnFramebufferInfo framebufferInfo);
|
||||
void (*_gnDestroyFramebuffer)(gnFramebuffer framebuffer);
|
||||
|
||||
gnReturnCode (*_gnCreateCommandPool)(gnCommandPoolHandle commandPool, gnOutputDeviceHandle device, gnCommandPoolInfo info);
|
||||
void (*_gnDestroyCommandPool)(gnCommandPoolHandle commandPool);
|
||||
|
||||
gnReturnCode (*_gnCreateSemaphore)(gnSemaphoreHandle semaphore, gnOutputDeviceHandle device);
|
||||
void (*_gnDestroySemaphore)(gnSemaphoreHandle semaphore);
|
||||
|
||||
gnReturnCode (*_gnCreateBuffer)(gnBufferHandle buffer, gnDeviceHandle device, gnBufferInfo info);
|
||||
void (*_gnBufferData)(gnBufferHandle buffer, size_t size, void* data);
|
||||
void* (*_gnMapBuffer)(gnBufferHandle buffer);
|
||||
void (*_gnDestroyBuffer)(gnBufferHandle buffer);
|
||||
|
||||
gnReturnCode (*_gnCreateUniformPool)(gnUniformPool pool, gnDeviceHandle device);
|
||||
gnUniform* (*_gnUniformPoolAllocateUniforms)(gnUniformPool pool, gnUniformAllocationInfo allocInfo);
|
||||
void (*_gnDestroyUniformPool)(gnUniformPool pool);
|
||||
|
||||
void (*_gnUpdateBufferUniform)(gnUniform uniform, gnBufferUniformInfo* bufferInfo);
|
||||
void (*_gnUpdateImageUniform)(gnUniform uniform, gnImageUniformInfo* imageInfo);
|
||||
|
||||
gnReturnCode (*_gnCreateTexture)(gnTexture texture, gnDevice device, const gnTextureInfo info);
|
||||
void (*_gnTextureData)(gnTextureHandle texture, void* pixelData);
|
||||
void (*_gnDestroyTexture)(gnTexture texture);
|
||||
|
||||
gnReturnCode (*_gnCreateFence)(gnFenceHandle fence, gnOutputDeviceHandle device);
|
||||
void (*_gnSignalFence)(gnFenceHandle fence);
|
||||
void (*_gnWaitForFence)(gnFenceHandle fence, uint64_t timeout);
|
||||
void (*_gnResetFence)(gnFenceHandle fence);
|
||||
void (*_gnDestroyFence)(gnFenceHandle fence);
|
||||
|
||||
gnReturnCode (*_gnSubmit)(gnOutputDeviceHandle device, gnSubmitInfo submit);
|
||||
gnReturnCode (*_gnPresent)(gnOutputDeviceHandle device, gnPresentInfo info);
|
||||
|
||||
void (*_gnWaitForDevice)(gnOutputDeviceHandle device);
|
||||
} gnDeviceFunctions;
|
||||
|
||||
typedef struct gnCommandFunctions_t {
|
||||
gnReturnCode (*_gnCommandPoolAllocateCommandBuffers)(gnCommandBufferHandle* commandBuffers, uint32_t count, gnCommandPoolHandle pool);
|
||||
gnReturnCode (*_gnBeginCommandBuffer)(gnCommandBufferHandle commandBuffer);
|
||||
void (*_gnResetCommandBuffer)(gnCommandBufferHandle commandBuffer);
|
||||
gnReturnCode (*_gnEndCommandBuffer)(gnCommandBufferHandle commandBuffer);
|
||||
|
||||
void (*_gnCommandBeginRenderPass)(gnCommandBufferHandle buffer, gnRenderPassInfo passInfo);
|
||||
void (*_gnCommandEndRenderPass)(gnCommandBufferHandle buffer);
|
||||
|
||||
void (*_gnCommandBindGraphicsPipeline)(gnCommandBufferHandle buffer, gnGraphicsPipelineHandle graphicsPipeline);
|
||||
void (*_gnCommandSetViewport)(gnCommandBufferHandle buffer, gnViewport viewport);
|
||||
void (*_gnCommandSetScissor)(gnCommandBufferHandle buffer, gnScissor scissor);
|
||||
void (*_gnCommandBindUniform)(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t set);
|
||||
void (*_gnCommandPushConstant)(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data);
|
||||
|
||||
void (*_gnCommandBindBuffer)(gnCommandBufferHandle buffer, gnBufferHandle bufferToBind, gnBufferType type);
|
||||
void (*_gnCommandDraw)(gnCommandBufferHandle buffer, int vertexCount, int firstVertex, int instanceCount, int firstInstance);
|
||||
void (*_gnCommandDrawIndexed)(gnCommandBufferHandle buffer, gnIndexType type, int indexCount, int firstIndex, int vertexOffset, int instanceCount, int firstInstance);
|
||||
} gnCommandFunctions;
|
25
projects/core/src/gryphn_rendering_api.h
Normal file
25
projects/core/src/gryphn_rendering_api.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "utils/gryphn_string.h"
|
||||
|
||||
typedef enum gnRenderingAPI_t {
|
||||
GN_RENDERINGAPI_NONE, // idk why im putting this
|
||||
GN_RENDERINGAPI_SOFTWARE, // i kinda wanna write a software renderer
|
||||
|
||||
GN_RENDERINGAPI_OPENGL,
|
||||
GN_RENDERINGAPI_VULKAN,
|
||||
GN_RENDERINGAPI_DIRECTX11, GN_RENDERINGAPI_DIRECTX12,
|
||||
GN_RENDERINGAPI_METAL
|
||||
} gnRenderingAPI;
|
||||
|
||||
static gnString gnRenderingAPIName(gnRenderingAPI api) {
|
||||
switch (api) {
|
||||
case GN_RENDERINGAPI_NONE: return gnCreateString("GN_RENDERINGAPI_NONE");
|
||||
case GN_RENDERINGAPI_SOFTWARE: return gnCreateString("GN_RENDERINGAPI_SOFTWARE");
|
||||
case GN_RENDERINGAPI_OPENGL: return gnCreateString("GN_RENDERINGAPI_OPENGL");
|
||||
case GN_RENDERINGAPI_VULKAN: return gnCreateString("GN_RENDERINGAPI_VULKAN");
|
||||
case GN_RENDERINGAPI_DIRECTX11: return gnCreateString("GN_RENDERINGAPI_DIRECTX11");
|
||||
case GN_RENDERINGAPI_DIRECTX12: return gnCreateString("GN_RENDERINGAPI_DIRECTX12");
|
||||
case GN_RENDERINGAPI_METAL: return gnCreateString("GN_RENDERINGAPI_METAL");
|
||||
}
|
||||
return gnCreateString("GN_INVALID_API");
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user