panwrap-decoder.c 33.7 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 269

	panwrap_property_u32_list("weights", s->weights, MALI_FBD_HIERARCHY_WEIGHTS);

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

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

282 283 284 285
	if (s->stencil_buffer | s->stencil_buffer_enable) {
		panwrap_prop("stencil_buffer = " MALI_PTR_FMT, s->depth_buffer);
		panwrap_prop("stencil_buffer_enable = %s", DS_ENABLE(s->stencil_buffer_enable));
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
286

287 288 289 290 291 292
	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
293

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

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

305 306 307
	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
308 309 310 311

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
312
	panwrap_prop("tiler_jc_list = 0x%" PRIx64, s->tiler_jc_list);
313 314

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

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

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

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

336 337
	/* 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
338

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

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

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

347 348
		size_t vertex_count;
		size_t component_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
349

350 351 352
		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
353

354
			float *buffer = panwrap_fetch_gpu_mem(mem, raw_elements, attr[i].size);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
355

356 357
			vertex_count = attr[i].size / attr[i].stride;
			component_count = attr[i].stride / sizeof(float);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
358

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

361 362 363
			panwrap_indent++;
			for (int row = 0; row < vertex_count; row++) {
				panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
364

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

368 369 370 371 372 373
				panwrap_log_cont("\n");

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

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

385
	panwrap_log("struct mali_attr %s_%d[] = {\n", prefix, job_no);
386 387
	panwrap_indent++;

388 389 390 391 392 393 394 395 396 397 398
	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");
399 400 401 402 403
	}

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

404
	TOUCH_LEN(mem, addr, sizeof(*attr) * count, prefix, job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
405 406
}

407 408 409 410 411 412 413 414 415 416 417 418 419
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;
}

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

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

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

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
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");
}

466 467
static int
panwrap_replay_vertex_or_tiler_job(const struct mali_job_descriptor_header *h,
468 469 470 471 472 473
					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
474
	mali_ptr shader_meta_ptr = (u64) (uintptr_t) (v->_shader_upper << 4);
475

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

479
	int varying_count, attribute_count, uniform_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
480

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
481 482 483 484 485 486 487
	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++;

488
		mali_ptr shader_ptr = panwrap_replay_shader_address("shader", s->shader);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
489

490 491
		if (s->zero1)
			panwrap_msg("XXX shader zero tripped\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
492

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
493
		panwrap_prop("attribute_count = %" PRId16, s->attribute_count);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
494
		panwrap_prop("varying_count = %" PRId16, s->varying_count);
495 496 497 498
		panwrap_prop("uniform_count = %" PRId16, s->uniform_count);
		panwrap_prop("work_count = %" PRId16, s->work_count);
		panwrap_prop("unknown1 = 0x%" PRIx32, s->unknown1);
		panwrap_prop("unknown2 = 0x%" PRIx32, s->unknown2);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
499

500 501
		/* Save for dumps */
		attribute_count = s->attribute_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
502
		varying_count = s->varying_count;
503
		uniform_count = s->uniform_count; 
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
504

505 506 507
		/* WTF? All zero for vertex shaders; block of assorted, largely
		 * unknown fields for fragment shaders. Let's figure it out,
		 * girls :) */
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
508

509 510 511 512
		if (s->depth_units || s->depth_factor) {
			panwrap_prop("depth_units = MALI_NEGATIVE(%f)", s->depth_units - 1.0f);
			panwrap_prop("depth_factor = %f", s->depth_factor);
		}
513

514 515 516 517 518 519 520
		bool invert_alpha_coverage = s->alpha_coverage & 0xFFF0;
		uint16_t inverted_coverage = invert_alpha_coverage ? ~s->alpha_coverage : s->alpha_coverage;

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

521
		panwrap_log(".unknown2_3 = ");
522 523

		int unknown2_3 = s->unknown2_3;
524
		int unknown2_4 = s->unknown2_4;
525 526 527 528 529 530 531 532 533 534 535 536
		
		/* 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);
537
		panwrap_log_cont(",\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
538

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
539
		panwrap_log(".unknown2_4 = ");
540 541 542 543 544 545 546 547 548 549

		/* 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
550 551
		panwrap_log_cont(",\n");

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
552 553
		panwrap_replay_stencil("front", &s->stencil_front);
		panwrap_replay_stencil("back", &s->stencil_back);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
554

555 556
		panwrap_prop("unknown2_7 = 0x%" PRIx32, s->unknown2_7);
		panwrap_prop("unknown2_8 = 0x%" PRIx32, s->unknown2_8);
557 558 559 560

		if (s->unknown2_3 & MALI_HAS_BLEND_SHADER) {
			panwrap_replay_shader_address("blend_shader", s->blend_shader);
		} else {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
561
			panwrap_replay_blend_equation(&s->blend_equation);
562
		}
563

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
564 565
		panwrap_indent--;
		panwrap_log("};\n");
566
		TOUCH(smem, shader_meta_ptr, *meta, "shader_meta", job_no, false);
567

568
		panwrap_shader_disassemble(shader_ptr, job_no, h->job_type);
569

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
570 571
	} else
		panwrap_msg("<no shader>\n");
572
	
573 574 575
	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);
576

577
		panwrap_log("struct mali_viewport viewport_%d = {\n", job_no);
578
		panwrap_indent++;
579
		panwrap_log(".floats = {\n");
580 581 582 583 584 585
		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--;
586
		panwrap_log("},\n");
587

588 589 590
		panwrap_prop("depth_range_n = %f", f->depth_range_n);
		panwrap_prop("depth_range_f = %f", f->depth_range_f);

591 592 593 594 595 596 597 598
		/* 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);

599 600 601
		panwrap_indent--;
		panwrap_log("};\n");

602
		TOUCH(fmem, v->viewport, *f, "viewport", job_no, true);
603
	}
604 605

	if (v->attribute_meta) {
606
		panwrap_log("struct mali_attr_meta attribute_meta_%d[] = {\n", job_no);
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
		panwrap_indent++;

		size_t count = 0;

		struct mali_attr_meta *attr_meta;
		mali_ptr p;

		attr_mem = panwrap_find_mapped_gpu_mem_containing(v->attribute_meta);

		for (p = v->attribute_meta;
		     *PANWRAP_PTR(attr_mem, p, u64) != 0;
		     p += sizeof(struct mali_attr_meta), count++) {
			attr_meta = panwrap_fetch_gpu_mem(attr_mem, p,
							  sizeof(*attr_mem));

			panwrap_log("{ .index = %d, .flags = 0x%" PRIx64 "},\n",
623
					attr_meta->index, (u64) attr_meta->flags);
624 625 626 627 628
		}

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

629
		TOUCH_LEN(attr_mem, v->attribute_meta, sizeof(struct mali_attr_meta) * count, "attribute_meta", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
630 631 632

		attr_mem = panwrap_find_mapped_gpu_mem_containing(v->attributes);

633
		panwrap_replay_attributes( attr_mem, v->attributes, job_no, attribute_count, false);
634
	}
635

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
636 637 638 639 640 641
	/* 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);
642

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
643 644
		/* Number of descriptors depends on whether there are
		 * non-internal varyings */
645

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

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

	if (v->uniforms) {
652
		int rows = uniform_count, width = 4;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
653 654 655 656 657 658 659 660 661 662
		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++) {
663
			panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
664 665 666 667 668 669 670 671 672 673 674

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

			panwrap_log_cont("\n");

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

675
		TOUCH_LEN(mem, v->uniforms, sz, "uniforms", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
676 677
	}

678 679 680 681 682 683 684 685 686
	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;

687 688 689 690 691
			/* 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);
692
			TOUCH_LEN(umem, ptr, 0, "inner_unknown1", job_no, true);
693 694

			panwrap_log("u64 unknown1_%d = ((inner_unknown1_%d_p) << 8) | %d;\n", job_no, job_no, flags);
695
			TOUCH(umem, v->unknown1, u64, "unknown1", job_no, true);
696 697
		}
	}
698 699 700 701 702

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

		if (umem) {
703
			struct mali_unknown6 *PANWRAP_PTR_VAR(u, umem, v->unknown6 & ~0xF);
704 705 706 707 708 709 710 711 712 713 714

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

715
			TOUCH(umem, v->unknown6 & ~0xF, *u, "unknown6", job_no, true);
716 717
		}
	}
718

719 720
	/* Just a pointer to... another pointer >_< */

721 722
	if (v->texture_trampoline) {
		struct panwrap_mapped_memory *mmem = panwrap_find_mapped_gpu_mem_containing(v->texture_trampoline);
723 724

		if (mmem) {
725
			mali_ptr *PANWRAP_PTR_VAR(u, mmem, v->texture_trampoline);
726 727

			char *a = pointer_as_memory_reference(*u);
728
			panwrap_log("uint64_t texture_trampoline_%d = %s;", job_no, a);
729 730
			free(a);

731
			TOUCH(mmem, v->texture_trampoline, *u, "texture_trampoline", job_no, true);
732 733 734 735 736 737 738 739 740 741

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

745
				panwrap_prop("unknown1 = 0x%" PRIx32, t->unknown1);
746
				
747
				/* TODO: I don't understand how this works at all yet */
748
				panwrap_prop("format1 = 0x%" PRIx32, t->format1);
749 750 751 752 753 754 755 756 757 758 759

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

761
				panwrap_prop("unknown3 = 0x%" PRIx32, t->unknown3);
762

763 764 765
				panwrap_prop("unknown5 = 0x%" PRIx32, t->unknown5);
				panwrap_prop("unknown6 = 0x%" PRIx32, t->unknown6);
				panwrap_prop("unknown7 = 0x%" PRIx32, t->unknown7);
766 767 768

				MEMORY_PROP(t, swizzled_bitmap_0);
				MEMORY_PROP(t, swizzled_bitmap_1);
769 770 771 772

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

773
				TOUCH(tmem, *u, *t, "texture_descriptor", job_no, false);
774
			}
775 776 777
		}
	}

778 779 780 781 782 783 784 785 786
	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++;

787
			/* Only the lower two bits are understood right now; the rest we display as hex */
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
788
			panwrap_log(".filter_mode = MALI_GL_TEX_MIN(%s) | MALI_GL_TEX_MAG(%s) | 0x%" PRIx32",\n",
789 790 791
				       	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);
792 793

			panwrap_prop("unknown1 = 0x%" PRIx32, s->unknown1);
794 795 796 797 798 799 800 801 802 803 804 805 806

			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);
