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 214 215
#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



Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
216 217 218 219 220 221 222 223 224 225
static void panwrap_property_u32_list(const char *name, const u32 *lst, size_t c)
{
	panwrap_log(".%s = { ", name);
	panwrap_indent++;
	for (int i = 0; i < c; ++i)
		panwrap_log_cont("0x%" PRIx32 ", ", lst[i]);
	panwrap_indent--;
	panwrap_log_cont("},\n");
}

226 227 228 229 230 231 232
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!?";
}

233 234 235 236 237 238 239 240 241 242 243 244 245 246
static bool
panwrap_deduplicate(struct panwrap_mapped_memory *mem, uint64_t gpu_va, const char *name, int number)
{
	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
247
{
248
	struct panwrap_mapped_memory *mem = panwrap_find_mapped_gpu_mem_containing(gpu_va);
249
	const struct mali_single_framebuffer *PANWRAP_PTR_VAR(s, mem, (mali_ptr) gpu_va);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
250

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

254
	panwrap_log("struct mali_single_framebuffer framebuffer_%d = {\n", job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
255 256 257 258 259
	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);
260 261 262 263

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
265 266
	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
267

268
	MEMORY_PROP(s, framebuffer_end);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
269

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

272 273 274 275 276 277 278
	/* 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");

279
	if (s->depth_buffer | s->depth_buffer_enable) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
280
		MEMORY_PROP(s, depth_buffer);
281 282
		panwrap_prop("depth_buffer_enable = %s", DS_ENABLE(s->depth_buffer_enable));
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
283

284
	if (s->stencil_buffer | s->stencil_buffer_enable) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
285
		MEMORY_PROP(s, stencil_buffer);
286 287
		panwrap_prop("stencil_buffer_enable = %s", DS_ENABLE(s->stencil_buffer_enable));
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
288

289 290 291 292 293 294
	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
295

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
296
	if (s->clear_depth_1 != 0 || s->clear_depth_2 != 0 || s->clear_depth_3 != 0 || s->clear_depth_4 != 0) {
297 298 299 300 301
		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
302

303 304 305
	if (s->clear_stencil) {
		panwrap_prop("clear_stencil = 0x%x", s->clear_stencil);
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
306

307 308 309
	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
310 311 312 313

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

314
	MEMORY_PROP(s, tiler_jc_list);
315 316

	MEMORY_PROP(s, unknown_address_4);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
317 318 319 320 321 322 323 324 325 326 327 328 329

	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);

330
	TOUCH(mem, (mali_ptr) gpu_va, *s, "framebuffer", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
331 332
}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
333
void panwrap_replay_attributes(const struct panwrap_mapped_memory *mem,
334
			       mali_ptr addr, int job_no, int count, bool varying)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
335
{
336
	char *prefix = varying ? "varyings" : "attributes";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
337

338 339
	/* 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
340

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

343 344
	char base[128];
	snprintf(base, sizeof(base), "%s_data_%d", prefix, job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
345

346 347
	for (int i = 0; i < count; ++i) {
		mali_ptr raw_elements = attr[i].elements & ~3;
348

349 350
		size_t vertex_count;
		size_t component_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
351

352 353 354
		if (!varying) {
			/* 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
355

356
			return;
357
			float *buffer = panwrap_fetch_gpu_mem(mem, raw_elements, attr[i].size);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
358

359 360
			vertex_count = attr[i].size / attr[i].stride;
			component_count = attr[i].stride / sizeof(float);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
361

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

364 365 366
			panwrap_indent++;
			for (int row = 0; row < vertex_count; row++) {
				panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
367

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

371 372 373 374 375 376
				panwrap_log_cont("\n");

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

378
			TOUCH_LEN(mem, raw_elements, attr[i].size, base, i, true);
379 380 381 382 383 384 385
		} 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
386
	}
387

388
	panwrap_log("struct mali_attr %s_%d[] = {\n", prefix, job_no);
389 390
	panwrap_indent++;

391 392 393 394 395 396 397 398 399 400 401
	for (int i = 0; i < count; ++i) {
		panwrap_log("{\n");
		panwrap_indent++;

		int flags = attr[i].elements & 3;
		panwrap_prop("elements = (%s_%d_p) | %d", base, i, attr[i].elements & 3);

		panwrap_prop("stride = 0x%" PRIx32, attr[i].stride);
		panwrap_prop("size = 0x%" PRIx32, attr[i].size);
		panwrap_indent--;
		panwrap_log("}, \n");
402 403 404 405 406
	}

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

407
	TOUCH_LEN(mem, addr, sizeof(*attr) * count, prefix, job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
408 409
}

410 411 412 413 414 415 416 417 418 419 420 421 422
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;
}

423
static void
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
424
panwrap_replay_stencil(const char *name, const u32 *raw)
425
{
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
426
	const struct mali_stencil_test *stencil = (struct mali_stencil_test *) raw;
427

428
	const char *func = panwrap_func_name(stencil->func);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
429 430 431
	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);
432

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
436 437 438 439 440 441 442 443 444 445
	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");
446 447
}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
static void
panwrap_replay_blend_equation(const u32 *raw)
{
	const struct mali_blend_equation *blend = (struct mali_blend_equation *) raw;

	if (blend->zero)
		panwrap_msg("Blend zero tripped: %X\n", blend->zero);

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

	panwrap_prop("unknown = 0x%X", blend->unknown);

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

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

469
static void
470
panwrap_replay_attribute_meta(int job_no, int count, const struct mali_payload_vertex_tiler *v, bool varying)
471 472 473 474 475 476 477 478 479
{
	char base[128];
	char *prefix = varying ? "varying" : "attribute";
	snprintf(base, sizeof(base), "%s_meta", prefix, job_no);

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

	struct mali_attr_meta *attr_meta;
480
	mali_ptr p = varying ? (v->unknown6 & ~0xF) : v->attribute_meta;
481 482 483

	struct panwrap_mapped_memory *attr_mem = panwrap_find_mapped_gpu_mem_containing(p);

484
	for (int i = 0; i < count; ++i, p += sizeof(struct mali_attr_meta)) {
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
		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);
}

513 514
static int
panwrap_replay_vertex_or_tiler_job(const struct mali_job_descriptor_header *h,
515 516 517 518 519 520
					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
521
	mali_ptr shader_meta_ptr = (u64) (uintptr_t) (v->_shader_upper << 4);
522

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

526
	int varying_count, attribute_count, uniform_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
527

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
528 529 530 531 532 533 534
	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++;

535 536 537
		/* 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
538

539 540 541 542 543 544 545 546 547 548 549
		/* 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)
550
			panwrap_msg("XXX shader zero tripped\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
551

552 553 554 555
		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);
556
		panwrap_prop("unknown1 = %s0x%" PRIx32,
557 558 559
				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
560

561 562 563 564 565
		panwrap_indent--;
		panwrap_log("},\n");

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
567

568 569 570
		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);
571
		}
572

573 574
		bool invert_alpha_coverage = f->alpha_coverage & 0xFFF0;
		uint16_t inverted_coverage = invert_alpha_coverage ? ~f->alpha_coverage : f->alpha_coverage;
575 576 577 578 579

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

580
		panwrap_log(".unknown2_3 = ");
581

582 583
		int unknown2_3 = f->unknown2_3;
		int unknown2_4 = f->unknown2_4;
584 585 586 587 588 589 590 591 592 593 594 595
		
		/* 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);
596
		panwrap_log_cont(",\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
597

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
598
		panwrap_log(".unknown2_4 = ");
599 600 601 602 603 604 605 606 607 608

		/* TODO: Make less ugly */

		panwrap_log_cont("MALI_STENCIL_MASK_FRONT(0x%02X) | MALI_STENCIL_MASK_BACK(0x%02X) | ",
				MALI_GET_STENCIL_MASK_FRONT(unknown2_4),
				MALI_GET_STENCIL_MASK_BACK(unknown2_4));

		unknown2_4 &= ~MALI_STENCIL_MASK_MASK;

		panwrap_log_decoded_flags(u4_flag_info, unknown2_4);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
609 610
		panwrap_log_cont(",\n");

611 612
		panwrap_replay_stencil("front", &f->stencil_front);
		panwrap_replay_stencil("back", &f->stencil_back);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
613

614 615
		panwrap_prop("unknown2_7 = 0x%" PRIx32, f->unknown2_7);
		panwrap_prop("unknown2_8 = 0x%" PRIx32, f->unknown2_8);
616

617 618
		if (f->unknown2_3 & MALI_HAS_BLEND_SHADER) {
			panwrap_replay_shader_address("blend_shader", f->blend_shader);
619
		} else {
620
			panwrap_replay_blend_equation(&f->blend_equation);
621
		}
622

623 624 625
		panwrap_indent--;
		panwrap_log("}\n");

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
626 627
		panwrap_indent--;
		panwrap_log("};\n");
628

629
		TOUCH(smem, shader_meta_ptr, *meta, "shader_meta", job_no, false);
630

631
		panwrap_shader_disassemble(shader_ptr, job_no, h->job_type);
632

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
633 634
	} else
		panwrap_msg("<no shader>\n");
635
	
636 637 638
	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);
