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

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

21 22
#include "panwrap-shader.h"

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

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

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

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

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

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

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

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

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

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

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

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

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



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

#undef DEFINE_CASE

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

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



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

226 227 228 229 230 231 232
static inline char *panwrap_decode_fbd_type(enum mali_fbd_type type)
{
	if (type == MALI_SFBD)      return "SFBD";
	else if (type == MALI_MFBD) return "MFBD";
	else return "WTF!?";
}

233 234 235 236 237 238 239 240 241 242 243 244 245 246
static bool
panwrap_deduplicate(struct panwrap_mapped_memory *mem, uint64_t gpu_va, const char *name, int number)
{
	if (mem->touched[(gpu_va - mem->gpu_va) / sizeof(uint32_t)]) {
		/* XXX: Is this correct? */
		panwrap_log("mali_ptr %s_%d_p = %s_%d_p;\n", name, number, name, number - 1);
		return true;
	}

	return false;
}

static void
panwrap_replay_sfbd(uint64_t gpu_va, int job_no)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
247
{
248
	struct panwrap_mapped_memory *mem = panwrap_find_mapped_gpu_mem_containing(gpu_va);
249
	const struct mali_single_framebuffer *PANWRAP_PTR_VAR(s, mem, (mali_ptr) gpu_va);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
250

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

254
	panwrap_log("struct mali_single_framebuffer framebuffer_%d = {\n", job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
255 256 257 258 259
	panwrap_indent++;

	panwrap_prop("unknown1 = 0x%" PRIx32, s->unknown1);
	panwrap_prop("flags = 0x%" PRIx32, s->flags);
	panwrap_prop("heap_free_address = 0x%" PRIx64, s->heap_free_address);
260 261 262 263

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
265 266
	panwrap_prop("width = MALI_POSITIVE(%" PRId16 ")", s->width + 1);
	panwrap_prop("height = MALI_POSITIVE(%" PRId16 ")", s->height + 1);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
267

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

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

272 273 274 275 276 277 278
	/* Earlier in the actual commandstream -- right before width -- but we
	 * delay to flow nicer */

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

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

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

289 290 291 292 293 294
	if (s->clear_color_1 | s->clear_color_2 | s->clear_color_3 | s->clear_color_4) {
		panwrap_prop("clear_color_1 = 0x%" PRIx32, s->clear_color_1);
		panwrap_prop("clear_color_2 = 0x%" PRIx32, s->clear_color_2);
		panwrap_prop("clear_color_3 = 0x%" PRIx32, s->clear_color_3);
		panwrap_prop("clear_color_4 = 0x%" PRIx32, s->clear_color_4);
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
295

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
296
	if (s->clear_depth_1 != 0 || s->clear_depth_2 != 0 || s->clear_depth_3 != 0 || s->clear_depth_4 != 0) {
297 298 299 300 301
		panwrap_prop("clear_depth_1 = %f", s->clear_depth_1);
		panwrap_prop("clear_depth_2 = %f", s->clear_depth_2);
		panwrap_prop("clear_depth_3 = %f", s->clear_depth_3);
		panwrap_prop("clear_depth_4 = %f", s->clear_depth_4);
	}
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
302

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

307 308 309
	MEMORY_PROP(s, unknown_address_0);
	MEMORY_PROP(s, unknown_address_1);
	MEMORY_PROP(s, unknown_address_2);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
310 311 312 313

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

314
	MEMORY_PROP(s, tiler_jc_list);
315 316

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

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

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

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

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

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

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

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

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

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

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
352 353 354 355
		/* gl_VertexID and gl_InstanceID do not have elements to
		 * decode; we would crash if we tried */

		if (!varying && i < MALI_SPECIAL_ATTRIBUTE_BASE) {
356 357
			/* 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
358

359 360
			panwrap_msg("i: %d\n", i);
			panwrap_msg("attr: %llx\n", raw_elements);
361
			float *buffer = panwrap_fetch_gpu_mem(mem, raw_elements, attr[i].size);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
362

363 364
			vertex_count = attr[i].size / attr[i].stride;
			component_count = attr[i].stride / sizeof(float);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
365

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

368 369 370
			panwrap_indent++;
			for (int row = 0; row < vertex_count; row++) {
				panwrap_log_empty();
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
371

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

375 376 377 378 379 380
				panwrap_log_cont("\n");

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

382
			TOUCH_LEN(mem, raw_elements, attr[i].size, base, i, true);
383 384 385 386 387 388 389
		} 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
390
	}
391

392
	panwrap_log("struct mali_attr %s_%d[] = {\n", prefix, job_no);
393 394
	panwrap_indent++;

395 396 397 398 399 400 401 402 403 404 405
	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");
406 407 408 409 410
	}

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

411
	TOUCH_LEN(mem, addr, sizeof(*attr) * count, prefix, job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
412 413
}

414 415 416 417 418 419 420 421 422 423 424 425 426
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;
}

427
static void
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
428
panwrap_replay_stencil(const char *name, const u32 *raw)
429
{
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
430
	const struct mali_stencil_test *stencil = (struct mali_stencil_test *) raw;
431

432
	const char *func = panwrap_func_name(stencil->func);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
433 434 435
	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);
436

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
440 441 442 443 444 445 446 447 448 449
	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");
450 451
}

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
452 453 454 455 456
static void
panwrap_replay_blend_equation(const u32 *raw)
{
	const struct mali_blend_equation *blend = (struct mali_blend_equation *) raw;

457 458
	if (blend->zero1 || blend->padding)
		panwrap_msg("Blend zero tripped: %X, %X\n", blend->zero1, blend->padding);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
459 460 461 462

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

463 464
	panwrap_prop("rgb_mode = 0x%X", blend->rgb_mode);
	panwrap_prop("alpha_mode = 0x%X", blend->alpha_mode);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
465 466 467 468 469 470 471 472 473

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

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

474
static void
475
panwrap_replay_attribute_meta(int job_no, int count, const struct mali_payload_vertex_tiler *v, bool varying)
476 477 478 479 480 481 482 483 484
{
	char base[128];
	char *prefix = varying ? "varying" : "attribute";
	snprintf(base, sizeof(base), "%s_meta", prefix, job_no);

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

	struct mali_attr_meta *attr_meta;
485
	mali_ptr p = varying ? (v->unknown6 & ~0xF) : v->attribute_meta;
486 487 488

	struct panwrap_mapped_memory *attr_mem = panwrap_find_mapped_gpu_mem_containing(p);

489
	for (int i = 0; i < count; ++i, p += sizeof(struct mali_attr_meta)) {
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
		attr_meta = panwrap_fetch_gpu_mem(attr_mem, p,
						  sizeof(*attr_mem));

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

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

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

	}

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

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

518 519
static int
panwrap_replay_vertex_or_tiler_job(const struct mali_job_descriptor_header *h,
520 521 522 523 524 525
					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
526
	mali_ptr shader_meta_ptr = (u64) (uintptr_t) (v->_shader_upper << 4);
527

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

531
	int varying_count, attribute_count, uniform_count;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
532

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
533 534 535 536 537 538 539
	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++;

540 541 542
		/* Shader meta contains metadata for the entire shader core */
		struct mali_tripipe *t = &s->tripipe;
		struct mali_fragment_core *f = &s->fragment_core;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
543

544 545 546 547 548 549 550 551 552 553 554
		/* Save for dumps */
		attribute_count = t->attribute_count;
		varying_count = t->varying_count;
		uniform_count = t->uniform_count; 

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

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

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

557 558 559 560
		panwrap_prop("attribute_count = %" PRId16, t->attribute_count);
		panwrap_prop("varying_count = %" PRId16, t->varying_count);
		panwrap_prop("uniform_count = %" PRId16, t->uniform_count);
		panwrap_prop("work_count = %" PRId16, t->work_count);
561
		panwrap_prop("unknown1 = %s0x%" PRIx32,
562 563 564
				t->unknown1 & MALI_NO_ALPHA_TO_COVERAGE ? "MALI_NO_ALPHA_TO_COVERAGE | " : "",
				t->unknown1 & ~MALI_NO_ALPHA_TO_COVERAGE);
		panwrap_prop("unknown2 = 0x%" PRIx32, t->unknown2);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
565

566 567 568 569 570
		panwrap_indent--;
		panwrap_log("},\n");

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
572

573 574 575
		if (f->depth_units || f->depth_factor) {
			panwrap_prop("depth_units = MALI_NEGATIVE(%f)", f->depth_units - 1.0f);
			panwrap_prop("depth_factor = %f", f->depth_factor);
576
		}
577

578 579
		bool invert_alpha_coverage = f->alpha_coverage & 0xFFF0;
		uint16_t inverted_coverage = invert_alpha_coverage ? ~f->alpha_coverage : f->alpha_coverage;
580 581 582 583 584

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

585
		panwrap_log(".unknown2_3 = ");
586

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
603
		panwrap_log(".unknown2_4 = ");
604 605 606 607 608 609 610 611 612 613

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

616 617
		panwrap_replay_stencil("front", &f->stencil_front);
		panwrap_replay_stencil("back", &f->stencil_back);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
618

619 620
		panwrap_prop("unknown2_7 = 0x%" PRIx32, f->unknown2_7);
		panwrap_prop("unknown2_8 = 0x%" PRIx32, f->unknown2_8);
621

622 623
		if (f->unknown2_3 & MALI_HAS_BLEND_SHADER) {
			panwrap_replay_shader_address("blend_shader", f->blend_shader);
624
		} else {
625
			panwrap_replay_blend_equation(&f->blend_equation);
626
		}
627

628 629 630
		panwrap_indent--;
		panwrap_log("}\n");

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
631 632
		panwrap_indent--;
		panwrap_log("};\n");
633

634
		TOUCH(smem, shader_meta_ptr, *meta, "shader_meta", job_no, false);
635

636
		panwrap_shader_disassemble(shader_ptr, job_no, h->job_type);
637

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
638 639
	} else
		panwrap_msg("<no shader>\n");
640
	
641 642 643
	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);
644

645
		panwrap_log("struct mali_viewport viewport_%d = {\n", job_no);
646
		panwrap_indent++;
647
		panwrap_log(".floats = {\n");
648 649 650 651 652 653
		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--;
654
		panwrap_log("},\n");
655

656 657 658
		panwrap_prop("depth_range_n = %f", f->depth_range_n);
		panwrap_prop("depth_range_f = %f", f->depth_range_f);

659 660 661 662 663 664 665 666
		/* 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);

667 668 669
		panwrap_indent--;
		panwrap_log("};\n");

670
		TOUCH(fmem, v->viewport, *f, "viewport", job_no, true);
671
	}
672 673

	if (v->attribute_meta) {
674
		panwrap_replay_attribute_meta(job_no, attribute_count, v, false);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
675 676

		attr_mem = panwrap_find_mapped_gpu_mem_containing(v->attributes);
677
		panwrap_replay_attributes(attr_mem, v->attributes, job_no, attribute_count, false);
678
	}
679

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
680 681 682 683 684 685
	/* 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);
686

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
687 688
		/* Number of descriptors depends on whether there are
		 * non-internal varyings */
689

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

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

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

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

			panwrap_log_cont("\n");

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

719
		TOUCH_LEN(mem, v->uniforms, sz, "uniforms", job_no, true);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
720 721
	}

722 723 724 725 726 727 728 729 730
	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;

731 732 733 734 735
			/* 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);
736
			TOUCH_LEN(umem, ptr, 0, "inner_unknown1", job_no, true);
737 738

			panwrap_log("u64 unknown1_%d = ((inner_unknown1_%d_p) << 8) | %d;\n", job_no, job_no, flags);
739
			TOUCH(umem, v->unknown1, u64, "unknown1", job_no, true);
740 741
		}
	}
742 743 744 745 746

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

		if (umem) {
747
			struct mali_unknown6 *PANWRAP_PTR_VAR(u, umem, v->unknown6 & ~0xF);
748 749 750 751 752 753 754 755 756 757 758

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

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

761
			panwrap_replay_attribute_meta(job_no, varying_count, v, true);
762 763
		}
	}
764

765 766
	/* Just a pointer to... another pointer >_< */

767 768
	if (v->texture_trampoline) {
		struct panwrap_mapped_memory *mmem = panwrap_find_mapped_gpu_mem_containing(v->texture_trampoline);
769 770

		if (mmem) {
771
			mali_ptr *PANWRAP_PTR_VAR(u, mmem, v->texture_trampoline);
772 773

			char *a = pointer_as_memory_reference(*u);
774
			panwrap_log("uint64_t texture_trampoline_%d = %s;", job_no, a);
775 776
			free(a);

777
			TOUCH(mmem, v->texture_trampoline, *u, "texture_trampoline", job_no, true);
778 779 780 781 782 783 784 785 786 787

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

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

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

807
				panwrap_prop("unknown3 = 0x%" PRIx32, t->unknown3);
808

809 810 811
				panwrap_prop("unknown5 = 0x%" PRIx32, t->unknown5);
				panwrap_prop("unknown6 = 0x%" PRIx32, t->unknown6);
				panwrap_prop("unknown7 = 0x%" PRIx32, t->unknown7);
812 813 814

				MEMORY_PROP(t, swizzled_bitmap_0);
				MEMORY_PROP(t, swizzled_bitmap_1);
815 816 817 818

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

819
				TOUCH(tmem, *u, *t, "texture_descriptor", job_no, false);
820
			}
821 822 823
		}
	}