807 808 809 810

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

811
			TOUCH(smem, v->sampler_descriptor, *s, "sampler_descriptor", job_no, false);
812 813
		}
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834

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

835
			TOUCH_LEN(imem, v->indices, sizeof(uint32_t) * (v->index_count + 1), "indices", job_no, false);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
836 837
		}
	}
838 839


840
	panwrap_log("struct mali_payload_vertex_tiler payload_%d = {\n", job_no);
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
	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);

	if (h->job_type == JOB_TYPE_TILER) {
		panwrap_prop("draw_mode = 0x%" PRIx32 " | %s", v->draw_mode & ~(0xF), panwrap_gl_mode_name(v->draw_mode & 0xF));
	} 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");

	if (v->zero0 | v->zero1 | v->zero3 | v->zero4 | v->zero5 | v->zero6) {
		panwrap_msg("Zero tripped, replay may be wrong\n");
		panwrap_prop("zero0 = 0x%" PRIx32, v->zero0);
		panwrap_prop("zero1 = 0x%" PRIx32, v->zero1);
		panwrap_prop("zero3 = 0x%" PRIx32, v->zero3);
		panwrap_prop("zero4 = 0x%" PRIx32, v->zero4);
		panwrap_prop("zero5 = 0x%" PRIx32, v->zero5);
		panwrap_prop("zero6 = 0x%" PRIx32, v->zero6);
	}