639

640
		panwrap_log("struct mali_viewport viewport_%d = {\n", job_no);
641
		panwrap_indent++;
642
		panwrap_log(".floats = {\n");
643 644 645 646 647 648
		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--;
649
		panwrap_log("},\n");
650

651 652 653
		panwrap_prop("depth_range_n = %f", f->depth_range_n);
		panwrap_prop("depth_range_f = %f", f->depth_range_f);

654 655 656 657 658 659 660 661
		/* 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);

662 663 664
		panwrap_indent--;
		panwrap_log("};\n");

665
		TOUCH(fmem, v->viewport, *f, "viewport", job_no, true);
666
	}
667 668

	if (v->attribute_meta) {
669
		panwrap_replay_attribute_meta(job_no, attribute_count, v, false);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
670 671

		attr_mem = panwrap_find_mapped_gpu_mem_containing(v->attributes);
672
		panwrap_replay_attributes(attr_mem, v->attributes, job_no, attribute_count, false);
673
	}
674

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
675 676 677 678 679 680
	/* 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);
681

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
682 683
		/* Number of descriptors depends on whether there are
		 * non-internal varyings */
684

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

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

	if (v->uniforms) {
691
		int rows = uniform_count, width = 4;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
692 693 694 695 696 697 698 699 700 701
		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++) {
702
			panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
703 704 705 706 707 708 709 710 711 712 713

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

			panwrap_log_cont("\n");

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

714
		TOUCH_LEN(mem, v->uniforms, sz, "uniforms", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
715 716
	}

717 718 719 720 721 722 723 724 725
	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;

726 727 728 729 730
			/* 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);
731
			TOUCH_LEN(umem, ptr, 0, "inner_unknown1", job_no, true);
732 733

			panwrap_log("u64 unknown1_%d = ((inner_unknown1_%d_p) << 8) | %d;\n", job_no, job_no, flags);
734
			TOUCH(umem, v->unknown1, u64, "unknown1", job_no, true);
735 736
		}
	}
737 738 739 740 741

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

		if (umem) {
742
			struct mali_unknown6 *PANWRAP_PTR_VAR(u, umem, v->unknown6 & ~0xF);
743 744 745 746 747 748 749 750 751 752 753

			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");

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

756
			panwrap_replay_attribute_meta(job_no, varying_count, v, true);
757 758
		}
	}
759

760 761
	/* Just a pointer to... another pointer >_< */

762 763
	if (v->texture_trampoline) {
		struct panwrap_mapped_memory *mmem = panwrap_find_mapped_gpu_mem_containing(v->texture_trampoline);
764 765

		if (mmem) {
766
			mali_ptr *PANWRAP_PTR_VAR(u, mmem, v->texture_trampoline);
767 768

			char *a = pointer_as_memory_reference(*u);
769
			panwrap_log("uint64_t texture_trampoline_%d = %s;", job_no, a);
770 771
			free(a);

772
			TOUCH(mmem, v->texture_trampoline, *u, "texture_trampoline", job_no, true);
773 774 775 776 777 778 779 780 781 782

			/* 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
783 784
				panwrap_prop("width = MALI_POSITIVE(%" PRId16 ")", t->width + 1);
				panwrap_prop("height = MALI_POSITIVE(%" PRId16 ")", t->height + 1);
785

786
				panwrap_prop("unknown1 = 0x%" PRIx32, t->unknown1);
787
				
788
				/* TODO: I don't understand how this works at all yet */
789
				panwrap_prop("format1 = 0x%" PRIx32, t->format1);
790 791 792 793 794 795 796 797 798 799 800

				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);
				}
801

802
				panwrap_prop("unknown3 = 0x%" PRIx32, t->unknown3);
803

804 805 806
				panwrap_prop("unknown5 = 0x%" PRIx32, t->unknown5);
				panwrap_prop("unknown6 = 0x%" PRIx32, t->unknown6);
				panwrap_prop("unknown7 = 0x%" PRIx32, t->unknown7);
807 808 809

				MEMORY_PROP(t, swizzled_bitmap_0);
				MEMORY_PROP(t, swizzled_bitmap_1);
810 811 812 813

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

814
				TOUCH(tmem, *u, *t, "texture_descriptor", job_no, false);
815
			}
