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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
268 269 270 271 272 273 274 275 276 277 278 279 280
	{
		/* No idea where the weird negative alignment requirements come
		 * from */

		int mask = s->unknown_address_5 & 0xFFF;

		int offset = mask ? 0x1000 - mask : 0;

		char *a = pointer_as_memory_reference(s->unknown_address_5 + offset);
		//panwrap_prop("unknown_address_5 = %s - %d", a, offset);
		free(a);
	}

281
	MEMORY_PROP(s, unknown_address_5);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
282

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

285 286 287 288 289 290 291
	/* 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");

292
	if (s->depth_buffer | s->depth_buffer_enable) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
293
		MEMORY_PROP(s, depth_buffer);
294 295
		panwrap_prop("depth_buffer_enable = %s", DS_ENABLE(s->depth_buffer_enable));
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
296

297
	if (s->stencil_buffer | s->stencil_buffer_enable) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
298
		MEMORY_PROP(s, stencil_buffer);
299 300
		panwrap_prop("stencil_buffer_enable = %s", DS_ENABLE(s->stencil_buffer_enable));
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
301

302 303 304 305 306 307
	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
308

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
309
	if (s->clear_depth_1 != 0 || s->clear_depth_2 != 0 || s->clear_depth_3 != 0 || s->clear_depth_4 != 0) {
310 311 312 313 314
		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
315

316 317 318
	if (s->clear_stencil) {
		panwrap_prop("clear_stencil = 0x%x", s->clear_stencil);
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
319

320 321 322
	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
323 324 325 326

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

327
	MEMORY_PROP(s, tiler_jc_list);
328 329

	MEMORY_PROP(s, unknown_address_4);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
330 331 332 333 334 335 336 337 338 339 340 341 342

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

343
	TOUCH(mem, (mali_ptr) gpu_va, *s, "framebuffer", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
344 345
}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
346
void panwrap_replay_attributes(const struct panwrap_mapped_memory *mem,
347
			       mali_ptr addr, int job_no, int count, bool varying)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
348
{
349
	char *prefix = varying ? "varyings" : "attributes";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
350

351 352
	/* 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
353

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

356 357
	char base[128];
	snprintf(base, sizeof(base), "%s_data_%d", prefix, job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
358

359 360
	for (int i = 0; i < count; ++i) {
		mali_ptr raw_elements = attr[i].elements & ~3;
361

362 363
		size_t vertex_count;
		size_t component_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
364

365 366 367
		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
368

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

371 372
			vertex_count = attr[i].size / attr[i].stride;
			component_count = attr[i].stride / sizeof(float);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
373

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

376 377 378
			panwrap_indent++;
			for (int row = 0; row < vertex_count; row++) {
				panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
379

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

383 384 385 386 387 388
				panwrap_log_cont("\n");

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

390
			TOUCH_LEN(mem, raw_elements, attr[i].size, base, i, true);
391 392 393 394 395 396 397
		} 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
398
	}
399

400
	panwrap_log("struct mali_attr %s_%d[] = {\n", prefix, job_no);
401 402
	panwrap_indent++;

403 404 405 406 407 408 409 410 411 412 413
	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");
414 415 416 417 418
	}

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

419
	TOUCH_LEN(mem, addr, sizeof(*attr) * count, prefix, job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
420 421
}

422 423 424 425 426 427 428 429 430 431 432 433 434
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;
}

435
static void
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
436
panwrap_replay_stencil(const char *name, const u32 *raw)
437
{
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
438
	const struct mali_stencil_test *stencil = (struct mali_stencil_test *) raw;
439

440
	const char *func = panwrap_func_name(stencil->func);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
441 442 443
	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);
444

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
448 449 450 451 452 453 454 455 456 457
	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");
458 459
}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
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");
}

481 482
static int
panwrap_replay_vertex_or_tiler_job(const struct mali_job_descriptor_header *h,
483 484 485 486 487 488
					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
489
	mali_ptr shader_meta_ptr = (u64) (uintptr_t) (v->_shader_upper << 4);
490

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

494
	int varying_count, attribute_count, uniform_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
495

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
496 497 498 499 500 501 502
	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++;

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

505 506
		if (s->zero1)
			panwrap_msg("XXX shader zero tripped\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
507

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
508
		panwrap_prop("attribute_count = %" PRId16, s->attribute_count);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
509
		panwrap_prop("varying_count = %" PRId16, s->varying_count);
510 511
		panwrap_prop("uniform_count = %" PRId16, s->uniform_count);
		panwrap_prop("work_count = %" PRId16, s->work_count);
512 513 514
		panwrap_prop("unknown1 = %s0x%" PRIx32,
				s->unknown1 & MALI_NO_ALPHA_TO_COVERAGE ? "MALI_NO_ALPHA_TO_COVERAGE | " : "",
				s->unknown1 & ~MALI_NO_ALPHA_TO_COVERAGE);
515
		panwrap_prop("unknown2 = 0x%" PRIx32, s->unknown2);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
516

517 518
		/* Save for dumps */
		attribute_count = s->attribute_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