886
	DYN_MEMORY_PROP(v, job_no, indices);
887
	//DYN_MEMORY_PROP(v, job_no, unknown0);
888
	DYN_MEMORY_PROP(v, job_no, unknown1); 
889
	DYN_MEMORY_PROP(v, job_no, texture_trampoline);
890
	DYN_MEMORY_PROP(v, job_no, sampler_descriptor);
891 892 893 894
	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); 
895
	//DYN_MEMORY_PROP(v, job_no, unknown6);
896
	DYN_MEMORY_PROP(v, job_no, viewport);
897
	DYN_MEMORY_PROP(v, job_no, framebuffer);
898

899
	MEMORY_PROP(v, unknown0);
900

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

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

907 908 909
	panwrap_indent--;
	panwrap_log("};\n");

910
	return sizeof(*v);
911 912
}

913
static int panwrap_replay_fragment_job(const struct panwrap_mapped_memory *mem,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
914 915 916 917
					mali_ptr payload, int job_no)
{
	const struct mali_payload_fragment *PANWRAP_PTR_VAR(s, mem, payload);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
918 919
	bool fbd_dumped = false;

920
	if ((s->framebuffer & FBD_TYPE) == MALI_SFBD) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
921 922 923 924 925 926 927 928
		/* 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. */

929
		panwrap_replay_sfbd(s->framebuffer & FBD_MASK, job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
930 931 932
		fbd_dumped = true;
	}

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

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

938 939 940
	if (s->zero)
		panwrap_msg("ZT\n");

941 942 943
	/* See the comments by the macro definitions for mathematical context
	 * on why this is so weird */

944 945 946 947 948 949 950 951 952
	panwrap_prop("min_tile_coord = MALI_COORDINATE_TO_TILE_MIN(%d, %d, %d)",
			MALI_TILE_COORD_X(s->min_tile_coord) << MALI_TILE_SHIFT,
			MALI_TILE_COORD_Y(s->min_tile_coord) << MALI_TILE_SHIFT,
			MALI_TILE_COORD_FLAGS(s->min_tile_coord));

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

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

957
	const char *fbd_type = s->framebuffer & MALI_MFBD ? "MALI_MFBD" : "MALI_SFBD";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
958 959

	if (fbd_dumped)
960
		panwrap_prop("framebuffer = framebuffer_%d_p | %s", job_no, fbd_type);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
961
	else
962
		panwrap_prop("framebuffer = %s | %s", pointer_as_memory_reference(p), fbd_type);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
963

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
964 965
	panwrap_indent--;
	panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
966

967
	return sizeof(*s);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
968 969
}

