From 572fba95e4cd85aebdde9bd757c17f719af2af04 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Oct 2014 22:14:03 -0700 Subject: vc4: Add support for rebasing texture levels so firstlevel == 0. GLES2 doesn't have GL_TEXTURE_BASE_LEVEL, so the hardware doesn't. Fixes piglit levelclamp, tex-miplevel-selection, and texture-storage/2D mipmap rendering. --- src/gallium/drivers/vc4/vc4_context.c | 6 ++++++ src/gallium/drivers/vc4/vc4_program.c | 3 ++- src/gallium/drivers/vc4/vc4_resource.c | 37 +++++++++++++++++++++++++++++++++- src/gallium/drivers/vc4/vc4_resource.h | 14 +++++++++++++ src/gallium/drivers/vc4/vc4_state.c | 26 +++++++++++++++++++++++- 5 files changed, 83 insertions(+), 3 deletions(-) (limited to 'src/gallium') diff --git a/src/gallium/drivers/vc4/vc4_context.c b/src/gallium/drivers/vc4/vc4_context.c index cc57486e103..87f025142ce 100644 --- a/src/gallium/drivers/vc4/vc4_context.c +++ b/src/gallium/drivers/vc4/vc4_context.c @@ -253,6 +253,12 @@ vc4_setup_rcl(struct vc4_context *vc4) assert(!coords_emitted); } } + + if (vc4->resolve & PIPE_CLEAR_COLOR0) + ctex->writes++; + + if (vc4->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) + ztex->writes++; } void diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index 66dff974a71..7a2a9756a59 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -2265,7 +2265,8 @@ write_texture_p0(struct vc4_context *vc4, cl_reloc(vc4, &vc4->uniforms, rsc->bo, VC4_SET_FIELD(rsc->slices[0].offset >> 12, VC4_TEX_P0_OFFSET) | - VC4_SET_FIELD(texture->u.tex.last_level, VC4_TEX_P0_MIPLVLS) | + VC4_SET_FIELD(texture->u.tex.last_level - + texture->u.tex.first_level, VC4_TEX_P0_MIPLVLS) | VC4_SET_FIELD(texture->target == PIPE_TEXTURE_CUBE, VC4_TEX_P0_CMMODE) | VC4_SET_FIELD(rsc->vc4_format & 7, VC4_TEX_P0_TYPE)); diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c index 7006af3d8ff..803d3575f09 100644 --- a/src/gallium/drivers/vc4/vc4_resource.c +++ b/src/gallium/drivers/vc4/vc4_resource.c @@ -83,6 +83,9 @@ vc4_resource_transfer_map(struct pipe_context *pctx, if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) vc4_flush_for_bo(pctx, rsc->bo); + if (usage & PIPE_TRANSFER_WRITE) + rsc->writes++; + trans = util_slab_alloc(&vc4->transfer_pool); if (!trans) return NULL; @@ -168,6 +171,7 @@ vc4_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc) { struct vc4_resource *rsc = vc4_resource(prsc); + pipe_resource_reference(&rsc->shadow_parent, NULL); vc4_bo_unreference(&rsc->bo); free(rsc); } @@ -297,7 +301,7 @@ get_resource_texture_format(struct pipe_resource *prsc) return format; } -static struct pipe_resource * +struct pipe_resource * vc4_resource_create(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) { @@ -477,6 +481,37 @@ vc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) render_blit(pctx, &info); } +void +vc4_update_shadow_baselevel_texture(struct pipe_context *pctx, + struct pipe_sampler_view *view) +{ + struct vc4_resource *shadow = vc4_resource(view->texture); + struct vc4_resource *orig = vc4_resource(shadow->shadow_parent); + assert(orig); + + if (shadow->writes == orig->writes) + return; + + for (int i = 0; i <= shadow->base.b.last_level; i++) { + struct pipe_box box = { + .x = 0, + .y = 0, + .z = 0, + .width = u_minify(shadow->base.b.width0, i), + .height = u_minify(shadow->base.b.height0, i), + .depth = 1, + }; + + util_resource_copy_region(pctx, + &shadow->base.b, i, 0, 0, 0, + &orig->base.b, + view->u.tex.first_level + i, + &box); + } + + shadow->writes = orig->writes; +} + void vc4_resource_screen_init(struct pipe_screen *pscreen) { diff --git a/src/gallium/drivers/vc4/vc4_resource.h b/src/gallium/drivers/vc4/vc4_resource.h index 01f481d15c4..7cc16a4540b 100644 --- a/src/gallium/drivers/vc4/vc4_resource.h +++ b/src/gallium/drivers/vc4/vc4_resource.h @@ -61,6 +61,16 @@ struct vc4_resource { bool tiled; /** One of VC4_TEXTURE_TYPE_* */ enum vc4_texture_data_type vc4_format; + + /** + * Number of times the resource has been written to. + * + * This is used to track when we need to update this shadow resource + * from its parent in the case of GL_TEXTURE_BASE_LEVEL (which we + * can't support in hardware). + */ + uint64_t writes; + struct pipe_resource *shadow_parent; }; static INLINE struct vc4_resource * @@ -83,5 +93,9 @@ vc4_transfer(struct pipe_transfer *ptrans) void vc4_resource_screen_init(struct pipe_screen *pscreen); void vc4_resource_context_init(struct pipe_context *pctx); +struct pipe_resource *vc4_resource_create(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl); +void vc4_update_shadow_baselevel_texture(struct pipe_context *pctx, + struct pipe_sampler_view *view); #endif /* VC4_RESOURCE_H */ diff --git a/src/gallium/drivers/vc4/vc4_state.c b/src/gallium/drivers/vc4/vc4_state.c index 099006b3e57..d3219b39d61 100644 --- a/src/gallium/drivers/vc4/vc4_state.c +++ b/src/gallium/drivers/vc4/vc4_state.c @@ -483,7 +483,28 @@ vc4_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, return NULL; *so = *cso; + pipe_reference(NULL, &prsc->reference); + + /* There is no hardware level clamping, and the start address of a + * texture may be misaligned, so in that case we have to copy to a + * temporary. + */ + if (so->u.tex.first_level) { + struct vc4_resource *shadow_parent = vc4_resource(prsc); + struct pipe_resource tmpl = shadow_parent->base.b; + struct vc4_resource *clone; + + tmpl.width0 = u_minify(tmpl.width0, so->u.tex.first_level); + tmpl.height0 = u_minify(tmpl.height0, so->u.tex.first_level); + tmpl.last_level = so->u.tex.last_level - so->u.tex.first_level; + + prsc = vc4_resource_create(pctx->screen, &tmpl); + clone = vc4_resource(prsc); + clone->shadow_parent = &shadow_parent->base.b; + /* Flag it as needing update of the contents from the parent. */ + clone->writes = shadow_parent->writes - 1; + } so->texture = prsc; so->reference.count = 1; so->context = pctx; @@ -514,8 +535,11 @@ vc4_set_sampler_views(struct pipe_context *pctx, unsigned shader, vc4->dirty |= VC4_DIRTY_TEXSTATE; for (i = 0; i < nr; i++) { - if (views[i]) + if (views[i]) { new_nr = i + 1; + if (views[i]->u.tex.first_level != 0) + vc4_update_shadow_baselevel_texture(pctx, views[i]); + } pipe_sampler_view_reference(&stage_tex->textures[i], views[i]); stage_tex->dirty_samplers |= (1 << i); } -- cgit v1.2.3