panwrap-decoder.c 34.9 KB
Newer Older
1
/*
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
2
 * © Copyright 2017-2018 The Panfrost Community
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * A copy of the licence is included with the program, and can also be obtained
 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 */

#include "panwrap.h"
#include <mali-ioctl.h>
#include <mali-job.h>
18
#include <stdio.h>
19
#include <memory.h>
20

21 22
#include "panwrap-shader.h"

23 24
#define MEMORY_PROP(obj, p) {\
	char *a = pointer_as_memory_reference(obj->p); \
25 26 27 28
	panwrap_prop("%s = %s", #p, a); \
	free(a); \
}

29 30 31 32 33
#define DYN_MEMORY_PROP(obj, no, p) { \
	if (obj->p) \
		panwrap_prop("%s = %s_%d_p", #p, #p, no); \
}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
34 35
#define FLAG_INFO(flag) { MALI_GL_##flag, "MALI_GL_" #flag }
static const struct panwrap_flag_info gl_enable_flag_info[] = {
36 37
	FLAG_INFO(CULL_FACE_FRONT),
	FLAG_INFO(CULL_FACE_BACK),
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
38 39 40 41
	{}
};
#undef FLAG_INFO

42 43 44 45 46 47 48 49 50
#define FLAG_INFO(flag) { MALI_CLEAR_##flag, "MALI_CLEAR_" #flag }
static const struct panwrap_flag_info clear_flag_info[] = {
	FLAG_INFO(FAST),
	FLAG_INFO(SLOW),
	FLAG_INFO(SLOW_STENCIL),
	{}
};
#undef FLAG_INFO

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
51 52 53 54 55 56 57 58 59 60
#define FLAG_INFO(flag) { MALI_MASK_##flag, "MALI_MASK_" #flag }
static const struct panwrap_flag_info mask_flag_info[] = {
	FLAG_INFO(R),
	FLAG_INFO(G),
	FLAG_INFO(B),
	FLAG_INFO(A),
	{}
};
#undef FLAG_INFO

61 62
#define FLAG_INFO(flag) { MALI_##flag, "MALI_" #flag }
static const struct panwrap_flag_info u3_flag_info[] = {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
63
	FLAG_INFO(HAS_MSAA),
64 65
	FLAG_INFO(CAN_DISCARD),
	FLAG_INFO(HAS_BLEND_SHADER),
66
	FLAG_INFO(DEPTH_TEST),
67 68
	{}
};
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
69 70 71

static const struct panwrap_flag_info u4_flag_info[] = {
	FLAG_INFO(NO_MSAA),
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
72
	FLAG_INFO(NO_DITHER),
73 74
	FLAG_INFO(DEPTH_RANGE_A),
	FLAG_INFO(DEPTH_RANGE_B),
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
75
	FLAG_INFO(STENCIL_TEST),
76
	FLAG_INFO(SAMPLE_ALPHA_TO_COVERAGE_NO_BLEND_SHADER),
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
77 78
	{}
};
79
#undef FLAG_INFO
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
80

81 82 83 84 85 86 87
#define FLAG_INFO(flag) { MALI_FRAMEBUFFER_##flag, "MALI_FRAMEBUFFER_" #flag }
static const struct panwrap_flag_info u2_flag_info[] = {
	FLAG_INFO(MSAA_A),
	FLAG_INFO(MSAA_B),
	FLAG_INFO(MSAA_8),
	{}
};
88
#undef FLAG_INFO
89

90 91
extern char* replace_fragment;
extern char* replace_vertex;
92 93 94

static char *panwrap_job_type_name(enum mali_job_type type)
{
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
95
#define DEFINE_CASE(name) case JOB_TYPE_ ## name: return "JOB_TYPE_" #name
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
	switch (type) {
	DEFINE_CASE(NULL);
	DEFINE_CASE(SET_VALUE);
	DEFINE_CASE(CACHE_FLUSH);
	DEFINE_CASE(COMPUTE);
	DEFINE_CASE(VERTEX);
	DEFINE_CASE(TILER);
	DEFINE_CASE(FUSED);
	DEFINE_CASE(FRAGMENT);
	case JOB_NOT_STARTED:
		return "NOT_STARTED";
	default:
		panwrap_log("Warning! Unknown job type %x\n", type);
		return "!?!?!?";
	}
#undef DEFINE_CASE
}

static char *panwrap_gl_mode_name(enum mali_gl_mode mode)
{
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
116
#define DEFINE_CASE(name) case MALI_ ## name: return "MALI_" #name
117 118 119 120 121 122
	switch(mode) {
	DEFINE_CASE(GL_POINTS);
	DEFINE_CASE(GL_LINES);
	DEFINE_CASE(GL_TRIANGLES);
	DEFINE_CASE(GL_TRIANGLE_STRIP);
	DEFINE_CASE(GL_TRIANGLE_FAN);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
123 124
	DEFINE_CASE(GL_LINE_STRIP);
	DEFINE_CASE(GL_LINE_LOOP);
125 126 127 128 129
	default: return "MALI_GL_TRIANGLES /* XXX: Unknown GL mode, check dump */";
	}
#undef DEFINE_CASE
}

130 131
#define DEFINE_CASE(name) case MALI_FUNC_ ## name: return "MALI_FUNC_" #name
static char *panwrap_func_name(enum mali_func mode)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
132 133 134 135 136 137 138 139 140 141
{
	switch(mode) {
	DEFINE_CASE(NEVER);
	DEFINE_CASE(LESS);
	DEFINE_CASE(EQUAL);
	DEFINE_CASE(LEQUAL);
	DEFINE_CASE(GREATER);
	DEFINE_CASE(NOTEQUAL);
	DEFINE_CASE(GEQUAL);
	DEFINE_CASE(ALWAYS);
142
	default: return "MALI_FUNC_NEVER /* XXX: Unknown function, check dump */";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
143 144
	}
}
145
#undef DEFINE_CASE
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
146

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
/* Why is this duplicated? Who knows... */
#define DEFINE_CASE(name) case MALI_ALT_FUNC_ ## name: return "MALI_ALT_FUNC_" #name
static char *panwrap_alt_func_name(enum mali_alt_func mode)
{
	switch(mode) {
	DEFINE_CASE(NEVER);
	DEFINE_CASE(LESS);
	DEFINE_CASE(EQUAL);
	DEFINE_CASE(LEQUAL);
	DEFINE_CASE(GREATER);
	DEFINE_CASE(NOTEQUAL);
	DEFINE_CASE(GEQUAL);
	DEFINE_CASE(ALWAYS);
	default: return "MALI_FUNC_NEVER /* XXX: Unknown function, check dump */";
	}
}
#undef DEFINE_CASE



