Compare commits
31 Commits
e11a705dbd
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| eaf3bcb290 | |||
| 629036542a | |||
| fb2aa8504f | |||
| 0eff3c62ee | |||
| 587f3cd224 | |||
| dd3c50be07 | |||
| a252a9cf6b | |||
| 96ddecda52 | |||
| f86d6b9a54 | |||
| f39024c045 | |||
| b0c36a6bea | |||
| ebaf4fde0a | |||
| 9387e8afd9 | |||
| c51c05fb08 | |||
| 55889a32d4 | |||
| 7a952fcb19 | |||
| e8e54c0c0d | |||
| 01148e2dad | |||
| 2379e3ae6b | |||
| de67b88f18 | |||
| 6fd8917b88 | |||
| 204383372d | |||
| d9c1e8a345 | |||
| 3ad8f10f50 | |||
| 562b235f6a | |||
| d5c6aa10ae | |||
| dca85ff7e8 | |||
| 4087972149 | |||
| cf212dd9ad | |||
| b93fd9cfec | |||
| b46497d3e1 |
@@ -1 +1,2 @@
|
|||||||
build/
|
build/
|
||||||
|
glfw
|
||||||
|
|||||||
+24
-3
@@ -1,10 +1,31 @@
|
|||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
project(ChemistryRenderingApp LANGUAGES C CXX OBJCXX) # OBJCXX is required for Metal .mm files
|
project(ChemistryRenderingApp LANGUAGES C CXX)
|
||||||
add_executable(ChemistryRenderingApp main.cpp)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
if (APPLE)
|
||||||
|
add_executable(ChemistryRenderingApp main.mm)
|
||||||
|
target_link_libraries(ChemistryRenderingApp PRIVATE
|
||||||
|
"-framework Metal"
|
||||||
|
"-framework Foundation"
|
||||||
|
"-framework QuartzCore"
|
||||||
|
"-framework Cocoa"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
add_executable(ChemistryRenderingApp main.cpp)
|
||||||
|
endif()
|
||||||
target_include_directories(ChemistryRenderingApp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
target_include_directories(ChemistryRenderingApp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
target_link_libraries(ChemistryRenderingApp PRIVATE GryphnLoader)
|
target_include_directories(ChemistryRenderingApp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/glfw/include/")
|
||||||
|
target_link_libraries(ChemistryRenderingApp PRIVATE GryphnLoader glfw)
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
add_subdirectory(Gryphn)
|
add_subdirectory(Gryphn)
|
||||||
|
set(BUILD_SHARED_LIBS ON)
|
||||||
|
|
||||||
|
set(GLFW_BUILD_WAYLAND OFF CACHE BOOL "" FORCE)
|
||||||
|
set(GLFW_BUILD_X11 ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
add_subdirectory(glfw)
|
||||||
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
project(Gryphn LANGUAGES C CXX OBJCXX) # OBJCXX is required for Metal .mm files
|
project(Gryphn LANGUAGES C CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
@@ -10,4 +10,11 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
|||||||
|
|
||||||
# Add subdirectories
|
# Add subdirectories
|
||||||
add_subdirectory(GryphnLoader)
|
add_subdirectory(GryphnLoader)
|
||||||
add_subdirectory(apis/GryphnMetal)
|
if (APPLE)
|
||||||
|
add_compile_definitions(GN_USE_SURFACE_COCOA)
|
||||||
|
add_subdirectory(apis/GryphnMetal)
|
||||||
|
endif()
|
||||||
|
if (UNIX)
|
||||||
|
add_compile_definitions(GN_USE_SURFACE_XLIB)
|
||||||
|
add_subdirectory(apis/GryphnVulkan)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ target_include_directories(GryphnLoader PUBLIC
|
|||||||
if(APPLE)
|
if(APPLE)
|
||||||
target_compile_definitions(GryphnLoader PUBLIC GN_PLATFORM_MACOS)
|
target_compile_definitions(GryphnLoader PUBLIC GN_PLATFORM_MACOS)
|
||||||
endif()
|
endif()
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
target_compile_definitions(GryphnLoader PUBLIC GN_PLATFORM_LINUX)
|
||||||
|
endif()
|
||||||
|
|
||||||
# 4. Links
|
# 4. Links
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
|||||||
@@ -6,18 +6,31 @@
|
|||||||
|
|
||||||
typedef uint32_t (*PFN_gnInternalIsApiSupported)(gnVersion);
|
typedef uint32_t (*PFN_gnInternalIsApiSupported)(gnVersion);
|
||||||
|
|
||||||
gnReturnCode gnGetAvaliableBackends(gnVersion version, uint32_t* avaliable_backends, gnBackend* backends) {
|
int gryphn_CheckLib(gnVersion version, const char* name) {
|
||||||
*avaliable_backends = 0;
|
gnLib metalLib = gnLoadLib(name);
|
||||||
gnLib metalLib = gnLoadLib("bin/gryphn_metal.dylib");
|
|
||||||
if (gnLibValid(&metalLib)) {
|
if (gnLibValid(&metalLib)) {
|
||||||
PFN_gnInternalIsApiSupported isSupported = (PFN_gnInternalIsApiSupported)gnLoadLibFunction(&metalLib, "gnInternalIsApiSupported");
|
PFN_gnInternalIsApiSupported isSupported = (PFN_gnInternalIsApiSupported)gnLoadLibFunction(&metalLib, "gnInternalIsApiSupported");
|
||||||
if (isSupported(version) > 0) {
|
if (isSupported(version) > 0) {
|
||||||
if (backends != NULL) {
|
return 1;
|
||||||
backends[*avaliable_backends] = GN_BACKEND_METAL;
|
|
||||||
}
|
|
||||||
*avaliable_backends += 1;
|
|
||||||
}
|
}
|
||||||
|
gnCloseLib(&metalLib);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode gnGetAvaliableBackends(gnVersion version, uint32_t* avaliable_backends, gnBackend* backends) {
|
||||||
|
*avaliable_backends = 0;
|
||||||
|
int metalSupported = gryphn_CheckLib(version, "bin/gryphn_metal.dylib");
|
||||||
|
int vulkanSupported = gryphn_CheckLib(version, "bin/gryphn_vulkan.so");
|
||||||
|
if (metalSupported) {
|
||||||
|
if (backends != NULL)
|
||||||
|
backends[*avaliable_backends] = GN_BACKEND_METAL;
|
||||||
|
*avaliable_backends += 1;
|
||||||
|
}
|
||||||
|
if (vulkanSupported) {
|
||||||
|
if (backends != NULL)
|
||||||
|
backends[*avaliable_backends] = GN_BACKEND_VULKAN;
|
||||||
|
*avaliable_backends += 1;
|
||||||
}
|
}
|
||||||
gnCloseLib(&metalLib);
|
|
||||||
return GN_SUCCESS;
|
return GN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum gnFormat {
|
||||||
|
GN_FORMAT_UNDEFINED = 0,
|
||||||
|
GN_FORMAT_RGBA8_UNORM = 1,
|
||||||
|
GN_FORMAT_RGBA8_SNORM = 2,
|
||||||
|
GN_FORMAT_RGBA8_USCALED = 3,
|
||||||
|
GN_FORMAT_RGBA8_SSCALED = 4,
|
||||||
|
GN_FORMAT_RGBA8_UINT = 5,
|
||||||
|
GN_FORMAT_RGBA8_SINT = 6,
|
||||||
|
GN_FORMAT_RGBA8_SRGB = 7,
|
||||||
|
|
||||||
|
GN_FORMAT_BGRA8_UNORM = 8,
|
||||||
|
GN_FORMAT_BGRA8_SNORM = 9,
|
||||||
|
GN_FORMAT_BGRA8_USCALED = 10,
|
||||||
|
GN_FORMAT_BGRA8_SSCALED = 11,
|
||||||
|
GN_FORMAT_BGRA8_UINT = 12,
|
||||||
|
GN_FORMAT_BGRA8_SINT = 13,
|
||||||
|
GN_FORMAT_BGRA8_SRGB = 14,
|
||||||
|
} gnFormat;
|
||||||
|
|
||||||
|
typedef enum gnColorSpace {
|
||||||
|
GN_COLOR_SPACE_SRGB_NONLINEAR = 0,
|
||||||
|
GN_COLOR_SPACE_UNKNOWN = 1
|
||||||
|
} gnColorSpace;
|
||||||
|
|
||||||
|
typedef struct gnSurfaceFormat {
|
||||||
|
gnFormat format;
|
||||||
|
gnColorSpace colorSpace;
|
||||||
|
} gnSurfaceFormat;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum gnPresentMode {
|
||||||
|
GN_PRESENT_MODE_IMMEDIATE = 0,
|
||||||
|
GN_PRESENT_MODE_MAILBOX = 1,
|
||||||
|
GN_PRESENT_MODE_FIFO = 2,
|
||||||
|
GN_PRESENT_MODE_FIFO_RELAXED = 3,
|
||||||
|
GN_PRESENT_MODE_UNKNOWN = 4
|
||||||
|
} gnPresentMode;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
typedef struct gnExtent2D {
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
} gnExtent2D;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#include "gryphn_device.h"
|
||||||
|
#include "instance/gryphn_instance.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
gnReturnCode gnCreateDevice(gnInstance instance, gnDeviceCreateInfo* createInfo, gnDevice* device) {
|
||||||
|
gnDevice newDevice = malloc(sizeof(gnDevice_t));
|
||||||
|
newDevice->instance = instance;
|
||||||
|
*device = newDevice;
|
||||||
|
return instance->dispatchTable.createDevice(instance, createInfo, newDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode gnDestroyDevice(gnDevice* device) {
|
||||||
|
gnReturnCode returnCode = (*device)->dispatchTable.destroyDevice(*device);
|
||||||
|
*device = NULL;
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "gryphn_physical_device.h"
|
||||||
|
#include "instance/dispatch/gryphn_device_dispatch_table.h"
|
||||||
|
|
||||||
|
typedef struct gnDeviceCreateInfo {
|
||||||
|
gnPhysicalDevice physicalDevice;
|
||||||
|
uint32_t enabledExtensionCount;
|
||||||
|
const char** enabledExtensions;
|
||||||
|
} gnDeviceCreateInfo;
|
||||||
|
|
||||||
|
typedef struct gnDevice_t {
|
||||||
|
gnDeviceDispatchTable dispatchTable;
|
||||||
|
gnInstance instance;
|
||||||
|
void* internalData;
|
||||||
|
} gnDevice_t;
|
||||||
|
|
||||||
|
gnReturnCode gnCreateDevice(gnInstance instance, gnDeviceCreateInfo* createInfo, gnDevice* device);
|
||||||
|
gnReturnCode gnDestroyDevice(gnDevice* device);
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#include "gryphn_physical_device.h"
|
||||||
|
#include "instance/gryphn_instance.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
gnReturnCode gnEnumeratePhysicalDevices(gnInstance instance, uint32_t* deviceCount, gnPhysicalDevice* devices) {
|
||||||
|
return instance->dispatchTable.enumeratePhysicalDevices(instance, deviceCount, devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode gnGetPhysicalDeviceProperties(gnPhysicalDevice device, gnPhysicalDeviceProperties* properties) {
|
||||||
|
return device->instance->dispatchTable.getPhysicalDeviceProperties(device, properties);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "instance/gryphn_application_info.h"
|
||||||
|
|
||||||
|
typedef enum gnPhysicalDeviceType {
|
||||||
|
GN_PHYSICAL_DEVICE_TYPE_CPU = 1,
|
||||||
|
GN_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 2,
|
||||||
|
GN_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 3,
|
||||||
|
GN_PHYSICAL_DEVICE_TYPE_EXTERNAL_GPU = 4,
|
||||||
|
GN_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 5,
|
||||||
|
GN_PHYSICAL_DEVICE_TYPE_OTHER = 6,
|
||||||
|
} gnPhysicalDeviceType;
|
||||||
|
|
||||||
|
// typedef struct gnPhysicalDeviceLimits {
|
||||||
|
|
||||||
|
// } gnPhysicalDeviceLimits;
|
||||||
|
|
||||||
|
typedef struct gnPhysicalDeviceProperties {
|
||||||
|
gnVersion apiVersion;
|
||||||
|
uint32_t vendorID;
|
||||||
|
uint32_t deviceID;
|
||||||
|
gnPhysicalDeviceType deviceType;
|
||||||
|
char deviceName[256];
|
||||||
|
// gnPhysicalDeviceLimits limits;
|
||||||
|
} gnPhysicalDeviceProperties;
|
||||||
|
|
||||||
|
typedef struct gnPhysicalDevice_t {
|
||||||
|
gnInstance instance;
|
||||||
|
void* internalData;
|
||||||
|
} gnPhysicalDevice_t;
|
||||||
|
|
||||||
|
gnReturnCode gnEnumeratePhysicalDevices(gnInstance instance, uint32_t* deviceCount, gnPhysicalDevice* devices);
|
||||||
|
gnReturnCode gnGetPhysicalDeviceProperties(gnPhysicalDevice device, gnPhysicalDeviceProperties* properties);
|
||||||
|
gnReturnCode gnDoesDeviceSupportSurface(gnPhysicalDevice device, gnSurface surface);
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "gryphn_swapchain.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include <device/gryphn_device.h>
|
||||||
|
|
||||||
|
gnReturnCode gnCreateSwapchain(gnDevice device, gnSwapchainCreateInfo* createInfo, gnSwapchain* swapchain) {
|
||||||
|
return device->dispatchTable.createSwapchain(device, createInfo, swapchain);
|
||||||
|
}
|
||||||
|
gnReturnCode gnDestroySwapchain(gnDevice device, gnSwapchain* swapchain) {
|
||||||
|
return device->dispatchTable.destroySwapchain(device, swapchain);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <gryphn_handle.h>
|
||||||
|
#include "core/gryphn_format.h"
|
||||||
|
#include "core/gryphn_present_mode.h"
|
||||||
|
#include "core/gryphn_vec2d.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
typedef struct gnSwapchainCreateInfo {
|
||||||
|
gnSurface surface;
|
||||||
|
uint32_t minImageCount;
|
||||||
|
gnFormat imageFormat;
|
||||||
|
gnColorSpace imageColorSpace;
|
||||||
|
gnExtent2D imageExtent;
|
||||||
|
uint32_t imageArrayLayers;
|
||||||
|
gnPresentMode presentMode;
|
||||||
|
} gnSwapchainCreateInfo;
|
||||||
|
|
||||||
|
gnReturnCode gnCreateSwapchain(gnDevice device, gnSwapchainCreateInfo* createInfo, gnSwapchain* swapchain);
|
||||||
|
gnReturnCode gnDestroySwapchain(gnDevice device, gnSwapchain* swapchain);
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifdef GN_USE_SURFACE_COCOA
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
|
||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
typedef struct gnMetalSurfaceCreateInfo {
|
||||||
|
CAMetalLayer* metalLayer;
|
||||||
|
} gnMetalSurfaceCreateInfo;
|
||||||
|
gnReturnCode gnCreateMetalSurface(gnInstance instance, gnMetalSurfaceCreateInfo* createInfo, gnSurface* surface);
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#include "gryphn_surface.h"
|
||||||
|
#include "instance/gryphn_instance.h"
|
||||||
|
#include "device/gryphn_physical_device.h"
|
||||||
|
|
||||||
|
gnReturnCode gnGetSurfaceCapabilities(gnPhysicalDevice device, gnSurface surface, gnSurfaceCapabilities* capabilities) {
|
||||||
|
return device->instance->dispatchTable.getSurfaceCapabilities(device, surface, capabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode gnGetSurfaceFormats(gnPhysicalDevice device, gnSurface surface, uint32_t* formatCount, gnSurfaceFormat* formats) {
|
||||||
|
return device->instance->dispatchTable.getSurfaceFormats(device, surface, formatCount, formats);
|
||||||
|
}
|
||||||
|
gnReturnCode gnGetSurfacePresentModes(gnPhysicalDevice device, gnSurface surface, uint32_t* presentModeCount, gnPresentMode* presentModes) {
|
||||||
|
return device->instance->dispatchTable.getSurfacePresentModes(device, surface, presentModeCount, presentModes);
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode gnDestroySurface(gnInstance instance, gnSurface* surface) {
|
||||||
|
return instance->dispatchTable.destroySurface(instance, surface);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "gryphn_metal_surface.h"
|
||||||
|
#include "gryphn_xlib_surface.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
#include "core/gryphn_vec2d.h"
|
||||||
|
#include "core/gryphn_format.h"
|
||||||
|
#include "core/gryphn_present_mode.h"
|
||||||
|
|
||||||
|
typedef struct gnSurfaceCapabilities {
|
||||||
|
uint32_t minImageCount;
|
||||||
|
uint32_t maxImageCount;
|
||||||
|
gnExtent2D currentExtent;
|
||||||
|
gnExtent2D minImageExtent;
|
||||||
|
gnExtent2D maxImageExtent;
|
||||||
|
uint32_t maxImageArrayLayers;
|
||||||
|
} gnSurfaceCapabilities;
|
||||||
|
|
||||||
|
gnReturnCode gnGetSurfaceCapabilities(gnPhysicalDevice device, gnSurface surface, gnSurfaceCapabilities* capabilities);
|
||||||
|
gnReturnCode gnGetSurfaceFormats(gnPhysicalDevice device, gnSurface surface, uint32_t* formatCount, gnSurfaceFormat* formats);
|
||||||
|
gnReturnCode gnGetSurfacePresentModes(gnPhysicalDevice device, gnSurface surface, uint32_t* presentModeCount, gnPresentMode* presentModes);
|
||||||
|
gnReturnCode gnDestroySurface(gnInstance instance, gnSurface* surface);
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "gryphn_xlib_surface.h"
|
||||||
|
#include "instance/gryphn_instance.h"
|
||||||
|
|
||||||
|
gnReturnCode gnCreateXlibSurface(gnInstance instance, gnXlibSurfaceCreateInfo* createInfo, gnSurface* surface) {
|
||||||
|
return instance->dispatchTable.createXlibSurface(instance, createInfo, surface);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifdef GN_USE_SURFACE_XLIB
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
|
||||||
|
#include "X11/Xlib.h"
|
||||||
|
typedef struct gnXlibSurfaceCreateInfo {
|
||||||
|
Display* dpy;
|
||||||
|
Window window;
|
||||||
|
} gnXlibSurfaceCreateInfo;
|
||||||
|
|
||||||
|
gnReturnCode gnCreateXlibSurface(gnInstance instance, gnXlibSurfaceCreateInfo* createInfo, gnSurface* surface);
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define GN_HANDLE(type) typedef struct type##_t* type
|
#define GN_HANDLE(type) typedef struct type##_t* type
|
||||||
|
#define GN_IMPLEMENTATION_HANDLE(type) typedef void* type
|
||||||
|
|
||||||
GN_HANDLE(gnInstance);
|
GN_HANDLE(gnInstance);
|
||||||
|
GN_HANDLE(gnPhysicalDevice);
|
||||||
|
GN_HANDLE(gnDevice);
|
||||||
|
GN_IMPLEMENTATION_HANDLE(gnSurface);
|
||||||
|
GN_IMPLEMENTATION_HANDLE(gnSwapchain);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef struct gnLib {
|
typedef struct gnLib {
|
||||||
#ifdef GN_PLATFORM_MACOS
|
#if defined(GN_PLATFORM_MACOS) || defined(GN_PLATFORM_LINUX)
|
||||||
void* dylib;
|
void* dylib;
|
||||||
#endif
|
#endif
|
||||||
} gnLib;
|
} gnLib;
|
||||||
|
|
||||||
gnLib gnLoadLib(const char* path);
|
gnLib gnLoadLib(const char* path);
|
||||||
|
|||||||
+4
-12
@@ -1,31 +1,23 @@
|
|||||||
#include "gryphn_lib.h"
|
#include "gryphn_lib.h"
|
||||||
#ifdef GN_PLATFORM_MACOS
|
#if defined(GN_PLATFORM_MACOS) || defined(GN_PLATFORM_LINUX)
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
gnLib gnLoadLib(const char* path) {
|
gnLib gnLoadLib(const char* path) {
|
||||||
#ifdef GN_PLATFORM_MACOS
|
|
||||||
gnLib lib;
|
gnLib lib;
|
||||||
lib.dylib = dlopen(path, RTLD_NOW | RTLD_LOCAL);
|
lib.dylib = dlopen(path, RTLD_NOW | RTLD_LOCAL);
|
||||||
return lib;
|
return lib;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int gnLibValid(const gnLib* lib) {
|
int gnLibValid(const gnLib* lib) {
|
||||||
#ifdef GN_PLATFORM_MACOS
|
return lib->dylib != 0;
|
||||||
return lib->dylib != 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* gnLoadLibFunction(const gnLib* lib, const char* function) {
|
void* gnLoadLibFunction(const gnLib* lib, const char* function) {
|
||||||
#ifdef GN_PLATFORM_MACOS
|
|
||||||
return dlsym(lib->dylib, function);
|
return dlsym(lib->dylib, function);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gnCloseLib(const gnLib* lib) {
|
void gnCloseLib(const gnLib* lib) {
|
||||||
#ifdef GN_PLATFORM_MACOS
|
|
||||||
dlclose(lib->dylib);
|
dlclose(lib->dylib);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef enum gnReturnCode {
|
typedef enum gnReturnCode {
|
||||||
GN_SUCCESS,
|
GN_SUCCESS = 0,
|
||||||
GN_FAILED_TO_FIND_LIBARY
|
GN_FAILED_TO_FIND_LIBARY = 1,
|
||||||
|
GN_UNSUPPORTED_BACKEND = 2,
|
||||||
|
GN_EXTENSION_NOT_PRESENT = 3,
|
||||||
|
GN_UNSUPPOTED_SURFACE
|
||||||
} gnReturnCode;
|
} gnReturnCode;
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
typedef struct gnSwapchainCreateInfo gnSwapchainCreateInfo;
|
||||||
|
|
||||||
|
typedef gnReturnCode (*PFN_gnDestroyDevice)(gnDevice);
|
||||||
|
typedef gnReturnCode (*PFN_gnCreateSwapchain)(gnDevice, gnSwapchainCreateInfo*, gnSwapchain*);
|
||||||
|
typedef gnReturnCode (*PFN_gnDestroySwapchain)(gnDevice, gnSwapchain*);
|
||||||
|
|
||||||
|
typedef struct gnDeviceDispatchTable {
|
||||||
|
PFN_gnDestroyDevice destroyDevice;
|
||||||
|
PFN_gnCreateSwapchain createSwapchain;
|
||||||
|
PFN_gnDestroySwapchain destroySwapchain;
|
||||||
|
} gnDeviceDispatchTable;
|
||||||
@@ -1,8 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "gryphn_handle.h"
|
#include "gryphn_handle.h"
|
||||||
|
#include "core/gryphn_format.h"
|
||||||
|
#include "core/gryphn_present_mode.h"
|
||||||
|
typedef struct gnMetalSurfaceCreateInfo gnMetalSurfaceCreateInfo;
|
||||||
|
typedef struct gnXlibSurfaceCreateInfo gnXlibSurfaceCreateInfo;
|
||||||
|
typedef struct gnSurfaceCapabilities gnSurfaceCapabilities;
|
||||||
|
typedef struct gnPhysicalDeviceProperties gnPhysicalDeviceProperties;
|
||||||
|
typedef struct gnDeviceCreateInfo gnDeviceCreateInfo;
|
||||||
|
|
||||||
|
typedef gnReturnCode (*PFN_gnCreateMetalSurface)(gnInstance, gnMetalSurfaceCreateInfo*, gnSurface*);
|
||||||
|
typedef gnReturnCode (*PFN_gnCreateXlibSurface)(gnInstance, gnXlibSurfaceCreateInfo*, 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_gnGetSurfaceFormats)(gnPhysicalDevice, gnSurface, uint32_t*, gnSurfaceFormat*);
|
||||||
|
typedef gnReturnCode (*PFN_gnGetSurfacePresentModes)(gnPhysicalDevice, gnSurface, uint32_t*, gnPresentMode*);
|
||||||
|
typedef gnReturnCode (*PFN_gnGetSurfaceCapabilities)(gnPhysicalDevice, gnSurface, gnSurfaceCapabilities*);
|
||||||
|
typedef gnReturnCode (*PFN_gnDestroySurface)(gnInstance, gnSurface*);
|
||||||
typedef gnReturnCode (*PFN_gnDestroyInstance)(gnInstance);
|
typedef gnReturnCode (*PFN_gnDestroyInstance)(gnInstance);
|
||||||
|
|
||||||
typedef struct gnInstanceDispatchTable {
|
typedef struct gnInstanceDispatchTable {
|
||||||
|
PFN_gnCreateMetalSurface createMetalSurface;
|
||||||
|
PFN_gnCreateXlibSurface createXlibSurface;
|
||||||
|
PFN_gnGetSurfaceCapabilities getSurfaceCapabilities;
|
||||||
|
PFN_gnGetSurfaceFormats getSurfaceFormats;
|
||||||
|
PFN_gnGetSurfacePresentModes getSurfacePresentModes;
|
||||||
|
PFN_gnDestroySurface destroySurface;
|
||||||
|
PFN_enumeratePhysicalDevices enumeratePhysicalDevices;
|
||||||
|
PFN_gnGetPhysicalDeviceProperties getPhysicalDeviceProperties;
|
||||||
|
PFN_gnCreateDevice createDevice;
|
||||||
PFN_gnDestroyInstance destroyInstance;
|
PFN_gnDestroyInstance destroyInstance;
|
||||||
} gnInstanceDispatchTable;
|
} gnInstanceDispatchTable;
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ typedef struct gnApplicationInfo {
|
|||||||
const char* applicationName;
|
const char* applicationName;
|
||||||
gnVersion applicationVersion;
|
gnVersion applicationVersion;
|
||||||
const char* engineName;
|
const char* engineName;
|
||||||
gnVersion enginnVersion;
|
gnVersion engineVersion;
|
||||||
} gnApplicationInfo;
|
} gnApplicationInfo;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
#include "gryphn_return_code.h"
|
||||||
#include "gryphn_instance.h"
|
#include "gryphn_instance.h"
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "stdio.h"
|
|
||||||
|
|
||||||
typedef gnReturnCode (*PFN_initBackend)(gnInstance, gnInstanceCreateInfo*);
|
typedef gnReturnCode (*PFN_initBackend)(gnInstance, gnInstanceCreateInfo*);
|
||||||
|
|
||||||
@@ -11,10 +11,15 @@ gnReturnCode gnCreateInstance(gnInstance* newInstance, gnInstanceCreateInfo* cre
|
|||||||
if (createInfo->backend == GN_BACKEND_METAL) {
|
if (createInfo->backend == GN_BACKEND_METAL) {
|
||||||
instance->internalLib = gnLoadLib("bin/gryphn_metal.dylib");
|
instance->internalLib = gnLoadLib("bin/gryphn_metal.dylib");
|
||||||
PFN_initBackend initBackend = (PFN_initBackend)gnLoadLibFunction(&instance->internalLib, "initBackend");
|
PFN_initBackend initBackend = (PFN_initBackend)gnLoadLibFunction(&instance->internalLib, "initBackend");
|
||||||
initBackend(instance, createInfo);
|
return initBackend(instance, createInfo);
|
||||||
|
}
|
||||||
|
if (createInfo->backend == GN_BACKEND_VULKAN) {
|
||||||
|
instance->internalLib = gnLoadLib("bin/gryphn_vulkan.so");
|
||||||
|
PFN_initBackend initBackend = (PFN_initBackend)gnLoadLibFunction(&instance->internalLib, "initBackend");
|
||||||
|
return initBackend(instance, createInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GN_SUCCESS;
|
return GN_UNSUPPORTED_BACKEND;
|
||||||
}
|
}
|
||||||
gnReturnCode gnDestroyInstance(gnInstance* instance) {
|
gnReturnCode gnDestroyInstance(gnInstance* instance) {
|
||||||
(*instance)->dispatchTable.destroyInstance(*instance);
|
(*instance)->dispatchTable.destroyInstance(*instance);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
file(GLOB_RECURSE METAL_SOURCES CONFIGURE_DEPENDS "src/*.m")
|
file(GLOB_RECURSE METAL_SOURCES CONFIGURE_DEPENDS "src/*.m")
|
||||||
add_library(gryphn_metal SHARED ${METAL_SOURCES})
|
add_library(gryphn_metal SHARED ${METAL_SOURCES})
|
||||||
|
project(gryphn_metal LANGUAGES C CXX OBJC OBJCXX)
|
||||||
set_target_properties(gryphn_metal PROPERTIES PREFIX "")
|
set_target_properties(gryphn_metal PROPERTIES PREFIX "")
|
||||||
target_link_libraries(gryphn_metal PRIVATE GryphnLoader)
|
target_link_libraries(gryphn_metal PRIVATE GryphnLoader)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#import <Metal/Metal.h>
|
||||||
|
#include "../metal_functions.h"
|
||||||
|
#include "core/gryphn_format.h"
|
||||||
|
|
||||||
|
gnReturnCode metalCreateSurface(gnInstance instance, gnMetalSurfaceCreateInfo* createInfo, gnSurface* surface) {
|
||||||
|
*surface = createInfo->metalLayer;
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode metalGetSurfaceCapabilities(gnPhysicalDevice device, gnSurface surface, gnSurfaceCapabilities* capabilities) {
|
||||||
|
CAMetalLayer* layer = surface;
|
||||||
|
capabilities->minImageCount = 2;
|
||||||
|
capabilities->maxImageCount = 3;
|
||||||
|
|
||||||
|
capabilities->currentExtent.width = (uint32_t)layer.drawableSize.width;
|
||||||
|
capabilities->currentExtent.height = (uint32_t)layer.drawableSize.height;
|
||||||
|
|
||||||
|
id<MTLDevice> mtlDevice = (id<MTLDevice>)device->internalData;
|
||||||
|
uint32_t maxTextureSize = 8192;
|
||||||
|
if ([mtlDevice respondsToSelector:@selector(supportsFamily:)]) {
|
||||||
|
if ([mtlDevice supportsFamily:MTLGPUFamilyApple1] ||
|
||||||
|
[mtlDevice supportsFamily:MTLGPUFamilyMac2]) {
|
||||||
|
maxTextureSize = 16384;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
capabilities->minImageExtent = (gnExtent2D){ 1, 1 };
|
||||||
|
capabilities->maxImageExtent = (gnExtent2D){ maxTextureSize, maxTextureSize };
|
||||||
|
|
||||||
|
capabilities->maxImageArrayLayers = 1;
|
||||||
|
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode metalGetSurfaceFormats(gnPhysicalDevice device, gnSurface surface, uint32_t* formatCount, gnSurfaceFormat* formats) {
|
||||||
|
gnSurfaceFormat supported[] = {
|
||||||
|
{ GN_FORMAT_BGRA8_UNORM, GN_COLOR_SPACE_SRGB_NONLINEAR },
|
||||||
|
{ GN_FORMAT_BGRA8_SRGB, GN_COLOR_SPACE_SRGB_NONLINEAR },
|
||||||
|
};
|
||||||
|
if (formats == NULL) {
|
||||||
|
*formatCount = 2;
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
|
formats[i] = supported[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
gnReturnCode metalGetSurfacePresentModes(gnPhysicalDevice device, gnSurface surface, uint32_t* presentModeCount, gnPresentMode* presentModes) {
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode metalDestroySurface(gnInstance instance, gnSurface* surface) {
|
||||||
|
*surface = NULL;
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
@@ -2,23 +2,38 @@
|
|||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "instance/gryphn_instance.h"
|
#include "instance/gryphn_instance.h"
|
||||||
#include "gryphn_handle.h"
|
#include "gryphn_handle.h"
|
||||||
|
#include "metal_functions.h"
|
||||||
|
|
||||||
extern "C" uint32_t gnInternalIsApiSupported(gnVersion version) {
|
uint32_t gnInternalIsApiSupported(gnVersion version) {
|
||||||
if (version != gnCreateVersion(1, 0, 0)) return 0;
|
if (version != gnCreateVersion(1, 0, 0)) return 0;
|
||||||
id<MTLDevice> testDevice = MTLCreateSystemDefaultDevice();
|
id<MTLDevice> testDevice = MTLCreateSystemDefaultDevice();
|
||||||
if (testDevice == nil)
|
if (testDevice == nil)
|
||||||
return 0;
|
return 0;
|
||||||
[testDevice release];
|
[testDevice release];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gnReturnCode destroyBackend(gnInstance instance) {
|
gnReturnCode destroyBackend(gnInstance instance) {
|
||||||
printf("Calling destroy instance");
|
|
||||||
return GN_SUCCESS;
|
return GN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" gnReturnCode initBackend(gnInstance instance, gnInstanceCreateInfo* info) {
|
gnReturnCode initBackend(gnInstance instance, gnInstanceCreateInfo* info) {
|
||||||
printf("calling init instance\n");
|
|
||||||
instance->dispatchTable.destroyInstance = destroyBackend;
|
instance->dispatchTable.destroyInstance = destroyBackend;
|
||||||
|
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.destroySurface = metalDestroySurface;
|
||||||
|
instance->dispatchTable.getSurfaceCapabilities = metalGetSurfaceCapabilities;
|
||||||
|
instance->dispatchTable.getSurfaceFormats = metalGetSurfaceFormats;
|
||||||
|
instance->dispatchTable.getSurfacePresentModes = metalGetSurfacePresentModes;
|
||||||
|
}
|
||||||
|
if (strcmp(info->enabledExtensions[i], "GN_EXT_surface_cocoa") == 0) {
|
||||||
|
instance->dispatchTable.createMetalSurface = metalCreateSurface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return GN_SUCCESS;
|
return GN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
#import "Metal/Metal.h"
|
||||||
|
#include "metal_functions.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "device/gryphn_physical_device.h"
|
||||||
|
#include "device/gryphn_device.h"
|
||||||
|
|
||||||
|
gnReturnCode metalEnumeratePhysicalDevices(gnInstance instance, uint32_t* deviceCount, gnPhysicalDevice* devices) {
|
||||||
|
NSArray<id<MTLDevice>>* mtlDevices = MTLCopyAllDevices();
|
||||||
|
uint32_t systemCount = (uint32_t)[mtlDevices count];
|
||||||
|
*deviceCount = systemCount;
|
||||||
|
|
||||||
|
if (devices == NULL)
|
||||||
|
return GN_SUCCESS;
|
||||||
|
for (uint32_t i = 0; i < *deviceCount; i++) {
|
||||||
|
devices[i] = (gnPhysicalDevice)malloc(sizeof(gnPhysicalDevice_t));
|
||||||
|
devices[i]->instance = instance;
|
||||||
|
devices[i]->internalData = mtlDevices[i];
|
||||||
|
}
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode metalGetPhysicalDeviceProperties(gnPhysicalDevice device, gnPhysicalDeviceProperties* properties) {
|
||||||
|
id<MTLDevice> mtlDevice = (id<MTLDevice>)device->internalData;
|
||||||
|
|
||||||
|
properties->apiVersion = gnCreateVersion(1, 0, 0);
|
||||||
|
|
||||||
|
if ([[mtlDevice name] containsString:@"Apple"]) {
|
||||||
|
properties->vendorID = 0x106B;
|
||||||
|
} else if ([[mtlDevice name] containsString:@"Intel"]) {
|
||||||
|
properties->vendorID = 0x8086;
|
||||||
|
} else if ([[mtlDevice name] containsString:@"AMD"] || [[mtlDevice name] containsString:@"Radeon"]) {
|
||||||
|
properties->vendorID = 0x1002;
|
||||||
|
} else {
|
||||||
|
properties->vendorID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@available(macOS 10.13, *)) {
|
||||||
|
properties->deviceID = (uint32_t)[mtlDevice registryID];
|
||||||
|
} else {
|
||||||
|
properties->deviceID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([mtlDevice isRemovable])
|
||||||
|
properties->deviceType = GN_PHYSICAL_DEVICE_TYPE_EXTERNAL_GPU;
|
||||||
|
else if ([mtlDevice isLowPower])
|
||||||
|
properties->deviceType = GN_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
|
||||||
|
else if (![mtlDevice isLowPower] && ![mtlDevice hasUnifiedMemory])
|
||||||
|
properties->deviceType = GN_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
|
||||||
|
else
|
||||||
|
properties->deviceType = GN_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
|
||||||
|
|
||||||
|
const char* rawName = [[mtlDevice name] UTF8String];
|
||||||
|
strncpy(properties->deviceName, rawName, 255);
|
||||||
|
properties->deviceName[255] = '\0';
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode metalCreateDevice(gnInstance instance, gnDeviceCreateInfo* createInfo, gnDevice device) {
|
||||||
|
device->dispatchTable.destroyDevice = metalDestroyDevice;
|
||||||
|
device->internalData = createInfo->physicalDevice->internalData;
|
||||||
|
for (int i = 0; i < createInfo->enabledExtensionCount; i++) {
|
||||||
|
if (strcmp(createInfo->enabledExtensions[i], "GN_EXT_swapchain") == 0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode metalDestroyDevice(gnDevice device) {
|
||||||
|
device->internalData = NULL;
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#define GN_CA_METAL_LAYER
|
||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "device/gryphn_physical_device.h"
|
||||||
|
#include "device/gryphn_device.h"
|
||||||
|
#include "ext/instance/surface/gryphn_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);
|
||||||
|
gnReturnCode metalGetSurfaceCapabilities(gnPhysicalDevice device, gnSurface surface, gnSurfaceCapabilities* capabilities);
|
||||||
|
gnReturnCode metalGetSurfaceFormats(gnPhysicalDevice device, gnSurface surface, uint32_t* formatCount, gnSurfaceFormat* formats);
|
||||||
|
gnReturnCode metalGetSurfacePresentModes(gnPhysicalDevice device, gnSurface surface, uint32_t* presentModeCount, gnPresentMode* presentModes);
|
||||||
|
gnReturnCode metalDestroySurface(gnInstance instance, gnSurface* surface);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
file(GLOB_RECURSE VULKAN_SOURCES CONFIGURE_DEPENDS "src/*.c")
|
||||||
|
add_library(gryphn_vulkan SHARED ${VULKAN_SOURCES})
|
||||||
|
project(gryphn_vulkan LANGUAGES C)
|
||||||
|
set_target_properties(gryphn_vulkan PROPERTIES PREFIX "")
|
||||||
|
target_link_libraries(gryphn_vulkan PRIVATE GryphnLoader vulkan)
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
#include "core/gryphn_format.h"
|
||||||
|
#include "core/gryphn_present_mode.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "../vulkan_functions.h"
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#include "instance/gryphn_instance.h"
|
||||||
|
#include "ext/instance/surface/gryphn_surface.h"
|
||||||
|
#include "../vulkan_helpers.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef GN_USE_SURFACE_XLIB
|
||||||
|
#include <vulkan/vulkan_xlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gnReturnCode vulkanCreateXlibSurface(gnInstance instance, gnXlibSurfaceCreateInfo* info, gnSurface* surface) {
|
||||||
|
#ifdef GN_USE_SURFACE_XLIB
|
||||||
|
VkXlibSurfaceCreateInfoKHR createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
|
||||||
|
.pNext = 0,
|
||||||
|
.flags = 0,
|
||||||
|
.dpy = info->dpy,
|
||||||
|
.window = info->window
|
||||||
|
};
|
||||||
|
return vulkanCodeToGryphnCode(vkCreateXlibSurfaceKHR(instance->internalData, &createInfo, NULL, (VkSurfaceKHR*)surface));
|
||||||
|
#else
|
||||||
|
return GN_SUCCESS;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
gnReturnCode vulkanGetSurfaceCapabilities(gnPhysicalDevice device, gnSurface surface, gnSurfaceCapabilities* capabilities) {
|
||||||
|
VkSurfaceCapabilitiesKHR vulkanCapabilities;
|
||||||
|
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->internalData, surface, &vulkanCapabilities);
|
||||||
|
*capabilities = (gnSurfaceCapabilities){
|
||||||
|
.minImageCount = vulkanCapabilities.minImageCount,
|
||||||
|
.maxImageCount = vulkanCapabilities.maxImageCount,
|
||||||
|
.currentExtent = { vulkanCapabilities.currentExtent.width, vulkanCapabilities.currentExtent.height },
|
||||||
|
.minImageExtent = { vulkanCapabilities.maxImageExtent.width, vulkanCapabilities.maxImageExtent.height },
|
||||||
|
.maxImageExtent = { vulkanCapabilities.maxImageExtent.width, vulkanCapabilities.maxImageExtent.height },
|
||||||
|
.maxImageArrayLayers = vulkanCapabilities.maxImageArrayLayers
|
||||||
|
};
|
||||||
|
return vulkanCodeToGryphnCode(result);
|
||||||
|
}
|
||||||
|
gnReturnCode vulkanGetSurfaceFormats(gnPhysicalDevice device, gnSurface surface, uint32_t* formatCount, gnSurfaceFormat* formats) {
|
||||||
|
*formatCount = 0;
|
||||||
|
uint32_t internal_formatCout;
|
||||||
|
gnReturnCode result = vulkanCodeToGryphnCode(vkGetPhysicalDeviceSurfaceFormatsKHR(device->internalData, surface, &internal_formatCout, NULL));
|
||||||
|
if (result != GN_SUCCESS) {
|
||||||
|
*formatCount = internal_formatCout;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
VkSurfaceFormatKHR* internal_formats = malloc(sizeof(VkSurfaceFormatKHR) * internal_formatCout);
|
||||||
|
result = vulkanCodeToGryphnCode(vkGetPhysicalDeviceSurfaceFormatsKHR(device->internalData, surface, &internal_formatCout, internal_formats));
|
||||||
|
if (result != GN_SUCCESS) {
|
||||||
|
free(internal_formats);
|
||||||
|
*formatCount = internal_formatCout;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < internal_formatCout; i++) {
|
||||||
|
gnSurfaceFormat format = {
|
||||||
|
.format = vulkanFormatToGryphnFormat(internal_formats[i].format),
|
||||||
|
.colorSpace = vulkanColorSpaceToGryphnColorSpace(internal_formats[i].colorSpace)
|
||||||
|
};
|
||||||
|
if ((format.format == GN_FORMAT_UNDEFINED && internal_formats[i].format != VK_FORMAT_UNDEFINED) || format.colorSpace == GN_COLOR_SPACE_UNKNOWN)
|
||||||
|
continue;
|
||||||
|
if (formats != NULL)
|
||||||
|
formats[*formatCount] = format;
|
||||||
|
(*formatCount)++;
|
||||||
|
}
|
||||||
|
free(internal_formats);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
gnReturnCode vulkanGetSurfacePresentModes(gnPhysicalDevice device, gnSurface surface, uint32_t* presentModeCount, gnPresentMode* presentModes) {
|
||||||
|
*presentModeCount = 0;
|
||||||
|
uint32_t internal_presentModeCount;
|
||||||
|
gnReturnCode result = vulkanCodeToGryphnCode(vkGetPhysicalDeviceSurfacePresentModesKHR(device->internalData, surface, &internal_presentModeCount, NULL));
|
||||||
|
if (result != GN_SUCCESS) {
|
||||||
|
*presentModeCount = internal_presentModeCount;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
VkPresentModeKHR* internal_presentModes = malloc(sizeof(VkPresentModeKHR) * internal_presentModeCount);
|
||||||
|
result = vulkanCodeToGryphnCode(vkGetPhysicalDeviceSurfacePresentModesKHR(device->internalData, surface, &internal_presentModeCount, NULL));
|
||||||
|
if (result != GN_SUCCESS) {
|
||||||
|
free(internal_presentModes);
|
||||||
|
*presentModeCount = internal_presentModeCount;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < internal_presentModeCount; i++) {
|
||||||
|
gnPresentMode mode = vulkanPresentModeToGryphnPresentMode(internal_presentModes[i]);
|
||||||
|
if (mode == GN_PRESENT_MODE_UNKNOWN) continue;
|
||||||
|
if (presentModes != NULL)
|
||||||
|
presentModes[*presentModeCount] = mode;
|
||||||
|
(*presentModeCount)++;
|
||||||
|
}
|
||||||
|
free(internal_presentModes);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
gnReturnCode vulkanDestroySurface(gnInstance instance, gnSurface* surface) {
|
||||||
|
vkDestroySurfaceKHR(instance->internalData, *surface, NULL);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#include "../vulkan_functions.h"
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "ext/device/swapchain/gryphn_swapchain.h"
|
||||||
|
#include "../vulkan_helpers.h"
|
||||||
|
#include "../vulkan_device.h"
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
typedef struct vulkanSwapchain {
|
||||||
|
uint32_t presentQueueIndex;
|
||||||
|
VkQueue presentQueue;
|
||||||
|
} vulkanSwapchain;
|
||||||
|
|
||||||
|
gnReturnCode vulkanCreateSwapchain(gnDevice device, gnSwapchainCreateInfo* info, gnSwapchain* swapchain) {
|
||||||
|
uint32_t presentQueueIndex;
|
||||||
|
VkBool32 presentSupport = VK_FALSE;
|
||||||
|
for (int i = 0; i < ((vulkanDevice*)device->internalData)->queueCount; i++) {
|
||||||
|
vkGetPhysicalDeviceSurfaceSupportKHR(((vulkanDevice*)device->internalData)->physicalDevice, i, info->surface, &presentSupport);
|
||||||
|
if (presentSupport == VK_TRUE) {
|
||||||
|
presentQueueIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (presentSupport == VK_FALSE) return GN_UNSUPPOTED_SURFACE;
|
||||||
|
|
||||||
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(((vulkanDevice*)device->internalData)->physicalDevice, info->surface, &capabilities);
|
||||||
|
|
||||||
|
VkSwapchainCreateInfoKHR createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||||
|
.pNext = NULL,
|
||||||
|
.flags = 0,
|
||||||
|
.surface = info->surface,
|
||||||
|
.minImageCount = info->minImageCount,
|
||||||
|
.imageFormat = gryphnFormatToVulkanFormat(info->imageFormat),
|
||||||
|
.imageColorSpace = gryphnColorSpaceToVulkanColorSpace(info->imageColorSpace),
|
||||||
|
.imageExtent = { info->imageExtent.width, info->imageExtent.height },
|
||||||
|
.imageArrayLayers = info->imageArrayLayers,
|
||||||
|
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
|
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
|
.queueFamilyIndexCount = 0,
|
||||||
|
.pQueueFamilyIndices = NULL,
|
||||||
|
.preTransform = capabilities.currentTransform,
|
||||||
|
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||||
|
.presentMode = gryphnPresentModeToVulkanPresentMode(info->presentMode),
|
||||||
|
.clipped = VK_TRUE,
|
||||||
|
.oldSwapchain = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (((vulkanDevice*)device->internalData)->graphicsQueueIndex != presentQueueIndex) {
|
||||||
|
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
|
createInfo.queueFamilyIndexCount = 2;
|
||||||
|
createInfo.pQueueFamilyIndices = (uint32_t[]){((vulkanDevice*)device->internalData)->graphicsQueueIndex, presentQueueIndex};
|
||||||
|
}
|
||||||
|
|
||||||
|
return vulkanCodeToGryphnCode(vkCreateSwapchainKHR(((vulkanDevice*)device->internalData)->device, &createInfo, NULL, (VkSwapchainKHR*)swapchain));
|
||||||
|
}
|
||||||
|
gnReturnCode vulkanDestroySwapchain(gnDevice device, gnSwapchain* swapchain) {
|
||||||
|
vkDestroySwapchainKHR(((vulkanDevice*)device->internalData)->device, *((VkSwapchainKHR*)swapchain), NULL);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#include "instance/gryphn_instance.h"
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#include "vulkan_functions.h"
|
||||||
|
#include "vulkan_helpers.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
uint32_t gnInternalIsApiSupported(gnVersion gryphnVersion) {
|
||||||
|
if (gryphnVersion != gnCreateVersion(1, 0, 0)) return 0;
|
||||||
|
|
||||||
|
VkApplicationInfo appInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
|
.pApplicationName = "Gryphn Vulkan Test",
|
||||||
|
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
|
.pEngineName = "Gryphn Vulkan Test",
|
||||||
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
|
.apiVersion = VK_API_VERSION_1_0
|
||||||
|
};
|
||||||
|
|
||||||
|
VkInstanceCreateInfo createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
.pApplicationInfo = &appInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
VkInstance instance;
|
||||||
|
VkResult result = vkCreateInstance(&createInfo, NULL, &instance);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return 0;
|
||||||
|
vkDestroyInstance(instance, NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode destroyBackend(gnInstance instance) {
|
||||||
|
vkDestroyInstance(instance->internalData, NULL);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode initBackend(gnInstance instance, gnInstanceCreateInfo* info) {
|
||||||
|
VkApplicationInfo applicationInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
|
.pNext = NULL,
|
||||||
|
.pApplicationName = info->info.applicationName,
|
||||||
|
.applicationVersion = info->info.applicationVersion,
|
||||||
|
.pEngineName = info->info.engineName,
|
||||||
|
.engineVersion = info->info.engineVersion,
|
||||||
|
.apiVersion = VK_API_VERSION_1_0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const char** extensions = malloc(sizeof(const char*) * info->enabledExtensionCount);
|
||||||
|
int realEnabledExtensionCount = 0;
|
||||||
|
for (int i = 0; i < info->enabledExtensionCount; i++) {
|
||||||
|
if (strcmp(info->enabledExtensions[i], "GN_EXT_surface") == 0) {
|
||||||
|
extensions[realEnabledExtensionCount] = "VK_KHR_surface";
|
||||||
|
realEnabledExtensionCount++;
|
||||||
|
instance->dispatchTable.destroySurface = vulkanDestroySurface;
|
||||||
|
instance->dispatchTable.getSurfaceCapabilities = vulkanGetSurfaceCapabilities;
|
||||||
|
instance->dispatchTable.getSurfaceFormats = vulkanGetSurfaceFormats;
|
||||||
|
instance->dispatchTable.getSurfacePresentModes = vulkanGetSurfacePresentModes;
|
||||||
|
}
|
||||||
|
if (strcmp(info->enabledExtensions[i], "GN_EXT_surface_xlib") == 0) {
|
||||||
|
extensions[realEnabledExtensionCount] = "VK_KHR_xlib_surface";
|
||||||
|
realEnabledExtensionCount++;
|
||||||
|
instance->dispatchTable.createXlibSurface = vulkanCreateXlibSurface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VkInstanceCreateInfo createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
.pNext = NULL,
|
||||||
|
.flags = 0,
|
||||||
|
.pApplicationInfo = &applicationInfo,
|
||||||
|
.enabledLayerCount = 0,
|
||||||
|
.ppEnabledLayerNames = NULL,
|
||||||
|
.enabledExtensionCount = realEnabledExtensionCount,
|
||||||
|
.ppEnabledExtensionNames = extensions,
|
||||||
|
};
|
||||||
|
|
||||||
|
instance->dispatchTable.destroyInstance = destroyBackend;
|
||||||
|
instance->dispatchTable.enumeratePhysicalDevices = vulkanEnumeratePhysicalDevices;
|
||||||
|
instance->dispatchTable.getPhysicalDeviceProperties = vulkanGetPhysicalDeviceProperties;
|
||||||
|
instance->dispatchTable.createDevice = vulkanCreateDevice;
|
||||||
|
|
||||||
|
VkInstance vulkanInstance;
|
||||||
|
VkResult result = vkCreateInstance(&createInfo, NULL, &vulkanInstance);
|
||||||
|
instance->internalData = vulkanInstance;
|
||||||
|
return vulkanCodeToGryphnCode(result);
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
#include "stdlib.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "vulkan_functions.h"
|
||||||
|
#include "vulkan_helpers.h"
|
||||||
|
#include "instance/gryphn_instance.h"
|
||||||
|
#include "device/gryphn_physical_device.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#include "vulkan_device.h"
|
||||||
|
|
||||||
|
gnPhysicalDeviceType vulkanDeviceTypeToGryphnDeviceType(VkPhysicalDeviceType type) {
|
||||||
|
switch (type) {
|
||||||
|
case VK_PHYSICAL_DEVICE_TYPE_OTHER: return GN_PHYSICAL_DEVICE_TYPE_OTHER;
|
||||||
|
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_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode vulkanEnumeratePhysicalDevices(gnInstance instance, uint32_t* deviceCount, gnPhysicalDevice* devices) {
|
||||||
|
if (devices == NULL) {
|
||||||
|
vkEnumeratePhysicalDevices(instance->internalData, deviceCount, NULL);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPhysicalDevice* vulkanDevices = malloc(sizeof(VkPhysicalDevice) * (*deviceCount));
|
||||||
|
VkResult result = vkEnumeratePhysicalDevices(instance->internalData, deviceCount, vulkanDevices);
|
||||||
|
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
free(vulkanDevices);
|
||||||
|
return vulkanCodeToGryphnCode(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < *deviceCount; i++) {
|
||||||
|
devices[i] = malloc(sizeof(gnPhysicalDevice_t));
|
||||||
|
devices[i]->instance = instance;
|
||||||
|
devices[i]->internalData = vulkanDevices[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
free(vulkanDevices);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode vulkanGetPhysicalDeviceProperties(gnPhysicalDevice device, gnPhysicalDeviceProperties* properties) {
|
||||||
|
VkPhysicalDeviceProperties deviceProperties;
|
||||||
|
vkGetPhysicalDeviceProperties(device->internalData, &deviceProperties);
|
||||||
|
|
||||||
|
*properties = (gnPhysicalDeviceProperties){
|
||||||
|
.apiVersion = deviceProperties.apiVersion,
|
||||||
|
.vendorID = deviceProperties.vendorID,
|
||||||
|
.deviceID = deviceProperties.deviceID,
|
||||||
|
.deviceType = vulkanDeviceTypeToGryphnDeviceType(deviceProperties.deviceType),
|
||||||
|
};
|
||||||
|
strcpy(properties->deviceName, deviceProperties.deviceName);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnReturnCode vulkanCreateDevice(gnInstance instance, gnDeviceCreateInfo* info, gnDevice device) {
|
||||||
|
// create a list of the vulkan extentions to enable from gryphn extententions
|
||||||
|
const char** extensions = malloc(sizeof(const char*) * info->enabledExtensionCount);
|
||||||
|
int realEnabledExtensionCount = 0;
|
||||||
|
for (int i = 0; i < info->enabledExtensionCount; i++) {
|
||||||
|
if (strcmp(info->enabledExtensions[i], "GN_EXT_swapchain") == 0) {
|
||||||
|
extensions[realEnabledExtensionCount] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
|
||||||
|
realEnabledExtensionCount++;
|
||||||
|
device->dispatchTable.createSwapchain = vulkanCreateSwapchain;
|
||||||
|
device->dispatchTable.destroySwapchain = vulkanDestroySwapchain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t queueFamilyCount = 0;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(info->physicalDevice->internalData, &queueFamilyCount, NULL);
|
||||||
|
VkQueueFamilyProperties* queueFamilyProperties = malloc(sizeof(VkQueueFamilyProperties) * queueFamilyCount);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(info->physicalDevice->internalData, &queueFamilyCount, queueFamilyProperties);
|
||||||
|
|
||||||
|
VkDeviceQueueCreateInfo* queueCreateInfos = malloc(sizeof(VkDeviceQueueCreateInfo) * queueFamilyCount);
|
||||||
|
for (int i = 0; i < queueFamilyCount; i++) {
|
||||||
|
queueCreateInfos[i] = (VkDeviceQueueCreateInfo){
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||||
|
.pNext = NULL,
|
||||||
|
.flags = 0,
|
||||||
|
.queueFamilyIndex = i,
|
||||||
|
.queueCount = 1,
|
||||||
|
.pQueuePriorities = (float[]){ 1.0f }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPhysicalDeviceFeatures deviceFeatures = {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDeviceCreateInfo createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
|
.pNext = NULL,
|
||||||
|
.flags = 0,
|
||||||
|
.queueCreateInfoCount = queueFamilyCount,
|
||||||
|
.pQueueCreateInfos = queueCreateInfos,
|
||||||
|
.enabledExtensionCount = realEnabledExtensionCount,
|
||||||
|
.ppEnabledExtensionNames = extensions,
|
||||||
|
.pEnabledFeatures = &deviceFeatures,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDevice vkDevice;
|
||||||
|
VkResult result = vkCreateDevice(info->physicalDevice->internalData, &createInfo, NULL, &vkDevice);
|
||||||
|
device->internalData = malloc(sizeof(vulkanDevice));
|
||||||
|
((vulkanDevice*)device->internalData)->device = vkDevice;
|
||||||
|
((vulkanDevice*)device->internalData)->physicalDevice = info->physicalDevice->internalData;
|
||||||
|
((vulkanDevice*)device->internalData)->queueCount = queueFamilyCount;
|
||||||
|
|
||||||
|
for (int i = 0; i < queueFamilyCount; i++) {
|
||||||
|
if ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT) {
|
||||||
|
((vulkanDevice*)device->internalData)->graphicsQueueIndex = i;
|
||||||
|
vkGetDeviceQueue(vkDevice, i, 0, &((vulkanDevice*)device->internalData)->graphicsQueue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device->dispatchTable.destroyDevice = vulkanDestroyDevice;
|
||||||
|
free(extensions);
|
||||||
|
return vulkanCodeToGryphnCode(result);
|
||||||
|
}
|
||||||
|
gnReturnCode vulkanDestroyDevice(gnDevice device) {
|
||||||
|
vkDestroyDevice(((vulkanDevice*)device->internalData)->device, NULL);
|
||||||
|
free(device->internalData);
|
||||||
|
return GN_SUCCESS;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
typedef struct vulkanDevice {
|
||||||
|
VkDevice device;
|
||||||
|
VkPhysicalDevice physicalDevice;
|
||||||
|
|
||||||
|
uint32_t queueCount;
|
||||||
|
uint32_t graphicsQueueIndex;
|
||||||
|
VkQueue graphicsQueue;
|
||||||
|
} vulkanDevice;
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "gryphn_handle.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "device/gryphn_physical_device.h"
|
||||||
|
#include "device/gryphn_device.h"
|
||||||
|
#include "dispatch/gryphn_instance_dispatch_table.h"
|
||||||
|
|
||||||
|
gnReturnCode vulkanEnumeratePhysicalDevices(gnInstance instance, uint32_t* deviceCount, gnPhysicalDevice* devices);
|
||||||
|
gnReturnCode vulkanGetPhysicalDeviceProperties(gnPhysicalDevice device, gnPhysicalDeviceProperties* properties);
|
||||||
|
gnReturnCode vulkanCreateDevice(gnInstance instance, gnDeviceCreateInfo* createInfo, gnDevice device);
|
||||||
|
gnReturnCode vulkanDestroyDevice(gnDevice device);
|
||||||
|
gnReturnCode vulkanCreateXlibSurface(gnInstance instance, gnXlibSurfaceCreateInfo* createInfo, gnSurface* surface);
|
||||||
|
gnReturnCode vulkanGetSurfaceCapabilities(gnPhysicalDevice device, gnSurface surface, gnSurfaceCapabilities* capabilities);
|
||||||
|
gnReturnCode vulkanGetSurfaceFormats(gnPhysicalDevice device, gnSurface surface, uint32_t* formatCount, gnSurfaceFormat* formats);
|
||||||
|
gnReturnCode vulkanGetSurfacePresentModes(gnPhysicalDevice device, gnSurface surface, uint32_t* presentModeCount, gnPresentMode* presentModes);
|
||||||
|
gnReturnCode vulkanDestroySurface(gnInstance instance, gnSurface* surface);
|
||||||
|
gnReturnCode vulkanCreateSwapchain(gnDevice device, gnSwapchainCreateInfo* createInfo, gnSwapchain* swapchain);
|
||||||
|
gnReturnCode vulkanDestroySwapchain(gnDevice device, gnSwapchain* swapchain);
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
#include "vulkan_helpers.h"
|
||||||
|
#include "core/gryphn_format.h"
|
||||||
|
#include "core/gryphn_present_mode.h"
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
gnReturnCode vulkanCodeToGryphnCode(VkResult result) {
|
||||||
|
switch(result) {
|
||||||
|
default: {
|
||||||
|
printf("Unknown instance fail mr gregory please diagnose this: %d\n", result);
|
||||||
|
return GN_UNSUPPORTED_BACKEND;
|
||||||
|
}
|
||||||
|
case VK_SUCCESS: return GN_SUCCESS;
|
||||||
|
case VK_ERROR_EXTENSION_NOT_PRESENT: return GN_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gnFormat vulkanFormatToGryphnFormat(VkFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case VK_FORMAT_UNDEFINED: return GN_FORMAT_UNDEFINED;
|
||||||
|
case VK_FORMAT_R8G8B8A8_UNORM: return GN_FORMAT_RGBA8_UNORM;
|
||||||
|
case VK_FORMAT_R8G8B8A8_SNORM: return GN_FORMAT_RGBA8_SNORM;
|
||||||
|
case VK_FORMAT_R8G8B8A8_USCALED: return GN_FORMAT_RGBA8_USCALED;
|
||||||
|
case VK_FORMAT_R8G8B8A8_SSCALED: return GN_FORMAT_RGBA8_SSCALED;
|
||||||
|
case VK_FORMAT_R8G8B8A8_UINT: return GN_FORMAT_RGBA8_UINT;
|
||||||
|
case VK_FORMAT_R8G8B8A8_SINT: return GN_FORMAT_RGBA8_SINT;
|
||||||
|
case VK_FORMAT_R8G8B8A8_SRGB: return GN_FORMAT_RGBA8_SRGB;
|
||||||
|
|
||||||
|
case VK_FORMAT_B8G8R8A8_UNORM: return GN_FORMAT_BGRA8_UNORM;
|
||||||
|
case VK_FORMAT_B8G8R8A8_SNORM: return GN_FORMAT_BGRA8_SNORM;
|
||||||
|
case VK_FORMAT_B8G8R8A8_USCALED: return GN_FORMAT_BGRA8_USCALED;
|
||||||
|
case VK_FORMAT_B8G8R8A8_SSCALED: return GN_FORMAT_BGRA8_SSCALED;
|
||||||
|
case VK_FORMAT_B8G8R8A8_UINT: return GN_FORMAT_BGRA8_UINT;
|
||||||
|
case VK_FORMAT_B8G8R8A8_SINT: return GN_FORMAT_BGRA8_SINT;
|
||||||
|
case VK_FORMAT_B8G8R8A8_SRGB: return GN_FORMAT_BGRA8_SRGB;
|
||||||
|
default: return GN_FORMAT_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gnColorSpace vulkanColorSpaceToGryphnColorSpace(VkColorSpaceKHR colorSpace) {
|
||||||
|
switch (colorSpace) {
|
||||||
|
case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR: return GN_COLOR_SPACE_SRGB_NONLINEAR;
|
||||||
|
default: return GN_COLOR_SPACE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gnPresentMode vulkanPresentModeToGryphnPresentMode(VkPresentModeKHR presentMode) {
|
||||||
|
switch (presentMode) {
|
||||||
|
case VK_PRESENT_MODE_IMMEDIATE_KHR: return GN_PRESENT_MODE_IMMEDIATE;
|
||||||
|
case VK_PRESENT_MODE_MAILBOX_KHR: return GN_PRESENT_MODE_MAILBOX;
|
||||||
|
case VK_PRESENT_MODE_FIFO_KHR: return GN_PRESENT_MODE_FIFO;
|
||||||
|
case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return GN_PRESENT_MODE_FIFO_RELAXED;
|
||||||
|
default: return GN_PRESENT_MODE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFormat gryphnFormatToVulkanFormat(gnFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case GN_FORMAT_UNDEFINED: return VK_FORMAT_UNDEFINED;
|
||||||
|
case GN_FORMAT_RGBA8_UNORM: return VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
case GN_FORMAT_RGBA8_SNORM: return VK_FORMAT_R8G8B8A8_SNORM;
|
||||||
|
case GN_FORMAT_RGBA8_USCALED: return VK_FORMAT_R8G8B8A8_USCALED;
|
||||||
|
case GN_FORMAT_RGBA8_SSCALED: return VK_FORMAT_R8G8B8A8_SSCALED;
|
||||||
|
case GN_FORMAT_RGBA8_UINT: return VK_FORMAT_R8G8B8A8_UINT;
|
||||||
|
case GN_FORMAT_RGBA8_SINT: return VK_FORMAT_R8G8B8A8_SINT;
|
||||||
|
case GN_FORMAT_RGBA8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
case GN_FORMAT_BGRA8_UNORM: return VK_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
case GN_FORMAT_BGRA8_SNORM: return VK_FORMAT_B8G8R8A8_SNORM;
|
||||||
|
case GN_FORMAT_BGRA8_USCALED: return VK_FORMAT_B8G8R8A8_USCALED;
|
||||||
|
case GN_FORMAT_BGRA8_SSCALED: return VK_FORMAT_B8G8R8A8_SSCALED;
|
||||||
|
case GN_FORMAT_BGRA8_UINT: return VK_FORMAT_B8G8R8A8_UINT;
|
||||||
|
case GN_FORMAT_BGRA8_SINT: return VK_FORMAT_B8G8R8A8_SINT;
|
||||||
|
case GN_FORMAT_BGRA8_SRGB: return VK_FORMAT_B8G8R8A8_SRGB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VkColorSpaceKHR gryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace) {
|
||||||
|
switch (colorSpace) {
|
||||||
|
case GN_COLOR_SPACE_SRGB_NONLINEAR: return VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||||
|
case GN_COLOR_SPACE_UNKNOWN: return VK_COLOR_SPACE_MAX_ENUM_KHR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VkPresentModeKHR gryphnPresentModeToVulkanPresentMode(gnPresentMode presentMode) {
|
||||||
|
switch (presentMode) {
|
||||||
|
case GN_PRESENT_MODE_IMMEDIATE: return VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
|
case GN_PRESENT_MODE_MAILBOX: return VK_PRESENT_MODE_MAILBOX_KHR;
|
||||||
|
case GN_PRESENT_MODE_FIFO: return VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
case GN_PRESENT_MODE_FIFO_RELAXED: return VK_PRESENT_MODE_FIFO_RELAXED_KHR;
|
||||||
|
case GN_PRESENT_MODE_UNKNOWN: return VK_PRESENT_MODE_MAX_ENUM_KHR;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "gryphn_return_code.h"
|
||||||
|
#include "core/gryphn_format.h"
|
||||||
|
#include "core/gryphn_present_mode.h"
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
gnReturnCode vulkanCodeToGryphnCode(VkResult result);
|
||||||
|
gnFormat vulkanFormatToGryphnFormat(VkFormat format);
|
||||||
|
gnColorSpace vulkanColorSpaceToGryphnColorSpace(VkColorSpaceKHR colorSpace);
|
||||||
|
gnPresentMode vulkanPresentModeToGryphnPresentMode(VkPresentModeKHR presentMode);
|
||||||
|
|
||||||
|
VkFormat gryphnFormatToVulkanFormat(gnFormat format);
|
||||||
|
VkColorSpaceKHR gryphnColorSpaceToVulkanColorSpace(gnColorSpace colorSpace);
|
||||||
|
VkPresentModeKHR gryphnPresentModeToVulkanPresentMode(gnPresentMode presentMode);
|
||||||
@@ -4,6 +4,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
#include "GryphnLoader/src/instance/gryphn_instance.h"
|
#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/ext/instance/surface/gryphn_surface.h"
|
||||||
|
#include "GryphnLoader/src/ext/device/swapchain/gryphn_swapchain.h"
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#include "Gryphn/gryphn.h"
|
#define GN_USE_SURFACE_XLIB
|
||||||
#include <iostream>
|
#include <Gryphn/gryphn.h>
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
|
#include "iostream"
|
||||||
|
#define GLFW_EXPOSE_NATIVE_X11
|
||||||
|
#include "glfw/include/GLFW/glfw3.h"
|
||||||
|
#include "glfw/include/GLFW/glfw3native.h"
|
||||||
|
|
||||||
#define CONCAT_IMPL(a, b) a##b
|
#define CONCAT_IMPL(a, b) a##b
|
||||||
#define CONCAT(a, b) CONCAT_IMPL(a, b)
|
#define CONCAT(a, b) CONCAT_IMPL(a, b)
|
||||||
@@ -11,8 +15,18 @@
|
|||||||
<< ": " << CONCAT(res, __LINE__) << "\n"; \
|
<< ": " << CONCAT(res, __LINE__) << "\n"; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWwindow* window;
|
||||||
gnVersion version = gnCreateVersion(1, 0, 0);
|
gnVersion version = gnCreateVersion(1, 0, 0);
|
||||||
gnInstance instance;
|
gnInstance instance;
|
||||||
|
gnPhysicalDevice pysicalDevice;
|
||||||
|
gnDevice device;
|
||||||
|
gnSurface surface;
|
||||||
|
gnSwapchain swapchain;
|
||||||
|
|
||||||
|
uint32_t min(uint32_t a, uint32_t b) {
|
||||||
|
if (a < b) return a;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
void createInstance() {
|
void createInstance() {
|
||||||
uint32_t backendCount = 0;
|
uint32_t backendCount = 0;
|
||||||
@@ -22,6 +36,10 @@ void createInstance() {
|
|||||||
}
|
}
|
||||||
gnBackend* backends = (gnBackend*)malloc(sizeof(gnBackend) * backendCount);
|
gnBackend* backends = (gnBackend*)malloc(sizeof(gnBackend) * backendCount);
|
||||||
CHECK(gnGetAvaliableBackends(version, &backendCount, backends));
|
CHECK(gnGetAvaliableBackends(version, &backendCount, backends));
|
||||||
|
const char* extensions[2] = {
|
||||||
|
"GN_EXT_surface",
|
||||||
|
"GN_EXT_surface_xlib"
|
||||||
|
};
|
||||||
|
|
||||||
gnInstanceCreateInfo createInfo = {
|
gnInstanceCreateInfo createInfo = {
|
||||||
.backend = backends[0],
|
.backend = backends[0],
|
||||||
@@ -29,23 +47,136 @@ void createInstance() {
|
|||||||
.applicationName = "Chemistry Rendering App",
|
.applicationName = "Chemistry Rendering App",
|
||||||
.applicationVersion = gnCreateVersion(0, 0, 1),
|
.applicationVersion = gnCreateVersion(0, 0, 1),
|
||||||
.engineName = "Chemistry Rendering Engine",
|
.engineName = "Chemistry Rendering Engine",
|
||||||
.enginnVersion = gnCreateVersion(0, 0, 1)
|
.engineVersion = gnCreateVersion(0, 0, 1)
|
||||||
},
|
},
|
||||||
.enabledValidationLayerCount = 0,
|
.enabledValidationLayerCount = 0,
|
||||||
.enabledValidationLayers = nullptr,
|
.enabledValidationLayers = nullptr,
|
||||||
.enabledExtensionCount = 0,
|
.enabledExtensionCount = 2,
|
||||||
.enabledExtensions = nullptr
|
.enabledExtensions = extensions
|
||||||
};
|
};
|
||||||
CHECK(gnCreateInstance(&instance, &createInfo));
|
CHECK(gnCreateInstance(&instance, &createInfo));
|
||||||
free(backends);
|
free(backends);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createDevice() {
|
||||||
|
uint32_t physicalDeviceCount;
|
||||||
|
CHECK(gnEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr));
|
||||||
|
gnPhysicalDevice* devices = (gnPhysicalDevice*)malloc(sizeof(gnPhysicalDevice) * physicalDeviceCount);
|
||||||
|
CHECK(gnEnumeratePhysicalDevices(instance, &physicalDeviceCount, devices));
|
||||||
|
|
||||||
|
std::cout << "Found " << physicalDeviceCount << " physical devices:\n";
|
||||||
|
for (int i = 0; i < physicalDeviceCount; i++) {
|
||||||
|
gnPhysicalDeviceProperties properties;
|
||||||
|
gnGetPhysicalDeviceProperties(devices[i], &properties);
|
||||||
|
std::cout << "Name: " << properties.deviceName << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
pysicalDevice = devices[0];
|
||||||
|
const char* extensions[1] = {
|
||||||
|
"GN_EXT_swapchain"
|
||||||
|
};
|
||||||
|
|
||||||
|
gnDeviceCreateInfo createInfo = {
|
||||||
|
.physicalDevice = pysicalDevice,
|
||||||
|
.enabledExtensionCount = 1,
|
||||||
|
.enabledExtensions = extensions
|
||||||
|
};
|
||||||
|
CHECK(gnCreateDevice(instance, &createInfo, &device));
|
||||||
|
}
|
||||||
|
|
||||||
|
void createSurface() {
|
||||||
|
gnXlibSurfaceCreateInfo createInfo = {
|
||||||
|
.dpy = glfwGetX11Display(),
|
||||||
|
.window = glfwGetX11Window(window)
|
||||||
|
};
|
||||||
|
|
||||||
|
CHECK(gnCreateXlibSurface(instance, &createInfo, &surface));
|
||||||
|
}
|
||||||
|
|
||||||
|
gnSurfaceFormat getSurfaceFormat() {
|
||||||
|
uint32_t surfaceFormatCount = 0;
|
||||||
|
CHECK(gnGetSurfaceFormats(pysicalDevice, surface, &surfaceFormatCount, NULL));
|
||||||
|
|
||||||
|
if (surfaceFormatCount == 0)
|
||||||
|
throw std::runtime_error("Gryphn returned 0 avaliable surface formats");
|
||||||
|
|
||||||
|
gnSurfaceFormat* formats = (gnSurfaceFormat*)malloc(sizeof(gnSurfaceFormat) * surfaceFormatCount);
|
||||||
|
CHECK(gnGetSurfaceFormats(pysicalDevice, surface, &surfaceFormatCount, formats));
|
||||||
|
|
||||||
|
for (int i = 0; i < surfaceFormatCount; i++)
|
||||||
|
if (formats[i].format == GN_FORMAT_BGRA8_SRGB && formats[i].colorSpace == GN_COLOR_SPACE_SRGB_NONLINEAR) return formats[i];
|
||||||
|
return formats[0];
|
||||||
|
return (gnSurfaceFormat){
|
||||||
|
.format = GN_FORMAT_UNDEFINED,
|
||||||
|
.colorSpace = GN_COLOR_SPACE_UNKNOWN
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
gnPresentMode getPresentMode() {
|
||||||
|
uint32_t presentModeCount = 0;
|
||||||
|
CHECK(gnGetSurfacePresentModes(pysicalDevice, surface, &presentModeCount, NULL));
|
||||||
|
|
||||||
|
if (presentModeCount == 0)
|
||||||
|
throw std::runtime_error("Gryphn returned 0 avaliable presentMode");
|
||||||
|
|
||||||
|
gnPresentMode* presentModes = (gnPresentMode*)malloc(sizeof(gnPresentMode) * presentModeCount);
|
||||||
|
CHECK(gnGetSurfacePresentModes(pysicalDevice, surface, &presentModeCount, presentModes));
|
||||||
|
|
||||||
|
for (int i = 0; i < presentModeCount; i++)
|
||||||
|
if (presentModes[i] == GN_PRESENT_MODE_MAILBOX) return presentModes[i];
|
||||||
|
return presentModes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void createSwapchain() {
|
||||||
|
gnSurfaceCapabilities capabilites;
|
||||||
|
gnGetSurfaceCapabilities(pysicalDevice, surface, &capabilites);
|
||||||
|
|
||||||
|
gnSurfaceFormat chosenFormat = getSurfaceFormat();
|
||||||
|
gnPresentMode chosenMode = getPresentMode();
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
glfwGetWindowSize(window, &width, &height);
|
||||||
|
|
||||||
|
gnSwapchainCreateInfo createInfo = {
|
||||||
|
.surface = surface,
|
||||||
|
.minImageCount = min(capabilites.minImageCount + 1, capabilites.maxImageCount),
|
||||||
|
.imageFormat = chosenFormat.format,
|
||||||
|
.imageColorSpace = chosenFormat.colorSpace,
|
||||||
|
.imageExtent = { (uint32_t)width, (uint32_t)height },
|
||||||
|
.imageArrayLayers = 1,
|
||||||
|
.presentMode = chosenMode,
|
||||||
|
};
|
||||||
|
CHECK(gnCreateSwapchain(device, &createInfo, &swapchain));
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
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";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
createInstance();
|
createInstance();
|
||||||
|
createDevice();
|
||||||
|
createSurface();
|
||||||
|
createSwapchain();
|
||||||
|
while (!glfwWindowShouldClose(window)) {
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << "Caught Exception: " << e.what() << "\n";
|
std::cerr << "Caught Exception: " << e.what() << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
gnDestroySurface(instance, &surface);
|
||||||
|
gnDestroyDevice(&device);
|
||||||
gnDestroyInstance(&instance);
|
gnDestroyInstance(&instance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#define GN_CA_METAL_LAYER
|
||||||
|
#include "Gryphn/gryphn.h"
|
||||||
|
#include <iostream>
|
||||||
|
#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)
|
||||||
|
#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"; \
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWwindow* window;
|
||||||
|
CAMetalLayer* layer;
|
||||||
|
gnVersion version = gnCreateVersion(1, 0, 0);
|
||||||
|
gnInstance instance;
|
||||||
|
gnPhysicalDevice pysicalDevice;
|
||||||
|
gnDevice device;
|
||||||
|
gnSurface surface;
|
||||||
|
|
||||||
|
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));
|
||||||
|
const char* extensions[2] = {
|
||||||
|
"GN_EXT_surface",
|
||||||
|
"GN_EXT_surface_cocoa"
|
||||||
|
};
|
||||||
|
|
||||||
|
gnInstanceCreateInfo createInfo = {
|
||||||
|
.backend = backends[0],
|
||||||
|
.info = {
|
||||||
|
.applicationName = "Chemistry Rendering App",
|
||||||
|
.applicationVersion = gnCreateVersion(0, 0, 1),
|
||||||
|
.engineName = "Chemistry Rendering Engine",
|
||||||
|
.engineVersion = gnCreateVersion(0, 0, 1)
|
||||||
|
},
|
||||||
|
.enabledValidationLayerCount = 0,
|
||||||
|
.enabledValidationLayers = nullptr,
|
||||||
|
.enabledExtensionCount = 2,
|
||||||
|
.enabledExtensions = extensions
|
||||||
|
};
|
||||||
|
CHECK(gnCreateInstance(&instance, &createInfo));
|
||||||
|
free(backends);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createDevice() {
|
||||||
|
uint32_t physicalDeviceCount;
|
||||||
|
CHECK(gnEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr));
|
||||||
|
gnPhysicalDevice* devices = (gnPhysicalDevice*)malloc(sizeof(gnPhysicalDevice) * physicalDeviceCount);
|
||||||
|
CHECK(gnEnumeratePhysicalDevices(instance, &physicalDeviceCount, devices));
|
||||||
|
|
||||||
|
std::cout << "Found " << physicalDeviceCount << " physical devices:\n";
|
||||||
|
for (int i = 0; i < physicalDeviceCount; i++) {
|
||||||
|
gnPhysicalDeviceProperties properties;
|
||||||
|
gnGetPhysicalDeviceProperties(devices[i], &properties);
|
||||||
|
std::cout << "Name: " << properties.deviceName << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
pysicalDevice = devices[0];
|
||||||
|
|
||||||
|
const char* extensions[1] = {
|
||||||
|
"GN_EXT_swapchain"
|
||||||
|
};
|
||||||
|
|
||||||
|
gnDeviceCreateInfo createInfo = {
|
||||||
|
.physicalDevice = pysicalDevice,
|
||||||
|
.enabledExtensionCount = 1,
|
||||||
|
.enabledExtensions = extensions
|
||||||
|
};
|
||||||
|
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));
|
||||||
|
|
||||||
|
gnSurfaceCapabilities capabilites;
|
||||||
|
gnGetSurfaceCapabilities(pysicalDevice, surface, &capabilites);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createSwapchain() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
createInstance();
|
||||||
|
createDevice();
|
||||||
|
createSurface();
|
||||||
|
createSwapchain();
|
||||||
|
while (!glfwWindowShouldClose(window)) {
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Caught Exception: " << e.what() << "\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
gnDestroySurface(instance, &surface);
|
||||||
|
gnDestroyDevice(&device);
|
||||||
|
gnDestroyInstance(&instance);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user