824 825 826 827 828 829 830 831 832
	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++;

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

			panwrap_prop("unknown1 = 0x%" PRIx32, s->unknown1);
840 841 842 843 844 845 846 847 848 849 850 851 852

			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);
853 854 855 856

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

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

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

881
			TOUCH_LEN(imem, v->indices, sizeof(uint32_t) * (v->index_count + 1), "indices", job_no, false);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
882 883
		}
	}
884 885


886
	panwrap_log("struct mali_payload_vertex_tiler payload_%d = {\n", job_no);
887 888 889 890 891
	panwrap_indent++;

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

894 895
	panwrap_prop("unknown_draw = 0x%" PRIx32, v->unknown_draw);

896
	if (h->job_type == JOB_TYPE_TILER) {
897
		panwrap_prop("draw_mode = %s", panwrap_gl_mode_name(v->draw_mode));
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
	} else {
		panwrap_prop("draw_mode = 0x%" PRIx32, v->draw_mode);
	}

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

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

	uint32_t remaining_gl_enables = v->gl_enables;

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

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

	panwrap_log_decoded_flags(gl_enable_flag_info, remaining_gl_enables);

	panwrap_log_cont(",\n");

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
925 926
	if (v->zero0 | v->zero1 | v->zero3 | v->zero5 | v->zero6) {
		panwrap_msg("Zero tripped\n");
927 928 929 930 931 932 933
		panwrap_prop("zero0 = 0x%" PRIx32, v->zero0);
		panwrap_prop("zero1 = 0x%" PRIx32, v->zero1);
		panwrap_prop("zero3 = 0x%" PRIx32, v->zero3);
		panwrap_prop("zero5 = 0x%" PRIx32, v->zero5);
		panwrap_prop("zero6 = 0x%" PRIx32, v->zero6);
	}