167
#define DEFINE_CASE(name) case MALI_STENCIL_ ## name: return "MALI_STENCIL_" #name
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
static char *panwrap_stencil_op_name(enum mali_stencil_op op)
{
	switch(op) {
	DEFINE_CASE(KEEP);
	DEFINE_CASE(REPLACE);
	DEFINE_CASE(ZERO);
	DEFINE_CASE(INVERT);
	DEFINE_CASE(INCR_WRAP);
	DEFINE_CASE(DECR_WRAP);
	DEFINE_CASE(INCR);
	DEFINE_CASE(DECR);
	default: return "MALI_STENCIL_KEEP /* XXX: Unknown stencil op, check dump */";
	}
}

#undef DEFINE_CASE

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
#define DEFINE_CASE(name) case MALI_CHANNEL_## name: return "MALI_CHANNEL_" #name
static char *panwrap_channel_name(enum mali_stencil_op op)
{
	switch(op) {
	DEFINE_CASE(RED);
	DEFINE_CASE(GREEN);
	DEFINE_CASE(BLUE);
	DEFINE_CASE(ALPHA);
	DEFINE_CASE(ZERO);
	DEFINE_CASE(ONE);
	DEFINE_CASE(RESERVED_0);
	DEFINE_CASE(RESERVED_1);
	default: return "MALI_CHANNEL_ZERO /* XXX: Unknown channel, check dump */";
	}
}
#undef DEFINE_CASE

202 203 204 205 206 207 208 209 210 211 212 213
#define DEFINE_CASE(name) case MALI_WRAP_## name: return "MALI_WRAP_" #name
static char *panwrap_wrap_mode_name(enum mali_wrap_mode op)
{
	switch(op) {
	DEFINE_CASE(REPEAT);
	DEFINE_CASE(CLAMP_TO_EDGE);
	DEFINE_CASE(MIRRORED_REPEAT);
	default: return "MALI_WRAP_REPEAT /* XXX: Unknown wrap mode, check dump */";
	}
}
#undef DEFINE_CASE

214 215 216 217 218 219 220
static inline char *panwrap_decode_fbd_type(enum mali_fbd_type type)
{
	if (type == MALI_SFBD)      return "SFBD";
	else if (type == MALI_MFBD) return "MFBD";
	else return "WTF!?";
}

221
static bool
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
222
panwrap_deduplicate(const struct panwrap_mapped_memory *mem, uint64_t gpu_va, const char *name, int number)
223 224 225 226 227 228 229 230 231 232 233 234
{
	if (mem->touched[(gpu_va - mem->gpu_va) / sizeof(uint32_t)]) {
		/* XXX: Is this correct? */
		panwrap_log("mali_ptr %s_%d_p = %s_%d_p;\n", name, number, name, number - 1);
		return true;
	}

	return false;
}

