pco: printing and validation boilerplate

Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32258>
This commit is contained in:
Simon Perretta 2024-05-13 19:50:01 +01:00 committed by Marge Bot
parent 3c51c6ac17
commit f014a14e2c
7 changed files with 361 additions and 11 deletions

View file

@ -10,7 +10,9 @@ libpowervr_compiler_files = files(
'pco_end.c',
'pco_ir.c',
'pco_nir.c',
'pco_print.c',
'pco_trans_nir.c',
'pco_validate.c',
)
pco_pygen_dep_files = files('pco_pygen_common.py', 'pco_isa.py', 'pco_ops.py')

View file

@ -42,4 +42,9 @@ void pco_shader_finalize(pco_ctx *ctx, pco_shader *shader);
unsigned pco_shader_binary_size(pco_shader *shader);
const void *pco_shader_binary_data(pco_shader *shader);
void pco_validate_shader(pco_shader *shader, const char *when);
void pco_print_shader(pco_shader *shader, FILE *fp, const char *when);
void pco_print_binary(pco_shader *shader, FILE *fp, const char *when);
#endif /* PCO_H */

View file

@ -25,6 +25,9 @@
void pco_encode_ir(pco_ctx *ctx, pco_shader *shader)
{
puts("finishme: pco_encode_ir");
if (pco_should_print_binary(shader))
pco_print_binary(shader, stdout, "after encoding");
}
/**
@ -36,6 +39,9 @@ void pco_encode_ir(pco_ctx *ctx, pco_shader *shader)
void pco_shader_finalize(pco_ctx *ctx, pco_shader *shader)
{
puts("finishme: pco_shader_finalize");
if (pco_should_print_binary(shader))
pco_print_binary(shader, stdout, "after finalize");
}
/**

View file

@ -616,6 +616,76 @@ static inline pco_igrp *pco_prev_igrp(pco_igrp *igrp)
return list_entry(igrp->link.prev, pco_igrp, link);
}
/* Debug printing helpers. */
static inline bool pco_should_print_nir(nir_shader *nir)
{
if (!PCO_DEBUG_PRINT(NIR))
return false;
if (nir->info.internal && !PCO_DEBUG_PRINT(INTERNAL))
return false;
if (nir->info.stage == MESA_SHADER_VERTEX && !PCO_DEBUG_PRINT(VS))
return false;
else if (nir->info.stage == MESA_SHADER_FRAGMENT && !PCO_DEBUG_PRINT(FS))
return false;
else if (nir->info.stage == MESA_SHADER_COMPUTE && !PCO_DEBUG_PRINT(CS))
return false;
return true;
}
static inline bool pco_should_print_shader(pco_shader *shader)
{
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;
}
static inline bool pco_should_print_shader_pass(pco_shader *shader)
{
if (!PCO_DEBUG_PRINT(PASSES))
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;
}
static inline bool pco_should_print_binary(pco_shader *shader)
{
if (!PCO_DEBUG_PRINT(BINARY))
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;
}
/* PCO IR passes. */
bool pco_end(pco_shader *shader);
#endif /* PCO_INTERNAL_H */

View file

