From a758973ac13a2544cdc58eb5f2cfe3fbd14842e5 Mon Sep 17 00:00:00 2001 From: Stanislav Vorobiov Date: Thu, 13 Sep 2012 11:03:08 +0400 Subject: [PATCH] YaGL: Moved batch processing to the GL thread This gave a significant performance improvement. --- hw/yagl_api.h | 2 - hw/yagl_apis/egl/yagl_host_egl_calls.c | 7 -- hw/yagl_apis/gles2/yagl_host_gles2_calls.c | 5 -- hw/yagl_device.c | 45 ++--------- hw/yagl_marshal.h | 5 ++ hw/yagl_server.c | 69 +++-------------- hw/yagl_server.h | 13 ++-- hw/yagl_thread.c | 120 +++++++++++++++++++++-------- hw/yagl_thread.h | 15 +--- 9 files changed, 115 insertions(+), 166 deletions(-) diff --git a/hw/yagl_api.h b/hw/yagl_api.h index 6da67e4..c44b22e 100644 --- a/hw/yagl_api.h +++ b/hw/yagl_api.h @@ -23,8 +23,6 @@ struct yagl_api_ps yagl_api_func (*get_func)(struct yagl_api_ps */*api_ps*/, uint32_t /*func_id*/); - void (*bad_call)(void); - void (*thread_fini)(struct yagl_api_ps */*api_ps*/); void (*fini)(struct yagl_api_ps */*api_ps*/); diff --git a/hw/yagl_apis/egl/yagl_host_egl_calls.c b/hw/yagl_apis/egl/yagl_host_egl_calls.c index 9dbefed..8b5b96f 100644 --- a/hw/yagl_apis/egl/yagl_host_egl_calls.c +++ b/hw/yagl_apis/egl/yagl_host_egl_calls.c @@ -179,12 +179,6 @@ static bool yagl_egl_release_current_context(struct yagl_egl_display *dpy) return true; } -static void yagl_host_egl_bad_call(void) -{ - YAGL_LOG_FUNC_SET_TS(egl_api_ts->ts, yagl_host_egl_bad_call); - YAGL_SET_ERR(EGL_BAD_PARAMETER); -} - static yagl_api_func yagl_host_egl_get_func(struct yagl_api_ps *api_ps, uint32_t func_id) { @@ -287,7 +281,6 @@ struct yagl_api_ps egl_api_ps->base.thread_init = &yagl_host_egl_thread_init; egl_api_ps->base.get_func = &yagl_host_egl_get_func; - egl_api_ps->base.bad_call = &yagl_host_egl_bad_call; egl_api_ps->base.thread_fini = &yagl_host_egl_thread_fini; egl_api_ps->base.fini = &yagl_host_egl_process_fini; egl_api_ps->base.destroy = &yagl_host_egl_process_destroy; diff --git a/hw/yagl_apis/gles2/yagl_host_gles2_calls.c b/hw/yagl_apis/gles2/yagl_host_gles2_calls.c index b6a6864..54dee74 100644 --- a/hw/yagl_apis/gles2/yagl_host_gles2_calls.c +++ b/hw/yagl_apis/gles2/yagl_host_gles2_calls.c @@ -61,10 +61,6 @@ static struct yagl_client_context return &ctx->base.base; } -static void yagl_host_gles2_bad_call(void) -{ -} - static yagl_api_func yagl_host_gles2_get_func(struct yagl_api_ps *api_ps, uint32_t func_id) { @@ -167,7 +163,6 @@ struct yagl_api_ps gles2_api_ps->base.thread_init = &yagl_host_gles2_thread_init; gles2_api_ps->base.get_func = &yagl_host_gles2_get_func; - gles2_api_ps->base.bad_call = &yagl_host_gles2_bad_call; gles2_api_ps->base.thread_fini = &yagl_host_gles2_thread_fini; gles2_api_ps->base.fini = &yagl_host_gles2_process_fini; gles2_api_ps->base.destroy = &yagl_host_gles2_process_destroy; diff --git a/hw/yagl_device.c b/hw/yagl_device.c index 66ffa25..e46fee6 100644 --- a/hw/yagl_device.c +++ b/hw/yagl_device.c @@ -16,8 +16,6 @@ #define YAGL_MEM_SIZE 0x1000 -#define YAGL_BUFF_SIZE 0x1000 - #define YAGL_MAX_USERS (YAGL_MEM_SIZE / YAGL_REGS_SIZE) struct yagl_user @@ -151,7 +149,6 @@ static void yagl_device_trigger(YaGLState *s, int user_index) { target_phys_addr_t buff_len = YAGL_BUFF_SIZE; uint8_t *buff = NULL; - uint8_t *current_buff; YAGL_LOG_FUNC_ENTER_NPT(yagl_device_trigger, "%d", user_index); @@ -171,43 +168,11 @@ static void yagl_device_trigger(YaGLState *s, int user_index) goto out; } - current_buff = buff; - - while (true) { - uint8_t *tmp; - - if (current_buff >= (buff + YAGL_BUFF_SIZE)) { - YAGL_LOG_CRITICAL("batch passes the end of buffer, protocol error"); - - memset(s->in_buff, 0, YAGL_MARSHAL_MAX_RESPONSE); - - break; - } - - current_buff = yagl_server_dispatch(s->ss, - s->users[user_index].process_id, - s->users[user_index].thread_id, - current_buff, - s->in_buff); - - if (!current_buff) { - /* - * Error occured. - */ - - break; - } - - tmp = current_buff; - - /* - * Take a peak to see if there's a batch terminator. - */ - - if (!yagl_marshal_get_uint32(&tmp)) { - break; - } - } + yagl_server_dispatch(s->ss, + s->users[user_index].process_id, + s->users[user_index].thread_id, + buff, + s->in_buff); memcpy(buff, s->in_buff, YAGL_MARSHAL_MAX_RESPONSE); diff --git a/hw/yagl_marshal.h b/hw/yagl_marshal.h index 1fe1a2f..eb41f73 100644 --- a/hw/yagl_marshal.h +++ b/hw/yagl_marshal.h @@ -19,6 +19,11 @@ */ #define YAGL_MARSHAL_MAX_RESPONSE (8 * 2) +/* + * Max batch buffer size. + */ +#define YAGL_BUFF_SIZE 0x1000 + static __inline int yagl_marshal_skip(uint8_t** buff) { *buff += 8; diff --git a/hw/yagl_server.c b/hw/yagl_server.c index 96c4207..0b9ab5f 100644 --- a/hw/yagl_server.c +++ b/hw/yagl_server.c @@ -226,83 +226,32 @@ bool yagl_server_dispatch_init(struct yagl_server_state *ss, } } -/* - * out_buff is: - * (yagl_api_id) api_id - * (yagl_func_id) func_id - * ... api_id/func_id dependent - * in_buff must be: - * (uint32_t) 1/0 - call ok/failed - * ... api_id/func_id dependent - */ -uint8_t *yagl_server_dispatch(struct yagl_server_state *ss, - yagl_pid target_pid, - yagl_tid target_tid, - uint8_t *out_buff, - uint8_t *in_buff) +void yagl_server_dispatch(struct yagl_server_state *ss, + yagl_pid target_pid, + yagl_tid target_tid, + uint8_t *out_buff, + uint8_t *in_buff) { - yagl_api_id api_id = yagl_marshal_get_api_id(&out_buff); - yagl_func_id func_id = yagl_marshal_get_func_id(&out_buff); - struct yagl_api* api; struct yagl_thread_state *ts; - uint8_t *in_buff_ret; YAGL_LOG_FUNC_ENTER(target_pid, target_tid, yagl_server_dispatch, - "api_id = %u, func_id = %u", - api_id, - func_id); + NULL); ts = yagl_server_find_thread(ss, target_pid, target_tid); - if (!ts) { + if (ts) { + yagl_thread_call(ts, out_buff, in_buff); + } else { YAGL_LOG_CRITICAL( "process/thread %u/%u not found", target_pid, target_tid); yagl_marshal_put_uint32(&in_buff, 0); - - YAGL_LOG_FUNC_EXIT(NULL); - - return NULL; } - if ((api_id <= 0) || (api_id > YAGL_NUM_APIS)) { - YAGL_LOG_CRITICAL( - "target-host protocol error, bad api_id - %u", api_id); - - yagl_marshal_put_uint32(&in_buff, 0); - - YAGL_LOG_FUNC_EXIT(NULL); - - return NULL; - } - - api = ss->apis[api_id - 1]; - - if (!api) { - YAGL_LOG_CRITICAL( - "uninitialized api - %u. host logic error", api_id); - - yagl_marshal_put_uint32(&in_buff, 0); - - YAGL_LOG_FUNC_EXIT(NULL); - - return NULL; - } - - in_buff_ret = in_buff; - - yagl_marshal_skip(&in_buff); - - out_buff = yagl_thread_call(ts, api_id, func_id, out_buff, in_buff); - - yagl_marshal_put_uint32(&in_buff_ret, (out_buff ? 1 : 0)); - YAGL_LOG_FUNC_EXIT(NULL); - - return out_buff; } void yagl_server_dispatch_exit(struct yagl_server_state *ss, diff --git a/hw/yagl_server.h b/hw/yagl_server.h index 429a35d..3fc11d4 100644 --- a/hw/yagl_server.h +++ b/hw/yagl_server.h @@ -41,14 +41,13 @@ bool yagl_server_dispatch_init(struct yagl_server_state *ss, uint8_t *in_buff); /* - * This is called for each host YaGL call. Returns new - * position of 'out_buff' on success and NULL on failure. + * This is called for each YaGL batch. */ -uint8_t *yagl_server_dispatch(struct yagl_server_state *ss, - yagl_pid target_pid, - yagl_tid target_tid, - uint8_t *out_buff, - uint8_t *in_buff); +void yagl_server_dispatch(struct yagl_server_state *ss, + yagl_pid target_pid, + yagl_tid target_tid, + uint8_t *out_buff, + uint8_t *in_buff); /* * This is called for last YaGL call. diff --git a/hw/yagl_thread.c b/hw/yagl_thread.c index d98bd19..2458474 100644 --- a/hw/yagl_thread.c +++ b/hw/yagl_thread.c @@ -38,8 +38,9 @@ static void *yagl_thread_func(void* arg) } while (true) { - struct yagl_api_ps *api_ps; - yagl_api_func func; + bool ret = true; + uint8_t *current_buff; + uint8_t *tmp; yagl_event_wait(&ts->call_event); @@ -47,24 +48,91 @@ static void *yagl_thread_func(void* arg) break; } - YAGL_LOG_TRACE("calling (api = %u, func = %u)", - ts->current_api, - ts->current_func); + current_buff = ts->current_out_buff; - api_ps = ts->ps->api_states[ts->current_api - 1]; - assert(api_ps); + /* + * current_buff is: + * (yagl_api_id) api_id + * (yagl_func_id) func_id + * ... api_id/func_id dependent + * current_in_buff must be: + * (uint32_t) 1/0 - call ok/failed + * ... api_id/func_id dependent + */ - func = api_ps->get_func(api_ps, ts->current_func); + while (true) { + yagl_api_id api_id; + yagl_func_id func_id; + struct yagl_api_ps *api_ps; + yagl_api_func func; - if (!func) { - api_ps->bad_call(); - ts->current_out_buff = NULL; - } else { - ts->current_out_buff = func(ts, - ts->current_out_buff, - ts->current_in_buff); + if (current_buff >= (ts->current_out_buff + YAGL_BUFF_SIZE)) { + YAGL_LOG_CRITICAL("batch passes the end of buffer, protocol error"); + + ret = false; + + break; + } + + api_id = yagl_marshal_get_api_id(¤t_buff); + + if (api_id == 0) { + /* + * Batch ended. + */ + + break; + } + + func_id = yagl_marshal_get_func_id(¤t_buff); + + YAGL_LOG_TRACE("calling (api = %u, func = %u)", + api_id, + func_id); + + if ((api_id <= 0) || (api_id > YAGL_NUM_APIS)) { + YAGL_LOG_CRITICAL("target-host protocol error, bad api_id - %u", api_id); + + ret = false; + + break; + } + + api_ps = ts->ps->api_states[api_id - 1]; + + if (!api_ps) { + YAGL_LOG_CRITICAL("uninitialized api - %u. host logic error", api_id); + + ret = false; + + break; + } + + func = api_ps->get_func(api_ps, func_id); + + if (func) { + tmp = ts->current_in_buff; + + yagl_marshal_skip(&tmp); + + current_buff = func(ts, + current_buff, + tmp); + } else { + YAGL_LOG_CRITICAL("bad function call (api = %u, func = %u)", + api_id, + func_id); + + ret = false; + + break; + } } + tmp = ts->current_in_buff; + + yagl_marshal_put_uint32(&tmp, (ret ? 1 : 0)); + yagl_event_set(&ts->call_processed_event); } @@ -116,36 +184,22 @@ void yagl_thread_state_destroy(struct yagl_thread_state *ts) g_free(ts); } -uint8_t *yagl_thread_call(struct yagl_thread_state *ts, - yagl_api_id api_id, - yagl_func_id func_id, - uint8_t *out_buff, - uint8_t *in_buff) +void yagl_thread_call(struct yagl_thread_state *ts, + uint8_t *out_buff, + uint8_t *in_buff) { - YAGL_LOG_FUNC_ENTER_TS(ts, - yagl_thread_call, - "api = %u, func = %u", - api_id, - func_id); + YAGL_LOG_FUNC_ENTER_TS(ts, yagl_thread_call, NULL); assert(cpu_single_env); - ts->current_api = api_id; - ts->current_func = func_id; ts->current_out_buff = out_buff; ts->current_in_buff = in_buff; ts->current_env = cpu_single_env; - YAGL_LOG_TRACE("calling (api = %u, func = %u)", - ts->current_api, - ts->current_func); - yagl_cpu_synchronize_state(ts->ps); yagl_event_set(&ts->call_event); yagl_event_wait(&ts->call_processed_event); YAGL_LOG_FUNC_EXIT(NULL); - - return ts->current_out_buff; } diff --git a/hw/yagl_thread.h b/hw/yagl_thread.h index 5ac218e..91b5fc2 100644 --- a/hw/yagl_thread.h +++ b/hw/yagl_thread.h @@ -30,10 +30,6 @@ struct yagl_thread_state * @} */ - volatile yagl_api_id current_api; - - volatile yagl_func_id current_func; - /* * Allocated by the caller of yagl_thread_call, * invalidated after function return. @@ -55,14 +51,9 @@ struct yagl_thread_state void yagl_thread_state_destroy(struct yagl_thread_state *ts); -/* - * Returns new position of 'out_buff' on success and NULL on failure. - */ -uint8_t *yagl_thread_call(struct yagl_thread_state *ts, - yagl_api_id api_id, - yagl_func_id func_id, - uint8_t *out_buff, - uint8_t *in_buff); +void yagl_thread_call(struct yagl_thread_state *ts, + uint8_t *out_buff, + uint8_t *in_buff); #define YAGL_BARRIER_ARG(ts) #define YAGL_BARRIER_RET(ts) 1 -- 2.7.4