From 521fb82113b9d6d49e30774bf00a6d173ee976ff Mon Sep 17 00:00:00 2001 From: Yuval Dolev Date: Wed, 8 Jan 2020 21:44:47 +0200 Subject: [PATCH] The Metal renderer is now fully functioning. --- metal/4ed_metal_render.mm | 82 ++++++++++++++++++++++++++++--- platform_mac/mac_4ed.mm | 8 +++ platform_mac/mac_4ed_functions.mm | 6 +-- platform_mac/mac_4ed_metal.mm | 20 ++++++++ 4 files changed, 105 insertions(+), 11 deletions(-) diff --git a/metal/4ed_metal_render.mm b/metal/4ed_metal_render.mm index a1d8e7f0..147af602 100644 --- a/metal/4ed_metal_render.mm +++ b/metal/4ed_metal_render.mm @@ -10,6 +10,8 @@ //////////////////////////////// +typedef id Metal_Texture; + struct Metal_Buffer{ Node node; @@ -18,22 +20,24 @@ struct Metal_Buffer{ u64 last_reuse_time; }; -struct Metal_Texture{ - -}; - //////////////////////////////// @interface Metal_Renderer : NSObject @property (nonatomic) Render_Target *target; - (nonnull instancetype)initWithMetalKitView:(nonnull MTKView*)mtkView; +- (u32)get_texture_of_dim:(Vec3_i32)dim kind:(Texture_Kind)kind; +- (b32)fill_texture:(u32)texture kind:(Texture_Kind)kind pos:(Vec3_i32)p dim:(Vec3_i32)dim data:(void*)data; - (Metal_Buffer*)get_reusable_buffer_with_size:(NSUInteger)size; - (void)add_reusable_buffer:(Metal_Buffer*)buffer; @end //////////////////////////////// +global_const u32 metal__max_textures = 256; + +//////////////////////////////// + global_const char *metal__shaders_source = R"( #include #include @@ -106,11 +110,14 @@ return(result); } fragment float4 -fragment_shader(Rasterizer_Data in [[stage_in]]){ +fragment_shader(Rasterizer_Data in [[stage_in]], +texture2d_array in_texture [[texture(0)]]){ float has_thickness = step(0.49, in.half_thickness); -// float does_not_have_thickness = (1.0 - has_thickness); +float does_not_have_thickness = (1.0 - has_thickness); -// TODO(yuval): Sample texture here. +constexpr sampler texture_sampler(coord::normalized, min_filter::linear, mag_filter::linear, mip_filter::linear); +half sample_value = in_texture.sample(texture_sampler, in.uvw.xy, in.uvw.z).r; +sample_value *= does_not_have_thickness; float2 center = in.uvw.xy; float roundness = in.uvw.z; @@ -121,7 +128,7 @@ float shape_value = (1.0 - smoothstep(-1.0, 0.0, sd)); shape_value *= has_thickness; // TOOD(yuval): Add sample_value to alpha -float4 out_color = in.color;// float4(in.color.xyz, in.color.a * (shape_value)); +float4 out_color = float4(in.color.xyz, in.color.a * (sample_value + shape_value)); return(out_color); } )"; @@ -153,6 +160,9 @@ metal__make_buffer(u32 size, id device){ Node buffer_cache; u64 last_buffer_cache_purge_time; + + Metal_Texture *textures; + u32 next_texture_handle_index; } - (nonnull instancetype)initWithMetalKitView:(nonnull MTKView*)mtk_view{ @@ -209,6 +219,7 @@ metal__make_buffer(u32 size, id device){ pipeline_state_descriptor.vertexFunction = vertex_function; pipeline_state_descriptor.fragmentFunction = fragment_function; pipeline_state_descriptor.vertexDescriptor = vertexDescriptor; + pipeline_state_descriptor.sampleCount = mtk_view.sampleCount; pipeline_state_descriptor.colorAttachments[0].pixelFormat = mtk_view.colorPixelFormat; pipeline_state_descriptor.colorAttachments[0].blendingEnabled = YES; pipeline_state_descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; @@ -231,6 +242,10 @@ metal__make_buffer(u32 size, id device){ dll_init_sentinel(&buffer_cache); last_buffer_cache_purge_time = system_now_time(); + // NOTE(yuval): Initialize the textures array + textures = (Metal_Texture*)system_memory_allocate(metal__max_textures * sizeof(Metal_Texture), file_name_line_number_lit_u8); + next_texture_handle_index = 0; + // NOTE(yuval): Create a capture scope for gpu frame capture capture_scope = [[MTLCaptureManager sharedCaptureManager] newCaptureScopeWithDevice:device]; @@ -338,6 +353,12 @@ metal__make_buffer(u32 size, id device){ Face* face = font_set_face_from_id(font_set, group->face_id); if (face != 0){ // TODO(yuval): Bind face texture + u32 texture_handle = face->texture; + Metal_Texture texture = textures[texture_handle]; + if (texture != 0){ + [render_encoder setFragmentTexture:texture + atIndex:0]; + } } else{ // TODO(yuval): Bind default texture } @@ -391,6 +412,51 @@ metal__make_buffer(u32 size, id device){ [capture_scope endScope]; } +- (u32)get_texture_of_dim:(Vec3_i32)dim kind:(Texture_Kind)kind{ + u32 handle = next_texture_handle_index; + + // NOTE(yuval): Create a texture descriptor + MTLTextureDescriptor *texture_descriptor = [[MTLTextureDescriptor alloc] init]; + texture_descriptor.textureType = MTLTextureType2DArray; + texture_descriptor.pixelFormat = MTLPixelFormatR8Unorm; + texture_descriptor.width = dim.x; + texture_descriptor.height = dim.y; + texture_descriptor.depth = dim.z; + + // NOTE(yuval): Create the texture from the device using the descriptor and add it to the textures array + Metal_Texture texture = [device newTextureWithDescriptor:texture_descriptor]; + textures[handle] = texture; + + next_texture_handle_index += 1; + + return handle; +} + +- (b32)fill_texture:(u32)handle kind:(Texture_Kind)kind pos:(Vec3_i32)p dim:(Vec3_i32)dim data:(void*)data{ + b32 result = false; + + if (data){ + Metal_Texture texture = textures[handle]; + + if (texture != 0){ + MTLRegion replace_region = { + {(NSUInteger)p.x, (NSUInteger)p.y, (NSUInteger)p.z}, + {(NSUInteger)dim.x, (NSUInteger)dim.y, (NSUInteger)dim.z} + }; + + // NOTE(yuval): Fill the texture with data + [texture replaceRegion:replace_region + mipmapLevel:0 + withBytes:data + bytesPerRow:dim.x]; + + result = true; + } + } + + return result; +} + - (Metal_Buffer*)get_reusable_buffer_with_size:(NSUInteger)size{ // NOTE(yuval): This routine is a modified version of Dear ImGui's MetalContext::dequeueReusableBufferOfLength in imgui_impl_metal.mm diff --git a/platform_mac/mac_4ed.mm b/platform_mac/mac_4ed.mm index 6ea09e72..05d07a2a 100644 --- a/platform_mac/mac_4ed.mm +++ b/platform_mac/mac_4ed.mm @@ -318,6 +318,7 @@ mac_file_can_be_made(u8* filename){ function void mac_resize(float width, float height){ if ((width > 0.0f) && (height > 0.0f)){ +#if 1 NSSize coord_size = NSMakeSize(width, height); NSSize backing_size = [mac_vars.view convertSizeToBacking:coord_size]; @@ -326,6 +327,13 @@ mac_resize(float width, float height){ target.width = (i32)backing_size.width; target.height = (i32)backing_size.height; +#else + mac_vars.width = (i32)width; + mac_vars.height = (i32)height; + + target.width = (i32)width; + target.height = (i32)height; +#endif } system_signal_step(0); diff --git a/platform_mac/mac_4ed_functions.mm b/platform_mac/mac_4ed_functions.mm index aa3f619d..11dac318 100644 --- a/platform_mac/mac_4ed_functions.mm +++ b/platform_mac/mac_4ed_functions.mm @@ -30,7 +30,7 @@ system_get_path_sig(){ local_persist b32 has_stashed_4ed_path = false; if (!has_stashed_4ed_path){ local_const i32 binary_path_capacity = KB(32); - u8 *memory = (u8*)system_memory_allocate(binary_path_capacity, string_u8_litexpr(file_name_line_number)); + u8 *memory = (u8*)system_memory_allocate(binary_path_capacity, file_name_line_number_lit_u8); pid_t pid = getpid(); i32 size = proc_pidpath(pid, memory, binary_path_capacity); @@ -804,13 +804,13 @@ system_get_keyboard_modifiers_sig(){ function graphics_get_texture_sig(){ - u32 result = gl__get_texture(dim, texture_kind); + u32 result = mac_metal_get_texture(dim, texture_kind); return(result); } function graphics_fill_texture_sig(){ - b32 result = gl__fill_texture(texture_kind, texture, p, dim, data); + b32 result = mac_metal_fill_texture(texture_kind, texture, p, dim, data); return(result); } diff --git a/platform_mac/mac_4ed_metal.mm b/platform_mac/mac_4ed_metal.mm index 4970feab..063e618a 100644 --- a/platform_mac/mac_4ed_metal.mm +++ b/platform_mac/mac_4ed_metal.mm @@ -12,6 +12,7 @@ mac_metal_init(NSWindow *window){ [metal_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [metal_view setPaused:YES]; [metal_view setEnableSetNeedsDisplay:NO]; + [metal_view setSampleCount:4]; metal_view.device = MTLCreateSystemDefaultDevice(); @@ -30,4 +31,23 @@ mac_metal_render(Render_Target* target){ [metal_view draw]; u64 end_time = system_now_time(); printf("Metal Render Time: %fs\n\n", mac_get_time_diff_sec(begin_time, end_time)); +} + +function u32 +mac_metal_get_texture(Vec3_i32 dim, Texture_Kind texture_kind){ + u32 result = [metal_renderer get_texture_of_dim:dim + kind:texture_kind]; + + return result; +} + +function b32 +mac_metal_fill_texture(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 dim, void *data){ + b32 result = [metal_renderer fill_texture:texture + kind:texture_kind + pos:p + dim:dim + data:data]; + + return result; } \ No newline at end of file