assert(!coords_emitted);
}
}
+
+ if (vc4->resolve & PIPE_CLEAR_COLOR0)
+ ctex->writes++;
+
+ if (vc4->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))
+ ztex->writes++;
}
void
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));
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;
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);
}
return format;
}
-static struct pipe_resource *
+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)
+{
+ 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)
{
pscreen->resource_create = vc4_resource_create;
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 *
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 */
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;
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);
}