From f485331c5b6fb5ab3493ef7c2c7ae787d56f7cb9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 11 Dec 2020 21:23:58 -0500 Subject: [PATCH] mesa: merge local and env program parameters for faster uploads MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This reduces CPU overhead for applications using ARB programs. We can simply memcpy all local and env parameters into a constant buffer if there are no holes. Reviewed-by: Zoltán Böszörményi Part-of: --- src/mesa/program/prog_statevars.c | 101 ++++++++++++++++++++++++++++++++++++++ src/mesa/program/prog_statevars.h | 4 ++ 2 files changed, 105 insertions(+) diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c index 9094ce1..3d0f14d 100644 --- a/src/mesa/program/prog_statevars.c +++ b/src/mesa/program/prog_statevars.c @@ -381,6 +381,12 @@ fetch_state(struct gl_context *ctx, const gl_state_index16 state[], COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); return; } + case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: { + const unsigned idx = state[1]; + const unsigned bytes = state[2] * 16; + memcpy(value, ctx->FragmentProgram.Parameters[idx], bytes); + return; + } case STATE_FRAGMENT_PROGRAM_LOCAL: { float (*params)[4] = ctx->FragmentProgram.Current->arb.LocalParams; if (unlikely(!params)) { @@ -396,11 +402,32 @@ fetch_state(struct gl_context *ctx, const gl_state_index16 state[], COPY_4V(value, params[idx]); return; } + case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: { + const unsigned idx = state[1]; + const unsigned bytes = state[2] * 16; + float (*params)[4] = ctx->FragmentProgram.Current->arb.LocalParams; + if (!params) { + /* Local parameters haven't been allocated yet. + * ARB_fragment_program says that local parameters are + * "initially set to (0,0,0,0)." Return that. + */ + memset(value, 0, bytes); + return; + } + memcpy(value, params[idx], bytes); + return; + } case STATE_VERTEX_PROGRAM_ENV: { const int idx = (int) state[1]; COPY_4V(value, ctx->VertexProgram.Parameters[idx]); return; } + case STATE_VERTEX_PROGRAM_ENV_ARRAY: { + const unsigned idx = state[1]; + const unsigned bytes = state[2] * 16; + memcpy(value, ctx->VertexProgram.Parameters[idx], bytes); + return; + } case STATE_VERTEX_PROGRAM_LOCAL: { float (*params)[4] = ctx->VertexProgram.Current->arb.LocalParams; if (unlikely(!params)) { @@ -416,6 +443,21 @@ fetch_state(struct gl_context *ctx, const gl_state_index16 state[], COPY_4V(value, params[idx]); return; } + case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: { + const unsigned idx = state[1]; + const unsigned bytes = state[2] * 16; + float (*params)[4] = ctx->VertexProgram.Current->arb.LocalParams; + if (!params) { + /* Local parameters haven't been allocated yet. + * ARB_vertex_program says that local parameters are + * "initially set to (0,0,0,0)." Return that. + */ + memset(value, 0, bytes); + return; + } + memcpy(value, params[idx], bytes); + return; + } case STATE_NORMAL_SCALE_EYESPACE: ASSIGN_4V(value, ctx->_ModelViewInvScaleEyespace, 0, 0, 1); @@ -722,9 +764,13 @@ _mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH]) return _NEW_VIEWPORT; case STATE_FRAGMENT_PROGRAM_ENV: + case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: case STATE_FRAGMENT_PROGRAM_LOCAL: + case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: case STATE_VERTEX_PROGRAM_ENV: + case STATE_VERTEX_PROGRAM_ENV_ARRAY: case STATE_VERTEX_PROGRAM_LOCAL: + case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: return _NEW_PROGRAM; case STATE_NORMAL_SCALE_EYESPACE: @@ -962,10 +1008,18 @@ append_token(char *dst, gl_state_index k) case STATE_FRAGMENT_PROGRAM_ENV: append(dst, "env"); break; + case STATE_VERTEX_PROGRAM_ENV_ARRAY: + case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: + append(dst, "env.range"); + break; case STATE_VERTEX_PROGRAM_LOCAL: case STATE_FRAGMENT_PROGRAM_LOCAL: append(dst, "local"); break; + case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: + case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: + append(dst, "local.range"); + break; case STATE_CURRENT_ATTRIB: append(dst, "current"); break; @@ -1145,6 +1199,13 @@ _mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH]) /* state[1] = parameter index */ append_index(str, state[1], false); break; + case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: + case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: + case STATE_VERTEX_PROGRAM_ENV_ARRAY: + case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: + sprintf(tmp, "[%d..%d]", state[1], state[1] + state[2] - 1); + append(str, tmp); + break; case STATE_NORMAL_SCALE_EYESPACE: break; case STATE_CURRENT_ATTRIB: @@ -1339,6 +1400,46 @@ _mesa_optimize_state_parameters(struct gl_constants *consts, param_diff = last_param - first_param; } break; + + case STATE_VERTEX_PROGRAM_ENV: + case STATE_VERTEX_PROGRAM_LOCAL: + case STATE_FRAGMENT_PROGRAM_ENV: + case STATE_FRAGMENT_PROGRAM_LOCAL: + if (list->Parameters[first_param].Size != 4) + break; + + /* Search for adjacent mergeable state vars. */ + for (int i = first_param + 1; i < (int)list->NumParameters; i++) { + if (list->Parameters[i].StateIndexes[0] == + list->Parameters[i - 1].StateIndexes[0] && + list->Parameters[i].StateIndexes[1] == + list->Parameters[i - 1].StateIndexes[1] + 1 && + list->Parameters[i].Size == 4) { + last_param = i; + continue; + } + break; /* The adjacent state var is incompatible. */ + } + if (last_param > first_param) { + /* Set STATE_xxx_RANGE. */ + STATIC_ASSERT(STATE_VERTEX_PROGRAM_ENV + 1 == + STATE_VERTEX_PROGRAM_ENV_ARRAY); + STATIC_ASSERT(STATE_VERTEX_PROGRAM_LOCAL + 1 == + STATE_VERTEX_PROGRAM_LOCAL_ARRAY); + STATIC_ASSERT(STATE_FRAGMENT_PROGRAM_ENV + 1 == + STATE_FRAGMENT_PROGRAM_ENV_ARRAY); + STATIC_ASSERT(STATE_FRAGMENT_PROGRAM_LOCAL + 1 == + STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY); + list->Parameters[first_param].StateIndexes[0]++; + + param_diff = last_param - first_param; + + /* Set the size. */ + unsigned size = param_diff + 1; + list->Parameters[first_param].StateIndexes[2] = size; + list->Parameters[first_param].Size = size * 4; + } + break; } if (param_diff) { diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h index f7a9d0c..43e7516 100644 --- a/src/mesa/program/prog_statevars.h +++ b/src/mesa/program/prog_statevars.h @@ -130,9 +130,13 @@ typedef enum gl_state_index_ { STATE_DEPTH_RANGE, STATE_VERTEX_PROGRAM_ENV, + STATE_VERTEX_PROGRAM_ENV_ARRAY, STATE_VERTEX_PROGRAM_LOCAL, + STATE_VERTEX_PROGRAM_LOCAL_ARRAY, STATE_FRAGMENT_PROGRAM_ENV, + STATE_FRAGMENT_PROGRAM_ENV_ARRAY, STATE_FRAGMENT_PROGRAM_LOCAL, + STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY, STATE_CURRENT_ATTRIB, /* ctx->Current vertex attrib value */ STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED, /* ctx->Current vertex attrib value after passthrough vertex processing */ -- 2.7.4