nir: Add a new memory_barrier_tcs_patch intrinsic
[mesa.git] / src / panfrost / include / panfrost-job.h
index 0fbe0a2fa10914d84e15d4ea7e07fd387e46e104..dfc5d83a80d6136766062c871e1848a0eba92883 100644 (file)
 #define __PANFROST_JOB_H__
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <panfrost-misc.h>
 
-#define MALI_SHORT_PTR_BITS (sizeof(uintptr_t)*8)
-
-#define MALI_FBD_HIERARCHY_WEIGHTS 8
-
-#define MALI_PAYLOAD_SIZE 256
-
-typedef u32 mali_jd_core_req;
-
 enum mali_job_type {
         JOB_NOT_STARTED        = 0,
         JOB_TYPE_NULL = 1,
-        JOB_TYPE_SET_VALUE = 2,
+        JOB_TYPE_WRITE_VALUE = 2,
         JOB_TYPE_CACHE_FLUSH = 3,
         JOB_TYPE_COMPUTE = 4,
         JOB_TYPE_VERTEX = 5,
@@ -70,7 +63,6 @@ enum mali_draw_mode {
 
 /* Applies to tiler_gl_enables */
 
-
 #define MALI_OCCLUSION_QUERY    (1 << 3)
 #define MALI_OCCLUSION_PRECISE  (1 << 4)
 
@@ -78,20 +70,12 @@ enum mali_draw_mode {
  * In OpenGL, this would corresponds to glFrontFace(GL_CW). Mesa and the blob
  * disagree about how to do viewport flipping, so the blob actually sets this
  * for GL_CW but then has a negative viewport stride */
+
 #define MALI_FRONT_CCW_TOP      (1 << 5)
 
 #define MALI_CULL_FACE_FRONT    (1 << 6)
 #define MALI_CULL_FACE_BACK     (1 << 7)
 
-/* TODO: Might this actually be a finer bitfield? */
-#define MALI_DEPTH_STENCIL_ENABLE 0x6400
-
-#define DS_ENABLE(field) \
-       (field == MALI_DEPTH_STENCIL_ENABLE) \
-       ? "MALI_DEPTH_STENCIL_ENABLE" \
-       : (field == 0) ? "0" \
-       : "0 /* XXX: Unknown, check hexdump */"
-
 /* Used in stencil and depth tests */
 
 enum mali_func {
@@ -105,19 +89,6 @@ enum mali_func {
         MALI_FUNC_ALWAYS   = 7
 };
 
-/* Same OpenGL, but mixed up. Why? Because forget me, that's why! */
-
-enum mali_alt_func {
-        MALI_ALT_FUNC_NEVER    = 0,
-        MALI_ALT_FUNC_GREATER  = 1,
-        MALI_ALT_FUNC_EQUAL    = 2,
-        MALI_ALT_FUNC_GEQUAL   = 3,
-        MALI_ALT_FUNC_LESS     = 4,
-        MALI_ALT_FUNC_NOTEQUAL = 5,
-        MALI_ALT_FUNC_LEQUAL   = 6,
-        MALI_ALT_FUNC_ALWAYS   = 7
-};
-
 /* Flags apply to unknown2_3? */
 
 #define MALI_HAS_MSAA          (1 << 0)
@@ -131,7 +102,7 @@ enum mali_alt_func {
 #define MALI_GET_DEPTH_FUNC(flags) ((flags >> 8) & 0x7)
 #define MALI_DEPTH_FUNC_MASK      MALI_DEPTH_FUNC(0x7)
 
-#define MALI_DEPTH_TEST                (1 << 11)
+#define MALI_DEPTH_WRITEMASK    (1 << 11)
 
 /* Next flags to unknown2_4 */
 #define MALI_STENCIL_TEST              (1 << 0)
@@ -434,16 +405,26 @@ union midgard_blend {
         };
 };
 
+/* We need to load the tilebuffer to blend (i.e. the destination factor is not
+ * ZERO) */
+
+#define MALI_BLEND_LOAD_TIB (0x1)
+
+/* A blend shader is used to blend this render target */
+#define MALI_BLEND_MRT_SHADER (0x2)
+
 /* On MRT Midgard systems (using an MFBD), each render target gets its own
  * blend descriptor */
 
 #define MALI_BLEND_SRGB (0x400)
 
+/* Dithering is specified here for MFBD, otherwise NO_DITHER for SFBD */
+#define MALI_BLEND_NO_DITHER (0x800)
+
 struct midgard_blend_rt {
         /* Flags base value of 0x200 to enable the render target.
          * OR with 0x1 for blending (anything other than REPLACE).
-         * OR with 0x2 for programmable blending with 0-2 registers
-         * OR with 0x3 for programmable blending with 2+ registers
+         * OR with 0x2 for programmable blending
          * OR with MALI_BLEND_SRGB for implicit sRGB
          */
 
@@ -528,8 +509,8 @@ struct bifrost_blend_rt {
 
 struct mali_shader_meta {
         mali_ptr shader;
-        u16 texture_count;
         u16 sampler_count;
+        u16 texture_count;
         u16 attribute_count;
         u16 varying_count;
 
@@ -542,9 +523,7 @@ struct mali_shader_meta {
                         unsigned uniform_buffer_count : 4;
                         unsigned flags : 12;
 
-                        /* Whole number of uniform registers used, times two;
-                         * whole number of work registers used (no scale).
-                         */
+                        /* vec4 units */
                         unsigned work_count : 5;
                         unsigned uniform_count : 5;
                         unsigned unknown2 : 6;
@@ -642,22 +621,35 @@ struct mali_job_descriptor_header {
         u16 job_index;
         u16 job_dependency_index_1;
         u16 job_dependency_index_2;
-
-        union {
-                u64 next_job_64;
-                u32 next_job_32;
-        };
+        u64 next_job;
 } __attribute__((packed));
 
-struct mali_payload_set_value {
-        u64 out;
-        u64 unknown;
-} __attribute__((packed));
+/* These concern exception_status */
+
+/* Access type causing a fault, paralleling AS_FAULTSTATUS_* entries in the
+ * kernel */
+
+enum mali_exception_access {
+        /* Atomic in the kernel for MMU, but that doesn't make sense for a job
+         * fault so it's just unused */
+        MALI_EXCEPTION_ACCESS_NONE    = 0,
+
+        MALI_EXCEPTION_ACCESS_EXECUTE = 1,
+        MALI_EXCEPTION_ACCESS_READ    = 2,
+        MALI_EXCEPTION_ACCESS_WRITE   = 3
+};
 
-/* Special attributes have a fixed index */
-#define MALI_SPECIAL_ATTRIBUTE_BASE 16
-#define MALI_VERTEX_ID   (MALI_SPECIAL_ATTRIBUTE_BASE + 0)
-#define MALI_INSTANCE_ID (MALI_SPECIAL_ATTRIBUTE_BASE + 1)
+/* Details about write_value from panfrost igt tests which use it as a generic
+ * dword write primitive */
+
+#define MALI_WRITE_VALUE_ZERO 3
+
+struct mali_payload_write_value {
+        u64 address;
+        u32 value_descriptor;
+        u32 reserved;
+        u64 immediate;
+} __attribute__((packed));
 
 /*
  * Mali Attributes
@@ -780,6 +772,14 @@ struct mali_payload_set_value {
  * 3. If e <= 2^shift, then we need to use the round-down algorithm. Set
  * magic_divisor = m - 1 and extra_flags = 1.
  * 4. Otherwise, set magic_divisor = m and extra_flags = 0.
+ *
+ * Unrelated to instancing/actual attributes, images (the OpenCL kind) are
+ * implemented as special attributes, denoted by MALI_ATTR_IMAGE. For images,
+ * let shift=extra_flags=0. Stride is set to the image format's bytes-per-pixel
+ * (*NOT the row stride*). Size is set to the size of the image itself.
+ *
+ * Special internal attribtues and varyings (gl_VertexID, gl_FrontFacing, etc)
+ * use particular fixed addresses with modified structures.
  */
 
 enum mali_attr_mode {
@@ -788,14 +788,27 @@ enum mali_attr_mode {
        MALI_ATTR_POT_DIVIDE = 2,
        MALI_ATTR_MODULO = 3,
        MALI_ATTR_NPOT_DIVIDE = 4,
+        MALI_ATTR_IMAGE = 5,
 };
 
+/* Pseudo-address for gl_VertexID, gl_FragCoord, gl_FrontFacing */
+
+#define MALI_ATTR_VERTEXID (0x22)
+#define MALI_ATTR_INSTANCEID (0x24)
+#define MALI_VARYING_FRAG_COORD (0x25)
+#define MALI_VARYING_FRONT_FACING (0x26)
+
 /* This magic "pseudo-address" is used as `elements` to implement
  * gl_PointCoord. When read from a fragment shader, it generates a point
  * coordinate per the OpenGL ES 2.0 specification. Flipped coordinate spaces
  * require an affine transformation in the shader. */
 
-#define MALI_VARYING_POINT_COORD (0x60)
+#define MALI_VARYING_POINT_COORD (0x61)
+
+/* Used for comparison to check if an address is special. Mostly a guess, but
+ * it doesn't really matter. */
+
+#define MALI_RECORD_SPECIAL (0x100)
 
 union mali_attr {
        /* This is used for actual attributes. */
@@ -835,14 +848,14 @@ struct mali_attr_meta {
         int32_t src_offset;
 } __attribute__((packed));
 
-enum mali_fbd_type {
-        MALI_SFBD = 0,
-        MALI_MFBD = 1,
-};
-
-#define FBD_TYPE (1)
 #define FBD_MASK (~0x3f)
 
+/* MFBD, rather than SFBD */
+#define MALI_MFBD (0x1)
+
+/* ORed into an MFBD address to specify the fbx section is included */
+#define MALI_MFBD_TAG_EXTRA (0x2)
+
 struct mali_uniform_buffer_meta {
         /* This is actually the size minus 1 (MALI_POSITIVE), in units of 16
          * bytes. This gives a maximum of 2^14 bytes, which just so happens to
@@ -868,7 +881,16 @@ struct mali_uniform_buffer_meta {
 #define MALI_DRAW_INDEXED_UINT8  (0x10)
 #define MALI_DRAW_INDEXED_UINT16 (0x20)
 #define MALI_DRAW_INDEXED_UINT32 (0x30)
+#define MALI_DRAW_INDEXED_SIZE   (0x30)
+#define MALI_DRAW_INDEXED_SHIFT  (4)
+
 #define MALI_DRAW_VARYING_SIZE   (0x100)
+
+/* Set to use first vertex as the provoking vertex for flatshading. Clear to
+ * use the last vertex. This is the default in DX and VK, but not in GL. */
+
+#define MALI_DRAW_FLATSHADE_FIRST (0x800)
+
 #define MALI_DRAW_PRIMITIVE_RESTART_FIXED_INDEX (0x10000)
 
 struct mali_vertex_tiler_prefix {
@@ -897,13 +919,16 @@ struct mali_vertex_tiler_prefix {
          */
         u32 invocation_count;
 
-        u32 size_y_shift : 5;
-        u32 size_z_shift : 5;
-        u32 workgroups_x_shift : 6;
-        u32 workgroups_y_shift : 6;
-        u32 workgroups_z_shift : 6;
-        /* This is max(workgroups_x_shift, 2) in all the cases I've seen. */
-        u32 workgroups_x_shift_2 : 4;
+        /* Bitfield for shifts:
+         *
+         * size_y_shift : 5
+         * size_z_shift : 5
+         * workgroups_x_shift : 6
+         * workgroups_y_shift : 6
+         * workgroups_z_shift : 6
+         * workgroups_x_shift_2 : 4
+         */
+        u32 invocation_shifts;
 
         u32 draw_mode : 4;
         u32 unknown_draw : 22;
@@ -917,8 +942,23 @@ struct mali_vertex_tiler_prefix {
         u32 workgroups_x_shift_3 : 6;
 
 
-        /* Negative of draw_start for TILER jobs from what I've seen */
-        int32_t negative_start;
+        /* Negative of min_index. This is used to compute
+         * the unbiased index in tiler/fragment shader runs.
+         * 
+         * The hardware adds offset_bias_correction in each run,
+         * so that absent an index bias, the first vertex processed is
+         * genuinely the first vertex (0). But with an index bias,
+         * the first vertex process is numbered the same as the bias.
+         *
+         * To represent this more conviniently:
+         * unbiased_index = lower_bound_index +
+         *                  index_bias +
+         *                  offset_bias_correction
+         *
+         * This is done since the hardware doesn't accept a index_bias
+         * and this allows it to recover the unbiased index.
+         */
+        int32_t offset_bias_correction;
         u32 zero1;
 
         /* Like many other strictly nonzero quantities, index_count is
@@ -935,7 +975,7 @@ struct mali_vertex_tiler_prefix {
          * indices (width depends on flags). Thanks, guys, for not making my
          * life insane for once! NULL for non-indexed draws. */
 
-        uintptr_t indices;
+        u64 indices;
 } __attribute__((packed));
 
 /* Point size / line width can either be specified as a 32-bit float (for
@@ -947,7 +987,7 @@ struct mali_vertex_tiler_prefix {
 
 union midgard_primitive_size {
         float constant;
-        uintptr_t pointer;
+        u64 pointer;
 };
 
 struct bifrost_vertex_only {
@@ -1011,34 +1051,33 @@ struct mali_vertex_tiler_postfix {
          * output from the vertex shader for tiler jobs.
          */
 
-        uintptr_t position_varying;
+        u64 position_varying;
 
         /* An array of mali_uniform_buffer_meta's. The size is given by the
          * shader_meta.
          */
-        uintptr_t uniform_buffers;
+        u64 uniform_buffers;
 
         /* This is a pointer to an array of pointers to the texture
          * descriptors, number of pointers bounded by number of textures. The
          * indirection is needed to accomodate varying numbers and sizes of
          * texture descriptors */
-        uintptr_t texture_trampoline;
+        u64 texture_trampoline;
 
         /* For OpenGL, from what I've seen, this is intimately connected to
          * texture_meta. cwabbott says this is not the case under Vulkan, hence
          * why this field is seperate (Midgard is Vulkan capable). Pointer to
          * array of sampler descriptors (which are uniform in size) */
-        uintptr_t sampler_descriptor;
-
-        uintptr_t uniforms;
-        u8 flags : 4;
-        uintptr_t _shader_upper : MALI_SHORT_PTR_BITS - 4; /* struct shader_meta */
-        uintptr_t attributes; /* struct attribute_buffer[] */
-        uintptr_t attribute_meta; /* attribute_meta[] */
-        uintptr_t varyings; /* struct attr */
-        uintptr_t varying_meta; /* pointer */
-        uintptr_t viewport;
-        uintptr_t occlusion_counter; /* A single bit as far as I can tell */
+        u64 sampler_descriptor;
+
+        u64 uniforms;
+        u64 shader;
+        u64 attributes; /* struct attribute_buffer[] */
+        u64 attribute_meta; /* attribute_meta[] */
+        u64 varyings; /* struct attr */
+        u64 varying_meta; /* pointer */
+        u64 viewport;
+        u64 occlusion_counter; /* A single bit as far as I can tell */
 
         /* Note: on Bifrost, this isn't actually the FBD. It points to
          * bifrost_scratchpad instead. However, it does point to the same thing
@@ -1048,16 +1087,8 @@ struct mali_vertex_tiler_postfix {
 } __attribute__((packed));
 
 struct midgard_payload_vertex_tiler {
-#ifndef __LP64__
-        union midgard_primitive_size primitive_size;
-#endif
-
         struct mali_vertex_tiler_prefix prefix;
 
-#ifndef __LP64__
-        u32 zero3;
-#endif
-
         u16 gl_enables; // 0x5
 
         /* Both zero for non-instanced draws. For instanced draws, a
@@ -1070,15 +1101,13 @@ struct midgard_payload_vertex_tiler {
         u8 zero4;
 
         /* Offset for first vertex in buffer */
-        u32 draw_start;
+        u32 offset_start;
 
-       uintptr_t zero5;
+       u64 zero5;
 
         struct mali_vertex_tiler_postfix postfix;
 
-#ifdef __LP64__
         union midgard_primitive_size primitive_size;
-#endif
 } __attribute__((packed));
 
 struct bifrost_payload_vertex {
@@ -1110,17 +1139,17 @@ struct bifrost_payload_fused {
 
 #define MALI_POSITIVE(dim) (dim - 1)
 
-/* Opposite of MALI_POSITIVE, found in the depth_units field */
-
-#define MALI_NEGATIVE(dim) (dim + 1)
-
-/* Used with wrapping. Incomplete (this is a 4-bit field...) */
+/* Used with wrapping. Unclear what top bit conveys */
 
 enum mali_wrap_mode {
-        MALI_WRAP_REPEAT = 0x8,
-        MALI_WRAP_CLAMP_TO_EDGE = 0x9,
-        MALI_WRAP_CLAMP_TO_BORDER = 0xB,
-        MALI_WRAP_MIRRORED_REPEAT = 0xC
+        MALI_WRAP_REPEAT                   = 0x8 |       0x0,
+        MALI_WRAP_CLAMP_TO_EDGE            = 0x8 |       0x1,
+        MALI_WRAP_CLAMP                    = 0x8 |       0x2,
+        MALI_WRAP_CLAMP_TO_BORDER          = 0x8 |       0x3,
+        MALI_WRAP_MIRRORED_REPEAT          = 0x8 | 0x4 | 0x0,
+        MALI_WRAP_MIRRORED_CLAMP_TO_EDGE   = 0x8 | 0x4 | 0x1,
+        MALI_WRAP_MIRRORED_CLAMP           = 0x8 | 0x4 | 0x2,
+        MALI_WRAP_MIRRORED_CLAMP_TO_BORDER = 0x8 | 0x4 | 0x3,
 };
 
 /* Shared across both command stream and Midgard, and even with Bifrost */
@@ -1141,10 +1170,21 @@ enum mali_texture_type {
 /* For each pointer, there is an address and optionally also a stride */
 #define MAX_ELEMENTS (2)
 
-/* Corresponds to the type passed to glTexImage2D and so forth */
+/* It's not known why there are 4-bits allocated -- this enum is almost
+ * certainly incomplete */
+
+enum mali_texture_layout {
+        /* For a Z/S texture, this is linear */
+        MALI_TEXTURE_TILED = 0x1,
 
-/* Flags for usage2 */
-#define MALI_TEX_MANUAL_STRIDE (0x20)
+        /* Z/S textures cannot be tiled */
+        MALI_TEXTURE_LINEAR = 0x2,
+
+        /* 16x16 sparse */
+        MALI_TEXTURE_AFBC = 0xC
+};
+
+/* Corresponds to the type passed to glTexImage2D and so forth */
 
 struct mali_texture_format {
         unsigned swizzle : 12;
@@ -1154,8 +1194,15 @@ struct mali_texture_format {
         unsigned unknown1 : 1;
 
         enum mali_texture_type type : 2;
+        enum mali_texture_layout layout : 4;
+
+        /* Always set */
+        unsigned unknown2 : 1;
+
+        /* Set to allow packing an explicit stride */
+        unsigned manual_stride : 1;
 
-        unsigned usage2 : 8;
+        unsigned zero : 2;
 } __attribute__((packed));
 
 struct mali_texture_descriptor {
@@ -1172,7 +1219,7 @@ struct mali_texture_descriptor {
         uint8_t unknown3A;
 
         /* Zero for non-mipmapped, (number of levels - 1) for mipmapped */
-        uint8_t nr_mipmap_levels;
+        uint8_t levels;
 
         /* Swizzling is a single 32-bit word, broken up here for convenience.
          * Here, swizzling refers to the ES 3.0 texture parameters for channel
@@ -1185,58 +1232,58 @@ struct mali_texture_descriptor {
         uint32_t unknown5;
         uint32_t unknown6;
         uint32_t unknown7;
-
-        mali_ptr payload[MAX_MIP_LEVELS * MAX_CUBE_FACES * MAX_ELEMENTS];
 } __attribute__((packed));
 
-/* Used as part of filter_mode */
+/* filter_mode */
 
-#define MALI_LINEAR 0
-#define MALI_NEAREST 1
-#define MALI_MIP_LINEAR (0x18)
+#define MALI_SAMP_MAG_NEAREST (1 << 0)
+#define MALI_SAMP_MIN_NEAREST (1 << 1)
 
-/* Used to construct low bits of filter_mode */
+/* TODO: What do these bits mean individually? Only seen set together */
 
-#define MALI_TEX_MAG(mode) (((mode) & 1) << 0)
-#define MALI_TEX_MIN(mode) (((mode) & 1) << 1)
+#define MALI_SAMP_MIP_LINEAR_1 (1 << 3)
+#define MALI_SAMP_MIP_LINEAR_2 (1 << 4)
 
-#define MALI_TEX_MAG_MASK (1)
-#define MALI_TEX_MIN_MASK (2)
+/* Flag in filter_mode, corresponding to OpenCL's NORMALIZED_COORDS_TRUE
+ * sampler_t flag. For typical OpenGL textures, this is always set. */
 
-#define MALI_FILTER_NAME(filter) (filter ? "MALI_NEAREST" : "MALI_LINEAR")
+#define MALI_SAMP_NORM_COORDS (1 << 5)
 
 /* Used for lod encoding. Thanks @urjaman for pointing out these routines can
  * be cleaned up a lot. */
 
 #define DECODE_FIXED_16(x) ((float) (x / 256.0))
 
-static inline uint16_t
-FIXED_16(float x)
+static inline int16_t
+FIXED_16(float x, bool allow_negative)
 {
         /* Clamp inputs, accounting for float error */
         float max_lod = (32.0 - (1.0 / 512.0));
+        float min_lod = allow_negative ? -max_lod : 0.0;
 
-        x = ((x > max_lod) ? max_lod : ((x < 0.0) ? 0.0 : x));
+        x = ((x > max_lod) ? max_lod : ((x < min_lod) ? min_lod : x));
 
         return (int) (x * 256.0);
 }
 
 struct mali_sampler_descriptor {
-        uint32_t filter_mode;
+        uint16_t filter_mode;
 
-        /* Fixed point. Upper 8-bits is before the decimal point, although it
-         * caps [0-31]. Lower 8-bits is after the decimal point: int(round(x *
-         * 256)) */
+        /* Fixed point, signed.
+         * Upper 7 bits before the decimal point, although it caps [0-31].
+         * Lower 8 bits after the decimal point: int(round(x * 256)) */
 
-        uint16_t min_lod;
-        uint16_t max_lod;
+        int16_t lod_bias;
+        int16_t min_lod;
+        int16_t max_lod;
 
-        /* All one word in reality, but packed a bit */
+        /* All one word in reality, but packed a bit. Comparisons are flipped
+         * from OpenGL. */
 
         enum mali_wrap_mode wrap_s : 4;
         enum mali_wrap_mode wrap_t : 4;
         enum mali_wrap_mode wrap_r : 4;
-        enum mali_alt_func compare_func : 3;
+        enum mali_func compare_func : 3;
 
         /* No effect on 2D textures. For cubemaps, set for ES3 and clear for
          * ES2, controlling seamless cubemapping */
@@ -1291,11 +1338,6 @@ struct mali_viewport {
 
 #define MALI_TILE_COORD_X(coord) ((coord) & MALI_X_COORD_MASK)
 #define MALI_TILE_COORD_Y(coord) (((coord) & MALI_Y_COORD_MASK) >> 16)
-#define MALI_TILE_COORD_FLAGS(coord) ((coord) & ~(MALI_X_COORD_MASK | MALI_Y_COORD_MASK))
-
-/* No known flags yet, but just in case...? */
-
-#define MALI_TILE_NO_FLAG (0)
 
 /* Helpers to generate tile coordinates based on the boundary coordinates in
  * screen space. So, with the bounds (0, 0) to (128, 128) for the screen, these
@@ -1320,9 +1362,10 @@ struct mali_payload_fragment {
 /* Flags apply to format. With just MSAA_A and MSAA_B, the framebuffer is
  * configured for 4x. With MSAA_8, it is configured for 8x. */
 
-#define MALI_FRAMEBUFFER_MSAA_8 (1 << 3)
-#define MALI_FRAMEBUFFER_MSAA_A (1 << 4)
-#define MALI_FRAMEBUFFER_MSAA_B (1 << 23)
+#define MALI_SFBD_FORMAT_MSAA_8 (1 << 3)
+#define MALI_SFBD_FORMAT_MSAA_A (1 << 4)
+#define MALI_SFBD_FORMAT_MSAA_B (1 << 4)
+#define MALI_SFBD_FORMAT_SRGB  (1 << 5)
 
 /* Fast/slow based on whether all three buffers are cleared at once */
 
@@ -1334,6 +1377,20 @@ struct mali_payload_fragment {
  * 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 */
@@ -1344,7 +1401,9 @@ struct midgard_tiler_descriptor {
          * 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. */
+         * of tiler_flags set in the kernel, but no comment why.
+         *
+         * hierarchy_mask can have the TILER_DISABLED flag */
 
         u16 hierarchy_mask;
         u16 flags;
@@ -1364,17 +1423,41 @@ struct midgard_tiler_descriptor {
         u32 weights[8];
 };
 
+enum mali_block_format {
+        MALI_BLOCK_TILED   = 0x0,
+        MALI_BLOCK_UNKNOWN = 0x1,
+        MALI_BLOCK_LINEAR  = 0x2,
+        MALI_BLOCK_AFBC    = 0x3,
+};
+
+struct mali_sfbd_format {
+        /* 0x1 */
+        unsigned unk1 : 6;
+
+        /* mali_channel_swizzle */
+        unsigned swizzle : 12;
+
+        /* MALI_POSITIVE */
+        unsigned nr_channels : 2;
+
+        /* 0x4 */
+        unsigned unk2 : 6;
+
+        enum mali_block_format block : 2;
+
+        /* 0xb */
+        unsigned unk3 : 4;
+};
+
 struct mali_single_framebuffer {
         u32 unknown1;
         u32 unknown2;
-        u64 unknown_address_0;
+        mali_ptr scratchpad;
+
         u64 zero1;
         u64 zero0;
 
-        /* Exact format is ironically not known, since EGL is finnicky with the
-         * blob. MSAA, colourspace, etc are configured here. */
-
-        u32 format;
+        struct mali_sfbd_format format;
 
         u32 clear_flags;
         u32 zero2;
@@ -1385,7 +1468,10 @@ struct mali_single_framebuffer {
         u16 width;
         u16 height;
 
-        u32 zero3[8];
+        u32 zero3[4];
+        mali_ptr checksum;
+        u32 checksum_stride;
+        u32 zero5;
 
         /* By default, the framebuffer is upside down from OpenGL's
          * perspective. Set framebuffer to the end and negate the stride to
@@ -1403,10 +1489,14 @@ struct mali_single_framebuffer {
          * disabled. */
 
         mali_ptr depth_buffer; // not SAME_VA
-        u64 depth_buffer_enable;
+        u32 depth_stride_zero : 4;
+        u32 depth_stride : 28;
+        u32 zero7;
 
         mali_ptr stencil_buffer; // not SAME_VA
-        u64 stencil_buffer_enable;
+        u32 stencil_stride_zero : 4;
+        u32 stencil_stride : 28;
+        u32 zero8;
 
         u32 clear_color_1; // RGBA8888 from glClear, actually used by hardware
         u32 clear_color_2; // always equal, but unclear function?
@@ -1433,7 +1523,7 @@ struct mali_single_framebuffer {
  * of compute jobs. Superficially resembles a single framebuffer descriptor */
 
 struct mali_compute_fbd {
-        u32 unknown1[16];
+        u32 unknown1[8];
 } __attribute__((packed));
 
 /* Format bits for the render target flags */
@@ -1441,13 +1531,6 @@ struct mali_compute_fbd {
 #define MALI_MFBD_FORMAT_MSAA    (1 << 1)
 #define MALI_MFBD_FORMAT_SRGB    (1 << 2)
 
-enum mali_mfbd_block_format {
-        MALI_MFBD_BLOCK_TILED   = 0x0,
-        MALI_MFBD_BLOCK_UNKNOWN = 0x1,
-        MALI_MFBD_BLOCK_LINEAR  = 0x2,
-        MALI_MFBD_BLOCK_AFBC    = 0x3,
-};
-
 struct mali_rt_format {
         unsigned unk1 : 32;
         unsigned unk2 : 3;
@@ -1455,12 +1538,21 @@ struct mali_rt_format {
         unsigned nr_channels : 2; /* MALI_POSITIVE */
 
         unsigned unk3 : 5;
-        enum mali_mfbd_block_format block : 2;
+        enum mali_block_format block : 2;
         unsigned flags : 4;
 
         unsigned swizzle : 12;
 
-        unsigned unk4 : 4;
+        unsigned zero : 3;
+
+        /* Disables MFBD preload. When this bit is set, the render target will
+         * be cleared every frame. When this bit is clear, the hardware will
+         * automatically wallpaper the render target back from main memory.
+         * Unfortunately, MFBD preload is very broken on Midgard, so in
+         * practice, this is a chicken bit that should always be set.
+         * Discovered by accident, as all good chicken bits are. */
+
+        unsigned no_preload : 1;
 } __attribute__((packed));
 
 struct bifrost_render_target {
@@ -1468,27 +1560,21 @@ struct bifrost_render_target {
 
         u64 zero1;
 
-        union {
-                struct {
-                        /* Stuff related to ARM Framebuffer Compression. When AFBC is enabled,
-                         * there is an extra metadata buffer that contains 16 bytes per tile.
-                         * The framebuffer needs to be the same size as before, since we don't
-                         * know ahead of time how much space it will take up. The
-                         * framebuffer_stride is set to 0, since the data isn't stored linearly
-                         * anymore.
-                         */
-
-                        mali_ptr metadata;
-                        u32 stride; // stride in units of tiles
-                        u32 unk; // = 0x20000
-                } afbc;
-
-                struct {
-                        /* Heck if I know */
-                        u64 unk;
-                        mali_ptr pointer;
-                } chunknown;
-        };
+        struct {
+                /* Stuff related to ARM Framebuffer Compression. When AFBC is enabled,
+                 * there is an extra metadata buffer that contains 16 bytes per tile.
+                 * The framebuffer needs to be the same size as before, since we don't
+                 * know ahead of time how much space it will take up. The
+                 * framebuffer_stride is set to 0, since the data isn't stored linearly
+                 * anymore.
+                 *
+                 * When AFBC is disabled, these fields are zero.
+                 */
+
+                mali_ptr metadata;
+                u32 stride; // stride in units of tiles
+                u32 unk; // = 0x20000
+        } afbc;
 
         mali_ptr framebuffer;
 
@@ -1567,7 +1653,8 @@ struct bifrost_fb_extra {
 #define MALI_MFBD_EXTRA (1 << 13)
 
 struct bifrost_framebuffer {
-        u32 unk0; // = 0x10
+        u32 stack_shift : 4;
+        u32 unk0 : 28;
 
         u32 unknown2; // = 0x1f, same as SFBD
         mali_ptr scratchpad;