[Mesa-dev] [PATCH] draw: fix draw_llvm_variant_key struct padding to avoid recompiles
Jose Fonseca
jfonseca at vmware.com
Mon Jan 28 23:02:37 PST 2013
----- Original Message -----
> On 01/28/2013 03:45 PM, sroland at vmware.com wrote:
> > From: Roland Scheidegger<sroland at vmware.com>
> >
> > The struct padding got broken by
> > c789b981b244333cfc903bcd1e2fefc010500013.
> > This caused serious performance regression because part of the key
> > was
> > unitialized and hence the shader always recompiled (at least on
> > release
> > builds...).
> > While here also fix key size calculation when the number of
> > samplers
> > and the number of sampler views are different.
> > ---
> > src/gallium/auxiliary/draw/draw_llvm.c | 3 ++-
> > src/gallium/auxiliary/draw/draw_llvm.h | 3 ++-
> > src/gallium/auxiliary/draw/draw_vs_llvm.c | 5 +++--
> > 3 files changed, 7 insertions(+), 4 deletions(-)
> >
> > diff --git a/src/gallium/auxiliary/draw/draw_llvm.c
> > b/src/gallium/auxiliary/draw/draw_llvm.c
> > index afb10a6..dc83f80 100644
> > --- a/src/gallium/auxiliary/draw/draw_llvm.c
> > +++ b/src/gallium/auxiliary/draw/draw_llvm.c
> > @@ -1378,7 +1378,8 @@ draw_llvm_make_variant_key(struct draw_llvm
> > *llvm, char *store)
> > key->clip_halfz =
> > !llvm->draw->rasterizer->gl_rasterization_rules;
> > key->need_edgeflags = (llvm->draw->vs.edgeflag_output ? TRUE :
> > FALSE);
> > key->ucp_enable = llvm->draw->rasterizer->clip_plane_enable;
> > - key->pad = 0;
> > + key->pad1 = 0;
> > + key->pad2 = 0;
> >
> > /* All variants of this shader will have the same value for
> > * nr_samplers. Not yet trying to compact away holes in the
> > diff --git a/src/gallium/auxiliary/draw/draw_llvm.h
> > b/src/gallium/auxiliary/draw/draw_llvm.h
> > index a664857..8e5bd3c 100644
> > --- a/src/gallium/auxiliary/draw/draw_llvm.h
> > +++ b/src/gallium/auxiliary/draw/draw_llvm.h
> > @@ -206,8 +206,9 @@ struct draw_llvm_variant_key
> > unsigned clip_halfz:1;
> > unsigned bypass_viewport:1;
> > unsigned need_edgeflags:1;
> > + unsigned pad1:1;
> > unsigned ucp_enable:PIPE_MAX_CLIP_PLANES;
> > - unsigned pad:33-PIPE_MAX_CLIP_PLANES;
> > + unsigned pad2:32-PIPE_MAX_CLIP_PLANES;
>
> There should probably be a prominent comment on this struct about the
> importance of zeroing-out any unused bits, adding padding fields,
> etc.
> to help prevent this in the future.
Yes, I agree.
> If we wanted to be really safe, during init we could create a dummy
> key, set it to all ones, then set all of the fields to zero, then
> assert that no bits in the key are still set.
Unfortunately that doesn't catch all the cases: during structure assignment (via the = operator) the compiler is fre to clobber (or copy) any unpadded bits. The actual behavior depends on compiler, flags, code, etc.
Another alternative is to never use the = operator, and instead use memcpy operator, but that loses type checking, so it has its own share of problems. I think that add padding and add big warnings as you suggest is the best way to go.
> > /* Variable number of vertex elements:
> > */
> > diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c
> > b/src/gallium/auxiliary/draw/draw_vs_llvm.c
> > index 3e46f8c..ac3999e 100644
> > --- a/src/gallium/auxiliary/draw/draw_vs_llvm.c
> > +++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
> > @@ -100,8 +100,9 @@ draw_create_vs_llvm(struct draw_context *draw,
> >
> > vs->variant_key_size =
> > draw_llvm_variant_key_size(
> > - vs->base.info.file_max[TGSI_FILE_INPUT]+1,
> > - vs->base.info.file_max[TGSI_FILE_SAMPLER]+1);
> > + vs->base.info.file_max[TGSI_FILE_INPUT]+1,
> > + MAX2(vs->base.info.file_max[TGSI_FILE_SAMPLER]+1,
> > + vs->base.info.file_max[TGSI_FILE_SAMPLER_VIEW]+1));
> >
> > vs->base.state.stream_output = state->stream_output;
> > vs->base.draw = draw;
>
> Otherwise,
>
> Reviewed-by: Brian Paul <brianp at vmware.com>
Reviewed-by: Jose Fonseca <jfonseca at vmware.com>
Jose
More information about the mesa-dev
mailing list