Compare commits

..

99 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
Gregory Wells
70f8d5f31d fix transfer queue jazz 2025-08-12 18:03:41 -04:00
Gregory Wells
94fb6fa2dc add allocators into instance 2025-08-12 17:54:10 -04:00
Gregory Wells
3c8205c20f finish moving present queue index to presentation queue 2025-08-12 17:53:56 -04:00
Gregory Wells
9b0a90f8fc make debugger header only 2025-08-12 17:53:41 -04:00
Gregory Wells
499fa5b1e7 present queue now stores present queue index 2025-08-12 17:49:37 -04:00
Gregory Wells
baac536897 redo does support present 2025-08-12 17:47:45 -04:00
Gregory Wells
0736d87d23 fix some stuff up 2025-08-12 16:08:56 -04:00
Gregory Wells
96808c1940 Merge branch 'master' of https://github.com/GregoryWells2007/Gryphn 2025-08-12 16:07:08 -04:00
Gregory Wells
acf2f8c228 fix destruction order 2025-08-12 15:40:32 -04:00
Gregory Wells
ddd28858ef gnUnmapBuffer 2025-08-12 14:33:03 -04:00
Gregory Wells
56d79663a2 fix some bugs on linux 2025-08-05 09:12:21 -04:00
Gregory Wells
dd5f1485d9 get OpenGL to work 2025-08-05 09:12:12 -04:00
115 changed files with 1805 additions and 446 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

