diff --git a/CMakeLists.txt b/CMakeLists.txt index 29450d6..eaa2d08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,16 @@ cmake_minimum_required(VERSION 3.12) project(ChemistryRenderingApp LANGUAGES C CXX OBJCXX) # OBJCXX is required for Metal .mm files -add_executable(ChemistryRenderingApp main.cpp) +add_executable(ChemistryRenderingApp main.mm) +target_link_libraries(ChemistryRenderingApp PRIVATE + "-framework Metal" + "-framework Foundation" + "-framework QuartzCore" + "-framework Cocoa" +) target_include_directories(ChemistryRenderingApp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(ChemistryRenderingApp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/glfw/include/") target_link_libraries(ChemistryRenderingApp PRIVATE GryphnLoader glfw) -project(ChemistryRenderingApp LANGUAGES C CXX OBJC OBJCXX) + set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/Gryphn/GryphnLoader/src/gryphn_handle.h b/Gryphn/GryphnLoader/src/gryphn_handle.h index 660a71a..7d8e9d0 100644 --- a/Gryphn/GryphnLoader/src/gryphn_handle.h +++ b/Gryphn/GryphnLoader/src/gryphn_handle.h @@ -6,3 +6,4 @@ GN_HANDLE(gnInstance); GN_HANDLE(gnPhysicalDevice); GN_HANDLE(gnDevice); +GN_IMPLEMENTATION_HANDLE(gnSurface); diff --git a/Gryphn/GryphnLoader/src/instance/dispatch/gryphn_instance_dispatch_table.h b/Gryphn/GryphnLoader/src/instance/dispatch/gryphn_instance_dispatch_table.h index 5626a6b..6f90695 100644 --- a/Gryphn/GryphnLoader/src/instance/dispatch/gryphn_instance_dispatch_table.h +++ b/Gryphn/GryphnLoader/src/instance/dispatch/gryphn_instance_dispatch_table.h @@ -1,16 +1,19 @@ #pragma once #include "gryphn_handle.h" +typedef struct gnMetalSurfaceCreateInfo gnMetalSurfaceCreateInfo; typedef struct gnPhysicalDeviceProperties gnPhysicalDeviceProperties; typedef struct gnDeviceCreateInfo gnDeviceCreateInfo; -typedef gnReturnCode (*PFN_gnDestroyInstance)(gnInstance); +typedef gnReturnCode (*PFN_gnCreateMetalSurface)(gnInstance, gnMetalSurfaceCreateInfo*, gnSurface*); typedef gnReturnCode (*PFN_enumeratePhysicalDevices)(gnInstance, uint32_t*, gnPhysicalDevice*); typedef gnReturnCode (*PFN_gnGetPhysicalDeviceProperties)(gnPhysicalDevice, gnPhysicalDeviceProperties*); typedef gnReturnCode (*PFN_gnCreateDevice)(gnInstance, gnDeviceCreateInfo*, gnDevice); +typedef gnReturnCode (*PFN_gnDestroyInstance)(gnInstance); typedef struct gnInstanceDispatchTable { - PFN_gnDestroyInstance destroyInstance; + PFN_gnCreateMetalSurface createMetalSurface; PFN_enumeratePhysicalDevices enumeratePhysicalDevices; PFN_gnGetPhysicalDeviceProperties getPhysicalDeviceProperties; PFN_gnCreateDevice createDevice; + PFN_gnDestroyInstance destroyInstance; } gnInstanceDispatchTable; diff --git a/Gryphn/GryphnLoader/src/surface/gryphn_metal_surface.c b/Gryphn/GryphnLoader/src/surface/gryphn_metal_surface.c new file mode 100644 index 0000000..428064b --- /dev/null +++ b/Gryphn/GryphnLoader/src/surface/gryphn_metal_surface.c @@ -0,0 +1,6 @@ +#include "gryphn_metal_surface.h" +#include "instance/gryphn_instance.h" + +gnReturnCode gnCreateMetalSurface(gnInstance instance, gnMetalSurfaceCreateInfo* createInfo, gnSurface* surface) { + return instance->dispatchTable.createMetalSurface(instance, createInfo, surface); +} diff --git a/Gryphn/GryphnLoader/src/surface/gryphn_metal_surface.h b/Gryphn/GryphnLoader/src/surface/gryphn_metal_surface.h new file mode 100644 index 0000000..aab88da --- /dev/null +++ b/Gryphn/GryphnLoader/src/surface/gryphn_metal_surface.h @@ -0,0 +1,11 @@ +#pragma once +#include "gryphn_handle.h" +#include "gryphn_return_code.h" + +#ifndef GN_CA_METAL_LAYER +typedef struct CAMetalLayer CAMetalLayer; +#endif +typedef struct gnMetalSurfaceCreateInfo { + CAMetalLayer* metalLayer; +} gnMetalSurfaceCreateInfo; +gnReturnCode gnCreateMetalSurface(gnInstance instance, gnMetalSurfaceCreateInfo* createInfo, gnSurface* surface); diff --git a/Gryphn/apis/GryphnMetal/CMakeLists.txt b/Gryphn/apis/GryphnMetal/CMakeLists.txt index 6a822bd..a63823d 100644 --- a/Gryphn/apis/GryphnMetal/CMakeLists.txt +++ b/Gryphn/apis/GryphnMetal/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB_RECURSE METAL_SOURCES CONFIGURE_DEPENDS "src/*.m") add_library(gryphn_metal SHARED ${METAL_SOURCES}) +project(gryphn_metal LANGUAGES C CXX OBJC OBJCXX) set_target_properties(gryphn_metal PROPERTIES PREFIX "") target_link_libraries(gryphn_metal PRIVATE GryphnLoader) if(APPLE) diff --git a/Gryphn/apis/GryphnMetal/src/extentions/metal_ext_surface.m b/Gryphn/apis/GryphnMetal/src/extentions/metal_ext_surface.m new file mode 100644 index 0000000..c653e9e --- /dev/null +++ b/Gryphn/apis/GryphnMetal/src/extentions/metal_ext_surface.m @@ -0,0 +1,6 @@ +#include "../metal_functions.h" + +gnReturnCode metalCreateSurface(gnInstance instance, gnMetalSurfaceCreateInfo* createInfo, gnSurface* surface) { + *surface = createInfo->metalLayer; + return GN_SUCCESS; +} diff --git a/Gryphn/apis/GryphnMetal/src/metal.m b/Gryphn/apis/GryphnMetal/src/metal.m index 3b2527e..067c868 100644 --- a/Gryphn/apis/GryphnMetal/src/metal.m +++ b/Gryphn/apis/GryphnMetal/src/metal.m @@ -22,5 +22,12 @@ gnReturnCode initBackend(gnInstance instance, gnInstanceCreateInfo* info) { instance->dispatchTable.enumeratePhysicalDevices = metalEnumeratePhysicalDevices; instance->dispatchTable.getPhysicalDeviceProperties = metalGetPhysicalDeviceProperties; instance->dispatchTable.createDevice = metalCreateDevice; + + for (int i = 0; i < info->enabledExtensionCount; i++) { + if (strcmp(info->enabledExtensions[i], "GN_EXT_surface") == 0) { + instance->dispatchTable.createMetalSurface = metalCreateSurface; + } + } + return GN_SUCCESS; } diff --git a/Gryphn/apis/GryphnMetal/src/metal_functions.h b/Gryphn/apis/GryphnMetal/src/metal_functions.h index 8be9654..2938d5c 100644 --- a/Gryphn/apis/GryphnMetal/src/metal_functions.h +++ b/Gryphn/apis/GryphnMetal/src/metal_functions.h @@ -1,11 +1,15 @@ #pragma once +#define GN_CA_METAL_LAYER +#import #include "gryphn_handle.h" #include "gryphn_return_code.h" #include "stdint.h" #include "device/gryphn_physical_device.h" #include "device/gryphn_device.h" +#include "surface/gryphn_metal_surface.h" gnReturnCode metalEnumeratePhysicalDevices(gnInstance instance, uint32_t* deviceCount, gnPhysicalDevice* devices); gnReturnCode metalGetPhysicalDeviceProperties(gnPhysicalDevice device, gnPhysicalDeviceProperties* properties); gnReturnCode metalCreateDevice(gnInstance instance, gnDeviceCreateInfo* createInfo, gnDevice device); gnReturnCode metalDestroyDevice(gnDevice device); +gnReturnCode metalCreateSurface(gnInstance instance, gnMetalSurfaceCreateInfo* createInfo, gnSurface* surface); diff --git a/Gryphn/gryphn.h b/Gryphn/gryphn.h index ec39753..bffe6b2 100644 --- a/Gryphn/gryphn.h +++ b/Gryphn/gryphn.h @@ -6,6 +6,7 @@ extern "C" { #include "GryphnLoader/src/instance/gryphn_instance.h" #include "GryphnLoader/src/device/gryphn_physical_device.h" #include "GryphnLoader/src/device/gryphn_device.h" +#include "GryphnLoader/src/surface/gryphn_metal_surface.h" #ifdef __cplusplus } #endif diff --git a/main.cpp b/main.mm similarity index 76% rename from main.cpp rename to main.mm index d47d3ef..36a9e92 100644 --- a/main.cpp +++ b/main.mm @@ -1,7 +1,13 @@ +#import +#import +#import +#define GN_CA_METAL_LAYER #include "Gryphn/gryphn.h" #include #include "stdlib.h" +#define GLFW_EXPOSE_NATIVE_COCOA #include "glfw/include/GLFW/glfw3.h" +#include "glfw/include/GLFW/glfw3native.h" #define CONCAT_IMPL(a, b) a##b #define CONCAT(a, b) CONCAT_IMPL(a, b) @@ -13,9 +19,11 @@ } GLFWwindow* window; +CAMetalLayer* layer; gnVersion version = gnCreateVersion(1, 0, 0); gnInstance instance; gnDevice device; +gnSurface surface; void createInstance() { uint32_t backendCount = 0; @@ -25,6 +33,9 @@ void createInstance() { } gnBackend* backends = (gnBackend*)malloc(sizeof(gnBackend) * backendCount); CHECK(gnGetAvaliableBackends(version, &backendCount, backends)); + const char* extensions[1] = { + "GN_EXT_surface" + }; gnInstanceCreateInfo createInfo = { .backend = backends[0], @@ -36,8 +47,8 @@ void createInstance() { }, .enabledValidationLayerCount = 0, .enabledValidationLayers = nullptr, - .enabledExtensionCount = 0, - .enabledExtensions = nullptr + .enabledExtensionCount = 1, + .enabledExtensions = extensions }; CHECK(gnCreateInstance(&instance, &createInfo)); free(backends); @@ -62,12 +73,27 @@ void createDevice() { CHECK(gnCreateDevice(instance, &createInfo, &device)); } +void createSurface() { + NSWindow* nswin = glfwGetCocoaWindow((GLFWwindow*)window); + NSView* view = [nswin contentView]; + layer = [CAMetalLayer layer]; + [view setWantsLayer:YES]; + [view setLayer:layer]; + layer.contentsScale = [nswin backingScaleFactor]; + + gnMetalSurfaceCreateInfo createInfo = { + .metalLayer = layer + }; + CHECK(gnCreateMetalSurface(instance, &createInfo, &surface)) +} + int main() { if (!glfwInit()) { std::cout << "Failed to init GLFW\n"; return -1; } + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); window = glfwCreateWindow(640, 360, "Chemistry Rendering App", nullptr, nullptr); if (!window) { std::cerr << "Failed to create window\n"; @@ -77,6 +103,7 @@ int main() { try { createInstance(); createDevice(); + createSurface(); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); }