519
		varying_count = s->varying_count;
520
		uniform_count = s->uniform_count; 
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
521

522 523 524
		/* 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
525

526 527 528 529
		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);
		}
530

531 532 533 534 535 536 537
		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));

538
		panwrap_log(".unknown2_3 = ");
539 540

		int unknown2_3 = s->unknown2_3;
541
		int unknown2_4 = s->unknown2_4;
542 543 544 545 546 547 548 549 550 551 552 553
		
		/* 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);
554
		panwrap_log_cont(",\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
555

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
556
		panwrap_log(".unknown2_4 = ");
557 558 559 560 561 562 563 564 565 566

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
569 570
		panwrap_replay_stencil("front", &s->stencil_front);
		panwrap_replay_stencil("back", &s->stencil_back);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
571

572 573
		panwrap_prop("unknown2_7 = 0x%" PRIx32, s->unknown2_7);
		panwrap_prop("unknown2_8 = 0x%" PRIx32, s->unknown2_8);
574 575 576 577

		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
578
			panwrap_replay_blend_equation(&s->blend_equation);
579
		}
580

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
581 582
		panwrap_indent--;
		panwrap_log("};\n");
583
		TOUCH(smem, shader_meta_ptr, *meta, "shader_meta", job_no, false);
584

585
		panwrap_shader_disassemble(shader_ptr, job_no, h->job_type);
586

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
587 588
	} else
		panwrap_msg("<no shader>\n");
589
	
590 591 592
	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);
593

594
		panwrap_log("struct mali_viewport viewport_%d = {\n", job_no);
595
		panwrap_indent++;
596
		panwrap_log(".floats = {\n");
597 598 599 600 601 602
		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--;
603
		panwrap_log("},\n");
604

605 606 607
		panwrap_prop("depth_range_n = %f", f->depth_range_n);
		panwrap_prop("depth_range_f = %f", f->depth_range_f);

608 609 610 611 612 613 614 615
		/* 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);

616 617 618
		panwrap_indent--;
		panwrap_log("};\n");

619
		TOUCH(fmem, v->viewport, *f, "viewport", job_no, true);
620
	}
621 622

	if (v->attribute_meta) {
623
		panwrap_log("struct mali_attr_meta attribute_meta_%d[] = {\n", job_no);
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
		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));

639 640 641
			panwrap_log("{\n");
			panwrap_indent++;
			panwrap_prop("index = %d", attr_meta->index);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
642
			panwrap_prop("type = %d", attr_meta->type);
643
			panwrap_prop("nr_components = MALI_POSITIVE(%d)", MALI_NEGATIVE(attr_meta->nr_components));
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
644 645

			/* TODO: Dissect correctly */
646
			panwrap_prop("is_int_signed = %d", attr_meta->is_int_signed);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
647

648
			panwrap_prop("not_normalised = %d", attr_meta->not_normalised);
649 650
			panwrap_prop("unknown1 = 0x%" PRIx64, (u64) attr_meta->unknown1);
			panwrap_prop("unknown2 = 0x%" PRIx64, (u64) attr_meta->unknown2);
651
			panwrap_prop("unknown3 = 0x%" PRIx64, (u64) attr_meta->unknown3);
652 653 654
			panwrap_indent--;
			panwrap_log("},\n");

655 656 657 658 659
		}

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

660
		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
661 662 663

		attr_mem = panwrap_find_mapped_gpu_mem_containing(v->attributes);

664
		panwrap_replay_attributes( attr_mem, v->attributes, job_no, attribute_count, false);
665
	}
666

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
667 668 669 670 671 672
	/* 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);
673

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
674 675
		/* Number of descriptors depends on whether there are
		 * non-internal varyings */
