panfrost: Pack vertex properties when compiling
[mesa.git] / src / gallium / drivers / panfrost / pan_fragment.c
index d6b8afdc6b946422c517999892fa7df641a9ef4f..9c8f31fc96c012226b0e67ce792cbd229c3e2e9c 100644 (file)
 
 #include "pan_context.h"
 #include "pan_util.h"
-#include "pan_format.h"
+#include "panfrost-quirks.h"
 
-#include "util/u_format.h"
+#include "util/format/u_format.h"
 
 /* Mark a surface as written */
 
 static void
-panfrost_initialize_surface(struct pipe_surface *surf)
+panfrost_initialize_surface(
+                struct panfrost_batch *batch,
+                struct pipe_surface *surf)
 {
+        if (!surf)
+                return;
+
         unsigned level = surf->u.tex.level;
         struct panfrost_resource *rsrc = pan_resource(surf->texture);
 
-        rsrc->bo->slices[level].initialized = true;
+        rsrc->slices[level].initialized = true;
 }
 
 /* Generate a fragment job. This should be called once per frame. (According to
  * presentations, this is supposed to correspond to eglSwapBuffers) */
 
 mali_ptr
-panfrost_fragment_job(struct panfrost_context *ctx, bool has_draws)
+panfrost_fragment_job(struct panfrost_batch *batch, bool has_draws)
 {
-        mali_ptr framebuffer = ctx->require_sfbd ?
-                panfrost_sfbd_fragment(ctx, has_draws) :
-                panfrost_mfbd_fragment(ctx, has_draws);
+        struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
+
+        mali_ptr framebuffer = (dev->quirks & MIDGARD_SFBD) ?
+                               panfrost_sfbd_fragment(batch, has_draws) :
+                               panfrost_mfbd_fragment(batch, has_draws);
 
-        /* Mark the affected buffers as initialized, since we're writing to it */
-        struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
+        /* Mark the affected buffers as initialized, since we're writing to it.
+         * Also, add the surfaces we're writing to to the batch */
+
+        struct pipe_framebuffer_state *fb = &batch->key;
 
         for (unsigned i = 0; i < fb->nr_cbufs; ++i) {
-                panfrost_initialize_surface(fb->cbufs[i]);
+                panfrost_initialize_surface(batch, fb->cbufs[i]);
         }
 
         if (fb->zsbuf)
-                panfrost_initialize_surface(fb->zsbuf);
+                panfrost_initialize_surface(batch, fb->zsbuf);
 
         struct mali_job_descriptor_header header = {
-                .job_type = JOB_TYPE_FRAGMENT,
+                .job_type = MALI_JOB_TYPE_FRAGMENT,
                 .job_index = 1,
-#ifdef __LP64__
                 .job_descriptor_size = 1
-#endif
         };
 
-        struct panfrost_job *job = panfrost_get_job_for_fbo(ctx);
+        /* The passed tile coords can be out of range in some cases, so we need
+         * to clamp them to the framebuffer size to avoid a TILE_RANGE_FAULT.
+         * Theoretically we also need to clamp the coordinates positive, but we
+         * avoid that edge case as all four values are unsigned. Also,
+         * theoretically we could clamp the minima, but if that has to happen
+         * the asserts would fail anyway (since the maxima would get clamped
+         * and then be smaller than the minima). An edge case of sorts occurs
+         * when no scissors are added to draw, so by default min=~0 and max=0.
+         * But that can't happen if any actual drawing occurs (beyond a
+         * wallpaper reload), so this is again irrelevant in practice. */
+
+        batch->maxx = MIN2(batch->maxx, fb->width);
+        batch->maxy = MIN2(batch->maxy, fb->height);
+
+        /* Rendering region must be at least 1x1; otherwise, there is nothing
+         * to do and the whole job chain should have been discarded. */
+
+        assert(batch->maxx > batch->minx);
+        assert(batch->maxy > batch->miny);
 
         struct mali_payload_fragment payload = {
-                .min_tile_coord = MALI_COORDINATE_TO_TILE_MIN(job->minx, job->miny),
-                .max_tile_coord = MALI_COORDINATE_TO_TILE_MAX(job->maxx, job->maxy),
+                .min_tile_coord = MALI_COORDINATE_TO_TILE_MIN(batch->minx, batch->miny),
+                .max_tile_coord = MALI_COORDINATE_TO_TILE_MAX(batch->maxx, batch->maxy),
                 .framebuffer = framebuffer,
         };
 
-        /* Normally, there should be no padding. However, fragment jobs are
-         * shared with 64-bit Bifrost systems, and accordingly there is 4-bytes
-         * of zero padding in between. */
-
-        struct panfrost_transfer transfer = panfrost_allocate_transient(ctx, sizeof(header) + sizeof(payload));
+        struct panfrost_transfer transfer = panfrost_pool_alloc_aligned(&batch->pool, sizeof(header) + sizeof(payload), 64);
         memcpy(transfer.cpu, &header, sizeof(header));
         memcpy(transfer.cpu + sizeof(header), &payload, sizeof(payload));
         return transfer.gpu;