Commit 0dddbcdf authored by Connor Abbott's avatar Connor Abbott

panwrap: Rewrite panwrap decoding and add Bifrost support

In order to properly support 64-bit jobs as well as Bifrost, a number of
structures need to be moved around, split, etc. which requires a lot of
shuffling things around. I think this would probably be hard to untangle
from the actual new Bifrost bits, so I've left everything together in
one commit. The list of things changed includes:

- To save some space due to the larger pointers, vertex and tiler jobs
  no longer have the same layout (i.e. common fields like shader_meta,
  etc. no longer have the same offset). A few of the tiler-only fields
  and vertex-only fields now overlap. The tiler job structure is much
  larger than the vertex job structure, although most of the new fields
  are zero for the things I've tried so far. It's not clear whether this
  also also happens on Midgard 64-bit jobs. In addition, there is a new
  Bifrost-only fused job type, where the common fields in the beginning
  are shared. The end result is that there is now a common prefix,
  followed by tiler-only or vertex-only fields (or both, for Midgard),
  and then a common postfix.
- For Bifrost, we no longer have to make a special incomplete FBD just
  for vertex and tiler jobs. Instead, the relevant fields (tiler_meta
  and the scratchpad) have been moved out into separate structures, and
  removed from the FBD when not needed for fragment jobs.
- There is no Bifrost driver that uses the SFBD, so we need to decode
  the MFBD now.
