#include "tgsi/tgsi_from_mesa.h"
#include "util/u_math.h"
+#include "midgard_pack.h"
#include "pan_screen.h"
#include "pan_blending.h"
#include "pan_blend_shaders.h"
#include "decode.h"
#include "util/pan_lower_framebuffer.h"
-struct midgard_tiler_descriptor
-panfrost_emit_midg_tiler(struct panfrost_batch *batch, unsigned vertex_count)
+void
+panfrost_emit_midg_tiler(struct panfrost_batch *batch,
+ struct mali_midgard_tiler_packed *tp,
+ unsigned vertex_count)
{
struct panfrost_device *device = pan_device(batch->ctx->base.screen);
bool hierarchy = !(device->quirks & MIDGARD_NO_HIER_TILING);
- struct midgard_tiler_descriptor t = {0};
unsigned height = batch->key.height;
unsigned width = batch->key.width;
- t.hierarchy_mask =
- panfrost_choose_hierarchy_mask(width, height, vertex_count, hierarchy);
-
- /* Compute the polygon header size and use that to offset the body */
+ pan_pack(tp, MIDGARD_TILER, t) {
+ t.hierarchy_mask =
+ panfrost_choose_hierarchy_mask(width, height,
+ vertex_count, hierarchy);
- unsigned header_size = panfrost_tiler_header_size(
- width, height, t.hierarchy_mask, hierarchy);
+ /* Compute the polygon header size and use that to offset the body */
- t.polygon_list_size = panfrost_tiler_full_size(
- width, height, t.hierarchy_mask, hierarchy);
+ unsigned header_size =
+ panfrost_tiler_header_size(width, height,
+ t.hierarchy_mask, hierarchy);
- if (vertex_count) {
- t.polygon_list = panfrost_batch_get_polygon_list(batch,
- header_size +
- t.polygon_list_size);
+ t.polygon_list_size =
+ panfrost_tiler_full_size(width, height, t.hierarchy_mask,
+ hierarchy);
+ if (vertex_count) {
+ t.polygon_list =
+ panfrost_batch_get_polygon_list(batch,
+ header_size +
+ t.polygon_list_size);
- t.heap_start = device->tiler_heap->gpu;
- t.heap_end = device->tiler_heap->gpu + device->tiler_heap->size;
- } else {
- struct panfrost_bo *tiler_dummy;
+ t.heap_start = device->tiler_heap->gpu;
+ t.heap_end = device->tiler_heap->gpu +
+ device->tiler_heap->size;
+ } else {
+ struct panfrost_bo *tiler_dummy;
- tiler_dummy = panfrost_batch_get_tiler_dummy(batch);
- header_size = MALI_TILER_MINIMUM_HEADER_SIZE;
+ tiler_dummy = panfrost_batch_get_tiler_dummy(batch);
+ header_size = MALI_MIDGARD_TILER_MINIMUM_HEADER_SIZE;
- /* The tiler is disabled, so don't allow the tiler heap */
- t.heap_start = tiler_dummy->gpu;
- t.heap_end = t.heap_start;
+ /* The tiler is disabled, so don't allow the tiler heap */
+ t.heap_start = tiler_dummy->gpu;
+ t.heap_end = t.heap_start;
- /* Use a dummy polygon list */
- t.polygon_list = tiler_dummy->gpu;
+ /* Use a dummy polygon list */
+ t.polygon_list = tiler_dummy->gpu;
- /* Disable the tiler */
- if (hierarchy)
- t.hierarchy_mask |= MALI_TILER_DISABLED;
- else {
- t.hierarchy_mask = MALI_TILER_USER;
- t.polygon_list_size = MALI_TILER_MINIMUM_HEADER_SIZE + 4;
+ /* Disable the tiler */
+ if (hierarchy)
+ t.hierarchy_mask |= MALI_MIDGARD_TILER_DISABLED;
+ else {
+ t.hierarchy_mask = MALI_MIDGARD_TILER_USER;
+ t.polygon_list_size = MALI_MIDGARD_TILER_MINIMUM_HEADER_SIZE + 4;
- /* We don't have a WRITE_VALUE job, so write the polygon list manually */
- uint32_t *polygon_list_body = (uint32_t *) (tiler_dummy->cpu + header_size);
- polygon_list_body[0] = 0xa0000000; /* TODO: Just that? */
+ /* We don't have a WRITE_VALUE job, so write the polygon list manually */
+ uint32_t *polygon_list_body = (uint32_t *) (tiler_dummy->cpu + header_size);
+ polygon_list_body[0] = 0xa0000000; /* TODO: Just that? */
+ }
}
+ t.polygon_list_body = t.polygon_list + header_size;
}
-
- t.polygon_list_body =
- t.polygon_list + header_size;
-
- return t;
}
static void
void
panfrost_attach_sfbd(struct panfrost_batch *batch, unsigned vertex_count);
-struct midgard_tiler_descriptor
-panfrost_emit_midg_tiler(struct panfrost_batch *batch, unsigned vertex_count);
+void
+panfrost_emit_midg_tiler(struct panfrost_batch *batch,
+ struct mali_midgard_tiler_packed *tp,
+ unsigned vertex_count);
mali_ptr
panfrost_fragment_job(struct panfrost_batch *batch, bool has_draws);
}
mali_ptr polygon_list = panfrost_batch_get_polygon_list(batch,
- MALI_TILER_MINIMUM_HEADER_SIZE);
+ MALI_MIDGARD_TILER_MINIMUM_HEADER_SIZE);
panfrost_scoreboard_initialize_tiler(&batch->pool, &batch->scoreboard, polygon_list);
ls.wls_instances = MALI_LOCAL_STORAGE_NO_WORKGROUP_MEM;
}
mfbd.shared_memory = lsp;
- mfbd.tiler = panfrost_emit_midg_tiler(batch, vertex_count);
+
+ struct mali_midgard_tiler_packed t;
+ panfrost_emit_midg_tiler(batch, &t, vertex_count);
+ mfbd.tiler = t;
}
return mfbd;
.unk3 = 0x3,
},
.clear_flags = 0x1000,
- .tiler = panfrost_emit_midg_tiler(batch, vertex_count),
};
+ struct mali_midgard_tiler_packed t;
+ panfrost_emit_midg_tiler(batch, &t, vertex_count);
+ framebuffer.tiler = t;
+
struct mali_local_storage_packed lsp;
pan_pack(&lsp, LOCAL_STORAGE, ls) {
ls.tls_size = shift;
#define MALI_CLEAR_SLOW (1 << 28)
#define MALI_CLEAR_SLOW_STENCIL (1 << 31)
-/* Configures hierarchical tiling on Midgard for both SFBD/MFBD (embedded
- * within the larget framebuffer descriptor). Analogous to
- * bifrost_tiler_heap_meta and bifrost_tiler_meta*/
-
-/* See pan_tiler.c for derivation */
-#define MALI_HIERARCHY_MASK ((1 << 9) - 1)
-
-/* Flag disabling the tiler for clear-only jobs, with
- hierarchical tiling */
-#define MALI_TILER_DISABLED (1 << 12)
-
-/* Flag selecting userspace-generated polygon list, for clear-only jobs without
- * hierarhical tiling. */
-#define MALI_TILER_USER 0xFFF
-
-/* Absent any geometry, the minimum size of the polygon list header */
-#define MALI_TILER_MINIMUM_HEADER_SIZE 0x200
-
-struct midgard_tiler_descriptor {
- /* Size of the entire polygon list; see pan_tiler.c for the
- * computation. It's based on hierarchical tiling */
-
- u32 polygon_list_size;
-
- /* Name known from the replay workaround in the kernel. What exactly is
- * flagged here is less known. We do that (tiler_hierarchy_mask & 0x1ff)
- * specifies a mask of hierarchy weights, which explains some of the
- * performance mysteries around setting it. We also see the bottom bit
- * of tiler_flags set in the kernel, but no comment why.
- *
- * hierarchy_mask can have the TILER_DISABLED flag */
-
- u16 hierarchy_mask;
- u16 flags;
-
- /* See mali_tiler.c for an explanation */
- mali_ptr polygon_list;
- mali_ptr polygon_list_body;
-
- /* Names based on we see symmetry with replay jobs which name these
- * explicitly */
-
- mali_ptr heap_start; /* tiler heap_free_address */
- mali_ptr heap_end;
-
- /* Hierarchy weights. We know these are weights based on the kernel,
- * but I've never seen them be anything other than zero */
- u32 weights[8];
-};
-
struct mali_sfbd_format {
/* 0x1 */
unsigned unk1 : 6;
u32 zero6[7];
- struct midgard_tiler_descriptor tiler;
+ struct mali_midgard_tiler_packed tiler;
+ struct mali_midgard_tiler_weights_packed tiler_weights;
/* More below this, maybe */
} __attribute__((packed));
float clear_depth;
union {
- struct midgard_tiler_descriptor tiler;
+ struct {
+ struct mali_midgard_tiler_packed tiler;
+ struct mali_midgard_tiler_weights_packed tiler_weights;
+ };
struct {
mali_ptr tiler_meta;
u32 zeros[16];
static void
pandecode_midgard_tiler_descriptor(
- const struct midgard_tiler_descriptor *t,
+ const struct mali_midgard_tiler_packed *tp,
+ const struct mali_midgard_tiler_weights_packed *wp,
unsigned width,
unsigned height,
bool is_fragment,
bool has_hierarchy)
{
- pandecode_log(".tiler = {\n");
- pandecode_indent++;
-
- if (t->hierarchy_mask == MALI_TILER_DISABLED)
- pandecode_prop("hierarchy_mask = MALI_TILER_DISABLED");
- else
- pandecode_prop("hierarchy_mask = 0x%" PRIx16, t->hierarchy_mask);
+ pan_unpack(tp, MIDGARD_TILER, t);
+ DUMP_UNPACKED(MIDGARD_TILER, t, "Tiler:\n");
- /* We know this name from the kernel, but we never see it nonzero */
-
- if (t->flags)
- pandecode_msg("XXX: unexpected tiler flags 0x%" PRIx16, t->flags);
-
- MEMORY_PROP(t, polygon_list);
+ MEMORY_PROP_DIR(t, polygon_list);
/* The body is offset from the base of the polygon list */
//assert(t->polygon_list_body > t->polygon_list);
- unsigned body_offset = t->polygon_list_body - t->polygon_list;
+ unsigned body_offset = t.polygon_list_body - t.polygon_list;
/* It needs to fit inside the reported size */
//assert(t->polygon_list_size >= body_offset);
/* Now that we've sanity checked, we'll try to calculate the sizes
* ourselves for comparison */
- unsigned ref_header = panfrost_tiler_header_size(width, height, t->hierarchy_mask, has_hierarchy);
- unsigned ref_size = panfrost_tiler_full_size(width, height, t->hierarchy_mask, has_hierarchy);
+ unsigned ref_header = panfrost_tiler_header_size(width, height, t.hierarchy_mask, has_hierarchy);
+ unsigned ref_size = panfrost_tiler_full_size(width, height, t.hierarchy_mask, has_hierarchy);
- if (!((ref_header == body_offset) && (ref_size == t->polygon_list_size))) {
+ if (!((ref_header == body_offset) && (ref_size == t.polygon_list_size))) {
pandecode_msg("XXX: bad polygon list size (expected %d / 0x%x)\n",
ref_header, ref_size);
- pandecode_prop("polygon_list_size = 0x%x", t->polygon_list_size);
+ pandecode_prop("polygon_list_size = 0x%x", t.polygon_list_size);
pandecode_msg("body offset %d\n", body_offset);
}
* identical to what we have in the BO. The exception is if tiling is
* disabled. */
- MEMORY_PROP(t, heap_start);
- assert(t->heap_end >= t->heap_start);
+ MEMORY_PROP_DIR(t, heap_start);
+ assert(t.heap_end >= t.heap_start);
- unsigned heap_size = t->heap_end - t->heap_start;
+ unsigned heap_size = t.heap_end - t.heap_start;
/* Tiling is enabled with a special flag */
- unsigned hierarchy_mask = t->hierarchy_mask & MALI_HIERARCHY_MASK;
- unsigned tiler_flags = t->hierarchy_mask ^ hierarchy_mask;
+ unsigned hierarchy_mask = t.hierarchy_mask & MALI_MIDGARD_TILER_HIERARCHY_MASK;
+ unsigned tiler_flags = t.hierarchy_mask ^ hierarchy_mask;
bool tiling_enabled = hierarchy_mask;
} else {
/* When tiling is disabled, we should have that flag and no others */
- if (tiler_flags != MALI_TILER_DISABLED) {
- pandecode_msg("XXX: unexpected tiler flag %X, expected MALI_TILER_DISABLED\n",
+ if (tiler_flags != MALI_MIDGARD_TILER_DISABLED) {
+ pandecode_msg("XXX: unexpected tiler flag %X, expected MALI_MIDGARD_TILER_DISABLED\n",
tiler_flags);
}
/* We've never seen weights used in practice, but we know from the
* kernel these fields is there */
+ pan_unpack(wp, MIDGARD_TILER_WEIGHTS, w);
bool nonzero_weights = false;
- for (unsigned w = 0; w < ARRAY_SIZE(t->weights); ++w) {
- nonzero_weights |= t->weights[w] != 0x0;
- }
-
- if (nonzero_weights) {
- pandecode_log(".weights = { ");
-
- for (unsigned w = 0; w < ARRAY_SIZE(t->weights); ++w) {
- pandecode_log_cont("%d, ", t->weights[w]);
- }
-
- pandecode_log("},");
- }
-
- pandecode_indent--;
- pandecode_log("}\n");
+ nonzero_weights |= w.weight0 != 0x0;
+ nonzero_weights |= w.weight1 != 0x0;
+ nonzero_weights |= w.weight2 != 0x0;
+ nonzero_weights |= w.weight3 != 0x0;
+ nonzero_weights |= w.weight4 != 0x0;
+ nonzero_weights |= w.weight5 != 0x0;
+ nonzero_weights |= w.weight6 != 0x0;
+ nonzero_weights |= w.weight7 != 0x0;
+
+ if (nonzero_weights)
+ DUMP_UNPACKED(MIDGARD_TILER_WEIGHTS, w, "Tiler Weights:\n");
}
/* TODO: The Bifrost tiler is not understood at all yet */
pandecode_prop("clear_stencil = 0x%x", s->clear_stencil);
}
- const struct midgard_tiler_descriptor t = s->tiler;
+ const struct mali_midgard_tiler_packed t = s->tiler;
+ const struct mali_midgard_tiler_weights_packed w = s->tiler_weights;
bool has_hierarchy = !(gpu_id == 0x0720 || gpu_id == 0x0820 || gpu_id == 0x0830);
- pandecode_midgard_tiler_descriptor(&t, s->width + 1, s->height + 1, is_fragment, has_hierarchy);
+ pandecode_midgard_tiler_descriptor(&t, &w, s->width + 1, s->height + 1, is_fragment, has_hierarchy);
pandecode_indent--;
pandecode_log("};\n");
if (is_bifrost)
pandecode_bifrost_tiler_descriptor(fb);
else {
- const struct midgard_tiler_descriptor t = fb->tiler;
- pandecode_midgard_tiler_descriptor(&t, fb->width1 + 1, fb->height1 + 1, is_fragment, true);
+ const struct mali_midgard_tiler_packed t = fb->tiler;
+ const struct mali_midgard_tiler_weights_packed w = fb->tiler_weights;
+ pandecode_midgard_tiler_descriptor(&t, &w, fb->width1 + 1, fb->height1 + 1, is_fragment, true);
}
else
pandecode_msg("XXX: skipping compute MFBD, fixme\n");
<field name="TLS Base Pointer" size="64" start="2:0" type="address"/>
<field name="WLS Base Pointer" size="64" start="4:0" type="address"/>
</struct>
+
+ <struct name="Midgard Tiler">
+ <field name="Polygon List Size" size="32" start="0:0" type="uint" prefix="MALI_MIDGARD_TILER">
+ <value name="Minimum Header Size" value="512"/>
+ </field>
+ <field name="Hierarchy Mask" size="16" start="1:0" type="uint" prefix="MALI_MIDGARD_TILER">
+ <value name="Disabled" value="4096"/>
+ <value name="User" value="4095"/>
+ <value name="Hierarchy Mask" value="511"/>
+ </field>
+ <field name="Polygon List" size="64" start="2:0" type="address"/>
+ <field name="Polygon List Body" size="64" start="4:0" type="address"/>
+ <field name="Heap Start" size="64" start="6:0" type="address"/>
+ <field name="Heap End" size="64" start="8:0" type="address"/>
+ </struct>
+
+ <struct name="Midgard Tiler Weights">
+ <field name="Weight0" size="32" start="0:0" type="uint"/>
+ <field name="Weight1" size="32" start="1:0" type="uint"/>
+ <field name="Weight2" size="32" start="2:0" type="uint"/>
+ <field name="Weight3" size="32" start="3:0" type="uint"/>
+ <field name="Weight4" size="32" start="4:0" type="uint"/>
+ <field name="Weight5" size="32" start="5:0" type="uint"/>
+ <field name="Weight6" size="32" start="6:0" type="uint"/>
+ <field name="Weight7" size="32" start="7:0" type="uint"/>
+ </struct>
</panxml>