816 817 818
		}
	}

819 820 821 822 823 824 825 826 827
	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++;

828
			/* Only the lower two bits are understood right now; the rest we display as hex */
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
829
			panwrap_log(".filter_mode = MALI_GL_TEX_MIN(%s) | MALI_GL_TEX_MAG(%s) | 0x%" PRIx32",\n",
830 831 832
				       	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);
833 834

			panwrap_prop("unknown1 = 0x%" PRIx32, s->unknown1);
835 836 837 838 839 840 841 842 843 844 845 846 847

			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);
848 849 850 851

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

852
			TOUCH(smem, v->sampler_descriptor, *s, "sampler_descriptor", job_no, false);
853 854
		}
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875

	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");

876
			TOUCH_LEN(imem, v->indices, sizeof(uint32_t) * (v->index_count + 1), "indices", job_no, false);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
877 878
		}
	}
879 880


881
	panwrap_log("struct mali_payload_vertex_tiler payload_%d = {\n", job_no);
882 883 884 885 886
	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
887
	panwrap_prop("draw_start = 0x%" PRIx32, v->draw_start);
888

889 890
	panwrap_prop("unknown_draw = 0x%" PRIx32, v->unknown_draw);

891
	if (h->job_type == JOB_TYPE_TILER) {
892
		panwrap_prop("draw_mode = %s", panwrap_gl_mode_name(v->draw_mode));
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
	} 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
