Compare commits

..

87 Commits

Author SHA1 Message Date
Gregory Wells
5228b6630c finally redo physical device creation 2025-10-01 13:22:52 -04:00
Gregory Wells
5ce0ff3350 fix can device present function 2025-10-01 11:41:08 -04:00
Gregory Wells
63ec31216e forgot to return array of devices 2025-10-01 11:37:40 -04:00
Gregory Wells
ebc6ce724f fix some shit in the validation layers 2025-10-01 09:23:09 -04:00
Gregory Wells
3a5ddac2c5 "fixed" metal impl 2025-10-01 09:21:21 -04:00
Gregory Wells
f93853608c removed a ton of errors 2025-10-01 09:19:43 -04:00
Gregory Wells
481f590234 did some stuff in queue creation for vulkan 2025-10-01 09:18:22 -04:00
Gregory Wells
d79a3c45bf change more words 2025-09-29 23:33:47 -04:00
Gregory Wells
3bf252d582 uhhhh me change word 2025-09-29 23:30:32 -04:00
Gregory Wells
228d75e5ac finish query functions in Vulkan 2025-09-19 10:12:10 -04:00
Gregory Wells
3066f7c2bd check functions for new API 2025-09-19 09:29:55 -04:00
Gregory Wells
427f0ee5b1 reorder code 2025-09-19 09:25:12 -04:00
Gregory Wells
4b981055bd forgot that im stuipd 2025-09-19 09:24:20 -04:00
Gregory Wells
1095e20dc2 update utils version 2025-09-19 09:21:25 -04:00
Gregory Wells
a0450a0351 write all new functions headers 2025-09-19 09:21:18 -04:00
Gregory Wells
c495a7a0e8 change some useless stuff 2025-09-19 09:21:03 -04:00
Gregory Wells
eef7045ac2 feature layer functions 2025-09-17 13:47:23 -04:00
Gregory Wells
7ace503ab0 physical device features function and struct 2025-09-17 13:45:42 -04:00
Gregory Wells
6f278affc6 metal is instance suitable 2025-09-17 13:39:19 -04:00
Gregory Wells
f7e71b77c2 metal physical device properties function 2025-09-17 13:37:50 -04:00
Gregory Wells
88bdbe1e64 don't remember what I changed 2025-09-17 13:26:16 -04:00
Gregory Wells
17b7970aa0 vulkan physical device get properties 2025-09-17 13:24:30 -04:00
Gregory Wells
ef53ffd458 physical device retrieval functions 2025-09-10 13:46:49 -04:00
Gregory Wells
a446d6e75f instance suitability functions 2025-09-10 13:26:18 -04:00
Gregory Wells
0310652abc finish queryDevices function 2025-09-09 09:39:13 -04:00
Gregory Wells
88649174a9 remove old gnGetPhysicalDevices 2025-09-09 09:32:01 -04:00
Gregory Wells
9244b82f79 query metal devices 2025-09-09 09:31:09 -04:00
Gregory Wells
c5297cb17b start to redo physical device model 2025-09-04 14:52:37 -04:00
Gregory Wells
a709ff8808 rename gnPhysicalOutputDevice -> gnPhysicalDevice 2025-08-29 13:55:29 -04:00
Gregory Wells
76a787d48f fix some compile errors 2025-08-29 13:45:08 -04:00
Gregory Wells
1e8855905d update version of utils used 2025-08-29 13:43:25 -04:00
Gregory Wells
809750749a Update README.md 2025-08-20 14:39:18 -04:00
Gregory Wells
4d904557d8 Finish OpenGL support 2025-08-20 14:37:39 -04:00
Gregory Wells
263a8e54fa truly bind all uniforms 2025-08-20 10:52:26 -04:00
Gregory Wells
5422fd8b68 finally get stuff to present 2025-08-20 10:47:50 -04:00
Gregory Wells
0c89bdb791 bind texture uniforms 2025-08-19 22:20:53 -04:00
Gregory Wells
c7ae6532fd update uniforms properly 2025-08-19 22:18:55 -04:00
Gregory Wells
18ec089ebc copy set map to graphics pipeline 2025-08-19 22:18:44 -04:00
Gregory Wells
0c0988b75a redo shader mapping 2025-08-19 22:15:24 -04:00
Gregory Wells
01de997df5 fix buffer binding on OpenGL 2025-08-19 21:43:12 -04:00
Gregory Wells
380c5d056f flip framebuffer 2025-08-19 20:41:45 -04:00
Gregory Wells
f5d7257e66 fix framebuffers being drawn flipped 2025-08-19 17:43:56 -04:00
Gregory Wells
16d2e7b8fc SRGB in OpenGL 2025-08-19 16:50:16 -04:00
Gregory Wells
7f6ec430de finish the most basic rendering pipeline 2025-08-19 16:31:19 -04:00
Gregory Wells
50d8a669b3 draw commands 2025-08-19 08:50:00 -04:00
Gregory Wells
55605b6d5f render 2025-08-19 08:39:29 -04:00
Gregory Wells
740cf1e628 render fullscreen texcoord quad 2025-08-18 23:22:09 -04:00
Gregory Wells
453f7b70db create framebuffer object 2025-08-18 23:02:56 -04:00
Gregory Wells
51bd6e28fa get the first opengl commands to be deferred 2025-08-18 22:30:00 -04:00
Gregory Wells
7b1266281c Run OpenGL commands 2025-08-18 22:09:05 -04:00
Gregory Wells
be2f91e2bb command runner and some tests 2025-08-18 22:00:23 -04:00
Gregory Wells
d1862e3d6f setup basic command runner 2025-08-18 21:42:32 -04:00
Gregory Wells
10cd374731 create graphics pipelines 2025-08-18 21:30:54 -04:00
Gregory Wells
4477c41dc4 render pass in OpenGL 2025-08-18 21:22:22 -04:00
Gregory Wells
916df68f06 OpenGL framebuffer API 2025-08-18 21:13:40 -04:00
Gregory Wells
5db32f367a OpenGL texture API 2025-08-18 20:24:17 -04:00
Gregory Wells
2e02bbf799 fix formats in OpenGL 2025-08-18 20:23:59 -04:00
Gregory Wells
8658c7646f add support for more formats in vulkan 2025-08-18 20:11:41 -04:00
Gregory Wells
c99a4cdb31 fix validation 2025-08-18 16:31:20 -04:00
Gregory Wells
f045793322 just create texture storage 2025-08-18 16:20:33 -04:00
Gregory Wells
5213e0135a fix OpenGL surface format stuff 2025-08-18 01:07:03 -04:00
Gregory Wells
e973386511 implmenent debug callback for OpenGL 2025-08-18 01:06:40 -04:00
Gregory Wells
cb55a7716f copy needed data into renderpass 2025-08-18 00:08:18 -04:00
Gregory Wells
97a70e911d fix glBufferData not being called to set buffer size 2025-08-17 23:37:40 -04:00
Gregory Wells
2f1db4043a remove usless include 2025-08-17 23:28:35 -04:00
Gregory Wells
eb11649a03 dont destroy texture if handle is NULL 2025-08-17 23:28:21 -04:00
Gregory Wells
026fc52d7c uniform API in OpenGL 2025-08-17 23:15:14 -04:00
Gregory Wells
f4e448177b update utils to new repo 2025-08-17 23:00:53 -04:00
Gregory Wells
6c6037b76f Update README.md 2025-08-13 09:28:05 -04:00
Gregory Wells
8fc99079dc command buffer basic lifecycle 2025-08-12 23:56:35 -04:00
Gregory Wells
5b43e3d5be OpenGL buffers 2025-08-12 23:51:04 -04:00
Gregory Wells
362efd8920 command pool and command buffers 2025-08-12 23:34:30 -04:00
Gregory Wells
d48332fdcd write the functions for the command pool/buffers 2025-08-12 23:09:39 -04:00
Gregory Wells
f251613d77 opengl uniform pools 2025-08-12 23:00:22 -04:00
Gregory Wells
bb416aca61 create OpenGL render pass descriptors (faked) 2025-08-12 22:51:51 -04:00
Gregory Wells
9d4dfd85fc finish OpenGL shader creation 2025-08-12 22:49:23 -04:00
Gregory Wells
3f7b0737d7 finish cross compiliation to GLSL 2025-08-12 22:40:06 -04:00
Gregory Wells
23f46385fe actually compile shaders 2025-08-12 22:17:54 -04:00
Gregory Wells
f6484ddde5 make plain cpp 2025-08-12 20:37:36 -04:00
Gregory Wells
adf72d6436 add more stufff to utils 2025-08-12 20:32:00 -04:00
Gregory Wells
c51c29f7a4 create cpp files and functions for OpenGL shaders 2025-08-12 20:27:41 -04:00
Gregory Wells
317ffda9e7 remove warning 2025-08-12 20:27:28 -04:00
Gregory Wells
1846bdbf26 ad sprvcross to OpenGL 2025-08-12 20:19:24 -04:00
Gregory Wells
eeb2896a26 remove format that is unsupported on OpenGL 2025-08-12 20:17:31 -04:00
Gregory Wells
50e84d9802 Update utils 2025-08-12 20:02:57 -04:00
Gregory Wells
45cceff843 update utils 2025-08-12 19:52:25 -04:00
Gregory Wells
dbf90882bf remove utils 2025-08-12 19:52:07 -04:00
96 changed files with 1684 additions and 385 deletions

9
.gitmodules vendored
View File

@@ -1,6 +1,9 @@
[submodule "projects/utils"]
path = projects/utils
url = https://github.com/GregoryWells2007/GryphnUtils.git
[submodule "projects/apis/metal/depends/SPIRV-Cross"]
path = projects/apis/metal/depends/SPIRV-Cross
url = https://github.com/KhronosGroup/SPIRV-Cross.git
[submodule "projects/utils"]
path = projects/utils
url = https://git.astraltech.xyz/AstralTech/Gryphn-Utils.git
[submodule "projects/apis/opengl/depends/SPIRV-Cross"]
path = projects/apis/opengl/depends/SPIRV-Cross
url = https://github.com/KhronosGroup/SPIRV-Cross.git

View File

