mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 02:58:05 +02:00
iris: Defer uploading sampler state tables until draw time
Gallium might call us multiple times to bind subsets of the samplers,
at which point we'd recreate the table a bunch of times. It doesn't
really buy us anything to do it here - even if we defer to draw time,
the dirty tracking ensures we'll only do it on the first draw after a
bind_sampler_states() call.
We now use the number of samplers specified by the shader instead of
the binding count. If this number changes, we flag sampler state as
dirty so we re-upload a table with the right number of entries.
This also fixes a bug where ice->state.need_border_colors was never
unset, so once something needed border colors, the pool would always
be pinned in all future batches.
v2: Explicitly flag sampler states as dirty, rather than assuming that
bind_sampler_states() will be called if the program texture count
changes. While this may be true for st/mesa, it isn't the case for
Gallium HUD.
Tested-by: Timur Kristóf <timur.kristof@gmail.com>
Tested-by: Andre Heider <a.heider@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
parent
9caabd6c5f
commit
fbc51c4c95
3 changed files with 44 additions and 20 deletions
|
|
@ -575,8 +575,8 @@ struct iris_context {
|
|||
/** Do vertex shader uses edge flag ? */
|
||||
bool vs_needs_edge_flag;
|
||||
|
||||
/** Do any samplers (for any stage) need border color? */
|
||||
bool need_border_colors;
|
||||
/** Do any samplers need border color? One bit per shader stage. */
|
||||
uint8_t need_border_colors;
|
||||
|
||||
struct pipe_stream_output_target *so_target[PIPE_MAX_SO_BUFFERS];
|
||||
bool streamout_active;
|
||||
|
|
|
|||
|
|
@ -1614,6 +1614,14 @@ bind_state(struct iris_context *ice,
|
|||
uint64_t dirty_bit = IRIS_DIRTY_UNCOMPILED_VS << stage;
|
||||
const uint64_t nos = ish ? ish->nos : 0;
|
||||
|
||||
const struct shader_info *old_info = iris_get_shader_info(ice, stage);
|
||||
const struct shader_info *new_info = ish ? &ish->nir->info : NULL;
|
||||
|
||||
if ((old_info ? util_last_bit(old_info->textures_used) : 0) !=
|
||||
(new_info ? util_last_bit(new_info->textures_used) : 0)) {
|
||||
ice->state.dirty |= IRIS_DIRTY_SAMPLER_STATES_VS << stage;
|
||||
}
|
||||
|
||||
ice->shaders.uncompiled[stage] = ish;
|
||||
ice->state.dirty |= dirty_bit;
|
||||
|
||||
|
|
|
|||
|
|
@ -1437,19 +1437,7 @@ iris_create_sampler_state(struct pipe_context *ctx,
|
|||
|
||||
/**
|
||||
* The pipe->bind_sampler_states() driver hook.
|
||||
*
|
||||
* Now that we know all the sampler states, we upload them all into a
|
||||
* contiguous area of GPU memory, for 3DSTATE_SAMPLER_STATE_POINTERS_*.
|
||||
* We also fill out the border color state pointers at this point.
|
||||
*
|
||||
* We could defer this work to draw time, but we assume that binding
|
||||
* will be less frequent than drawing.
|
||||
*/
|
||||
// XXX: this may be a bad idea, need to make sure that st/mesa calls us
|
||||
// XXX: with the complete set of shaders. If it makes multiple calls to
|
||||
// XXX: things one at a time, we could waste a lot of time assembling things.
|
||||
// XXX: it doesn't even BUY us anything to do it here, because we only flag
|
||||
// XXX: IRIS_DIRTY_SAMPLER_STATE when this is called...
|
||||
static void
|
||||
iris_bind_sampler_states(struct pipe_context *ctx,
|
||||
enum pipe_shader_type p_stage,
|
||||
|
|
@ -1466,6 +1454,29 @@ iris_bind_sampler_states(struct pipe_context *ctx,
|
|||
shs->samplers[start + i] = states[i];
|
||||
}
|
||||
|
||||
ice->state.dirty |= IRIS_DIRTY_SAMPLER_STATES_VS << stage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload the sampler states into a contiguous area of GPU memory, for
|
||||
* for 3DSTATE_SAMPLER_STATE_POINTERS_*.
|
||||
*
|
||||
* Also fill out the border color state pointers.
|
||||
*/
|
||||
static void
|
||||
iris_upload_sampler_states(struct iris_context *ice, gl_shader_stage stage)
|
||||
{
|
||||
struct iris_shader_state *shs = &ice->state.shaders[stage];
|
||||
const struct shader_info *info = iris_get_shader_info(ice, stage);
|
||||
|
||||
/* We assume the state tracker will call pipe->bind_sampler_states()
|
||||
* if the program's number of textures changes.
|
||||
*/
|
||||
unsigned count = info ? util_last_bit(info->textures_used) : 0;
|
||||
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
/* Assemble the SAMPLER_STATEs into a contiguous table that lives
|
||||
* in the dynamic state memory zone, so we can point to it via the
|
||||
* 3DSTATE_SAMPLER_STATE_POINTERS_* commands.
|
||||
|
|
@ -1483,6 +1494,8 @@ iris_bind_sampler_states(struct pipe_context *ctx,
|
|||
/* Make sure all land in the same BO */
|
||||
iris_border_color_pool_reserve(ice, IRIS_MAX_TEXTURE_SAMPLERS);
|
||||
|
||||
ice->state.need_border_colors &= ~(1 << stage);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
struct iris_sampler_state *state = shs->samplers[i];
|
||||
|
||||
|
|
@ -1491,7 +1504,7 @@ iris_bind_sampler_states(struct pipe_context *ctx,
|
|||
} else if (!state->needs_border_color) {
|
||||
memcpy(map, state->sampler_state, 4 * GENX(SAMPLER_STATE_length));
|
||||
} else {
|
||||
ice->state.need_border_colors = true;
|
||||
ice->state.need_border_colors |= 1 << stage;
|
||||
|
||||
/* Stream out the border color and merge the pointer. */
|
||||
uint32_t offset =
|
||||
|
|
@ -1508,8 +1521,6 @@ iris_bind_sampler_states(struct pipe_context *ctx,
|
|||
|
||||
map += GENX(SAMPLER_STATE_length);
|
||||
}
|
||||
|
||||
ice->state.dirty |= IRIS_DIRTY_SAMPLER_STATES_VS << stage;
|
||||
}
|
||||
|
||||
static enum isl_channel_select
|
||||
|
|
@ -4439,14 +4450,13 @@ iris_upload_dirty_render_state(struct iris_context *ice,
|
|||
}
|
||||
}
|
||||
|
||||
if (ice->state.need_border_colors)
|
||||
iris_use_pinned_bo(batch, ice->state.border_color_pool.bo, false);
|
||||
|
||||
for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
|
||||
if (!(dirty & (IRIS_DIRTY_SAMPLER_STATES_VS << stage)) ||
|
||||
!ice->shaders.prog[stage])
|
||||
continue;
|
||||
|
||||
iris_upload_sampler_states(ice, stage);
|
||||
|
||||
struct iris_shader_state *shs = &ice->state.shaders[stage];
|
||||
struct pipe_resource *res = shs->sampler_table.res;
|
||||
if (res)
|
||||
|
|
@ -4458,6 +4468,9 @@ iris_upload_dirty_render_state(struct iris_context *ice,
|
|||
}
|
||||
}
|
||||
|
||||
if (ice->state.need_border_colors)
|
||||
iris_use_pinned_bo(batch, ice->state.border_color_pool.bo, false);
|
||||
|
||||
if (dirty & IRIS_DIRTY_MULTISAMPLE) {
|
||||
iris_emit_cmd(batch, GENX(3DSTATE_MULTISAMPLE), ms) {
|
||||
ms.PixelLocation =
|
||||
|
|
@ -5101,6 +5114,9 @@ iris_upload_compute_state(struct iris_context *ice,
|
|||
if (dirty & IRIS_DIRTY_BINDINGS_CS)
|
||||
iris_populate_binding_table(ice, batch, MESA_SHADER_COMPUTE, false);
|
||||
|
||||
if (dirty & IRIS_DIRTY_SAMPLER_STATES_CS)
|
||||
iris_upload_sampler_states(ice, MESA_SHADER_COMPUTE);
|
||||
|
||||
iris_use_optional_res(batch, shs->sampler_table.res, false);
|
||||
iris_use_pinned_bo(batch, iris_resource_bo(shader->assembly.res), false);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue