}
}
-static void
-panfrost_enable_checksum(struct panfrost_context *ctx, struct panfrost_resource *rsrc)
-{
- struct pipe_context *gallium = (struct pipe_context *) ctx;
- struct panfrost_screen *screen = pan_screen(gallium->screen);
- int tile_w = (rsrc->base.width0 + (MALI_TILE_LENGTH - 1)) >> MALI_TILE_SHIFT;
- int tile_h = (rsrc->base.height0 + (MALI_TILE_LENGTH - 1)) >> MALI_TILE_SHIFT;
-
- /* 8 byte checksum per tile */
- rsrc->bo->checksum_stride = tile_w * 8;
- int pages = (((rsrc->bo->checksum_stride * tile_h) + 4095) / 4096);
- panfrost_drm_allocate_slab(screen, &rsrc->bo->checksum_slab, pages, false, 0, 0, 0);
-
- rsrc->bo->has_checksum = true;
-}
-
/* Framebuffer descriptor */
static void
if (job->requirements & PAN_REQ_DEPTH_WRITE)
fb.mfbd_flags |= MALI_MFBD_DEPTH_WRITE;
+ /* Checksumming only works with a single render target */
+
if (ctx->pipe_framebuffer.nr_cbufs == 1) {
- struct panfrost_resource *rsrc = (struct panfrost_resource *) ctx->pipe_framebuffer.cbufs[0]->texture;
+ struct pipe_surface *surf = ctx->pipe_framebuffer.cbufs[0];
+ struct panfrost_resource *rsrc = pan_resource(surf->texture);
+ struct panfrost_bo *bo = rsrc->bo;
+
+ if (bo->checksummed) {
+ unsigned level = surf->u.tex.level;
+ struct panfrost_slice *slice = &bo->slices[level];
- if (rsrc->bo->has_checksum) {
fb.mfbd_flags |= MALI_MFBD_EXTRA;
fbx.flags |= MALI_EXTRA_PRESENT;
- fbx.checksum_stride = rsrc->bo->checksum_stride;
- fbx.checksum = rsrc->bo->gpu + rsrc->bo->slices[0].stride * rsrc->base.height0;
+ fbx.checksum_stride = slice->checksum_stride;
+ fbx.checksum = bo->gpu + slice->checksum_offset;
}
}
ralloc_free(surf);
}
+/* Computes sizes for checksumming, which is 8 bytes per 16x16 tile */
+
+#define CHECKSUM_TILE_WIDTH 16
+#define CHECKSUM_TILE_HEIGHT 16
+#define CHECKSUM_BYTES_PER_TILE 8
+
+static unsigned
+panfrost_compute_checksum_sizes(
+ struct panfrost_slice *slice,
+ unsigned width,
+ unsigned height)
+{
+ unsigned aligned_width = ALIGN(width, CHECKSUM_TILE_WIDTH);
+ unsigned aligned_height = ALIGN(width, CHECKSUM_TILE_HEIGHT);
+
+ unsigned tile_count_x = aligned_width / CHECKSUM_TILE_WIDTH;
+ unsigned tile_count_y = aligned_height / CHECKSUM_TILE_HEIGHT;
+
+ slice->checksum_stride = tile_count_x * CHECKSUM_BYTES_PER_TILE;
+
+ return slice->checksum_stride * tile_count_y;
+}
+
+/* Setup the mip tree given a particular layout, possibly with checksumming */
+
static void
panfrost_setup_slices(const struct pipe_resource *tmpl, struct panfrost_bo *bo)
{
offset += slice_full_size;
+ /* Add a checksum region if necessary */
+ if (bo->checksummed) {
+ slice->checksum_offset = offset;
+
+ unsigned size = panfrost_compute_checksum_sizes(
+ slice, width, height);
+
+ offset += size;
+ }
+
width = u_minify(width, 1);
height = u_minify(height, 1);
depth = u_minify(depth, 1);
/* Depth/stencil can't be tiled, only linear or AFBC */
should_tile &= !(template->bind & PIPE_BIND_DEPTH_STENCIL);
+ /* FBOs we would like to checksum, if at all possible */
+ bool can_checksum = !(template->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED));
+ bool should_checksum = template->bind & PIPE_BIND_RENDER_TARGET;
+
+ bo->checksummed = can_checksum && should_checksum;
+
/* Set the layout appropriately */
bo->layout = should_tile ? PAN_TILED : PAN_LINEAR;
static void
panfrost_destroy_bo(struct panfrost_screen *screen, struct panfrost_bo *bo)
{
- if (!bo->imported) {
+ if (bo->imported) {
+ panfrost_drm_free_imported_bo(screen, bo);
+ } else {
struct panfrost_memory mem = {
.cpu = bo->cpu,
.gpu = bo->gpu,
panfrost_drm_free_slab(screen, &mem);
}
- if (bo->has_checksum) {
- struct panfrost_memory mem = {
- .cpu = bo->checksum_slab.cpu,
- .gpu = bo->checksum_slab.gpu,
- .size = bo->checksum_slab.size,
- .gem_handle = bo->checksum_slab.gem_handle,
- };
-
- panfrost_drm_free_slab(screen, &mem);
- }
-
- if (bo->imported) {
- panfrost_drm_free_imported_bo(screen, bo);
- }
-
ralloc_free(bo);
}
unsigned offset;
unsigned stride;
- /* If there is a header preceding each slice, how big is that header?
- * Used for AFBC */
+ /* If there is a header preceding each slice, how big is
+ * that header? Used for AFBC */
unsigned header_size;
+ /* If checksumming is enabled following the slice, what
+ * is its offset/stride? */
+ unsigned checksum_offset;
+ unsigned checksum_stride;
+
/* Has anything been written to this slice? */
bool initialized;
};
/* Internal layout (tiled?) */
enum panfrost_memory_layout layout;
- /* If transaciton elimination is enabled, we have a dedicated
- * buffer for that as well. */
-
- bool has_checksum;
- struct panfrost_memory checksum_slab;
- int checksum_stride;
+ /* Is transaciton elimination enabled? */
+ bool checksummed;
int gem_handle;
};