934
	DYN_MEMORY_PROP(v, job_no, indices);
935
	//DYN_MEMORY_PROP(v, job_no, unknown0);
936
	DYN_MEMORY_PROP(v, job_no, unknown1); 
937
	DYN_MEMORY_PROP(v, job_no, texture_trampoline);
938
	DYN_MEMORY_PROP(v, job_no, sampler_descriptor);
939 940 941 942
	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); 
943
	//DYN_MEMORY_PROP(v, job_no, unknown6);
944
	DYN_MEMORY_PROP(v, job_no, viewport);
945
	DYN_MEMORY_PROP(v, job_no, framebuffer);
946

947
	MEMORY_PROP(v, position_varying);
948

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

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

955 956 957
	panwrap_indent--;
	panwrap_log("};\n");

958
	return sizeof(*v);
959 960
}

961
static int panwrap_replay_fragment_job(const struct panwrap_mapped_memory *mem,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
962 963 964 965
					mali_ptr payload, int job_no)
{
	const struct mali_payload_fragment *PANWRAP_PTR_VAR(s, mem, payload);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
966 967
	bool fbd_dumped = false;

968
	if ((s->framebuffer & FBD_TYPE) == MALI_SFBD) {
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
969 970 971 972 973 974 975 976
		/* 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. */

977
		panwrap_replay_sfbd(s->framebuffer & FBD_MASK, job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
978 979 980
		fbd_dumped = true;
	}

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

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

986 987 988
	if (s->zero)
		panwrap_msg("ZT\n");

989 990 991
	/* See the comments by the macro definitions for mathematical context
	 * on why this is so weird */

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
992 993 994 995
	if (MALI_TILE_COORD_FLAGS(s->max_tile_coord) || MALI_TILE_COORD_FLAGS(s->min_tile_coord))
		panwrap_msg("Tile coordinate flag missed, replay wrong\n");

	panwrap_prop("min_tile_coord = MALI_COORDINATE_TO_TILE_MIN(%d, %d)",
996
			MALI_TILE_COORD_X(s->min_tile_coord) << MALI_TILE_SHIFT,
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
997
			MALI_TILE_COORD_Y(s->min_tile_coord) << MALI_TILE_SHIFT);
998

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

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

1006
	const char *fbd_type = s->framebuffer & MALI_MFBD ? "MALI_MFBD" : "MALI_SFBD";
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1007 1008

	if (fbd_dumped)
1009
		panwrap_prop("framebuffer = framebuffer_%d_p | %s", job_no, fbd_type);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1010
	else
1011
		panwrap_prop("framebuffer = %s | %s", pointer_as_memory_reference(p), fbd_type);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1012

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1013 1014
	panwrap_indent--;
	panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1015

1016
	return sizeof(*s);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1017 1018
}

1019 1020
static int job_descriptor_number = 0;

1021
int panwrap_replay_jc(mali_ptr jc_gpu_va)
1022 1023 1024
{
	struct mali_job_descriptor_header *h;

1025 1026
	int start_number;

1027
	bool first = true;
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1028
	bool last_size;
1029

1030
	do {
1031 1032 1033
		struct panwrap_mapped_memory *mem =
			panwrap_find_mapped_gpu_mem_containing(jc_gpu_va);

1034 1035 1036
		void *payload;

		h = PANWRAP_PTR(mem, jc_gpu_va, typeof(*h));
1037 1038 1039 1040

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

1041 1042 1043
		payload = panwrap_fetch_gpu_mem(mem, payload_ptr,
						MALI_PAYLOAD_SIZE);

1044 1045
		int job_no = job_descriptor_number++;

1046 1047 1048
		if (first)
			start_number = job_no;

1049 1050 1051
		panwrap_log("struct mali_job_descriptor_header job_%d = {\n", job_no);
		panwrap_indent++;

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

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1054 1055 1056
		/* Save for next job fixing */
		last_size = h->job_descriptor_size;

1057 1058 1059
		if (h->job_descriptor_size)
			panwrap_prop("job_descriptor_size = %d", h->job_descriptor_size);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
		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);

1072 1073
		panwrap_prop("job_index = %d", h->job_index);

Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1074 1075 1076
		if (h->unknown_flags)
			panwrap_prop("unknown_flags = %d", h->unknown_flags);

1077
		if (h->job_dependency_index_1)
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1078
			panwrap_prop("job_dependency_index_1 = %d", h->job_dependency_index_1);
1079

1080 1081
		if (h->job_dependency_index_2)
			panwrap_prop("job_dependency_index_2 = %d", h->job_dependency_index_2);
1082

1083 1084 1085
		panwrap_indent--;
		panwrap_log("};\n");

1086 1087 1088 1089 1090
		/* 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. */
1091

1092
		int payload_size = 0;
1093

1094 1095 1096 1097 1098
		switch (h->job_type) {
		case JOB_TYPE_SET_VALUE:
			{
				struct mali_payload_set_value *s = payload;

1099
				panwrap_log("struct mali_payload_set_value payload_%d = {\n", job_no);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1100
				panwrap_indent++;
1101
				MEMORY_PROP(s, out);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1102 1103 1104
				panwrap_prop("unknown = 0x%" PRIX64, s->unknown);
				panwrap_indent--;
				panwrap_log("};\n");
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1105

1106
				payload_size = sizeof(*s);
Alyssa Rosenzweig's avatar
Alyssa Rosenzweig committed
1107

1108 1109 1110 1111
				break;
			}
		case JOB_TYPE_TILER:
		case JOB_TYPE_VERTEX:
1112 1113
			payload_size = panwrap_replay_vertex_or_tiler_job(h, mem, payload_ptr, job_no);

1114 1115
			break;
		case JOB_TYPE_FRAGMENT:
1116
			payload_size = panwrap_replay_fragment_job(mem, payload_ptr, job_no);
1117 1118 1119 1120
			break;
		default:
			break;
		}
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141

		/* 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
1142
	} while ((jc_gpu_va = h->job_descriptor_size ? h->next_job_64 : h->next_job_32));
1143 1144

	return start_number;
1145
}
1146

1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
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++;

1159 1160 1161
	MEMORY_PROP(v, tiler_jc_list);
	MEMORY_PROP(v, fragment_jc);
	MEMORY_PROP(v, tiler_heap_free);
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183

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

1184
	TOUCH(mem, jc_gpu_va, *v, "soft_replay_payload", job_no, false);
1185 1186
}

1187
int panwrap_replay_soft_replay(mali_ptr jc_gpu_va)
1188 1189
{
	struct mali_jd_replay_jc *v;
1190 1191
	int start_no;
	bool first = true;
1192 1193 1194 1195 1196 1197 1198 1199

	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++;
1200 1201 1202 1203 1204 1205 1206

		if (first)
			start_no = job_no;

		first = false;

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

1209 1210
		MEMORY_PROP(v, next);
		MEMORY_PROP(v, jc);
1211 1212 1213 1214

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

1215 1216
		panwrap_replay_soft_replay_payload(jc_gpu_va + sizeof(struct mali_jd_replay_jc), job_no);

1217
		TOUCH(mem, jc_gpu_va, *v, "job", job_no, false);
1218
	} while ((jc_gpu_va = v->next));
1219 1220

	return start_no;
1221
}