pan/decode: Use GLSL style formats/swizzles

This dramatically reduces visual clutter: now an entire
attribute/varying record looks something like:

    rgba32f attribute_0[16].bgra;

which is equivalent to the raw structure:

{
   .index = 0,
   .format = MALI_FORMAT_RGBA32F,
   .swizzle = (MALI_CHANNEL_BLUE << 9) | ....,
   .src_offset = 16,
}

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
This commit is contained in:
Alyssa Rosenzweig 2019-08-20 14:34:09 -07:00
parent ac090b365f
commit e09392fc27
2 changed files with 133 additions and 122 deletions

View file

@ -29,6 +29,7 @@
#include <memory.h>
#include <stdbool.h>
#include <stdarg.h>
#include <ctype.h>
#include "decode.h"
#include "util/macros.h"
#include "util/u_math.h"
@ -431,25 +432,6 @@ static char *pandecode_attr_mode(enum mali_attr_mode mode)
#undef DEFINE_CASE
#define DEFINE_CASE(name) case MALI_CHANNEL_## name: return "MALI_CHANNEL_" #name
static char *
pandecode_channel(enum mali_channel channel)
{
switch (channel) {
DEFINE_CASE(RED);
DEFINE_CASE(GREEN);
DEFINE_CASE(BLUE);
DEFINE_CASE(ALPHA);
DEFINE_CASE(ZERO);
DEFINE_CASE(ONE);
default:
pandecode_msg("XXX: invalid channel %X\n", channel);
return "";
}
}
#undef DEFINE_CASE
#define DEFINE_CASE(name) case MALI_WRAP_## name: return "MALI_WRAP_" #name
static char *
pandecode_wrap_mode(enum mali_wrap_mode op)
@ -753,14 +735,118 @@ pandecode_compute_fbd(uint64_t gpu_va, int job_no)
printf("},\n");
}
static void
pandecode_swizzle(unsigned swizzle)
/* Extracts the number of components associated with a Mali format */
static unsigned
pandecode_format_component_count(enum mali_format fmt)
{
pandecode_prop("swizzle = %s | (%s << 3) | (%s << 6) | (%s << 9)",
pandecode_channel((swizzle >> 0) & 0x7),
pandecode_channel((swizzle >> 3) & 0x7),
pandecode_channel((swizzle >> 6) & 0x7),
pandecode_channel((swizzle >> 9) & 0x7));
/* Mask out the format class */
unsigned top = fmt & 0b11100000;
switch (top) {
case MALI_FORMAT_SNORM:
case MALI_FORMAT_UINT:
case MALI_FORMAT_UNORM:
case MALI_FORMAT_SINT:
return ((fmt >> 3) & 3) + 1;
default:
/* TODO: Validate */
return 4;
}
}
/* Extracts a mask of accessed components from a 12-bit Mali swizzle */
static unsigned
pandecode_access_mask_from_channel_swizzle(unsigned swizzle)
{
unsigned mask = 0;
assert(MALI_CHANNEL_RED == 0);
for (unsigned c = 0; c < 4; ++c) {
enum mali_channel chan = (swizzle >> (3*c)) & 0x7;
if (chan <= MALI_CHANNEL_ALPHA)
mask |= (1 << chan);
}
return mask;
}
/* Validates that a (format, swizzle) pair is valid, in the sense that the
* swizzle doesn't access any components that are undefined in the format.
* Returns whether the swizzle is trivial (doesn't do any swizzling) and can be
* omitted */
static bool
pandecode_validate_format_swizzle(enum mali_format fmt, unsigned swizzle)
{
unsigned nr_comp = pandecode_format_component_count(fmt);
unsigned access_mask = pandecode_access_mask_from_channel_swizzle(swizzle);
unsigned valid_mask = (1 << nr_comp) - 1;
unsigned invalid_mask = ~valid_mask;
if (access_mask & invalid_mask) {
pandecode_msg("XXX: invalid components accessed\n");
return false;
}
/* Check for the default non-swizzling swizzle so we can suppress
* useless printing for the defaults */
unsigned default_swizzles[4] = {
MALI_CHANNEL_RED | (MALI_CHANNEL_ZERO << 3) | (MALI_CHANNEL_ZERO << 6) | (MALI_CHANNEL_ONE << 9),
MALI_CHANNEL_RED | (MALI_CHANNEL_GREEN << 3) | (MALI_CHANNEL_ZERO << 6) | (MALI_CHANNEL_ONE << 9),
MALI_CHANNEL_RED | (MALI_CHANNEL_GREEN << 3) | (MALI_CHANNEL_BLUE << 6) | (MALI_CHANNEL_ONE << 9),
MALI_CHANNEL_RED | (MALI_CHANNEL_GREEN << 3) | (MALI_CHANNEL_BLUE << 6) | (MALI_CHANNEL_ALPHA << 9)
};
return (swizzle == default_swizzles[nr_comp - 1]);
}
/* Maps MALI_RGBA32F to rgba32f, etc */
static void
pandecode_format_short(enum mali_format fmt)
{
/* We want a type-like format, so cut off the initial MALI_ */
char *format = pandecode_format(fmt);
format += strlen("MALI_");
unsigned len = strlen(format);
char *lower_format = calloc(1, len + 1);
for (unsigned i = 0; i < len; ++i)
lower_format[i] = tolower(format[i]);
pandecode_log_cont("%s", lower_format);
free(lower_format);
}
static void
pandecode_swizzle(unsigned swizzle, enum mali_format format)
{
/* First, do some validation */
bool trivial_swizzle = pandecode_validate_format_swizzle(
format, swizzle);
if (trivial_swizzle)
return;
/* Next, print the swizzle */
pandecode_log_cont(".");
static const char components[] = "rgba01";
for (unsigned c = 0; c < 4; ++c) {
enum mali_channel chan = (swizzle >> (3 * c)) & 0x7;
if (chan >= MALI_CHANNEL_RESERVED_0) {
pandecode_log("XXX: invalid swizzle channel %d\n", chan);
continue;
}
pandecode_log_cont("%c", components[chan]);
}
}
static void
@ -776,6 +862,11 @@ pandecode_rt_format(struct mali_rt_format format)
pandecode_prop("block = %s",
pandecode_mfbd_block_format(format.block));
/* TODO: Map formats so we can check swizzles and print nicely */
pandecode_log("swizzle");
pandecode_swizzle(format.swizzle, MALI_RGBA8_UNORM);
pandecode_log_cont(",\n");
pandecode_prop("nr_channels = MALI_POSITIVE(%d)",
MALI_NEGATIVE(format.nr_channels));
@ -783,8 +874,6 @@ pandecode_rt_format(struct mali_rt_format format)
pandecode_log_decoded_flags(mfbd_fmt_flag_info, format.flags);
pandecode_log_cont(",\n");
pandecode_swizzle(format.swizzle);
/* In theory, the no_preload bit can be cleared to enable MFBD preload,
* which is a faster hardware-based alternative to the wallpaper method
* to preserve framebuffer contents across frames. In practice, MFBD
@ -1370,75 +1459,6 @@ pandecode_midgard_blend_mrt(void *descs, int job_no, int rt_no)
* want to validate that the combinations specified are self-consistent.
*/
/* Extracts the number of components associated with a Mali format */
static unsigned
pandecode_format_component_count(enum mali_format fmt)
{
/* Mask out the format class */
unsigned top = fmt & 0b11100000;
switch (top) {
case MALI_FORMAT_SNORM:
case MALI_FORMAT_UINT:
case MALI_FORMAT_UNORM:
case MALI_FORMAT_SINT:
return ((fmt >> 3) & 3) + 1;
default:
/* TODO: Validate */
return 4;
}
}
/* Extracts a mask of accessed components from a 12-bit Mali swizzle */
static unsigned
pandecode_access_mask_from_channel_swizzle(unsigned swizzle)
{
unsigned mask = 0;
assert(MALI_CHANNEL_RED == 0);
for (unsigned c = 0; c < 4; ++c) {
enum mali_channel chan = (swizzle >> (3*c)) & 0x7;
if (chan <= MALI_CHANNEL_ALPHA)
mask |= (1 << chan);
}
return mask;
}
/* Validates that a (format, swizzle) pair is valid, in the sense that the
* swizzle doesn't access any components that are undefined in the format.
* Returns whether the swizzle is trivial (doesn't do any swizzling) and can be
* omitted */
static bool
pandecode_validate_format_swizzle(enum mali_format fmt, unsigned swizzle)
{
unsigned nr_comp = pandecode_format_component_count(fmt);
unsigned access_mask = pandecode_access_mask_from_channel_swizzle(swizzle);
unsigned valid_mask = (1 << nr_comp) - 1;
unsigned invalid_mask = ~valid_mask;
if (access_mask & invalid_mask) {
pandecode_msg("XXX: invalid components accessed\n");
return false;
}
/* Check for the default non-swizzling swizzle so we can suppress
* useless printing for the defaults */
unsigned default_swizzles[4] = {
MALI_CHANNEL_RED | (MALI_CHANNEL_ZERO << 3) | (MALI_CHANNEL_ZERO << 6) | (MALI_CHANNEL_ONE << 9),
MALI_CHANNEL_RED | (MALI_CHANNEL_GREEN << 3) | (MALI_CHANNEL_ZERO << 6) | (MALI_CHANNEL_ONE << 9),
MALI_CHANNEL_RED | (MALI_CHANNEL_GREEN << 3) | (MALI_CHANNEL_BLUE << 6) | (MALI_CHANNEL_ONE << 9),
MALI_CHANNEL_RED | (MALI_CHANNEL_GREEN << 3) | (MALI_CHANNEL_BLUE << 6) | (MALI_CHANNEL_ALPHA << 9)
};
return (swizzle == default_swizzles[nr_comp - 1]);
}
static int
pandecode_attribute_meta(int job_no, int count, const struct mali_vertex_tiler_postfix *v, bool varying, char *suffix)
{
@ -1491,25 +1511,9 @@ pandecode_attribute_meta(int job_no, int count, const struct mali_vertex_tiler_p
}
}
pandecode_log("{\n");
pandecode_indent++;
pandecode_prop("index = %d", attr_meta->index);
if (attr_meta->index > max_index)
max_index = attr_meta->index;
/* Check the swizzle/format, and if they match and the swizzle
* is simple enough, we can avoid printing the swizzle since
* it's just noise */
bool trivial_swizzle = pandecode_validate_format_swizzle(
attr_meta->format, attr_meta->swizzle);
if (!trivial_swizzle)
pandecode_swizzle(attr_meta->swizzle);
pandecode_prop("format = %s", pandecode_format(attr_meta->format));
if (attr_meta->unknown1 != 0x2) {
pandecode_msg("XXX: expected unknown1 = 0x2\n");
pandecode_prop("unknown1 = 0x%" PRIx64, (u64) attr_meta->unknown1);
@ -1520,10 +1524,16 @@ pandecode_attribute_meta(int job_no, int count, const struct mali_vertex_tiler_p
pandecode_prop("unknown3 = 0x%" PRIx64, (u64) attr_meta->unknown3);
}
pandecode_prop("src_offset = %d", attr_meta->src_offset);
pandecode_indent--;
pandecode_log("},\n");
pandecode_make_indent();
pandecode_format_short(attr_meta->format);
pandecode_log_cont(" %s_%u", prefix, attr_meta->index);
if (attr_meta->src_offset)
pandecode_log_cont("[%u]", attr_meta->src_offset);
pandecode_swizzle(attr_meta->swizzle, attr_meta->format);
pandecode_log_cont(";\n");
}
pandecode_indent--;
@ -2038,8 +2048,11 @@ pandecode_vertex_tiler_postfix_pre(const struct mali_vertex_tiler_postfix *p,
pandecode_log(".format = {\n");
pandecode_indent++;
pandecode_swizzle(f.swizzle);
pandecode_prop("format = %s", pandecode_format(f.format));
pandecode_log(".format = ");
pandecode_format_short(f.format);
pandecode_swizzle(f.swizzle, f.format);
pandecode_log_cont(",\n");
pandecode_prop("type = %s", pandecode_texture_type(f.type));
pandecode_prop("srgb = %" PRId32, f.srgb);
pandecode_prop("unknown1 = %" PRId32, f.unknown1);
@ -2048,8 +2061,6 @@ pandecode_vertex_tiler_postfix_pre(const struct mali_vertex_tiler_postfix *p,
pandecode_indent--;
pandecode_log("},\n");
pandecode_swizzle(t->swizzle);
if (t->swizzle_zero) {
/* Shouldn't happen */
pandecode_msg("XXX: swizzle zero tripped\n");

View file

@ -33,7 +33,7 @@
#define DEFINE_CASE(name) case MALI_## name: return "MALI_" #name
char *pandecode_format(enum mali_format format)
{
static char unk_format_str[5];
static char unk_format_str[10];
switch (format) {
DEFINE_CASE(RGB565);
@ -118,7 +118,7 @@ char *pandecode_format(enum mali_format format)
DEFINE_CASE(RGBA8_2);
DEFINE_CASE(RGB10_A2_2);
default:
snprintf(unk_format_str, sizeof(unk_format_str), "0x%02x", format);
snprintf(unk_format_str, sizeof(unk_format_str), "MALI_0x%02x", format);
return unk_format_str;
}
}