Started working on an abstraction for the macOS renderer implementations.

master
Yuval Dolev 2020-01-09 02:15:25 +02:00
parent 521fb82113
commit 912bcae8a7
8 changed files with 194 additions and 102 deletions

View File

@ -263,8 +263,10 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
[capture_scope beginScope]; [capture_scope beginScope];
i32 width = _target->width; // HACK(yuval): This is the best way I found to force valid width and height without drawing on the next drawing cycle (1 frame delay).
i32 height = _target->height; CGSize drawable_size = [view drawableSize];
i32 width = (i32)Min(_target->width, drawable_size.width);
i32 height = (i32)Min(_target->height, drawable_size.height);
Font_Set *font_set = (Font_Set*)_target->font_set; Font_Set *font_set = (Font_Set*)_target->font_set;
@ -332,6 +334,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
{ {
Rect_i32 box = Ri32(group->clip_box); Rect_i32 box = Ri32(group->clip_box);
NSUInteger x0 = (NSUInteger)Min(Max(0, box.x0), width - 1); NSUInteger x0 = (NSUInteger)Min(Max(0, box.x0), width - 1);
NSUInteger x1 = (NSUInteger)Min(Max(0, box.x1), width); NSUInteger x1 = (NSUInteger)Min(Max(0, box.x1), width);
NSUInteger y0 = (NSUInteger)Min(Max(0, box.y0), height - 1); NSUInteger y0 = (NSUInteger)Min(Max(0, box.y0), height - 1);

View File

@ -129,7 +129,7 @@ sd = abs(sd + half_thickness) - half_thickness;
float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd); float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd);
shape_value *= has_thickness; shape_value *= has_thickness;
out_color = fragment_color;//vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value)); out_color = vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value));
} }
)foo"; )foo";
@ -285,8 +285,6 @@ gl_render(Render_Target *t){
t->free_texture_first = 0; t->free_texture_first = 0;
t->free_texture_last = 0; t->free_texture_last = 0;
u32 all_vertex_count = 0;
u64 begin_draw = system_now_time(); u64 begin_draw = system_now_time();
for (Render_Group *group = t->group_first; for (Render_Group *group = t->group_first;
group != 0; group != 0;
@ -342,18 +340,9 @@ gl_render(Render_Target *t){
glDisableVertexAttribArray(gpu_program.vertex_c); glDisableVertexAttribArray(gpu_program.vertex_c);
glDisableVertexAttribArray(gpu_program.vertex_ht); glDisableVertexAttribArray(gpu_program.vertex_ht);
} }
all_vertex_count += vertex_count;
} }
u64 end_draw = system_now_time();
printf("Draw time: %fs\n", mac_get_time_diff_sec(begin_draw, end_draw));
u64 begin_flush = system_now_time();
glFlush(); glFlush();
u64 end_flush = system_now_time();
printf("Flush time: %fs\n", mac_get_time_diff_sec(begin_flush, end_flush));
printf("Drawn %d Vertices\n", all_vertex_count);
} }
// BOTTOM // BOTTOM

View File

