static INLINE void nv50_stage_set_sampler_views(struct nv50_context *nv50, int s, unsigned nr, struct pipe_sampler_view **views) { unsigned i; assert(nr <= PIPE_MAX_SAMPLERS); for (i = 0; i < nr; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nv50->textures[s][i]); if (old) nv50_screen_tic_unlock(nv50->screen, old); pipe_sampler_view_reference(&nv50->textures[s][i], views[i]); } assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS); for (i = nr; i < nv50->num_textures[s]; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nv50->textures[s][i]); if (!old) continue; nv50_screen_tic_unlock(nv50->screen, old); pipe_sampler_view_reference(&nv50->textures[s][i], NULL); } nv50->num_textures[s] = nr; nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES); nv50->dirty |= NV50_NEW_TEXTURES; }
static void nvc0_stage_set_sampler_views_range(struct nvc0_context *nvc0, const unsigned s, unsigned start, unsigned nr, struct pipe_sampler_view **views) { struct nouveau_bufctx *bctx = (s == 5) ? nvc0->bufctx_cp : nvc0->bufctx_3d; const unsigned end = start + nr; const unsigned bin = (s == 5) ? NVC0_BIND_CP_TEX(0) : NVC0_BIND_3D_TEX(s, 0); int last_valid = -1; unsigned i; if (views) { for (i = start; i < end; ++i) { const unsigned p = i - start; if (views[p]) last_valid = i; if (views[p] == nvc0->textures[s][i]) continue; nvc0->textures_dirty[s] |= 1 << i; if (views[p] && views[p]->texture) { struct pipe_resource *res = views[p]->texture; if (res->target == PIPE_BUFFER && (res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)) nvc0->textures_coherent[s] |= 1 << i; else nvc0->textures_coherent[s] &= ~(1 << i); } else { nvc0->textures_coherent[s] &= ~(1 << i); } if (nvc0->textures[s][i]) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); nouveau_bufctx_reset(bctx, bin + i); nvc0_screen_tic_unlock(nvc0->screen, old); } pipe_sampler_view_reference(&nvc0->textures[s][i], views[p]); } } else { for (i = start; i < end; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); if (!old) continue; nvc0->textures_dirty[s] |= 1 << i; nvc0_screen_tic_unlock(nvc0->screen, old); pipe_sampler_view_reference(&nvc0->textures[s][i], NULL); nouveau_bufctx_reset(bctx, bin + i); } } if (nvc0->num_textures[s] <= end) { if (last_valid < 0) { for (i = start; i && !nvc0->textures[s][i - 1]; --i); nvc0->num_textures[s] = i; } else { nvc0->num_textures[s] = last_valid + 1; } } }
static inline void nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s, unsigned nr, struct pipe_sampler_view **views) { unsigned i; for (i = 0; i < nr; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); if (views[i] == nvc0->textures[s][i]) continue; nvc0->textures_dirty[s] |= 1 << i; if (old) { nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(s, i)); nvc0_screen_tic_unlock(nvc0->screen, old); } pipe_sampler_view_reference(&nvc0->textures[s][i], views[i]); } for (i = nr; i < nvc0->num_textures[s]; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); if (old) { nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(s, i)); nvc0_screen_tic_unlock(nvc0->screen, old); pipe_sampler_view_reference(&nvc0->textures[s][i], NULL); } } nvc0->num_textures[s] = nr; nvc0->dirty |= NVC0_NEW_TEXTURES; }
static INLINE void nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s, unsigned nr, struct pipe_sampler_view **views) { unsigned i; for (i = 0; i < nr; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); if (old) nvc0_screen_tic_unlock(nvc0->screen, old); pipe_sampler_view_reference(&nvc0->textures[s][i], views[i]); } for (i = nr; i < nvc0->num_textures[s]; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); if (!old) continue; nvc0_screen_tic_unlock(nvc0->screen, old); pipe_sampler_view_reference(&nvc0->textures[s][i], NULL); } nvc0->num_textures[s] = nr; nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_TEXTURES); nvc0->dirty |= NVC0_NEW_TEXTURES; }
/* NOTE: only called when not referenced anywhere, won't be bound */ static void nv50_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) { pipe_resource_reference(&view->texture, NULL); nv50_screen_tic_free(nv50_context(pipe)->screen, nv50_tic_entry(view)); FREE(nv50_tic_entry(view)); }
static inline void nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s, unsigned nr, struct pipe_sampler_view **views) { unsigned i; for (i = 0; i < nr; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); if (views[i] == nvc0->textures[s][i]) continue; nvc0->textures_dirty[s] |= 1 << i; if (views[i] && views[i]->texture) { struct pipe_resource *res = views[i]->texture; if (res->target == PIPE_BUFFER && (res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)) nvc0->textures_coherent[s] |= 1 << i; else nvc0->textures_coherent[s] &= ~(1 << i); } else { nvc0->textures_coherent[s] &= ~(1 << i); } if (old) { if (s == 5) nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i)); else nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i)); nvc0_screen_tic_unlock(nvc0->screen, old); } pipe_sampler_view_reference(&nvc0->textures[s][i], views[i]); } for (i = nr; i < nvc0->num_textures[s]; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]); if (old) { if (s == 5) nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i)); else nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i)); nvc0_screen_tic_unlock(nvc0->screen, old); pipe_sampler_view_reference(&nvc0->textures[s][i], NULL); } } nvc0->num_textures[s] = nr; }
static boolean nve4_validate_tic(struct nvc0_context *nvc0, unsigned s) { struct nouveau_bo *txc = nvc0->screen->txc; struct nouveau_pushbuf *push = nvc0->base.pushbuf; unsigned i; boolean need_flush = FALSE; for (i = 0; i < nvc0->num_textures[s]; ++i) { struct nv50_tic_entry *tic = nv50_tic_entry(nvc0->textures[s][i]); struct nv04_resource *res; const boolean dirty = !!(nvc0->textures_dirty[s] & (1 << i)); if (!tic) { nvc0->tex_handles[s][i] |= NVE4_TIC_ENTRY_INVALID; continue; } res = nv04_resource(tic->pipe.texture); if (tic->id < 0) { tic->id = nvc0_screen_tic_alloc(nvc0->screen, tic); PUSH_SPACE(push, 16); BEGIN_NVC0(push, NVE4_P2MF(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(LINE_LENGTH_IN), 2); PUSH_DATA (push, 32); PUSH_DATA (push, 1); BEGIN_1IC0(push, NVE4_P2MF(EXEC), 9); PUSH_DATA (push, 0x1001); PUSH_DATAp(push, &tic->tic[0], 8); need_flush = TRUE; } 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; nvc0->tex_handles[s][i] &= ~NVE4_TIC_ENTRY_INVALID; nvc0->tex_handles[s][i] |= tic->id; if (dirty) BCTX_REFN(nvc0->bufctx_3d, TEX(s, i), res, RD); } for (; i < nvc0->state.num_textures[s]; ++i) { nvc0->tex_handles[s][i] |= NVE4_TIC_ENTRY_INVALID; nvc0->textures_dirty[s] |= 1 << i; } nvc0->state.num_textures[s] = nvc0->num_textures[s]; return need_flush; }
static inline void nv50_stage_set_sampler_views(struct nv50_context *nv50, int s, unsigned nr, struct pipe_sampler_view **views) { unsigned i; assert(nr <= PIPE_MAX_SAMPLERS); for (i = 0; i < nr; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nv50->textures[s][i]); if (old) nv50_screen_tic_unlock(nv50->screen, old); if (views[i] && views[i]->texture) { struct pipe_resource *res = views[i]->texture; if (res->target == PIPE_BUFFER && (res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)) nv50->textures_coherent[s] |= 1 << i; else nv50->textures_coherent[s] &= ~(1 << i); } else { nv50->textures_coherent[s] &= ~(1 << i); } pipe_sampler_view_reference(&nv50->textures[s][i], views[i]); } assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS); for (i = nr; i < nv50->num_textures[s]; ++i) { struct nv50_tic_entry *old = nv50_tic_entry(nv50->textures[s][i]); if (!old) continue; nv50_screen_tic_unlock(nv50->screen, old); pipe_sampler_view_reference(&nv50->textures[s][i], NULL); } nv50->num_textures[s] = nr; nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_TEXTURES); nv50->dirty_3d |= NV50_NEW_3D_TEXTURES; }
static INLINE void nv50_blit_fixup_tic_entry(struct pipe_sampler_view *view) { struct nv50_tic_entry *ent = nv50_tic_entry(view); ent->tic[2] &= ~(1 << 31); /* scaled coordinates, ok with 3d textures ? */ /* magic: */ ent->tic[3] = 0x20000000; /* affects quality of near vertical edges in MS8 */ }
static bool nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s, unsigned start, unsigned nr, const struct pipe_image_view *pimages) { const unsigned end = start + nr; unsigned mask = 0; unsigned i; assert(s < 6); if (pimages) { for (i = start; i < end; ++i) { struct pipe_image_view *img = &nvc0->images[s][i]; const unsigned p = i - start; if (img->resource == pimages[p].resource && img->format == pimages[p].format && img->access == pimages[p].access) { if (img->resource == NULL) continue; if (img->resource->target == PIPE_BUFFER && img->u.buf.offset == pimages[p].u.buf.offset && img->u.buf.size == pimages[p].u.buf.size) continue; if (img->resource->target != PIPE_BUFFER && img->u.tex.first_layer == pimages[p].u.tex.first_layer && img->u.tex.last_layer == pimages[p].u.tex.last_layer && img->u.tex.level == pimages[p].u.tex.level) continue; } mask |= (1 << i); if (pimages[p].resource) nvc0->images_valid[s] |= (1 << i); else nvc0->images_valid[s] &= ~(1 << i); img->format = pimages[p].format; img->access = pimages[p].access; if (pimages[p].resource && pimages[p].resource->target == PIPE_BUFFER) img->u.buf = pimages[p].u.buf; else img->u.tex = pimages[p].u.tex; pipe_resource_reference( &img->resource, pimages[p].resource); if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) { if (nvc0->images_tic[s][i]) { struct nv50_tic_entry *old = nv50_tic_entry(nvc0->images_tic[s][i]); nvc0_screen_tic_unlock(nvc0->screen, old); pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL); } nvc0->images_tic[s][i] = gm107_create_texture_view_from_image(&nvc0->base.pipe, &pimages[p]); } } if (!mask) return false; } else { mask = ((1 << nr) - 1) << start; if (!(nvc0->images_valid[s] & mask)) return false; 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; if (s == 5) nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF); else nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF); return true; }
static boolean nvc0_validate_tic(struct nvc0_context *nvc0, int s) { uint32_t commands[32]; struct nouveau_pushbuf *push = nvc0->base.pushbuf; struct nouveau_bo *txc = nvc0->screen->txc; unsigned i; unsigned n = 0; boolean need_flush = FALSE; for (i = 0; i < nvc0->num_textures[s]; ++i) { struct nv50_tic_entry *tic = nv50_tic_entry(nvc0->textures[s][i]); struct nv04_resource *res; const boolean dirty = !!(nvc0->textures_dirty[s] & (1 << i)); if (!tic) { if (dirty) commands[n++] = (i << 1) | 0; continue; } res = nv04_resource(tic->pipe.texture); if (tic->id < 0) { tic->id = nvc0_screen_tic_alloc(nvc0->screen, tic); PUSH_SPACE(push, 17); BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2); PUSH_DATAh(push, txc->offset + (tic->id * 32)); PUSH_DATA (push, txc->offset + (tic->id * 32)); BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2); PUSH_DATA (push, 32); PUSH_DATA (push, 1); BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1); PUSH_DATA (push, 0x100111); BEGIN_NIC0(push, NVC0_M2MF(DATA), 8); PUSH_DATAp(push, &tic->tic[0], 8); need_flush = TRUE; } 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; if (!dirty) continue; commands[n++] = (tic->id << 9) | (i << 1) | 1; BCTX_REFN(nvc0->bufctx_3d, TEX(s, i), res, RD); } for (; i < nvc0->state.num_textures[s]; ++i) commands[n++] = (i << 1) | 0; nvc0->state.num_textures[s] = nvc0->num_textures[s]; if (n) { BEGIN_NIC0(push, NVC0_3D(BIND_TIC(s)), n); PUSH_DATAp(push, commands, n); } nvc0->textures_dirty[s] = 0; return need_flush; }
static boolean nv50_validate_tic(struct nv50_context *nv50, int s) { struct nouveau_pushbuf *push = nv50->base.pushbuf; struct nouveau_bo *txc = nv50->screen->txc; unsigned i; boolean need_flush = FALSE; assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS); for (i = 0; i < nv50->num_textures[s]; ++i) { struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); struct nv04_resource *res; if (!tic) { BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); PUSH_DATA (push, (i << 1) | 0); continue; } res = &nv50_miptree(tic->pipe.texture)->base; if (tic->id < 0) { tic->id = nv50_screen_tic_alloc(nv50->screen, tic); BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM); PUSH_DATA (push, 1); BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); PUSH_DATA (push, 262144); PUSH_DATA (push, 65536); PUSH_DATA (push, 1); PUSH_DATAh(push, txc->offset); PUSH_DATA (push, txc->offset); BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); PUSH_DATA (push, 0); PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM); BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); PUSH_DATA (push, 32); PUSH_DATA (push, 1); PUSH_DATA (push, 0); PUSH_DATA (push, 1); PUSH_DATA (push, 0); PUSH_DATA (push, 1); PUSH_DATA (push, 0); PUSH_DATA (push, tic->id * 32); PUSH_DATA (push, 0); PUSH_DATA (push, 0); BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8); PUSH_DATAp(push, &tic->tic[0], 8); need_flush = TRUE; } else if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 0x20); } nv50->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(nv50->bufctx_3d, TEXTURES, res, RD); BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1); } for (; i < nv50->state.num_textures[s]; ++i) { BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); PUSH_DATA (push, (i << 1) | 0); } if (nv50->num_textures[s]) { BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); PUSH_DATA (push, (NV50_CB_AUX_TEX_MS_OFFSET << (8 - 2)) | NV50_CB_AUX); BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nv50->num_textures[s] * 2); for (i = 0; i < nv50->num_textures[s]; i++) { struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); struct nv50_miptree *res; if (!tic) { PUSH_DATA (push, 0); PUSH_DATA (push, 0); continue; } res = nv50_miptree(tic->pipe.texture); PUSH_DATA (push, res->ms_x); PUSH_DATA (push, res->ms_y); } } nv50->state.num_textures[s] = nv50->num_textures[s]; return need_flush; }