pvr: add basic support for shader statistics framework

Mesa now has a statistics framework. This adds support for emitting
additional statistics about PowerVR shaders for the Rogue architecture.

Add support for emitting the following statistics: Code size, scratch
size, spill count, temp count, loop count, number of inst groups, number
of main inst groups, number of bitwise inst groups and number of control
inst groups.
Add support for new PCO_DEBUG_PRINT option "stats" to emit shader stats.

Signed-off-by: Duncan Brawley <duncan.brawley@imgtec.com>
Reviewed-by: Simon Perretta <simon.perretta@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39523>
This commit is contained in:
Duncan Brawley 2026-01-05 11:25:42 +00:00 committed by Marge Bot
parent 41d7debcfe
commit b8889f5eaa
9 changed files with 129 additions and 1 deletions

View file

@ -2168,6 +2168,8 @@ PowerVR driver environment variables
Print verbose IR.
``ra``
Print register alloc info.
``stats``
Print shader stats.
.. envvar:: PCO_COLOR

View file

@ -19,6 +19,7 @@
#include "util/list.h"
#include "util/macros.h"
#include "util/ralloc.h"
#include "util/shader_stats.h"
#include <assert.h>
#include <stdbool.h>
@ -316,3 +317,64 @@ pco_precomp_data pco_get_precomp_data(pco_shader *shader)
.size_dwords = size_dwords,
};
}
/**
* \brief Returns statistics for a shader.
*
* \param[in] shader PCO shader.
* \return The shader statistics.
*/
struct pvr_stats pco_get_pvr_stats(pco_shader *shader)
{
assert(shader->is_grouped);
unsigned shader_size = pco_shader_binary_size(shader);
assert(shader_size > 0);
unsigned loop_count = 0;
unsigned igrp_count = 0;
unsigned main_count = 0;
unsigned bitwise_count = 0;
unsigned control_count = 0;
pco_foreach_func_in_shader (func, shader) {
pco_foreach_loop_in_func (loop, func) {
loop_count++;
}
pco_foreach_igrp_in_func (igrp, func) {
igrp_count++;
switch (igrp->hdr.alutype) {
case PCO_ALUTYPE_MAIN:
main_count++;
break;
case PCO_ALUTYPE_BITWISE:
bitwise_count++;
break;
case PCO_ALUTYPE_CONTROL:
control_count++;
break;
default:
UNREACHABLE("Invalid pco_alutype");
}
}
}
return (struct pvr_stats){
.isa = PVR_STAT_ROGUE,
.rogue = (struct rogue_stats) {
.code_size = shader_size,
.scratch_size = shader->data.common.scratch,
.spill_count = shader->data.common.spilled_temps,
.temp_count = shader->data.common.temps,
.loop_count = loop_count,
.inst_group_count = igrp_count,
.main_inst_group_count = main_count,
.bitwise_inst_group_count = bitwise_count,
.control_inst_group_count = control_count,
},
};
}

View file

@ -55,6 +55,7 @@ const void *pco_shader_binary_data(pco_shader *shader);
void pco_validate_shader(pco_shader *shader, const char *when);
void pco_print_shader_stats(pco_shader *shader, FILE *fp);
void pco_print_shader(pco_shader *shader, FILE *fp, const char *when);
void pco_print_binary(pco_shader *shader, FILE *fp, const char *when);

View file

@ -127,6 +127,9 @@ void pco_encode_ir(pco_ctx *ctx, pco_shader *shader)
if (pco_should_print_binary(shader))
pco_print_binary(shader, stdout, "after encoding");
if (pco_should_print_stats(shader))
pco_print_shader_stats(shader, stdout);
}
/**

View file

@ -256,4 +256,6 @@ typedef struct PACKED _pco_precomp_data {
static_assert(sizeof(pco_precomp_data) == 8, "sizeof(pco_precomp_data) != 8");
pco_precomp_data pco_get_precomp_data(pco_shader *shader);
struct pvr_stats pco_get_pvr_stats(pco_shader *shader);
#endif /* PCO_DATA_H */

