[Mesa-dev] [PATCH RFC 2/8] nvc0: bind images for 3d/cp shaders on GM107+
Samuel Pitoiset
samuel.pitoiset at gmail.com
Mon Jul 18 21:23:17 UTC 2016
On 07/18/2016 11:13 PM, Ilia Mirkin wrote:
> On Mon, Jul 18, 2016 at 4:55 PM, Samuel Pitoiset
> <samuel.pitoiset at gmail.com> wrote:
>> On Maxwell, images binding is slightly different (and much better)
>> regarding Fermi and Kepler because a texture view needs to be uploaded
>> for each image and this is going to simplify the thing a lot.
>>
>> Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
>> ---
>> src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 5 +-
>> src/gallium/drivers/nouveau/nvc0/nvc0_context.h | 4 +
>> src/gallium/drivers/nouveau/nvc0/nvc0_state.c | 10 ++-
>> src/gallium/drivers/nouveau/nvc0/nvc0_tex.c | 110 ++++++++++++++++++++++--
>> src/gallium/drivers/nouveau/nvc0/nve4_compute.c | 91 ++++++++++++++++++--
>> 5 files changed, 202 insertions(+), 18 deletions(-)
>>
>> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
>> index 1137e6c..4bd240b 100644
>> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
>> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
>> @@ -161,8 +161,11 @@ nvc0_context_unreference_resources(struct nvc0_context *nvc0)
>> for (i = 0; i < NVC0_MAX_BUFFERS; ++i)
>> pipe_resource_reference(&nvc0->buffers[s][i].buffer, NULL);
>>
>> - for (i = 0; i < NVC0_MAX_IMAGES; ++i)
>> + for (i = 0; i < NVC0_MAX_IMAGES; ++i) {
>> pipe_resource_reference(&nvc0->images[s][i].resource, NULL);
>> + if (nvc0->screen->base.class_3d >= GM107_3D_CLASS)
>> + pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL);
>> + }
>> }
>>
>> for (s = 0; s < 2; ++s) {
>> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
>> index 4b73ec3..1d9fca1 100644
>> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
>> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
>> @@ -246,6 +246,7 @@ struct nvc0_context {
>> uint32_t buffers_valid[6];
>>
>> struct pipe_image_view images[6][NVC0_MAX_IMAGES];
>> + struct pipe_sampler_view *images_tic[6][NVC0_MAX_IMAGES]; /* GM107+ */
>> uint16_t images_dirty[6];
>> uint16_t images_valid[6];
>>
>> @@ -349,6 +350,9 @@ struct pipe_sampler_view *
>> nvc0_create_sampler_view(struct pipe_context *,
>> struct pipe_resource *,
>> const struct pipe_sampler_view *);
>> +struct pipe_sampler_view *
>> +gm107_create_texture_view_from_image(struct pipe_context *,
>> + struct pipe_image_view *);
>>
>> /* nvc0_transfer.c */
>> void
>> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
>> index 441cfc9..98becf4 100644
>> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
>> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
>> @@ -1303,8 +1303,16 @@ nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s,
>> mask = ((1 << nr) - 1) << start;
>> if (!(nvc0->images_valid[s] & mask))
>> return false;
>> - for (i = start; i < end; ++i)
>> + for (i = start; i < end; ++i) {
>> pipe_resource_reference(&nvc0->images[s][i].resource, NULL);
>> + if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) {
>> + struct nv50_tic_entry *old = nv50_tic_entry(nvc0->images_tic[s][i]);
>> + if (old) {
>> + nvc0_screen_tic_unlock(nvc0->screen, old);
>> + pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL);
>> + }
>> + }
>> + }
>> nvc0->images_valid[s] &= ~mask;
>> }
>> nvc0->images_dirty[s] |= mask;
>> diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
>> index 5f7bba8..efbaacf 100644
>> --- a/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
>> +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c
>> @@ -236,6 +236,38 @@ gm107_create_texture_view(struct pipe_context *pipe,
>> return &view->pipe;
>> }
>>
>> +struct pipe_sampler_view *
>> +gm107_create_texture_view_from_image(struct pipe_context *pipe,
>> + struct pipe_image_view *view)
>> +{
>> + struct nv04_resource *res = nv04_resource(view->resource);
>> + enum pipe_texture_target target = res->base.target;
>> + struct pipe_sampler_view templ = {};
>> + uint32_t flags = 0;
>> +
>> + if (target == PIPE_TEXTURE_CUBE || target == PIPE_TEXTURE_CUBE_ARRAY)
>> + target = PIPE_TEXTURE_2D_ARRAY;
>> +
>> + templ.format = view->format;
>> + templ.swizzle_r = PIPE_SWIZZLE_X;
>> + templ.swizzle_g = PIPE_SWIZZLE_Y;
>> + templ.swizzle_b = PIPE_SWIZZLE_Z;
>> + templ.swizzle_a = PIPE_SWIZZLE_W;
>> +
>> + if (target == PIPE_BUFFER) {
>> + templ.u.buf.first_element = view->u.buf.first_element;
>> + templ.u.buf.last_element = view->u.buf.last_element;
>> + } else {
>> + templ.u.tex.first_layer = view->u.tex.first_layer;
>> + templ.u.tex.last_layer = view->u.tex.last_layer;
>> + templ.u.tex.first_level = templ.u.tex.last_level = view->u.tex.level;
>> + }
>> +
>> + flags = res->base.last_level ? 0 : NV50_TEXVIEW_SCALED_COORDS;
>
> I think you just want 0 here, always.
I thought too, but this will hit the assert at nvc0_tex.c:134 for image
buffers. And this is loosely based on the blit code .
>
>> +
>> + return gm107_create_texture_view(pipe, &res->base, &templ, flags, target);
>
> I think you want to call the nvc0_foo version of it, that will
> dispatch to the gm107 function when nvc0->tic.maxwell is set. That way
> we can still test with the old descriptor types on GM10x. (GM20x+
> doesn't even support the old ones.)
Yeah.
>
>> +}
>> +
>> static struct pipe_sampler_view *
>> gf100_create_texture_view(struct pipe_context *pipe,
>> struct pipe_resource *texture,
>> @@ -1099,6 +1131,66 @@ nvc0_update_surface_bindings(struct nvc0_context *nvc0)
>> nvc0->images_dirty[5] |= nvc0->images_valid[5];
>> }
>>
>> +static void
>> +gm107_validate_surfaces(struct nvc0_context *nvc0,
>> + struct pipe_image_view *view, int stage, int slot)
>> +{
>> + struct nv04_resource *res = nv04_resource(view->resource);
>> + struct nouveau_pushbuf *push = nvc0->base.pushbuf;
>> + struct pipe_context *pipe = &nvc0->base.pipe;
>> + struct nvc0_screen *screen = nvc0->screen;
>> + struct nouveau_bo *txc = nvc0->screen->txc;
>> + struct nv50_tic_entry *tic;
>> +
>> + if (nvc0->images_tic[stage][slot])
>> + pipe->sampler_view_destroy(pipe, nvc0->images_tic[stage][slot]);
>
> Huh? Why are you doing this at validate time? You should be creating a
> new sampler view at set time.
Probably better to do that at bind time yeah.
>
>> +
>> + nvc0->images_tic[stage][slot] =
>> + gm107_create_texture_view_from_image(pipe, view);
>> + tic = nv50_tic_entry(nvc0->images_tic[stage][slot]);
>> +
>> + res = nv04_resource(tic->pipe.texture);
>> + nvc0_update_tic(nvc0, tic, res);
>> +
>> + if (tic->id < 0) {
>> + tic->id = nvc0_screen_tic_alloc(nvc0->screen, tic);
>> +
>> + /* upload the texture view */
>> + PUSH_SPACE(push, 16);
>> + BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH), 2);
>> + PUSH_DATAh(push, txc->offset + (tic->id * 32));
>> + PUSH_DATA (push, txc->offset + (tic->id * 32));
>> + BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_LINE_LENGTH_IN), 2);
>> + PUSH_DATA (push, 32);
>> + PUSH_DATA (push, 1);
>> + BEGIN_1IC0(push, NVE4_P2MF(UPLOAD_EXEC), 9);
>> + PUSH_DATA (push, 0x1001);
>> + PUSH_DATAp(push, &tic->tic[0], 8);
>> +
>> + BEGIN_NVC0(push, NVC0_3D(TIC_FLUSH), 1);
>> + PUSH_DATA (push, 0);
>> + } else
>> + if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
>> + BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1);
>> + PUSH_DATA (push, (tic->id << 4) | 1);
>> + }
>> + nvc0->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
>> +
>> + res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING;
>> + res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
>> +
>> + BCTX_REFN(nvc0->bufctx_3d, 3D_SUF, res, RD);
>> +
>> + /* upload the texture handle */
>> + 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(stage));
>> + PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(stage));
>> + BEGIN_NVC0(push, NVC0_3D(CB_POS), 2);
>> + PUSH_DATA (push, NVC0_CB_AUX_TEX_INFO(slot + 32));
>> + PUSH_DATA (push, tic->id);
>> +}
>> +
>> static inline void
>> nve4_update_surface_bindings(struct nvc0_context *nvc0)
>> {
>> @@ -1110,15 +1202,16 @@ nve4_update_surface_bindings(struct nvc0_context *nvc0)
>> if (!nvc0->images_dirty[s])
>> continue;
>>
>> - 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(s));
>> - PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s));
>> - BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 16 * NVC0_MAX_IMAGES);
>> - PUSH_DATA (push, NVC0_CB_AUX_SU_INFO(0));
>> -
>> for (i = 0; i < NVC0_MAX_IMAGES; ++i) {
>> struct pipe_image_view *view = &nvc0->images[s][i];
>> +
>> + 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(s));
>> + PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s));
>> + BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 16);
>> + PUSH_DATA (push, NVC0_CB_AUX_SU_INFO(i));
>> +
>> if (view->resource) {
>> struct nv04_resource *res = nv04_resource(view->resource);
>>
>> @@ -1129,6 +1222,9 @@ nve4_update_surface_bindings(struct nvc0_context *nvc0)
>>
>> nve4_set_surface_info(push, view, nvc0);
>> BCTX_REFN(nvc0->bufctx_3d, 3D_SUF, res, RDWR);
>> +
>> + if (nvc0->screen->base.class_3d >= GM107_3D_CLASS)
>> + gm107_validate_surfaces(nvc0, view, s, i);
>> } else {
>> for (j = 0; j < 16; j++)
>> PUSH_DATA(push, 0);
>> diff --git a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c
>> index 27301a1..3d32dfd 100644
>> --- a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c
>> +++ b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c
>> @@ -188,29 +188,99 @@ nve4_screen_compute_setup(struct nvc0_screen *screen,
>> }
>>
>> static void
>> -nve4_compute_validate_surfaces(struct nvc0_context *nvc0)
>> +gm107_compute_validate_surfaces(struct nvc0_context *nvc0,
>> + struct pipe_image_view *view, int slot)
>> {
>> + struct nv04_resource *res = nv04_resource(view->resource);
>> struct nouveau_pushbuf *push = nvc0->base.pushbuf;
>> + struct pipe_context *pipe = &nvc0->base.pipe;
>> + struct nvc0_screen *screen = nvc0->screen;
>> + struct nouveau_bo *txc = nvc0->screen->txc;
>> + struct nv50_tic_entry *tic;
>> uint64_t address;
>> const int s = 5;
>> - int i, j;
>>
>> - if (!nvc0->images_dirty[s])
>> - return;
>> + if (nvc0->images_tic[s][slot])
>> + pipe->sampler_view_destroy(pipe, nvc0->images_tic[s][slot]);
>>
>> - address = nvc0->screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s);
>> + nvc0->images_tic[s][slot] =
>> + gm107_create_texture_view_from_image(pipe, view);
>> + tic = nv50_tic_entry(nvc0->images_tic[s][slot]);
>> +
>> + res = nv04_resource(tic->pipe.texture);
>> + nvc0_update_tic(nvc0, tic, res);
>> +
>> + if (tic->id < 0) {
>> + tic->id = nvc0_screen_tic_alloc(nvc0->screen, tic);
>> +
>> + /* upload the texture view */
>> + PUSH_SPACE(push, 16);
>> + BEGIN_NVC0(push, NVE4_CP(UPLOAD_DST_ADDRESS_HIGH), 2);
>> + PUSH_DATAh(push, txc->offset + (tic->id * 32));
>> + PUSH_DATA (push, txc->offset + (tic->id * 32));
>> + BEGIN_NVC0(push, NVE4_CP(UPLOAD_LINE_LENGTH_IN), 2);
>> + PUSH_DATA (push, 32);
>> + PUSH_DATA (push, 1);
>> + BEGIN_1IC0(push, NVE4_CP(UPLOAD_EXEC), 9);
>> + PUSH_DATA (push, NVE4_COMPUTE_UPLOAD_EXEC_LINEAR | (0x20 << 1));
>> + PUSH_DATAp(push, &tic->tic[0], 8);
>> +
>> + BEGIN_NIC0(push, NVE4_CP(TIC_FLUSH), 1);
>> + PUSH_DATA (push, (tic->id << 4) | 1);
>> + } else
>> + if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
>> + BEGIN_NIC0(push, NVE4_CP(TEX_CACHE_CTL), 1);
>> + PUSH_DATA (push, (tic->id << 4) | 1);
>> + }
>> + nvc0->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
>> +
>> + res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING;
>> + res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
>> +
>> + BCTX_REFN(nvc0->bufctx_cp, CP_SUF, res, RD);
>>
>> + address = screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s);
>> +
>> + /* upload the texture handle */
>> BEGIN_NVC0(push, NVE4_CP(UPLOAD_DST_ADDRESS_HIGH), 2);
>> - PUSH_DATAh(push, address + NVC0_CB_AUX_SU_INFO(0));
>> - PUSH_DATA (push, address + NVC0_CB_AUX_SU_INFO(0));
>> + PUSH_DATAh(push, address + NVC0_CB_AUX_TEX_INFO(slot + 32));
>> + PUSH_DATA (push, address + NVC0_CB_AUX_TEX_INFO(slot + 32));
>> BEGIN_NVC0(push, NVE4_CP(UPLOAD_LINE_LENGTH_IN), 2);
>> - PUSH_DATA (push, 16 * NVC0_MAX_IMAGES * 4);
>> + PUSH_DATA (push, 4);
>> PUSH_DATA (push, 0x1);
>> - BEGIN_1IC0(push, NVE4_CP(UPLOAD_EXEC), 1 + 16 * NVC0_MAX_IMAGES);
>> + BEGIN_1IC0(push, NVE4_CP(UPLOAD_EXEC), 2);
>> PUSH_DATA (push, NVE4_COMPUTE_UPLOAD_EXEC_LINEAR | (0x20 << 1));
>> + PUSH_DATA (push, tic->id);
>> +
>> + BEGIN_NVC0(push, NVE4_CP(FLUSH), 1);
>> + PUSH_DATA (push, NVE4_COMPUTE_FLUSH_CB);
>> +}
>> +
>> +static void
>> +nve4_compute_validate_surfaces(struct nvc0_context *nvc0)
>> +{
>> + struct nouveau_pushbuf *push = nvc0->base.pushbuf;
>> + uint64_t address;
>> + const int s = 5;
>> + int i, j;
>> +
>> + if (!nvc0->images_dirty[s])
>> + return;
>> +
>> + address = nvc0->screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s);
>>
>> for (i = 0; i < NVC0_MAX_IMAGES; ++i) {
>> struct pipe_image_view *view = &nvc0->images[s][i];
>> +
>> + BEGIN_NVC0(push, NVE4_CP(UPLOAD_DST_ADDRESS_HIGH), 2);
>> + PUSH_DATAh(push, address + NVC0_CB_AUX_SU_INFO(i));
>> + PUSH_DATA (push, address + NVC0_CB_AUX_SU_INFO(i));
>> + BEGIN_NVC0(push, NVE4_CP(UPLOAD_LINE_LENGTH_IN), 2);
>> + PUSH_DATA (push, 16 * 4);
>> + PUSH_DATA (push, 0x1);
>> + BEGIN_1IC0(push, NVE4_CP(UPLOAD_EXEC), 1 + 16);
>> + PUSH_DATA (push, NVE4_COMPUTE_UPLOAD_EXEC_LINEAR | (0x20 << 1));
>> +
>> if (view->resource) {
>> struct nv04_resource *res = nv04_resource(view->resource);
>>
>> @@ -221,6 +291,9 @@ nve4_compute_validate_surfaces(struct nvc0_context *nvc0)
>>
>> nve4_set_surface_info(push, view, nvc0);
>> BCTX_REFN(nvc0->bufctx_cp, CP_SUF, res, RDWR);
>> +
>> + if (nvc0->screen->base.class_3d >= GM107_3D_CLASS)
>> + gm107_compute_validate_surfaces(nvc0, view, i);
>> } else {
>> for (j = 0; j < 16; j++)
>> PUSH_DATA(push, 0);
>> --
>> 2.9.0
>>
>> _______________________________________________
>> mesa-dev mailing list
>> mesa-dev at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list