[Mesa-dev] [PATCH] nvc0: serialize before updating some constant buffer bindings
Ilia Mirkin
imirkin at alum.mit.edu
Sun Jul 15 22:38:20 UTC 2018
On Sun, Jul 15, 2018 at 6:14 PM, Rhys Perry <pendingchaos02 at gmail.com> wrote:
> To avoid serializing, this has the user constant buffer always be 65536
> bytes and enabled unless it's required that something else is used for
> constant buffer 0.
>
> Fixes artifacts with at least 0 A.D. and Unigine Valley, Heaven and
> Superposition.
>
> This has only been tested on Pascal but the fix and problem probably
> apply to Maxwell+.
>
> Signed-off-by: Rhys Perry <pendingchaos02 at gmail.com>
> ---
> src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 46 +++++++++++++++++++---
> src/gallium/drivers/nouveau/nvc0/nvc0_screen.h | 13 +++++-
> .../drivers/nouveau/nvc0/nvc0_state_validate.c | 37 ++++++++---------
> 3 files changed, 69 insertions(+), 27 deletions(-)
>
> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
> index 37e10dcd07..197b0c1911 100644
> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
> @@ -829,6 +829,40 @@ nvc0_screen_resize_text_area(struct nvc0_screen *screen, uint64_t size)
> return 0;
> }
>
> +void
> +nvc0_screen_bind_cb_3d(struct nvc0_screen *screen, bool *can_serialize,
> + int stage, int index, int size, uint64_t addr)
> +{
> + assert(stage != 5);
> +
> + struct nouveau_pushbuf *push = screen->base.pushbuf;
> +
> + if (screen->base.class_3d >= GM107_3D_CLASS) {
> + struct nvc0_cb_binding *binding = &screen->cb_bindings[stage][index];
> +
> + // TODO: Better figure out the conditions in which this is needed
> + bool serialize = binding->addr == addr && binding->size != size;
> + if (can_serialize)
> + serialize = serialize && *can_serialize;
> + if (serialize) {
> + IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0);
> + if (can_serialize)
> + *can_serialize = false;
> + }
> +
> + binding->addr = addr;
> + binding->size = size;
> + }
> +
> + if (size >= 0) {
> + BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
> + PUSH_DATA (push, size);
> + PUSH_DATAh(push, addr);
> + PUSH_DATA (push, addr);
> + }
> + IMMED_NVC0(push, NVC0_3D(CB_BIND(stage)), (index << 4) | (size >= 0));
> +}
> +
> #define FAIL_SCREEN_INIT(str, err) \
> do { \
> NOUVEAU_ERR(str, err); \
> @@ -1272,14 +1306,14 @@ nvc0_screen_create(struct nouveau_device *dev)
>
> /* XXX: Compute and 3D are somehow aliased on Fermi. */
> for (i = 0; i < 5; ++i) {
> + unsigned j = 0;
> + for (j = 0; j < 16; j++)
> + screen->cb_bindings[i][j].size = -1;
> +
> /* TIC and TSC entries for each unit (nve4+ only) */
> /* auxiliary constants (6 user clip planes, base instance id) */
> - BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
> - PUSH_DATA (push, NVC0_CB_AUX_SIZE);
> - PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i));
> - PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i));
> - BEGIN_NVC0(push, NVC0_3D(CB_BIND(i)), 1);
> - PUSH_DATA (push, (15 << 4) | 1);
> + nvc0_screen_bind_cb_3d(screen, NULL, i, 15, NVC0_CB_AUX_SIZE,
> + screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i));
> if (screen->eng3d->oclass >= NVE4_3D_CLASS) {
> unsigned j;
> BEGIN_1IC0(push, NVC0_3D(CB_POS), 9);
> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
> index efd62a8a41..d088db984a 100644
> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
> @@ -53,12 +53,17 @@ struct nvc0_graph_state {
> uint8_t tls_required; /* bitmask of shader types using l[] */
> uint8_t clip_enable;
> uint32_t clip_mode;
> - uint32_t uniform_buffer_bound[6];
> + bool uniform_buffer_bound[6];
> struct nvc0_transform_feedback_state *tfb;
> bool seamless_cube_map;
> bool post_depth_coverage;
> };
>
> +struct nvc0_cb_binding {
> + uint64_t addr;
> + int size;
> +};
> +
> struct nvc0_screen {
> struct nouveau_screen base;
>
> @@ -114,6 +119,9 @@ struct nvc0_screen {
> bool mp_counters_enabled;
> } pm;
>
> + /* only maintained on Maxwell+ */
> + struct nvc0_cb_binding cb_bindings[5][16];
> +
> struct nouveau_object *eng3d; /* sqrt(1/2)|kepler> + sqrt(1/2)|fermi> */
> struct nouveau_object *eng2d;
> struct nouveau_object *m2mf;
> @@ -146,6 +154,9 @@ int nvc0_screen_compute_setup(struct nvc0_screen *, struct nouveau_pushbuf *);
>
> int nvc0_screen_resize_text_area(struct nvc0_screen *, uint64_t);
>
> +// 3D Only
> +void nvc0_screen_bind_cb_3d(struct nvc0_screen *, bool *, int, int, int, uint64_t);
> +
> static inline void
> nvc0_resource_fence(struct nv04_resource *res, uint32_t flags)
> {
> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
> index cc18f41c4b..bdfe3c4782 100644
> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
> @@ -565,9 +565,10 @@ nvc0_validate_rasterizer(struct nvc0_context *nvc0)
> static void
> nvc0_constbufs_validate(struct nvc0_context *nvc0)
> {
> - struct nouveau_pushbuf *push = nvc0->base.pushbuf;
> unsigned s;
>
> + bool can_serialize = true;
> +
> for (s = 0; s < 5; ++s) {
> while (nvc0->constbuf_dirty[s]) {
> int i = ffs(nvc0->constbuf_dirty[s]) - 1;
> @@ -581,14 +582,11 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
> assert(nvc0->constbuf[s][0].u.data);
>
> if (nvc0->state.uniform_buffer_bound[s] < size) {
uniform_buffer_bound is a bool now, so this will ~always be true...
> - nvc0->state.uniform_buffer_bound[s] = align(size, 0x100);
> -
> - BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
> - PUSH_DATA (push, nvc0->state.uniform_buffer_bound[s]);
> - PUSH_DATAh(push, bo->offset + base);
> - PUSH_DATA (push, bo->offset + base);
> - BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
> - PUSH_DATA (push, (0 << 4) | 1);
> + nvc0->state.uniform_buffer_bound[s] = 65536;
> +
> + nvc0_screen_bind_cb_3d(nvc0->screen, &can_serialize, s, i,
> + nvc0->state.uniform_buffer_bound[s],
> + bo->offset + base);
> }
> nvc0_cb_bo_push(&nvc0->base, bo, NV_VRAM_DOMAIN(&nvc0->screen->base),
> base, nvc0->state.uniform_buffer_bound[s],
> @@ -598,23 +596,20 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
> struct nv04_resource *res =
> nv04_resource(nvc0->constbuf[s][i].u.buf);
> if (res) {
> - BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
> - PUSH_DATA (push, nvc0->constbuf[s][i].size);
> - PUSH_DATAh(push, res->address + nvc0->constbuf[s][i].offset);
> - PUSH_DATA (push, res->address + nvc0->constbuf[s][i].offset);
> - BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
> - PUSH_DATA (push, (i << 4) | 1);
> + nvc0_screen_bind_cb_3d(nvc0->screen, &can_serialize, s, i,
> + nvc0->constbuf[s][i].size,
> + res->address + nvc0->constbuf[s][i].offset);
>
> BCTX_REFN(nvc0->bufctx_3d, 3D_CB(s, i), res, RD);
>
> nvc0->cb_dirty = 1; /* Force cache flush for UBO. */
> res->cb_bindings[s] |= 1 << i;
> - } else {
> - BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
> - PUSH_DATA (push, (i << 4) | 0);
> +
> + if (i == 0)
> + nvc0->state.uniform_buffer_bound[s] = 0;
> + } else if (i != 0) {
> + nvc0_screen_bind_cb_3d(nvc0->screen, &can_serialize, s, i, -1, 0);
> }
> - if (i == 0)
> - nvc0->state.uniform_buffer_bound[s] = 0;
> }
> }
> }
> @@ -721,6 +716,8 @@ nvc0_validate_driverconst(struct nvc0_context *nvc0)
> PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i));
> BEGIN_NVC0(push, NVC0_3D(CB_BIND(i)), 1);
> PUSH_DATA (push, (15 << 4) | 1);
> + nvc0_screen_bind_cb_3d(screen, NULL, i, 15, NVC0_CB_AUX_SIZE,
> + screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i));
> }
>
> nvc0->dirty_cp |= NVC0_NEW_CP_DRIVERCONST;
> --
> 2.14.4
>
More information about the mesa-dev
mailing list