[Mesa-dev] [PATCH 1/5] anv: Move push constant allocation to the command buffer
Jason Ekstrand
jason at jlekstrand.net
Fri May 27 20:06:10 UTC 2016
On Fri, May 27, 2016 at 1:01 PM, Jordan Justen <jordan.l.justen at intel.com>
wrote:
> On 2016-05-20 12:41:04, Jason Ekstrand wrote:
> > Instead of blasting it out as part of the pipeline, we put it in the
> > command buffer and only blast it out when it's really needed. Since the
> > PUSH_CONSTANT_ALLOC commands aren't pipelined, they immediately cause a
> > stall which we would like to avoid.
> > ---
> > src/intel/vulkan/anv_cmd_buffer.c | 1 +
> > src/intel/vulkan/anv_pipeline.c | 22 ----------
> > src/intel/vulkan/anv_private.h | 2 +-
> > src/intel/vulkan/genX_cmd_buffer.c | 78
> +++++++++++++++++++++++++++++++----
> > src/intel/vulkan/genX_pipeline_util.h | 12 ------
> > 5 files changed, 71 insertions(+), 44 deletions(-)
> >
> > diff --git a/src/intel/vulkan/anv_cmd_buffer.c
> b/src/intel/vulkan/anv_cmd_buffer.c
> > index bba24e8..db7793e 100644
> > --- a/src/intel/vulkan/anv_cmd_buffer.c
> > +++ b/src/intel/vulkan/anv_cmd_buffer.c
> > @@ -130,6 +130,7 @@ anv_cmd_state_reset(struct anv_cmd_buffer
> *cmd_buffer)
> > state->descriptors_dirty = 0;
> > state->push_constants_dirty = 0;
> > state->pipeline = NULL;
> > + state->push_constant_stages = 0;
> > state->restart_index = UINT32_MAX;
> > state->dynamic = default_dynamic_state;
> > state->need_query_wa = true;
> > diff --git a/src/intel/vulkan/anv_pipeline.c
> b/src/intel/vulkan/anv_pipeline.c
> > index faa0adb..c010f0f 100644
> > --- a/src/intel/vulkan/anv_pipeline.c
> > +++ b/src/intel/vulkan/anv_pipeline.c
> > @@ -939,28 +939,6 @@ anv_compute_urb_partition(struct anv_pipeline
> *pipeline)
> > pipeline->urb.start[MESA_SHADER_TESS_EVAL] = push_constant_chunks;
> > pipeline->urb.size[MESA_SHADER_TESS_EVAL] = 1;
> > pipeline->urb.entries[MESA_SHADER_TESS_EVAL] = 0;
> > -
> > - const unsigned stages =
> > - _mesa_bitcount(pipeline->active_stages &
> VK_SHADER_STAGE_ALL_GRAPHICS);
> > - unsigned size_per_stage = stages ? (push_constant_kb / stages) : 0;
> > - unsigned used_kb = 0;
> > -
> > - /* Broadwell+ and Haswell gt3 require that the push constant sizes
> be in
> > - * units of 2KB. Incidentally, these are the same platforms that
> have
> > - * 32KB worth of push constant space.
> > - */
> > - if (push_constant_kb == 32)
> > - size_per_stage &= ~1u;
> > -
> > - for (int i = MESA_SHADER_VERTEX; i < MESA_SHADER_FRAGMENT; i++) {
> > - pipeline->urb.push_size[i] =
> > - (pipeline->active_stages & (1 << i)) ? size_per_stage : 0;
> > - used_kb += pipeline->urb.push_size[i];
> > - assert(used_kb <= push_constant_kb);
> > - }
> > -
> > - pipeline->urb.push_size[MESA_SHADER_FRAGMENT] =
> > - push_constant_kb - used_kb;
> > }
> >
> > static void
> > diff --git a/src/intel/vulkan/anv_private.h
> b/src/intel/vulkan/anv_private.h
> > index 33cbff9..80e768d 100644
> > --- a/src/intel/vulkan/anv_private.h
> > +++ b/src/intel/vulkan/anv_private.h
> > @@ -1177,6 +1177,7 @@ struct anv_cmd_state {
> > uint32_t restart_index;
> > struct anv_vertex_binding
> vertex_bindings[MAX_VBS];
> > struct anv_descriptor_set * descriptors[MAX_SETS];
> > + VkShaderStageFlags push_constant_stages;
> > struct anv_push_constants *
> push_constants[MESA_SHADER_STAGES];
> > struct anv_state
> binding_tables[MESA_SHADER_STAGES];
> > struct anv_state
> samplers[MESA_SHADER_STAGES];
> > @@ -1411,7 +1412,6 @@ struct anv_pipeline {
> > uint32_t
> scratch_start[MESA_SHADER_STAGES];
> > uint32_t total_scratch;
> > struct {
> > - uint8_t
> push_size[MESA_SHADER_FRAGMENT + 1];
> > uint32_t
> start[MESA_SHADER_GEOMETRY + 1];
> > uint32_t
> size[MESA_SHADER_GEOMETRY + 1];
> > uint32_t
> entries[MESA_SHADER_GEOMETRY + 1];
> > diff --git a/src/intel/vulkan/genX_cmd_buffer.c
> b/src/intel/vulkan/genX_cmd_buffer.c
> > index ee47c29..f5e3530 100644
> > --- a/src/intel/vulkan/genX_cmd_buffer.c
> > +++ b/src/intel/vulkan/genX_cmd_buffer.c
> > @@ -274,6 +274,72 @@ void genX(CmdPipelineBarrier)(
> > }
> > }
> >
> > +static void
> > +cmd_buffer_alloc_push_constants(struct anv_cmd_buffer *cmd_buffer)
> > +{
> > + VkShaderStageFlags stages =
> cmd_buffer->state.pipeline->active_stages;
> > +
> > + /* In order to avoid thrash, we assume that vertex and fragment
> stages
> > + * always exist. In the rare case where one is missing *and* the
> other
> > + * uses push concstants, this may be suboptimal. However, avoiding
> stalls
> > + * seems more important.
> > + */
> > + stages |= VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT;
> > +
> > + if (stages == cmd_buffer->state.push_constant_stages)
> > + return;
> > +
> > +#if GEN_GEN >= 8
> > + const unsigned push_constant_kb = 32;
> > +#elif GEN_IS_HASWELL
> > + const unsigned push_constant_kb = cmd_buffer->device->info.gt == 3
> ? 32 : 16;
> > +#else
> > + const unsigned push_constant_kb = 16;
> > +#endif
>
> I noted that this changed from the old code that just used 32k. I see
> that this matches src/mesa/drivers/dri/i965/gen7_urb.c. Maybe worth
> noting in the commit message?
>
I think we just use 32KB at one point, but I fixed that a while ago.
> Reviewed-by: Jordan Justen <jordan.l.justen at intel.com>
>
Thanks
>
> > +
> > + const unsigned num_stages =
> > + _mesa_bitcount(stages & VK_SHADER_STAGE_ALL_GRAPHICS);
> > + unsigned size_per_stage = push_constant_kb / num_stages;
> > +
> > + /* Broadwell+ and Haswell gt3 require that the push constant sizes
> be in
> > + * units of 2KB. Incidentally, these are the same platforms that
> have
> > + * 32KB worth of push constant space.
> > + */
> > + if (push_constant_kb == 32)
> > + size_per_stage &= ~1u;
> > +
> > + uint32_t kb_used = 0;
> > + for (int i = MESA_SHADER_VERTEX; i < MESA_SHADER_FRAGMENT; i++) {
> > + unsigned push_size = (stages & (1 << i)) ? size_per_stage : 0;
> > + anv_batch_emit(&cmd_buffer->batch,
> > + GENX(3DSTATE_PUSH_CONSTANT_ALLOC_VS), alloc) {
> > + alloc._3DCommandSubOpcode = 18 + i;
> > + alloc.ConstantBufferOffset = (push_size > 0) ? kb_used : 0;
> > + alloc.ConstantBufferSize = push_size;
> > + }
> > + kb_used += push_size;
> > + }
> > +
> > + anv_batch_emit(&cmd_buffer->batch,
> > + GENX(3DSTATE_PUSH_CONSTANT_ALLOC_PS), alloc) {
> > + alloc.ConstantBufferOffset = kb_used;
> > + alloc.ConstantBufferSize = push_constant_kb - kb_used;
> > + }
> > +
> > + cmd_buffer->state.push_constant_stages = stages;
> > +
> > + /* From the BDW PRM for 3DSTATE_PUSH_CONSTANT_ALLOC_VS:
> > + *
> > + * "The 3DSTATE_CONSTANT_VS must be reprogrammed prior to
> > + * the next 3DPRIMITIVE command after programming the
> > + * 3DSTATE_PUSH_CONSTANT_ALLOC_VS"
> > + *
> > + * Since 3DSTATE_PUSH_CONSTANT_ALLOC_VS is programmed as part of
> > + * pipeline setup, we need to dirty push constants.
> > + */
> > + cmd_buffer->state.push_constants_dirty |=
> VK_SHADER_STAGE_ALL_GRAPHICS;
> > +}
> > +
> > static uint32_t
> > cmd_buffer_flush_push_constants(struct anv_cmd_buffer *cmd_buffer)
> > {
> > @@ -384,16 +450,10 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer
> *cmd_buffer)
> >
> > anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->batch);
> >
> > - /* From the BDW PRM for 3DSTATE_PUSH_CONSTANT_ALLOC_VS:
> > - *
> > - * "The 3DSTATE_CONSTANT_VS must be reprogrammed prior to
> > - * the next 3DPRIMITIVE command after programming the
> > - * 3DSTATE_PUSH_CONSTANT_ALLOC_VS"
> > - *
> > - * Since 3DSTATE_PUSH_CONSTANT_ALLOC_VS is programmed as part of
> > - * pipeline setup, we need to dirty push constants.
> > + /* If the pipeline changed, we may need to re-allocate push
> constant
> > + * space in the URB.
> > */
> > - cmd_buffer->state.push_constants_dirty |=
> VK_SHADER_STAGE_ALL_GRAPHICS;
> > + cmd_buffer_alloc_push_constants(cmd_buffer);
> > }
> >
> > #if GEN_GEN <= 7
> > diff --git a/src/intel/vulkan/genX_pipeline_util.h
> b/src/intel/vulkan/genX_pipeline_util.h
> > index ecbe436..2ed55e0 100644
> > --- a/src/intel/vulkan/genX_pipeline_util.h
> > +++ b/src/intel/vulkan/genX_pipeline_util.h
> > @@ -205,18 +205,6 @@ emit_urb_setup(struct anv_pipeline *pipeline)
> > }
> > #endif
> >
> > - unsigned push_start = 0;
> > - for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_FRAGMENT; i++) {
> > - unsigned push_size = pipeline->urb.push_size[i];
> > - anv_batch_emit(&pipeline->batch,
> > - GENX(3DSTATE_PUSH_CONSTANT_ALLOC_VS), alloc) {
> > - alloc._3DCommandSubOpcode = 18 + i;
> > - alloc.ConstantBufferOffset = (push_size > 0) ? push_start : 0;
> > - alloc.ConstantBufferSize = push_size;
> > - }
> > - push_start += pipeline->urb.push_size[i];
> > - }
> > -
> > for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) {
> > anv_batch_emit(&pipeline->batch, GENX(3DSTATE_URB_VS), urb) {
> > urb._3DCommandSubOpcode = 48 + i;
> > --
> > 2.5.0.400.gff86faf
> >
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20160527/f4b30346/attachment-0001.html>
More information about the mesa-dev
mailing list