summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-06-09 01:43:02 +1000
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-06-09 01:43:02 +1000
commit859ea7e23d2bbbc4b32b43727ae50aebe399e720 (patch)
tree868b5d938cec7846637cf403cde3723829822305
parent19a5fae08d7f1f85cb5448a5f2b19f0f9d342a0e (diff)
metal is back, baby
-rw-r--r--assets/shaders/blinn_phong.vert2
-rw-r--r--assets/shaders/cube.frag2
-rw-r--r--assets/shaders/cube.vert2
-rw-r--r--assets/shaders/triangle.metal33
-rw-r--r--assets/shaders/triangle.vert2
-rw-r--r--deps/Unity/extras/fixture/src/unity_fixture.c6
-rw-r--r--examples/cube/ex_cube.c4
-rw-r--r--examples/triangle/ex_triangle.c42
-rw-r--r--src/defines.h4
-rw-r--r--src/renderer/backends/backend_vulkan.c1
-rw-r--r--src/renderer/backends/metal/backend_metal.h74
-rw-r--r--src/renderer/backends/metal/backend_metal.m285
-rw-r--r--src/renderer/backends/opengl/backend_opengl.c2
-rw-r--r--src/renderer/backends/opengl/opengl_helpers.h18
-rw-r--r--src/renderer/ral.c6
-rw-r--r--src/renderer/ral.h3
-rw-r--r--src/renderer/render_types.h4
-rw-r--r--xmake.lua13
18 files changed, 458 insertions, 45 deletions
diff --git a/assets/shaders/blinn_phong.vert b/assets/shaders/blinn_phong.vert
index 1d2a53e..18609b7 100644
--- a/assets/shaders/blinn_phong.vert
+++ b/assets/shaders/blinn_phong.vert
@@ -1,4 +1,4 @@
-#version 430 core
+#version 410 core
struct Uniforms {
mat4 model;
diff --git a/assets/shaders/cube.frag b/assets/shaders/cube.frag
index 292578f..88ba822 100644
--- a/assets/shaders/cube.frag
+++ b/assets/shaders/cube.frag
@@ -1,4 +1,4 @@
-#version 450
+#version 430
layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert
index fa9f85b..2f1d76d 100644
--- a/assets/shaders/cube.vert
+++ b/assets/shaders/cube.vert
@@ -1,4 +1,4 @@
-#version 450
+#version 430
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
diff --git a/assets/shaders/triangle.metal b/assets/shaders/triangle.metal
new file mode 100644
index 0000000..6055705
--- /dev/null
+++ b/assets/shaders/triangle.metal
@@ -0,0 +1,33 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct VertexIn {
+ float2 position;
+ float3 color;
+};
+
+struct VertexOut {
+ float4 computedPosition [[position]];
+ float3 fragColor;
+};
+
+// Vertex shader
+vertex VertexOut basic_vertex(
+ const device VertexIn* vertex_array [[ buffer(0) ]],
+ unsigned int vid [[ vertex_id ]]
+ ) {
+ VertexIn v = vertex_array[vid];
+
+ VertexOut outVertex = VertexOut();
+ outVertex.computedPosition = float4(v.position.xy, 0.0, 1.0);
+ outVertex.fragColor = v.color;
+ return outVertex;
+}
+
+// Fragment shader
+fragment float4 basic_fragment(
+ VertexOut interpolated [[stage_in]]
+) {
+ return float4(interpolated.fragColor, 1.0);
+} \ No newline at end of file
diff --git a/assets/shaders/triangle.vert b/assets/shaders/triangle.vert
index 8030561..f98696c 100644
--- a/assets/shaders/triangle.vert
+++ b/assets/shaders/triangle.vert
@@ -1,4 +1,4 @@
-#version 450
+#version 430
layout(location = 0) in vec2 inPos;
layout(location = 1) in vec3 inColor;
diff --git a/deps/Unity/extras/fixture/src/unity_fixture.c b/deps/Unity/extras/fixture/src/unity_fixture.c
index e69b5a3..8ffe1f8 100644
--- a/deps/Unity/extras/fixture/src/unity_fixture.c
+++ b/deps/Unity/extras/fixture/src/unity_fixture.c
@@ -15,10 +15,8 @@ struct UNITY_FIXTURE_T UnityFixture;
* Build with -D UNITY_OUTPUT_CHAR=outputChar and include <stdio.h>
* int (*outputChar)(int) = putchar; */
-void setUp(void) { /*does nothing*/
-}
-void tearDown(void) { /*does nothing*/
-}
+void setUp(void) { /*does nothing*/ }
+void tearDown(void) { /*does nothing*/ }
static void announceTestRun(unsigned int runNumber) {
UnityPrint("Unity test run ");
diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c
index 7b0ab48..a3d5a9f 100644
--- a/examples/cube/ex_cube.c
+++ b/examples/cube/ex_cube.c
@@ -70,8 +70,8 @@ int main() {
str8 vert_path, frag_path;
#ifdef CEL_REND_BACKEND_OPENGL
- vert_path = str8lit("assets/shaders/blinn_phong.vert");
- frag_path = str8lit("assets/shaders/blinn_phong.frag");
+ vert_path = str8lit("assets/shaders/cube.vert");
+ frag_path = str8lit("assets/shaders/cube.frag");
#else
vert_path = str8lit("build/linux/x86_64/debug/cube.vert.spv");
frag_path = str8lit("build/linux/x86_64/debug/cube.frag.spv");
diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c
index 0191c18..d9954e6 100644
--- a/examples/triangle/ex_triangle.c
+++ b/examples/triangle/ex_triangle.c
@@ -36,12 +36,12 @@ int main() {
gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description);
str8 vert_path, frag_path;
-#ifdef CEL_REND_BACKEND_OPENGL
+#if defined(CEL_REND_BACKEND_OPENGL)
vert_path = str8lit("assets/shaders/triangle.vert");
frag_path = str8lit("assets/shaders/triangle.frag");
-#else
- vert_path = str8lit("build/linux/x86_64/debug/triangle.vert.spv");
- frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv");
+#elif defined(CEL_REND_BACKEND_METAL)
+ vert_path = str8lit("build/gfx.metallib");
+ frag_path = str8lit("build/gfx.metallib");
#endif
str8_opt vertex_shader = str8_from_file(&scratch, vert_path);
str8_opt fragment_shader = str8_from_file(&scratch, frag_path);
@@ -57,7 +57,11 @@ int main() {
.vs = { .debug_name = "Triangle Vertex Shader",
.filepath = vert_path,
.code = vertex_shader.contents,
- .is_spirv = true },
+#ifdef CEL_REND_BACKEND_METAL
+ .is_combined_vert_frag = true,
+#endif
+ .is_spirv = true,
+ },
.fs = { .debug_name = "Triangle Fragment Shader",
.filepath = frag_path,
.code = fragment_shader.contents,
@@ -75,7 +79,7 @@ int main() {
buffer_handle triangle_index_buf =
gpu_buffer_create(sizeof(indices), CEL_BUFFER_INDEX, CEL_BUFFER_FLAG_GPU, indices);
- // Main loop
+ // // Main loop
while (!should_exit()) {
input_update(&g_core.input);
@@ -83,24 +87,24 @@ int main() {
continue;
}
gpu_cmd_encoder* enc = gpu_get_default_cmd_encoder();
- // Begin recording
+ // // Begin recording
gpu_cmd_encoder_begin(*enc);
gpu_cmd_encoder_begin_render(enc, renderpass);
- encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline);
- encode_set_default_settings(enc);
+ // encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline);
+ // encode_set_default_settings(enc);
- // Record draw calls
- encode_set_vertex_buffer(enc, triangle_vert_buf);
- encode_set_index_buffer(enc, triangle_index_buf);
- encode_draw_indexed(enc, 6);
+ // // Record draw calls
+ // encode_set_vertex_buffer(enc, triangle_vert_buf);
+ // encode_set_index_buffer(enc, triangle_index_buf);
+ // encode_draw_indexed(enc, 6);
- // End recording
- gpu_cmd_encoder_end_render(enc);
+ // // End recording
+ // gpu_cmd_encoder_end_render(enc);
- gpu_cmd_buffer buf = gpu_cmd_encoder_finish(
- enc); // Command buffer is no longer recording and is ready to submit
- // Submit
- gpu_queue_submit(&buf);
+ // gpu_cmd_buffer buf = gpu_cmd_encoder_finish(enc); // Command buffer is no longer recording
+ // and is ready to submit
+ // // Submit
+ // gpu_queue_submit(&buf);
gpu_backend_end_frame();
}
diff --git a/src/defines.h b/src/defines.h
index a35dbf4..9050f25 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -77,6 +77,6 @@ Renderer backend defines:
#endif
#if defined(CEL_PLATFORM_MAC)
-// #define CEL_REND_BACKEND_METAL 1
-#define CEL_REND_BACKEND_OPENGL 1
+#define CEL_REND_BACKEND_METAL 1
+// #define CEL_REND_BACKEND_OPENGL 1
#endif \ No newline at end of file
diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c
index 06d8898..112e38b 100644
--- a/src/renderer/backends/backend_vulkan.c
+++ b/src/renderer/backends/backend_vulkan.c
@@ -403,6 +403,7 @@ VkFormat format_from_vertex_attr(vertex_attrib_type attr) {
}
gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) {
+ TRACE("GPU Graphics Pipeline creation");
// Allocate
gpu_pipeline_layout* layout =
pipeline_layout_pool_alloc(&context.gpu_pools.pipeline_layouts, NULL);
diff --git a/src/renderer/backends/metal/backend_metal.h b/src/renderer/backends/metal/backend_metal.h
new file mode 100644
index 0000000..59b21d6
--- /dev/null
+++ b/src/renderer/backends/metal/backend_metal.h
@@ -0,0 +1,74 @@
+#pragma once
+#define CEL_REND_BACKEND_METAL
+#if defined(CEL_REND_BACKEND_METAL)
+
+#include "defines.h"
+#include "maths_types.h"
+#ifdef __OBJC__
+#import <Metal/Metal.h>
+#import <MetalKit/MetalKit.h>
+#import <QuartzCore/CAMetalLayer.h>
+#import <Foundation/Foundation.h>
+#else
+typedef void* id;
+#endif
+
+typedef struct gpu_swapchain {
+ u32x2 dimensions;
+ #ifdef __OBJC__
+ CAMetalLayer* swapchain;
+ #else
+ void* swapchain;
+ #endif
+} gpu_swapchain;
+typedef struct gpu_device {
+ /** @brief `device` gives us access to our GPU */
+ #ifdef __OBJC__
+ id<MTLDevice> id;
+ #else
+ void* id;
+ #endif
+} gpu_device;
+typedef struct gpu_pipeline_layout {
+ void* pad;
+} gpu_pipeline_layout;
+typedef struct gpu_pipeline {
+ #ifdef __OBJC__
+ id<MTLRenderPipelineState> pipeline_state;
+ #else
+ void* pipeline_state;
+ #endif
+} gpu_pipeline;
+typedef struct gpu_renderpass {
+ #ifdef __OBJC__
+ MTLRenderPassDescriptor* rpass_descriptor;
+ #else
+ void* rpass_descriptor;
+ #endif
+} gpu_renderpass;
+typedef struct gpu_cmd_encoder {
+ #ifdef __OBJC__
+ id<MTLCommandBuffer> cmd_buffer;
+ id<MTLRenderCommandEncoder> render_encoder;
+ #else
+ void* cmd_buffer;
+ void* render_encoder;
+ #endif
+} gpu_cmd_encoder;
+typedef struct gpu_cmd_buffer {
+ void* pad;
+} gpu_cmd_buffer;
+
+typedef struct gpu_buffer {
+ #ifdef __OBJC__
+ id<MTLBuffer> id;
+ #else
+ void* id;
+ #endif
+ u64 size;
+} gpu_buffer;
+typedef struct gpu_texture {
+ void* pad;
+} gpu_texture;
+
+#endif \ No newline at end of file
diff --git a/src/renderer/backends/metal/backend_metal.m b/src/renderer/backends/metal/backend_metal.m
new file mode 100644
index 0000000..0e9399e
--- /dev/null
+++ b/src/renderer/backends/metal/backend_metal.m
@@ -0,0 +1,285 @@
+#include <assert.h>
+#define CEL_REND_BACKEND_METAL
+#if defined(CEL_REND_BACKEND_METAL)
+#include <stddef.h>
+#include "ral_types.h"
+#include "colours.h"
+#include <stdlib.h>
+#include "camera.h"
+#include "defines.h"
+#include "file.h"
+#include "log.h"
+#include "maths_types.h"
+#include "ral.h"
+
+#define GLFW_INCLUDE_NONE
+#define GLFW_EXPOSE_NATIVE_COCOA
+
+#include <GLFW/glfw3.h>
+#include <GLFW/glfw3native.h>
+
+#import <Foundation/Foundation.h>
+#import <Metal/Metal.h>
+#import <MetalKit/MetalKit.h>
+#import <QuartzCore/CAMetalLayer.h>
+#include "backend_metal.h"
+
+// --- Handy macros
+#define BUFFER_GET(h) (buffer_pool_get(&context.resource_pools->buffers, h))
+#define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h))
+
+typedef struct metal_context {
+ GLFWwindow* window;
+ NSWindow* metal_window;
+ arena pool_arena;
+
+ gpu_device* device;
+ gpu_swapchain* swapchain;
+ id<CAMetalDrawable> surface;
+
+ id<MTLCommandQueue> command_queue;
+ gpu_cmd_encoder main_command_buf;
+ gpu_backend_pools gpu_pools;
+ struct resource_pools* resource_pools;
+} metal_context;
+
+static metal_context context;
+
+struct GLFWwindow;
+
+bool gpu_backend_init(const char *window_name, struct GLFWwindow *window) {
+ INFO("loading Metal backend");
+
+ memset(&context, 0, sizeof(metal_context));
+ context.window = window;
+
+ size_t pool_buffer_size = 1024 * 1024;
+ context.pool_arena = arena_create(malloc(pool_buffer_size), pool_buffer_size);
+
+ backend_pools_init(&context.pool_arena, &context.gpu_pools);
+ context.resource_pools = malloc(sizeof(struct resource_pools));
+ resource_pools_init(&context.pool_arena, context.resource_pools);
+
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+
+ glfwMakeContextCurrent(window);
+ // FIXME: glfwSetFramebufferSizeCallback(ren->window, framebuffer_size_callback);
+
+ // get a NSWindow pointer from GLFWwindow
+ NSWindow *nswindow = glfwGetCocoaWindow(window);
+ context.metal_window = nswindow;
+
+ // const id<MTLCommandQueue> queue = [gpu newCommandQueue];
+ // CAMetalLayer *swapchain = [CAMetalLayer layer];
+ // swapchain.device = gpu;
+ // swapchain.opaque = YES;
+
+ // // set swapchain for the window
+ // nswindow.contentView.layer = swapchain;
+ // nswindow.contentView.wantsLayer = YES;
+
+ // MTLClearColor color = MTLClearColorMake(0.7, 0.1, 0.2, 1.0);
+
+ // // set all our state properties
+ // state->device = gpu;
+ // state->cmd_queue = queue;
+ // state->swapchain = swapchain;
+ // state->clear_color = color;
+
+ // NSError *err = 0x0; // TEMPORARY
+
+ // WARN("About to try loading metallib");
+ // id<MTLLibrary> defaultLibrary = [state->device newLibraryWithFile: @"build/gfx.metallib" error:&err];
+ // CASSERT(defaultLibrary);
+ // state->default_lib = defaultLibrary;
+ // if (!state->default_lib) {
+ // NSLog(@"Failed to load library");
+ // exit(0);
+ // }
+
+ // create_render_pipeline(state);
+
+ return true;
+}
+
+void gpu_backend_shutdown() {}
+
+bool gpu_device_create(gpu_device* out_device) {
+ TRACE("GPU Device creation");
+ const id<MTLDevice> gpu = MTLCreateSystemDefaultDevice();
+ out_device->id = gpu;
+ context.device = out_device;
+
+ const id<MTLCommandQueue> queue = [gpu newCommandQueue];
+ context.command_queue = queue;
+
+ return true;
+}
+void gpu_device_destroy() {}
+
+// --- Render Pipeline
+gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) {
+ TRACE("GPU Graphics Pipeline creation");
+ // Allocate
+ // gpu_pipeline_layout* layout =
+ // pipeline_layout_pool_alloc(&context.gpu_pools.pipeline_layouts, NULL);
+ gpu_pipeline* pipeline = pipeline_pool_alloc(&context.gpu_pools.pipelines, NULL);
+
+ WARN("About to try loading metallib");
+ assert(description.vs.is_combined_vert_frag);
+ // Ignore fragment shader data, as vert shader data contains both
+ NSError *err = 0x0; // TEMPORARY
+ NSString *myNSString = [NSString stringWithUTF8String:(char*)description.vs.filepath.buf];
+ id<MTLLibrary> default_library = [context.device->id newLibraryWithFile:myNSString error:&err];
+ assert(default_library);
+
+ // setup vertex and fragment shaders
+ id<MTLFunction> ren_vert = [default_library newFunctionWithName:@"basic_vertex"];
+ assert(ren_vert);
+ id<MTLFunction> ren_frag = [default_library newFunctionWithName:@"basic_fragment"];
+ assert(ren_frag);
+
+ // create pipeline descriptor
+ @autoreleasepool {
+ NSError *err = 0x0;
+ MTLRenderPipelineDescriptor *pld = [[MTLRenderPipelineDescriptor alloc] init];
+ NSString *pipeline_name = [NSString stringWithUTF8String: description.debug_name];
+ pld.label = pipeline_name;
+ pld.vertexFunction = ren_vert;
+ pld.fragmentFunction = ren_frag;
+ pld.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
+ pld.colorAttachments[0].blendingEnabled = YES;
+
+ MTLDepthStencilDescriptor *depthStencilDescriptor = [MTLDepthStencilDescriptor new];
+ depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionLess;
+ depthStencilDescriptor.depthWriteEnabled = YES;
+ pld.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
+
+ id<MTLDepthStencilState> depth_descriptor = [context.device->id newDepthStencilStateWithDescriptor:depthStencilDescriptor];
+ // FIXME: state->depth_state = depth_descriptor;
+
+ id<MTLRenderPipelineState> pipeline_state = [context.device->id newRenderPipelineStateWithDescriptor:pld error:&err];
+ TRACE("created renderpipelinestate");
+ pipeline->pipeline_state = pipeline_state;
+
+ }
+
+ return pipeline;
+}
+void gpu_pipeline_destroy(gpu_pipeline* pipeline) {}
+
+// --- Renderpass
+gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) {
+ gpu_renderpass* renderpass = renderpass_pool_alloc(&context.gpu_pools.renderpasses, NULL);
+
+ // TODO: Configure based on description
+ // set up render pass
+ context.surface = [context.swapchain->swapchain nextDrawable];
+ MTLRenderPassDescriptor *renderPassDescriptor = [[MTLRenderPassDescriptor alloc] init];
+ MTLRenderPassColorAttachmentDescriptor *cd = renderPassDescriptor.colorAttachments[0];
+ [cd setTexture:context.surface.texture];
+ [cd setLoadAction:MTLLoadActionClear];
+ MTLClearColor clearColor = MTLClearColorMake(0.1, 0.1, 0.0, 1.0);
+ [cd setClearColor:clearColor];
+ [cd setStoreAction:MTLStoreActionStore];
+
+ renderpass->rpass_descriptor = renderPassDescriptor;
+
+ return renderpass;
+}
+
+void gpu_renderpass_destroy(gpu_renderpass* pass) {}
+
+// --- Swapchain
+bool gpu_swapchain_create(gpu_swapchain* out_swapchain) {
+ TRACE("GPU Swapchain creation");
+ CAMetalLayer *swapchain = [CAMetalLayer layer];
+ swapchain.device = context.device->id;
+ swapchain.opaque = YES;
+ out_swapchain->swapchain = swapchain;
+
+ // set swapchain for the window
+ context.metal_window.contentView.layer = swapchain;
+ context.metal_window.contentView.wantsLayer = YES;
+
+ context.swapchain = out_swapchain;
+ return true;
+}
+void gpu_swapchain_destroy(gpu_swapchain* swapchain) {}
+
+// --- Command buffer
+gpu_cmd_encoder gpu_cmd_encoder_create() {
+ id <MTLCommandBuffer> cmd_buffer = [context.command_queue commandBuffer];
+
+ return (gpu_cmd_encoder) {
+ .cmd_buffer = cmd_buffer
+ };
+}
+void gpu_cmd_encoder_destroy(gpu_cmd_encoder* encoder) {}
+void gpu_cmd_encoder_begin(gpu_cmd_encoder encoder) { /* no-op */ }
+void gpu_cmd_encoder_begin_render(gpu_cmd_encoder* encoder, gpu_renderpass* renderpass) {
+ DEBUG("Create Render Command Encoder");
+ id<MTLRenderCommandEncoder> render_encoder = [encoder->cmd_buffer renderCommandEncoderWithDescriptor:renderpass->rpass_descriptor];
+ encoder->render_encoder = render_encoder;
+ // [encoder setDepthStencilState:state->depth_state];
+}
+void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder) {}
+void gpu_cmd_encoder_begin_compute() {}
+gpu_cmd_encoder* gpu_get_default_cmd_encoder() {
+ return &context.main_command_buf;
+}
+
+/** @brief Finish recording and return a command buffer that can be submitted to a queue */
+gpu_cmd_buffer gpu_cmd_encoder_finish(gpu_cmd_encoder* encoder) {}
+
+void gpu_queue_submit(gpu_cmd_buffer* buffer) {}
+
+void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_offset,
+ buffer_handle dst, u64 dst_offset, u64 copy_size);
+void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size);
+
+void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst,
+ u64 dst_offset, u64 copy_size);
+void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst);
+
+void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline) {}
+void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data) {}
+void encode_set_default_settings(gpu_cmd_encoder* encoder) {
+ [encoder->render_encoder setCullMode:MTLCullModeBack];
+}
+void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {
+ gpu_buffer* vertex_buf = BUFFER_GET(buf);
+ [encoder->render_encoder setVertexBuffer:vertex_buf->id offset:0 atIndex:0];
+}
+void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {}
+void encode_set_bind_group() {}
+void encode_draw(gpu_cmd_encoder* encoder) {}
+void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count) {}
+void encode_clear_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) {}
+
+buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_flags flags,
+ const void* data) {
+ buffer_handle handle;
+ gpu_buffer* buffer = buffer_pool_alloc(&context.resource_pools->buffers, &handle);
+ buffer->size = size;
+
+ id<MTLBuffer> mtl_vert_buf = [context.device->id newBufferWithBytes:data
+ length: size
+ options:MTLResourceStorageModeShared];
+ return handle;
+}
+void gpu_buffer_destroy(buffer_handle buffer) {}
+void gpu_buffer_upload(const void* data) {}
+
+texture_handle gpu_texture_create(texture_desc desc, bool create_view, const void* data) {}
+void gpu_texture_destroy(texture_handle) {}
+void gpu_texture_upload(texture_handle texture, const void* data) {}
+
+bool gpu_backend_begin_frame() {
+ context.main_command_buf.cmd_buffer = [context.command_queue commandBuffer];
+ return true;
+ }
+void gpu_backend_end_frame() {}
+void gpu_temp_draw(size_t n_verts) {}
+
+#endif \ No newline at end of file
diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c
index 8be1c2a..96415f1 100644
--- a/src/renderer/backends/opengl/backend_opengl.c
+++ b/src/renderer/backends/opengl/backend_opengl.c
@@ -2,7 +2,7 @@
#include "colours.h"
#include "opengl_helpers.h"
#include "ral_types.h"
-#define CEL_REND_BACKEND_OPENGL
+// #define CEL_REND_BACKEND_OPENGL
#if defined(CEL_REND_BACKEND_OPENGL)
#include <stdlib.h>
#include "camera.h"
diff --git a/src/renderer/backends/opengl/opengl_helpers.h b/src/renderer/backends/opengl/opengl_helpers.h
index 2f6bef3..44d40cb 100644
--- a/src/renderer/backends/opengl/opengl_helpers.h
+++ b/src/renderer/backends/opengl/opengl_helpers.h
@@ -1,36 +1,36 @@
#pragma once
-#include "ral_types.h"
#include <glad/glad.h>
#include <glfw3.h>
+#include "ral_types.h"
typedef struct opengl_vertex_attr {
u32 count;
GLenum data_type;
-} opengl_vertex_attr ;
+} opengl_vertex_attr;
opengl_vertex_attr format_from_vertex_attr(vertex_attrib_type attr) {
switch (attr) {
case ATTR_F32:
- return (opengl_vertex_attr){.count = 1, .data_type = GL_FLOAT };
+ return (opengl_vertex_attr){ .count = 1, .data_type = GL_FLOAT };
case ATTR_U32:
- return (opengl_vertex_attr){.count = 1, .data_type = GL_UNSIGNED_INT };
+ return (opengl_vertex_attr){ .count = 1, .data_type = GL_UNSIGNED_INT };
case ATTR_I32:
- return (opengl_vertex_attr){.count = 1, .data_type = GL_INT };
+ return (opengl_vertex_attr){ .count = 1, .data_type = GL_INT };
case ATTR_F32x2:
- return (opengl_vertex_attr){.count = 2, .data_type = GL_FLOAT };
+ return (opengl_vertex_attr){ .count = 2, .data_type = GL_FLOAT };
case ATTR_U32x2:
// return VK_FORMAT_R32G32_UINT;
case ATTR_I32x2:
// return VK_FORMAT_R32G32_UINT;
case ATTR_F32x3:
- return (opengl_vertex_attr){.count = 3, .data_type = GL_FLOAT };
+ return (opengl_vertex_attr){ .count = 3, .data_type = GL_FLOAT };
case ATTR_U32x3:
// return VK_FORMAT_R32G32B32_UINT;
case ATTR_I32x3:
// return VK_FORMAT_R32G32B32_SINT;
case ATTR_F32x4:
- return (opengl_vertex_attr){.count = 4, .data_type = GL_FLOAT };
+ return (opengl_vertex_attr){ .count = 4, .data_type = GL_FLOAT };
case ATTR_U32x4:
// return VK_FORMAT_R32G32B32A32_UINT;
case ATTR_I32x4:
- // return VK_FORMAT_R32G32B32A32_SINT;
+ return (opengl_vertex_attr){ .count = 4, .data_type = GL_INT };
}
} \ No newline at end of file
diff --git a/src/renderer/ral.c b/src/renderer/ral.c
index 4f2a999..fe12b4f 100644
--- a/src/renderer/ral.c
+++ b/src/renderer/ral.c
@@ -1,6 +1,12 @@
#include "ral.h"
+#if defined(CEL_REND_BACKEND_VULKAN)
+#include "backend_vulkan.h"
+#elif defined(CEL_REND_BACKEND_METAL)
+#include "backend_metal.h"
+#elif defined(CEL_REND_BACKEND_OPENGL)
#include "backend_opengl.h"
+#endif
size_t vertex_attrib_size(vertex_attrib_type attr) {
switch (attr) {
diff --git a/src/renderer/ral.h b/src/renderer/ral.h
index a18ea87..3415b04 100644
--- a/src/renderer/ral.h
+++ b/src/renderer/ral.h
@@ -66,9 +66,10 @@ typedef enum pipeline_kind {
typedef struct shader_desc {
const char* debug_name;
- str8 filepath; // where it came from
+ str8 filepath; // Where it came from
str8 code; // Either GLSL or SPIRV bytecode
bool is_spirv;
+ bool is_combined_vert_frag; // Contains both vertex and fragment stages
} shader_desc;
struct graphics_pipeline_desc {
diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h
index 63e5b29..a2c35fe 100644
--- a/src/renderer/render_types.h
+++ b/src/renderer/render_types.h
@@ -17,12 +17,12 @@
#endif
#if defined(CEL_REND_BACKEND_VULKAN)
#include "backend_vulkan.h"
+#elif defined(CEL_REND_BACKEND_METAL)
+#include "backend_metal.h"
#elif defined(CEL_REND_BACKEND_OPENGL)
#include "backend_opengl.h"
#endif
-#include "backend_opengl.h"
-
struct GLFWwindow;
/** @brief configuration passed to the renderer at init time */
diff --git a/xmake.lua b/xmake.lua
index 5a2707c..86a673a 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -1,6 +1,6 @@
set_project("celeritas")
set_version("0.1.0")
-set_config("cc", "gcc")
+set_config("cc", "clang")
add_rules("mode.debug", "mode.release") -- we have two modes: debug & release
@@ -30,6 +30,7 @@ elseif is_plat("windows") then
elseif is_plat("macosx") then
add_defines("CEL_PLATFORM_MAC")
add_frameworks("Cocoa", "IOKit", "CoreVideo", "OpenGL")
+ add_frameworks( "Foundation", "Metal", "QuartzCore")
set_runenv("MTL_DEBUG_LAYER", "1")
-- add_syslinks("GL")
end
@@ -62,6 +63,7 @@ local core_sources = {
"src/renderer/*.c",
"src/renderer/backends/*.c",
"src/renderer/backends/opengl/*.c",
+ "src/renderer/backends/metal/*.m",
"src/resources/*.c",
"src/std/*.c",
"src/std/containers/*.c",
@@ -113,6 +115,7 @@ target("core_config")
add_includedirs("src/renderer/", {public = true})
add_includedirs("src/renderer/backends/", {public = true})
add_includedirs("src/renderer/backends/opengl", {public = true})
+ add_includedirs("src/renderer/backends/metal", {public = true})
add_includedirs("src/resources/", {public = true})
add_includedirs("src/std/", {public = true})
add_includedirs("src/std/containers", {public = true})
@@ -166,6 +169,14 @@ target("tri")
add_deps("core_static")
add_files("examples/triangle/ex_triangle.c")
set_rundir("$(projectdir)")
+ if is_plat("macosx") then
+ before_build(function (target)
+ print("build metal shaders lib")
+ os.exec("mkdir -p build/shaders")
+ os.exec("xcrun -sdk macosx metal -c assets/shaders/triangle.metal -o build/shaders/gfx.air")
+ os.exec("xcrun -sdk macosx metallib build/shaders/gfx.air -o build/gfx.metallib")
+ end)
+ end
target("cube")
set_kind("binary")