920 921
	if (v->zero0 | v->zero1 | v->zero3 | v->zero5 | v->zero6) {
		panwrap_msg("Zero tripped\n");
922 923 924 925 926 927 928
		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);
	}

929
	DYN_MEMORY_PROP(v, job_no, indices);
930
	//DYN_MEMORY_PROP(v, job_no, unknown0);
931
	DYN_MEMORY_PROP(v, job_no, unknown1); 
932
	DYN_MEMORY_PROP(v, job_no, texture_trampoline);
933
	DYN_MEMORY_PROP(v, job_no, sampler_descriptor);
934 935 936 937
	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); 
938
	//DYN_MEMORY_PROP(v, job_no, unknown6);
939
	DYN_MEMORY_PROP(v, job_no, viewport);
940
	DYN_MEMORY_PROP(v, job_no, framebuffer);
941

942
	MEMORY_PROP(v, position_varying);
943

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

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

950 951 952
	panwrap_indent--;
	panwrap_log("};\n");

953
	return sizeof(*v);
954 955
}

956
static int panwrap_replay_fragment_job(const struct panwrap_mapped_memory *mem,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
957 958 959 960
					mali_ptr payload, int job_no)
{
	const struct mali_payload_fragment *PANWRAP_PTR_VAR(s, mem, payload);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
961 962
	bool fbd_dumped = false;

963
	if ((s->framebuffer & FBD_TYPE) == MALI_SFBD) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
964 965 966 967 968 969 970 971
		/* 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. */

972
		panwrap_replay_sfbd(s->framebuffer & FBD_MASK, job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
973 974 975
		fbd_dumped = true;
	}

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

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

981 982 983
	if (s->zero)
		panwrap_msg("ZT\n");

984 985 986
	/* See the comments by the macro definitions for mathematical context
	 * on why this is so weird */

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
987 988 989 990
	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)",
991
			MALI_TILE_COORD_X(s->min_tile_coord) << MALI_TILE_SHIFT,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
992
			MALI_TILE_COORD_Y(s->min_tile_coord) << MALI_TILE_SHIFT);
993

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
994
	panwrap_prop("max_tile_coord = MALI_COORDINATE_TO_TILE_MAX(%d, %d)",
995
			(MALI_TILE_COORD_X(s->max_tile_coord) + 1) << MALI_TILE_SHIFT,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
996
			(MALI_TILE_COORD_Y(s->max_tile_coord) + 1) << MALI_TILE_SHIFT);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
997

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

1001
	const char *fbd_type = s->framebuffer & MALI_MFBD ? "MALI_MFBD" : "MALI_SFBD";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1002 1003

	if (fbd_dumped)
1004
		panwrap_prop("framebuffer = framebuffer_%d_p | %s", job_no, fbd_type);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1005
	else
1006
		panwrap_prop("framebuffer = %s | %s", pointer_as_memory_reference(p), fbd_type);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1007

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1008 1009
	panwrap_indent--;
	panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1010

