vc4: Add support for rebasing texture levels so firstlevel == 0.
[mesa.git] / src / gallium / drivers / vc4 / vc4_resource.c
index 3048b23eec3629d0514675faae0d769b69291653..803d3575f099eb8a8de3e3f89472852c5a0eed1a 100644 (file)
@@ -45,7 +45,8 @@ vc4_resource_transfer_unmap(struct pipe_context *pctx,
 
         if (trans->map) {
                 if (ptrans->usage & PIPE_TRANSFER_WRITE) {
-                        vc4_store_tiled_image(rsc->bo->map + slice->offset,
+                        vc4_store_tiled_image(rsc->bo->map + slice->offset +
+                                              ptrans->box.z * rsc->cube_map_stride,
                                               slice->stride,
                                               trans->map, ptrans->stride,
                                               slice->tiling, rsc->cpp,
@@ -73,15 +74,23 @@ vc4_resource_transfer_map(struct pipe_context *pctx,
         enum pipe_format format = prsc->format;
         char *buf;
 
-        vc4_flush_for_bo(pctx, rsc->bo);
+        if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
+                uint32_t size = rsc->bo->size;
+                vc4_bo_unreference(&rsc->bo);
+                rsc->bo = vc4_bo_alloc(vc4->screen, size, "resource");
+        }
+
+        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;
 
-        /* XXX: Handle DISCARD_WHOLE_RESOURCE, DONTBLOCK, UNSYNCHRONIZED,
-         * DISCARD_WHOLE_RESOURCE, PERSISTENT, COHERENT.
-         */
+        /* XXX: Handle DONTBLOCK, DISCARD_RANGE, PERSISTENT, COHERENT. */
 
         /* util_slab_alloc() doesn't zero: */
         memset(trans, 0, sizeof(*trans));
@@ -132,7 +141,8 @@ vc4_resource_transfer_map(struct pipe_context *pctx,
                 trans->map = malloc(ptrans->stride * ptrans->box.height);
                 if (usage & PIPE_TRANSFER_READ) {
                         vc4_load_tiled_image(trans->map, ptrans->stride,
-                                             buf + slice->offset,
+                                             buf + slice->offset +
+                                             box->z * rsc->cube_map_stride,
                                              slice->stride,
                                              slice->tiling, rsc->cpp,
                                              &ptrans->box);
@@ -147,7 +157,7 @@ vc4_resource_transfer_map(struct pipe_context *pctx,
                 return buf + slice->offset +
                         box->y / util_format_get_blockheight(format) * ptrans->stride +
                         box->x / util_format_get_blockwidth(format) * rsc->cpp +
-                        box->z * slice->size0;
+                        box->z * rsc->cube_map_stride;
         }
 
 
@@ -161,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);
 }
@@ -191,15 +202,23 @@ vc4_setup_slices(struct vc4_resource *rsc)
         struct pipe_resource *prsc = &rsc->base.b;
         uint32_t width = prsc->width0;
         uint32_t height = prsc->height0;
-        uint32_t depth = prsc->depth0;
+        uint32_t pot_width = util_next_power_of_two(width);
+        uint32_t pot_height = util_next_power_of_two(height);
         uint32_t offset = 0;
         uint32_t utile_w = vc4_utile_width(rsc->cpp);
         uint32_t utile_h = vc4_utile_height(rsc->cpp);
 
         for (int i = prsc->last_level; i >= 0; i--) {
                 struct vc4_resource_slice *slice = &rsc->slices[i];
-                uint32_t level_width = u_minify(width, i);
-                uint32_t level_height = u_minify(height, i);
+
+                uint32_t level_width, level_height;
+                if (i == 0) {
+                        level_width = width;
+                        level_height = height;
+                } else {
+                        level_width = u_minify(pot_width, i);
+                        level_height = u_minify(pot_height, i);
+                }
 
                 if (rsc->tiled == VC4_TILING_FORMAT_LINEAR) {
                         slice->tiling = VC4_TILING_FORMAT_LINEAR;
@@ -221,12 +240,9 @@ vc4_setup_slices(struct vc4_resource *rsc)
 
                 slice->offset = offset;
                 slice->stride = level_width * rsc->cpp;
-                slice->size0 = level_height * slice->stride;
+                slice->size = level_height * slice->stride;
 
-                /* Note, since we have cubes but no 3D, depth is invariant
-                 * with miplevel.
-                 */
-                offset += slice->size0 * depth;
+                offset += slice->size;
         }
 
         /* The texture base pointer that has to point to level 0 doesn't have
@@ -239,6 +255,14 @@ vc4_setup_slices(struct vc4_resource *rsc)
                 for (int i = 0; i <= prsc->last_level; i++)
                         rsc->slices[i].offset += page_align_offset;
         }
+
+        /* Cube map faces appear as whole miptrees at a page-aligned offset
+         * from the first face's miptree.
+         */
+        if (prsc->target == PIPE_TEXTURE_CUBE) {
+                rsc->cube_map_stride = align(rsc->slices[0].offset +
+                                             rsc->slices[0].size, 4096);
+        }
 }
 
 static struct vc4_resource *
@@ -277,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)
 {
@@ -301,7 +325,8 @@ vc4_resource_create(struct pipe_screen *pscreen,
 
         rsc->bo = vc4_bo_alloc(vc4_screen(pscreen),
                                rsc->slices[0].offset +
-                               rsc->slices[0].size0 * prsc->depth0,
+                               rsc->slices[0].size +
+                               rsc->cube_map_stride * (prsc->array_size - 1),
                                "resource");
         if (!rsc->bo)
                 goto fail;
@@ -407,11 +432,11 @@ render_blit(struct pipe_context *ctx, struct pipe_blit_info *info)
 
         util_blitter_save_vertex_buffer_slot(vc4->blitter, vc4->vertexbuf.vb);
         util_blitter_save_vertex_elements(vc4->blitter, vc4->vtx);
-        util_blitter_save_vertex_shader(vc4->blitter, vc4->prog.vs);
+        util_blitter_save_vertex_shader(vc4->blitter, vc4->prog.bind_vs);
         util_blitter_save_rasterizer(vc4->blitter, vc4->rasterizer);
         util_blitter_save_viewport(vc4->blitter, &vc4->viewport);
         util_blitter_save_scissor(vc4->blitter, &vc4->scissor);
-        util_blitter_save_fragment_shader(vc4->blitter, vc4->prog.fs);
+        util_blitter_save_fragment_shader(vc4->blitter, vc4->prog.bind_fs);
         util_blitter_save_blend(vc4->blitter, vc4->blend);
         util_blitter_save_depth_stencil_alpha(vc4->blitter, vc4->zsa);
         util_blitter_save_stencil_ref(vc4->blitter, &vc4->stencil_ref);
@@ -456,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)
 {