summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-17 16:49:11 +1100
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-17 16:49:11 +1100
commit3e1aea0243f54e0b68baa3b19ac19f3d965484e0 (patch)
tree9f6e6d691be59ed328ffd716a0f56a2e33dbdf3d
parent16afbddeada7161e931dc261d3404bb5bbc1743d (diff)
start on metal backend
-rw-r--r--Makefile27
-rw-r--r--TODO.md1
-rw-r--r--archive/src/render/archive/backends/metal/backend_metal.m2
-rw-r--r--examples/triangle.c2
-rw-r--r--include/celeritas.h19
-rw-r--r--src/backend_mtl.m52
-rw-r--r--src/core.c29
7 files changed, 108 insertions, 24 deletions
diff --git a/Makefile b/Makefile
index 9689dae..67b79a4 100644
--- a/Makefile
+++ b/Makefile
@@ -4,11 +4,7 @@ CFLAGS := -Wall -Wextra -O2 $(INCLUDES)
LDFLAGS := -lglfw
# Detect OS
-ifeq ($(OS),Windows_NT)
- DETECTED_OS := Windows
-else
- DETECTED_OS := $(shell uname -s)
-endif
+UNAME_S := $(shell uname -s)
# Directories
SRC_DIR := src
@@ -22,17 +18,14 @@ EXAMPLES_DIR := examples
SRCS := $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/**/*.c)
OBJS := $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRCS))
-# Add Metal backend written in Objective C only on Mac platform
-ifeq ($(DETECTED_OS),Darwin)
- SRCS += $(SRC_DIR)/backend_mtl.m
-endif
-
# Library outputs
STATIC_LIB := $(BUILD_DIR)/libceleritas.a
ifeq ($(UNAME_S),Darwin)
SHARED_LIB := $(BUILD_DIR)/libceleritas.dylib
SHARED_FLAGS := -dynamiclib
- LDFLAGS += -framework Foundation -framework CoreFoundation -framework CoreGraphics -framework AppKit
+ LDFLAGS += -framework Foundation -framework CoreFoundation -framework CoreGraphics -framework AppKit -framework QuartzCore -framework Metal -framework MetalKit
+ SRCS += $(SRC_DIR)/backend_mtl.m
+ OBJS += $(OBJ_DIR)/backend_mtl.o
else
SHARED_LIB := $(BUILD_DIR)/libceleritas.so
SHARED_FLAGS := -shared
@@ -47,6 +40,11 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(OBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $@
+# Objective C
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.m
+ @mkdir -p $(OBJ_DIR)
+ $(CC) $(CFLAGS) -c $< -o $@
+
$(SHARED_LIB): $(OBJS)
@mkdir -p $(BUILD_DIR)
$(CC) $(SHARED_FLAGS) -o $@ $^ $(LDFLAGS)
@@ -63,11 +61,10 @@ static: $(STATIC_LIB)
all: shared static
.PHONY: triangle
-triangle: build/triangle.bin
-
-build/triangle.bin: $(EXAMPLES_DIR)/triangle.c $(STATIC_LIB)
+triangle: $(EXAMPLES_DIR)/triangle.c $(SHARED_LIB)
@mkdir -p $(BUILD_DIR)
- $(CC) $(CFLAGS) $< -o $@ -L$(BUILD_DIR) -lceleritas $(LDFLAGS)
+ $(CC) $(CFLAGS) $(EXAMPLES_DIR)/triangle.c -L$(BUILD_DIR) -lceleritas $(LDFLAGS)
+ MTL_DEBUG_LAYER=1 build/triangle.bin
.PHONY: clean
clean:
diff --git a/TODO.md b/TODO.md
index 6e255fa..aa01249 100644
--- a/TODO.md
+++ b/TODO.md
@@ -6,6 +6,7 @@
- compile example
- [ ] Consolidate down to a handful of examples
- [x] Get rid of doxygen
+- [ ] make format
- [ ] Move to Vulkan-first rendering
- [ ] Build in pipeline (needs vulkan)
- [ ] Incorporate vma \ No newline at end of file
diff --git a/archive/src/render/archive/backends/metal/backend_metal.m b/archive/src/render/archive/backends/metal/backend_metal.m
index 4787755..0e9399e 100644
--- a/archive/src/render/archive/backends/metal/backend_metal.m
+++ b/archive/src/render/archive/backends/metal/backend_metal.m
@@ -1,5 +1,5 @@
#include <assert.h>
-// #define CEL_REND_BACKEND_METAL
+#define CEL_REND_BACKEND_METAL
#if defined(CEL_REND_BACKEND_METAL)
#include <stddef.h>
#include "ral_types.h"
diff --git a/examples/triangle.c b/examples/triangle.c
index 83da5e4..ccbcea3 100644
--- a/examples/triangle.c
+++ b/examples/triangle.c
@@ -6,7 +6,7 @@ int main() {
core_bringup("Celeritas Example: Triangle", NULL);
while (!app_should_exit()) {
- //
+ glfwPollEvents();
}
return 0;
diff --git a/include/celeritas.h b/include/celeritas.h
index 0437e15..c157918 100644
--- a/include/celeritas.h
+++ b/include/celeritas.h
@@ -78,6 +78,7 @@ struct GLFWwindow* get_window();
struct core {
const char* app_name;
struct GLFWwindow* window;
+ bool should_exit;
renderer* renderer;
input_state* input;
};
@@ -238,7 +239,6 @@ DEFINE_HANDLE(pipeline_handle);
#define MAX_SHADER_BINDINGS 16
// Backend-specific structs
-typedef struct gpu_device gpu_device;
typedef struct gpu_swapchain gpu_swapchain;
typedef struct gpu_compute_pipeline gpu_compute_pipeline;
typedef struct gpu_gfx_pipeline gpu_gfx_pipeline;
@@ -341,11 +341,21 @@ typedef struct gfx_pipeline_desc {
} gfx_pipeline_desc;
// --- RAL Functions
+
+// Resources
buf_handle ral_buffer_create(u64 size, const void* data);
void ral_buffer_destroy(buf_handle handle);
tex_handle ral_texture_create(texture_desc desc, bool create_view, const void* data);
void ral_texture_destroy(tex_handle handle);
+// Backend lifecycle
+void ral_backend_init(const char* window_name, struct GLFWwindow* window);
+void ral_backend_shutdown();
+
+// Frame lifecycle
+void ral_frame_start();
+void ral_frame_end();
+
// --- Containers (Forward declared as internals are unnecessary for external header)
typedef struct u32_darray u32_darray;
@@ -381,6 +391,11 @@ geometry geo_cone(f32 radius, f32 height, u32 resolution);
geometry geo_uv_sphere(f32 radius, u32 north_south_lines, u32 east_west_lines);
geometry geo_ico_sphere(f32 radius, f32 n_subdivisions);
+// --- Renderer
+
+// void renderer_init(renderer* rend);
+// void renderer_shutdown(renderer* rend);
+
// --- Scene / Transform Hierarchy
// --- Gameplay
@@ -407,6 +422,8 @@ model_handle model_load_from_gltf(const char* path);
// --- Animation
+// Compute shader approach so we only need one kind of vertex format
+
// --- Collisions
// --- Physics
diff --git a/src/backend_mtl.m b/src/backend_mtl.m
index 9a99e14..b3cd224 100644
--- a/src/backend_mtl.m
+++ b/src/backend_mtl.m
@@ -3,20 +3,66 @@
#ifdef GPU_METAL
#include <celeritas.h>
+#define MTL_DEBUG_LAYER 1
+
// Obj-C imports
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import <QuartzCore/CAMetalLayer.h>
+#define GLFW_INCLUDE_NONE
+#import <GLFW/glfw3.h>
+#define GLFW_EXPOSE_NATIVE_COCOA
+#import <GLFW/glfw3native.h>
+
// --- RAL types
-struct gpu_device {
- id<MTLDevice> id;
-};
struct gpu_swapchain {
int width, height;
CAMetalLayer* swapchain;
};
+typedef struct metal_context {
+ GLFWwindow* window;
+ NSWindow* metal_window;
+
+ id<MTLDevice> device;
+ id<CAMetalDrawable> surface;
+ gpu_swapchain default_swapchain;
+
+ id<MTLCommandQueue> command_queue;
+} metal_context;
+
+static metal_context ctx;
+
+void ral_backend_init(const char* window_name, struct GLFWwindow* window) {
+ printf("loading Metal backend\n");
+
+ printf("gpu device creation\n");
+ const id<MTLDevice> gpu = MTLCreateSystemDefaultDevice();
+ ctx.device = gpu;
+
+ printf("window init\n");
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+ glfwMakeContextCurrent(window);
+ NSWindow* nswindow = glfwGetCocoaWindow(window);
+ ctx.metal_window = nswindow;
+
+ // effectively the "framebuffer"
+ CAMetalLayer* metal_layer = [CAMetalLayer layer];
+ metal_layer.device = gpu;
+ metal_layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+ ctx.metal_window.contentView.layer = metal_layer;
+ ctx.metal_window.contentView.wantsLayer = true;
+
+ printf("command queue creation\n");
+ const id<MTLCommandQueue> queue = [ctx.device newCommandQueue];
+ ctx.command_queue = queue;
+}
+
+void ral_backend_shutdown() {
+ // no-op
+}
+
#endif \ No newline at end of file
diff --git a/src/core.c b/src/core.c
index 0c3c5ea..080e806 100644
--- a/src/core.c
+++ b/src/core.c
@@ -4,12 +4,35 @@
NAMESPACED_LOGGER(core);
+core g_core = {0};
+
+// forward declares
+void key_callback(GLFWwindow* win, int key, int scancode, int action, int mods);
+
void core_bringup(const char* window_name, struct GLFWwindow* optional_window) {
- // INFO("Initiate Core bringup");
INFO("Initiate Core bringup");
INFO("Create GLFW window");
+ glfwInit();
+ GLFWwindow* glfw_window = glfwCreateWindow(800, 600, window_name, NULL, NULL);
+ g_core.window = glfw_window;
+
+ // This may move into a renderer struct
+ ral_backend_init(window_name, glfw_window);
+
+ glfwSetKeyCallback(glfw_window, key_callback);
+}
+void core_shutdown() {
+ ral_backend_shutdown();
+ glfwTerminate();
+}
+
+bool app_should_exit() {
+ return glfwWindowShouldClose(g_core.window) || g_core.should_exit;
}
-void core_shutdown() {}
-bool app_should_exit() { return false; }
+void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
+ if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
+ g_core.should_exit = true;
+ }
+} \ No newline at end of file