970 971
static int job_descriptor_number = 0;

972
int panwrap_replay_jc(mali_ptr jc_gpu_va)
973 974 975
{
	struct mali_job_descriptor_header *h;

976 977
	int start_number;

978
	bool first = true;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
979
	bool last_size;
980

981
	do {
982 983 984
		struct panwrap_mapped_memory *mem =
			panwrap_find_mapped_gpu_mem_containing(jc_gpu_va);

985 986 987
		void *payload;

		h = PANWRAP_PTR(mem, jc_gpu_va, typeof(*h));
988 989 990 991

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

992 993 994
		payload = panwrap_fetch_gpu_mem(mem, payload_ptr,
						MALI_PAYLOAD_SIZE);

995 996
		int job_no = job_descriptor_number++;

997 998 999
		if (first)
			start_number = job_no;

1000 1001 1002
		panwrap_log("struct mali_job_descriptor_header job_%d = {\n", job_no);
		panwrap_indent++;

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1005 1006 1007
		/* Save for next job fixing */
		last_size = h->job_descriptor_size;

1008 1009 1010
		if (h->job_descriptor_size)
			panwrap_prop("job_descriptor_size = %d", h->job_descriptor_size);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
		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);

1023 1024
		panwrap_prop("job_index = %d", h->job_index);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1025 1026 1027
		if (h->unknown_flags)
			panwrap_prop("unknown_flags = %d", h->unknown_flags);

1028
		if (h->job_dependency_index_1)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1029
			panwrap_prop("job_dependency_index_1 = %d", h->job_dependency_index_1);
1030

1031 1032
		if (h->job_dependency_index_2)
			panwrap_prop("job_dependency_index_2 = %d", h->job_dependency_index_2);
1033

1034 1035 1036
		panwrap_indent--;
		panwrap_log("};\n");

1037 1038 1039 1040 1041
		/* 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. */
1042

1043
		int payload_size = 0;
1044

1045 1046 1047 1048 1049
		switch (h->job_type) {
		case JOB_TYPE_SET_VALUE:
			{
				struct mali_payload_set_value *s = payload;

1050
				panwrap_log("struct mali_payload_set_value payload_%d = {\n", job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1051
				panwrap_indent++;
1052
				MEMORY_PROP(s, out);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1053 1054 1055
				panwrap_prop("unknown = 0x%" PRIX64, s->unknown);
				panwrap_indent--;
				panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1056

1057
				payload_size = sizeof(*s);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1058

1059 1060 1061 1062
				break;
			}
		case JOB_TYPE_TILER:
		case JOB_TYPE_VERTEX:
1063 1064
			payload_size = panwrap_replay_vertex_or_tiler_job(h, mem, payload_ptr, job_no);

1065 1066
			break;
		case JOB_TYPE_FRAGMENT:
1067
			payload_size = panwrap_replay_fragment_job(mem, payload_ptr, job_no);
1068 1069 1070 1071
			break;
		default:
			break;
		}
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092

		/* 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
1093
	} while ((jc_gpu_va = h->job_descriptor_size ? h->next_job_64 : h->next_job_32));
1094 1095

	return start_number;
1096
}
1097

1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
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++;

1110 1111 1112
	MEMORY_PROP(v, tiler_jc_list);
	MEMORY_PROP(v, fragment_jc);
	MEMORY_PROP(v, tiler_heap_free);
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134

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

1135
	TOUCH(mem, jc_gpu_va, *v, "soft_replay_payload", job_no, false);
1136 1137
}

1138
int panwrap_replay_soft_replay(mali_ptr jc_gpu_va)
1139 1140
{
	struct mali_jd_replay_jc *v;
1141 1142
	int start_no;
	bool first = true;
1143 1144 1145 1146 1147 1148 1149 1150

	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++;
1151 1152 1153 1154 1155 1156 1157

		if (first)
			start_no = job_no;

		first = false;

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

1160 1161
		MEMORY_PROP(v, next);
		MEMORY_PROP(v, jc);
1162 1163 1164 1165

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

1166 1167
		panwrap_replay_soft_replay_payload(jc_gpu_va + sizeof(struct mali_jd_replay_jc), job_no);

1168
		TOUCH(mem, jc_gpu_va, *v, "job", job_no, false);
1169
	} while ((jc_gpu_va = v->next));
1170 1171

	return start_no;
1172
}