@ -22,17 +22,22 @@ static inline bool pco_should_skip_pass(const char *pass)
return comma_separated_list_contains(pco_skip_passes, pass);
}
#define PCO_PASS(progress, shader, pass, ...) \
do { \
if (pco_should_skip_pass(#pass)) { \
fprintf(stdout, "Skipping pass '%s'\n", #pass); \
break; \
} \
\
if (pass(shader, ##__VA_ARGS__)) { \
UNUSED bool _; \
progress = true; \
} \
#define PCO_PASS(progress, shader, pass, ...) \
do { \
if (pco_should_skip_pass(#pass)) { \
fprintf(stdout, "Skipping pass '%s'\n", #pass); \
break; \
} \
\
if (pass(shader, ##__VA_ARGS__)) { \
UNUSED bool _; \
progress = true; \
\
pco_validate_shader(shader, "after " #pass); \
\
if (pco_should_print_shader_pass(shader)) \
pco_print_shader(shader, stdout, "after " #pass); \
} \
} while (0)
/**
@ -43,7 +48,14 @@ static inline bool pco_should_skip_pass(const char *pass)
*/
void pco_process_ir(pco_ctx *ctx, pco_shader *shader)
{
pco_validate_shader(shader, "before passes");
PCO_PASS(_, shader, pco_end);
pco_validate_shader(shader, "after passes");
if (pco_should_print_shader(shader))
pco_print_shader(shader, stdout, "after passes");
puts("finishme: pco_process_ir");
}

View file

@ -0,0 +1,224 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_print.c
*
* \brief PCO printing functions.
*/
#include "pco.h"
#include "pco_builder.h"
#include "pco_common.h"
#include "pco_internal.h"
#include "util/macros.h"
#include "util/u_hexdump.h"
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
typedef struct _pco_print_state {
FILE *fp; /** The print target file pointer. */
pco_shader *shader; /** The shader being printed. */
unsigned indent; /** The current printing indent. */
bool is_grouped; /** Whether the shader uses igrps. */
} pco_print_state;
enum color_esc {
ESC_RESET = 0,
ESC_BLACK,
ESC_RED,
ESC_GREEN,
ESC_YELLOW,
ESC_BLUE,
ESC_PURPLE,
ESC_CYAN,
ESC_WHITE,
_ESC_COUNT,
};
static
const char *color_esc[2][_ESC_COUNT] = {
[0] = {
[ESC_RESET] = "",
[ESC_BLACK] = "",
[ESC_RED] = "",
[ESC_GREEN] = "",
[ESC_YELLOW] = "",
[ESC_BLUE] = "",
[ESC_PURPLE] = "",
[ESC_CYAN] = "",
[ESC_WHITE] = "",
},
[1] = {
[ESC_RESET] = "\033[0m",
[ESC_BLACK] = "\033[0;30m",
[ESC_RED] = "\033[0;31m",
[ESC_GREEN] = "\033[0;32m",
[ESC_YELLOW] = "\033[0;33m",
[ESC_BLUE] = "\033[0;34m",
[ESC_PURPLE] = "\033[0;35m",
[ESC_CYAN] = "\033[0;36m",
[ESC_WHITE] = "\033[0;37m",
},
};
static inline void RESET(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_RESET], state->fp);
}
static inline void BLACK(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_BLACK], state->fp);
}
static inline void RED(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_RED], state->fp);
}
static inline void GREEN(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_GREEN], state->fp);
}
static inline void YELLOW(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_YELLOW], state->fp);
}
static inline void BLUE(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_BLUE], state->fp);
}
static inline void PURPLE(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_PURPLE], state->fp);
}
static inline void CYAN(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_CYAN], state->fp);
}
static inline void WHITE(pco_print_state *state)
{
fputs(color_esc[pco_color][ESC_WHITE], state->fp);
}
inline static const char *true_false_str(bool b)
{
return b ? "true" : "false";
}
static void
_pco_printf(pco_print_state *state, bool nl, const char *fmt, va_list args)
{
if (nl)
for (unsigned u = 0; u < state->indent; ++u)
fputs(" ", state->fp);
vfprintf(state->fp, fmt, args);
}
/**
* \brief Formatted print.
*
* \param[in] state Print state.
* \param[in] fmt Print format.
*/
PRINTFLIKE(2, 3)
static void pco_printf(pco_print_state *state, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
_pco_printf(state, false, fmt, args);
va_end(args);
}
/**
* \brief Formatted print, with indentation.
*
* \param[in] state Print state.
* \param[in] fmt Print format.
*/
PRINTFLIKE(2, 3)
static void pco_printfi(pco_print_state *state, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
_pco_printf(state, true, fmt, args);
va_end(args);
}
/**
* \brief Print PCO shader info.
*
* \param[in] state Print state.
* \param[in] shader PCO shader.
*/
static void pco_print_shader_info(pco_print_state *state, pco_shader *shader)
{
if (shader->name)
pco_printfi(state, "name: \"%s\"\n", shader->name);
pco_printfi(state, "stage: %s\n", gl_shader_stage_name(shader->stage));
pco_printfi(state, "internal: %s\n", true_false_str(shader->is_internal));
/* TODO: more info/stats, e.g. stage, temps/other regs used, etc.? */
}
/**
* \brief Print PCO shader.
*
* \param[in] shader PCO shader.
* \param[in] fp Print target file pointer.
* \param[in] when When the printing is being performed.
*/
void pco_print_shader(pco_shader *shader, FILE *fp, const char *when)
{
pco_print_state state = {
.fp = fp,
.shader = shader,
.indent = 0,
.is_grouped = shader->is_grouped,
};
if (when)
fprintf(fp, "%s\n", when);
pco_print_shader_info(&state, shader);
pco_printfi(&state, "finishme: pco_print_shader\n");
}
/**
* \brief Print PCO shader binary.
*
* \param[in] shader PCO shader.
* \param[in] fp Print target file pointer.
* \param[in] when When the printing is being performed.
*/
void pco_print_binary(pco_shader *shader, FILE *fp, const char *when)
{
pco_print_state state = {
.fp = fp,
.shader = shader,
.indent = 0,
.is_grouped = shader->is_grouped,
};
if (when)
fprintf(fp, "%s\n", when);
pco_print_shader_info(&state, shader);
return u_hexdump(fp,
pco_shader_binary_data(shader),
pco_shader_binary_size(shader),
true);
}

View file

@ -0,0 +1,31 @@
/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \file pco_validate.c
*
* \brief PCO validation functions.
*/
#include "pco.h"
#include "pco_internal.h"
#include "util/macros.h"
/**
* \brief Validates a PCO shader.
*
* \param[in] shader PCO shader.
* \param[in] when When the validation check is being run.
*/
void pco_validate_shader(UNUSED pco_shader *shader, UNUSED const char *when)
{
#ifndef NDEBUG
if (PCO_DEBUG(VAL_SKIP))
return;
puts("finishme: pco_validate_shader");
#endif /* NDEBUG */
}