summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorKenneth Graunke <[email protected]>2018-12-04 15:34:30 -0800
committerKenneth Graunke <[email protected]>2019-03-07 11:39:27 -0800
commitfbc51c4c956bb681c52e3163f73051303b24d8b8 (patch)
tree91b2b743448da8c632c006f60344003fb0dad1bc /src/gallium/drivers
parent9caabd6c5f15e8c0e7ebe0147372d16750e2a20b (diff)
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 <[email protected]> Tested-by: Andre Heider <[email protected]> Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/iris/iris_context.h4
-rw-r--r--src/gallium/drivers/iris/iris_program.c8
-rw-r--r--src/gallium/drivers/iris/iris_state.c52
3 files changed, 44 insertions, 20 deletions
diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h
index 771c47ffced..70a929178df 100644
--- a/src/gallium/drivers/iris/iris_context.h
+++ b/src/gallium/drivers/iris/iris_context.h
@@ -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;
diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c
index 0ceaeb22d27..9d1664029d9 100644
--- a/src/gallium/drivers/iris/iris_program.c
+++ b/src/gallium/drivers/iris/iris_program.c
@@ -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;
diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c
index 7e1ead70797..0483bb8caa0 100644
--- a/src/gallium/drivers/iris/iris_state.c
+++ b/src/gallium/drivers/iris/iris_state.c
@@ -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);