pco: NIR translation and PCO IR pass 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:
committed by
Marge Bot
parent
f179e5a220
commit
3c51c6ac17
@@ -199,6 +199,7 @@ MacroBlockEnd: ''
|
||||
ForEachMacros: [
|
||||
'foreach_instr',
|
||||
'foreach_instr_safe',
|
||||
'foreach_list_typed',
|
||||
'hash_table_foreach',
|
||||
'LIST_FOR_EACH_ENTRY',
|
||||
'LIST_FOR_EACH_ENTRY_FROM',
|
||||
@@ -220,6 +221,7 @@ ForEachMacros: [
|
||||
'nir_foreach_block_safe',
|
||||
'nir_foreach_block_unstructured',
|
||||
'nir_foreach_function',
|
||||
'nir_foreach_function_with_impl',
|
||||
'nir_foreach_instr',
|
||||
'nir_foreach_instr_safe',
|
||||
'nir_foreach_shader_in_variable',
|
||||
|
||||
@@ -7,6 +7,7 @@ libpowervr_compiler_files = files(
|
||||
'pco.c',
|
||||
'pco_binary.c',
|
||||
'pco_debug.c',
|
||||
'pco_end.c',
|
||||
'pco_ir.c',
|
||||
'pco_nir.c',
|
||||
'pco_trans_nir.c',
|
||||
|
||||
@@ -12,9 +12,13 @@
|
||||
|
||||
#include "pco.h"
|
||||
#include "pco_internal.h"
|
||||
#include "util/list.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/ralloc.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* \brief Allocates and sets up a PCO compiler context.
|
||||
*
|
||||
@@ -65,6 +69,140 @@ const nir_shader_compiler_options *pco_nir_options(pco_ctx *ctx)
|
||||
return &ctx->nir_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates and sets up a PCO shader from a NIR shader.
|
||||
*
|
||||
* \param[in] ctx PCO compiler context.
|
||||
* \param[in] nir The NIR shader.
|
||||
* \return The PCO shader, or NULL on failure.
|
||||
*/
|
||||
pco_shader *pco_shader_create(pco_ctx *ctx, nir_shader *nir, void *mem_ctx)
|
||||
{
|
||||
pco_shader *shader = rzalloc_size(mem_ctx, sizeof(*shader));
|
||||
|
||||
shader->ctx = ctx;
|
||||
shader->nir = nir;
|
||||
shader->stage = nir->info.stage;
|
||||
shader->name = ralloc_strdup(shader, nir->info.name);
|
||||
shader->is_internal = nir->info.internal;
|
||||
shader->is_grouped = false;
|
||||
list_inithead(&shader->funcs);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets up a PCO cf node.
|
||||
*
|
||||
* \param[in,out] cf_node PCO cf node.
|
||||
* \param[in] type CF node type.
|
||||
*/
|
||||
static inline void init_cf_node(pco_cf_node *cf_node,
|
||||
enum pco_cf_node_type type)
|
||||
{
|
||||
cf_node->type = type;
|
||||
cf_node->parent = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates and sets up a PCO function.
|
||||
*
|
||||
* \param[in,out] shader PCO shader.
|
||||
* \param[in] type The function type.
|
||||
* \param[in] num_params The number of parameters.
|
||||
* \return The PCO function, or NULL on failure.
|
||||
*/
|
||||
pco_func *pco_func_create(pco_shader *shader,
|
||||
enum pco_func_type type,
|
||||
unsigned num_params)
|
||||
{
|
||||
pco_func *func = rzalloc_size(shader, sizeof(*func));
|
||||
pco_func *preamble = pco_preamble(shader);
|
||||
|
||||
/* Add the function to the shader; preamble goes first, then entrypoint.
|
||||
* The rest of the functions will get appended.
|
||||
*/
|
||||
if (type == PCO_FUNC_TYPE_PREAMBLE) {
|
||||
assert(!preamble);
|
||||
list_add(&func->link, &shader->funcs);
|
||||
} else if (type == PCO_FUNC_TYPE_ENTRYPOINT) {
|
||||
assert(!pco_entrypoint(shader));
|
||||
list_add(&func->link, !preamble ? &shader->funcs : &preamble->link);
|
||||
} else {
|
||||
list_addtail(&func->link, &shader->funcs);
|
||||
}
|
||||
|
||||
init_cf_node(&func->cf_node, PCO_CF_NODE_TYPE_FUNC);
|
||||
func->parent_shader = shader;
|
||||
func->type = type;
|
||||
func->index = shader->next_func++;
|
||||
|
||||
list_inithead(&func->body);
|
||||
|
||||
func->num_params = num_params;
|
||||
if (num_params) {
|
||||
func->params =
|
||||
rzalloc_array_size(func, sizeof(*func->params), num_params);
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates and sets up a PCO block.
|
||||
*
|
||||
* \param[in,out] func Parent function.
|
||||
* \return The PCO block, or NULL on failure.
|
||||
*/
|
||||
pco_block *pco_block_create(pco_func *func)
|
||||
{
|
||||
pco_block *block = rzalloc_size(func, sizeof(*block));
|
||||
|
||||
init_cf_node(&block->cf_node, PCO_CF_NODE_TYPE_BLOCK);
|
||||
block->parent_func = func;
|
||||
list_inithead(&block->instrs);
|
||||
block->index = func->next_block++;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates and sets up a PCO if construct.
|
||||
*
|
||||
* \param[in,out] func Parent function.
|
||||
* \return The PCO if construct, or NULL on failure.
|
||||
*/
|
||||
pco_if *pco_if_create(pco_func *func)
|
||||
{
|
||||
pco_if *pif = rzalloc_size(func, sizeof(*pif));
|
||||
|
||||
init_cf_node(&pif->cf_node, PCO_CF_NODE_TYPE_IF);
|
||||
pif->parent_func = func;
|
||||
list_inithead(&pif->then_body);
|
||||
list_inithead(&pif->else_body);
|
||||
pif->index = func->next_if++;
|
||||
|
||||
return pif;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates and sets up a PCO loop.
|
||||
*
|
||||
* \param[in,out] func Parent function.
|
||||
* \return The PCO loop, or NULL on failure.
|
||||
*/
|
||||
pco_loop *pco_loop_create(pco_func *func)
|
||||
{
|
||||
pco_loop *loop = rzalloc_size(func, sizeof(*loop));
|
||||
|
||||
init_cf_node(&loop->cf_node, PCO_CF_NODE_TYPE_LOOP);
|
||||
loop->parent_func = func;
|
||||
list_inithead(&loop->body);
|
||||
loop->index = func->next_loop++;
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates and sets up a PCO instruction.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2024 Imagination Technologies Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file pco_end.c
|
||||
*
|
||||
* \brief PCO shader ending pass.
|
||||
*/
|
||||
|
||||
#include "pco.h"
|
||||
#include "pco_builder.h"
|
||||
#include "pco_internal.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* \brief Processes end of shader instruction(s).
|
||||
*
|
||||
* \param[in,out] shader PCO shader.
|
||||
*/
|
||||
bool pco_end(pco_shader *shader)
|
||||
{
|
||||
/* TODO: Support for multiple end points. */
|
||||
pco_func *entry = pco_entrypoint(shader);
|
||||
pco_block *last_block = pco_last_block(entry);
|
||||
pco_instr *last_instr = pco_last_instr(last_block);
|
||||
|
||||
pco_builder b =
|
||||
pco_builder_create(entry, pco_cursor_after_block(last_block));
|
||||
|
||||
if (last_instr && pco_instr_has_end(last_instr)) {
|
||||
pco_instr_set_end(last_instr, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
pco_nop(&b, .end = true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -292,7 +292,7 @@ typedef struct _pco_func {
|
||||
|
||||
pco_shader *parent_shader; /** Shader containing the function. */
|
||||
|
||||
bool is_entrypoint;
|
||||
enum pco_func_type type; /** Function type. */
|
||||
unsigned index; /** Function index. */
|
||||
const char *name; /** Function name. */
|
||||
|
||||
@@ -372,6 +372,13 @@ struct pco_ref_mod_info {
|
||||
};
|
||||
extern const struct pco_ref_mod_info pco_ref_mod_info[_PCO_REF_MOD_COUNT];
|
||||
|
||||
pco_shader *pco_shader_create(pco_ctx *ctx, nir_shader *nir, void *mem_ctx);
|
||||
pco_func *pco_func_create(pco_shader *shader,
|
||||
enum pco_func_type type,
|
||||
unsigned num_params);
|
||||
pco_block *pco_block_create(pco_func *func);
|
||||
pco_if *pco_if_create(pco_func *func);
|
||||
pco_loop *pco_loop_create(pco_func *func);
|
||||
pco_instr *pco_instr_create(pco_func *func,
|
||||
enum pco_op op,
|
||||
unsigned num_dests,
|
||||
@@ -412,20 +419,46 @@ PCO_DEFINE_CAST(pco_cf_node_as_func,
|
||||
type,
|
||||
PCO_CF_NODE_TYPE_FUNC)
|
||||
|
||||
/**
|
||||
* \brief Returns the preamble function of a PCO shader.
|
||||
*
|
||||
* \param[in] shader The PCO shader.
|
||||
* \return The preamble function, or NULL if the shader has no preamble.
|
||||
*/
|
||||
static inline pco_func *pco_preamble(pco_shader *shader)
|
||||
{
|
||||
if (list_is_empty(&shader->funcs))
|
||||
return NULL;
|
||||
|
||||
pco_func *func = list_first_entry(&shader->funcs, pco_func, link);
|
||||
if (func->type == PCO_FUNC_TYPE_PREAMBLE)
|
||||
return func;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the entrypoint function of a PCO shader.
|
||||
*
|
||||
* \param[in] shader The PCO shader.
|
||||
* \return The entrypoint function, or NULL if the shader has no functions.
|
||||
* \return The entrypoint function, or NULL if the shader has no entrypoint.
|
||||
*/
|
||||
static inline pco_func *pco_entrypoint(pco_shader *shader)
|
||||
{
|
||||
if (list_is_empty(&shader->funcs))
|
||||
return NULL;
|
||||
|
||||
pco_func *func = list_first_entry(&shader->funcs, pco_func, link);
|
||||
assert(func->is_entrypoint);
|
||||
return func;
|
||||
/* Entrypoint will either be the first or second function in the shader,
|
||||
* depending on whether or not there is a preamble.
|
||||
*/
|
||||
pco_func *preamble = pco_preamble(shader);
|
||||
pco_func *func = !preamble ? list_first_entry(&shader->funcs, pco_func, link)
|
||||
: list_entry(preamble->link.next, pco_func, link);
|
||||
|
||||
if (func->type == PCO_FUNC_TYPE_ENTRYPOINT)
|
||||
return func;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Motions. */
|
||||
@@ -582,4 +615,7 @@ static inline pco_igrp *pco_prev_igrp(pco_igrp *igrp)
|
||||
|
||||
return list_entry(igrp->link.prev, pco_igrp, link);
|
||||
}
|
||||
|
||||
/* PCO IR passes. */
|
||||
bool pco_end(pco_shader *shader);
|
||||
#endif /* PCO_INTERNAL_H */
|
||||
|
||||
@@ -12,9 +12,29 @@
|
||||
|
||||
#include "pco.h"
|
||||
#include "pco_internal.h"
|
||||
#include "util/u_debug.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \brief Runs passes on a PCO shader.
|
||||
*
|
||||
@@ -23,5 +43,7 @@
|
||||
*/
|
||||
void pco_process_ir(pco_ctx *ctx, pco_shader *shader)
|
||||
{
|
||||
PCO_PASS(_, shader, pco_end);
|
||||
|
||||
puts("finishme: pco_process_ir");
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@ REF_TYPE = enum_type('ref_type', [
|
||||
'drc',
|
||||
])
|
||||
|
||||
FUNC_TYPE = enum_type('func_type', [
|
||||
'callable',
|
||||
'preamble',
|
||||
'entrypoint',
|
||||
'phase_change',
|
||||
])
|
||||
|
||||
# Ref mods.
|
||||
RM_ONEMINUS = ref_mod('oneminus', BaseType.bool)
|
||||
RM_CLAMP = ref_mod('clamp', BaseType.bool)
|
||||
|
||||
@@ -10,12 +10,174 @@
|
||||
* \brief NIR translation functions.
|
||||
*/
|
||||
|
||||
#include "compiler/glsl/list.h"
|
||||
#include "pco.h"
|
||||
#include "pco_builder.h"
|
||||
#include "pco_internal.h"
|
||||
#include "util/bitset.h"
|
||||
#include "util/list.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/ralloc.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/** Translation context. */
|
||||
typedef struct _trans_ctx {
|
||||
pco_ctx *pco_ctx; /** PCO compiler context. */
|
||||
pco_shader *shader; /** Current shader. */
|
||||
pco_func *func; /** Current function. */
|
||||
pco_builder b; /** Builder. */
|
||||
|
||||
BITSET_WORD *float_types; /** NIR SSA float vars. */
|
||||
BITSET_WORD *int_types; /** NIR SSA int vars. */
|
||||
} trans_ctx;
|
||||
|
||||
/* Forward declarations. */
|
||||
static pco_block *trans_cf_nodes(trans_ctx *tctx,
|
||||
pco_cf_node *parent_cf_node,
|
||||
struct list_head *cf_node_list,
|
||||
struct exec_list *nir_cf_node_list);
|
||||
|
||||
/**
|
||||
* \brief Translates a NIR block into PCO.
|
||||
*
|
||||
* \param[in] tctx Translation context.
|
||||
* \param[in] nblock The nir block.
|
||||
* \return The PCO block.
|
||||
*/
|
||||
static pco_block *trans_block(trans_ctx *tctx, nir_block *nblock)
|
||||
{
|
||||
pco_block *block = pco_block_create(tctx->func);
|
||||
tctx->b = pco_builder_create(tctx->func, pco_cursor_after_block(block));
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Translates a NIR if into PCO.
|
||||
*
|
||||
* \param[in] tctx Translation context.
|
||||
* \param[in] nif The nir if.
|
||||
* \return The PCO if.
|
||||
*/
|
||||
static pco_if *trans_if(trans_ctx *tctx, nir_if *nif)
|
||||
{
|
||||
pco_if *pif = pco_if_create(tctx->func);
|
||||
|
||||
unreachable("finishme: trans_if");
|
||||
|
||||
return pif;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Translates a NIR loop into PCO.
|
||||
*
|
||||
* \param[in] tctx Translation context.
|
||||
* \param[in] nloop The nir loop.
|
||||
* \return The PCO loop.
|
||||
*/
|
||||
static pco_loop *trans_loop(trans_ctx *tctx, nir_loop *nloop)
|
||||
{
|
||||
pco_loop *loop = pco_loop_create(tctx->func);
|
||||
|
||||
unreachable("finishme: trans_loop");
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Translates a NIR function into PCO.
|
||||
*
|
||||
* \param[in] tctx Translation context.
|
||||
* \param[in] impl The nir function impl.
|
||||
* \return The PCO function.
|
||||
*/
|
||||
static pco_func *trans_func(trans_ctx *tctx, nir_function_impl *impl)
|
||||
{
|
||||
nir_function *nfunc = impl->function;
|
||||
enum pco_func_type func_type = PCO_FUNC_TYPE_CALLABLE;
|
||||
|
||||
if (nfunc->is_preamble)
|
||||
func_type = PCO_FUNC_TYPE_PREAMBLE;
|
||||
else if (nfunc->is_entrypoint)
|
||||
func_type = PCO_FUNC_TYPE_ENTRYPOINT;
|
||||
|
||||
pco_func *func = pco_func_create(tctx->shader, func_type, nfunc->num_params);
|
||||
tctx->func = func;
|
||||
|
||||
func->name = ralloc_strdup(func, nfunc->name);
|
||||
func->next_ssa = impl->ssa_alloc;
|
||||
|
||||
/* TODO: Function parameter support. */
|
||||
assert(func->num_params == 0 && func->params == NULL);
|
||||
|
||||
/* Gather types. */
|
||||
tctx->float_types =
|
||||
rzalloc_array(NULL, BITSET_WORD, BITSET_WORDS(impl->ssa_alloc));
|
||||
tctx->int_types =
|
||||
rzalloc_array(NULL, BITSET_WORD, BITSET_WORDS(impl->ssa_alloc));
|
||||
nir_gather_types(impl, tctx->float_types, tctx->int_types);
|
||||
|
||||
trans_cf_nodes(tctx, &func->cf_node, &func->body, &impl->body);
|
||||
|
||||
ralloc_free(tctx->float_types);
|
||||
ralloc_free(tctx->int_types);
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Translates NIR control flow nodes into PCO.
|
||||
*
|
||||
* \param[in] tctx Translation context.
|
||||
* \param[in] parent_cf_node The parent cf node.
|
||||
* \param[in] cf_node_list The PCO cf node list.
|
||||
* \param[in,out] nir_cf_node_list The NIR cf node list.
|
||||
* \return The first block from the cf nodes.
|
||||
*/
|
||||
static pco_block *trans_cf_nodes(trans_ctx *tctx,
|
||||
pco_cf_node *parent_cf_node,
|
||||
struct list_head *cf_node_list,
|
||||
struct exec_list *nir_cf_node_list)
|
||||
{
|
||||
pco_block *start_block = NULL;
|
||||
|
||||
pco_cf_node *cf_node;
|
||||
foreach_list_typed (nir_cf_node, ncf_node, node, nir_cf_node_list) {
|
||||
switch (ncf_node->type) {
|
||||
case nir_cf_node_block: {
|
||||
pco_block *block = trans_block(tctx, nir_cf_node_as_block(ncf_node));
|
||||
cf_node = &block->cf_node;
|
||||
|
||||
if (!start_block)
|
||||
start_block = block;
|
||||
break;
|
||||
}
|
||||
|
||||
case nir_cf_node_if: {
|
||||
pco_if *pif = trans_if(tctx, nir_cf_node_as_if(ncf_node));
|
||||
cf_node = &pif->cf_node;
|
||||
break;
|
||||
}
|
||||
|
||||
case nir_cf_node_loop: {
|
||||
pco_loop *loop = trans_loop(tctx, nir_cf_node_as_loop(ncf_node));
|
||||
cf_node = &loop->cf_node;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
|
||||
cf_node->parent = parent_cf_node;
|
||||
list_addtail(&cf_node->link, cf_node_list);
|
||||
}
|
||||
|
||||
return start_block;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Translates a NIR shader into a PCO shader.
|
||||
*
|
||||
@@ -26,6 +188,15 @@
|
||||
*/
|
||||
pco_shader *pco_trans_nir(pco_ctx *ctx, nir_shader *nir, void *mem_ctx)
|
||||
{
|
||||
puts("finishme: pco_trans_nir");
|
||||
return ralloc_context(mem_ctx);
|
||||
pco_shader *shader = pco_shader_create(ctx, nir, mem_ctx);
|
||||
trans_ctx tctx = {
|
||||
.pco_ctx = ctx,
|
||||
.shader = shader,
|
||||
};
|
||||
|
||||
nir_foreach_function_with_impl (func, impl, nir) {
|
||||
trans_func(&tctx, impl);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user