The Metal renderer is now fully functioning.
parent
a18ef3197a
commit
521fb82113
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
typedef id<MTLTexture> Metal_Texture;
|
||||||
|
|
||||||
struct Metal_Buffer{
|
struct Metal_Buffer{
|
||||||
Node node;
|
Node node;
|
||||||
|
|
||||||
|
@ -18,22 +20,24 @@ struct Metal_Buffer{
|
||||||
u64 last_reuse_time;
|
u64 last_reuse_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Metal_Texture{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
@interface Metal_Renderer : NSObject<MTKViewDelegate>
|
@interface Metal_Renderer : NSObject<MTKViewDelegate>
|
||||||
@property (nonatomic) Render_Target *target;
|
@property (nonatomic) Render_Target *target;
|
||||||
|
|
||||||
- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView*)mtkView;
|
- (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;
|
- (Metal_Buffer*)get_reusable_buffer_with_size:(NSUInteger)size;
|
||||||
- (void)add_reusable_buffer:(Metal_Buffer*)buffer;
|
- (void)add_reusable_buffer:(Metal_Buffer*)buffer;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
global_const u32 metal__max_textures = 256;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
global_const char *metal__shaders_source = R"(
|
global_const char *metal__shaders_source = R"(
|
||||||
#include <metal_stdlib>
|
#include <metal_stdlib>
|
||||||
#include <simd/simd.h>
|
#include <simd/simd.h>
|
||||||
|
@ -106,11 +110,14 @@ return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment float4
|
fragment float4
|
||||||
fragment_shader(Rasterizer_Data in [[stage_in]]){
|
fragment_shader(Rasterizer_Data in [[stage_in]],
|
||||||
|
texture2d_array<half> in_texture [[texture(0)]]){
|
||||||
float has_thickness = step(0.49, in.half_thickness);
|
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;
|
float2 center = in.uvw.xy;
|
||||||
float roundness = in.uvw.z;
|
float roundness = in.uvw.z;
|
||||||
|
@ -121,7 +128,7 @@ float shape_value = (1.0 - smoothstep(-1.0, 0.0, sd));
|
||||||
shape_value *= has_thickness;
|
shape_value *= has_thickness;
|
||||||
|
|
||||||
// TOOD(yuval): Add sample_value to alpha
|
// 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);
|
return(out_color);
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -153,6 +160,9 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
|
|
||||||
Node buffer_cache;
|
Node buffer_cache;
|
||||||
u64 last_buffer_cache_purge_time;
|
u64 last_buffer_cache_purge_time;
|
||||||
|
|
||||||
|
Metal_Texture *textures;
|
||||||
|
u32 next_texture_handle_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView*)mtk_view{
|
- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView*)mtk_view{
|
||||||
|
@ -209,6 +219,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
pipeline_state_descriptor.vertexFunction = vertex_function;
|
pipeline_state_descriptor.vertexFunction = vertex_function;
|
||||||
pipeline_state_descriptor.fragmentFunction = fragment_function;
|
pipeline_state_descriptor.fragmentFunction = fragment_function;
|
||||||
pipeline_state_descriptor.vertexDescriptor = vertexDescriptor;
|
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].pixelFormat = mtk_view.colorPixelFormat;
|
||||||
pipeline_state_descriptor.colorAttachments[0].blendingEnabled = YES;
|
pipeline_state_descriptor.colorAttachments[0].blendingEnabled = YES;
|
||||||
pipeline_state_descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
pipeline_state_descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
||||||
|
@ -231,6 +242,10 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
dll_init_sentinel(&buffer_cache);
|
dll_init_sentinel(&buffer_cache);
|
||||||
last_buffer_cache_purge_time = system_now_time();
|
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
|
// NOTE(yuval): Create a capture scope for gpu frame capture
|
||||||
capture_scope = [[MTLCaptureManager sharedCaptureManager]
|
capture_scope = [[MTLCaptureManager sharedCaptureManager]
|
||||||
newCaptureScopeWithDevice:device];
|
newCaptureScopeWithDevice:device];
|
||||||
|
@ -338,6 +353,12 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
Face* face = font_set_face_from_id(font_set, group->face_id);
|
Face* face = font_set_face_from_id(font_set, group->face_id);
|
||||||
if (face != 0){
|
if (face != 0){
|
||||||
// TODO(yuval): Bind face texture
|
// 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{
|
} else{
|
||||||
// TODO(yuval): Bind default texture
|
// TODO(yuval): Bind default texture
|
||||||
}
|
}
|
||||||
|
@ -391,6 +412,51 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
|
||||||
[capture_scope endScope];
|
[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{
|
- (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
|
// NOTE(yuval): This routine is a modified version of Dear ImGui's MetalContext::dequeueReusableBufferOfLength in imgui_impl_metal.mm
|
||||||
|
|
||||||
|
|
|
@ -318,6 +318,7 @@ mac_file_can_be_made(u8* filename){
|
||||||
function void
|
function void
|
||||||
mac_resize(float width, float height){
|
mac_resize(float width, float height){
|
||||||
if ((width > 0.0f) && (height > 0.0f)){
|
if ((width > 0.0f) && (height > 0.0f)){
|
||||||
|
#if 1
|
||||||
NSSize coord_size = NSMakeSize(width, height);
|
NSSize coord_size = NSMakeSize(width, height);
|
||||||
NSSize backing_size = [mac_vars.view convertSizeToBacking:coord_size];
|
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.width = (i32)backing_size.width;
|
||||||
target.height = (i32)backing_size.height;
|
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);
|
system_signal_step(0);
|
||||||
|
|
|
@ -30,7 +30,7 @@ system_get_path_sig(){
|
||||||
local_persist b32 has_stashed_4ed_path = false;
|
local_persist b32 has_stashed_4ed_path = false;
|
||||||
if (!has_stashed_4ed_path){
|
if (!has_stashed_4ed_path){
|
||||||
local_const i32 binary_path_capacity = KB(32);
|
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();
|
pid_t pid = getpid();
|
||||||
i32 size = proc_pidpath(pid, memory, binary_path_capacity);
|
i32 size = proc_pidpath(pid, memory, binary_path_capacity);
|
||||||
|
@ -804,13 +804,13 @@ system_get_keyboard_modifiers_sig(){
|
||||||
|
|
||||||
function
|
function
|
||||||
graphics_get_texture_sig(){
|
graphics_get_texture_sig(){
|
||||||
u32 result = gl__get_texture(dim, texture_kind);
|
u32 result = mac_metal_get_texture(dim, texture_kind);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function
|
function
|
||||||
graphics_fill_texture_sig(){
|
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);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ mac_metal_init(NSWindow *window){
|
||||||
[metal_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
[metal_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||||
[metal_view setPaused:YES];
|
[metal_view setPaused:YES];
|
||||||
[metal_view setEnableSetNeedsDisplay:NO];
|
[metal_view setEnableSetNeedsDisplay:NO];
|
||||||
|
[metal_view setSampleCount:4];
|
||||||
|
|
||||||
metal_view.device = MTLCreateSystemDefaultDevice();
|
metal_view.device = MTLCreateSystemDefaultDevice();
|
||||||
|
|
||||||
|
@ -31,3 +32,22 @@ mac_metal_render(Render_Target* target){
|
||||||
u64 end_time = system_now_time();
|
u64 end_time = system_now_time();
|
||||||
printf("Metal Render Time: %fs\n\n", mac_get_time_diff_sec(begin_time, end_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;
|
||||||
|
}
|
Loading…
Reference in New Issue