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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user