676

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

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

	if (v->uniforms) {
683
		int rows = uniform_count, width = 4;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
684 685 686 687 688 689 690 691 692 693
		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++) {
694
			panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
695 696 697 698 699 700 701 702 703 704 705

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

			panwrap_log_cont("\n");

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

706
		TOUCH_LEN(mem, v->uniforms, sz, "uniforms", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
707 708
	}

709 710 711 712 713 714 715 716 717
	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;

718 719 720 721 722
			/* 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);
723
			TOUCH_LEN(umem, ptr, 0, "inner_unknown1", job_no, true);
724 725

			panwrap_log("u64 unknown1_%d = ((inner_unknown1_%d_p) << 8) | %d;\n", job_no, job_no, flags);
726
			TOUCH(umem, v->unknown1, u64, "unknown1", job_no, true);
727 728
		}
	}
729 730 731 732 733

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

		if (umem) {
734
			struct mali_unknown6 *PANWRAP_PTR_VAR(u, umem, v->unknown6 & ~0xF);
735 736 737 738 739 740 741 742 743 744 745

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

746
			TOUCH(umem, v->unknown6 & ~0xF, *u, "unknown6", job_no, false);
747 748
		}
	}
749

750 751
	/* Just a pointer to... another pointer >_< */

752 753
	if (v->texture_trampoline) {
		struct panwrap_mapped_memory *mmem = panwrap_find_mapped_gpu_mem_containing(v->texture_trampoline);
754 755

		if (mmem) {
756
			mali_ptr *PANWRAP_PTR_VAR(u, mmem, v->texture_trampoline);
757 758

			char *a = pointer_as_memory_reference(*u);
759
			panwrap_log("uint64_t texture_trampoline_%d = %s;", job_no, a);
760 761
			free(a);

762
			TOUCH(mmem, v->texture_trampoline, *u, "texture_trampoline", job_no, true);
763 764 765 766 767 768 769 770 771 772

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

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

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

792
				panwrap_prop("unknown3 = 0x%" PRIx32, t->unknown3);
793

794 795 796
				panwrap_prop("unknown5 = 0x%" PRIx32, t->unknown5);
				panwrap_prop("unknown6 = 0x%" PRIx32, t->unknown6);
				panwrap_prop("unknown7 = 0x%" PRIx32, t->unknown7);
797 798 799

				MEMORY_PROP(t, swizzled_bitmap_0);
				MEMORY_PROP(t, swizzled_bitmap_1);
800 801 802 803

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

804
				TOUCH(tmem, *u, *t, "texture_descriptor", job_no, false);
805
			}
806 807 808
		}
	}

809 810 811 812 813 814 815 816 817
	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++;

818
			/* Only the lower two bits are understood right now; the rest we display as hex */
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
819
			panwrap_log(".filter_mode = MALI_GL_TEX_MIN(%s) | MALI_GL_TEX_MAG(%s) | 0x%" PRIx32",\n",
820 821 822
				       	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);
823 824

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

			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);
838 839 840 841

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

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

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

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


871
	panwrap_log("struct mali_payload_vertex_tiler payload_%d = {\n", job_no);
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
	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);
	}

917
	DYN_MEMORY_PROP(v, job_no, indices);
918
	//DYN_MEMORY_PROP(v, job_no, unknown0);
919
	DYN_MEMORY_PROP(v, job_no, unknown1); 
920
	DYN_MEMORY_PROP(v, job_no, texture_trampoline);
921
	DYN_MEMORY_PROP(v, job_no, sampler_descriptor);
922 923 924 925
	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); 
926
	//DYN_MEMORY_PROP(v, job_no, unknown6);
927
	DYN_MEMORY_PROP(v, job_no, viewport);
928
	DYN_MEMORY_PROP(v, job_no, framebuffer);
929

930
	MEMORY_PROP(v, unknown0);
931

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

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

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

941
	return sizeof(*v);
942 943
}

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

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

951
	if ((s->framebuffer & FBD_TYPE) == MALI_SFBD) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
952 953 954 955 956 957 958 959
		/* 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. */

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

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

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

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

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

975 976 977 978 979 980 981 982 983
	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
984

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

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

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

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

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

1001 1002
static int job_descriptor_number = 0;

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

1007 1008
	int start_number;

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

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

1016 1017 1018
		void *payload;

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

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

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

1026 1027
		int job_no = job_descriptor_number++;

1028 1029 1030
		if (first)
			start_number = job_no;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1074
		int payload_size = 0;
1075

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

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

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

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

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

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

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

		/* Handle linkage */

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

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

		first = false;


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

	return start_number;
1127
}
1128

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

	struct panwrap_mapped_memory *mem =
		panwrap_find_mapped_gpu_mem_containing(jc_gpu_va);

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

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

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

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

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

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

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

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

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

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

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

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

		if (first)
			start_no = job_no;

		first = false;

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

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

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

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

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

	return start_no;
1203
}