mesa: merge local and env program parameters for faster uploads

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 <zboszor@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8183>
This commit is contained in:
Marek Olšák 2020-12-11 21:23:58 -05:00 committed by Marge Bot
parent 293526a273
commit f485331c5b
2 changed files with 105 additions and 0 deletions

View File

@ -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) {

View File

@ -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 */