summaryrefslogtreecommitdiff
path: root/src/backend_mtl.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend_mtl.m')
-rw-r--r--src/backend_mtl.m61
1 files changed, 59 insertions, 2 deletions
diff --git a/src/backend_mtl.m b/src/backend_mtl.m
index 6ff5058..48e0ab0 100644
--- a/src/backend_mtl.m
+++ b/src/backend_mtl.m
@@ -2,18 +2,20 @@
#ifdef GPU_METAL
-#define MTL_DEBUG_LAYER 1
+#define MTL_DEBUG_LAYER 1 // enable all metal validation layers
// Obj-C imports
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import <QuartzCore/CAMetalLayer.h>
+#include <CoreGraphics/CGGeometry.h>
#define GLFW_INCLUDE_NONE
#import <GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_COCOA
#import <GLFW/glfw3native.h>
+#include "stb_image.h"
NAMESPACED_LOGGER(metal);
@@ -37,7 +39,12 @@ typedef struct metal_buffer {
id<MTLBuffer> id;
} metal_buffer;
+typedef struct metal_texture {
+ id<MTLTexture> id;
+} metal_texture;
+
TYPED_POOL(metal_buffer, buf);
+TYPED_POOL(metal_texture, tex);
TYPED_POOL(metal_pipeline, pipeline);
typedef struct metal_context {
@@ -53,6 +60,7 @@ typedef struct metal_context {
/* pools */
buf_pool bufpool;
+ tex_pool texpool;
pipeline_pool psopool; // pso = pipeline state object
} metal_context;
@@ -66,15 +74,18 @@ void ral_backend_init(const char* window_name, struct GLFWwindow* window) {
ctx.device = gpu;
TRACE("window init");
- glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwMakeContextCurrent(window);
NSWindow* nswindow = glfwGetCocoaWindow(window);
ctx.metal_window = nswindow;
+ int width, height;
+ glfwGetFramebufferSize(window, &width, &height);
+
// effectively the "framebuffer"
CAMetalLayer* metal_layer = [CAMetalLayer layer];
metal_layer.device = gpu;
metal_layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+ metal_layer.drawableSize = CGSizeMake(width, height);
ctx.metal_window.contentView.layer = metal_layer;
ctx.metal_window.contentView.wantsLayer = true;
ctx.default_swapchain.swapchain = metal_layer;
@@ -87,6 +98,9 @@ void ral_backend_init(const char* window_name, struct GLFWwindow* window) {
metal_buffer* buffer_storage = malloc(sizeof(metal_buffer) * 100);
ctx.bufpool = buf_pool_create(buffer_storage, 100, sizeof(metal_buffer));
+ metal_texture* texture_storage = malloc(sizeof(metal_texture) * 100);
+ ctx.texpool = tex_pool_create(texture_storage, 100, sizeof(metal_texture));
+
metal_pipeline* pipeline_storage = malloc(sizeof(metal_pipeline) * 100);
ctx.psopool = pipeline_pool_create(pipeline_storage, 100, sizeof(metal_pipeline));
@@ -114,6 +128,39 @@ buf_handle ral_buffer_create(u64 size, const void *data) {
return handle;
}
+tex_handle ral_texture_create(texture_desc desc, bool create_view, const void *data) {
+ tex_handle handle;
+ metal_texture* texture = tex_pool_alloc(&ctx.texpool, &handle);
+
+ MTLTextureDescriptor* texture_descriptor = [[MTLTextureDescriptor alloc] init];
+ [texture_descriptor setPixelFormat:MTLPixelFormatRGBA8Unorm];
+ [texture_descriptor setWidth:desc.width];
+ [texture_descriptor setHeight:desc.height];
+
+ texture->id = [ctx.device newTextureWithDescriptor:texture_descriptor];
+
+ MTLRegion region = MTLRegionMake2D(0, 0, desc.width, desc.height);
+ u32 bytes_per_row = 4 * desc.width;
+
+ [texture->id replaceRegion:region mipmapLevel:0 withBytes:data bytesPerRow:bytes_per_row];
+
+ [texture_descriptor release];
+
+ return handle;
+}
+
+tex_handle ral_texture_load_from_file(const char* filepath) {
+ texture_desc desc;
+
+ stbi_set_flip_vertically_on_load(true);
+ unsigned char* image = stbi_load(filepath, &desc.width, &desc.height, &desc.num_channels, STBI_rgb_alpha);
+ assert(image != NULL);
+
+ tex_handle handle = ral_texture_create(desc, false, image);
+ stbi_image_free(image);
+ return handle;
+}
+
pipeline_handle ral_gfx_pipeline_create(gfx_pipeline_desc desc) {
TRACE("creating graphics pipeline");
@@ -187,6 +234,11 @@ void ral_encode_set_vertex_buf(gpu_encoder *enc, buf_handle vbuf) {
[enc->cmd_encoder setVertexBuffer:b->id offset:0 atIndex:0 ];
}
+void ral_encode_set_texture(gpu_encoder* enc, tex_handle texture, u32 slot) {
+ metal_texture* t = tex_pool_get(&ctx.texpool, texture);
+ [enc->cmd_encoder setFragmentTexture:t->id atIndex:slot];
+}
+
void ral_encode_draw_tris(gpu_encoder* enc, size_t start, size_t count) {
MTLPrimitiveType tri_primitive = MTLPrimitiveTypeTriangle;
[enc->cmd_encoder drawPrimitives:tri_primitive vertexStart:start vertexCount:count];
@@ -203,4 +255,9 @@ void ral_frame_draw(scoped_draw_commands draw_fn) {
void ral_frame_end() {}
+void ral_backend_resize_framebuffer(int width, int height) {
+ TRACE("resizing framebuffer");
+ ctx.default_swapchain.swapchain.drawableSize = CGSizeMake((float)width, (float)height);
+}
+
#endif \ No newline at end of file