st/mesa: add a faster path for uploading state parameters into constant buffers
The old path copies state parameters into the parameter list, and then the driver copies them into a buffer. The optional new path loads state parameters into a buffer directly. This increases performance by 5% in one subtest of viewperf. Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6946>
This commit is contained in:
@@ -94,21 +94,8 @@ st_upload_constants(struct st_context *st, struct gl_program *prog)
|
||||
struct pipe_constant_buffer cb;
|
||||
const uint paramBytes = params->NumParameterValues * sizeof(GLfloat);
|
||||
|
||||
/* Update the constants which come from fixed-function state, such as
|
||||
* transformation matrices, fog factors, etc. The rest of the values in
|
||||
* the parameters list are explicitly set by the user with glUniform,
|
||||
* glProgramParameter(), etc.
|
||||
*/
|
||||
if (params->StateFlags)
|
||||
_mesa_load_state_parameters(st->ctx, params);
|
||||
|
||||
_mesa_shader_write_subroutine_indices(st->ctx, stage);
|
||||
|
||||
cb.buffer = NULL;
|
||||
cb.user_buffer = params->ParameterValues;
|
||||
cb.buffer_offset = 0;
|
||||
cb.buffer_size = paramBytes;
|
||||
|
||||
if (ST_DEBUG & DEBUG_CONSTANTS) {
|
||||
debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n",
|
||||
__func__, shader_type, params->NumParameters,
|
||||
@@ -116,22 +103,86 @@ st_upload_constants(struct st_context *st, struct gl_program *prog)
|
||||
_mesa_print_parameter_list(params);
|
||||
}
|
||||
|
||||
cso_set_constant_buffer(st->cso_context, shader_type, 0, &cb);
|
||||
pipe_resource_reference(&cb.buffer, NULL);
|
||||
cb.buffer = NULL;
|
||||
cb.user_buffer = NULL;
|
||||
cb.buffer_offset = 0;
|
||||
cb.buffer_size = paramBytes;
|
||||
|
||||
/* Set inlinable constants. */
|
||||
unsigned num_inlinable_uniforms = prog->info.num_inlinable_uniforms;
|
||||
if (num_inlinable_uniforms) {
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
uint32_t values[MAX_INLINABLE_UNIFORMS];
|
||||
gl_constant_value *constbuf = params->ParameterValues;
|
||||
if (st->prefer_real_buffer_in_constbuf0) {
|
||||
uint32_t *ptr;
|
||||
/* fetch_state always stores 4 components (16 bytes) per matrix row,
|
||||
* but matrix rows are sometimes allocated partially, so add 12
|
||||
* to compensate for the fetch_state defect.
|
||||
*/
|
||||
u_upload_alloc(st->pipe->const_uploader, 0, paramBytes + 12, 64,
|
||||
&cb.buffer_offset, &cb.buffer, (void**)&ptr);
|
||||
|
||||
for (unsigned i = 0; i < num_inlinable_uniforms; i++)
|
||||
values[i] = constbuf[prog->info.inlinable_uniform_dw_offsets[i]].u;
|
||||
int uniform_bytes = params->UniformBytes;
|
||||
if (uniform_bytes)
|
||||
memcpy(ptr, params->ParameterValues, uniform_bytes);
|
||||
|
||||
pipe->set_inlinable_constants(pipe, shader_type,
|
||||
prog->info.num_inlinable_uniforms,
|
||||
values);
|
||||
/* Upload the constants which come from fixed-function state, such as
|
||||
* transformation matrices, fog factors, etc.
|
||||
*/
|
||||
if (params->StateFlags)
|
||||
_mesa_upload_state_parameters(st->ctx, params, ptr);
|
||||
|
||||
u_upload_unmap(st->pipe->const_uploader);
|
||||
cso_set_constant_buffer(st->cso_context, shader_type, 0, &cb);
|
||||
pipe_resource_reference(&cb.buffer, NULL);
|
||||
|
||||
/* Set inlinable constants. This is more involved because state
|
||||
* parameters are uploaded directly above instead of being loaded
|
||||
* into gl_program_parameter_list. The easiest way to get their values
|
||||
* is to load them.
|
||||
*/
|
||||
unsigned num_inlinable_uniforms = prog->info.num_inlinable_uniforms;
|
||||
if (num_inlinable_uniforms) {
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
uint32_t values[MAX_INLINABLE_UNIFORMS];
|
||||
gl_constant_value *constbuf = params->ParameterValues;
|
||||
bool loaded_state_vars = false;
|
||||
|
||||
for (unsigned i = 0; i < num_inlinable_uniforms; i++) {
|
||||
unsigned dw_offset = prog->info.inlinable_uniform_dw_offsets[i];
|
||||
|
||||
if (dw_offset * 4 >= uniform_bytes && !loaded_state_vars) {
|
||||
_mesa_load_state_parameters(st->ctx, params);
|
||||
loaded_state_vars = true;
|
||||
}
|
||||
|
||||
values[i] = constbuf[prog->info.inlinable_uniform_dw_offsets[i]].u;
|
||||
}
|
||||
|
||||
pipe->set_inlinable_constants(pipe, shader_type,
|
||||
prog->info.num_inlinable_uniforms,
|
||||
values);
|
||||
}
|
||||
} else {
|
||||
cb.user_buffer = params->ParameterValues;
|
||||
|
||||
/* Update the constants which come from fixed-function state, such as
|
||||
* transformation matrices, fog factors, etc.
|
||||
*/
|
||||
if (params->StateFlags)
|
||||
_mesa_load_state_parameters(st->ctx, params);
|
||||
|
||||
cso_set_constant_buffer(st->cso_context, shader_type, 0, &cb);
|
||||
|
||||
/* Set inlinable constants. */
|
||||
unsigned num_inlinable_uniforms = prog->info.num_inlinable_uniforms;
|
||||
if (num_inlinable_uniforms) {
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
uint32_t values[MAX_INLINABLE_UNIFORMS];
|
||||
gl_constant_value *constbuf = params->ParameterValues;
|
||||
|
||||
for (unsigned i = 0; i < num_inlinable_uniforms; i++)
|
||||
values[i] = constbuf[prog->info.inlinable_uniform_dw_offsets[i]].u;
|
||||
|
||||
pipe->set_inlinable_constants(pipe, shader_type,
|
||||
prog->info.num_inlinable_uniforms,
|
||||
values);
|
||||
}
|
||||
}
|
||||
|
||||
st->state.constants[shader_type].ptr = params->ParameterValues;
|
||||
|
@@ -700,6 +700,8 @@ st_create_context_priv(struct gl_context *ctx, struct pipe_context *pipe,
|
||||
!screen->get_param(screen, PIPE_CAP_TWO_SIDED_COLOR);
|
||||
st->lower_ucp =
|
||||
!screen->get_param(screen, PIPE_CAP_CLIP_PLANES);
|
||||
st->prefer_real_buffer_in_constbuf0 =
|
||||
screen->get_param(screen, PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0);
|
||||
st->allow_st_finalize_nir_twice = screen->finalize_nir != NULL;
|
||||
|
||||
st->has_hw_atomics =
|
||||
|
@@ -153,6 +153,7 @@ struct st_context
|
||||
boolean lower_point_size;
|
||||
boolean lower_two_sided_color;
|
||||
boolean lower_ucp;
|
||||
boolean prefer_real_buffer_in_constbuf0;
|
||||
|
||||
/* There are consequences for drivers wanting to call st_finalize_nir
|
||||
* twice, once before shader caching and once after lowering for shader
|
||||
|
@@ -223,11 +223,24 @@ st_feedback_draw_vbo(struct gl_context *ctx,
|
||||
info.has_user_indices = false;
|
||||
}
|
||||
|
||||
/* set constant buffers */
|
||||
/* set constant buffer 0 */
|
||||
struct gl_program_parameter_list *params = st->vp->Base.Parameters;
|
||||
|
||||
/* Update the constants which come from fixed-function state, such as
|
||||
* transformation matrices, fog factors, etc.
|
||||
*
|
||||
* It must be done here if the state tracker doesn't update state vars
|
||||
* in gl_program_parameter_list because allow_constbuf0_as_real_buffer
|
||||
* is set.
|
||||
*/
|
||||
if (st->prefer_real_buffer_in_constbuf0 && params->StateFlags)
|
||||
_mesa_load_state_parameters(st->ctx, params);
|
||||
|
||||
draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
|
||||
st->state.constants[PIPE_SHADER_VERTEX].ptr,
|
||||
st->state.constants[PIPE_SHADER_VERTEX].size);
|
||||
|
||||
/* set uniform buffers */
|
||||
const struct gl_program *prog = &vp->Base.Base;
|
||||
struct pipe_transfer *ubo_transfer[PIPE_MAX_CONSTANT_BUFFERS] = {0};
|
||||
assert(prog->info.num_ubos <= ARRAY_SIZE(ubo_transfer));
|
||||
|
Reference in New Issue
Block a user