[Mesa-dev] [PATCH 2/2] nvc0: add support for bindless on maxwell+
Samuel Pitoiset
samuel.pitoiset at gmail.com
Sat Feb 10 17:37:31 UTC 2018
On 02/10/2018 06:12 AM, Ilia Mirkin wrote:
> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
> ---
>
> Tested on GM107 with DOW3 and DiRT Rally (in bindless mode). Seems to
> work about as well as on Kepler, except I got a few ltc errors in DiRT
> Rally. Unclear if it's related to this patch though. Could be a missing
> flush somewhere.
>
> docs/relnotes/18.1.0.html | 1 +
> .../nouveau/codegen/nv50_ir_lowering_nvc0.cpp | 32 ++++++--
> src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 3 +-
> src/gallium/drivers/nouveau/nvc0/nvc0_tex.c | 96 +++++++++++++++++++++-
> 4 files changed, 118 insertions(+), 14 deletions(-)
>
> diff --git a/docs/relnotes/18.1.0.html b/docs/relnotes/18.1.0.html
> index b8a0cd0d02c..93cf1f2b4ff 100644
> --- a/docs/relnotes/18.1.0.html
> +++ b/docs/relnotes/18.1.0.html
> @@ -44,6 +44,7 @@ Note: some of the new features are only available with certain drivers.
> </p>
>
> <ul>
> +<li>GL_ARB_bindless_texture on nvc0/maxwell+</li>
> <li>GL_EXT_semaphore on radeonsi</li>
> <li>GL_EXT_semaphore_fd on radeonsi</li>
> </ul>
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
> index ddcae1e5a51..65c5bd7810b 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nvc0.cpp
> @@ -2400,6 +2400,7 @@ NVC0LoweringPass::processSurfaceCoordsGM107(TexInstruction *su)
> const int dim = su->tex.target.getDim();
> const int arg = dim + (su->tex.target.isArray() || su->tex.target.isCube());
> Value *ind = su->getIndirectR();
> + Value *handle;
> int pos = 0;
>
> bld.setPosition(su, false);
> @@ -2416,7 +2417,16 @@ NVC0LoweringPass::processSurfaceCoordsGM107(TexInstruction *su)
> assert(pos == 0);
> break;
> }
> - su->setSrc(arg + pos, loadTexHandle(ind, slot + 32));
> + if (su->tex.bindless)
> + handle = ind;
> + else
> + handle = loadTexHandle(ind, slot + 32);
> + su->setSrc(arg + pos, handle);
> +
> + // The address check doesn't make sense here. The format check could make
> + // sense but it's a bit of a pain.
> + if (su->tex.bindless)
> + return;
>
> // prevent read fault when the image is not actually bound
> CmpInstruction *pred =
> @@ -2450,18 +2460,22 @@ NVC0LoweringPass::handleSurfaceOpGM107(TexInstruction *su)
> Value *def = su->getDef(0);
>
> su->op = OP_SUREDB;
> - su->setDef(0, bld.getSSA());
>
> - bld.setPosition(su, true);
> + // There may not be a predicate in the bindless case.
> + if (su->getPredicate()) {
> + su->setDef(0, bld.getSSA());
>
> - // make sure to initialize dst value when the atomic operation is not
> - // performed
> - Instruction *mov = bld.mkMov(bld.getSSA(), bld.loadImm(NULL, 0));
> + bld.setPosition(su, true);
>
> - assert(su->cc == CC_NOT_P);
> - mov->setPredicate(CC_P, su->getPredicate());
> + // make sure to initialize dst value when the atomic operation is not
> + // performed
> + Instruction *mov = bld.mkMov(bld.getSSA(), bld.loadImm(NULL, 0));
> +
> + assert(su->cc == CC_NOT_P);
> + mov->setPredicate(CC_P, su->getPredicate());
>
> - bld.mkOp2(OP_UNION, TYPE_U32, def, su->getDef(0), mov->getDef(0));
> + bld.mkOp2(OP_UNION, TYPE_U32, def, su->getDef(0), mov->getDef(0));
> + }
> }
> }
>
> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
> index 7ba8086a533..b3d7768aed7 100644
> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
> @@ -266,9 +266,8 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
> return class_3d >= GM200_3D_CLASS;
> case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
> case PIPE_CAP_TGSI_BALLOT:
> - return class_3d >= NVE4_3D_CLASS;
> case PIPE_CAP_BINDLESS_TEXTURE:
> - return class_3d >= NVE4_3D_CLASS && class_3d < GM107_3D_CLASS;
> + return class_3d >= NVE4_3D_CLASS;
>
> /* unsupported caps */
> case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
> index 9e391fe1acf..ce58cced916 100644
> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
> @@ -1386,15 +1386,105 @@ nve4_make_image_handle_resident(struct pipe_context *pipe, uint64_t handle,
> }
> }
>
> +static uint64_t
> +gm107_create_image_handle(struct pipe_context *pipe,
> + const struct pipe_image_view *view)
> +{
> + /* GM107+ use TIC handles to reference images. As such, image handles are
> + * just the TIC id.
> + */
> + struct nvc0_context *nvc0 = nvc0_context(pipe);
> + struct nouveau_pushbuf *push = nvc0->base.pushbuf;
> + struct pipe_sampler_view *sview =
> + gm107_create_texture_view_from_image(pipe, view);
> + struct nv50_tic_entry *tic = nv50_tic_entry(sview);
> +
> + if (tic == NULL)
> + goto fail;
> +
> + tic->bindless = 1;
> + tic->id = nvc0_screen_tic_alloc(nvc0->screen, tic);
> + if (tic->id < 0)
> + goto fail;
> +
> + nve4_p2mf_push_linear(&nvc0->base, nvc0->screen->txc, tic->id * 32,
> + NV_VRAM_DOMAIN(&nvc0->screen->base), 32,
> + tic->tic);
> +
> + IMMED_NVC0(push, NVC0_3D(TIC_FLUSH), 0);
> +
> + nvc0->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
> +
> + return 0x100000000ULL | tic->id;
> +
> +fail:
> + if (tic)
> + FREE(tic);
Do we really need the conditional here, I don't think but your call.
> + return 0;
> +}
> +
> +static void
> +gm107_delete_image_handle(struct pipe_context *pipe, uint64_t handle)
> +{
> + struct nvc0_context *nvc0 = nvc0_context(pipe);
> + int tic = handle & NVE4_TIC_ENTRY_INVALID;
> + struct nv50_tic_entry *entry = nvc0->screen->tic.entries[tic];
> + struct pipe_sampler_view *view = &entry->pipe;
> + assert(entry->bindless == 1);
> + assert(!view_bound(nvc0, view));
> + entry->bindless = 0;
> + nvc0_screen_tic_unlock(nvc0->screen, entry);
> + pipe_sampler_view_reference(&view, NULL);
> +}
> +
> +static void
> +gm107_make_image_handle_resident(struct pipe_context *pipe, uint64_t handle,
> + unsigned access, bool resident)
> +{
> + struct nvc0_context *nvc0 = nvc0_context(pipe);
> +
> + if (resident) {
> + struct nvc0_resident *res = calloc(1, sizeof(struct nvc0_resident));
> + struct nv50_tic_entry *tic =
> + nvc0->screen->tic.entries[handle & NVE4_TIC_ENTRY_INVALID];
> + assert(tic);
> + assert(tic->bindless);
> +
> + res->handle = handle;
> + res->buf = nv04_resource(tic->pipe.texture);
> + res->flags = (access & 3) << 8;
(access & 3) looks useless, gallium should correctly set that flag,
maybe add an assertion instead?
Nice work, looks good to me!
> + if (res->buf->base.target == PIPE_BUFFER &&
> + access & PIPE_IMAGE_ACCESS_WRITE)
> + util_range_add(&res->buf->valid_buffer_range,
> + tic->pipe.u.buf.offset,
> + tic->pipe.u.buf.offset + tic->pipe.u.buf.size);
> + list_add(&res->list, &nvc0->img_head);
> + } else {
> + list_for_each_entry_safe(struct nvc0_resident, pos, &nvc0->img_head, list) {
> + if (pos->handle == handle) {
> + list_del(&pos->list);
> + free(pos);
> + break;
> + }
> + }
> + }
> +}
> +
> void
> nvc0_init_bindless_functions(struct pipe_context *pipe) {
> pipe->create_texture_handle = nve4_create_texture_handle;
> pipe->delete_texture_handle = nve4_delete_texture_handle;
> pipe->make_texture_handle_resident = nve4_make_texture_handle_resident;
>
> - pipe->create_image_handle = nve4_create_image_handle;
> - pipe->delete_image_handle = nve4_delete_image_handle;
> - pipe->make_image_handle_resident = nve4_make_image_handle_resident;
> + if (nvc0_context(pipe)->screen->base.class_3d < GM107_3D_CLASS) {
> + pipe->create_image_handle = nve4_create_image_handle;
> + pipe->delete_image_handle = nve4_delete_image_handle;
> + pipe->make_image_handle_resident = nve4_make_image_handle_resident;
> + } else {
> + pipe->create_image_handle = gm107_create_image_handle;
> + pipe->delete_image_handle = gm107_delete_image_handle;
> + pipe->make_image_handle_resident = gm107_make_image_handle_resident;
> + }
> }
>
>
>
More information about the mesa-dev
mailing list