Ilia Mirkin
2015-Jul-26 04:56 UTC
[Nouveau] [PATCH] nvc0: bind a fake tess control program when there isn't one available
Apparently this is necessary in order for tess factors to work in a tess eval program without a tess control program bound. Probably because it uses the fake program's shader header to work out the number of patch constants. Fixes vs-tes-tessinner-tessouter-inputs Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu> --- src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 5 +++++ src/gallium/drivers/nouveau/nvc0/nvc0_context.h | 3 +++ src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 17 +++++++++++++++++ src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c | 6 +++++- 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c index 84f8db6..46970db 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c @@ -132,6 +132,9 @@ nvc0_context_unreference_resources(struct nvc0_context *nvc0) pipe_resource_reference(res, NULL); } util_dynarray_fini(&nvc0->global_residents); + + if (nvc0->tcp_empty) + nvc0->base.pipe.delete_tcs_state(&nvc0->base.pipe, nvc0->tcp_empty); } static void @@ -326,6 +329,8 @@ nvc0_create(struct pipe_screen *pscreen, void *priv) /* shader builtin library is per-screen, but we need a context for m2mf */ nvc0_program_library_upload(nvc0); + nvc0_program_init_tcp_empty(nvc0); + nvc0->dirty |= NVC0_NEW_TCTLPROG; /* add permanently resident buffers to bufctxts */ diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h index f449942..df1a891 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h @@ -128,6 +128,8 @@ struct nvc0_context { struct nvc0_program *fragprog; struct nvc0_program *compprog; + struct nvc0_program *tcp_empty; + struct nvc0_constbuf constbuf[6][NVC0_MAX_PIPE_CONSTBUFS]; uint16_t constbuf_dirty[6]; uint16_t constbuf_valid[6]; @@ -227,6 +229,7 @@ void nvc0_program_destroy(struct nvc0_context *, struct nvc0_program *); void nvc0_program_library_upload(struct nvc0_context *); uint32_t nvc0_program_symbol_offset(const struct nvc0_program *, uint32_t label); +void nvc0_program_init_tcp_empty(struct nvc0_context *); /* nvc0_query.c */ void nvc0_init_query_functions(struct nvc0_context *); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c index 4941831..e9975ce 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c @@ -22,6 +22,8 @@ #include "pipe/p_defines.h" +#include "tgsi/tgsi_ureg.h" + #include "nvc0/nvc0_context.h" #include "codegen/nv50_ir_driver.h" @@ -803,3 +805,18 @@ nvc0_program_symbol_offset(const struct nvc0_program *prog, uint32_t label) return prog->code_base + base + syms[i].offset; return prog->code_base; /* no symbols or symbol not found */ } + +void +nvc0_program_init_tcp_empty(struct nvc0_context *nvc0) +{ + struct ureg_program *ureg; + + ureg = ureg_create(TGSI_PROCESSOR_TESS_CTRL); + if (!ureg) + return; + + ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT, 1); + ureg_END(ureg); + + nvc0->tcp_empty = ureg_create_shader_and_destroy(ureg, &nvc0->base.pipe); +} diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c index 8aa127a..e21515f 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c @@ -148,8 +148,12 @@ nvc0_tctlprog_validate(struct nvc0_context *nvc0) BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(2)), 1); PUSH_DATA (push, tp->num_gprs); } else { - BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 1); + tp = nvc0->tcp_empty; + if (!nvc0_program_validate(nvc0, tp)) + assert(!"unable to validate empty tcp"); + BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 2); PUSH_DATA (push, 0x20); + PUSH_DATA (push, tp->code_base); } nvc0_program_update_context_state(nvc0, tp, 1); } -- 2.3.6
Samuel Pitoiset
2015-Jul-26 08:37 UTC
[Nouveau] [Mesa-dev] [PATCH] nvc0: bind a fake tess control program when there isn't one available
On 07/26/2015 06:56 AM, Ilia Mirkin wrote:> Apparently this is necessary in order for tess factors to work in a tess > eval program without a tess control program bound. Probably because it > uses the fake program's shader header to work out the number of patch > constants. > > Fixes vs-tes-tessinner-tessouter-inputs > > Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu> > --- > src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 5 +++++ > src/gallium/drivers/nouveau/nvc0/nvc0_context.h | 3 +++ > src/gallium/drivers/nouveau/nvc0/nvc0_program.c | 17 +++++++++++++++++ > src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c | 6 +++++- > 4 files changed, 30 insertions(+), 1 deletion(-) > > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c > index 84f8db6..46970db 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c > @@ -132,6 +132,9 @@ nvc0_context_unreference_resources(struct nvc0_context *nvc0) > pipe_resource_reference(res, NULL); > } > util_dynarray_fini(&nvc0->global_residents); > + > + if (nvc0->tcp_empty) > + nvc0->base.pipe.delete_tcs_state(&nvc0->base.pipe, nvc0->tcp_empty); > } > > static void > @@ -326,6 +329,8 @@ nvc0_create(struct pipe_screen *pscreen, void *priv) > > /* shader builtin library is per-screen, but we need a context for m2mf */ > nvc0_program_library_upload(nvc0); > + nvc0_program_init_tcp_empty(nvc0); > + nvc0->dirty |= NVC0_NEW_TCTLPROG; > > /* add permanently resident buffers to bufctxts */ > > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h > index f449942..df1a891 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h > @@ -128,6 +128,8 @@ struct nvc0_context { > struct nvc0_program *fragprog; > struct nvc0_program *compprog; > > + struct nvc0_program *tcp_empty; > + > struct nvc0_constbuf constbuf[6][NVC0_MAX_PIPE_CONSTBUFS]; > uint16_t constbuf_dirty[6]; > uint16_t constbuf_valid[6]; > @@ -227,6 +229,7 @@ void nvc0_program_destroy(struct nvc0_context *, struct nvc0_program *); > void nvc0_program_library_upload(struct nvc0_context *); > uint32_t nvc0_program_symbol_offset(const struct nvc0_program *, > uint32_t label); > +void nvc0_program_init_tcp_empty(struct nvc0_context *); > > /* nvc0_query.c */ > void nvc0_init_query_functions(struct nvc0_context *); > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c > index 4941831..e9975ce 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c > @@ -22,6 +22,8 @@ > > #include "pipe/p_defines.h" > > +#include "tgsi/tgsi_ureg.h" > + > #include "nvc0/nvc0_context.h" > > #include "codegen/nv50_ir_driver.h" > @@ -803,3 +805,18 @@ nvc0_program_symbol_offset(const struct nvc0_program *prog, uint32_t label) > return prog->code_base + base + syms[i].offset; > return prog->code_base; /* no symbols or symbol not found */ > } > + > +void > +nvc0_program_init_tcp_empty(struct nvc0_context *nvc0) > +{ > + struct ureg_program *ureg; > + > + ureg = ureg_create(TGSI_PROCESSOR_TESS_CTRL); > + if (!ureg) > + return; > + > + ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT, 1); > + ureg_END(ureg); > + > + nvc0->tcp_empty = ureg_create_shader_and_destroy(ureg, &nvc0->base.pipe); > +} > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c > index 8aa127a..e21515f 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c > @@ -148,8 +148,12 @@ nvc0_tctlprog_validate(struct nvc0_context *nvc0) > BEGIN_NVC0(push, NVC0_3D(SP_GPR_ALLOC(2)), 1); > PUSH_DATA (push, tp->num_gprs); > } else { > - BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 1); > + tp = nvc0->tcp_empty; > + if (!nvc0_program_validate(nvc0, tp)) > + assert(!"unable to validate empty tcp"); > + BEGIN_NVC0(push, NVC0_3D(SP_SELECT(2)), 2); > PUSH_DATA (push, 0x20); > + PUSH_DATA (push, tp->code_base); > }It would be good to check if tp is not NULL before trying to validate the program. And if the program can't be validated, I don't think we want to push tp->code_base, isn't it?> nvc0_program_update_context_state(nvc0, tp, 1); > }