View file

@ -42,6 +42,7 @@ static const struct debug_named_value pco_debug_print_options[] = {
{ "binary", PCO_DEBUG_PRINT_BINARY, "Print the resulting binary." },
{ "verbose", PCO_DEBUG_PRINT_VERBOSE, "Print verbose IR." },
{ "ra", PCO_DEBUG_PRINT_RA, "Print register alloc info." },
{ "stats", PCO_DEBUG_PRINT_STATS, "Print shader stats." },
DEBUG_NAMED_VALUE_END,
};

View file

@ -75,6 +75,7 @@ enum pco_debug_print {
PCO_DEBUG_PRINT_BINARY = BITFIELD64_BIT(6),
PCO_DEBUG_PRINT_VERBOSE = BITFIELD64_BIT(7),
PCO_DEBUG_PRINT_RA = BITFIELD64_BIT(8),
PCO_DEBUG_PRINT_STATS = BITFIELD64_BIT(9),
};
extern uint64_t pco_debug_print;
@ -1727,6 +1728,24 @@ static inline bool pco_should_print_binary(pco_shader *shader)
return true;
}
static inline bool pco_should_print_stats(pco_shader *shader)
{
if (!PCO_DEBUG_PRINT(STATS))
return false;
if (shader->is_internal && !PCO_DEBUG_PRINT(INTERNAL))
return false;
if (shader->stage == MESA_SHADER_VERTEX && !PCO_DEBUG_PRINT(VS))
return false;
else if (shader->stage == MESA_SHADER_FRAGMENT && !PCO_DEBUG_PRINT(FS))
return false;
else if (shader->stage == MESA_SHADER_COMPUTE && !PCO_DEBUG_PRINT(CS))
return false;
return true;
}
/* Interface with NIR. */
typedef union PACKED _pco_smp_flags {
struct PACKED {

View file

@ -17,6 +17,7 @@
#include "util/bitscan.h"
#include "util/list.h"
#include "util/macros.h"
#include "util/shader_stats.h"
#include "util/u_hexdump.h"
#include <assert.h>
@ -1239,7 +1240,30 @@ static void _pco_print_shader_info(pco_print_state *state, pco_shader *shader)
pco_printfi(state, "name: \"%s\"\n", shader->name);
pco_printfi(state, "stage: %s\n", mesa_shader_stage_name(shader->stage));
pco_printfi(state, "internal: %s\n", true_false_str(shader->is_internal));
/* TODO: more info/stats, e.g. temps/other regs used, etc.? */
}
/**
* \brief Print PCO shader stats.
*
* \param[in] shader PCO state.
* \param[in] fp Print target file pointer.
*/
void pco_print_shader_stats(pco_shader *shader, FILE *fp)
{
pco_print_state state = {
.fp = fp,
.shader = shader,
.indent = 0,
.is_grouped = shader->is_grouped,
.verbose = PCO_DEBUG_PRINT(VERBOSE),
};
_pco_print_shader_info(&state, shader);
struct pvr_stats stats = pco_get_pvr_stats(shader);
pvr_stats_fprintf(fp,
_mesa_shader_stage_to_abbrev(shader->nir->info.stage),
&stats);
}
/**

View file

@ -187,4 +187,18 @@
</stat>
</isa>
</family>
<family name="PVR">
<isa name="Rogue">
<stat name="Code size">Binary size in bytes</stat>
<stat name="Scratch size">Scratch size per instance in bytes</stat>
<stat name="Spill count">Number of spilled registers per instance</stat>
<stat name="Temp count">Number of allocated temp registers</stat>
<stat name="Loop count">Number of not unrolled loops in the shader</stat>
<stat name="Inst group count">Total number of instruction groups</stat>
<stat name="Main inst group count">Number of main instruction groups</stat>
<stat name="Bitwise inst group count">Number of bitwise instruction groups</stat>
<stat name="Control inst group count">Number of control instruction groups</stat>
</isa>
</family>
</shaderdb>