1011
	return sizeof(*s);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1012 1013
}

1014 1015
static int job_descriptor_number = 0;

1016
int panwrap_replay_jc(mali_ptr jc_gpu_va)
1017 1018 1019
{
	struct mali_job_descriptor_header *h;

1020 1021
	int start_number;

1022
	bool first = true;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1023
	bool last_size;
1024

1025
	do {
1026 1027 1028
		struct panwrap_mapped_memory *mem =
			panwrap_find_mapped_gpu_mem_containing(jc_gpu_va);

1029 1030 1031
		void *payload;

		h = PANWRAP_PTR(mem, jc_gpu_va, typeof(*h));
1032 1033 1034 1035

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

1036 1037 1038
		payload = panwrap_fetch_gpu_mem(mem, payload_ptr,
						MALI_PAYLOAD_SIZE);

1039 1040
		int job_no = job_descriptor_number++;

1041 1042 1043
		if (first)
			start_number = job_no;

1044 1045 1046
		panwrap_log("struct mali_job_descriptor_header job_%d = {\n", job_no);
		panwrap_indent++;

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1049 1050 1051
		/* Save for next job fixing */
		last_size = h->job_descriptor_size;

1052 1053 1054
		if (h->job_descriptor_size)
			panwrap_prop("job_descriptor_size = %d", h->job_descriptor_size);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
		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);

1067 1068
		panwrap_prop("job_index = %d", h->job_index);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1069 1070 1071
		if (h->unknown_flags)
			panwrap_prop("unknown_flags = %d", h->unknown_flags);

1072
		if (h->job_dependency_index_1)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1073
			panwrap_prop("job_dependency_index_1 = %d", h->job_dependency_index_1);
1074

1075 1076
		if (h->job_dependency_index_2)
			panwrap_prop("job_dependency_index_2 = %d", h->job_dependency_index_2);
1077

1078 1079 1080
		panwrap_indent--;
		panwrap_log("};\n");

1081 1082 1083 1084 1085
		/* 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. */
1086

1087
		int payload_size = 0;
1088

1089 1090 1091 1092 1093
		switch (h->job_type) {
		case JOB_TYPE_SET_VALUE:
			{
				struct mali_payload_set_value *s = payload;

1094
				panwrap_log("struct mali_payload_set_value payload_%d = {\n", job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1095
				panwrap_indent++;
1096
				MEMORY_PROP(s, out);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1097 1098 1099
				panwrap_prop("unknown = 0x%" PRIX64, s->unknown);
				panwrap_indent--;
				panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1100

1101
				payload_size = sizeof(*s);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1102

1103 1104 1105 1106
				break;
			}
		case JOB_TYPE_TILER:
		case JOB_TYPE_VERTEX:
1107 1108
			payload_size = panwrap_replay_vertex_or_tiler_job(h, mem, payload_ptr, job_no);

1109 1110
			break;
		case JOB_TYPE_FRAGMENT:
1111
			payload_size = panwrap_replay_fragment_job(mem, payload_ptr, job_no);
1112 1113 1114 1115
			break;
		default:
			break;
		}
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136

		/* 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
1137
	} while ((jc_gpu_va = h->job_descriptor_size ? h->next_job_64 : h->next_job_32));
1138 1139

	return start_number;
1140
}
1141

1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
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++;

1154 1155 1156
	MEMORY_PROP(v, tiler_jc_list);
	MEMORY_PROP(v, fragment_jc);
	MEMORY_PROP(v, tiler_heap_free);
1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178

	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");

1179
	TOUCH(mem, jc_gpu_va, *v, "soft_replay_payload", job_no, false);
1180 1181
}

1182
int panwrap_replay_soft_replay(mali_ptr jc_gpu_va)
1183 1184
{
	struct mali_jd_replay_jc *v;
1185 1186
	int start_no;
	bool first = true;
1187 1188 1189 1190 1191 1192 1193 1194

	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++;
1195 1196 1197 1198 1199 1200 1201

		if (first)
			start_no = job_no;

		first = false;

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

1204 1205
		MEMORY_PROP(v, next);
		MEMORY_PROP(v, jc);
1206 1207 1208 1209

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

1210 1211
		panwrap_replay_soft_replay_payload(jc_gpu_va + sizeof(struct mali_jd_replay_jc), job_no);

1212
		TOUCH(mem, jc_gpu_va, *v, "job", job_no, false);
1213
	} while ((jc_gpu_va = v->next));
1214 1215

	return start_no;
1216
}