@@ -9,9 +9,8 @@ Gryphn works to abstract away platform API functions (Vulkan, Metal, D3D11/D3D12
- [x] Metal
- [ ] Direct 3D 11
- [ ] Direct 3D 12
- [ ] OpenGL
- [x] OpenGL
- [ ] Software
* Currently working on the OpenGL backend
# Features
#### Application objects
@@ -63,6 +62,7 @@ Gryphn validation layers are meant to be more specific so there are certain ones
#### Supported layers: <br />
- GN_DEBUGGER_LAYER_PLATFORM, this only does anything on vulkan for the time being, metal currently doesnt allow you to disable its validation but that API has a lot more problems when working with it so im fine with that for the time being, it will do things like enable vulkan validation layers or it will also allow the APIs to load there specific validation layers
- GN_DEBUGGER_LAYER_FUNCTIONS, this is more for my own sake but when I am writing new backends or layers I may tend to forget to implement a specific function so this layer will just check to make sure that every function is loaded properly.
- GN_DEBUGGER_LAYER_ALLOCATORS, this layer will override all Gryphn allocation calls and provide a debug message telling the user an allocation has occured, gryphn will also keep track of all internal allocations and log when certain allocations are not being deallocated, NOTE: these are bugs in Gryphn, where a heap allocated array is never freed unless the programmer has not called the appropriate gnDestroyXXX function.
# Plans
#### 1.0 Spec <br />
Gryphn is getting to the point where I can't keep developing it in the same way I have in the past where I just implement functions and features based on when I need them so slowly over the coming weeks I want to have a true spec written down for every function, that its expected results are, what its functionality does, and just go back and look at every line of code. The spec is going to be based on what I have right now with a few modifacations and also I would like to add more features.
@@ -97,3 +97,8 @@ if (code != GN_SUCCESS) printf("Failed to create XXXX %s\n", gnErrorCodeToCStrin
```
# Known limitations
### OpenGL:
OpenGL currently doesn't support push constants, I have some ideas brainstormed to help me support them but for the time being the max push constant size is set to zero
### Metal:
The device must support argument buffers for metal, at some point I will work on a solition to support both

View File

@@ -3,7 +3,7 @@
// core functionality
#include <core/src/instance/gryphn_instance.h>
#include <core/src/output_device/gryphn_physical_output_device.h>
#include <core/src/output_device/gryphn_physical_device.h>
#include <core/src/window_surface/gryphn_surface.h>
#include <core/src/window_surface/gryphn_surface_create_functions.h>
#include <core/src/presentation_queue/gryphn_presentation_queue.h>

View File

@@ -3,7 +3,7 @@ set(CMAKE_CXX_STANDARD 17)
project(GryphnMetalImpl)
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS
"src/*.c" "src/*.h" "src/*.m" "src/*.mm"
"src/*.c" "src/*.cpp" "src/*.h" "src/*.m" "src/*.mm"
)
file(GLOB_RECURSE LOADER_FILES CONFIGURE_DEPENDS
"loader/*.m"

View File

@@ -6,14 +6,16 @@
gryphnInstanceFunctionLayers metalLoadAPILayer(void) {
return (gryphnInstanceFunctionLayers) {
.createInstance = metalCreateInstance,
.queryDevices = metalQueryDevices,
.destroyInstance = metalDestroyInstance,
.isSuitable = metalIsInstanceSuitable,
.getPhysicalDeviceProperties = metalQueryPhysicalDeviceProperties,
.next = NULL
};
}
gnInstanceFunctions loadMetalInstanceFunctions(void) {
return (gnInstanceFunctions){
._gnGetPhysicalDevices = getMetalDevices,
._gnPhysicalDeviceCanPresentToSurface = metalCanDevicePresent,
._gnCreateOutputDevice = createMetalOutputDevice,
._gnDestroyOutputDevice = destroyMetalOutputDevice,

View File

@@ -1,4 +1,4 @@
#include <output_device/gryphn_physical_output_device.h>
#include <output_device/gryphn_physical_device.h>
#include <Metal/Metal.h>
#include "metal_output_devices.h"
#include "instance/metal_instance.h"
@@ -10,7 +10,7 @@ gnReturnCode createMetalOutputDevice(gnInstanceHandle instance, gnOutputDeviceHa
if (instance == GN_NULL_HANDLE) return GN_INVALID_HANDLE;
outputDevice->outputDevice = malloc(sizeof(gnPlatformOutputDevice));
outputDevice->outputDevice->device = deviceInfo.physicalDevice->physicalDevice->device.retain;
outputDevice->outputDevice->device = ((mtlDevice)deviceInfo.physicalDevice).retain;
outputDevice->outputDevice->transferQueue = outputDevice->outputDevice->device.newCommandQueue;
outputDevice->outputDevice->stagingBuffer = [outputDevice->outputDevice->device newBufferWithLength:(128 * 1024 * 1024) options:MTLResourceStorageModeShared];

View File

@@ -4,9 +4,8 @@
#include <Metal/Metal.h>
#include <MetalKit/MetalKit.h>
struct gnPlatformPhysicalDevice_t {
id<MTLDevice> device;
} gnPlatformPhysicalDevice;
typedef id<MTLDevice> mtlDevice;
gnPhysicalDeviceProperties metalQueryPhysicalDeviceProperties(gnInstance instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* layers);
struct gnPlatformOutputDevice_t {
id<MTLDevice> device;
@@ -24,7 +23,7 @@ struct gnPlatformOutputDevice_t {
} gnPlatformOutputDevice;
gnPhysicalDevice* getMetalDevices(gnInstanceHandle instance, uint32_t* deviceCount);
gnBool metalCanDevicePresent(gnPhysicalDevice device, gnWindowSurface windowSurface);
gnBool metalCanDevicePresent(gnInstance instance, gnPhysicalDevice device, gnWindowSurface windowSurface);
gnReturnCode createMetalOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle outputDevice, gnOutputDeviceInfo deviceInfo);
void waitForMetalDevice(gnOutputDeviceHandle device);

View File

@@ -1,47 +1,29 @@
#include <output_device/gryphn_physical_output_device.h>
#include <output_device/gryphn_physical_device.h>
#include <Metal/Metal.h>
#include "metal_output_devices.h"
#include "window_surface/gryphn_surface.h"
gnPhysicalDevice* getMetalDevices(gnInstanceHandle instance, uint32_t* deviceCount) {
if (instance == GN_NULL_HANDLE) return NULL;
NSArray *devices = MTLCopyAllDevices();
*deviceCount = (uint32_t)[devices count];
gnPhysicalDevice* devicesList = (gnPhysicalDevice*)malloc(sizeof(gnPhysicalDevice) * *deviceCount);
for (uint32_t i = 0; i < *deviceCount; i++) {
devicesList[i] = malloc(sizeof(gnPhysicalOutputDevice_t));
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;
devicesList[i]->features.maxColorSamples = GN_SAMPLE_BIT_1;
if ([device supportsTextureSampleCount:2]) { devicesList[i]->features.maxColorSamples |= GN_SAMPLE_BIT_2; } else {}
if ([device supportsTextureSampleCount:4]) { devicesList[i]->features.maxColorSamples |= GN_SAMPLE_BIT_4; } else {}
if ([device supportsTextureSampleCount:8]) { devicesList[i]->features.maxColorSamples |= GN_SAMPLE_BIT_8; } else {}
if ([device supportsTextureSampleCount:16]) { devicesList[i]->features.maxColorSamples |= GN_SAMPLE_BIT_16; } else {}
if ([device supportsTextureSampleCount:32]) { devicesList[i]->features.maxColorSamples |= GN_SAMPLE_BIT_32; } else {}
devicesList[i]->features.maxDepthSamples = devicesList[i]->features.maxColorSamples;
devicesList[i]->features.maxMemoryAllocations = 0x40000000;
devicesList[i]->features.maxPushConstantSize = 4096;
// i made some educated guesses on these conversions and I dont think they are going to work
// but for now im worried about the MVP
gnPhysicalDeviceType metalDeviceLocationToGryphn(MTLDeviceLocation location) {
switch (location) {
case MTLDeviceLocationBuiltIn: return GN_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
case MTLDeviceLocationSlot: return GN_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
case MTLDeviceLocationExternal: return GN_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
case MTLDeviceLocationUnspecified: return GN_PHYSICAL_DEVICE_TYPE_FAKED_GPU; //very bad if we get here
}
[devices release];
return devicesList;
}
gnBool metalCanDevicePresent(gnPhysicalDevice device, gnWindowSurface windowSurface) {
if (device == GN_NULL_HANDLE || windowSurface == GN_NULL_HANDLE) return GN_FALSE;
gnPhysicalDeviceProperties metalQueryPhysicalDeviceProperties(gnInstance instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* layers) {
return (gnPhysicalDeviceProperties){
.deviceID = ((mtlDevice)device).registryID,
.deviceName = gnCreateString(((mtlDevice)device).name.UTF8String),
.deviceType = metalDeviceLocationToGryphn(((mtlDevice)device).location),
.driverVersion = ((mtlDevice)device).hash // very bad hack, me should not do this
};
}
gnBool metalCanDevicePresent(gnInstance instance, gnPhysicalDevice device, gnWindowSurface windowSurface) {
if (device == GN_NULL_HANDLE || windowSurface == GN_NULL_HANDLE) return GN_FALSE;
return GN_TRUE; // I belive that a window should always be able to present to a surface in metal
}

View File

@@ -8,4 +8,6 @@ typedef struct gnPlatformInstance_t {
} gnPlatformInstance;
gnReturnCode metalCreateInstance(gnInstanceHandle instance, gnInstanceCreateInfo* instanceInfo, gryphnInstanceFunctionLayers* next, gnAllocators* allocators);
gnReturnCode metalQueryDevices(gnInstanceHandle instance, uint32_t* count, gnPhysicalDeviceHandle* devices, gryphnInstanceFunctionLayers* next);
gnBool metalIsInstanceSuitable(gnInstanceHandle instance, gnSuitableField field, gryphnInstanceFunctionLayers* next);
void metalDestroyInstance(gnInstance instance, gryphnInstanceFunctionLayers* next, gnAllocators* allocators);

View File

@@ -8,6 +8,20 @@ gnReturnCode metalCreateInstance(gnInstanceHandle instance, gnInstanceCreateInfo
instance->instance = allocators->malloc(sizeof(gnPlatformInstance), allocators->userData);
return GN_SUCCESS;
}
gnReturnCode metalQueryDevices(gnInstanceHandle instance, uint32_t* count, gnPhysicalDeviceHandle* devices, gryphnInstanceFunctionLayers* next) {
if (instance == GN_NULL_HANDLE) return GN_INVALID_HANDLE;
NSArray *metalDevices = MTLCopyAllDevices();
*count = (uint32_t)[metalDevices count];
if (devices == NULL) return GN_SUCCESS;
for (int i = 0; i < *count; i++)
devices[i] = (uint64_t)metalDevices[i];
return GN_SUCCESS;
}
gnBool metalIsInstanceSuitable(gnInstanceHandle instance, gnSuitableField field, gryphnInstanceFunctionLayers* next) {
switch (field) {
case GN_NON_EXISTANT_PHYSICAL_DEVICE: return GN_FALSE;
}
}
void metalDestroyInstance(gnInstanceHandle instance, gryphnInstanceFunctionLayers* next, gnAllocators* allocators) {
if (next != NULL) return;
allocators->free(instance->instance, allocators->userData);

View File

@@ -22,8 +22,6 @@ typedef struct gnPlatformRenderPassDescriptor_t {
uint32_t subpassCount;
mtlSubpass* subpasses;
mtlSubpassCopyInfo* copyInfos;
} gnPlatformRenderPassDescriptor;
gnReturnCode createMetalRenderPass(gnRenderPassDescriptor renderPass, gnDevice device, gnRenderPassDescriptorInfo info);

View File

@@ -1,5 +1,6 @@
#include "metal_shader_compiler.h"
#include "spirv_msl.hpp"
#include "stdlib.h"
// #include "iostream"
typedef struct mtlCompiler_t {
@@ -43,10 +44,10 @@ GN_CPP_FUNCTION const char* mtlCompilerShader(mtlCompiler compiler, gnUniformLay
for (size_t c = 0; c < uniformLayout->sets[i].uniformBindingCount; c++) {
gnUniformBinding gryphnBinding = uniformLayout->sets[i].uniformBindings[c];
spirv_cross::MSLResourceBinding binding = {
.stage = (compiler->stage == mtlVertex) ? spv::ExecutionModelVertex : spv::ExecutionModelFragment,
.desc_set = ((uint32_t)i + 1),
.binding = gryphnBinding.binding,
.count = 1,
.desc_set = ((uint32_t)i + 1),
.stage = (compiler->stage == mtlVertex) ? spv::ExecutionModelVertex : spv::ExecutionModelFragment,
};
if (gryphnBinding.type == GN_COMBINED_IMAGE_SAMPLER_DESCRIPTOR) {
binding.msl_texture = currentBinding;

View File

@@ -1,17 +1,11 @@
#pragma once
#include "stdint.h"
#include "stdlib.h"
#include "utils/gryphn_bool.h"
#include "utils/gryphn_cpp_function.h"
#include <core/src/uniforms/gryphn_uniform_layout.h>
#ifdef __cplusplus
#define GN_CPP_FUNCTION extern "C"
#else
#define GN_CPP_FUNCTION
#endif
#define MAX_METAL_SETS 32
#define MAX_METAL_BINDINGS 16
#define MAX_METAL_SETS 16
#define MAX_METAL_BINDINGS 32
typedef struct mtlCompiler_t* mtlCompiler;
@@ -31,33 +25,3 @@ typedef struct mtlCompilerInfo {
GN_CPP_FUNCTION mtlCompiler mtlCreateCompiler(mtlCompilerInfo* info);
GN_CPP_FUNCTION const char* mtlCompilerShader(mtlCompiler compiler, gnUniformLayout* uniformLayout);
// typedef struct mtlShaderOptions {
// gnBool useArgumentBuffers;
// mtlShaderModuleStage stage;
// const char* entryPoint;
// } mtlShaderOptions;
// typedef struct mtlBinding {
// uint32_t spvBinding;
// uint32_t metalID;
// } mtlBinding;
// typedef struct mtlSetMap {
// uint32_t setIndex, mtlSetIndex;
// mtlBinding bindings[MAX_METAL_BINDINGS];
// } mtlSetMap;
// typedef struct mtlShaderMap {
// mtlSetMap sets[MAX_METAL_SETS];
// } mtlShaderMap;
// typedef struct mtlShader {
// const char* code;
// mtlShaderMap map;
// } mtlShader;
// #ifdef __cplusplus
// extern "C"
// #endif
// mtlShader mtlCompileShader(uint32_t* code, size_t wordCount, mtlShaderOptions* options);

View File

@@ -41,8 +41,9 @@ gnSurfaceDetails getMetalSurfaceDetails(
MTLPixelFormat mtlGryphnFormatToMetalFormat(gnImageFormat format) {
switch (format) {
case GN_FORMAT_NONE: return MTLPixelFormatInvalid;
case GN_FORMAT_BGRA8_SRGB: return MTLPixelFormatBGRA8Unorm_sRGB;
case GN_FORMAT_BGRA8: return MTLPixelFormatBGRA8Unorm;
case GN_FORMAT_BGRA8_SRGB: return MTLPixelFormatBGRA8Unorm_sRGB;
case GN_FORMAT_RGBA8: return MTLPixelFormatRGBA8Unorm;
case GN_FORMAT_RGBA8_SRGB: return MTLPixelFormatRGBA8Unorm_sRGB;
case GN_FORMAT_D24S8_UINT: return MTLPixelFormatDepth24Unorm_Stencil8;
case GN_FORMAT_D32S8_UINT: return MTLPixelFormatDepth32Float_Stencil8;

View File

@@ -13,4 +13,4 @@ void metalTextureData(gnTextureHandle texture, void* pixelData);
void metalDestroyTexture(gnTexture texture);
NSUInteger mtlSampleCount(gnMultisampleCountFlags flags);
NSUInteger mtlSampleCount(gnSampleCountFlags flags);

View File

@@ -2,7 +2,7 @@
#include "surface/metal_surface.h"
#include "devices/metal_output_devices.h"
NSUInteger mtlSampleCount(gnMultisampleCountFlags flags) {
NSUInteger mtlSampleCount(gnSampleCountFlags flags) {
if ((flags & GN_SAMPLE_BIT_64) == GN_SAMPLE_BIT_64) { return 64; }
if ((flags & GN_SAMPLE_BIT_32) == GN_SAMPLE_BIT_32) { return 32; }
if ((flags & GN_SAMPLE_BIT_16) == GN_SAMPLE_BIT_16) { return 16; }

View File

@@ -3,7 +3,7 @@ set(CMAKE_CXX_STANDARD 17)
project(GryphnOpenGLImpl)
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS
"src/*.c"
"src/*.c" "src/*.cpp"
)
file(GLOB_RECURSE LOADER_FILES CONFIGURE_DEPENDS
"loader/*.c"
@@ -19,8 +19,9 @@ target_include_directories(GryphnOpenGLImpl PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../../
${CMAKE_CURRENT_SOURCE_DIR}/../../../include/
)
add_subdirectory(depends/SPIRV-Cross)
target_include_directories(GryphnOpenGLImpl PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/depends/glad/include/
)
add_compile_definitions(GN_REVEAL_IMPL)
target_link_libraries(GryphnOpenGLImpl GL "X11")
target_link_libraries(GryphnOpenGLImpl GL "X11" spirv-cross-core spirv-cross-glsl spirv-cross-cpp)

View File

@@ -0,0 +1,27 @@
#include "opengl_loader.h"
#include "commands/buffers/opengl_command_buffer.h"
#include "commands/commands/opengl_commands.h"
gnCommandFunctions loadOpenGLCommandFunctions() {
return (gnCommandFunctions) {
._gnCommandPoolAllocateCommandBuffers = openglCommandPoolAllocateCommandBuffers,
._gnBeginCommandBuffer = openglBeginCommandBuffer,
._gnResetCommandBuffer = openglResetCommandBuffer,
._gnEndCommandBuffer = openglEndCommandBuffer,
._gnDestroyCommandBuffer = openglDestroyCommandBuffer,
._gnCommandBeginRenderPass = openglBeginRenderPass,
._gnCommandEndRenderPass = openglEndRenderPass,
._gnCommandBindGraphicsPipeline = openglBindGraphicsPipeline,
._gnCommandSetViewport = openglSetViewport,
._gnCommandSetScissor = openglSetScissor,
._gnCommandBindUniform = openglBindUniform,
._gnCommandPushConstant = openglPushConstant,
._gnCommandBindBuffer = openglBindBuffer,
._gnCommandDraw = openglDraw,
._gnCommandDrawIndexed = openglDrawIndexed,
};
}

View File

@@ -1,6 +1,17 @@
#include "opengl_loader.h"
#include "device/opengl_output_device.h"
#include "presentation_queue/opengl_presentation_queue.h"
#include "shaders/opengl_shader_module.h"
#include "renderpass/opengl_render_pass_descriptor.h"
#include "uniforms/pool/opengl_uniform_pool.h"
#include "uniforms/uniform/opengl_uniform.h"
#include "commands/pool/opengl_command_pool.h"
#include "buffer/opengl_buffer.h"
#include "textures/opengl_texture.h"
#include "framebuffer/opengl_framebuffer.h"
#include "graphics_pipeline/opengl_graphics_pipeline.h"
#include "submit/opengl_submit.h"
#include "present/opengl_present.h"
gnDeviceFunctions loadOpenGLDeviceFunctions() {
return (gnDeviceFunctions){
@@ -8,41 +19,42 @@ gnDeviceFunctions loadOpenGLDeviceFunctions() {
._gnPresentationQueueGetImage = getOpenGLPresentationQueueImage,
._gnDestroyPresentationQueue = destroyOpenGLPresentationQueue,
._gnCreateShaderModule = NULL,
._gnDestroyShaderModule = NULL,
._gnCreateShaderModule = openglCreateShaderModule,
._gnDestroyShaderModule = openglDestroyShaderModule,
._gnCreateRenderPassDescriptor = NULL,
._gnDestroyRenderPassDescriptor = NULL,
._gnCreateRenderPassDescriptor = openglCreateRenderPass,
._gnDestroyRenderPassDescriptor = openglDestroyRenderPass,
._gnCreateGraphicsPipeline = NULL,
._gnDestroyGraphicsPipeline = NULL,
._gnCreateGraphicsPipeline = openglCreateGraphicsPipeline,
._gnDestroyGraphicsPipeline = openglDestroyGraphicsPipeline,
._gnCreateFramebuffer = NULL,
._gnDestroyFramebuffer = NULL,
._gnCreateFramebuffer = openglCreateFramebuffer,
._gnDestroyFramebuffer = openglDestroyFramebuffer,
._gnCreateCommandPool = NULL,
._gnDestroyCommandPool = NULL,
._gnCreateCommandPool = openglCreateCommandPool,
._gnDestroyCommandPool = openglDestroyCommandPool,
._gnCreateBuffer = NULL,
._gnBufferData = NULL,
._gnBufferSubData = NULL,
._gnMapBuffer = NULL,
._gnDestroyBuffer = NULL,
._gnCreateBuffer = openglCreateBuffer,
._gnBufferData = openglBufferData,
._gnBufferSubData = openglBufferSubData,
._gnMapBuffer = openglMapBuffer,
._gnUnmapBuffer = openglUnmapBuffer,
._gnDestroyBuffer = openglDestroyBuffer,
._gnCreateUniformPool = NULL,
._gnUniformPoolAllocateUniforms = NULL,
._gnDestroyUniformPool = NULL,
._gnCreateUniformPool = openglCreateUniformPool,
._gnUniformPoolAllocateUniforms = openglAllocateUniforms,
._gnDestroyUniformPool = openglDestroyUniformPool,
._gnUpdateBufferUniform = NULL,
._gnUpdateStorageUniform = NULL,
._gnUpdateImageUniform = NULL,
._gnUpdateBufferUniform = openglUpdateBufferUniform,
._gnUpdateStorageUniform = openglUpdateStorageUniform,
._gnUpdateImageUniform = openglUpdateImageUniform,
._gnCreateTexture = NULL,
._gnTextureData = NULL,
._gnDestroyTexture = NULL,
._gnCreateTexture = openglCreateTexture,
._gnTextureData = openglTextureData,
._gnDestroyTexture = openglDestroyTexture,
._gnSubmit = NULL,
._gnPresent = NULL,
._gnSubmit = openglSubmit,
._gnPresent = openglPresent,
._gnWaitForDevice = waitForOpenGLDevice
};

View File

@@ -0,0 +1,38 @@
#include "opengl_buffer.h"
#include "string.h"
GLenum gnBufferTypeToGLEnum(gnBufferType type) {
switch (type) {
case GN_VERTEX_BUFFER: return GL_ARRAY_BUFFER;
case GN_INDEX_BUFFER: return GL_ELEMENT_ARRAY_BUFFER;
case GN_UNIFORM_BUFFER: return GL_UNIFORM_BUFFER;
case GN_STORAGE_BUFFER: return GL_SHADER_STORAGE_BUFFER;
}
}
gnReturnCode openglCreateBuffer(gnBufferHandle buffer, gnDevice device, gnBufferInfo info) {
buffer->buffer = malloc(sizeof(gnPlatformBuffer));
glCreateBuffers(1, &buffer->buffer->id);
buffer->buffer->type = gnBufferTypeToGLEnum(info.type);
buffer->buffer->usage = (info.usage == GN_DYNAMIC_DRAW) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
glNamedBufferStorage(buffer->buffer->id, info.size, NULL, GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT);
return GN_SUCCESS;
}
void openglBufferData(gnBufferHandle buffer, size_t dataSize, void* data) {
openglBufferSubData(buffer, 0, dataSize, data);
}
#include "stdio.h"
void openglBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, gnBufferMemory data) {
void* buff = glMapNamedBufferRange(buffer->buffer->id, offset, buffer->info.size, GL_MAP_WRITE_BIT);
memcpy(buff, data, dataSize);
glUnmapNamedBuffer(buffer->buffer->id);
}
void* openglMapBuffer(gnBufferHandle buffer) {
return glMapNamedBufferRange(buffer->buffer->id, 0, buffer->info.size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
}
void openglUnmapBuffer(gnBufferHandle buffer) {
glUnmapNamedBuffer(buffer->buffer->id);
}
void openglDestroyBuffer(gnBufferHandle buffer) {
glDeleteBuffers(1, &buffer->buffer->id);
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include "core/src/buffers/gryphn_buffer.h"
#include "glad/glad.h"
#include "utils/gryphn_cpp_function.h"
typedef struct gnPlatformBuffer_t {
GLuint id;
GLenum type, usage;
} gnPlatformBuffer;
gnReturnCode openglCreateBuffer(gnBufferHandle buffer, gnDevice device, gnBufferInfo info);
void openglBufferData(gnBufferHandle buffer, size_t dataSize, void* data);
void openglBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, gnBufferMemory data);
void* openglMapBuffer(gnBufferHandle buffer);
void openglUnmapBuffer(gnBufferHandle buffer);
void openglDestroyBuffer(gnBufferHandle buffer);
GN_CPP_FUNCTION GLenum gnBufferTypeToGLEnum(gnBufferType type);

View File

@@ -0,0 +1,48 @@
#include "opengl_command_buffer.h"
#include "commands/pool/opengl_command_pool.h"
gnReturnCode openglCommandPoolAllocateCommandBuffers(gnCommandBufferHandle* commandBuffers, uint32_t count, gnCommandPoolHandle pool) {
for (int i = 0; i < count; i++) {
gnBool wasAbleToAllocate = GN_FALSE;
for (int c = i; c < pool->commandPool->allocatedCommandBufferCount; c++) {
if (pool->commandPool->canBeReallocated[c] == GN_TRUE) {
pool->commandPool->canBeReallocated[c] = GN_FALSE;
commandBuffers[i]->commandBuffer = &pool->commandPool->commandBuffers[c];
commandBuffers[i]->commandBuffer->commmandRunner = openglCreateCommandRunner();
commandBuffers[i]->commandBuffer->boundVertexBuffer = GN_NULL_HANDLE;
commandBuffers[i]->commandBuffer->boundIndexBuffer = GN_NULL_HANDLE;
// glGenBuffers(1, &commandBuffers[i]->commandBuffer->vertexBuffer);
// glBindBuffer(GL_ARRAY_BUFFER, commandBuffers[i]->commandBuffer->vertexBuffer);
// glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
// gl
// glGenBuffers(1, &commandBuffers[i]->commandBuffer->indexBuffer);
wasAbleToAllocate = GN_TRUE;
break;
}
}
if (!wasAbleToAllocate) {
openglResizeCommandPool(pool);
}
}
return GN_SUCCESS;
}
void openglResetCommandBuffer(gnCommandBuffer commandBuffer) { /* nothing, for now command buffers are implictly reset on begin */ }
gnReturnCode openglBeginCommandBuffer(gnCommandBuffer commandBuffer) {
openglResetCommandRunner(commandBuffer->commandBuffer->commmandRunner);
return GN_SUCCESS;
}
gnReturnCode openglEndCommandBuffer(gnCommandBuffer commandBuffer) {
return GN_SUCCESS;
}
void openglDestroyCommandBuffer(gnCommandBuffer commandBuffer) {
commandBuffer->commandPool->commandPool->canBeReallocated[commandBuffer->commandBuffer->index] = GN_TRUE;
openglDestroyCommandRunner(&commandBuffer->commandBuffer->commmandRunner);
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include "glad/glad.h"
#include "core/src/command/command_buffer/gryphn_command_buffer.h"
#include "commands/commands/opengl_command_runner.h"
typedef struct gnPlatformCommandBuffer_t {
int index;
openglCommandRunner commmandRunner;
gnGraphicsPipeline boundGraphicsPipeline;
gnBuffer boundVertexBuffer, boundIndexBuffer;
} gnPlatformCommandBuffer;
gnReturnCode openglCommandPoolAllocateCommandBuffers(gnCommandBufferHandle* commandBuffers, uint32_t count, gnCommandPoolHandle pool);
void openglResetCommandBuffer(gnCommandBuffer commandBuffer);
gnReturnCode openglBeginCommandBuffer(gnCommandBuffer commandBuffer);
gnReturnCode openglEndCommandBuffer(gnCommandBuffer commandBuffer);
void openglDestroyCommandBuffer(gnCommandBuffer commandBuffer);

View File

@@ -0,0 +1,23 @@
#include "opengl_command_runner.h"
#include "vector"
typedef struct openglCommandRunner_t {
std::vector<std::function<void()>> commands;
} glCommandRunner;
GN_CPP_FUNCTION openglCommandRunner openglCreateCommandRunner() { return new glCommandRunner(); }
GN_CPP_FUNCTION void openglRunCommandRunner(openglCommandRunner runner) {
for (int i = 0; i < runner->commands.size(); i++)
runner->commands[i]();
}
GN_CPP_FUNCTION void openglResetCommandRunner(openglCommandRunner runner) { runner->commands.clear(); }
GN_CPP_FUNCTION void openglDestroyCommandRunner(openglCommandRunner* runner) {
*runner = NULL;
delete runner;
}
void openglCommandRunnerBindFunction(openglCommandRunner runner, std::function<void()> function) {
runner->commands.push_back(function);
}
// void openglCommandRunnerBindFunction(openglCommandRunner runner, openglFunctionBinding binding) { runner->commands.push_back(binding); }

View File

@@ -0,0 +1,14 @@
#pragma once
#include "utils/gryphn_cpp_function.h"
typedef struct openglCommandRunner_t* openglCommandRunner;
GN_CPP_FUNCTION openglCommandRunner openglCreateCommandRunner();
GN_CPP_FUNCTION void openglResetCommandRunner(openglCommandRunner runner);
GN_CPP_FUNCTION void openglRunCommandRunner(openglCommandRunner runner);
GN_CPP_FUNCTION void openglDestroyCommandRunner(openglCommandRunner* runner);
#ifdef __cplusplus
#include "functional"
#define openglBindFunction(expr) std::function<void()>([=]{ expr; })
void openglCommandRunnerBindFunction(openglCommandRunner runner, std::function<void()> function);
#endif

View File

@@ -0,0 +1,145 @@
#include "glad/glad.h"
#include "opengl_commands.h"
#include "opengl_command_runner.h"
#include "commands/buffers/opengl_command_buffer.h"
#include "framebuffer/opengl_framebuffer.h"
#include <string.h>
#include "buffer/opengl_buffer.h"
#include "graphics_pipeline/opengl_graphics_pipeline.h"
#include "renderpass/opengl_render_pass_descriptor.h"
#include "uniforms/uniform/opengl_uniform.h"
#include "textures/opengl_texture.h"
GN_CPP_FUNCTION void openglBeginRenderPass(gnCommandBuffer buffer, gnRenderPassInfo sPassInfo) {
gnRenderPassInfo passInfo = sPassInfo;
gnClearValue* values = (gnClearValue*)malloc(sizeof(gnClearValue*) * passInfo.clearValueCount);
memcpy(values, passInfo.clearValues, sizeof(gnClearValue*) * passInfo.clearValueCount);
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([passInfo, values]{
glBindFramebuffer(GL_FRAMEBUFFER, passInfo.framebuffer->framebuffer->framebuffers[0]);
if (passInfo.renderPassDescriptor->renderPassDescriptor->subpasses[0].colorAttachments[0].format == GL_SRGB8_ALPHA8) glEnable(GL_FRAMEBUFFER_SRGB);
glClearColor(values[0].r, values[0].g, values[0].b, values[0].a);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(passInfo.offset.x, passInfo.offset.y, passInfo.size.x, passInfo.size.y);
free(values);
}));
}
GN_CPP_FUNCTION void openglEndRenderPass(gnCommandBuffer buffer) {
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([]{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_FRAMEBUFFER_SRGB);
}));
}
GN_CPP_FUNCTION void openglBindGraphicsPipeline(gnCommandBuffer commandBuffer, gnGraphicsPipeline graphicsPipeline) {
gnGraphicsPipeline pipeline = graphicsPipeline;
gnCommandBuffer buffer = commandBuffer;
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([buffer, pipeline]{
buffer->commandBuffer->boundGraphicsPipeline = pipeline;
glBindVertexArray(buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->vertexArrayObject);
if (buffer->commandBuffer->boundVertexBuffer != GN_NULL_HANDLE)
glVertexArrayVertexBuffer(
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->vertexArrayObject, 0,
buffer->commandBuffer->boundVertexBuffer->buffer->id, 0,
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->stride
);
if (buffer->commandBuffer->boundIndexBuffer != GN_NULL_HANDLE)
glVertexArrayElementBuffer(buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->vertexArrayObject, buffer->commandBuffer->boundIndexBuffer->buffer->id);
glUseProgram(buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->program);
}));
}
GN_CPP_FUNCTION void openglSetViewport(gnCommandBuffer buffer, gnViewport sViewport) {
gnViewport viewport = sViewport;
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([viewport]{
glViewport(viewport.position.x, viewport.position.y, viewport.size.x, viewport.size.y);
glDepthRange(viewport.minDepth, viewport.maxDepth);
}));
}
GN_CPP_FUNCTION void openglSetScissor(gnCommandBuffer buffer, gnScissor sScissor) {
gnScissor scissor = sScissor;
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([scissor]{
glScissor(scissor.position.x, scissor.position.y, scissor.size.x, scissor.size.y);
}));
}
GN_CPP_FUNCTION void openglBindBuffer(gnCommandBufferHandle buffer, gnBufferHandle bufferToBind, gnBufferType type) {
gnBufferType bType = type;
gnCommandBufferHandle bBuffer = buffer;
gnBufferHandle bBufferToBind = bufferToBind;
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([bType, bBuffer, bBufferToBind]{
if (bType == GN_VERTEX_BUFFER) {
bBuffer->commandBuffer->boundVertexBuffer = bBufferToBind;
glVertexArrayVertexBuffer(
bBuffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->vertexArrayObject, 0,
bBuffer->commandBuffer->boundVertexBuffer->buffer->id, 0,
bBuffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->stride
);
} else if (bType == GN_INDEX_BUFFER) {
bBuffer->commandBuffer->boundIndexBuffer = bBufferToBind;
glVertexArrayElementBuffer(bBuffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->vertexArrayObject, bBufferToBind->buffer->id);
}
}));
}
GN_CPP_FUNCTION void openglDraw(gnCommandBuffer buffer, int sVertexCount, int sFirstVertex, int sInstanceCount, int sFirstInstance) {
int vertexCount = sVertexCount, firstVertex = sFirstVertex, instanceCount = sInstanceCount, firstInstance = sFirstInstance;
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([vertexCount, firstVertex, instanceCount, firstInstance]{
glDrawArraysInstancedBaseInstance(GL_TRIANGLES, firstVertex, vertexCount, instanceCount, firstInstance);
}));
}
GN_CPP_FUNCTION void openglDrawIndexed(gnCommandBufferHandle sBuffer, gnIndexType sType, int sIndexCount, int sFirstIndex, int sVertexOffset, int sInstanceCount, int sFirstInstance) {
gnCommandBuffer buffer = sBuffer;
gnIndexType type = sType;
int indexCount = sIndexCount, firstIndex = sFirstIndex, vertexOffset = sVertexOffset, instanceCount = sInstanceCount, firstInstance = sFirstInstance;
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([buffer, type, indexCount, firstIndex, instanceCount, vertexOffset, firstInstance]{
glDrawElementsInstancedBaseVertexBaseInstance(GL_TRIANGLES, indexCount, (type == GN_UINT16) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(sizeof(GLuint) * firstIndex), instanceCount, vertexOffset, firstInstance);
}));
}
GN_CPP_FUNCTION void openglBindUniform(gnCommandBufferHandle sBuffer, gnUniform sUniform, uint32_t sSet, uint32_t dynamicOffsetCount, uint32_t* dynamicOffsets) {
gnCommandBufferHandle buffer = sBuffer;
gnUniform uniform = sUniform;
uint32_t set = sSet;
openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([buffer, uniform, set]{
for (int i = 0; i < MAX_OPENGL_BINDINGS; i++) {
if (uniform->uniform->bindings[i].isUpdated != GN_TRUE) continue;
if (uniform->uniform->bindings[i].type == gl_image) {
glActiveTexture(GL_TEXTURE0 + buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->setMap[set].bindings[uniform->uniform->bindings[i].image_info.binding]);
glBindTexture(GL_TEXTURE_2D, uniform->uniform->bindings[i].image_info.texture->texture->id);
} else if (uniform->uniform->bindings[i].type == gl_buffer) {
glBindBufferBase(
GL_UNIFORM_BUFFER,
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->setMap[set].bindings[uniform->uniform->bindings[i].buffer_info.binding],
uniform->uniform->bindings[i].buffer_info.buffer->buffer->id
);
glUniformBlockBinding(
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->program,
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->setMap[set].bindings[uniform->uniform->bindings[i].buffer_info.binding],
0
);
} else if (uniform->uniform->bindings[i].type == gl_storage) {
glBindBufferBase(
GL_SHADER_STORAGE_BUFFER,
buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->setMap[set].bindings[uniform->uniform->bindings[i].storage_info.binding],
uniform->uniform->bindings[i].storage_info.buffer->buffer->id
);
}
}
}));
}
// #include "stdio.h"
GN_CPP_FUNCTION void openglPushConstant(gnCommandBufferHandle sBuffer, gnPushConstantLayout sLayout, void* sData) {
// gnCommandBufferHandle buffer = sBuffer;
// // gnPushConstantLayout layout = sLayout;
// // void* data = malloc(sizeof(sLayout.size));
// // memcpy(data, sData, sizeof(sLayout.size));
// openglCommandRunnerBindFunction(buffer->commandBuffer->commmandRunner, std::function<void()>([buffer]{
// //TODO: implement OpenGL push constants, its just hard because OpenGL is a bitch and i hate it
// // GLint loc = glGetUniformLocation(buffer->commandBuffer->boundGraphicsPipeline->graphicsPipeline->program, "gnPushConstantBlock");
// // printf("member loc: %i\n", loc);
// // if (loc == -1) return;
// }));
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include "core/src/command/commands/gryphn_command.h"
#include "utils/gryphn_cpp_function.h"
GN_CPP_FUNCTION void openglBeginRenderPass(gnCommandBuffer buffer, gnRenderPassInfo passInfo);
GN_CPP_FUNCTION void openglEndRenderPass(gnCommandBuffer buffer);
GN_CPP_FUNCTION void openglBindGraphicsPipeline(gnCommandBuffer buffer, gnGraphicsPipeline graphicsPipeline);
GN_CPP_FUNCTION void openglSetViewport(gnCommandBuffer buffer, gnViewport viewport);
GN_CPP_FUNCTION void openglSetScissor(gnCommandBuffer buffer, gnScissor scissor);
GN_CPP_FUNCTION void openglBindBuffer(gnCommandBufferHandle buffer, gnBufferHandle bufferToBind, gnBufferType type);
GN_CPP_FUNCTION void openglDraw(gnCommandBuffer buffer, int vertexCount, int firstVertex, int instanceCount, int firstInstance);
GN_CPP_FUNCTION void openglDrawIndexed(gnCommandBufferHandle buffer, gnIndexType type, int indexCount, int firstIndex, int vertexOffset, int instanceCount, int firstInstance);
GN_CPP_FUNCTION void openglBindUniform(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t set, uint32_t dynamicOffsetCount, uint32_t* dynamicOffsets);
GN_CPP_FUNCTION void openglPushConstant(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data);

View File

@@ -0,0 +1,31 @@
#include "opengl_command_pool.h"
#include "stdlib.h"
gnReturnCode openglCreateCommandPool(gnCommandPool commandPool, gnDevice device, gnCommandPoolInfo info) {
commandPool->commandPool = malloc(sizeof(gnPlatformCommandPool));
uint32_t baseCommandBufferCount = 10;
commandPool->commandPool->allocatedCommandBufferCount = baseCommandBufferCount;
commandPool->commandPool->commandBuffers = malloc(sizeof(gnPlatformCommandBuffer) * baseCommandBufferCount);
commandPool->commandPool->canBeReallocated = malloc(sizeof(gnBool) * baseCommandBufferCount);
for (int i = 0; i < baseCommandBufferCount; i++) {
commandPool->commandPool->commandBuffers[i].index = i;
commandPool->commandPool->canBeReallocated[i] = GN_TRUE;
}
return GN_SUCCESS;
}
void openglDestroyCommandPool(gnCommandPool commandPool) {
commandPool->commandPool->allocatedCommandBufferCount = 0;
free(commandPool->commandPool->commandBuffers);
free(commandPool->commandPool->canBeReallocated);
free(commandPool->commandPool);
}
void openglResizeCommandPool(gnCommandPoolHandle pool) {
pool->commandPool->allocatedCommandBufferCount *= 2;
pool->commandPool->commandBuffers = realloc(pool->commandPool->commandBuffers, sizeof(gnPlatformCommandBuffer) * pool->commandPool->allocatedCommandBufferCount);
pool->commandPool->canBeReallocated = realloc(pool->commandPool->canBeReallocated, sizeof(gnBool) * pool->commandPool->allocatedCommandBufferCount);
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "core/src/command/command_pool/gryphn_command_pool.h"
#include "commands/buffers/opengl_command_buffer.h"
#include "utils/gryphn_bool.h"
typedef struct gnPlatformCommandPool_t {
uint32_t allocatedCommandBufferCount;
gnPlatformCommandBuffer* commandBuffers;
gnBool* canBeReallocated;
} gnPlatformCommandPool;
gnReturnCode openglCreateCommandPool(gnCommandPool commandPool, gnDevice device, gnCommandPoolInfo info);
void openglDestroyCommandPool(gnCommandPool commandPool);
void openglResizeCommandPool(gnCommandPoolHandle pool);

View File

@@ -0,0 +1,23 @@
const char * vertex_shader_source =
"#version 450 core\n"
"\n"
"layout(location = 0) in vec2 inPosition;\n"
"layout(location = 1) in vec2 inTexcoord;\n"
"\n"
"out vec2 texcoord;\n"
"\n"
"void main() {\n"
" gl_Position = vec4(inPosition, 0.0, 1.0);\n"
" texcoord = inTexcoord;\n"
"}\n" ;
const char * fragment_shader_source =
"#version 450 core\n"
"\n"
"out vec4 FragColor;\n"
"layout(binding = 0) uniform sampler2D tex;\n"
"in vec2 texcoord;\n"
"\n"
"void main() {\n"
" FragColor = texture(tex, texcoord);\n"
" //FragColor = vec4(texcoord, 0.0, 1.0);\n"
"}\n" ;

View File

@@ -1,5 +1,72 @@
#include "glad/glad.h"
#include "opengl_output_device.h"
#include "glsl_shader.glsl"
#include "stdlib.h"
#include "core/src/instance/gryphn_instance.h"
gnReturnCode createOpenGLOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle device, gnOutputDeviceInfo deviceInfo) { return GN_SUCCESS; }
gnReturnCode createOpenGLOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle device, gnOutputDeviceInfo deviceInfo) {
int success;
char infoLog[512];
device->outputDevice = malloc(sizeof(gnPlatformOutputDevice));
float vertices[] = {
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
};
glCreateBuffers(1, &device->outputDevice->buffer);
glBindBuffer(GL_ARRAY_BUFFER, device->outputDevice->buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(sizeof(float) * 2));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertex_shader_source, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success) {
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString(infoLog)
});
}
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragment_shader_source, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success) {
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString(infoLog)
});
}
device->outputDevice->shaderProgram = glCreateProgram();
glAttachShader(device->outputDevice->shaderProgram, vertexShader);
glAttachShader(device->outputDevice->shaderProgram, fragmentShader);
glLinkProgram(device->outputDevice->shaderProgram);
glGetProgramiv(device->outputDevice->shaderProgram, GL_LINK_STATUS, &success);
if(!success) {
glGetProgramInfoLog(device->outputDevice->shaderProgram, 512, NULL, infoLog);
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString(infoLog)
});
}
return GN_SUCCESS;
}
void waitForOpenGLDevice(const gnOutputDeviceHandle device) {}
void destroyOpenGLOutputDevice(gnOutputDeviceHandle device) {}

View File

@@ -1,7 +1,9 @@
#pragma once
#include <output_device/gryphn_output_device.h>
typedef struct gnPlatformOutputDevice_t {} gnPlatformOutputDevice;
typedef struct gnPlatformOutputDevice_t {
unsigned int buffer, shaderProgram;
} gnPlatformOutputDevice;
gnReturnCode createOpenGLOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle device, gnOutputDeviceInfo deviceInfo);
void waitForOpenGLDevice(const gnOutputDeviceHandle device);

View File

@@ -12,7 +12,7 @@ gnPhysicalDevice* getOpenGLDevice(gnInstanceHandle instance, uint32_t* deviceCou
.maxColorSamples = GN_SAMPLE_BIT_1,
.maxDepthSamples = GN_SAMPLE_BIT_1,
.maxMemoryAllocations = 0x40000000,
.maxPushConstantSize = 256
.maxPushConstantSize = 0
},
.properties = {
.deviceType = GN_DEDICATED_DEVICE,

View File

@@ -0,0 +1,34 @@
#include "opengl_framebuffer.h"
#include "stdlib.h"
#include "renderpass/opengl_render_pass_descriptor.h"
#include "textures/opengl_texture.h"
#include "stdio.h"
#include "core/src/output_device/gryphn_output_device.h"
#include "core/src/instance/gryphn_instance.h"
gnReturnCode openglCreateFramebuffer(gnFramebuffer framebuffer, gnDevice device, gnFramebufferInfo info) {
framebuffer->framebuffer = malloc(sizeof(struct gnPlatformFramebuffer_t));
framebuffer->framebuffer->framebufferCount = info.renderPassDescriptor->renderPassDescriptor->subpassCount;
framebuffer->framebuffer->framebuffers = malloc(sizeof(GLuint) * info.renderPassDescriptor->renderPassDescriptor->subpassCount);
for (int i = 0; i < info.renderPassDescriptor->renderPassDescriptor->subpassCount; i++) {
glCreateFramebuffers(1, &framebuffer->framebuffer->framebuffers[i]);
for (int c = 0; c < info.renderPassDescriptor->renderPassDescriptor->subpasses[i].colorAttachmentCount; c++)
glNamedFramebufferTexture(framebuffer->framebuffer->framebuffers[i], GL_COLOR_ATTACHMENT0 + c, info.attachments[info.renderPassDescriptor->renderPassDescriptor->subpasses[i].colorAttachments[c].attachmentIndex]->texture->id, 0);
if (info.renderPassDescriptor->renderPassDescriptor->subpasses[i].depthAttachment.index >= 0)
glNamedFramebufferTexture(framebuffer->framebuffer->framebuffers[i], GL_DEPTH_STENCIL_ATTACHMENT, info.attachments[info.renderPassDescriptor->renderPassDescriptor->subpasses[i].depthAttachment.index]->texture->id, 0);
if (glCheckNamedFramebufferStatus(framebuffer->framebuffer->framebuffers[i], GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
char string[500];
snprintf(string, 500, "Failed to create OpenGL framebuffer: 0x%x\n", glCheckNamedFramebufferStatus(framebuffer->framebuffer->framebuffers[i], GL_FRAMEBUFFER));
gnDebuggerSetErrorMessage(framebuffer->device->instance->debugger, (gnMessageData){
.message = gnCreateString(string)
});
return GN_FAILED_CREATE_OBJECT;
}
}
return GN_SUCCESS;
}
void openglDestroyFramebuffer(gnFramebuffer framebuffer) {
for (int i = 0; i < framebuffer->framebuffer->framebufferCount; i++)
glDeleteFramebuffers(1, &framebuffer->framebuffer->framebuffers[i]);
free(framebuffer->framebuffer);
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "glad/glad.h"
#include "core/src/framebuffer/gryphn_framebuffer.h"
typedef struct gnPlatformFramebuffer_t {
uint32_t framebufferCount;
GLuint* framebuffers;
} gnPlatformFramebuffer_t;
gnReturnCode openglCreateFramebuffer(gnFramebuffer framebuffer, gnDevice device, gnFramebufferInfo info);
void openglDestroyFramebuffer(gnFramebuffer framebuffer);

View File

@@ -0,0 +1,80 @@
#include "opengl_graphics_pipeline.h"
#include "core/src/instance/gryphn_instance.h"
#include "shaders/opengl_shader_module.h"
#include "stdio.h"
gnReturnCode openglCreateGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gnOutputDevice device, gnGraphicsPipelineInfo info) {
graphicsPipeline->graphicsPipeline = malloc(sizeof(gnPlatformGraphicsPipeline));
GLuint* ids = malloc(sizeof(GLuint) * info.shaderModuleCount);
for (int i = 0; i < info.shaderModuleCount; i++) {
glShader shader = glCompilerCompilerShader(info.shaderModules[i]->shaderModule->compiler, &info.uniformLayout);
if (i == 0)
for (int set = 0; set < MAX_OPENGL_SETS; set++)
for (int binding = 0; binding < MAX_OPENGL_BINDINGS; binding++)
graphicsPipeline->graphicsPipeline->setMap[set].bindings[binding] = shader.sets[set].bindings[binding];
ids[i] = glCreateShader(gnShaderTypeToGLEnum(info.shaderModules[i]->info.stage));
const char* source = shader.source;
printf("Shader Source %s\n", source);
glShaderSource(ids[i], 1, &source, NULL);
glCompileShader(ids[i]);
GLint returnCode;
glGetShaderiv(ids[i], GL_COMPILE_STATUS, &returnCode);
if(!returnCode) {
char infoLog[512];
glGetShaderInfoLog(ids[i], 512, NULL, infoLog);
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString(infoLog)
});
}
}
graphicsPipeline->graphicsPipeline->program = glCreateProgram();
for (int i = 0; i < info.shaderModuleCount; i++)
glAttachShader(graphicsPipeline->graphicsPipeline->program, ids[i]);
glLinkProgram(graphicsPipeline->graphicsPipeline->program);
GLint linked;
glGetProgramiv(graphicsPipeline->graphicsPipeline->program, GL_LINK_STATUS, &linked);
if (!linked) {
GLchar infoLog[512];
glGetProgramInfoLog(graphicsPipeline->graphicsPipeline->program, 512, NULL, infoLog);
gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){
.message = gnCreateString(infoLog)
});
} else {
gnDebuggerSetVerboseMessage(&device->instance->debugger, (gnMessageData){
.message = gnCreateString("Successfully linked program")
});
}
for (int i = 0; i < info.shaderModuleCount; i++)
glDeleteShader(ids[i]);
glCreateVertexArrays(1, &graphicsPipeline->graphicsPipeline->vertexArrayObject);
glVertexArrayAttribFormat(graphicsPipeline->graphicsPipeline->vertexArrayObject, 0, 3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(graphicsPipeline->graphicsPipeline->vertexArrayObject, 0, 0);
// Attribute 1: texcoord (2 floats)
glVertexArrayAttribFormat(graphicsPipeline->graphicsPipeline->vertexArrayObject, 1, 2, GL_FLOAT, GL_FALSE, sizeof(float)*3);
glVertexArrayAttribBinding(graphicsPipeline->graphicsPipeline->vertexArrayObject, 1, 0);
// Attribute 2: color (3 floats)
glVertexArrayAttribFormat(graphicsPipeline->graphicsPipeline->vertexArrayObject, 2, 3, GL_FLOAT, GL_FALSE, sizeof(float)*5);
glVertexArrayAttribBinding(graphicsPipeline->graphicsPipeline->vertexArrayObject, 2, 0);
graphicsPipeline->graphicsPipeline->stride = (sizeof(float) * 8);
// Enable them
glEnableVertexArrayAttrib(graphicsPipeline->graphicsPipeline->vertexArrayObject, 0);
glEnableVertexArrayAttrib(graphicsPipeline->graphicsPipeline->vertexArrayObject, 1);
glEnableVertexArrayAttrib(graphicsPipeline->graphicsPipeline->vertexArrayObject, 2);
return GN_SUCCESS;
}
void openglDestroyGraphicsPipeline(gnGraphicsPipeline graphicsPipeline) {
glDeleteProgram(graphicsPipeline->graphicsPipeline->program);
free(graphicsPipeline->graphicsPipeline);
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include "glad/glad.h"
#include "core/src/pipelines/graphics_pipeline/gryphn_graphics_pipeline.h"
#include "shaders/opengl_shader_compiler.h"
typedef struct gnPlatformGraphicsPipeline_t {
glSet setMap[MAX_OPENGL_SETS];
GLuint program;
GLuint vertexArrayObject;
GLsizei stride;
} gnPlatformGraphicsPipeline;
gnReturnCode openglCreateGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gnOutputDevice device, gnGraphicsPipelineInfo info);
void openglDestroyGraphicsPipeline(gnGraphicsPipeline graphicsPipeline);

View File

@@ -2,6 +2,9 @@
gnReturnCode openglCreateInstance(gnInstanceHandle instance, gnInstanceCreateInfo* instanceInfo, gryphnInstanceFunctionLayers* next, gnAllocators* allocators) {
if (instanceInfo->coreAPI != GN_RENDERINGAPI_OPENGL) return GN_UNSUPPORTED_API;
instance->instance = malloc(sizeof(gnPlatformInstance));
instance->instance->enableDebugger = instance->enabledLayerCounts[GN_DEBUGGER_LAYER_PLATFORM] >= 1;
return GN_SUCCESS;
}
void openglDestroyInstance(gnInstanceHandle instance, gryphnInstanceFunctionLayers* next, gnAllocators* allocators) {

View File

@@ -2,7 +2,9 @@
#include <GL/gl.h>
#include "instance/gryphn_instance.h"
typedef struct gnPlatformInstance_t {} gnPlatformInstance;
typedef struct gnPlatformInstance_t {
gnBool enableDebugger;
} gnPlatformInstance;
gnReturnCode openglCreateInstance(gnInstanceHandle instance, gnInstanceCreateInfo* instanceInfo, gryphnInstanceFunctionLayers* next, gnAllocators* allocators);
void openglDestroyInstance(gnInstanceHandle instance, gryphnInstanceFunctionLayers* next, gnAllocators* allocators);

View File

@@ -0,0 +1,36 @@
#include "opengl_present.h"
#include "presentation_queue/opengl_presentation_queue.h"
#include "device/opengl_output_device.h"
#include "surface/opengl_surface.h"
gnReturnCode openglPresent(gnOutputDeviceHandle device, gnPresentInfo info) {
for (uint32_t i =0 ; i < info.presentationQueueCount; i++) {
uint32_tArrayListAdd(info.presentationQueues[i]->presentationQueue->avaliableTextures, info.imageIndices[i]);
glBindVertexArray(0);
glDisable(GL_DEPTH_TEST);
if (info.presentationQueues[i]->presentationQueue->format == GL_SRGB8_ALPHA8) glEnable(GL_FRAMEBUFFER_SRGB);
glUseProgram(device->outputDevice->shaderProgram);
glBindBuffer(GL_ARRAY_BUFFER, device->outputDevice->buffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, GLuintArrayListAt(info.presentationQueues[i]->presentationQueue->textures, info.imageIndices[i]));
glDrawArrays(GL_TRIANGLES, 0, 6);
glUseProgram(0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
swapBuffers(info.presentationQueues[i]->info.surface);
glDisable(GL_FRAMEBUFFER_SRGB);
}
// for (uint32_t i = 0; i < info.presentationQueueCount; i++) {
// if (info.presentationQueues[i]->info.imageSize.x != info.presentationQueues[i]->info.surface->windowSurface->layer.drawableSize.width ||
// info.presentationQueues[i]->info.imageSize.y != info.presentationQueues[i]->info.surface->windowSurface->layer.drawableSize.height) {
// return GN_SUBOPTIMAL_PRESENTATION_QUEUE;
// }
// }
return GN_SUCCESS;
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include "core/src/present/gryphn_present.h"
gnReturnCode openglPresent(gnOutputDeviceHandle device, gnPresentInfo info);

View File

@@ -5,28 +5,21 @@
gnReturnCode createOpenGLPresentationQueue(gnPresentationQueueHandle presentationQueue, gnOutputDeviceHandle device, gnPresentationQueueInfo presentationInfo) {
presentationQueue->presentationQueue = malloc(sizeof(struct gnPlatformPresentationQueue_t));
uint32_t convertedFormat = glGryphnFormatToOpenGLFormat(presentationInfo.format.format);
presentationQueue->imageCount = presentationInfo.minImageCount;
presentationQueue->images = malloc(sizeof(gnTexture) * presentationInfo.minImageCount);
presentationQueue->presentationQueue->textures = GLuintArrayListCreate();
presentationQueue->presentationQueue->avaliableTextures = uint32_tArrayListCreate();
presentationQueue->presentationQueue->format = glGryphnFormatToOpenGLInternalFormat(presentationInfo.format.format);
for (int i = 0; i < presentationInfo.minImageCount; i++) {
presentationQueue->images[i] = malloc(sizeof(struct gnTexture_t));
presentationQueue->images[i]->texture = malloc(sizeof(gnPlatformTexture));
glGenTextures(1, &presentationQueue->images[i]->texture->id);
glTexImage2D(
GL_TEXTURE_2D,
0,
glCreateTextures(GL_TEXTURE_2D, 1, &presentationQueue->images[i]->texture->id);
glTextureStorage2D(
presentationQueue->images[i]->texture->id,
1,
glGryphnFormatToOpenGLInternalFormat(presentationInfo.format.format),
presentationInfo.imageSize.x, presentationInfo.imageSize.y,
0,
glGryphnFormatToOpenGLFormat(presentationInfo.format.format),
GL_UNSIGNED_BYTE,
NULL
presentationInfo.imageSize.x, presentationInfo.imageSize.y
);
GLuintArrayListAdd(presentationQueue->presentationQueue->textures, presentationQueue->images[i]->texture->id);
uint32_tArrayListAdd(presentationQueue->presentationQueue->avaliableTextures, i);
}

View File

@@ -7,6 +7,7 @@ GN_ARRAY_LIST_HEADER(GLuint);
typedef struct gnPlatformPresentationQueue_t {
GLuintArrayList textures;
uint32_tArrayList avaliableTextures;
GLenum format;
} gnPlatformPresentationQueue_t;
gnReturnCode createOpenGLPresentationQueue(gnPresentationQueueHandle presentationQueue, gnOutputDeviceHandle device, gnPresentationQueueInfo presentationInfo);

View File

@@ -0,0 +1,50 @@
#include "opengl_render_pass_descriptor.h"
#include "surface/opengl_surface.h"
#include "stdlib.h"
gnReturnCode openglCreateRenderPass(gnRenderPassDescriptor renderPass, gnDevice device, gnRenderPassDescriptorInfo info) {
if (device == GN_NULL_HANDLE) return GN_INVALID_HANDLE;
renderPass->renderPassDescriptor = malloc(sizeof(gnPlatformRenderPassDescriptor));
renderPass->renderPassDescriptor->subpassCount = info.subpassCount;
renderPass->renderPassDescriptor->subpasses = malloc(sizeof(glSubpass) * info.subpassCount);
for (uint32_t i = 0; i < info.subpassCount; i++) {
renderPass->renderPassDescriptor->subpasses[i] = (glSubpass){
.colorAttachmentCount = info.subpassInfos[i].colorAttachmentCount,
.colorAttachments = malloc(sizeof(glColorAttachment) * info.subpassInfos[i].colorAttachmentCount),
.depthAttachment.index = -1
};
gnBool resolve = !(info.subpassInfos[i].resolveAttachments == NULL);
for (uint32_t c = 0; c < info.subpassInfos[i].colorAttachmentCount; c++) {
uint32_t attachmentIndex = info.subpassInfos[i].colorAttachments[c].index;
int resolveAttachmentIndex = -1;
if (resolve)
resolveAttachmentIndex = info.subpassInfos[i].resolveAttachments[c].index;
renderPass->renderPassDescriptor->subpasses[i].colorAttachments[c] = (glColorAttachment){
.loadOperation = info.attachmentInfos[attachmentIndex].loadOperation,
.storeOperation = info.attachmentInfos[attachmentIndex].storeOperation,
.attachmentIndex = attachmentIndex,
.resolveAttachmentIndex = resolveAttachmentIndex,
.format = glGryphnFormatToOpenGLInternalFormat(info.attachmentInfos[attachmentIndex].format)
};
}
if (info.subpassInfos[i].depthAttachment != NULL) {
uint32_t depthAttachmentIndex = info.subpassInfos[i].depthAttachment->index;
renderPass->renderPassDescriptor->subpasses[i].depthAttachment = (gnDepthAttachment){
.index = depthAttachmentIndex,
.format = glGryphnFormatToOpenGLInternalFormat(info.attachmentInfos[depthAttachmentIndex].format),
.loadOperation = info.attachmentInfos[depthAttachmentIndex].loadOperation,
.storeOperation = info.attachmentInfos[depthAttachmentIndex].storeOperation,
};
}
}
return GN_SUCCESS;
}
void openglDestroyRenderPass(gnRenderPassDescriptor renderPass) {
for (int i = 0; i < renderPass->renderPassDescriptor->subpassCount; i++)
free(renderPass->renderPassDescriptor->subpasses[i].colorAttachments);
free(renderPass->renderPassDescriptor->subpasses);
free(renderPass->renderPassDescriptor);
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include "glad/glad.h"
#include "core/src/renderpass/gryphn_render_pass_descriptor.h"
#include "utils/gryphn_color.h"
typedef struct glColorAttachment {
gnColor clearColor;
gnLoadOperation loadOperation;
gnStoreOperation storeOperation;
GLenum format;
uint32_t attachmentIndex;
int resolveAttachmentIndex; // -1 = no attachment
} glColorAttachment;
typedef struct gnDepthAttachment {
int index;
gnLoadOperation loadOperation;
gnStoreOperation storeOperation;
GLint format;
} gnDepthAttachment;
typedef struct glSubpass {
uint32_t colorAttachmentCount;
glColorAttachment* colorAttachments;
gnDepthAttachment depthAttachment;
} glSubpass;
typedef struct gnPlatformRenderPassDescriptor_t {
uint32_t subpassCount;
glSubpass* subpasses;
} gnPlatformRenderPassDescriptor;
gnReturnCode openglCreateRenderPass(gnRenderPassDescriptor renderPass, gnDevice device, gnRenderPassDescriptorInfo info);
void openglDestroyRenderPass(gnRenderPassDescriptor renderPass);

View File

@@ -0,0 +1,73 @@
#include "opengl_shader_compiler.h"
#include "spirv_glsl.hpp"
typedef struct glCompiler_t {
spirv_cross::CompilerGLSL* glsl;
} glInternalCompiler;
void handle_resources(spirv_cross::CompilerGLSL& compiler, spirv_cross::SmallVector<spirv_cross::Resource>& resources, glSet* setMap) {
for (size_t i = 0; i < resources.size(); i++) {
uint32_t
set = compiler.get_decoration(resources[i].id, spv::DecorationDescriptorSet),
binding = compiler.get_decoration(resources[i].id, spv::DecorationBinding);
compiler.unset_decoration(resources[i].id, spv::DecorationBinding);
compiler.set_decoration(resources[i].id, spv::DecorationBinding, setMap[set].bindings[binding]);
}
}
GN_CPP_FUNCTION glCompiler glCreateCompiler(glCompilerInfo* info) {
glInternalCompiler* compiler = (glInternalCompiler*)malloc(sizeof(glInternalCompiler));
compiler->glsl = new spirv_cross::CompilerGLSL(info->code, info->wordCount);
// spirv_cross::CompilerGLSL::Options options = compiler->glsl->get_common_options();
// compiler->glsl->set_common_options(options);
return compiler;
}
GN_CPP_FUNCTION glShader glCompilerCompilerShader(glCompiler compiler, gnUniformLayout* layout) {
glShader shader = {};
uint32_t currentBinding = 0;
for (uint32_t i = 0; i < layout->setCount; i++) {
for (size_t c = 0; c < layout->sets[i].uniformBindingCount; c++) {
gnUniformBinding gryphnBinding = layout->sets[i].uniformBindings[c];
shader.sets[i].bindings[c] = currentBinding;
currentBinding++;
}
}
auto arg_buffers = compiler->glsl->get_shader_resources();
handle_resources(*compiler->glsl, arg_buffers.uniform_buffers, shader.sets);
handle_resources(*compiler->glsl, arg_buffers.storage_buffers, shader.sets);
handle_resources(*compiler->glsl, arg_buffers.sampled_images, shader.sets);
// for (auto &pc : arg_buffers.push_constant_buffers) {
// compiler->glsl->set_name(pc.id, "gnPushConstantBlock");
// auto type = compiler->glsl->get_type(pc.type_id);
// // printf("members: %lu\n", type.member_types.size());
// for (uint32_t i = 0; i < type.member_types.size(); ++i) {
// // // std::string name = compiler->glsl->get_member_name(pc.type_id, i);
// // compiler.set_member_name(push_constant_type_id, 0, "myMat4");
// // compiler.set_member_name(push_constant_type_id, 1, "myVec3");
// // compiler.set_member_name(push_constant_type_id, 2, "myInt");
// auto member_type = compiler->glsl->get_type(type.member_types[i]);
// // // Example: check if it's a mat4, vec3, or int
// // if (member_type.columns == 4 && member_type.vecsize == 4)
// // printf("member %s: mat4\n", name.c_str());
// // else if (member_type.vecsize == 3 && member_type.columns == 1)
// // printf("member %s: vec3\n", name.c_str());
// // else if (member_type.basetype == spirv_cross::SPIRType::Int)
// // printf("member %s: int\n", name.c_str());
// }
// }
std::string output = compiler->glsl->compile();
shader.source = (char*)malloc(sizeof(char*) * (output.size() + 1));
strcpy(shader.source, output.c_str());
shader.source[output.size()] = '\0';
return shader;
}
GN_CPP_FUNCTION void glDestroyCompiler(glCompiler compiler) {
delete compiler->glsl;
free(compiler);
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include "stdint.h"
#include "glad/glad.h"
#include "utils/gryphn_cpp_function.h"
#include "core/src/uniforms/gryphn_uniform_layout.h"
#define MAX_OPENGL_SETS 16
#define MAX_OPENGL_BINDINGS 32
typedef enum glShaderModuleStage {
glVertex = GL_VERTEX_SHADER,
mtlFragment = GL_FRAGMENT_SHADER,
mtlMaxStage
} glShaderModuleStage;
typedef struct glCompilerInfo {
uint32_t* code;
int wordCount;
const char* entryPoint;
// glShaderModuleStage stage;
} glCompilerInfo;
typedef struct glSet { uint32_t bindings[MAX_OPENGL_BINDINGS]; } glSet;
typedef struct glShader {
char* source;
glSet sets[MAX_OPENGL_SETS];
} glShader;
typedef struct glCompiler_t* glCompiler;
GN_CPP_FUNCTION glCompiler glCreateCompiler(glCompilerInfo* info);
GN_CPP_FUNCTION glShader glCompilerCompilerShader(glCompiler compiler, gnUniformLayout* layout);
GN_CPP_FUNCTION void glDestroyCompiler(glCompiler compiler);

View File

@@ -0,0 +1,26 @@
#include "opengl_shader_module.h"
#include "opengl_shader_compiler.h"
#include "stdlib.h"
GLenum gnShaderTypeToGLEnum(gnShaderModuleStage stage) {
switch (stage) {
case GN_VERTEX_SHADER_MODULE: return GL_VERTEX_SHADER;
case GN_FRAGMENT_SHADER_MODULE: return GL_FRAGMENT_SHADER;
case GN_ALL_SHADER_MODULE: return GL_VERTEX_SHADER | GL_FRAGMENT_SHADER;
}
}
gnReturnCode openglCreateShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo) {
module->shaderModule = malloc(sizeof(gnPlatformShaderModule));
glCompilerInfo info = {
.code = shaderModuleInfo.code,
.wordCount = shaderModuleInfo.size / 4,
.entryPoint = gnToCString(shaderModuleInfo.entryPoint),
};
module->shaderModule->compiler = glCreateCompiler(&info);
return GN_SUCCESS;
}
void openglDestroyShaderModule(gnShaderModule module) {
glDestroyCompiler(module->shaderModule->compiler);
free(module->shaderModule);
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include "core/src/shader_module/gryphn_shader_module.h"
#include "opengl_shader_compiler.h"
typedef struct gnPlatformShaderModule_t {
glCompiler compiler;
} gnPlatformShaderModule;
GLenum gnShaderTypeToGLEnum(gnShaderModuleStage stage);
gnReturnCode openglCreateShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo);
void openglDestroyShaderModule(gnShaderModule module);

View File

@@ -0,0 +1,11 @@
#include "core/src/submit/gryphn_submit.h"
#include "commands/buffers/opengl_command_buffer.h"
gnReturnCode openglSubmit(gnOutputDevice device, gnSubmitInfo info) {
if (device == GN_NULL_HANDLE) return GN_INVALID_HANDLE;
for (uint32_t i = 0; i < info.commandBufferCount; i++)
openglRunCommandRunner(info.commandBuffers[i]->commandBuffer->commmandRunner);
return GN_SUCCESS;
}

View File

@@ -0,0 +1,3 @@
#pragma once
#include "core/src/submit/gryphn_submit.h"
gnReturnCode openglSubmit(gnOutputDevice device, gnSubmitInfo info);

View File

@@ -1,8 +1,56 @@
#include <glad/glad.h>
#include "GL/glext.h"
#include "opengl_surface.h"
#include "utils/gryphn_string.h"
#include "stdio.h"
void GLAPIENTRY openglMessageCallback( GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam ) {
gnInstanceHandle handle = (gnInstanceHandle)userParam;
gnMessageSeverity gryphnSeverity;
if (severity == GL_DEBUG_SEVERITY_HIGH) gryphnSeverity = GN_MESSAGE_ERROR;
else if (severity == GL_DEBUG_SEVERITY_MEDIUM) gryphnSeverity = GN_MESSAGE_WARNING;
else if (severity == GL_DEBUG_SEVERITY_LOW) gryphnSeverity = GN_MESSAGE_WARNING;
else if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) gryphnSeverity = GN_MESSAGE_VERBOSE;
else {
handle->debugger.callback(
GN_MESSAGE_ERROR,
GN_DEBUG_MESSAGE_VALIDATION,
(gnMessageData){ .message = gnCreateString("Uknown severity type from OpenGL") },
handle->debugger.userData
);
}
gnMessageType gryphnType;
if (type == GL_DEBUG_TYPE_ERROR) gryphnType = GN_DEBUG_MESSAGE_VALIDATION;
else if (type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR) gryphnType = GN_DEBUG_MESSAGE_VALIDATION;
else if (type == GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR) gryphnType = GN_DEBUG_MESSAGE_VALIDATION;
else if (type == GL_DEBUG_TYPE_PORTABILITY) gryphnType = GN_DEBUG_MESSAGE_VALIDATION;
else if (type == GL_DEBUG_TYPE_PERFORMANCE) gryphnType = GN_DEBUG_MESSAGE_PERFORMANCE;
else if (type == GL_DEBUG_TYPE_OTHER) gryphnType = GN_DEBUG_MESSAGE_GENERAL;
else {
handle->debugger.callback(
GN_MESSAGE_ERROR,
GN_DEBUG_MESSAGE_VALIDATION,
(gnMessageData){ .message = gnCreateString("Uknown message type from OpenGL") },
handle->debugger.userData
);
}
handle->debugger.callback(
gryphnSeverity,
gryphnType,
(gnMessageData){ .message = gnCreateString(message) },
handle->debugger.userData
);
}
#ifdef GN_PLATFORM_LINUX
#ifdef GN_WINDOW_X11
#include <X11/Xlib.h>
@@ -28,6 +76,10 @@ gnReturnCode createGLXContext(gnWindowSurfaceHandle windowSurface, gnInstanceHan
return GN_UNKNOWN_ERROR;
}
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(openglMessageCallback, instance);
return GN_SUCCESS;
}
@@ -37,6 +89,10 @@ gnUInt2 getWindowSize(gnPlatformWindowSurface* surface) {
return (gnUInt2){ attr.width, attr.height };
}
void swapBuffers(gnWindowSurface surface) {
glXSwapBuffers(surface->windowSurface->display, surface->windowSurface->window);
}
#endif
#ifdef GN_WINFDOW_WAYLAND
@@ -51,11 +107,14 @@ gnSurfaceDetails genOpenGLSurfaceDetails(
) {
gnSurfaceDetails surfaceDetails;
surfaceDetails.formatCount = 1;
surfaceDetails.formats = (gnSurfaceFormat[]){
(gnSurfaceFormat){
surfaceDetails.formats = malloc(sizeof(gnSurfaceFormat) * 2);
surfaceDetails.formats[0] = (gnSurfaceFormat){
.format = GN_FORMAT_RGBA8_SRGB,
.colorSpace = GN_COLOR_SPACE_SRGB_NONLINEAR
}
};
surfaceDetails.formats[1] = (gnSurfaceFormat){
.format = GN_FORMAT_RGBA8,
.colorSpace = GN_COLOR_SPACE_SRGB_NONLINEAR
};
surfaceDetails.minImageCount = 2;
@@ -76,24 +135,26 @@ void destroyOpenGLSurface(gnWindowSurface surface) {
GLint glGryphnFormatToOpenGLFormat(gnImageFormat format) {
switch (format) {
case GN_FORMAT_NONE: return GL_NONE;
case GN_FORMAT_BGRA8: return GL_BGRA;
case GN_FORMAT_RGBA8_SRGB: return GL_SRGB_ALPHA;
case GN_FORMAT_RGBA8: return GL_RGBA;
case GN_FORMAT_RGBA8_SRGB: return GL_RGBA;
case GN_FORMAT_D32S8_UINT: return GL_DEPTH_STENCIL;
case GN_FORMAT_D24S8_UINT: return GL_DEPTH_STENCIL;
// unsupprted formats
case GN_FORMAT_BGRA8: return GL_NONE;
case GN_FORMAT_BGRA8_SRGB: return GL_NONE;
}
}
GLint glGryphnFormatToOpenGLInternalFormat(gnImageFormat format) {
switch (format) {
case GN_FORMAT_NONE: return GL_NONE;
case GN_FORMAT_BGRA8: return GL_BGRA8_EXT;
case GN_FORMAT_RGBA8: return GL_RGBA8;
case GN_FORMAT_RGBA8_SRGB: return GL_SRGB8_ALPHA8;
case GN_FORMAT_D32S8_UINT: return GL_DEPTH32F_STENCIL8;
case GN_FORMAT_D24S8_UINT: return GL_DEPTH24_STENCIL8;
// unsupprted formats
case GN_FORMAT_BGRA8: return GL_NONE;
case GN_FORMAT_BGRA8_SRGB: return GL_NONE;
}
}

View File

@@ -15,6 +15,7 @@ gnReturnCode createGLXContext(gnWindowSurfaceHandle windowSurface, gnInstanceHan
#endif
gnUInt2 getWindowSize(gnPlatformWindowSurface* surface);
void swapBuffers(gnWindowSurface surface);
gnSurfaceDetails genOpenGLSurfaceDetails(gnWindowSurfaceHandle windowSurface, gnPhysicalDevice device);
void destroyOpenGLSurface(gnWindowSurface surface);

View File

@@ -0,0 +1,36 @@
#include "opengl_texture.h"
#include "surface/opengl_surface.h"
GLenum GryphnTargetToOpenGL(gnTextureType type) {
switch(type) {
case GN_TEXTURE_2D: return GL_TEXTURE_2D;
}
}
gnReturnCode openglCreateTexture(gnTexture texture, gnDevice device, const gnTextureInfo info) {
texture->texture = malloc(sizeof(gnPlatformTexture));
glCreateTextures(GryphnTargetToOpenGL(info.type), 1, &texture->texture->id);
glTextureStorage2D(
texture->texture->id,
1,
glGryphnFormatToOpenGLInternalFormat(info.format),
info.extent.x, info.extent.y
);
return GN_SUCCESS;
}
#include "stdio.h"
void openglTextureData(gnTextureHandle texture, void* pixelData) {
printf("OpenGL id: %u\n", texture->texture->id);
glTextureSubImage2D(
texture->texture->id,
0,
0, 0,
texture->info.extent.x, texture->info.extent.y,
GL_RGBA,
GL_UNSIGNED_BYTE,
pixelData
);
}
void openglDestroyTexture(gnTexture texture) {
}

View File

@@ -5,3 +5,7 @@
typedef struct gnPlatformTexture_t {
GLuint id;
} gnPlatformTexture;
gnReturnCode openglCreateTexture(gnTexture texture, gnDevice device, const gnTextureInfo info);
void openglTextureData(gnTextureHandle texture, void* pixelData);
void openglDestroyTexture(gnTexture texture);

View File

@@ -0,0 +1,18 @@
#include "opengl_uniform_pool.h"
#include "uniforms/uniform/opengl_uniform.h"
gnReturnCode openglCreateUniformPool(gnUniformPool pool, gnDeviceHandle device) {
return GN_SUCCESS;
}
gnUniform* openglAllocateUniforms(gnUniformPool pool, const gnUniformAllocationInfo allocInfo) {
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));
for (int c = 0; c < MAX_OPENGL_BINDINGS; c++) uniforms[i]->uniform->bindings[c].isUpdated = GN_FALSE;
}
return uniforms;
}
void openglDestroyUniformPool(gnUniformPool pool) {
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "core/src/uniforms/gryphn_uniform_pool.h"
typedef struct gnPlatformUniformPool_t { gnBool warningAvoider; } gnPlatformUniformPool;
gnReturnCode openglCreateUniformPool(gnUniformPool pool, gnDeviceHandle device);
gnUniform* openglAllocateUniforms(gnUniformPool pool, const gnUniformAllocationInfo allocInfo);
void openglDestroyUniformPool(gnUniformPool pool);

View File

@@ -0,0 +1,17 @@
#include "opengl_uniform.h"
void openglUpdateBufferUniform(gnUniform uniform, gnBufferUniformInfo* info) {
uniform->uniform->bindings[info->binding].isUpdated = GN_TRUE;
uniform->uniform->bindings[info->binding].type = gl_buffer;
uniform->uniform->bindings[info->binding].buffer_info = *info;
}
void openglUpdateStorageUniform(gnUniform uniform, gnStorageUniformInfo* info) {
uniform->uniform->bindings[info->binding].isUpdated = GN_TRUE;
uniform->uniform->bindings[info->binding].type = gl_storage;
uniform->uniform->bindings[info->binding].storage_info = *info;
}
void openglUpdateImageUniform(gnUniform uniform, gnImageUniformInfo* info) {
uniform->uniform->bindings[info->binding].isUpdated = GN_TRUE;
uniform->uniform->bindings[info->binding].type = gl_image;
uniform->uniform->bindings[info->binding].image_info = *info;
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include "glad/glad.h"
#include "core/src/uniforms/gryphn_uniform.h"
#include "shaders/opengl_shader_compiler.h"
typedef enum openglUniformType {
gl_buffer, gl_storage, gl_image
} openglUniformType;
typedef struct glUniformBinding {
openglUniformType type;
union {
gnBufferUniformInfo buffer_info;
gnStorageUniformInfo storage_info;
gnImageUniformInfo image_info;
};
gnBool isUpdated;
} glUniformBinding;
typedef struct gnPlatformUniform_t {
glUniformBinding bindings[MAX_OPENGL_BINDINGS];
} gnPlatformUniform;
void openglUpdateBufferUniform(gnUniform uniform, gnBufferUniformInfo* info);
void openglUpdateStorageUniform(gnUniform uniform, gnStorageUniformInfo* info);
void openglUpdateImageUniform(gnUniform uniform, gnImageUniformInfo* info);

View File

@@ -2,7 +2,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS on)
project(GryphnVulkanImpl)
set(CMAKE_CXX_STANDARD 17)
add_compile_definitions(GN_REVEAL_IMPL)
add_compile_definitions(GN_REVEAL_IMPL GN_IMPLEMENTATION)
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS "src/*.c" "src/*.h")
file(GLOB_RECURSE LOADER_FILES CONFIGURE_DEPENDS "loader/*.c")

View File

@@ -7,15 +7,18 @@
gryphnInstanceFunctionLayers loadVulkanAPILayer(void) {
return (gryphnInstanceFunctionLayers) {
.createInstance = vulkanCreateInstance,
.isSuitable = vulkanIsInstanceSuitable,
.destroyInstance = vulkanDestroyInstance,
.queryDevices = vulkanQueryDevices,
.getPhysicalDeviceProperties = vulkanQueryPhysicalDeviceProperties,
.getPhysicalDeviceFeatures = vulkanQueryPhysicalDeviceFeatures,
.getPhysicalDeviceLimits = vulkanQueryPhysicalDeviceLimits,
.next = NULL
};
}
gnInstanceFunctions loadVulkanInstanceFunctions(void) {
return (gnInstanceFunctions){
._gnGetPhysicalDevices = getPhysicalDevices,
._gnPhysicalDeviceCanPresentToSurface = deviceCanPresentToSurface,
._gnCreateOutputDevice = createVulkanOutputDevice,

View File

@@ -1,12 +1,12 @@
#include "vulkan_device_queues.h"
#include "output_device/vulkan_output_devices.h"
gnReturnCode vulkanPhysicalDeviceQueueProperties(gnPhysicalOutputDeviceHandle device, uint32_t queueFamilyCount, gnQueueFamilyProperties* queues) {
vkGetPhysicalDeviceQueueFamilyProperties(device->physicalDevice->device, &queueFamilyCount, NULL);
gnReturnCode vulkanPhysicalDeviceQueueProperties(gnPhysicalDeviceHandle device, uint32_t queueFamilyCount, gnQueueFamilyProperties* queues) {
vkGetPhysicalDeviceQueueFamilyProperties((VkPhysicalDevice)device, &queueFamilyCount, NULL);
if (queues == NULL) return GN_SUCCESS;
VkQueueFamilyProperties* queueFamilies = malloc(sizeof(VkQueueFamilyProperties) * queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device->physicalDevice->device, &queueFamilyCount, queueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties((VkPhysicalDevice)device, &queueFamilyCount, queueFamilies);
for (uint32_t i = 0; i < queueFamilyCount; i++) {
queues[i].queueCount = queueFamilies[i].queueCount;
@@ -21,8 +21,9 @@ gnReturnCode vulkanPhysicalDeviceQueueProperties(gnPhysicalOutputDeviceHandle de
return GN_SUCCESS;
}
void getVulkanDeviceQueue(gnOutputDevice device, uint32_t queueFamily, uint32_t queueIndex, gnQueue* queue) {
VkQueue vulkanQueue;
vkGetDeviceQueue(device->outputDevice->device, queueFamily, queueIndex, &vulkanQueue);
*queue = (uint64_t)vulkanQueue;
*queue = (gnQueue)vulkanQueue;
}

View File

@@ -4,5 +4,5 @@
#include <output_device/vulkan_physical_device.h>
#include <extensions/queues/gryphn_physcial_device_queue.h>
gnReturnCode vulkanPhysicalDeviceQueueProperties(gnPhysicalOutputDeviceHandle device, uint32_t queueFamilyCount, gnQueueFamilyProperties* queues);
gnReturnCode vulkanPhysicalDeviceQueueProperties(gnPhysicalDeviceHandle device, uint32_t queueFamilyCount, gnQueueFamilyProperties* queues);
void getVulkanDeviceQueue(gnOutputDevice device, uint32_t queueFamily, uint32_t queueIndex, gnQueue* queue);

View File

@@ -1,4 +1,5 @@
#include "vulkan_instance.h"
// #include "output_device/vulkan_physical_device.h"
#include "vulkan_result_converter.h"
GN_ARRAY_LIST_DEFINITION(vkString)
@@ -109,6 +110,17 @@ gnReturnCode vulkanCreateInstance(gnInstanceHandle instance, gnInstanceCreateInf
return VkResultToGnReturnCode(vkCreateInstance(&createInfo, NULL, &instance->instance->vk_instance));
}
gnReturnCode vulkanQueryDevices(gnInstanceHandle handle, uint32_t* count, gnPhysicalDeviceHandle* devices, gryphnInstanceFunctionLayers* next) {
return VkResultToGnReturnCode(vkEnumeratePhysicalDevices(handle->instance->vk_instance, count, (VkPhysicalDevice*)devices));
}
gnBool vulkanIsInstanceSuitable(gnInstanceHandle instance, gnSuitableField field, gryphnInstanceFunctionLayers* next) {
switch (field) {
case GN_NON_EXISTANT_PHYSICAL_DEVICE: return GN_FALSE;
}
return GN_FALSE;
}
void vulkanDestroyInstance(gnInstanceHandle instance, gryphnInstanceFunctionLayers* next, gnAllocators* alloctors) {
if (next != NULL) { return; }
vkDestroyInstance(instance->instance->vk_instance, NULL);

View File

@@ -15,6 +15,8 @@ typedef struct gnPlatformInstance_t {
} gnPlatformInstance;
gnReturnCode vulkanCreateInstance(gnInstanceHandle instance, gnInstanceCreateInfo* instanceInfo, gryphnInstanceFunctionLayers* next, gnAllocators* alloctors);
gnBool vulkanIsInstanceSuitable(gnInstanceHandle instance, gnSuitableField field, gryphnInstanceFunctionLayers* next);
gnReturnCode vulkanQueryDevices(gnInstanceHandle handle, uint32_t* count, gnPhysicalDeviceHandle* devices, gryphnInstanceFunctionLayers* next);
void vulkanDestroyInstance(gnInstanceHandle instance, gryphnInstanceFunctionLayers* next, gnAllocators* alloctors);
typedef const char* vkString;

View File

@@ -8,25 +8,27 @@
#include "vulkan_result_converter.h"
#include "string.h"
#include "stdio.h"
#include <stdio.h>
gnReturnCode createVulkanOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle device, gnOutputDeviceInfo deviceInfo) {
device->outputDevice = malloc(sizeof(gnPlatformOutputDevice));
device->outputDevice->physicalDevice = deviceInfo.physicalDevice->physicalDevice->device;
device->outputDevice->physicalDevice = (VkPhysicalDevice)deviceInfo.physicalDevice;
int createQueueCount = 0;
VkDeviceQueueCreateInfo* queueCreateInfos = NULL;
if (!instance->enabledExtensions[GN_EXT_QUEUES]) {
queueCreateInfos = malloc(sizeof(VkDeviceQueueCreateInfo) * deviceInfo.physicalDevice->physicalDevice->neededQueueCount);
createQueueCount = deviceInfo.physicalDevice->physicalDevice->neededQueueCount;
uint32_t neededQueueCount;
vulkanNeededQueue* neededQueues = vulkanLoadNeededQueues(deviceInfo.physicalDevice, &neededQueueCount);
queueCreateInfos = malloc(sizeof(VkDeviceQueueCreateInfo) * neededQueueCount);
createQueueCount = neededQueueCount;
float queuePriority = 1.0f;
for (uint32_t i = 0; i < deviceInfo.physicalDevice->physicalDevice->neededQueueCount; i++) {
for (uint32_t i = 0; i < neededQueueCount; i++) {
queueCreateInfos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfos[i].pNext = NULL;
queueCreateInfos[i].flags = 0;
queueCreateInfos[i].queueCount = 1;
queueCreateInfos[i].queueFamilyIndex = deviceInfo.physicalDevice->physicalDevice->neededQueues[i].queueIndex;
queueCreateInfos[i].queueFamilyIndex = neededQueues[i].queueIndex;
queueCreateInfos[i].pQueuePriorities = &queuePriority;
}
} else {
@@ -54,7 +56,7 @@ gnReturnCode createVulkanOutputDevice(gnInstanceHandle instance, gnOutputDeviceH
.pQueueCreateInfos = queueCreateInfos,
.pEnabledFeatures = &deviceFeatures
};
deviceCreateInfo.ppEnabledExtensionNames = vkGetGryphnDeviceExtensions(&deviceCreateInfo.enabledExtensionCount, deviceInfo.physicalDevice->physicalDevice->device);
deviceCreateInfo.ppEnabledExtensionNames = vkGetGryphnDeviceExtensions(&deviceCreateInfo.enabledExtensionCount, (VkPhysicalDevice)deviceInfo.physicalDevice);
device->outputDevice->enabledOversizedDescriptorPools = GN_FALSE;
for (uint32_t i = 0; i < deviceCreateInfo.enabledExtensionCount; i++)
@@ -67,18 +69,16 @@ gnReturnCode createVulkanOutputDevice(gnInstanceHandle instance, gnOutputDeviceH
deviceCreateInfo.enabledLayerCount = 1;
deviceCreateInfo.ppEnabledLayerNames = validation_layers;
}
VkResult result = vkCreateDevice(deviceInfo.physicalDevice->physicalDevice->device, &deviceCreateInfo, NULL, &device->outputDevice->device);
VkResult result = vkCreateDevice((VkPhysicalDevice)deviceInfo.physicalDevice, &deviceCreateInfo, NULL, &device->outputDevice->device);
if (result != VK_SUCCESS)
return VkResultToGnReturnCode(result);
device->outputDevice->queues = malloc(sizeof(vulkanQueue) * deviceInfo.physicalDevice->physicalDevice->neededQueueCount);
device->outputDevice->queues = malloc(sizeof(vulkanQueue) * createQueueCount);
uint32_t transferQueue = 0;
gnBool foundTransferQueue = GN_FALSE, foundGraphicsQueue = GN_FALSE;
for (uint32_t i = 0; i < deviceInfo.physicalDevice->physicalDevice->neededQueueCount; i++) {
device->outputDevice->queues[i].queueInfo = deviceInfo.physicalDevice->physicalDevice->neededQueues[i];
vkGetDeviceQueue(device->outputDevice->device, deviceInfo.physicalDevice->physicalDevice->neededQueues[i].queueIndex, 0, &device->outputDevice->queues[i].queue);
for (uint32_t i = 0; i < createQueueCount; i++) {
vkGetDeviceQueue(device->outputDevice->device, queueCreateInfos[i].queueFamilyIndex, 0, &device->outputDevice->queues[i].queue);
if ((device->outputDevice->queues[i].queueInfo.createFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT && !foundTransferQueue) {
device->outputDevice->transferQueueIndex = i;
transferQueue = device->outputDevice->queues[i].queueInfo.queueIndex;
@@ -89,7 +89,12 @@ gnReturnCode createVulkanOutputDevice(gnInstanceHandle instance, gnOutputDeviceH
device->outputDevice->graphicsQueueIndex = i;
foundGraphicsQueue = GN_FALSE;
}
if ((device->outputDevice->queues[i].queueInfo.createFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT && !foundGraphicsQueue) {
device->outputDevice->graphicsQueueIndex = i;
foundGraphicsQueue = GN_FALSE;
}
}
VkCommandPoolCreateInfo poolInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,

View File

@@ -3,8 +3,120 @@
#include <output_device/vulkan_device_extensions.h>
#include <vulkan_surface/vulkan_surface.h>
gnMultisampleCountFlags vkSampleCountToGryphn(VkSampleCountFlags counts) {
gnMultisampleCountFlags sampleCount = 0;
inline gnPhysicalDeviceType vulkanDeviceTypeToGryphn(VkPhysicalDeviceType type) {
switch (type) {
case VK_PHYSICAL_DEVICE_TYPE_OTHER: return GN_PHYSICAL_DEVICE_TYPE_FAKED_GPU;
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return GN_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return GN_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return GN_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU;
case VK_PHYSICAL_DEVICE_TYPE_CPU: return GN_PHYSICAL_DEVICE_TYPE_CPU;
case VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM: return GN_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU; // WE SHOULD NEVER HAVE TO DEAL WITH THIS ERROR
}
}
gnPhysicalDeviceProperties vulkanQueryPhysicalDeviceProperties(gnInstance instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* layers) {
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties((VkPhysicalDevice)device, &properties);
return (gnPhysicalDeviceProperties){
.deviceID = properties.deviceID,
.deviceName = gnCreateString(properties.deviceName),
.deviceType = vulkanDeviceTypeToGryphn(properties.deviceType),
.driverVersion = properties.driverVersion
};
}
gnPhysicalDeviceFeatures vulkanQueryPhysicalDeviceFeatures(gnInstance instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* layers) {
VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures((VkPhysicalDevice)device, &features);
return (gnPhysicalDeviceFeatures){
.uint32Index = features.fullDrawIndexUint32,
.geometryShader = features.geometryShader,
.tessellationShader = features.tessellationShader,
.multiDrawIndirect = features.multiDrawIndirect,
.drawIndirectFirstInstance = features.drawIndirectFirstInstance,
.fillModeNonSolid = features.fillModeNonSolid,
.wideLines = features.wideLines,
.largePoints = features.largePoints,
.samplerAnisotropy = features.samplerAnisotropy
};
}
gnPhysicalDeviceLimits vulkanQueryPhysicalDeviceLimits(gnInstance instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* layers) {
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties((VkPhysicalDevice)device, &properties);
VkPhysicalDeviceLimits limits = properties.limits;
return (gnPhysicalDeviceLimits) {
.maxImageExtent1D = limits.maxImageDimension1D,
.maxImageExtent2D = limits.maxImageDimension2D,
.maxImageExtent3D = limits.maxImageDimension3D,
.maxImageExtentCube = limits.maxImageDimensionCube,
.maxImageArrayLayers = limits.maxImageArrayLayers,
.maxTexelBufferElements = limits.maxTexelBufferElements,
.maxUniformBufferRange = limits.maxUniformBufferRange,
.maxStorageBufferRange = limits.maxStorageBufferRange,
.maxPushConstantsSize = limits.maxPushConstantsSize,
.maxMemoryAllocationCount = limits.maxMemoryAllocationCount,
.maxSamplerAllocationCount = limits.maxSamplerAllocationCount,
.maxBoundUniforms = limits.maxBoundDescriptorSets,
.maxPerStageUniformSamplers = limits.maxPerStageDescriptorSamplers,
.maxPerStageUniformUniformBuffers = limits.maxPerStageDescriptorUniformBuffers,
.maxPerStageUniformStorageBuffers = limits.maxPerStageDescriptorStorageBuffers,
.maxPerStageUniformSampledImages = limits.maxPerStageDescriptorSampledImages,
.maxPerStageUniformStorageImages = limits.maxPerStageDescriptorStorageBuffers,
.maxPerStageUniformInputAttachments = limits.maxPerStageDescriptorInputAttachments,
.maxPerStageResources = limits.maxPerStageResources,
.maxUniformSamplers = limits.maxPerStageDescriptorSamplers,
.maxUniformUniformBuffers = limits.maxDescriptorSetUniformBuffers,
.maxUniformUniformBuffersDynamic = limits.maxDescriptorSetUniformBuffersDynamic,
.maxUniformStorageBuffers = limits.maxDescriptorSetStorageBuffers,
.maxUniformStorageBuffersDynamic = limits.maxDescriptorSetStorageBuffersDynamic,
.maxUniformSampledImages = limits.maxDescriptorSetSampledImages,
.maxUniformStorageImages = limits.maxPerStageDescriptorStorageImages,
.maxUniformInputAttachments = limits.maxDescriptorSetInputAttachments,
.maxVertexInputAttributes = limits.maxVertexInputAttributes,
.maxVertexInputBindings = limits.maxVertexInputBindings,
.maxVertexInputAttributeOffset = limits.maxVertexInputAttributeOffset,
.maxVertexInputBindingStride = limits.maxVertexInputBindingStride,
.maxVertexOutputComponents = limits.maxVertexOutputComponents,
.maxTessellationGenerationLevel = limits.maxTessellationGenerationLevel,
.maxTessellationPatchSize = limits.maxTessellationPatchSize,
.maxTessellationControlPerVertexInputComponents = limits.maxTessellationControlPerVertexInputComponents,
.maxTessellationControlPerVertexOutputComponents = limits.maxTessellationControlPerVertexOutputComponents,
.maxTessellationControlPerPatchOutputComponents = limits.maxTessellationControlPerPatchOutputComponents,
.maxTessellationControlTotalOutputComponents = limits.maxTessellationControlTotalOutputComponents,
.maxTessellationEvaluationInputComponents = limits.maxTessellationEvaluationInputComponents,
.maxTessellationEvaluationOutputComponents = limits.maxTessellationControlPerVertexOutputComponents,
.maxGeometryShaderInvocations = limits.maxGeometryShaderInvocations,
.maxGeometryInputComponents = limits.maxGeometryInputComponents,
.maxGeometryOutputComponents = limits.maxGeometryOutputComponents,
.maxGeometryOutputVertices = limits.maxGeometryOutputVertices,
.maxGeometryTotalOutputComponents = limits.maxGeometryTotalOutputComponents,
.maxFragmentInputComponents = limits.maxFragmentInputComponents,
.maxFragmentOutputAttachments = limits.maxFragmentOutputAttachments,
.maxFragmentDualSrcAttachments = limits.maxFragmentDualSrcAttachments,
.maxFragmentCombinedOutputResources = limits.maxFragmentCombinedOutputResources,
.maxDrawIndexedIndexValue = limits.maxDrawIndexedIndexValue,
.maxDrawIndirectCount = limits.maxDrawIndirectCount,
.maxSamplerLodBias = limits.maxSamplerLodBias,
.maxSamplerAnisotropy = limits.maxSamplerAnisotropy,
.maxViewports = limits.maxViewports,
.maxViewportExtents = { limits.maxViewportDimensions[0], limits.maxViewportDimensions[1] },
.viewportBoundsRange = { limits.viewportBoundsRange[0], limits.viewportBoundsRange[1] },
.maxFramebufferExtent = {limits.maxFramebufferWidth, limits.maxFramebufferHeight},
.maxFramebufferLayers = limits.maxFramebufferLayers,
.framebufferColorSampleCounts = vkSampleCountToGryphn(limits.framebufferColorSampleCounts),
.framebufferDepthSampleCounts = vkSampleCountToGryphn(limits.framebufferDepthSampleCounts),
.framebufferStencilSampleCounts = vkSampleCountToGryphn(limits.framebufferStencilSampleCounts),
.framebufferNoAttachmentsSampleCounts = vkSampleCountToGryphn(limits.framebufferNoAttachmentsSampleCounts),
.maxColorAttachments = limits.maxColorAttachments,
.pointSizeRange = { limits.pointSizeRange[0], limits.pointSizeRange[1] },
.lineWidthRange = { limits.lineWidthRange[0], limits.lineWidthRange[1] },
.pointSizeGranularity = limits.pointSizeGranularity,
.lineWidthGranularity = limits.lineWidthGranularity,
.strictLines = limits.strictLines
};
}
gnSampleCountFlags vkSampleCountToGryphn(VkSampleCountFlags counts) {
gnSampleCountFlags sampleCount = 0;
if ((counts & VK_SAMPLE_COUNT_64_BIT) == VK_SAMPLE_COUNT_64_BIT) { sampleCount |= GN_SAMPLE_BIT_64; }
if ((counts & VK_SAMPLE_COUNT_32_BIT) == VK_SAMPLE_COUNT_32_BIT) { sampleCount |= GN_SAMPLE_BIT_32; }
if ((counts & VK_SAMPLE_COUNT_16_BIT) == VK_SAMPLE_COUNT_16_BIT) { sampleCount |= GN_SAMPLE_BIT_16; }
@@ -15,9 +127,7 @@ gnMultisampleCountFlags vkSampleCountToGryphn(VkSampleCountFlags counts) {
return sampleCount;
}
#include <stdio.h>
VkSampleCountFlags gnSampleCountToVulkan(gnMultisampleCountFlags counts) {
VkSampleCountFlags gnSampleCountToVulkan(gnSampleCountFlags counts) {
VkSampleCountFlags sampleCount = 0;
if ((counts & GN_SAMPLE_BIT_64) == GN_SAMPLE_BIT_64) { sampleCount |= VK_SAMPLE_COUNT_64_BIT; }
@@ -31,20 +141,28 @@ VkSampleCountFlags gnSampleCountToVulkan(gnMultisampleCountFlags counts) {
return sampleCount;
}
void vulkanLoadNeededQueues(VkPhysicalDevice vulkanDevice, gnPhysicalDevice gryphnDevice) {
vulkanNeededQueue* vulkanLoadNeededQueues(gnPhysicalDevice physicalDevice, uint32_t* neededQueueCount) {
VkPhysicalDevice device = (VkPhysicalDevice)physicalDevice;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(vulkanDevice, &queueFamilyCount, NULL);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, NULL);
VkQueueFamilyProperties* queueFamilies = malloc(sizeof(VkQueueFamilyProperties) * queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(vulkanDevice, &queueFamilyCount, queueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies);
*neededQueueCount = 0;
gnBool foundGraphicsQueue = GN_FALSE, foundTransferQueue = GN_FALSE;
vulkanNeededQueue* neededQueues = malloc(sizeof(vulkanNeededQueue) * queueFamilyCount);
gryphnDevice->physicalDevice->neededQueues = malloc(sizeof(vulkanNeededQueue) * queueFamilyCount);
for (uint32_t c = 0; c < queueFamilyCount; c++) {
gnBool hasNeededQueue = GN_FALSE;
if ((queueFamilies[c].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT)
if ((queueFamilies[c].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT && !foundGraphicsQueue) {
hasNeededQueue = GN_TRUE;
if ((queueFamilies[c].queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT)
foundGraphicsQueue = GN_TRUE;
}
if ((queueFamilies[c].queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT && !foundTransferQueue) {
hasNeededQueue = GN_TRUE;
foundTransferQueue = GN_TRUE;
}
if (hasNeededQueue) {
vulkanNeededQueue neededQueue = {
@@ -55,98 +173,23 @@ void vulkanLoadNeededQueues(VkPhysicalDevice vulkanDevice, gnPhysicalDevice gryp
if ((queueFamilies[c].queueFlags & VK_QUEUE_GRAPHICS_BIT)) neededQueue.createFlags |= VK_QUEUE_GRAPHICS_BIT;
if ((queueFamilies[c].queueFlags & VK_QUEUE_TRANSFER_BIT)) neededQueue.createFlags |= VK_QUEUE_TRANSFER_BIT;
gryphnDevice->physicalDevice->neededQueues[gryphnDevice->physicalDevice->neededQueueCount] = neededQueue;
gryphnDevice->physicalDevice->neededQueueCount++;
neededQueues[*neededQueueCount] = neededQueue;
(*neededQueueCount)++;
}
}
free(queueFamilies);
neededQueues = realloc(neededQueues, sizeof(vulkanNeededQueue) * *neededQueueCount);
return neededQueues;
}
gnPhysicalDevice* getPhysicalDevices(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 (uint32_t i = 0; i < *deviceCount; i++) {
outputDevices[i] = malloc(sizeof(gnPhysicalOutputDevice_t));
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;
}
if (instance->enabledExtensions[GN_EXT_QUEUES] == GN_FALSE)
vulkanLoadNeededQueues(physicalDevices[i], outputDevices[i]);
VkPhysicalDeviceProperties physicalDeviceProperties;
vkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties);
outputDevices[i]->features.maxColorSamples = vkSampleCountToGryphn(physicalDeviceProperties.limits.framebufferColorSampleCounts);
outputDevices[i]->features.maxDepthSamples = vkSampleCountToGryphn(physicalDeviceProperties.limits.framebufferDepthSampleCounts);
outputDevices[i]->features.maxMemoryAllocations = physicalDeviceProperties.limits.maxMemoryAllocationCount;
outputDevices[i]->features.maxPushConstantSize = physicalDeviceProperties.limits.maxPushConstantsSize;
}
free(physicalDevices);
return outputDevices;
}
gnBool deviceCanPresentToSurface(gnPhysicalDevice device, gnWindowSurface surface) {
gnBool deviceCanPresentToSurface(gnInstance instance, gnPhysicalDevice physicalDevice, gnWindowSurface surface) {;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device->physicalDevice->device, &queueFamilyCount, NULL);
vkGetPhysicalDeviceQueueFamilyProperties((VkPhysicalDevice)physicalDevice, &queueFamilyCount, NULL);
for (uint32_t i = 0; i < queueFamilyCount; i++) {
VkBool32 supportsPresent;
vkGetPhysicalDeviceSurfaceSupportKHR(device->physicalDevice->device, i, surface->windowSurface->surface, &supportsPresent);
vkGetPhysicalDeviceSurfaceSupportKHR((VkPhysicalDevice)physicalDevice, i, surface->windowSurface->surface, &supportsPresent);
if (supportsPresent) return GN_TRUE;
}
return GN_FALSE;
}
// gnBool foundQueue = GN_FALSE;
// for (uint32_t i = 0; i < device->physicalDevice->neededQueueCount; i++) {
// VkBool32 supportsPresent = VK_FALSE;
// vkGetPhysicalDeviceSurfaceSupportKHR(device->physicalDevice->device, device->physicalDevice->neededQueues[i].queueIndex, surface->windowSurface->surface, &supportsPresent);
// if (supportsPresent) {
// device->physicalDevice->neededQueues[i].usedForPresent = GN_TRUE;
// foundQueue = GN_TRUE;
// break;
// }
// surface->windowSurface->presentQueueIndex = i;
// }
// if (!foundQueue) {
// uint32_t queueFamilyCount = 0;
// vkGetPhysicalDeviceQueueFamilyProperties(device->physicalDevice->device, &queueFamilyCount, NULL);
// for (uint32_t i = 0; i < queueFamilyCount; i++) {
// VkBool32 supportsPresent = VK_FALSE;
// vkGetPhysicalDeviceSurfaceSupportKHR(device->physicalDevice->device, i, surface->windowSurface->surface, &supportsPresent);
// if (supportsPresent) {
// device->physicalDevice->neededQueues[device->physicalDevice->neededQueueCount] = (vulkanNeededQueue){
// .queueIndex = i,
// .createFlags = 0,
// .usedForPresent = GN_TRUE
// };
// foundQueue = GN_TRUE;
// surface->windowSurface->presentQueueIndex = device->physicalDevice->neededQueueCount;
// device->physicalDevice->neededQueueCount++;
// break;
// }
// }
// }
// return foundQueue;

View File

@@ -1,23 +1,19 @@
#pragma once
#include "loader/src/gryphn_instance_functions.h"
#include <vulkan/vulkan.h>
#include <output_device/gryphn_physical_output_device.h>
#include <output_device/gryphn_physical_device.h>
typedef struct vulkanNeededQueue {
VkQueueFlags createFlags;
gnBool usedForPresent;
uint32_t queueIndex;
} vulkanNeededQueue;
vulkanNeededQueue* vulkanLoadNeededQueues(gnPhysicalDevice physicalDevice, uint32_t* neededQueueCount);
typedef struct gnPlatformPhysicalDevice_t {
VkPhysicalDevice device;
uint32_t neededQueueCount;
vulkanNeededQueue* neededQueues;
gnPhysicalDeviceProperties vulkanQueryPhysicalDeviceProperties(gnInstance instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* layers);
gnPhysicalDeviceFeatures vulkanQueryPhysicalDeviceFeatures(gnInstance instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* layers);
gnPhysicalDeviceLimits vulkanQueryPhysicalDeviceLimits(gnInstance instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* layers);
} gnPlatformPhysicalDevice;
gnPhysicalDevice* getPhysicalDevices(gnInstanceHandle instance, uint32_t* deviceCount);
gnBool deviceCanPresentToSurface(gnPhysicalDevice device, gnWindowSurface surface);
gnMultisampleCountFlags vkSampleCountToGryphn(VkSampleCountFlags counts);
VkSampleCountFlags gnSampleCountToVulkan(gnMultisampleCountFlags counts);
gnBool deviceCanPresentToSurface(gnInstance instance, gnPhysicalDevice device, gnWindowSurface surface);
gnSampleCountFlags vkSampleCountToGryphn(VkSampleCountFlags counts);
VkSampleCountFlags gnSampleCountToVulkan(gnSampleCountFlags counts);

View File

@@ -144,8 +144,15 @@ void VkCopyBufferToImage(VkGryphnBuffer buffer, VkGryphnImage image, gnExtent3D
gnReturnCode createTexture(gnTexture texture, gnDevice device, const gnTextureInfo info) {
texture->texture = malloc(sizeof(struct gnPlatformTexture_t));
size_t imageSize = info.extent.width * info.extent.height;
if (info.format == GN_FORMAT_BGRA8_SRGB) { imageSize *= 4; }
if (info.format == GN_FORMAT_RGBA8_SRGB) { imageSize *= 4; }
switch (info.format) {
case GN_FORMAT_NONE: imageSize *= 0; break;
case GN_FORMAT_BGRA8_SRGB: imageSize *= 4; break;
case GN_FORMAT_BGRA8: imageSize *= 4; break;
case GN_FORMAT_RGBA8: imageSize *= 4; break;
case GN_FORMAT_RGBA8_SRGB: imageSize *= 4; break;
case GN_FORMAT_D32S8_UINT: imageSize *= 5; break;
case GN_FORMAT_D24S8_UINT: imageSize *= 4; break;
};
texture->texture->size = imageSize;
VkImageCreateInfo imageInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,

View File

@@ -2,7 +2,6 @@
#include <instance/vulkan_instance.h>
#include "vulkan_surface.h"
#include <output_device/vulkan_physical_device.h>
#include "vulkan_result_converter.h"
#ifdef GN_PLATFORM_LINUX
#ifdef GN_WINDOW_X11
@@ -57,16 +56,17 @@ void destroyWindowSurface(struct gnWindowSurface_t* windowSurface) {
}
gnSurfaceFormat* vkGetSurfaceFormats(
struct gnWindowSurface_t* windowSurface, gnPhysicalDevice device, uint32_t* formatCount
struct gnWindowSurface_t* windowSurface, gnPhysicalDevice deviceHandle, uint32_t* formatCount
) {
gnSurfaceFormat* formats = NULL;
VkPhysicalDevice device = (VkPhysicalDevice)deviceHandle;
vkGetPhysicalDeviceSurfaceFormatsKHR(device->physicalDevice->device, windowSurface->windowSurface->surface, formatCount, NULL);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, windowSurface->windowSurface->surface, formatCount, NULL);
formats = malloc(sizeof(gnSurfaceFormat) * *formatCount);
VkSurfaceFormatKHR* vkFormats = malloc(sizeof(VkSurfaceFormatKHR) * *formatCount);;
if (*formatCount > 0) {
vkGetPhysicalDeviceSurfaceFormatsKHR(device->physicalDevice->device, windowSurface->windowSurface->surface, formatCount, vkFormats);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, windowSurface->windowSurface->surface, formatCount, vkFormats);
for (uint32_t i = 0; i < *formatCount; i++) {
switch (vkFormats[i].format) {
case VK_FORMAT_B8G8R8A8_SRGB: { formats[i].format = GN_FORMAT_BGRA8_SRGB; break; }
@@ -85,13 +85,13 @@ gnSurfaceFormat* vkGetSurfaceFormats(
}
gnSurfaceDetails getSurfaceDetails(
gnWindowSurfaceHandle windowSurface, gnPhysicalDevice device
gnWindowSurfaceHandle windowSurface, gnPhysicalDevice deviceHandle
) {
gnSurfaceDetails surfaceDetails;
surfaceDetails.formats = vkGetSurfaceFormats(windowSurface, device, &surfaceDetails.formatCount);
surfaceDetails.formats = vkGetSurfaceFormats(windowSurface, deviceHandle, &surfaceDetails.formatCount);
VkSurfaceCapabilitiesKHR details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physicalDevice->device, windowSurface->windowSurface->surface, &details);
vkGetPhysicalDeviceSurfaceCapabilitiesKHR((VkPhysicalDevice)deviceHandle, windowSurface->windowSurface->surface, &details);
surfaceDetails.minImageCount = details.minImageCount;
surfaceDetails.maxImageCount = details.maxImageCount;
@@ -109,6 +109,7 @@ VkFormat vkGryphnFormatToVulkanFormat(gnImageFormat format) {
case GN_FORMAT_NONE: return VK_FORMAT_UNDEFINED;
case GN_FORMAT_BGRA8_SRGB: return VK_FORMAT_B8G8R8A8_SRGB;
case GN_FORMAT_BGRA8: return VK_FORMAT_B8G8R8A8_UNORM;
case GN_FORMAT_RGBA8: return VK_FORMAT_R8G8B8A8_UNORM;
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;

View File

@@ -2,8 +2,9 @@
typedef enum gnImageFormat {
GN_FORMAT_NONE,
GN_FORMAT_BGRA8_SRGB,
GN_FORMAT_BGRA8,
GN_FORMAT_BGRA8_SRGB,
GN_FORMAT_RGBA8,
GN_FORMAT_RGBA8_SRGB,
GN_FORMAT_D24S8_UINT,
GN_FORMAT_D32S8_UINT,

View File

@@ -2,8 +2,6 @@
#include "command/command_pool/gryphn_command_pool.h"
#include "instance/gryphn_instance.h"
#include "stdio.h"
gnReturnCode gnCommandPoolAllocateCommandBuffersFromPointer(gnCommandBufferHandle* buffers, uint32_t count, gnCommandPoolHandle commandPool) {
for (uint32_t i = 0; i < count; i++) {
buffers[i] = malloc(sizeof(struct gnCommandBuffer_t));

View File

@@ -10,9 +10,15 @@ typedef struct type##_t* type##Handle; \
typedef struct type##_t* type
// The value of this handle is defined by the implementation
#ifndef GN_IMPLEMENTATION
#define GN_IMPLEMENTATION_HANDLE(type) \
typedef uint64_t type##Handle; \
typedef uint64_t type
#else
#define GN_IMPLEMENTATION_HANDLE(type) \
typedef uint64_t type##Handle; \
typedef uint64_t type
#endif
// can be used to alias a normal handle or an implementation handle
#define GN_HANDLE_ALIAS(handle, alias) \
@@ -20,14 +26,12 @@ typedef struct handle##_t* alias##Handle; \
typedef struct handle##_t* alias
GN_HANDLE(gnInstance);
GN_IMPLEMENTATION_HANDLE(gnPhysicalDevice); // NOTE: needs to become a impl handle
GN_HANDLE(gnWindowSurface);
GN_HANDLE(gnPresentationQueue);
GN_HANDLE(gnTexture);
GN_HANDLE(gnRenderPassDescriptor);
GN_HANDLE(gnPhysicalOutputDevice);
GN_HANDLE_ALIAS(gnPhysicalOutputDevice, gnPhysicalDevice);
GN_HANDLE(gnOutputDevice);
GN_HANDLE_ALIAS(gnOutputDevice, gnDevice);
GN_HANDLE(gnShaderModule);

View File

@@ -84,6 +84,14 @@ gnReturnCode gnCreateInstance(gnInstanceHandle* instance, gnInstanceCreateInfo*
return (*instance)->functions->createInstance(*instance, info, (*instance)->functions->next, &(*instance)->allocators);
}
gnBool gnIsInstanceSuitable(gnInstance instance, gnSuitableField field) {
return instance->functions->isSuitable(instance, field, instance->functions->next);
}
gnReturnCode gnInstanceQueryDevices(gnInstanceHandle instance, uint32_t* count, gnPhysicalDeviceHandle* devices) {
return instance->functions->queryDevices(instance, count, devices, instance->functions->next);
}
void gnDestroyInstance(gnInstanceHandle* instance) {
if (instance == GN_NULL_HANDLE) return;
(*instance)->functions->destroyInstance(*instance, (*instance)->functions->next, &(*instance)->allocators);

View File

@@ -7,7 +7,6 @@
#include "gryphn_allocators.h"
#include <gryphn_extensions.h>
typedef struct gnApplicationInfo {
gnString applicationName;
gnVersion applicationVersion;
@@ -16,6 +15,10 @@ typedef struct gnApplicationInfo {
gnVersion engineVersion;
} gnApplicationInfo;
typedef enum gnSuitableField {
GN_NON_EXISTANT_PHYSICAL_DEVICE
} gnSuitableField;
typedef struct gnInstanceCreateInfo {
gnApplicationInfo applicationInfo;
gnDebuggerCreateInfo debuggerInfo;
@@ -45,4 +48,6 @@ struct gnInstance_t {
#endif
gnReturnCode gnCreateInstance(gnInstanceHandle* instance, gnInstanceCreateInfo* info);
gnBool gnIsInstanceSuitable(gnInstance instance, gnSuitableField field);
gnReturnCode gnInstanceQueryDevices(gnInstanceHandle instance, uint32_t* count, gnPhysicalDeviceHandle* devices);
void gnDestroyInstance(gnInstanceHandle* instance);

View File

@@ -1,5 +1,5 @@
#pragma once
#include <output_device/gryphn_physical_output_device.h>
#include <output_device/gryphn_physical_device.h>
#include <core/gryphn_return_code.h>
typedef struct gnOutputDeviceEnabledFeatures {
@@ -24,7 +24,6 @@ typedef struct gnOutputDeviceInfo {
struct gnOutputDevice_t {
struct gnPlatformOutputDevice_t* outputDevice;
gnOutputDeviceInfo deviceInfo;
gnInstanceHandle instance;
};
#endif

View File

@@ -0,0 +1,19 @@
#include "gryphn_physical_device.h"
#include "instance/gryphn_instance.h"
#include "loader/src/gryphn_instance_functions.h"
gnPhysicalDeviceProperties gnQueryPhysicalDeviceProperties(gnInstanceHandle instance, gnPhysicalDeviceHandle device) {
return instance->functions->getPhysicalDeviceProperties(instance, device, instance->functions->next);
}
gnPhysicalDeviceFeatures gnQueryPhysicalDeviceFeatures(gnInstanceHandle instance, gnPhysicalDeviceHandle device) {
return instance->functions->getPhysicalDeviceFeatures(instance, device, instance->functions->next);
}
gnPhysicalDeviceLimits gnQueryPhysicalDeviceLimits(gnInstanceHandle instance, gnPhysicalDeviceHandle device) {
return instance->functions->getPhysicalDeviceLimits(instance, device, instance->functions->next);
}
gnBool gnPhysicalDeviceCanPresentToSurface(gnInstanceHandle instance, gnPhysicalDeviceHandle device, gnWindowSurfaceHandle windowSurface) {
return instance->callingLayer->instanceFunctions._gnPhysicalDeviceCanPresentToSurface(instance, device, windowSurface);
}

View File

@@ -0,0 +1,119 @@
#pragma once
#include "stdint.h"
#include "utils/gryphn_string.h"
#include "gryphn_handles.h"
#include <utils/math/gryphn_vec2.h>
typedef enum gnPhysicalDeviceType {
GN_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
GN_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
GN_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
GN_PHYSICAL_DEVICE_TYPE_FAKED_GPU,
GN_PHYSICAL_DEVICE_TYPE_CPU,
} gnPhysicalDeviceType;
typedef enum gnSampleCountFlags {
GN_SAMPLE_BIT_1 = 1 << 0, // 0x01
GN_SAMPLE_BIT_2 = 1 << 1, // 0x02
GN_SAMPLE_BIT_4 = 1 << 2, // 0x04
GN_SAMPLE_BIT_8 = 1 << 3, // 0x08
GN_SAMPLE_BIT_16 = 1 << 4, // 0x10
GN_SAMPLE_BIT_32 = 1 << 5, // 0x20
GN_SAMPLE_BIT_64 = 1 << 6, // 0x40
} gnSampleCountFlags;
typedef struct gnPhysicalDeviceProperties {
uint32_t driverVersion;
uint32_t deviceID;
gnString deviceName;
gnPhysicalDeviceType deviceType;
} gnPhysicalDeviceProperties;
typedef struct gnPhysicalDeviceFeatures {
gnBool uint32Index;
gnBool geometryShader;
gnBool tessellationShader;
gnBool multiDrawIndirect;
gnBool drawIndirectFirstInstance;
gnBool fillModeNonSolid;
gnBool wideLines;
gnBool largePoints;
gnBool samplerAnisotropy;
} gnPhysicalDeviceFeatures;
typedef struct gnPhysicalDeviceLimits {
uint32_t maxImageExtent1D;
uint32_t maxImageExtent2D;
uint32_t maxImageExtent3D;
uint32_t maxImageExtentCube;
uint32_t maxImageArrayLayers;
uint32_t maxTexelBufferElements;
uint32_t maxUniformBufferRange;
uint32_t maxStorageBufferRange;
uint32_t maxPushConstantsSize;
uint32_t maxMemoryAllocationCount;
uint32_t maxSamplerAllocationCount;
uint32_t maxBoundUniforms;
uint32_t maxPerStageUniformSamplers;
uint32_t maxPerStageUniformUniformBuffers;
uint32_t maxPerStageUniformStorageBuffers;
uint32_t maxPerStageUniformSampledImages;
uint32_t maxPerStageUniformStorageImages;
uint32_t maxPerStageUniformInputAttachments;
uint32_t maxPerStageResources;
uint32_t maxUniformSamplers;
uint32_t maxUniformUniformBuffers;
uint32_t maxUniformUniformBuffersDynamic;
uint32_t maxUniformStorageBuffers;
uint32_t maxUniformStorageBuffersDynamic;
uint32_t maxUniformSampledImages;
uint32_t maxUniformStorageImages;
uint32_t maxUniformInputAttachments;
uint32_t maxVertexInputAttributes;
uint32_t maxVertexInputBindings;
uint32_t maxVertexInputAttributeOffset;
uint32_t maxVertexInputBindingStride;
uint32_t maxVertexOutputComponents;
uint32_t maxTessellationGenerationLevel;
uint32_t maxTessellationPatchSize;
uint32_t maxTessellationControlPerVertexInputComponents;
uint32_t maxTessellationControlPerVertexOutputComponents;
uint32_t maxTessellationControlPerPatchOutputComponents;
uint32_t maxTessellationControlTotalOutputComponents;
uint32_t maxTessellationEvaluationInputComponents;
uint32_t maxTessellationEvaluationOutputComponents;
uint32_t maxGeometryShaderInvocations;
uint32_t maxGeometryInputComponents;
uint32_t maxGeometryOutputComponents;
uint32_t maxGeometryOutputVertices;
uint32_t maxGeometryTotalOutputComponents;
uint32_t maxFragmentInputComponents;
uint32_t maxFragmentOutputAttachments;
uint32_t maxFragmentDualSrcAttachments;
uint32_t maxFragmentCombinedOutputResources;
uint32_t maxDrawIndexedIndexValue;
uint32_t maxDrawIndirectCount;
float maxSamplerLodBias;
float maxSamplerAnisotropy;
uint32_t maxViewports;
uint32_t maxViewportExtents[2];
float viewportBoundsRange[2];
gnExtent2D maxFramebufferExtent;
uint32_t maxFramebufferLayers;
gnSampleCountFlags framebufferColorSampleCounts;
gnSampleCountFlags framebufferDepthSampleCounts;
gnSampleCountFlags framebufferStencilSampleCounts;
gnSampleCountFlags framebufferNoAttachmentsSampleCounts;
uint32_t maxColorAttachments;
float pointSizeRange[2];
float lineWidthRange[2];
float pointSizeGranularity;
float lineWidthGranularity;
gnBool strictLines;
} gnPhysicalDeviceLimits;
gnPhysicalDeviceProperties gnQueryPhysicalDeviceProperties(gnInstanceHandle instance, gnPhysicalDeviceHandle device);
gnPhysicalDeviceFeatures gnQueryPhysicalDeviceFeatures(gnInstanceHandle instance, gnPhysicalDeviceHandle device);
gnPhysicalDeviceLimits gnQueryPhysicalDeviceLimits(gnInstanceHandle instance, gnPhysicalDeviceHandle device);
gnBool gnPhysicalDeviceCanPresentToSurface(gnInstance instance, gnPhysicalDeviceHandle device, gnWindowSurfaceHandle windowSurface);

View File

@@ -1,17 +0,0 @@
#include "gryphn_physical_output_device.h"
#include "instance/gryphn_instance.h"
#include "loader/src/gryphn_instance_functions.h"
gnPhysicalOutputDeviceHandle* gnGetPhyscialDevices(gnInstanceHandle instance, uint32_t* count) {;
gnPhysicalOutputDeviceHandle* devices = instance->callingLayer->instanceFunctions._gnGetPhysicalDevices(instance, count);
for (uint32_t i = 0; i < *count; i++)
devices[i]->instance = instance;
return devices;
}
gnBool gnPhysicalDeviceCanPresentToSurface(gnPhysicalOutputDeviceHandle device, gnWindowSurfaceHandle windowSurface) {
return device->instance->callingLayer->instanceFunctions._gnPhysicalDeviceCanPresentToSurface(device, windowSurface);
}
gnPhysicalDeviceProperties gnGetPhysicalDeviceProperties(gnPhysicalOutputDeviceHandle device) { return device->properties; }
gnPhysicalDeviceFeatures gnGetPhysicalDeviceFeatures(gnPhysicalOutputDeviceHandle device) { return device->features; }

View File

@@ -1,45 +0,0 @@
#pragma once
#include "stdint.h"
#include "utils/gryphn_string.h"
#include "gryphn_handles.h"
typedef enum gnDeviceType {
GN_DEDICATED_DEVICE, GN_INTEGRATED_DEVICE, GN_EXTERNAL_DEVICE
} gnDeviceType;
typedef enum gnMultisampleCountFlags {
GN_SAMPLE_BIT_1 = 1 << 0, // 0x01
GN_SAMPLE_BIT_2 = 1 << 1, // 0x02
GN_SAMPLE_BIT_4 = 1 << 2, // 0x04
GN_SAMPLE_BIT_8 = 1 << 3, // 0x08
GN_SAMPLE_BIT_16 = 1 << 4, // 0x10
GN_SAMPLE_BIT_32 = 1 << 5, // 0x20
GN_SAMPLE_BIT_64 = 1 << 6, // 0x40
} gnMultisampleCountFlags;
typedef struct gnPhysicalDeviceProperties {
gnString name;
gnDeviceType deviceType;
} gnPhysicalDeviceProperties;
typedef struct gnPhysicalDeviceFeatures {
gnMultisampleCountFlags maxColorSamples, maxDepthSamples;
uint32_t maxMemoryAllocations;
uint32_t maxPushConstantSize;
} gnPhysicalDeviceFeatures;
#ifdef GN_REVEAL_IMPL
typedef struct gnPhysicalOutputDevice_t {
struct gnPlatformPhysicalDevice_t* physicalDevice;
gnPhysicalDeviceProperties properties;
gnPhysicalDeviceFeatures features;
gnInstanceHandle instance;
} gnPhysicalOutputDevice_t;
#endif
gnPhysicalOutputDeviceHandle* gnGetPhyscialDevices(gnInstanceHandle instance, uint32_t* count);
gnBool gnPhysicalDeviceCanPresentToSurface(gnPhysicalOutputDeviceHandle device, gnWindowSurfaceHandle windowSurface);
gnPhysicalDeviceProperties gnGetPhysicalDeviceProperties(gnPhysicalOutputDeviceHandle device);
gnPhysicalDeviceFeatures gnGetPhysicalDeviceFeatures(gnPhysicalOutputDeviceHandle device);

View File

@@ -47,7 +47,7 @@ typedef struct gnScissor {
} gnScissor;
typedef struct gnMultisample {
gnMultisampleCountFlags samples;
gnSampleCountFlags samples;
} gnMultisample;
typedef enum gnFillMode {

View File

@@ -2,7 +2,7 @@
#include "stdint.h"
#include "core/gryphn_image_format.h"
#include "core/gryphn_return_code.h"
#include "core/src/output_device/gryphn_physical_output_device.h"
#include "core/src/output_device/gryphn_physical_device.h"
#include "gryphn_handles.h"
typedef enum gnRenderPassStage {
@@ -34,7 +34,7 @@ typedef struct gnRenderPassAttachmentInfo_t {
gnImageLayout initialLayout;
gnImageLayout finalLayout;
gnMultisampleCountFlags samples;
gnSampleCountFlags samples;
} gnRenderPassAttachmentInfo;
typedef struct gnSubpassAttachmentInfo_t {

View File

@@ -6,6 +6,7 @@ gnReturnCode gnCreateTexture(gnTexture* texture, gnDevice device, const gnTextur
*texture = malloc(sizeof(struct gnTexture_t));
(*texture)->device = device;
(*texture)->info = info;
return device->instance->callingLayer->deviceFunctions._gnCreateTexture(*texture, device, info);
}
@@ -13,5 +14,6 @@ void gnTextureData(gnTextureHandle texture, void* pixelData) {
texture->device->instance->callingLayer->deviceFunctions._gnTextureData(texture, pixelData);
}
void gnDestroyTexture(gnTexture texture) {
if (texture == GN_NULL_HANDLE) return;
texture->device->instance->callingLayer->deviceFunctions._gnDestroyTexture(texture);
}

View File

@@ -2,7 +2,7 @@
#include "core/gryphn_image_format.h"
#include "core/gryphn_return_code.h"
#include "utils/math/gryphn_vec3.h"
#include "core/src/output_device/gryphn_physical_output_device.h"
#include "core/src/output_device/gryphn_physical_device.h"
#include <gryphn_handles.h>
typedef enum gnTextureType {
@@ -27,7 +27,7 @@ typedef enum gnTextureUsageFlags {
typedef struct gnTextureInfo {
gnExtent3D extent;
gnMultisampleCountFlags samples;
gnSampleCountFlags samples;
gnTextureUsageFlags usage;
uint32_t mipmapLevels;
gnTextureType type;

View File

@@ -16,4 +16,4 @@ typedef struct gnQueueFamilyProperties {
gnQueueTypeFlags queueTypeFlags;
} gnQueueFamilyProperties;
gnReturnCode gnGetPhysicalDeviceQueueProperties(gnPhysicalOutputDeviceHandle device, uint32_t queueCount, gnQueueFamilyProperties* queues);
gnReturnCode gnGetPhysicalDeviceQueueProperties(gnPhysicalDeviceHandle device, uint32_t queueCount, gnQueueFamilyProperties* queues);

View File

@@ -10,7 +10,7 @@ typedef struct gnPresentInfo gnPresentInfo;
typedef struct gnPresentSyncInfo gnPresentSyncInfo;
typedef struct gnQueueExtFunctions {
gnReturnCode (*_gnGetPhysicalDeviceQueueProperties)(gnPhysicalOutputDeviceHandle device, uint32_t queueCount, gnQueueFamilyProperties* queues);
gnReturnCode (*_gnGetPhysicalDeviceQueueProperties)(gnPhysicalDeviceHandle device, uint32_t queueCount, gnQueueFamilyProperties* queues);
void (*_gnGetDeviceQueue)(gnOutputDevice device, uint32_t queueFamily, uint32_t queueIndex, gnQueue* queue);
gnReturnCode (*_gnQueueSubmit)(gnOutputDevice device, gnQueue queue, gnSubmitInfo info);

View File

@@ -8,7 +8,10 @@
typedef struct gnInstanceCreateInfo gnInstanceCreateInfo;
typedef struct gnSurfaceDetails gnSurfaceDetails;
typedef struct gnOutputDeviceInfo gnOutputDeviceInfo;
typedef enum gnSuitableField gnSuitableField;
typedef struct gnPhysicalDeviceProperties gnPhysicalDeviceProperties;
typedef struct gnPhysicalDeviceFeatures gnPhysicalDeviceFeatures;
typedef struct gnPhysicalDeviceLimits gnPhysicalDeviceLimits;
#ifdef GN_PLATFORM_LINUX
#ifdef GN_WINDOW_X11
@@ -20,12 +23,17 @@ typedef struct gnOutputDeviceInfo gnOutputDeviceInfo;
#endif
typedef struct gryphnInstanceFunctionLayers gryphnInstanceFunctionLayers;
typedef gnReturnCode (*PFN_gnCreateInstance)(gnInstanceHandle instance, gnInstanceCreateInfo* info, gryphnInstanceFunctionLayers* next, gnAllocators* alloctors);
typedef void (*PFN_gnDestroyInstance)(gnInstanceHandle instance, gryphnInstanceFunctionLayers* next, gnAllocators* alloctors);
typedef gnReturnCode (*PFN_gnCreateInstance)(gnInstanceHandle, gnInstanceCreateInfo*, gryphnInstanceFunctionLayers*, gnAllocators*);
typedef gnBool (*PFN_gnIsInstanceSuitable)(gnInstanceHandle, gnSuitableField, gryphnInstanceFunctionLayers*);
typedef gnReturnCode (*PFN_gnInstanceQueryDevices)(gnInstanceHandle, uint32_t*, gnPhysicalDeviceHandle*, gryphnInstanceFunctionLayers*);
typedef void (*PFN_gnDestroyInstance)(gnInstanceHandle, gryphnInstanceFunctionLayers*, gnAllocators*);
typedef gnPhysicalDeviceProperties (*PFN_gnQueryPhysicalDeviceProperties)(gnInstance, gnPhysicalDeviceHandle, gryphnInstanceFunctionLayers*);
typedef gnPhysicalDeviceFeatures (*PFN_gnQueryPhysicalDeviceFeatures)(gnInstanceHandle, gnPhysicalDeviceHandle, gryphnInstanceFunctionLayers*);
typedef gnPhysicalDeviceLimits (*PFN_gnQueryPhysicalDeviceLimits)(gnInstanceHandle, gnPhysicalDeviceHandle, gryphnInstanceFunctionLayers*);
typedef struct gnInstanceFunctions {
gnPhysicalDevice* (*_gnGetPhysicalDevices)(gnInstanceHandle instance, uint32_t* count);
gnBool (*_gnPhysicalDeviceCanPresentToSurface)(gnPhysicalDevice device, gnWindowSurfaceHandle windowSurface);
gnBool (*_gnPhysicalDeviceCanPresentToSurface)(gnInstance instance, gnPhysicalDevice device, gnWindowSurfaceHandle windowSurface);
gnReturnCode (*_gnCreateOutputDevice)(gnInstanceHandle instance, gnOutputDeviceHandle device, gnOutputDeviceInfo deviceInfo);
void (*_gnDestroyOutputDevice)(gnOutputDeviceHandle device);

View File

@@ -84,7 +84,9 @@ gnCommandFunctions loadAPICommandFunctions(gnRenderingAPI api) {
case GN_RENDERINGAPI_SOFTWARE: return (gnCommandFunctions){ NULL };
case GN_RENDERINGAPI_DIRECTX11: return (gnCommandFunctions){ NULL };
case GN_RENDERINGAPI_DIRECTX12: return (gnCommandFunctions){ NULL };
case GN_RENDERINGAPI_OPENGL: return (gnCommandFunctions){ NULL };
#ifdef GN_API_OPENGL
case GN_RENDERINGAPI_OPENGL: return loadOpenGLCommandFunctions();
#endif
#ifdef GN_API_METAL
case GN_RENDERINGAPI_METAL: return loadMetalCommandFunctions();
#endif

View File

@@ -15,7 +15,12 @@ typedef struct gryphnFunctionLayer {
typedef struct gryphnInstanceFunctionLayers {
PFN_gnCreateInstance createInstance;
PFN_gnIsInstanceSuitable isSuitable;
PFN_gnInstanceQueryDevices queryDevices;
PFN_gnDestroyInstance destroyInstance;
PFN_gnQueryPhysicalDeviceProperties getPhysicalDeviceProperties;
PFN_gnQueryPhysicalDeviceFeatures getPhysicalDeviceFeatures;
PFN_gnQueryPhysicalDeviceLimits getPhysicalDeviceLimits;
struct gryphnInstanceFunctionLayers* next;
} gryphnInstanceFunctionLayers;

View File

@@ -1,6 +1,6 @@
#include "queue_functions.h"
#include "loader_utils.h"
#include "core/src/output_device/gryphn_physical_output_device.h"
#include "core/src/output_device/gryphn_physical_device.h"
#include "core/src/output_device/gryphn_output_device.h"
#include <core/src/instance/gryphn_debugger.h>
#include <core/src/instance/gryphn_instance.h>
@@ -9,8 +9,9 @@
#include "extensions/synchronization/commands/gryphn_sync_submit.h"
#include "extensions/synchronization/commands/gryphn_sync_present.h"
gnReturnCode checkGetPhysicalDeviceQueueProperties(gnPhysicalOutputDeviceHandle device, uint32_t queueCount, gnQueueFamilyProperties* queues) {
CHECK_FUNCTION_WITH_RETURN_CODE(device->instance, _gnGetPhysicalDeviceQueueProperties, queueFunctions, device, queueCount, queues);
gnReturnCode checkGetPhysicalDeviceQueueProperties(gnPhysicalDeviceHandle device, uint32_t queueCount, gnQueueFamilyProperties* queues) {
// CHECK_FUNCTION_WITH_RETURN_CODE(device->instance, _gnGetPhysicalDeviceQueueProperties, queueFunctions, device, queueCount, queues);
return GN_UNKNOWN_ERROR;
}
void checkGetDeviceQueue(gnOutputDevice device, uint32_t queueFamily, uint32_t queueIndex, gnQueue* queue) {
CHECK_VOID_FUNCTION(device->instance, _gnGetDeviceQueue, queueFunctions, device, queueFamily, queueIndex, queue);

View File

@@ -1,6 +1,6 @@
#include <loader/src/gryphn_loader.h>
gnReturnCode checkGetPhysicalDeviceQueueProperties(gnPhysicalOutputDeviceHandle device, uint32_t queueCount, gnQueueFamilyProperties* queues);
gnReturnCode checkGetPhysicalDeviceQueueProperties(gnPhysicalDeviceHandle device, uint32_t queueCount, gnQueueFamilyProperties* queues);
void checkGetDeviceQueue(gnOutputDevice device, uint32_t queueFamily, uint32_t queueIndex, gnQueue* queue);
gnReturnCode checkQueueSubmit(gnOutputDevice device, gnQueue queue, gnSubmitInfo info);

View File

@@ -8,13 +8,18 @@
gryphnInstanceFunctionLayers checkerLoadInstanceFunctions(void) {
return (gryphnInstanceFunctionLayers) {
.createInstance = checkCreateInstance,
.destroyInstance = checkDestroyInstance
.isSuitable = checkIsInstanceSuitable,
.queryDevices = checkQueryDevices,
.destroyInstance = checkDestroyInstance,
.getPhysicalDeviceProperties = checkQueryPhysicalDeviceProperties,
.getPhysicalDeviceFeatures = checkQueryPhysicalDeviceFeatures,
.getPhysicalDeviceLimits = checkQueryPhysicalDeviceLimits,
.next = GN_NULL_HANDLE
};
}
gnInstanceFunctions loadFunctionLoaderInstanceFunctions(void) {
return (gnInstanceFunctions){
._gnGetPhysicalDevices = checkGetPhysicalDevices,
._gnPhysicalDeviceCanPresentToSurface = checkCanDevicePresent,
._gnCreateOutputDevice = checkCreateOutputDevice,

View File

@@ -24,11 +24,61 @@ void checkDestroyInstance(gnInstanceHandle instance, gryphnInstanceFunctionLayer
next->destroyInstance(instance, next->next, alloctors);
}
gnPhysicalDevice* checkGetPhysicalDevices(gnInstanceHandle instance, uint32_t* count) {
CHECK_RETURNED_FUNCTION(instance, _gnGetPhysicalDevices, instanceFunctions, NULL, instance, count);
gnBool checkIsInstanceSuitable(gnInstanceHandle instance, gnSuitableField field, gryphnInstanceFunctionLayers* next) {
if (next == NULL || next->isSuitable == NULL) {
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString("Failed to load gnIsInstanceSuitable this indicates a bug within gryphn")
});
return GN_FAILED_TO_LOAD_FUNCTION;
}
return next->isSuitable(instance, field, next);
}
gnBool checkCanDevicePresent(gnPhysicalDevice device, gnWindowSurfaceHandle windowSurface) {
CHECK_RETURNED_FUNCTION(device->instance, _gnPhysicalDeviceCanPresentToSurface, instanceFunctions, GN_FALSE, device, windowSurface);
gnReturnCode checkQueryDevices(gnInstanceHandle instance, uint32_t* count, gnPhysicalDeviceHandle* devices, gryphnInstanceFunctionLayers* next) {
if (next == NULL || next->queryDevices == NULL) {
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString("Failed to load gnQueryDevices this indicates a bug within gryphn")
});
return GN_FAILED_TO_LOAD_FUNCTION;
}
return next->queryDevices(instance, count, devices, next->next);
}
gnPhysicalDeviceProperties checkQueryPhysicalDeviceProperties(gnInstanceHandle instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* next) {
if (next == NULL || next->getPhysicalDeviceProperties == NULL) {
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString("Failed to load gnQueryPhysicalDeviceProperties this indicates a bug within gryphn")
});
return (gnPhysicalDeviceProperties){
.deviceID = -1,
.deviceName = gnCreateString("Invalid device"),
.deviceType = GN_PHYSICAL_DEVICE_TYPE_FAKED_GPU,
.driverVersion = -1
};
}
return next->getPhysicalDeviceProperties(instance, device, next->next);
}
gnPhysicalDeviceFeatures checkQueryPhysicalDeviceFeatures(gnInstanceHandle instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* next) {
if (next == NULL || next->getPhysicalDeviceFeatures == NULL) {
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString("Failed to load gnQueryPhysicalDeviceFeatures this indicates a bug within gryphn")
});
return (gnPhysicalDeviceFeatures){};
}
return next->getPhysicalDeviceFeatures(instance, device, next->next);
}
gnPhysicalDeviceLimits checkQueryPhysicalDeviceLimits(gnInstanceHandle instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* next) {
if (next == NULL || next->getPhysicalDeviceLimits == NULL) {
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString("Failed to load gnQueryPhysicalDeviceLimits this indicates a bug within gryphn")
});
return (gnPhysicalDeviceLimits){};
}
return next->getPhysicalDeviceLimits(instance, device, next->next);
}
gnBool checkCanDevicePresent(gnInstance instance, gnPhysicalDevice device, gnWindowSurfaceHandle windowSurface) {
CHECK_RETURNED_FUNCTION(instance, _gnPhysicalDeviceCanPresentToSurface, instanceFunctions, GN_FALSE, instance, device, windowSurface);
}
gnReturnCode checkCreateOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle device, gnOutputDeviceInfo deviceInfo) {

View File

@@ -3,11 +3,16 @@
#include <core/src/window_surface/gryphn_surface_create_functions.h>
gnReturnCode checkCreateInstance(gnInstanceHandle instance, gnInstanceCreateInfo* info, gryphnInstanceFunctionLayers* next, gnAllocators* alloctors);
gnBool checkIsInstanceSuitable(gnInstanceHandle instance, gnSuitableField field, gryphnInstanceFunctionLayers* next);
gnReturnCode checkQueryDevices(gnInstanceHandle instance, uint32_t* count, gnPhysicalDeviceHandle* devices, gryphnInstanceFunctionLayers* next);
void checkDestroyInstance(gnInstanceHandle instance, gryphnInstanceFunctionLayers* next, gnAllocators* alloctors);
gnPhysicalDevice* checkGetPhysicalDevices(gnInstanceHandle instance, uint32_t* count);
gnBool checkCanDevicePresent(gnPhysicalDevice device, gnWindowSurfaceHandle windowSurface);
gnPhysicalDeviceProperties checkQueryPhysicalDeviceProperties(gnInstanceHandle instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* next);
gnPhysicalDeviceFeatures checkQueryPhysicalDeviceFeatures(gnInstanceHandle instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* next);
gnPhysicalDeviceLimits checkQueryPhysicalDeviceLimits(gnInstanceHandle instance, gnPhysicalDeviceHandle device, gryphnInstanceFunctionLayers* next);
// old ahh functions (currently working on removing)
gnBool checkCanDevicePresent(gnInstance instance, gnPhysicalDevice device, gnWindowSurfaceHandle windowSurface);
gnReturnCode checkCreateOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle device, gnOutputDeviceInfo deviceInfo);
void checkDestroyOutputDevice(gnOutputDeviceHandle device);