#pragma once global_variable Renderer renderer_memory; fn NSString* apple_string(String string) { NSString* result = [[NSString alloc] initWithBytes:string.pointer length:string.length encoding:NSUTF8StringEncoding]; return result; } fn Renderer* rendering_initialize(Arena* arena) { Renderer* renderer = &renderer_memory; @autoreleasepool { renderer->device = MTLCreateSystemDefaultDevice(); String shader_source = file_read(arena, strlit("bootstrap/std/shaders/rect.metal")); NSString* apple_shader_source = apple_string(shader_source); NSError* error = nil; id library = [renderer->device newLibraryWithSource: apple_shader_source options:nil error:&error]; if (!library) { // Inspect the error NSLog(@"Error Domain: %@", error.domain); NSLog(@"Error Code: %ld", (long)error.code); NSLog(@"Localized Description: %@", error.localizedDescription); NSDictionary *userInfo = error.userInfo; if (userInfo) { NSLog(@"Additional Info: %@", userInfo); } // Take action based on the error if ([error.domain isEqualToString:MTLLibraryErrorDomain]) { NSLog(@"Metal Library Compilation Error. Check the shader source."); } else { NSLog(@"Unexpected error occurred."); } } id vertex = [library newFunctionWithName:@"vertex_main"]; id fragment = [library newFunctionWithName:@"fragment_main"]; MTLRenderPipelineDescriptor* pipeline_descriptor = [[MTLRenderPipelineDescriptor alloc] init]; pipeline_descriptor.vertexFunction = vertex; pipeline_descriptor.fragmentFunction = fragment; pipeline_descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB; id pipeline_state = [renderer->device newRenderPipelineStateWithDescriptor:pipeline_descriptor error:&error]; if (!pipeline_state) { // Inspect the error NSLog(@"Error Domain: %@", error.domain); NSLog(@"Error Code: %ld", (long)error.code); NSLog(@"Localized Description: %@", error.localizedDescription); NSDictionary *userInfo = error.userInfo; if (userInfo) { NSLog(@"Additional Info: %@", userInfo); } } id command_queue = [renderer->device newCommandQueue]; } return renderer; } global_variable RenderWindow render_window_memory; fn RenderWindow* rendering_initialize_window(Renderer* renderer, WindowingInstance* window) { RenderWindow* render_window = &render_window_memory; CAMetalLayer* layer = [CAMetalLayer layer]; render_window->layer = layer; layer.device = renderer->device; layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB; layer.framebufferOnly = true; layer.frame = window.frame; window.contentView.layer = layer; window.opaque = true; window.backgroundColor = nil; return render_window; } fn void renderer_window_frame_begin(Renderer* renderer, RenderWindow* window) { @autoreleasepool { id drawable = [window->layer nextDrawable]; MTLRenderPassDescriptor* render_pass_descriptor = [MTLRenderPassDescriptor renderPassDescriptor]; MTLRenderPassColorAttachmentDescriptor* color_attachment = render_pass_descriptor.colorAttachments[0]; color_attachment.clearColor = MTLClearColorMake(1, 1, 1, 1); color_attachment.storeAction = MTLStoreActionStore; color_attachment.texture = drawable.texture; id command_buffer = [renderer->command_queue commandBuffer]; id render_command_encoder = [command_buffer renderCommandEncoderWithDescriptor:render_pass_descriptor]; [render_command_encoder setRenderPipelineState: renderer->pipeline_state]; [render_command_encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3]; [render_command_encoder endEncoding]; [command_buffer presentDrawable:drawable]; [command_buffer commit]; } } fn void renderer_window_frame_end(Renderer* renderer, RenderWindow* window) { // todo(); } fn TextureIndex renderer_texture_create(Renderer* renderer, TextureMemory texture_memory) { todo(); } fn void window_rect_texture_update_begin(RenderWindow* window) { todo(); } fn void renderer_queue_font_update(Renderer* renderer, RenderWindow* window, RenderFontType type, TextureAtlas atlas) { todo(); } fn void window_queue_rect_texture_update(RenderWindow* window, RectTextureSlot slot, TextureIndex texture_index) { todo(); } fn void window_rect_texture_update_end(Renderer* renderer, RenderWindow* window) { todo(); } fn void window_render_rect(RenderWindow* window, RectDraw draw) { // todo(); } fn void window_render_text(Renderer* renderer, RenderWindow* window, String string, float4 color, RenderFontType font_type, u32 x_offset, u32 y_offset) { // todo(); }