Fixed a performance issue regarding timers. Now we can start a single timer per step request.

master
Yuval Dolev 2020-01-12 23:16:03 +02:00
parent 020e2789d7
commit dbcb05d2d1
5 changed files with 72 additions and 30 deletions

View File

@ -290,7 +290,7 @@ metal__make_buffer(u32 size, id<MTLDevice> device){
// NOTE(yuval): Obtain the render pass descriptor from the renderer's view // NOTE(yuval): Obtain the render pass descriptor from the renderer's view
MTLRenderPassDescriptor *render_pass_descriptor = view.currentRenderPassDescriptor; MTLRenderPassDescriptor *render_pass_descriptor = view.currentRenderPassDescriptor;
if (render_pass_descriptor != nil){ if (render_pass_descriptor != nil){
render_pass_descriptor.colorAttachments[0].clearColor = MTLClearColorMake(1.0f, 0.0f, 1.0f, 1.0f); render_pass_descriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f);
// NOTE(yuval): Create the render command encoder // NOTE(yuval): Create the render command encoder
id<MTLRenderCommandEncoder> render_encoder id<MTLRenderCommandEncoder> render_encoder

View File

@ -195,6 +195,7 @@ struct Mac_Vars {
mach_timebase_info_data_t timebase_info; mach_timebase_info_data_t timebase_info;
b32 first; b32 first;
b32 step_requested;
void *base_ptr; void *base_ptr;
u64 timer_start; u64 timer_start;
@ -459,15 +460,18 @@ mac_resize(NSWindow *window){
mac_resize(bounds.size.width, bounds.size.height); mac_resize(bounds.size.width, bounds.size.height);
} }
#if defined(FRED_INTERNAL)
function inline void function inline void
mac_profile(char *name, u64 begin, u64 end){ mac_profile(char *name, u64 begin, u64 end){
printf("%s Time: %fs\n", name, ((end - begin) / 1000000.0f)); printf("%s Time: %fs\n", name, ((end - begin) / 1000000.0f));
} }
#define MacProfileScope(name) for (u64 i = 0, begin = system_now_time();\ #define MacProfileScope(name) for (u64 i = 0, begin = system_now_time();\
i < 1;\ i == 0;\
++i, mac_profile(name, begin, system_now_time())) i = 1, mac_profile(name, begin, system_now_time()))
#else
# define MacProfileScope(...)
#endif
//////////////////////////////// ////////////////////////////////
@implementation FCoder_App_Delegate @implementation FCoder_App_Delegate
@ -539,8 +543,10 @@ i < 1;\
} }
- (void)drawRect:(NSRect)bounds{ - (void)drawRect:(NSRect)bounds{
MacProfileScope("Frame"){ u64 prev_timer_start;
MacProfileScope("Acquire System Mutex"){
MacProfileScope("Draw Rect"){
MacProfileScope("Acquire Frame Mutex"){
// NOTE(yuval): Read comment in win32_4ed.cpp's main loop // NOTE(yuval): Read comment in win32_4ed.cpp's main loop
system_mutex_acquire(mac_vars.global_frame_mutex); system_mutex_acquire(mac_vars.global_frame_mutex);
} }
@ -606,14 +612,44 @@ i < 1;\
} }
} }
// NOTE(yuval): Sleep a bit to cool off
MacProfileScope("Cool Down"){
system_mutex_release(mac_vars.global_frame_mutex);
{
u64 timer_end = system_now_time();
u64 end_target = (mac_vars.timer_start + frame_useconds);
if (timer_end < end_target){
if ((end_target - timer_end) > 1000){
// NOTE(yuval): Sleep until the end target minus a millisecond (to allow the scheduler to wake the process in time)
system_sleep(end_target - timer_end - 1000);
}
// NOTE(yuval): Iterate through the rest of the time that's left using a regular for loop to make sure that we hit the end target
u64 now = system_now_time();
while (now < end_target){
now = system_now_time();
}
}
prev_timer_start = mac_vars.timer_start;
mac_vars.timer_start = system_now_time();
}
system_mutex_acquire(mac_vars.global_frame_mutex);
}
MacProfileScope("Cleanup"){ MacProfileScope("Cleanup"){
mac_vars.first = false; mac_vars.first = false;
mac_vars.step_requested = false;
linalloc_clear(mac_vars.frame_arena); linalloc_clear(mac_vars.frame_arena);
// NOTE(yuval): Release the global frame mutex until the next drawRect call
system_mutex_release(mac_vars.global_frame_mutex); system_mutex_release(mac_vars.global_frame_mutex);
} }
} }
mac_profile("Frame", prev_timer_start, mac_vars.timer_start);
printf("\n"); printf("\n");
} }
@ -762,6 +798,7 @@ i < 1;\
} }
- (void)request_display{ - (void)request_display{
printf("Display Requested!\n");
CGRect cg_rect = CGRectMake(0, 0, mac_vars.width, mac_vars.height); CGRect cg_rect = CGRectMake(0, 0, mac_vars.width, mac_vars.height);
NSRect rect = NSRectFromCGRect(cg_rect); NSRect rect = NSRectFromCGRect(cg_rect);
[self setNeedsDisplayInRect:rect]; [self setNeedsDisplayInRect:rect];
@ -829,7 +866,9 @@ i < 1;\
- (void)process_mouse_move_event:(NSEvent*)event{ - (void)process_mouse_move_event:(NSEvent*)event{
NSPoint location = [event locationInWindow]; NSPoint location = [event locationInWindow];
Vec2_i32 new_m = V2i32(location.x, mac_vars.height - location.y); NSPoint backing_location = [self convertPointToBacking:location];
Vec2_i32 new_m = V2i32(backing_location.x, mac_vars.height - backing_location.y);
if (new_m != mac_vars.input_chunk.pers.mouse){ if (new_m != mac_vars.input_chunk.pers.mouse){
mac_vars.input_chunk.pers.mouse = new_m; mac_vars.input_chunk.pers.mouse = new_m;
} }
@ -854,7 +893,7 @@ main(int arg_count, char **args){
pthread_mutex_init(&memory_tracker_mutex, 0); pthread_mutex_init(&memory_tracker_mutex, 0);
// NOTE(yuval): Context Setup // NOTE(yuval): Context setup
Thread_Context _tctx = {}; Thread_Context _tctx = {};
thread_ctx_init(&_tctx, ThreadKind_Main, thread_ctx_init(&_tctx, ThreadKind_Main,
get_base_allocator_system(), get_base_allocator_system(),
@ -1048,9 +1087,11 @@ main(int arg_count, char **args){
mac_resize(w, h); mac_resize(w, h);
// //
// TODO(yuval): Misc System Initializations // NOTE(yuval): Misc System Initializations
// //
// TODO(yuval): Initialize clipboard buffer
mac_keycode_init(); mac_keycode_init();
// NOTE(yuval): Get the timebase info // NOTE(yuval): Get the timebase info
@ -1072,6 +1113,7 @@ main(int arg_count, char **args){
// //
mac_vars.first = true; mac_vars.first = true;
mac_vars.step_requested = false;
mac_vars.global_frame_mutex = system_mutex_make(); mac_vars.global_frame_mutex = system_mutex_make();

View File

@ -406,10 +406,15 @@ system_wake_up_timer_set_sig(){
function function
system_signal_step_sig(){ system_signal_step_sig(){
printf("Signal Step!\n");
if (!mac_vars.step_requested){
[NSTimer scheduledTimerWithTimeInterval:0.0 [NSTimer scheduledTimerWithTimeInterval:0.0
target:mac_vars.view target:mac_vars.view
selector:@selector(request_display) selector:@selector(request_display)
userInfo:nil repeats:NO]; userInfo:nil repeats:NO];
mac_vars.step_requested = true;
}
} }
function function

View File

@ -21,7 +21,9 @@ typedef mac_fill_texture_sig(mac_fill_texture_type);
typedef i32 Mac_Renderer_Kind; typedef i32 Mac_Renderer_Kind;
enum{ enum{
MacRenderer_OpenGL, MacRenderer_OpenGL,
MacRenderer_Metal MacRenderer_Metal,
//
MacRenderer_COUNT
}; };
struct Mac_Renderer{ struct Mac_Renderer{

View File

@ -4,25 +4,18 @@
#import "mac_4ed_opengl.mm" #import "mac_4ed_opengl.mm"
#import "mac_4ed_metal.mm" #import "mac_4ed_metal.mm"
// TODO(yuval): Replace this array with an array of the paths to the renderer dlls
global mac_load_renderer_type *mac_renderer_load_functions[MacRenderer_COUNT] = {
mac_load_opengl_renderer,
mac_load_metal_renderer
};
function Mac_Renderer* function Mac_Renderer*
mac_init_renderer(Mac_Renderer_Kind kind, NSWindow *window, Render_Target *target){ 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. // TODO(yuval): Import renderer load function from a DLL instead of using an array of the load functions. This would allow us to switch the renderer backend and implemented new backends with ease.
Mac_Renderer *result = 0; mac_load_renderer_type *load_renderer = mac_renderer_load_functions[kind];
Mac_Renderer *result = load_renderer(window, target);
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){ if (!result){
mac_error_box("Unable to initialize the renderer!"); mac_error_box("Unable to initialize the renderer!");