@@ -36,8 +36,7 @@ add_subdirectory(projects/platform) # build gryphn platform
add_subdirectory(projects/validation_layers/function_loader/)
add_subdirectory(projects/validation_layers/allocators/)
target_link_libraries(Gryphn INTERFACE GryphnUtils GryphnCore GryphnLoader GryphnPlatform GryphnFunctionValidator GryphnAllocatorChecker GryphnExtensions)
target_link_libraries(Gryphn INTERFACE GryphnCore GryphnLoader GryphnPlatform GryphnFunctionValidator GryphnAllocatorChecker GryphnExtensions)
if (VULKAN_BUILT)
target_link_libraries(Gryphn INTERFACE GryphnVulkanImpl)
@@ -48,3 +47,5 @@ endif()
if (OPENGL_BUILT)
target_link_libraries(Gryphn INTERFACE GryphnOpenGLImpl)
endif()
target_link_libraries(Gryphn INTERFACE GryphnUtils)

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) {
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,8 @@
#include "opengl_loader.h"
#include "gryphn_extensions.h"
gnBool openglIsExtensionSupported(gnExtension extension) {
if (extension == GN_EXT_SYNCHRONIZATION) return GN_FALSE;
if (extension == GN_EXT_QUEUES) return GN_FALSE;
return GN_FALSE;
}

View File

@@ -4,12 +4,18 @@
#include "device/opengl_physical_device.h"
#include "device/opengl_output_device.h"
gryphnInstanceFunctionLayers loadOpenGLAPILayer() {
return (gryphnInstanceFunctionLayers) {
.createInstance = openglCreateInstance,
.destroyInstance = openglDestroyInstance,
NULL
};
}
gnInstanceFunctions loadOpenGLInstanceFunctions() {
return (gnInstanceFunctions){
._gnCreateInstance = createOpenGLInstance,
._gnDestroyInstance = destroyOpenGLInstance,
._gnGetPhysicalDevices = getOpenGLDevice,
._gnQueueCanPresentToSurface = openGLQueueCanPresent,
._gnPhysicalDeviceCanPresentToSurface = openglCanDevicePresent,
._gnCreateOutputDevice = createOpenGLOutputDevice,
._gnDestroyOutputDevice = destroyOpenGLOutputDevice,
#ifdef GN_PLATFORM_LINUX

View File

@@ -2,7 +2,11 @@
#include "loader/src/gryphn_instance_functions.h"
#include "loader/src/gryphn_device_functions.h"
#include "loader/src/gryphn_command_functions.h"
#include "gryphn_extensions.h"
gnInstanceFunctions loadOpenGLInstanceFunctions();
gnDeviceFunctions loadOpenGLDeviceFunctions();
gnCommandFunctions loadOpenGLCommandFunctions();
gryphnInstanceFunctionLayers loadOpenGLAPILayer();
gnBool openglIsExtensionSupported(gnExtension extension);

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(gnOutputDeviceHandle outputDevice, gnInstanceHandle instance, 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,8 +1,10 @@
#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(gnOutputDeviceHandle outputDevice, gnInstanceHandle instance, gnOutputDeviceInfo deviceInfo);
gnReturnCode createOpenGLOutputDevice(gnInstanceHandle instance, gnOutputDeviceHandle device, gnOutputDeviceInfo deviceInfo);
void waitForOpenGLDevice(const gnOutputDeviceHandle device);
void destroyOpenGLOutputDevice(gnOutputDeviceHandle device);

View File

@@ -1,35 +1,26 @@
#include "opengl_physical_device.h"
#include "stdlib.h"
gnPhysicalDevice* getOpenGLDevice(gnInstanceHandle instance, uint32_t* deviceCount) {
*deviceCount = 1;
gnPhysicalDevice* devices = malloc(sizeof(gnPhysicalDevice));
gnPhysicalDevice device = {
devices[0] = malloc(sizeof(struct gnPhysicalOutputDevice_t));
*devices[0] = (struct gnPhysicalOutputDevice_t){
.physicalDevice = malloc(sizeof(gnPlatformPhysicalDevice)),
.features = {
.maxColorSamples = GN_SAMPLE_BIT_1,
.maxDepthSamples = GN_SAMPLE_BIT_1,
.maxMemoryAllocations = 0x40000000,
.maxPushConstantSize = 256
.maxPushConstantSize = 0
},
.properties = {
.deviceType = GN_DEDICATED_DEVICE,
.name = gnCreateString("Generic OpenGL device")
},
.queueProperties = {
.queueCount = 1,
.queueProperties = (gnQueueProperties[1]){
(gnQueueProperties){
.queueCount = 1,
.queueType = GN_QUEUE_GRAPHICS
}
}
}
};
devices[0] = device;
return devices;
}
gnBool openGLQueueCanPresent(const gnPhysicalDevice device, uint32_t queueIndex, gnWindowSurfaceHandle windowSurface) {
return gnTrue;
gnBool openglCanDevicePresent(gnPhysicalDevice device, gnWindowSurfaceHandle windowSurface) {
return GN_TRUE;
}

View File

@@ -5,4 +5,4 @@
typedef struct gnPlatformPhysicalDevice_t {} gnPlatformPhysicalDevice;
gnPhysicalDevice* getOpenGLDevice(gnInstanceHandle instance, uint32_t* deviceCount);
gnBool openGLQueueCanPresent(const gnPhysicalDevice device, uint32_t queueIndex, gnWindowSurfaceHandle windowSurface);
gnBool openglCanDevicePresent(gnPhysicalDevice device, gnWindowSurfaceHandle windowSurface);

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

@@ -1,8 +1,12 @@
#include "opengl_instance.h"
gnReturnCode createOpenGLInstance(gnInstanceHandle instance, gnInstanceInfo instanceInfo) {
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 destroyOpenGLInstance(gnInstanceHandle instance) {
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 createOpenGLInstance(gnInstanceHandle instance, gnInstanceInfo instanceInfo);
void destroyOpenGLInstance(gnInstanceHandle instance);
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,39 +5,36 @@
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);
GLuintArrayListAdd(presentationQueue->presentationQueue->textures, presentationQueue->images[i]->texture->id);
uint32_tArrayListAdd(presentationQueue->presentationQueue->avaliableTextures, i);
}
return GN_SUCCESS;
}
gnReturnCode getOpenGLPresentationQueueImage(gnPresentationQueue presentationQueue, uint32_t* imageIndex) {
while (presentationQueue->presentationQueue->avaliableTextures.count == 0) {}
*imageIndex = presentationQueue->presentationQueue->avaliableTextures.data[0];
uint32_tArrayListPopHead(&presentationQueue->presentationQueue->avaliableTextures);
while (uint32_tArrayListCount(presentationQueue->presentationQueue->avaliableTextures) == 0) {}
*imageIndex = uint32_tArrayListAt(presentationQueue->presentationQueue->avaliableTextures, 0);
uint32_tArrayListPopHead(presentationQueue->presentationQueue->avaliableTextures);
return GN_SUCCESS;
}
void destroyOpenGLPresentationQueue(gnPresentationQueueHandle presentationQueue) {
free(presentationQueue->presentationQueue);
}
GN_ARRAY_LIST_DEFINITION(GLuint);

View File

@@ -2,11 +2,12 @@
#include <glad/glad.h>
#include "presentation_queue/gryphn_presentation_queue.h"
GN_ARRAY_LIST(GLuint);
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,6 +1,55 @@
#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
@@ -17,11 +66,20 @@ gnReturnCode createGLXContext(gnWindowSurfaceHandle windowSurface, gnInstanceHan
XVisualInfo* vi = glXChooseVisual(createInfo.display, 0, attribs);
windowSurface->windowSurface->context = glXCreateContext(createInfo.display, vi, NULL, GL_TRUE);
if (glXMakeCurrent(createInfo.display, createInfo.window, windowSurface->windowSurface->context) == GL_FALSE)
return GN_FAILED_TO_ATTACH_WINDOW;
return GN_WINDOW_IN_USE;
windowSurface->windowSurface->window = createInfo.window;
windowSurface->windowSurface->display = createInfo.display;
if (!gladLoadGLLoader((GLADloadproc)glXGetProcAddress))
return GN_FAILED_TO_INIT_OPENGL;
if (!gladLoadGLLoader((GLADloadproc)glXGetProcAddress)) {
gnDebuggerSetErrorMessage(instance->debugger, (gnMessageData){
.message = gnCreateString("Failed to load OpenGL functions")
});
return GN_UNKNOWN_ERROR;
}
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(openglMessageCallback, instance);
return GN_SUCCESS;
}
@@ -31,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
@@ -45,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;
@@ -70,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

@@ -38,6 +38,7 @@ gnDeviceFunctions loadVulkanDeviceFunctions(void) {
._gnBufferData = vulkanBufferData,
._gnBufferSubData = vulkanBufferSubData,
._gnMapBuffer = vulkanMapBuffer,
._gnUnmapBuffer = vulkanUnmapBuffer,
._gnDestroyBuffer = destroyBuffer,
._gnCreateUniformPool = createUniformPool,

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)
@@ -83,10 +84,11 @@ gnReturnCode vulkanCreateInstance(gnInstanceHandle instance, gnInstanceCreateInf
#endif
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
const char* enabledLayerNames = "VK_LAYER_KHRONOS_validation";
if (instance->enabledLayerCounts[GN_DEBUGGER_LAYER_PLATFORM] > 0) {
vkStringArrayListAdd(extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
createInfo.enabledLayerCount = 1;
createInfo.ppEnabledLayerNames = (const char*[]){ "VK_LAYER_KHRONOS_validation" };
createInfo.ppEnabledLayerNames = &enabledLayerNames;
instance->instance->userData.debuggerCallback = instanceInfo->debuggerInfo.callback;
instance->instance->userData.userData = instanceInfo->debuggerInfo.userData;
@@ -108,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,22 +8,27 @@
#include "vulkan_result_converter.h"
#include "string.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 {
@@ -32,6 +37,7 @@ gnReturnCode createVulkanOutputDevice(gnInstanceHandle instance, gnOutputDeviceH
for (uint32_t i = 0; i < deviceInfo.queueInfoCount; i++) {
queueCreateInfos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfos[i].flags = 0;
queueCreateInfos[i].pNext = NULL;
queueCreateInfos[i].queueCount = deviceInfo.queueInfos[i].queueCount;
queueCreateInfos[i].queueFamilyIndex = deviceInfo.queueInfos[i].queueFamilyIndex;
queueCreateInfos[i].pQueuePriorities = deviceInfo.queueInfos[i].queuePrioritys;
@@ -44,11 +50,13 @@ gnReturnCode createVulkanOutputDevice(gnInstanceHandle instance, gnOutputDeviceH
VkDeviceCreateInfo deviceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.flags = 0,
.pNext = NULL,
.queueCreateInfoCount = createQueueCount,
.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++)
@@ -61,31 +69,38 @@ 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;
for (uint32_t i = 0; i < deviceInfo.physicalDevice->physicalDevice->neededQueueCount; i++) {
device->outputDevice->queues[i].queueInfo = deviceInfo.physicalDevice->physicalDevice->neededQueues[i];
gnBool foundTransferQueue = GN_FALSE, foundGraphicsQueue = GN_FALSE;
vkGetDeviceQueue(device->outputDevice->device, deviceInfo.physicalDevice->physicalDevice->neededQueues[i].queueIndex, 0, &device->outputDevice->queues[i].queue);
if ((device->outputDevice->queues[i].queueInfo.createFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT) {
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;
foundTransferQueue = GN_TRUE;
}
if ((device->outputDevice->queues[i].queueInfo.createFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT) {
if ((device->outputDevice->queues[i].queueInfo.createFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT && !foundGraphicsQueue) {
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,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = transferQueue
.queueFamilyIndex = transferQueue,
.pNext = NULL
};
VkResult command_pool_result = vkCreateCommandPool(device->outputDevice->device, &poolInfo, NULL, &device->outputDevice->transferCommandPool);
@@ -132,10 +147,10 @@ void waitForDevice(const gnOutputDeviceHandle device) {
void destroyVulkanOutputDevice(gnOutputDeviceHandle device) {
vkDestroyFence(device->outputDevice->device, device->outputDevice->barrierFence, NULL);
vmaDestroyBuffer(device->outputDevice->allocator, device->outputDevice->stagingBuffer.buffer, device->outputDevice->stagingBuffer.allocation);
vkDestroyCommandPool(device->outputDevice->device, device->outputDevice->transferCommandPool, NULL);
vkDestroyDevice(device->outputDevice->device, NULL);
vmaDestroyBuffer(device->outputDevice->allocator, device->outputDevice->stagingBuffer.buffer, device->outputDevice->stagingBuffer.allocation);
vmaDestroyAllocator(device->outputDevice->allocator);
vkDestroyDevice(device->outputDevice->device, NULL);
free(device->outputDevice);
}

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,89 +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 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) {
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 = 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;
VkBool32 supportsPresent;
vkGetPhysicalDeviceSurfaceSupportKHR((VkPhysicalDevice)physicalDevice, i, surface->windowSurface->surface, &supportsPresent);
if (supportsPresent) return GN_TRUE;
}
}
}
return foundQueue;
return GN_FALSE;
}

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

@@ -1,6 +1,5 @@
#include "vulkan_present.h"
#include "extensions/synchronization/commands/gryphn_sync_present.h"
#include "vulkan_surface/vulkan_surface.h"
#include "vulkan_result_converter.h"
gnReturnCode vulkanQueuePresentSync(gnDevice device, gnQueue queue, gnPresentSyncInfo info) {
@@ -25,7 +24,7 @@ gnReturnCode vulkanQueuePresentSync(gnDevice device, gnQueue queue, gnPresentSyn
}
gnReturnCode vulkanPresentSync(gnDevice device, gnPresentSyncInfo info) {
return vulkanQueuePresentSync(device, (gnQueue)device->outputDevice->queues[info.presentationQueues[0]->info.surface->windowSurface->presentQueueIndex].queue, info);
return vulkanQueuePresentSync(device, (gnQueue)device->outputDevice->queues[info.presentationQueues[0]->presentationQueue->presentQueueIndex].queue, info);
}
gnReturnCode vulkanQueuePresent(gnDevice device, gnQueue queue, gnPresentInfo info) {
@@ -47,5 +46,5 @@ gnReturnCode vulkanQueuePresent(gnDevice device, gnQueue queue, gnPresentInfo in
}
gnReturnCode vulkanPresent(gnDevice device, gnPresentInfo info) {
return vulkanQueuePresent(device, (gnQueue)device->outputDevice->queues[info.presentationQueues[0]->info.surface->windowSurface->presentQueueIndex].queue, info);
return vulkanQueuePresent(device, (gnQueue)device->outputDevice->queues[info.presentationQueues[0]->presentationQueue->presentQueueIndex].queue, info);
}

View File

@@ -40,17 +40,25 @@ gnReturnCode createPresentationQueue(gnPresentationQueueHandle presentationQueue
presentQueueCreateInfo.queueFamilyIndexCount = presentationInfo.queueFamilyCount;
presentQueueCreateInfo.pQueueFamilyIndices = presentationInfo.queueFamilies;
} else {
if (presentationInfo.surface->windowSurface->presentQueueIndex != device->outputDevice->graphicsQueueIndex) {
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device->outputDevice->physicalDevice, &queueFamilyCount, NULL);
for (uint32_t i = 0; i < queueFamilyCount; i++) {
VkBool32 supportsPresent;
vkGetPhysicalDeviceSurfaceSupportKHR(device->outputDevice->physicalDevice, i, presentationInfo.surface->windowSurface->surface, &supportsPresent);
if (supportsPresent) { presentationQueue->presentationQueue->presentQueueIndex = i; break; };
}
if (presentationQueue->presentationQueue->presentQueueIndex != device->outputDevice->graphicsQueueIndex) {
presentQueueCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
presentQueueCreateInfo.queueFamilyIndexCount = 2;
presentQueueCreateInfo.pQueueFamilyIndices = (uint32_t[]){
device->outputDevice->queues[presentationInfo.surface->windowSurface->presentQueueIndex].queueInfo.queueIndex,
presentationQueue->presentationQueue->presentQueueIndex,
device->outputDevice->queues[device->outputDevice->graphicsQueueIndex].queueInfo.queueIndex
};
} else {
presentQueueCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
presentQueueCreateInfo.queueFamilyIndexCount = 1;
presentQueueCreateInfo.pQueueFamilyIndices = &device->outputDevice->queues[presentationInfo.surface->windowSurface->presentQueueIndex].queueInfo.queueIndex;
presentQueueCreateInfo.pQueueFamilyIndices = &presentationQueue->presentationQueue->presentQueueIndex;
}
}

View File

@@ -7,6 +7,8 @@ typedef struct gnPlatformPresentationQueue_t {
VkImage* swapChainImages;
VkImageView* swapChainImageViews;
uint32_t presentQueueIndex;
} gnPlatformPresentationQueue;
gnReturnCode createPresentationQueue(gnPresentationQueueHandle presentationQueue, const gnDevice device, gnPresentationQueueInfo presentationInfo);

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

@@ -3,7 +3,6 @@
#include "vulkan_surface.h"
#include <output_device/vulkan_physical_device.h>
#ifdef GN_PLATFORM_LINUX
#ifdef GN_WINDOW_X11
#include <vulkan/vulkan_xlib.h>
@@ -14,11 +13,7 @@ gnReturnCode createX11WindowSurface(gnWindowSurfaceHandle windowSurface, gnInsta
info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
info.dpy = createInfo.display;
info.window = createInfo.window;
VkResult result = vkCreateXlibSurfaceKHR(instance->instance->vk_instance, &info, NULL, &windowSurface->windowSurface->surface);
if (result != VK_SUCCESS)
return GN_FAILED_TO_ATTACH_WINDOW;
return GN_SUCCESS;
return VkResultToGnReturnCode(vkCreateXlibSurfaceKHR(instance->instance->vk_instance, &info, NULL, &windowSurface->windowSurface->surface));
}
#endif
@@ -61,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; }
@@ -89,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;
@@ -113,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

@@ -5,7 +5,7 @@
typedef struct gnPlatformWindowSurface_t {
VkSurfaceKHR surface;
uint32_t presentQueueIndex;
// uint32_t presentQueueIndex;
} gnPlatformWindowSurface;
VkFormat vkGryphnFormatToVulkanFormat(gnImageFormat format);

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

@@ -21,6 +21,9 @@ void* gnMapBuffer(gnBufferHandle buffer) {
if (buffer->info.usage == GN_STATIC_DRAW) return NULL;
return buffer->device->instance->callingLayer->deviceFunctions._gnMapBuffer(buffer);
}
void gnUnmapBuffer(gnBufferHandle buffer) {
buffer->device->instance->callingLayer->deviceFunctions._gnUnmapBuffer(buffer);
}
void gnDestroyBuffer(gnBufferHandle buffer) {
buffer->device->instance->callingLayer->deviceFunctions._gnDestroyBuffer(buffer);
}

View File

@@ -44,4 +44,5 @@ gnReturnCode gnCreateBuffer(gnBufferHandle* buffer, gnOutputDeviceHandle device,
void gnBufferData(gnBufferHandle buffer, size_t dataSize, gnBufferMemory data);
void gnBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, gnBufferMemory data);
gnBufferMemory gnMapBuffer(gnBufferHandle buffer);
void gnUnmapBuffer(gnBufferHandle buffer);
void gnDestroyBuffer(gnBufferHandle buffer);

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

@@ -1,10 +1 @@
#include "gryphn_debugger.h"
void gnDebuggerSetVerboseMessage(gnDebuggerCreateInfo* debugger, gnMessageData data) {
debugger->callback(
GN_MESSAGE_VERBOSE,
GN_DEBUG_MESSAGE_GENERAL,
data,
debugger->userData
);
}

View File

@@ -43,9 +43,19 @@ typedef struct gnDebuggerCreateInfo {
} gnDebuggerCreateInfo;
#ifdef GN_REVEAL_IMPL
void gnDebuggerSetVerboseMessage(gnDebuggerCreateInfo* debugger, gnMessageData data);
#include "stdlib.h"
static inline void gnDebuggerSetVerboseMessage(gnDebuggerCreateInfo* debugger, gnMessageData data) {
if (debugger->callback == 0 || debugger == NULL) return;
debugger->callback(
GN_MESSAGE_VERBOSE,
GN_DEBUG_MESSAGE_GENERAL,
data,
debugger->userData
);
}
static inline void gnDebuggerSetErrorMessage(gnDebuggerCreateInfo debugger, gnMessageData data) {
// if (debugger == NULL) return;
if (debugger.callback == 0) return;
debugger.callback(
GN_MESSAGE_ERROR,
GN_DEBUG_MESSAGE_VALIDATION,

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);

Some files were not shown because too many files have changed in this diff Show More