Initial commit

This commit is contained in:
2026-05-07 16:31:39 -04:00
commit e11a705dbd
19 changed files with 308 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
build/
+10
View File
@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.12)
project(ChemistryRenderingApp LANGUAGES C CXX OBJCXX) # OBJCXX is required for Metal .mm files
add_executable(ChemistryRenderingApp main.cpp)
target_include_directories(ChemistryRenderingApp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(ChemistryRenderingApp PRIVATE GryphnLoader)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(Gryphn)
+13
View File
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.12)
project(Gryphn LANGUAGES C CXX OBJCXX) # OBJCXX is required for Metal .mm files
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Define output directories to keep all binaries in one place
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Add subdirectories
add_subdirectory(GryphnLoader)
add_subdirectory(apis/GryphnMetal)
+23
View File
@@ -0,0 +1,23 @@
project(GryphnLoader)
# 1. Collect sources
file(GLOB_RECURSE LOADER_SOURCES CONFIGURE_DEPENDS "src/*.c")
# 2. Build the library
add_library(GryphnLoader STATIC ${LOADER_SOURCES})
# 3. FIX: Add BOTH the include folder (for the API) and src (for internal headers)
# We use CMAKE_SOURCE_DIR to get back to the root 'include' folder
target_include_directories(GryphnLoader PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/src"
"${CMAKE_CURRENT_SOURCE_DIR}/src/instance"
)
if(APPLE)
target_compile_definitions(GryphnLoader PUBLIC GN_PLATFORM_MACOS)
endif()
# 4. Links
if(UNIX AND NOT APPLE)
target_link_libraries(GryphnLoader PRIVATE dl)
endif()
@@ -0,0 +1,23 @@
#include "gryphn_backend.h"
#include "stdio.h"
#include "instance/gryphn_application_info.h"
#include "gryphn_lib/gryphn_lib.h"
#include "stdint.h"
typedef uint32_t (*PFN_gnInternalIsApiSupported)(gnVersion);
gnReturnCode gnGetAvaliableBackends(gnVersion version, uint32_t* avaliable_backends, gnBackend* backends) {
*avaliable_backends = 0;
gnLib metalLib = gnLoadLib("bin/gryphn_metal.dylib");
if (gnLibValid(&metalLib)) {
PFN_gnInternalIsApiSupported isSupported = (PFN_gnInternalIsApiSupported)gnLoadLibFunction(&metalLib, "gnInternalIsApiSupported");
if (isSupported(version) > 0) {
if (backends != NULL) {
backends[*avaliable_backends] = GN_BACKEND_METAL;
}
*avaliable_backends += 1;
}
}
gnCloseLib(&metalLib);
return GN_SUCCESS;
}
@@ -0,0 +1,12 @@
#pragma once
#include "gryphn_return_code.h"
#include "stdint.h"
#include "instance/gryphn_application_info.h"
typedef enum gnBackend {
GN_BACKEND_VULKAN = 0,
GN_BACKEND_METAL = 1,
GN_BACKEND_OPENGL = 2,
GN_BACKEND_DIRECTX12 = 3
} gnBackend;
gnReturnCode gnGetAvaliableBackends(gnVersion version, uint32_t* avaliable_backends, gnBackend* backends);
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#define GN_HANDLE(type) typedef struct type##_t* type
GN_HANDLE(gnInstance);
@@ -0,0 +1,31 @@
#include "gryphn_lib.h"
#ifdef GN_PLATFORM_MACOS
#include <dlfcn.h>
#endif
gnLib gnLoadLib(const char* path) {
#ifdef GN_PLATFORM_MACOS
gnLib lib;
lib.dylib = dlopen(path, RTLD_NOW | RTLD_LOCAL);
return lib;
#endif
}
int gnLibValid(const gnLib* lib) {
#ifdef GN_PLATFORM_MACOS
return lib->dylib != 0;
#endif
}
void* gnLoadLibFunction(const gnLib* lib, const char* function) {
#ifdef GN_PLATFORM_MACOS
return dlsym(lib->dylib, function);
#endif
}
void gnCloseLib(const gnLib* lib) {
#ifdef GN_PLATFORM_MACOS
dlclose(lib->dylib);
#endif
}
@@ -0,0 +1,12 @@
#pragma once
typedef struct gnLib {
#ifdef GN_PLATFORM_MACOS
void* dylib;
#endif
} gnLib;
gnLib gnLoadLib(const char* path);
int gnLibValid(const gnLib* lib);
void* gnLoadLibFunction(const gnLib* lib, const char* function);
void gnCloseLib(const gnLib* lib);
@@ -0,0 +1,6 @@
#pragma once
typedef enum gnReturnCode {
GN_SUCCESS,
GN_FAILED_TO_FIND_LIBARY
} gnReturnCode;
@@ -0,0 +1,8 @@
#pragma once
#include "gryphn_handle.h"
typedef gnReturnCode (*PFN_gnDestroyInstance)(gnInstance);
typedef struct gnInstanceDispatchTable {
PFN_gnDestroyInstance destroyInstance;
} gnInstanceDispatchTable;
@@ -0,0 +1,12 @@
#pragma once
#include <stdint.h>
typedef uint32_t gnVersion;
#define gnCreateVersion(major, minor, patch) ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))
typedef struct gnApplicationInfo {
const char* applicationName;
gnVersion applicationVersion;
const char* engineName;
gnVersion enginnVersion;
} gnApplicationInfo;
@@ -0,0 +1,25 @@
#include "gryphn_instance.h"
#include "stdlib.h"
#include "stdio.h"
typedef gnReturnCode (*PFN_initBackend)(gnInstance, gnInstanceCreateInfo*);
gnReturnCode gnCreateInstance(gnInstance* newInstance, gnInstanceCreateInfo* createInfo) {
gnInstance_t* instance = malloc(sizeof(gnInstance_t));
*newInstance = instance;
if (createInfo->backend == GN_BACKEND_METAL) {
instance->internalLib = gnLoadLib("bin/gryphn_metal.dylib");
PFN_initBackend initBackend = (PFN_initBackend)gnLoadLibFunction(&instance->internalLib, "initBackend");
initBackend(instance, createInfo);
}
return GN_SUCCESS;
}
gnReturnCode gnDestroyInstance(gnInstance* instance) {
(*instance)->dispatchTable.destroyInstance(*instance);
gnCloseLib(&(*instance)->internalLib);
free(*instance);
*instance = NULL;
return GN_SUCCESS;
}
@@ -0,0 +1,14 @@
#pragma once
#include "gryphn_instance_create_info.h"
#include "gryphn_handle.h"
#include "dispatch/gryphn_instance_dispatch_table.h"
#include "gryphn_lib/gryphn_lib.h"
typedef struct gnInstance_t {
gnInstanceDispatchTable dispatchTable;
gnLib internalLib;
void* internalData;
} gnInstance_t;
gnReturnCode gnCreateInstance(gnInstance* instance, gnInstanceCreateInfo* createInfo);
gnReturnCode gnDestroyInstance(gnInstance* instance);
@@ -0,0 +1,18 @@
#pragma once
#include "gryphn_application_info.h"
#include "gryphn_return_code.h"
#include <backend/gryphn_backend.h>
typedef enum gnInstanceCreateInfoFlags {
GN_NO_FLAGS
} gnInstanceCreateInfoFlags;
typedef struct gnInstanceCreateInfo {
gnBackend backend;
gnInstanceCreateInfoFlags flags;
gnApplicationInfo info;
uint32_t enabledValidationLayerCount;
const char** enabledValidationLayers;
uint32_t enabledExtensionCount;
const char** enabledExtensions;
} gnInstanceCreateInfo;
+12
View File
@@ -0,0 +1,12 @@
file(GLOB_RECURSE METAL_SOURCES CONFIGURE_DEPENDS "src/*.m")
add_library(gryphn_metal SHARED ${METAL_SOURCES})
set_target_properties(gryphn_metal PROPERTIES PREFIX "")
target_link_libraries(gryphn_metal PRIVATE GryphnLoader)
if(APPLE)
target_link_libraries(gryphn_metal PRIVATE
"-framework Metal"
"-framework Foundation"
"-framework QuartzCore"
"-framework Cocoa"
)
endif()
+24
View File
@@ -0,0 +1,24 @@
#import <Metal/Metal.h>
#include "stdio.h"
#include "instance/gryphn_instance.h"
#include "gryphn_handle.h"
extern "C" uint32_t gnInternalIsApiSupported(gnVersion version) {
if (version != gnCreateVersion(1, 0, 0)) return 0;
id<MTLDevice> testDevice = MTLCreateSystemDefaultDevice();
if (testDevice == nil)
return 0;
[testDevice release];
return 1;
}
gnReturnCode destroyBackend(gnInstance instance) {
printf("Calling destroy instance");
return GN_SUCCESS;
}
extern "C" gnReturnCode initBackend(gnInstance instance, gnInstanceCreateInfo* info) {
printf("calling init instance\n");
instance->dispatchTable.destroyInstance = destroyBackend;
return GN_SUCCESS;
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "GryphnLoader/src/instance/gryphn_instance.h"
#ifdef __cplusplus
}
#endif
+51
View File
@@ -0,0 +1,51 @@
#include "Gryphn/gryphn.h"
#include <iostream>
#include "stdlib.h"
#define CONCAT_IMPL(a, b) a##b
#define CONCAT(a, b) CONCAT_IMPL(a, b)
#define CHECK(func) \
gnReturnCode CONCAT(res, __LINE__) = (func); \
if (CONCAT(res, __LINE__) != GN_SUCCESS) { \
std::cout << "Gryphn Error at line " << __LINE__ \
<< ": " << CONCAT(res, __LINE__) << "\n"; \
}
gnVersion version = gnCreateVersion(1, 0, 0);
gnInstance instance;
void createInstance() {
uint32_t backendCount = 0;
CHECK(gnGetAvaliableBackends(version, &backendCount, nullptr));
if (backendCount == 0) {
throw std::runtime_error("Gryphn returned 0 avaliable backends");
}
gnBackend* backends = (gnBackend*)malloc(sizeof(gnBackend) * backendCount);
CHECK(gnGetAvaliableBackends(version, &backendCount, backends));
gnInstanceCreateInfo createInfo = {
.backend = backends[0],
.info = {
.applicationName = "Chemistry Rendering App",
.applicationVersion = gnCreateVersion(0, 0, 1),
.engineName = "Chemistry Rendering Engine",
.enginnVersion = gnCreateVersion(0, 0, 1)
},
.enabledValidationLayerCount = 0,
.enabledValidationLayers = nullptr,
.enabledExtensionCount = 0,
.enabledExtensions = nullptr
};
CHECK(gnCreateInstance(&instance, &createInfo));
free(backends);
}
int main() {
try {
createInstance();
} catch (const std::exception& e) {
std::cerr << "Caught Exception: " << e.what() << "\n";
return 0;
}
gnDestroyInstance(&instance);
}