static void
panwrap_replay_sfbd(uint64_t gpu_va, int job_no)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
235
{
236
	struct panwrap_mapped_memory *mem = panwrap_find_mapped_gpu_mem_containing(gpu_va);
237
	const struct mali_single_framebuffer *PANWRAP_PTR_VAR(s, mem, (mali_ptr) gpu_va);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
238

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
239
	/* FBDs are frequently duplicated, so watch for this */
240
	if (panwrap_deduplicate(mem, gpu_va, "framebuffer", job_no)) return;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
241

242
	panwrap_log("struct mali_single_framebuffer framebuffer_%d = {\n", job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
243 244 245 246 247
	panwrap_indent++;

	panwrap_prop("unknown1 = 0x%" PRIx32, s->unknown1);
	panwrap_prop("flags = 0x%" PRIx32, s->flags);
	panwrap_prop("heap_free_address = 0x%" PRIx64, s->heap_free_address);
248 249 250 251

	panwrap_log(".unknown2 = ");
	panwrap_log_decoded_flags(u2_flag_info, s->unknown2);
	panwrap_log_cont(",\n");
252

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
253 254
	panwrap_prop("width = MALI_POSITIVE(%" PRId16 ")", s->width + 1);
	panwrap_prop("height = MALI_POSITIVE(%" PRId16 ")", s->height + 1);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
255

256
	MEMORY_PROP(s, framebuffer_end);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
257

258
	panwrap_prop("unknown10 = 0x%" PRIx64, s->unknown10);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
259

260 261 262 263 264 265 266
	/* Earlier in the actual commandstream -- right before width -- but we
	 * delay to flow nicer */

	panwrap_log(".clear_flags = ");
	panwrap_log_decoded_flags(clear_flag_info, s->clear_flags);
	panwrap_log_cont(",\n");

267
	if (s->depth_buffer | s->depth_buffer_enable) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
268
		MEMORY_PROP(s, depth_buffer);
269 270
		panwrap_prop("depth_buffer_enable = %s", DS_ENABLE(s->depth_buffer_enable));
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
271

272
	if (s->stencil_buffer | s->stencil_buffer_enable) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
273
		MEMORY_PROP(s, stencil_buffer);
274 275
		panwrap_prop("stencil_buffer_enable = %s", DS_ENABLE(s->stencil_buffer_enable));
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
276

277 278 279 280 281 282
	if (s->clear_color_1 | s->clear_color_2 | s->clear_color_3 | s->clear_color_4) {
		panwrap_prop("clear_color_1 = 0x%" PRIx32, s->clear_color_1);
		panwrap_prop("clear_color_2 = 0x%" PRIx32, s->clear_color_2);
		panwrap_prop("clear_color_3 = 0x%" PRIx32, s->clear_color_3);
		panwrap_prop("clear_color_4 = 0x%" PRIx32, s->clear_color_4);
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
283

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
284
	if (s->clear_depth_1 != 0 || s->clear_depth_2 != 0 || s->clear_depth_3 != 0 || s->clear_depth_4 != 0) {
285 286 287 288 289
		panwrap_prop("clear_depth_1 = %f", s->clear_depth_1);
		panwrap_prop("clear_depth_2 = %f", s->clear_depth_2);
		panwrap_prop("clear_depth_3 = %f", s->clear_depth_3);
		panwrap_prop("clear_depth_4 = %f", s->clear_depth_4);
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
290

291 292 293
	if (s->clear_stencil) {
		panwrap_prop("clear_stencil = 0x%x", s->clear_stencil);
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
294

295 296 297
	MEMORY_PROP(s, unknown_address_0);
	MEMORY_PROP(s, unknown_address_1);
	MEMORY_PROP(s, unknown_address_2);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
298 299 300 301

	panwrap_prop("unknown8 = 0x%" PRIx32, s->unknown8);
	panwrap_prop("unknown9 = 0x%" PRIx32, s->unknown9);

302
	MEMORY_PROP(s, tiler_heap_free);
303 304

	MEMORY_PROP(s, unknown_address_4);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
305 306 307 308 309 310 311 312 313 314 315 316 317

	panwrap_indent--;
	panwrap_log("};\n");

	int zero_sum_pun = 0;
	zero_sum_pun += s->zero1;
	zero_sum_pun += s->zero2;
	for (int i = 0; i < sizeof(s->zero3)/sizeof(s->zero3[0]); ++i) zero_sum_pun += s->zero3[i];
	for (int i = 0; i < sizeof(s->zero6)/sizeof(s->zero6[0]); ++i) zero_sum_pun += s->zero6[i];

	if (zero_sum_pun)
		panwrap_msg("Zero sum tripped (%d), replay may be wrong\n", zero_sum_pun);

318
	TOUCH(mem, (mali_ptr) gpu_va, *s, "framebuffer", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
319 320
}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
321
void panwrap_replay_attributes(const struct panwrap_mapped_memory *mem,
322
			       mali_ptr addr, int job_no, int count, bool varying)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
323
{
324
	char *prefix = varying ? "varyings" : "attributes";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
325

326 327
	/* Varyings in particular get duplicated between parts of the job */
	if (panwrap_deduplicate(mem, addr, prefix, job_no)) return;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
328

329
	struct mali_attr *attr = panwrap_fetch_gpu_mem(mem, addr, sizeof(struct mali_attr) * count); 
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
330

331 332
	char base[128];
	snprintf(base, sizeof(base), "%s_data_%d", prefix, job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
333

334 335
	for (int i = 0; i < count; ++i) {
		mali_ptr raw_elements = attr[i].elements & ~3;
336

337 338
		size_t vertex_count;
		size_t component_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
339

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
340 341 342 343
		/* gl_VertexID and gl_InstanceID do not have elements to
		 * decode; we would crash if we tried */

		if (!varying && i < MALI_SPECIAL_ATTRIBUTE_BASE) {
344 345
			/* TODO: Attributes are not necessarily float32 vectors in general;
			 * decoding like this without snarfing types from the shader is unsafe all things considered */
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
346

347 348
			panwrap_msg("i: %d\n", i);
			panwrap_msg("attr: %llx\n", raw_elements);
349
			float *buffer = panwrap_fetch_gpu_mem(mem, raw_elements, attr[i].size);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
350

351 352
			vertex_count = attr[i].size / attr[i].stride;
			component_count = attr[i].stride / sizeof(float);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
353

354
			panwrap_log("float %s_%d[] = {\n", base, i);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
355

356 357 358
			panwrap_indent++;
			for (int row = 0; row < vertex_count; row++) {
				panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
359

360 361
				for (int i = 0; i < component_count; i++)
					panwrap_log_cont("%ff, ", buffer[i]);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
362

363 364 365 366 367 368
				panwrap_log_cont("\n");

				buffer += component_count;
			}
			panwrap_indent--;
			panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
369

370
			TOUCH_LEN(mem, raw_elements, attr[i].size, base, i, true);
371 372 373 374 375 376 377
		} else {
			/* TODO: Allocate space for varyings dynamically? */

			char *a = pointer_as_memory_reference(raw_elements);
			panwrap_log("mali_ptr %s_%d_p = %s;\n", base, i, a);
			free(a);
		}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
378
	}
379

380
	panwrap_log("struct mali_attr %s_%d[] = {\n", prefix, job_no);
381 382
	panwrap_indent++;

383 384 385 386
	for (int i = 0; i < count; ++i) {
		panwrap_log("{\n");
		panwrap_indent++;

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
387
		panwrap_prop("elements = (%s_%d_p) | %d", base, i, (int) (attr[i].elements & 3));
388 389 390 391
		panwrap_prop("stride = 0x%" PRIx32, attr[i].stride);
		panwrap_prop("size = 0x%" PRIx32, attr[i].size);
		panwrap_indent--;
		panwrap_log("}, \n");
392 393 394 395 396
	}

	panwrap_indent--;
	panwrap_log("};\n");

397
	TOUCH_LEN(mem, addr, sizeof(*attr) * count, prefix, job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
398 399
}

400 401 402 403 404 405 406 407 408 409 410 411 412
static mali_ptr
panwrap_replay_shader_address(const char *name, mali_ptr ptr)
{
	/* TODO: Decode flags */
	mali_ptr shader_ptr = ptr & ~15;

	char *a = pointer_as_memory_reference(shader_ptr);
	panwrap_prop("%s = (%s) | %d", name, a, (int) (ptr & 15));
	free(a);

	return shader_ptr;
}

413
static void
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
414
panwrap_replay_stencil(const char *name, const struct mali_stencil_test *stencil)
415
{
416
	const char *func = panwrap_func_name(stencil->func);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
417 418 419
	const char *sfail = panwrap_stencil_op_name(stencil->sfail);
	const char *dpfail = panwrap_stencil_op_name(stencil->dpfail);
	const char *dppass = panwrap_stencil_op_name(stencil->dppass);
420

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
421 422
	if (stencil->zero)
		panwrap_msg("Stencil zero tripped: %X\n", stencil->zero);
423

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
424 425 426 427 428 429 430 431 432 433
	panwrap_log(".stencil_%s = {\n", name);
	panwrap_indent++;
	panwrap_prop("ref = %d", stencil->ref);
	panwrap_prop("mask = 0x%02X", stencil->mask);
	panwrap_prop("func = %s", func);
	panwrap_prop("sfail = %s", sfail);
	panwrap_prop("dpfail = %s", dpfail);
	panwrap_prop("dppass = %s", dppass);
	panwrap_indent--;
	panwrap_log("},\n");
434 435
}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
436
static void
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
437
panwrap_replay_blend_equation(const struct mali_blend_equation *blend)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
438
{
439 440
	if (blend->zero1 || blend->padding)
		panwrap_msg("Blend zero tripped: %X, %X\n", blend->zero1, blend->padding);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
441 442 443 444

	panwrap_log(".blend_equation = {\n");
	panwrap_indent++;

445 446
	panwrap_prop("rgb_mode = 0x%X", blend->rgb_mode);
	panwrap_prop("alpha_mode = 0x%X", blend->alpha_mode);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
447 448 449 450 451 452 453 454 455

	panwrap_log(".color_mask = ");
	panwrap_log_decoded_flags(mask_flag_info, blend->color_mask);
	panwrap_log_cont(",\n");

	panwrap_indent--;
	panwrap_log("},\n");
}

456
static void
457
panwrap_replay_attribute_meta(int job_no, int count, const struct mali_payload_vertex_tiler *v, bool varying)
458 459 460
{
	char base[128];
	char *prefix = varying ? "varying" : "attribute";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
461
	snprintf(base, sizeof(base), "%s_meta", prefix); 
462 463 464 465 466

	panwrap_log("struct mali_attr_meta %s_%d[] = {\n", base, job_no);
	panwrap_indent++;

	struct mali_attr_meta *attr_meta;
467
	mali_ptr p = varying ? (v->unknown6 & ~0xF) : v->attribute_meta;
468 469 470

	struct panwrap_mapped_memory *attr_mem = panwrap_find_mapped_gpu_mem_containing(p);

471
	for (int i = 0; i < count; ++i, p += sizeof(struct mali_attr_meta)) {
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
		attr_meta = panwrap_fetch_gpu_mem(attr_mem, p,
						  sizeof(*attr_mem));

		panwrap_log("{\n");
		panwrap_indent++;
		panwrap_prop("index = %d", attr_meta->index);
		panwrap_prop("type = %d", attr_meta->type);
		panwrap_prop("nr_components = MALI_POSITIVE(%d)", MALI_NEGATIVE(attr_meta->nr_components));

		/* TODO: Dissect correctly */
		panwrap_prop("is_int_signed = %d", attr_meta->is_int_signed);

		panwrap_prop("not_normalised = %d", attr_meta->not_normalised);
		panwrap_prop("unknown1 = 0x%" PRIx64, (u64) attr_meta->unknown1);
		panwrap_prop("unknown2 = 0x%" PRIx64, (u64) attr_meta->unknown2);
		panwrap_prop("unknown3 = 0x%" PRIx64, (u64) attr_meta->unknown3);
		panwrap_indent--;
		panwrap_log("},\n");

	}

	panwrap_indent--;
	panwrap_log("};\n");

	panwrap_msg("not working but touching %d * %d?\n", sizeof(struct mali_attr_meta), count);
	TOUCH_LEN(attr_mem, p, sizeof(struct mali_attr_meta) * count, base, job_no, true);
}

500 501
static int
panwrap_replay_vertex_or_tiler_job(const struct mali_job_descriptor_header *h,
502 503 504 505 506 507
					const struct panwrap_mapped_memory *mem,
					mali_ptr payload, int job_no)
{
	struct mali_payload_vertex_tiler *PANWRAP_PTR_VAR(v, mem, payload);
	struct mali_shader_meta *meta;
	struct panwrap_mapped_memory *attr_mem;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
508
	mali_ptr shader_meta_ptr = (u64) (uintptr_t) (v->_shader_upper << 4);
509

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
510
	/* TODO: Isn't this an -M-FBD? What's the difference? */
511
	panwrap_replay_sfbd((u64) (uintptr_t) v->framebuffer, job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
512

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
513
	int varying_count = 0, attribute_count = 0, uniform_count = 0;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
514

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
515 516 517 518 519 520 521
	if (shader_meta_ptr) {
		struct panwrap_mapped_memory *smem = panwrap_find_mapped_gpu_mem_containing(shader_meta_ptr);
		struct mali_shader_meta *PANWRAP_PTR_VAR(s, smem, shader_meta_ptr);

		panwrap_log("struct mali_shader_meta shader_meta_%d = {\n", job_no);
		panwrap_indent++;

522 523 524
		/* Shader meta contains metadata for the entire shader core */
		struct mali_tripipe *t = &s->tripipe;
		struct mali_fragment_core *f = &s->fragment_core;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
525

526 527 528 529 530 531 532 533 534 535 536
		/* Save for dumps */
		attribute_count = t->attribute_count;
		varying_count = t->varying_count;
		uniform_count = t->uniform_count; 

		panwrap_log(".tripipe = {\n");
		panwrap_indent++;

		mali_ptr shader_ptr = panwrap_replay_shader_address("shader", t->shader);

		if (t->zero1)
537
			panwrap_msg("XXX shader zero tripped\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
538

539 540 541 542
		panwrap_prop("attribute_count = %" PRId16, t->attribute_count);
		panwrap_prop("varying_count = %" PRId16, t->varying_count);
		panwrap_prop("uniform_count = %" PRId16, t->uniform_count);
		panwrap_prop("work_count = %" PRId16, t->work_count);
543
		panwrap_prop("unknown1 = %s0x%" PRIx32,
544 545 546
				t->unknown1 & MALI_NO_ALPHA_TO_COVERAGE ? "MALI_NO_ALPHA_TO_COVERAGE | " : "",
				t->unknown1 & ~MALI_NO_ALPHA_TO_COVERAGE);
		panwrap_prop("unknown2 = 0x%" PRIx32, t->unknown2);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
547

548 549 550 551 552
		panwrap_indent--;
		panwrap_log("},\n");

		panwrap_log(".fragment_core = {\n");
		panwrap_indent++;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
553

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
554

555 556 557
		if (f->depth_units || f->depth_factor) {
			panwrap_prop("depth_units = MALI_NEGATIVE(%f)", f->depth_units - 1.0f);
			panwrap_prop("depth_factor = %f", f->depth_factor);
558
		}
559

560 561
		bool invert_alpha_coverage = f->alpha_coverage & 0xFFF0;
		uint16_t inverted_coverage = invert_alpha_coverage ? ~f->alpha_coverage : f->alpha_coverage;
562 563 564 565 566

		panwrap_prop("alpha_coverage = %sMALI_ALPHA_COVERAGE(%f)",
				invert_alpha_coverage ? "~" : "",
				MALI_GET_ALPHA_COVERAGE(inverted_coverage));

567
		panwrap_log(".unknown2_3 = ");
568

569 570
		int unknown2_3 = f->unknown2_3;
		int unknown2_4 = f->unknown2_4;
571 572 573 574 575 576 577 578 579 580 581 582
		
		/* We're not quite sure what these flags mean without the depth test, if anything */

		if (unknown2_3 & (MALI_DEPTH_TEST | MALI_DEPTH_FUNC_MASK)) {
			const char *func = panwrap_func_name(MALI_GET_DEPTH_FUNC(unknown2_3));
			unknown2_3 &= ~MALI_DEPTH_FUNC_MASK;

			panwrap_log_cont("MALI_DEPTH_FUNC(%s) | ", func);
		}


		panwrap_log_decoded_flags(u3_flag_info, unknown2_3);
583
		panwrap_log_cont(",\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
584

585 586
		panwrap_prop("stencil_mask_front = 0x%02X", f->stencil_mask_front);
		panwrap_prop("stencil_mask_back = 0x%02X", f->stencil_mask_back);
587

588
		panwrap_log(".unknown2_4 = ");
589
		panwrap_log_decoded_flags(u4_flag_info, unknown2_4);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
590 591
		panwrap_log_cont(",\n");

592 593
		panwrap_replay_stencil("front", &f->stencil_front);
		panwrap_replay_stencil("back", &f->stencil_back);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
594

595 596
		panwrap_prop("unknown2_7 = 0x%" PRIx32, f->unknown2_7);
		panwrap_prop("unknown2_8 = 0x%" PRIx32, f->unknown2_8);
597

598 599
		bool blend_shader = false;

600
		if (f->unknown2_3 & MALI_HAS_BLEND_SHADER) {
601
			blend_shader = true;
602
			panwrap_replay_shader_address("blend_shader", f->blend_shader);
603
		} else {
604
			panwrap_replay_blend_equation(&f->blend_equation);
605
		}
606

607 608 609
		panwrap_indent--;
		panwrap_log("}\n");

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
610 611
		panwrap_indent--;
		panwrap_log("};\n");
612

613
		TOUCH(smem, shader_meta_ptr, *meta, "shader_meta", job_no, false);
614

615
		panwrap_shader_disassemble(shader_ptr, job_no, h->job_type);
616

617 618 619
		if (blend_shader)
			panwrap_shader_disassemble(f->blend_shader & ~0xF, job_no, h->job_type);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
620 621
	} else
		panwrap_msg("<no shader>\n");
622

623 624 625
	if (v->viewport) {
		struct panwrap_mapped_memory *fmem = panwrap_find_mapped_gpu_mem_containing(v->viewport);
		struct mali_viewport *PANWRAP_PTR_VAR(f, fmem, v->viewport);
626

627
		panwrap_log("struct mali_viewport viewport_%d = {\n", job_no);
628
		panwrap_indent++;
629
		panwrap_log(".floats = {\n");
630 631 632 633 634 635
		panwrap_indent++;

		for (int i = 0; i < sizeof(f->floats) / sizeof(f->floats[0]); i += 2)
			panwrap_log("%ff, %ff,\n", f->floats[i], f->floats[i + 1]);

		panwrap_indent--;
636
		panwrap_log("},\n");
637

638 639 640
		panwrap_prop("depth_range_n = %f", f->depth_range_n);
		panwrap_prop("depth_range_f = %f", f->depth_range_f);

641 642 643 644 645 646 647 648
		/* Only the higher coordinates are MALI_POSITIVE scaled */

		panwrap_prop("viewport0 = { %d, %d }",
				f->viewport0[0], f->viewport0[1]);

		panwrap_prop("viewport1 = { MALI_POSITIVE(%d), MALI_POSITIVE(%d) }",
				f->viewport1[0] + 1, f->viewport1[1] + 1);

649 650 651
		panwrap_indent--;
		panwrap_log("};\n");

652
		TOUCH(fmem, v->viewport, *f, "viewport", job_no, true);
653
	}
654 655

	if (v->attribute_meta) {
656
		panwrap_replay_attribute_meta(job_no, attribute_count, v, false);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
657 658

		attr_mem = panwrap_find_mapped_gpu_mem_containing(v->attributes);
659
		panwrap_replay_attributes(attr_mem, v->attributes, job_no, attribute_count, false);
660
	}
661

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
662 663 664 665 666 667
	/* Varyings are encoded like attributes but not actually sent; we just
	 * pass a zero buffer with the right stride/size set, (or whatever)
	 * since the GPU will write to it itself */

	if (v->varyings) {
		attr_mem = panwrap_find_mapped_gpu_mem_containing(v->varyings);
668

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
669 670
		/* Number of descriptors depends on whether there are
		 * non-internal varyings */
671

672
		panwrap_replay_attributes(attr_mem, v->varyings, job_no, varying_count > 1 ? 2 : 1, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
673 674
	}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
675 676 677
	/* XXX: This entire block is such a hack... where are uniforms configured exactly? */

	if (v->uniforms) {
678
		int rows = uniform_count, width = 4;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
679 680 681 682 683 684 685 686 687 688
		size_t sz = rows * width * sizeof(float);

		struct panwrap_mapped_memory *uniform_mem = panwrap_find_mapped_gpu_mem_containing(v->uniforms);
		panwrap_fetch_gpu_mem(uniform_mem, v->uniforms, sz);
		float *PANWRAP_PTR_VAR(uniforms, uniform_mem, v->uniforms);

		panwrap_log("float uniforms_%d[] = {\n", job_no);

		panwrap_indent++;
		for (int row = 0; row < rows; row++) {
689
			panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
690 691 692 693 694 695 696 697 698 699 700

			for (int i = 0; i < width; i++)
				panwrap_log_cont("%ff, ", uniforms[i]);

			panwrap_log_cont("\n");

			uniforms += width;
		}
		panwrap_indent--;
		panwrap_log("};\n");

701
		TOUCH_LEN(mem, v->uniforms, sz, "uniforms", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
702 703
	}

704 705 706 707 708 709 710 711 712
	if (v->unknown1) {
		struct panwrap_mapped_memory *umem = panwrap_find_mapped_gpu_mem_containing(v->unknown1);

		if (umem) {
			u64 *PANWRAP_PTR_VAR(u, umem, v->unknown1);

			mali_ptr ptr = *u >> 8;
			uint8_t flags = *u & 0xFF;

713 714 715 716 717
			/* Points to... a buffer of zeroes in the same region?
			 * *shrug* Deliberate 0 length so we don't memset
			 * anything out */
			
			panwrap_log("u32 inner_unknown1_%d = 0; /* XXX */\n", job_no);
718
			TOUCH_LEN(umem, ptr, 0, "inner_unknown1", job_no, true);
719 720

			panwrap_log("u64 unknown1_%d = ((inner_unknown1_%d_p) << 8) | %d;\n", job_no, job_no, flags);
721
			TOUCH(umem, v->unknown1, u64, "unknown1", job_no, true);
722 723
		}
	}
724 725 726 727 728

	if (v->unknown6) {
		struct panwrap_mapped_memory *umem = panwrap_find_mapped_gpu_mem_containing(v->unknown6);

		if (umem) {
729
			struct mali_unknown6 *PANWRAP_PTR_VAR(u, umem, v->unknown6 & ~0xF);
730 731 732 733 734 735 736 737 738 739 740

			panwrap_log("struct mali_unknown6 unknown6_%d = {\n", job_no);
			panwrap_indent++;

			panwrap_prop("unknown0 = 0x%" PRIx64, u->unknown0);
			panwrap_prop("unknown1 = 0x%" PRIx64, u->unknown1);


			panwrap_indent--;
			panwrap_log("};\n");

741
			TOUCH(umem, v->unknown6 & ~0xF, *u, "unknown6", job_no, false);
742

743
			panwrap_replay_attribute_meta(job_no, varying_count, v, true);
744 745
		}
	}
746

747 748
	/* Just a pointer to... another pointer >_< */

749 750
	if (v->texture_trampoline) {
		struct panwrap_mapped_memory *mmem = panwrap_find_mapped_gpu_mem_containing(v->texture_trampoline);
751 752

		if (mmem) {
753
			mali_ptr *PANWRAP_PTR_VAR(u, mmem, v->texture_trampoline);
754 755

			char *a = pointer_as_memory_reference(*u);
756
			panwrap_log("uint64_t texture_trampoline_%d = %s;", job_no, a);
757 758
			free(a);

759
			TOUCH(mmem, v->texture_trampoline, *u, "texture_trampoline", job_no, true);
760 761 762 763 764 765 766 767 768 769

			/* Now, finally, descend down into the texture descriptor */
			struct panwrap_mapped_memory *tmem = panwrap_find_mapped_gpu_mem_containing(*u);

			if (tmem) {
				struct mali_texture_descriptor *PANWRAP_PTR_VAR(t, tmem, *u);

				panwrap_log("struct mali_texture_descriptor texture_descriptor_%d = {\n", job_no);
				panwrap_indent++;

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
770 771
				panwrap_prop("width = MALI_POSITIVE(%" PRId16 ")", t->width + 1);
				panwrap_prop("height = MALI_POSITIVE(%" PRId16 ")", t->height + 1);
772

773
				panwrap_prop("unknown1 = 0x%" PRIx32, t->unknown1);
774
				
775
				/* TODO: I don't understand how this works at all yet */
776
				panwrap_prop("format1 = 0x%" PRIx32, t->format1);
777 778 779 780 781 782 783 784 785 786 787

				panwrap_prop("swizzle_r = %s", panwrap_channel_name(t->swizzle_r));
				panwrap_prop("swizzle_g = %s", panwrap_channel_name(t->swizzle_g));
				panwrap_prop("swizzle_b = %s", panwrap_channel_name(t->swizzle_b));
				panwrap_prop("swizzle_a = %s", panwrap_channel_name(t->swizzle_a));

				if (t->swizzle_zero) {
					/* Shouldn't happen */
					panwrap_msg("Swizzle zero tripped but replay will be fine anyway");
					panwrap_prop("swizzle_zero = %d", t->swizzle_zero);
				}
788

789
				panwrap_prop("unknown3 = 0x%" PRIx32, t->unknown3);
790

791 792 793
				panwrap_prop("unknown5 = 0x%" PRIx32, t->unknown5);
				panwrap_prop("unknown6 = 0x%" PRIx32, t->unknown6);
				panwrap_prop("unknown7 = 0x%" PRIx32, t->unknown7);
794 795 796

				MEMORY_PROP(t, swizzled_bitmap_0);
				MEMORY_PROP(t, swizzled_bitmap_1);
797 798 799 800

				panwrap_indent--;
				panwrap_log("};\n");

801
				TOUCH(tmem, *u, *t, "texture_descriptor", job_no, false);
802
			}
803 804 805
		}
	}

806 807 808 809 810 811 812 813 814
	if (v->sampler_descriptor) {
		struct panwrap_mapped_memory *smem = panwrap_find_mapped_gpu_mem_containing(v->sampler_descriptor);

		if (smem) {
			struct mali_sampler_descriptor *PANWRAP_PTR_VAR(s, smem, v->sampler_descriptor);

			panwrap_log("struct mali_sampler_descriptor sampler_descriptor_%d = {\n", job_no);
			panwrap_indent++;

815
			/* Only the lower two bits are understood right now; the rest we display as hex */
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
816
			panwrap_log(".filter_mode = MALI_GL_TEX_MIN(%s) | MALI_GL_TEX_MAG(%s) | 0x%" PRIx32",\n",
817 818 819
				       	MALI_FILTER_NAME(s->filter_mode & MALI_GL_TEX_MIN_MASK),
				       	MALI_FILTER_NAME(s->filter_mode & MALI_GL_TEX_MAG_MASK),
					s->filter_mode & ~3);
820 821

			panwrap_prop("unknown1 = 0x%" PRIx32, s->unknown1);
822 823 824 825 826 827 828 829 830 831 832 833 834

			panwrap_prop("wrap_s = %s", panwrap_wrap_mode_name(s->wrap_s));
			panwrap_prop("wrap_t = %s", panwrap_wrap_mode_name(s->wrap_t));
			panwrap_prop("wrap_r = %s", panwrap_wrap_mode_name(s->wrap_r));

			panwrap_prop("compare_func = %s", panwrap_alt_func_name(s->compare_func));

			if (s->zero) {
				panwrap_msg("Zero tripped\n");
				panwrap_prop("zero = 0x%X\n", s->zero);
			}

			panwrap_prop("unknown2 = %d\n", s->unknown2);
835 836 837 838

			panwrap_indent--;
			panwrap_log("};\n");

839
			TOUCH(smem, v->sampler_descriptor, *s, "sampler_descriptor", job_no, false);
840 841
		}
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862

	if (v->indices) {
		struct panwrap_mapped_memory *imem = panwrap_find_mapped_gpu_mem_containing(v->indices);

		if (imem) {
			/* Indices are literally just a u32 array :) */

			uint32_t *PANWRAP_PTR_VAR(indices, imem, v->indices);

			panwrap_log("uint32_t indices_%d[] = {\n", job_no);
			panwrap_indent++;

			for(int i = 0; i < (v->index_count + 1); i += 3)
				panwrap_log("%d, %d, %d,\n",
						indices[i],
						indices[i + 1],
						indices[i + 2]);

			panwrap_indent--;
			panwrap_log("};\n");

863
			TOUCH_LEN(imem, v->indices, sizeof(uint32_t) * (v->index_count + 1), "indices", job_no, false);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
864 865
		}
	}
866 867


868
	panwrap_log("struct mali_payload_vertex_tiler payload_%d = {\n", job_no);
869 870 871 872 873
	panwrap_indent++;

	panwrap_prop("line_width = %ff", v->line_width);
	panwrap_prop("vertex_count = MALI_POSITIVE(%" PRId32 ")", v->vertex_count + 1);
	panwrap_prop("unk1 = 0x%" PRIx32, v->unk1);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
874
	panwrap_prop("draw_start = 0x%" PRIx32, v->draw_start);
875

876 877
	panwrap_prop("unknown_draw = 0x%" PRIx32, v->unknown_draw);

878
	if (h->job_type == JOB_TYPE_TILER) {
879
		panwrap_prop("draw_mode = %s", panwrap_gl_mode_name(v->draw_mode));
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
	} else {
		panwrap_prop("draw_mode = 0x%" PRIx32, v->draw_mode);
	}

	/* Index count only exists for tiler jobs anyway */ 

	if (v->index_count)
		panwrap_prop("index_count = MALI_POSITIVE(%" PRId32 ")", v->index_count + 1);

	uint32_t remaining_gl_enables = v->gl_enables;

	panwrap_log(".gl_enables = ");
	
	if (h->job_type == JOB_TYPE_TILER) {
		panwrap_log_cont("MALI_GL_FRONT_FACE(MALI_GL_%s) | ",
		    v->gl_enables & MALI_GL_FRONT_FACE(MALI_GL_CW) ? "CW" : "CCW");

		remaining_gl_enables &= ~(MALI_GL_FRONT_FACE(1));
	}

	panwrap_log_decoded_flags(gl_enable_flag_info, remaining_gl_enables);

	panwrap_log_cont(",\n");

	if (h->job_type == JOB_TYPE_VERTEX && v->index_count)
		panwrap_msg("Warning: index count set in vertex job\n");

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
907 908
	if (v->zero0 | v->zero1 | v->zero3 | v->zero5 | v->zero6) {
		panwrap_msg("Zero tripped\n");
909 910 911 912 913 914 915
		panwrap_prop("zero0 = 0x%" PRIx32, v->zero0);
		panwrap_prop("zero1 = 0x%" PRIx32, v->zero1);
		panwrap_prop("zero3 = 0x%" PRIx32, v->zero3);
		panwrap_prop("zero5 = 0x%" PRIx32, v->zero5);
		panwrap_prop("zero6 = 0x%" PRIx32, v->zero6);
	}

916
	DYN_MEMORY_PROP(v, job_no, indices);
917
	//DYN_MEMORY_PROP(v, job_no, unknown0);
918
	DYN_MEMORY_PROP(v, job_no, unknown1); 
919
	DYN_MEMORY_PROP(v, job_no, texture_trampoline);
920
	DYN_MEMORY_PROP(v, job_no, sampler_descriptor);
921 922 923 924
	DYN_MEMORY_PROP(v, job_no, uniforms);
	DYN_MEMORY_PROP(v, job_no, attributes); 
	DYN_MEMORY_PROP(v, job_no, attribute_meta); 
	DYN_MEMORY_PROP(v, job_no, varyings); 
925
	//DYN_MEMORY_PROP(v, job_no, unknown6);
926
	DYN_MEMORY_PROP(v, job_no, viewport);
927
	DYN_MEMORY_PROP(v, job_no, framebuffer);
928

929
	MEMORY_PROP(v, position_varying);
930

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
931
	panwrap_prop("_shader_upper = (shader_meta_%d_p) >> 4", job_no);
932 933
	panwrap_prop("flags = %d", v->flags); 

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
934 935
	if (v->unknown6)
		panwrap_prop("unknown6 = (unknown6_%d_p) | 0x%X", job_no, v->unknown6 & 0xF);
936

937 938 939
	panwrap_indent--;
	panwrap_log("};\n");

940
	return sizeof(*v);
941 942
}

943
static int panwrap_replay_fragment_job(const struct panwrap_mapped_memory *mem,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
944 945 946 947
					mali_ptr payload, int job_no)
{
	const struct mali_payload_fragment *PANWRAP_PTR_VAR(s, mem, payload);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
948 949
	bool fbd_dumped = false;

950
	if ((s->framebuffer & FBD_TYPE) == MALI_SFBD) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
951 952 953 954 955 956 957 958
		/* Only SFBDs are understood, not MFBDs. We're speculating,
		 * based on the versioning, kernel code, etc, that the
		 * difference is between Single FrameBuffer Descriptor and
		 * Multiple FrmaeBuffer Descriptor; the change apparently lines
		 * up with multi-framebuffer support being added (T7xx onwards,
		 * including Gxx). In any event, there's some field shuffling
		 * that we haven't looked into yet. */

959
		panwrap_replay_sfbd(s->framebuffer & FBD_MASK, job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
960 961 962
		fbd_dumped = true;
	}

963
	uintptr_t p = (uintptr_t) s->framebuffer & FBD_MASK;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
964

965
	panwrap_log("struct mali_payload_fragment payload_%d = {\n", job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
966
	panwrap_indent++;
967

968 969 970
	if (s->zero)
		panwrap_msg("ZT\n");

971 972 973
	/* See the comments by the macro definitions for mathematical context
	 * on why this is so weird */

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
974 975 976 977
	if (MALI_TILE_COORD_FLAGS(s->max_tile_coord) || MALI_TILE_COORD_FLAGS(s->min_tile_coord))
		panwrap_msg("Tile coordinate flag missed, replay wrong\n");

	panwrap_prop("min_tile_coord = MALI_COORDINATE_TO_TILE_MIN(%d, %d)",
978
			MALI_TILE_COORD_X(s->min_tile_coord) << MALI_TILE_SHIFT,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
979
			MALI_TILE_COORD_Y(s->min_tile_coord) << MALI_TILE_SHIFT);
980

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
981
	panwrap_prop("max_tile_coord = MALI_COORDINATE_TO_TILE_MAX(%d, %d)",
982
			(MALI_TILE_COORD_X(s->max_tile_coord) + 1) << MALI_TILE_SHIFT,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
983
			(MALI_TILE_COORD_Y(s->max_tile_coord) + 1) << MALI_TILE_SHIFT);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
984

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
985 986 987
	/* If the FBD was just decoded, we can refer to it by pointer. If not,
	 * we have to fallback on offsets. */

988
	const char *fbd_type = s->framebuffer & MALI_MFBD ? "MALI_MFBD" : "MALI_SFBD";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
989 990

	if (fbd_dumped)
991
		panwrap_prop("framebuffer = framebuffer_%d_p | %s", job_no, fbd_type);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
992
	else
993
		panwrap_prop("framebuffer = %s | %s", pointer_as_memory_reference(p), fbd_type);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
994

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
995 996
	panwrap_indent--;
	panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
997

998
	return sizeof(*s);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
999 1000
}

1001 1002
static int job_descriptor_number = 0;

1003
int panwrap_replay_jc(mali_ptr jc_gpu_va)
1004 1005 1006
{
	struct mali_job_descriptor_header *h;

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1007
	int start_number = 0;
1008

1009
	bool first = true;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1010
	bool last_size;
1011

1012
	do {
1013 1014 1015
		struct panwrap_mapped_memory *mem =
			panwrap_find_mapped_gpu_mem_containing(jc_gpu_va);

1016 1017 1018
		void *payload;

		h = PANWRAP_PTR(mem, jc_gpu_va, typeof(*h));
1019 1020 1021 1022

		int offset = h->job_descriptor_size == MALI_JOB_32 ? 4 : 0;
		mali_ptr payload_ptr = jc_gpu_va + sizeof(*h) - offset;

1023 1024 1025
		payload = panwrap_fetch_gpu_mem(mem, payload_ptr,
						MALI_PAYLOAD_SIZE);

1026 1027
		int job_no = job_descriptor_number++;

1028 1029 1030
		if (first)
			start_number = job_no;

1031 1032 1033
		panwrap_log("struct mali_job_descriptor_header job_%d = {\n", job_no);
		panwrap_indent++;

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1034
		panwrap_prop("job_type = %s", panwrap_job_type_name(h->job_type));
1035

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1036 1037 1038
		/* Save for next job fixing */
		last_size = h->job_descriptor_size;

1039 1040 1041
		if (h->job_descriptor_size)
			panwrap_prop("job_descriptor_size = %d", h->job_descriptor_size);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
		if (h->exception_status)
			panwrap_prop("exception_status = %d", h->exception_status);

		if (h->first_incomplete_task)
			panwrap_prop("first_incomplete_task = %d", h->first_incomplete_task);

		if (h->fault_pointer)
			panwrap_prop("fault_pointer = 0x%" PRIx64, h->fault_pointer);

		if (h->job_barrier)
			panwrap_prop("job_barrier = %d", h->job_barrier);

1054 1055
		panwrap_prop("job_index = %d", h->job_index);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1056 1057 1058
		if (h->unknown_flags)
			panwrap_prop("unknown_flags = %d", h->unknown_flags);

1059
		if (h->job_dependency_index_1)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1060
			panwrap_prop("job_dependency_index_1 = %d", h->job_dependency_index_1);
1061

1062 1063
		if (h->job_dependency_index_2)
			panwrap_prop("job_dependency_index_2 = %d", h->job_dependency_index_2);
1064

1065 1066 1067
		panwrap_indent--;
		panwrap_log("};\n");

1068 1069 1070 1071 1072
		/* Do not touch the field yet -- decode the payload first, and
		 * don't touch that either. This is essential for the uploads
		 * to occur in sequence and therefore be dynamically allocated
		 * correctly. Do note the size, however, for that related
		 * reason. */
1073

1074
		int payload_size = 0;
1075

1076 1077 1078 1079 1080
		switch (h->job_type) {
		case JOB_TYPE_SET_VALUE:
			{
				struct mali_payload_set_value *s = payload;

1081
				panwrap_log("struct mali_payload_set_value payload_%d = {\n", job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1082
				panwrap_indent++;
1083
				MEMORY_PROP(s, out);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1084 1085 1086
				panwrap_prop("unknown = 0x%" PRIX64, s->unknown);
				panwrap_indent--;
				panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1087

1088
				payload_size = sizeof(*s);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1089

1090 1091 1092 1093
				break;
			}
		case JOB_TYPE_TILER:
		case JOB_TYPE_VERTEX:
1094 1095
			payload_size = panwrap_replay_vertex_or_tiler_job(h, mem, payload_ptr, job_no);

1096 1097
			break;
		case JOB_TYPE_FRAGMENT:
1098
			payload_size = panwrap_replay_fragment_job(mem, payload_ptr, job_no);
1099 1100 1101 1102
			break;
		default:
			break;
		}
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123

		/* Touch the job descriptor fields, careful about 32/64-bit */
		TOUCH_JOB_HEADER(mem, jc_gpu_va, sizeof(*h), offset, job_no);

		/* Touch the payload immediately after, sequentially */
		TOUCH_SEQUENTIAL(mem, payload_ptr, payload_size, "payload", job_no);

		/* Handle linkage */

		if (!first) {
			panwrap_log("((struct mali_job_descriptor_header *) (uintptr_t) job_%d_p)->", job_no - 1);

			if (last_size)
				panwrap_log_cont("next_job_64 = job_%d_p;\n\n", job_no);
			else
				panwrap_log_cont("next_job_32 = (u32) (uintptr_t) job_%d_p;\n\n", job_no);
		}

		first = false;


Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1124
	} while ((jc_gpu_va = h->job_descriptor_size ? h->next_job_64 : h->next_job_32));
1125 1126

	return start_number;
1127
}
1128

1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
void panwrap_replay_soft_replay_payload(mali_ptr jc_gpu_va, int job_no)
{
	struct mali_jd_replay_payload *v;

	struct panwrap_mapped_memory *mem =
		panwrap_find_mapped_gpu_mem_containing(jc_gpu_va);

	v = PANWRAP_PTR(mem, jc_gpu_va, typeof(*v));

	panwrap_log("struct mali_jd_replay_payload soft_replay_payload_%d = {\n", job_no);
	panwrap_indent++;

1141 1142 1143
	MEMORY_PROP(v, tiler_jc_list);
	MEMORY_PROP(v, fragment_jc);
	MEMORY_PROP(v, tiler_heap_free);
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165

	panwrap_prop("fragment_hierarchy_mask = 0x%" PRIx32, v->fragment_hierarchy_mask);
	panwrap_prop("tiler_hierarchy_mask = 0x%" PRIx32, v->tiler_hierarchy_mask);
	panwrap_prop("hierarchy_default_weight = 0x%" PRIx32, v->hierarchy_default_weight);

	panwrap_log(".tiler_core_req = ");
	if (v->tiler_core_req)
		ioctl_log_decoded_jd_core_req(v->tiler_core_req);
	else
		panwrap_log_cont("0");
	panwrap_log_cont(",\n");

	panwrap_log(".fragment_core_req = ");
	if (v->fragment_core_req)
		ioctl_log_decoded_jd_core_req(v->fragment_core_req);
	else
		panwrap_log_cont("0");
	panwrap_log_cont(",\n");

	panwrap_indent--;
	panwrap_log("};\n");

1166
	TOUCH(mem, jc_gpu_va, *v, "soft_replay_payload", job_no, false);
1167 1168
}

1169
int panwrap_replay_soft_replay(mali_ptr jc_gpu_va)
1170 1171
{
	struct mali_jd_replay_jc *v;
1172 1173
	int start_no;
	bool first = true;
1174 1175 1176 1177 1178 1179 1180 1181

	do {
		struct panwrap_mapped_memory *mem =
			panwrap_find_mapped_gpu_mem_containing(jc_gpu_va);

		v = PANWRAP_PTR(mem, jc_gpu_va, typeof(*v));

		int job_no = job_descriptor_number++;
1182 1183 1184 1185 1186 1187 1188

		if (first)
			start_no = job_no;

		first = false;

		panwrap_log("struct mali_jd_replay_jc job_%d = {\n", job_no);
1189 1190
		panwrap_indent++;

1191 1192
		MEMORY_PROP(v, next);
		MEMORY_PROP(v, jc);
1193 1194 1195 1196

		panwrap_indent--;
		panwrap_log("};\n");

1197
		panwrap_replay_soft_replay_payload(jc_gpu_va /* + sizeof(struct mali_jd_replay_jc) */, job_no);
1198

1199
		TOUCH(mem, jc_gpu_va, *v, "job", job_no, false);
1200
	} while ((jc_gpu_va = v->next));
1201 1202

	return start_no;
1203
}