@ -132,8 +132,6 @@ struct Mac_Input_Chunk{
//////////////////////////////// ////////////////////////////////
////////////////////////////////
typedef i32 Mac_Object_Kind; typedef i32 Mac_Object_Kind;
enum{ enum{
MacObjectKind_ERROR = 0, MacObjectKind_ERROR = 0,
@ -203,7 +201,12 @@ struct Mac_Vars {
//////////////////////////////// ////////////////////////////////
#include "mac_4ed_renderer.h"
////////////////////////////////
global Mac_Vars mac_vars; global Mac_Vars mac_vars;
global Mac_Renderer *renderer;
global Render_Target target; global Render_Target target;
global App_Functions app; global App_Functions app;
@ -269,30 +272,6 @@ mac_to_object(Plat_Handle handle){
//////////////////////////////// ////////////////////////////////
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#import "mac_4ed_opengl.mm"
#import "mac_4ed_metal.mm"
#include "4ed_font_provider_freetype.h"
#include "4ed_font_provider_freetype.cpp"
#import "mac_4ed_functions.mm"
////////////////////////////////
global Key_Code keycode_lookup_table[255];
function void
mac_key_code_init(void){
}
////////////////////////////////
function void function void
mac_error_box(char *msg, b32 shutdown = true){ mac_error_box(char *msg, b32 shutdown = true){
NSAlert *alert = [[[NSAlert alloc] init] autorelease]; NSAlert *alert = [[[NSAlert alloc] init] autorelease];
@ -309,6 +288,26 @@ mac_error_box(char *msg, b32 shutdown = true){
} }
} }
////////////////////////////////
#import "mac_4ed_renderer.mm"
#include "4ed_font_provider_freetype.h"
#include "4ed_font_provider_freetype.cpp"
#import "mac_4ed_functions.mm"
////////////////////////////////
global Key_Code keycode_lookup_table[255];
function void
mac_key_code_init(void){
}
////////////////////////////////
function b32 function b32
mac_file_can_be_made(u8* filename){ mac_file_can_be_made(u8* filename){
b32 result = access((char*)filename, W_OK) == 0; b32 result = access((char*)filename, W_OK) == 0;
@ -389,7 +388,7 @@ mac_resize(NSWindow *window){
} }
- (void)viewDidChangeBackingProperties{ - (void)viewDidChangeBackingProperties{
// NOTE(yuval): Screen scale factor calculation // TODO(yuval): Screen scale factor calculation
printf("Backing changed!\n"); printf("Backing changed!\n");
mac_resize(mac_vars.window); mac_resize(mac_vars.window);
} }
@ -449,7 +448,8 @@ this only gets called for window creation and other extraordinary events.
} }
//mac_gl_render(&target); //mac_gl_render(&target);
mac_metal_render(&target); //mac_metal_render(&target);
renderer->render(renderer, &target);
mac_vars.first = false; mac_vars.first = false;
@ -707,8 +707,9 @@ main(int arg_count, char **args){
[mac_vars.window makeKeyAndOrderFront:nil]; [mac_vars.window makeKeyAndOrderFront:nil];
// NOTE(yuval): Initialize the renderer // NOTE(yuval): Initialize the renderer
mac_gl_init(mac_vars.window); //mac_gl_init(mac_vars.window);
mac_metal_init(mac_vars.window); //mac_metal_init(mac_vars.window, &target);
renderer = mac_init_renderer(MacRenderer_OpenGL, mac_vars.window, &target);
mac_resize(w, h); mac_resize(w, h);

View File

@ -804,13 +804,13 @@ system_get_keyboard_modifiers_sig(){
function function
graphics_get_texture_sig(){ graphics_get_texture_sig(){
u32 result = mac_metal_get_texture(dim, texture_kind); u32 result = renderer->get_texture(renderer, dim, texture_kind);
return(result); return(result);
} }
function function
graphics_fill_texture_sig(){ graphics_fill_texture_sig(){
b32 result = mac_metal_fill_texture(texture_kind, texture, p, dim, data); b32 result = renderer->fill_texture(renderer, texture_kind, texture, p, dim, data);
return(result); return(result);
} }

View File

@ -4,7 +4,7 @@ global Metal_Renderer *metal_renderer;
global MTKView *metal_view; global MTKView *metal_view;
function void function void
mac_metal_init(NSWindow *window){ mac_metal_init(NSWindow *window, Render_Target *target){
// NOTE(yuval): Create Metal view // NOTE(yuval): Create Metal view
NSView *content_view = [window contentView]; NSView *content_view = [window contentView];
@ -26,11 +26,8 @@ mac_metal_init(NSWindow *window){
function void function void
mac_metal_render(Render_Target* target){ mac_metal_render(Render_Target* target){
u64 begin_time = system_now_time();
metal_renderer.target = target; metal_renderer.target = target;
[metal_view draw]; [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 function u32

View File

@ -1,24 +1,38 @@
/* Mac OpenGL layer for 4coder */ /* Mac OpenGL layer for 4coder */
#include "mac_4ed_renderer.h"
////////////////////////////////
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include "opengl/4ed_opengl_defines.h" #include "opengl/4ed_opengl_defines.h"
#define GL_FUNC(N,R,P) typedef R (CALL_CONVENTION N##_Function)P; N##_Function *N = 0; #define GL_FUNC(N,R,P) typedef R (CALL_CONVENTION N##_Function)P; N##_Function *N = 0;
#include "mac_4ed_opengl_funcs.h" #include "mac_4ed_opengl_funcs.h"
f64 mac_get_time_diff_sec(u64 begin, u64 end){ ////////////////////////////////
f64 result = ((end - begin) / 1000000.0);
return result;
}
#include "opengl/4ed_opengl_render.cpp" #include "opengl/4ed_opengl_render.cpp"
@interface OpenGLView : NSOpenGLView ////////////////////////////////
- (void)initGL;
@interface OpenGL_View : NSOpenGLView
- (void)init_gl;
- (void)render:(Render_Target*)target; - (void)render:(Render_Target*)target;
@end @end
@implementation OpenGLView{ ////////////////////////////////
b32 glIsInitialized;
struct Mac_OpenGL_Renderer{
Mac_Renderer base;
OpenGL_View *opengl_view;
};
////////////////////////////////
@implementation OpenGL_View{
b32 gl_is_initialized;
} }
- (id)init{ - (id)init{
@ -27,8 +41,8 @@ f64 mac_get_time_diff_sec(u64 begin, u64 end){
return nil; return nil;
} }
glIsInitialized = false; gl_is_initialized = false;
[self initGL]; [self init_gl];
return self; return self;
} }
@ -43,13 +57,13 @@ f64 mac_get_time_diff_sec(u64 begin, u64 end){
[[self openGLContext] makeCurrentContext]; [[self openGLContext] makeCurrentContext];
// NOTE(yuval): Setup vsync // NOTE(yuval): Setup vsync
GLint swapInt = 1; GLint swap_int = 1;
printf("Using vsync: %d\n", swapInt); printf("Using vsync: %d\n", swap_int);
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; [[self openGLContext] setValues:&swap_int forParameter:NSOpenGLCPSwapInterval];
} }
- (void)awakeFromNib{ - (void)awakeFromNib{
[self initGL]; [self init_gl];
} }
- (void)reshape{ - (void)reshape{
@ -59,8 +73,8 @@ f64 mac_get_time_diff_sec(u64 begin, u64 end){
[[self openGLContext] update]; [[self openGLContext] update];
} }
- (void)initGL{ - (void)init_gl{
if (glIsInitialized){ if (gl_is_initialized){
return; return;
} }
@ -92,65 +106,78 @@ f64 mac_get_time_diff_sec(u64 begin, u64 end){
[pixel_format release]; [pixel_format release];
glIsInitialized = true; gl_is_initialized = true;
} }
- (void)render:(Render_Target*)target{ - (void)render:(Render_Target*)target{
Assert(glIsInitialized); Assert(gl_is_initialized);
u64 context_lock_begin = system_now_time();
CGLLockContext([[self openGLContext] CGLContextObj]); CGLLockContext([[self openGLContext] CGLContextObj]);
u64 context_lock_end = system_now_time();
printf("Context lock time: %fs\n", mac_get_time_diff_sec(context_lock_begin, context_lock_end));
u64 make_current_context_begin = system_now_time();
[[self openGLContext] makeCurrentContext]; [[self openGLContext] makeCurrentContext];
u64 make_current_context_end = system_now_time();
printf("Make current context time: %fs\n", mac_get_time_diff_sec(make_current_context_begin, make_current_context_end));
u64 gl_render_begin = system_now_time();
gl_render(target); gl_render(target);
u64 gl_render_end = system_now_time();
printf("GL render time: %fs\n", mac_get_time_diff_sec(gl_render_begin, gl_render_end));
u64 gl_flush_buffer_begin = system_now_time();
[[self openGLContext] flushBuffer]; [[self openGLContext] flushBuffer];
u64 gl_flush_buffer_end = system_now_time();
printf("GL flush buffer time: %fs\n", mac_get_time_diff_sec(gl_flush_buffer_begin, gl_flush_buffer_end));
u64 context_unlock_begin = system_now_time();
CGLUnlockContext([[self openGLContext] CGLContextObj]); CGLUnlockContext([[self openGLContext] CGLContextObj]);
u64 context_unlock_end = system_now_time();
printf("Context unlock time: %fs\n", mac_get_time_diff_sec(context_unlock_begin, context_unlock_end));
} }
@end @end
global OpenGLView *opengl_view; ////////////////////////////////
function void function
mac_gl_init(NSWindow *window){ mac_render_sig(mac_gl_render){
// NOTE(yuval): Create OpenGLView printf("Rendering using OpenGL!\n");
Mac_OpenGL_Renderer *gl = (Mac_OpenGL_Renderer*)renderer;
[gl->opengl_view render:target];
}
function
mac_get_texture_sig(mac_gl_get_texture){
u32 result = gl__get_texture(dim, texture_kind);
return(result);
}
function
mac_fill_texture_sig(mac_gl_fill_texture){
b32 result = gl__fill_texture(texture_kind, texture, p, dim, data);
return(result);
}
function Mac_OpenGL_Renderer*
mac_gl__init(NSWindow *window, Render_Target *target){
// NOTE(yuval): Create the Mac Renderer
Mac_OpenGL_Renderer *gl = (Mac_OpenGL_Renderer*)system_memory_allocate(sizeof(Mac_OpenGL_Renderer),
file_name_line_number_lit_u8);
gl->base.render = mac_gl_render;
gl->base.get_texture = mac_gl_get_texture;
gl->base.fill_texture = mac_gl_fill_texture;
// NOTE(yuval): Create the OpenGL view
NSView *content_view = [window contentView]; NSView *content_view = [window contentView];
opengl_view = [[OpenGLView alloc] init]; gl->opengl_view = [[OpenGL_View alloc] init];
[opengl_view setFrame:[content_view bounds]]; [gl->opengl_view setFrame:[content_view bounds]];
[opengl_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [gl->opengl_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[opengl_view setWantsBestResolutionOpenGLSurface:YES]; [gl->opengl_view setWantsBestResolutionOpenGLSurface:YES];
// NOTE(yuval): Add the OpenGL view as a subview of the window // NOTE(yuval): Add the OpenGL view as a subview of the window
[content_view addSubview:opengl_view]; [content_view addSubview:gl->opengl_view];
// NOTE(yuval): Load gl functions // NOTE(yuval): Load gl functions
void *gl_image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); void *gl_image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
#define GL_FUNC(f,R,P) ((f) = (f##_Function*)dlsym(gl_image, #f)); #define GL_FUNC(f,R,P) ((f) = (f##_Function*)dlsym(gl_image, #f));
#include "mac_4ed_opengl_funcs.h" #include "mac_4ed_opengl_funcs.h"
return(gl);
} }
function void // TODO(yuval): This function should be exported to a DLL
mac_gl_render(Render_Target* target){ function
u64 begin_time = system_now_time(); mac_load_renderer_sig(mac_load_opengl_renderer){
[opengl_view render:target]; printf("Initializing The OpenGL Renderer!\n");
u64 end_time = system_now_time();
printf("Render Time: %fs\n\n", mac_get_time_diff_sec(begin_time, end_time)); Mac_Renderer *renderer = (Mac_Renderer*)mac_gl__init(window, target);
return(renderer);
} }

View File

@ -0,0 +1,42 @@
/* Mac Renderer Abstraction */
#if !defined(FRED_MAC_RENDERER_H)
#define FRED_MAC_RENDERER_H
////////////////////////////////
// TODO(yuval): This should be refactored into a platform independent renderer
struct Mac_Renderer;
#define mac_render_sig(name) void name(Mac_Renderer *renderer, Render_Target *target)
typedef mac_render_sig(mac_render_type);
#define mac_get_texture_sig(name) u32 name(Mac_Renderer *renderer, Vec3_i32 dim, Texture_Kind texture_kind)
typedef mac_get_texture_sig(mac_get_texture_type);
#define mac_fill_texture_sig(name) b32 name(Mac_Renderer *renderer, Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 dim, void* data)
typedef mac_fill_texture_sig(mac_fill_texture_type);
typedef i32 Mac_Renderer_Kind;
enum{
MacRenderer_OpenGL,
MacRenderer_Metal
};
struct Mac_Renderer{
mac_render_type *render;
mac_get_texture_type *get_texture;
mac_fill_texture_type *fill_texture;
};
////////////////////////////////
// NOTE(yuval): This is the actual platform dependent function that each renderer implementation implements and should be exported into a DLL
#define mac_load_renderer_sig(name) Mac_Renderer* name(NSWindow *window, Render_Target *target)
typedef mac_load_renderer_sig(mac_load_renderer_type);
////////////////////////////////
#endif

View File

@ -0,0 +1,33 @@
/* Mac Renderer Abstraction Implementation */
// TODO(yuval): This should NOT be included here once the renderer is exported to a DLL
#import "mac_4ed_opengl.mm"
#import "mac_4ed_metal.mm"
function Mac_Renderer*
mac_init_renderer(Mac_Renderer_Kind kind, NSWindow *window, Render_Target *target){
// TODO(yuval): Import renderer load function from a DLL instead of using a switch statement and a renderer kind. This would allow us to switch the renderer backend and implemented new backends with ease.
Mac_Renderer *result = 0;
switch (kind){
case MacRenderer_OpenGL:
{
result = mac_load_opengl_renderer(window, target);
} break;
case MacRenderer_Metal:
{
//result = mac_load_metal_renderer(window, target);
} break;
default: InvalidPath;
}
if (!result){
mac_error_box("Unable to initialize the renderer!");
}
return result;
}