parent a9ca7ce2
......@@ -198,8 +198,6 @@ struct mali_blend_equation {
/* Corresponds to MALI_MASK_* above and glColorMask arguments */
unsigned color_mask : 4;
unsigned padding : 32;
} __attribute__((packed));
/* Alpha coverage is encoded as 4-bits (from a clampf), with inversion
......@@ -212,33 +210,51 @@ struct mali_blend_equation {
/* Applies to unknown1 */
#define MALI_NO_ALPHA_TO_COVERAGE (1 << 10)
struct mali_tripipe {
mali_ptr shader;
struct mali_blend_meta {
u32 unk1; // = 0x200
struct mali_blend_equation blend_equation;
/*
* - 0x19 normally
* - 0x3 when this slot is unused (everything else is 0 except the index)
* - 0x11 when this is the fourth slot (and it's used)
*/
u16 unk2;
/* increments from 0 to 3 */
u16 index;
u32 unk3; // = 0x10ed688
} __attribute__((packed));
u16 texture_count;
struct mali_shader_meta {
mali_ptr shader;
u16 texture_count;
u16 sampler_count;
/* Counted as number of address slots (i.e. half-precision vec4's) */
u16 attribute_count;
u16 varying_count;
/* 0x200 except MALI_NO_ALPHA_TO_COVERAGE. Mysterious 1 other times. Who knows really? */
u16 unknown1;
union {
struct {
u32 uses_uniforms : 1;
u32 unk1 : 31; // = 0x4000000 for vertex, 0x4ac0100 for tiler
} bifrost1;
struct {
/* 0x200 except MALI_NO_ALPHA_TO_COVERAGE. Mysterious 1
* other times. Who knows really? */
u16 unknown1;
/* Whole number of uniform registers used, times two;
* whole number of work registers used (no scale).
*/
unsigned work_count : 5;
unsigned uniform_count : 5;
unsigned unknown2 : 6;
} midgard1;
};
/* Whole number of uniform registers used, times two; whole number of
* work registers used (no scale).
/* On bifrost: Exactly the same as glPolygonOffset() for both.
* On midgard: Depth factor is exactly as passed to glPolygonOffset.
* Depth units is equal to the value passed to glDeptOhffset + 1.0f
* (use MALI_NEGATIVE)
*/
unsigned work_count : 5;
unsigned uniform_count : 5;
unsigned unknown2 : 6;
} __attribute__((packed));
struct mali_fragment_core {
/* Depth factor is exactly as passed to glDepthOffset. Depth units is
* equal to the value passed to glDeptOhffset + 1.0f (use
* MALI_NEGATIVE) */
float depth_units;
float depth_factor;
......@@ -254,24 +270,41 @@ struct mali_fragment_core {
struct mali_stencil_test stencil_front;
struct mali_stencil_test stencil_back;
u32 unknown2_7;
union {
struct {
u32 unk3 : 15; // = 0x6000
/* In units of 8 bytes or 64 bits, since the
* uniform/const port loads 64 bits at a time.
*/
u32 uniform_count : 7;
u32 unk4 : 10; // = 2
} bifrost2;
struct {
u32 unknown2_7;
} midgard2;
};
/* zero on bifrost */
u32 unknown2_8;
/* Check for MALI_HAS_BLEND_SHADER to decide how to interpret */
/* Blending information for the older non-MRT Midgard HW. Check for
* MALI_HAS_BLEND_SHADER to decide how to interpret.
*/
union {
mali_ptr blend_shader;
/* Exact format of this is not known yet */
struct mali_blend_equation blend_equation;
struct {
struct mali_blend_equation blend_equation;
u32 padding;
};
};
} __attribute__((packed));
/* See the presentations about Mali architecture for why these are together like this */
struct mali_shader_meta {
struct mali_tripipe tripipe;
struct mali_fragment_core fragment_core;
/* There can be up to 4 blend_meta's. None of them are required for
* vertex shaders or the non-MRT case for Midgard (so the blob doesn't
* allocate any space).
*/
struct mali_blend_meta blend_meta[];
} __attribute__((packed));
/* This only concerns hardware jobs */
......@@ -376,15 +409,23 @@ enum mali_fbd_type {
#define FBD_TYPE (1)
#define FBD_MASK (~0x3f)
/* Applies to unknown_draw */
#define MALI_DRAW_INDEXED_UINT8 (0x10)
#define MALI_DRAW_INDEXED_UINT16 (0x20)
#define MALI_DRAW_INDEXED_UINT32 (0x30)
struct mali_unknown1 {
u8 flags;
/* Yes, this really isn't aligned. Go figure. It points to a buffer of
* size 48 for vertex jobs and 32 for tiler jobs which is part of the
* cmdstream, which so far is always 0.
*/
mali_ptr ptr;
/* padding? */
u64 zero : 64 - 8;
} __attribute__((packed));
struct mali_payload_vertex_tiler {
/* Exactly as passed to glLineWidth */
float line_width;
/* On Bifrost, these fields are the same between the vertex and tiler payloads.
* They also seem to be the same between Bifrost and Midgard. They're shared in
* fused payloads.
*/
struct mali_vertex_tiler_prefix {
/* Off by one */
u32 vertex_count;
......@@ -408,17 +449,67 @@ struct mali_payload_vertex_tiler {
* once! NULL for non-indexed draws. */
uintptr_t indices;
} __attribute__((packed));
u32 zero3;
u32 gl_enables; // 0x5
struct bifrost_vertex_only {
u32 unk2; /* =0x2 */
/* Offset for first vertex in buffer */
u32 draw_start;
u32 zero0;
u32 zero5;
u64 zero1;
} __attribute__((packed));
struct bifrost_tiler_heap_meta {
u32 zero;
u32 heap_size;
/* note: these are just guesses! */
mali_ptr tiler_heap_start;
mali_ptr tiler_heap_free;
mali_ptr tiler_heap_end;
/* hierarchy weights? but they're still 0 after the job has run... */
u32 zeros[12];
} __attribute__((packed));
struct bifrost_tiler_meta {
u64 zero0;
u32 unk; // = 0xf0
u16 width;
u16 height;
u64 zero1;
mali_ptr tiler_heap_meta;
/* TODO wtf is this used for */
u64 zeros[20];
} __attribute__((packed));
struct bifrost_tiler_only {
/* 0x20 */
float line_width;
u32 zero0;
mali_ptr tiler_meta;
u64 zero1, zero2, zero3, zero4, zero5, zero6;
u32 gl_enables;
u32 zero7;
u64 zero8;
} __attribute__((packed));
struct bifrost_scratchpad {
u32 zero;
u32 flags; // = 0x1f
/* This is a pointer to a CPU-inaccessible buffer, 16 pages, allocated
* during startup. It seems to serve the same purpose as the
* gpu_scratchpad in the SFBD for Midgard, although it's slightly
* larger.
*/
mali_ptr gpu_scratchpad;
} __attribute__((packed));
struct mali_vertex_tiler_postfix {
/* Zero for vertex jobs. Pointer to the position (gl_Position) varying
* output from the vertex shader for tiler jobs. */
* output from the vertex shader for tiler jobs.
*/
uintptr_t position_varying;
......@@ -439,12 +530,57 @@ struct mali_payload_vertex_tiler {
uintptr_t attributes; /* struct attribute_buffer[] */
uintptr_t attribute_meta; /* attribute_meta[] */
uintptr_t varyings; /* struct attr */
uintptr_t unknown6; /* pointer */
uintptr_t varying_meta; /* pointer */
uintptr_t viewport;
u32 zero6;
uintptr_t zero6;
/* Note: on Bifrost, this isn't actually the FBD. It points to
* bifrost_scratchpad instead. However, it does point to the same thing
* in vertex and tiler jobs.
*/
mali_ptr framebuffer;
#if UINTPTR_MAX == 0xffffffffffffffff /* 64-bit */
/* most likely padding to make this a multiple of 16 bytes */
u64 zero7;
#endif
} __attribute__((packed));
struct midgard_payload_vertex_tiler {
float line_width;
struct mali_vertex_tiler_prefix prefix;
u32 zero3;
u32 gl_enables; // 0x5
/* Offset for first vertex in buffer */
u32 draw_start;
u32 zero5;
struct mali_vertex_tiler_postfix postfix;
} __attribute__((packed));
struct bifrost_payload_vertex {
struct mali_vertex_tiler_prefix prefix;
struct bifrost_vertex_only vertex;
struct mali_vertex_tiler_postfix postfix;
} __attribute__((packed));
struct bifrost_payload_tiler {
struct mali_vertex_tiler_prefix prefix;
struct bifrost_tiler_only tiler;
struct mali_vertex_tiler_postfix postfix;
} __attribute__((packed));
struct bifrost_payload_fused {
struct mali_vertex_tiler_prefix prefix;
struct bifrost_tiler_only tiler;
struct mali_vertex_tiler_postfix tiler_postfix;
struct bifrost_vertex_only vertex;
struct mali_vertex_tiler_postfix vertex_postfix;
} __attribute__((packed));
//ASSERT_SIZEOF_TYPE(struct mali_payload_vertex_tiler, 256, 256);
/* Pointed to from texture_trampoline, mostly unknown still, haven't
* managed to replay successfully */
......@@ -803,6 +939,113 @@ struct mali_tentative_mfbd {
u8 block4[40];
} __attribute__((packed));
struct bifrost_render_target {
u32 unk1; // = 0x4000000
u32 format;
u64 zero1;
/* 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 afbc_metadata;
u32 afbc_stride; // stride in units of tiles
u32 afbc_unk; // = 0x20000
mali_ptr framebuffer;
u32 zero2 : 4;
u32 framebuffer_stride : 28; // in units of bytes
u32 zero3;
u32 clear_color_1; // RGBA8888 from glClear, actually used by hardware
u32 clear_color_2; // always equal, but unclear function?
u32 clear_color_3; // always equal, but unclear function?
u32 clear_color_4; // always equal, but unclear function?
} __attribute__((packed));
/* An optional part of bifrost_framebuffer. It comes between the main structure
* and the array of render targets. It must be included if any of these are
* enabled:
*
* - Transaction Elimination
* - Depth/stencil
* - TODO: Anything else?
*/
struct bifrost_fb_extra {
mali_ptr checksum;
/* Each tile has an 8 byte checksum, so the stride is "width in tiles * 8" */
u32 checksum_stride;
u32 unk;
union {
/* Note: AFBC is only allowed for 24/8 combined depth/stencil. */
struct {
mali_ptr depth_stencil_afbc_metadata;
u32 depth_stencil_afbc_stride; // in units of tiles
u32 zero1;
mali_ptr depth_stencil;
u64 padding;
} ds_afbc;
struct {
/* Depth becomes depth/stencil in case of combined D/S */
mali_ptr depth;
u32 depth_stride_zero : 4;
u32 depth_stride : 28;
u32 zero1;
mali_ptr stencil;
u32 stencil_stride_zero : 4;
u32 stencil_stride : 28;
u32 zero2;
} ds_linear;
};
u64 zero3, zero4;
} __attribute__((packed));
/* flags for unk3 */
#define MALI_MFBD_EXTRA (1 << 13)
struct bifrost_framebuffer {
u32 unk0; // = 0x10
u32 zero1;
u64 zero2;
/* 0x10 */
mali_ptr sample_locations;
mali_ptr unknown1;
/* 0x20 */
u16 width1, height1;
u32 zero3;
u16 width2, height2;
u32 unk1 : 19; // = 0x01000
u32 rt_count_1 : 2; // off-by-one (use MALI_POSITIVE)
u32 unk2 : 3; // = 0
u32 rt_count_2 : 3; // no off-by-one
u32 zero4 : 5;
/* 0x30 */
u32 clear_stencil : 8;
u32 unk3 : 24; // = 0x100
float clear_depth;
mali_ptr tiler_meta;
/* 0x40 */
u64 zero5, zero6, zero7, zero8, zero9, zero10, zero11, zero12;
/* optional: struct bifrost_fb_extra extra */
/* struct bifrost_render_target rts[] */
} __attribute__((packed));
/* Originally from chai, which found it from mali_kase_reply.c */
#endif /* __MALI_JOB_H__ */
......@@ -26,6 +26,12 @@
free(a); \
}
#define MEMORY_COMMENT(obj, p) {\
char *a = pointer_as_memory_reference(obj->p); \
panwrap_msg("%s = %s\n", #p, a); \
free(a); \
}
#define DYN_MEMORY_PROP(obj, no, p) { \
if (obj->p) \
panwrap_prop("%s = %s_%d_p", #p, #p, no); \
......@@ -183,9 +189,9 @@ static char *panwrap_stencil_op_name(enum mali_stencil_op op)
#undef DEFINE_CASE
#define DEFINE_CASE(name) case MALI_CHANNEL_## name: return "MALI_CHANNEL_" #name
static char *panwrap_channel_name(enum mali_stencil_op op)
static char *panwrap_channel_name(enum mali_channel channel)
{
switch(op) {
switch(channel) {
DEFINE_CASE(RED);
DEFINE_CASE(GREEN);
DEFINE_CASE(BLUE);
......@@ -332,8 +338,223 @@ panwrap_replay_sfbd(uint64_t gpu_va, int job_no)
TOUCH(mem, (mali_ptr) gpu_va, *s, "framebuffer", job_no, true);
}
void panwrap_replay_mfbd_bfr(uint64_t gpu_va, int job_no)
{
struct panwrap_mapped_memory *mem = panwrap_find_mapped_gpu_mem_containing(gpu_va);
const struct bifrost_framebuffer *PANWRAP_PTR_VAR(fb, mem, (mali_ptr) gpu_va);
/* The blob stores all possible sample locations in a single buffer
* allocated on startup, and just switches the pointer when switching
* MSAA state. For now, we just put the data into the cmdstream, but we
* should do something like what the blob does with a real driver.
*
* There seem to be 32 slots for sample locations, followed by another
* 16. The second 16 is just the center location followed by 15 zeros
* in all the cases I've identified (maybe shader vs. depth/color
* samples?).
*/
struct panwrap_mapped_memory *smem = panwrap_find_mapped_gpu_mem_containing(fb->sample_locations);
const u16 *PANWRAP_PTR_VAR(samples, smem, fb->sample_locations);
panwrap_log("uint16_t sample_locations_%d[] = {\n", job_no);
panwrap_indent++;
for (int i = 0; i < 32 + 16; i++) {
panwrap_log("%d, %d,\n", samples[2*i], samples[2*i+1]);
}
panwrap_indent--;
panwrap_log("};\n");
TOUCH_LEN(smem, fb->sample_locations, 4 * (32 + 16),
"sample_locations", job_no, true);
panwrap_log("struct bifrost_framebuffer framebuffer_%d = {\n", job_no);
panwrap_indent++;
panwrap_prop("unk0 = 0x%x", fb->unk0);
panwrap_prop("sample_locations = sample_locations_%d", job_no);
/* Assume that unknown1 and tiler_meta were emitted in the last job for
* now */
panwrap_prop("unknown1 = unknown1_%d", job_no - 1);
panwrap_prop("tiler_meta = tiler_meta_%d", job_no - 1);
panwrap_prop("width1 = MALI_POSITIVE(%d)", fb->width1 + 1);
panwrap_prop("height1 = MALI_POSITIVE(%d)", fb->height1 + 1);
panwrap_prop("width2 = MALI_POSITIVE(%d)", fb->width2 + 1);
panwrap_prop("height2 = MALI_POSITIVE(%d)", fb->height2 + 1);
panwrap_prop("unk1 = 0x%x", fb->unk1);
panwrap_prop("unk2 = 0x%x", fb->unk2);
panwrap_prop("rt_count_1 = MALI_POSITIVE(%d)", fb->rt_count_1 + 1);
panwrap_prop("rt_count_2 = %d", fb->rt_count_2);
panwrap_prop("unk3 = 0x%x", fb->unk3);
panwrap_prop("clear_stencil = 0x%x", fb->clear_stencil);
panwrap_prop("clear_depth = %f", fb->clear_depth);
if (fb->zero1 || fb->zero2 || fb->zero3 || fb->zero4 || fb->zero5 || fb->zero6 || fb->zero7 || fb->zero8 || fb->zero9 || fb->zero10 || fb->zero11 || fb->zero12) {
panwrap_msg("framebuffer zeros tripped\n");
panwrap_prop("zero1 = 0x%" PRIx32, fb->zero1);
panwrap_prop("zero2 = 0x%" PRIx64, fb->zero2);
panwrap_prop("zero3 = 0x%" PRIx32, fb->zero3);
panwrap_prop("zero4 = 0x%" PRIx32, fb->zero4);
panwrap_prop("zero5 = 0x%" PRIx64, fb->zero5);
panwrap_prop("zero6 = 0x%" PRIx64, fb->zero6);
panwrap_prop("zero7 = 0x%" PRIx64, fb->zero7);
panwrap_prop("zero8 = 0x%" PRIx64, fb->zero8);
panwrap_prop("zero9 = 0x%" PRIx64, fb->zero9);
panwrap_prop("zero10 = 0x%" PRIx64, fb->zero10);
panwrap_prop("zero11 = 0x%" PRIx64, fb->zero11);
panwrap_prop("zero12 = 0x%" PRIx64, fb->zero12);
}
panwrap_indent--;
panwrap_log("};\n");
TOUCH(mem, (mali_ptr) gpu_va, *fb, "framebuffer", job_no, true);
gpu_va += sizeof(struct bifrost_framebuffer);
if (fb->unk3 & MALI_MFBD_EXTRA) {
mem = panwrap_find_mapped_gpu_mem_containing(gpu_va);
const struct bifrost_fb_extra *PANWRAP_PTR_VAR(fbx, mem, (mali_ptr) gpu_va);
panwrap_log("struct bifrost_fb_extra fb_extra_%d = {\n", job_no);
panwrap_indent++;
MEMORY_PROP(fbx, checksum);
if (fbx->checksum_stride)
panwrap_prop("checksum_stride = %d", fbx->checksum_stride);
panwrap_prop("unk = 0x%x", fbx->unk);
/* TODO figure out if this is actually the right way to
* determine whether AFBC is enabled
*/
if (fbx->unk & 0x10) {
panwrap_log(".ds_afbc = {\n");
panwrap_indent++;
MEMORY_PROP((&fbx->ds_afbc), depth_stencil_afbc_metadata);
panwrap_prop("depth_stencil_afbc_stride = %d",
fbx->ds_afbc.depth_stencil_afbc_stride);
MEMORY_PROP((&fbx->ds_afbc), depth_stencil);
if (fbx->ds_afbc.zero1 || fbx->ds_afbc.padding) {
panwrap_msg("Depth/stencil AFBC zeros tripped\n");
panwrap_prop("zero1 = 0x%" PRIx32,
fbx->ds_afbc.zero1);
panwrap_prop("padding = 0x%" PRIx64,
fbx->ds_afbc.padding);
}
panwrap_indent--;
panwrap_log("},\n");
} else {
panwrap_log(".ds_linear = {\n");
panwrap_indent++;
if (fbx->ds_linear.depth) {
MEMORY_PROP((&fbx->ds_linear), depth);
panwrap_prop("depth_stride = %d",
fbx->ds_linear.depth_stride);
}
if (fbx->ds_linear.stencil) {
MEMORY_PROP((&fbx->ds_linear), stencil);
panwrap_prop("stencil_stride = %d",
fbx->ds_linear.stencil_stride);
}
if (fbx->ds_linear.depth_stride_zero ||
fbx->ds_linear.stencil_stride_zero ||
fbx->ds_linear.zero1 || fbx->ds_linear.zero2) {
panwrap_msg("Depth/stencil zeros tripped\n");
panwrap_prop("depth_stride_zero = 0x%x",
fbx->ds_linear.depth_stride_zero);
panwrap_prop("stencil_stride_zero = 0x%x",
fbx->ds_linear.stencil_stride_zero);
panwrap_prop("zero1 = 0x%" PRIx32,
fbx->ds_linear.zero1);
panwrap_prop("zero2 = 0x%" PRIx32,
fbx->ds_linear.zero2);
}
panwrap_indent--;
panwrap_log("},\n");
}
if (fbx->zero3 || fbx->zero4) {
panwrap_msg("fb_extra zeros tripped\n");
panwrap_prop("zero3 = 0x%" PRIx64, fbx->zero3);
panwrap_prop("zero4 = 0x%" PRIx64, fbx->zero4);
}
panwrap_indent--;
panwrap_log("};\n");
TOUCH(mem, (mali_ptr) gpu_va, *fbx, "fb_extra", job_no, true);
gpu_va += sizeof(struct bifrost_fb_extra);
}
/* TODO: which number actually describes how many entries there are? I
* haven't been able to find a case where they differ.
*/
panwrap_log("struct bifrost_render_target rts[] = {\n");
panwrap_indent++;
for (int i = 0; i < fb->rt_count_2; i++) {
mali_ptr rt_va = gpu_va + i * sizeof(struct bifrost_render_target);
mem = panwrap_find_mapped_gpu_mem_containing(rt_va);
const struct bifrost_render_target *PANWRAP_PTR_VAR(rt, mem, (mali_ptr) rt_va);
panwrap_log("{\n");
panwrap_indent++;
panwrap_prop("unk1 = 0x%" PRIx32, rt->unk1);
panwrap_prop("format = 0x%" PRIx32, rt->format);
MEMORY_PROP(rt, afbc_metadata);
panwrap_prop("afbc_stride = %d", rt->afbc_stride);
panwrap_prop("afbc_unk = 0x%" PRIx32, rt->afbc_unk);
MEMORY_PROP(rt, framebuffer);
panwrap_prop("framebuffer_stride = %d", rt->framebuffer_stride);
if (rt->clear_color_1 | rt->clear_color_2 | rt->clear_color_3 | rt->clear_color_4) {
panwrap_prop("clear_color_1 = 0x%" PRIx32, rt->clear_color_1);
panwrap_prop("clear_color_2 = 0x%" PRIx32, rt->clear_color_2);
panwrap_prop("clear_color_3 = 0x%" PRIx32, rt->clear_color_3);
panwrap_prop("clear_color_4 = 0x%" PRIx32, rt->clear_color_4);
}
if (rt->zero1 || rt->zero2 || rt->zero3) {
panwrap_msg("render target zeros tripped");
panwrap_prop("zero1 = 0x%" PRIx64, rt->zero1);
panwrap_prop("zero2 = 0x%" PRIx32, rt->zero2);
panwrap_prop("zero3 = 0x%" PRIx32, rt->zero3);
}
panwrap_indent--;
panwrap_log("},\n");
}
panwrap_indent--;
panwrap_log("};\n");
TOUCH_LEN(mem, (mali_ptr) gpu_va, fb->rt_count_2 * sizeof(struct bifrost_render_target), "rts", job_no, true);
}
void panwrap_replay_attributes(const struct panwrap_mapped_memory *mem,
mali_ptr addr, int job_no, int count, bool varying)
mali_ptr addr, int job_no, char *suffix,
int count, bool varying)
{
char *prefix = varying ? "varyings" : "attributes";
......@@ -343,7 +564,7 @@ void panwrap_replay_attributes(const struct panwrap_mapped_memory *mem,
struct mali_attr *attr = panwrap_fetch_gpu_mem(mem, addr, sizeof(struct mali_attr) * count);
char base[128];
snprintf(base, sizeof(base), "%s_data_%d", prefix, job_no);
snprintf(base, sizeof(base), "%s_data_%d%s", prefix, job_no, suffix);
for (int i = 0; i < count; ++i) {
mali_ptr raw_elements = attr[i].elements & ~3;
......@@ -453,8 +674,8 @@ panwrap_replay_stencil(const char *name, const struct mali_stencil_test *stencil
static void
panwrap_replay_blend_equation(const struct mali_blend_equation *blend)
{
if (blend->zero1 || blend->padding)
panwrap_msg("Blend zero tripped: %X, %X\n", blend->zero1, blend->padding);
if (blend->zero1)
panwrap_msg("Blend zero tripped: %X\n", blend->zero1);
panwrap_log(".blend_equation = {\n");
panwrap_indent++;
......@@ -471,17 +692,17 @@ panwrap_replay_blend_equation(const struct mali_blend_equation *blend)
}
static void
panwrap_replay_attribute_meta(int job_no, int count, const struct mali_payload_vertex_tiler *v, bool varying)
panwrap_replay_attribute_meta(int job_no, int count, const struct mali_vertex_tiler_postfix *v, bool varying, char *suffix)
{
char base[128];
char *prefix = varying ? "varying" : "attribute";
snprintf(base, sizeof(base), "%s_meta", prefix);
panwrap_log("struct mali_attr_meta %s_%d[] = {\n", base, job_no);
panwrap_log("struct mali_attr_meta %s_%d%s[] = {\n", base, job_no, suffix);
panwrap_indent++;
struct mali_attr_meta *attr_meta;