glsl: add support for converting global instructions to NIR

NIR doesn't really support global instructions such as global val
initilisation. So here we add functionality to glsl_to_nir() to
put these instructions into a temporary function that will be
later inlined into main.

We give the function a name starting with gl_mesa_tmp_ as functions
starting with gl_ are reserved and will not have any clashes with
user functions, we finish the name with the blake3 of the shader
source to avoid conflicts with multiple shaders attached to a single
stage.

Acked-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31137>
This commit is contained in:
Timothy Arceri 2024-05-22 15:32:02 +10:00 committed by Marge Bot
parent 1fc9d5223e
commit 7c5b21c032
9 changed files with 51 additions and 12 deletions

View file

@ -55,7 +55,8 @@ namespace {
class nir_visitor : public ir_visitor
{
public:
nir_visitor(const struct gl_constants *consts, nir_shader *shader);
nir_visitor(const struct gl_constants *consts, nir_shader *shader,
const uint8_t *src_blake3);
nir_visitor(const nir_visitor &) = delete;
~nir_visitor();
nir_visitor & operator=(const nir_visitor &) = delete;
@ -100,6 +101,7 @@ private:
nir_shader *shader;
nir_function_impl *impl;
nir_function_impl *global_impl;
nir_builder b;
nir_def *result; /* result of the expression tree last visited */
@ -153,13 +155,14 @@ private:
nir_shader *
glsl_to_nir(const struct gl_constants *consts,
struct exec_list **ir, shader_info *si, gl_shader_stage stage,
const nir_shader_compiler_options *options)
const nir_shader_compiler_options *options,
const uint8_t *src_blake3)
{
MESA_TRACE_FUNC();
nir_shader *shader = nir_shader_create(NULL, stage, options, si);
nir_visitor v1(consts, shader);
nir_visitor v1(consts, shader, src_blake3);
nir_function_visitor v2(&v1);
v2.run(*ir);
visit_exec_list(*ir, &v1);
@ -177,7 +180,8 @@ glsl_to_nir(const struct gl_constants *consts,
return shader;
}
nir_visitor::nir_visitor(const struct gl_constants *consts, nir_shader *shader)
nir_visitor::nir_visitor(const struct gl_constants *consts, nir_shader *shader,
const uint8_t *src_blake3)
{
this->consts = consts;
this->supports_std430 = consts->UseSTD430AsDefaultPacking;
@ -190,7 +194,26 @@ nir_visitor::nir_visitor(const struct gl_constants *consts, nir_shader *shader)
this->impl = NULL;
this->deref = NULL;
this->sig = NULL;
this->global_impl = NULL;
memset(&this->b, 0, sizeof(this->b));
if (src_blake3) {
char blake_as_str[BLAKE3_OUT_LEN * 2 + 1];;
_mesa_blake3_format(blake_as_str, src_blake3);
/* Create unique function name of function to temporarily hold global
* instructions.
*/
char gloabl_func_name[45];
snprintf(gloabl_func_name, 45, "%s_%s", "gl_mesa_tmp", blake_as_str);
nir_function *func = nir_function_create(shader, gloabl_func_name);
func->is_tmp_globals_wrapper = true;
this->global_impl = nir_function_impl_create(func);
this->impl = this->global_impl;
b = nir_builder_at(nir_after_impl(this->impl));
}
}
nir_visitor::~nir_visitor()
@ -690,9 +713,11 @@ nir_visitor::visit(ir_function_signature *ir)
visit_exec_list(&ir->body, this);
this->impl = global_impl;
if (this->impl)
b = nir_builder_at(nir_after_impl(this->impl));
this->is_global = true;
} else {
func->impl = NULL;
}
}
@ -2783,7 +2808,7 @@ glsl_float64_funcs_to_nir(struct gl_context *ctx,
nir_shader *nir = nir_shader_create(NULL, MESA_SHADER_VERTEX, options, NULL);
nir_visitor v1(&ctx->Const, nir);
nir_visitor v1(&ctx->Const, nir, NULL);
nir_function_visitor v2(&v1);
v2.run(sh->ir);
visit_exec_list(sh->ir, &v1);

View file

@ -41,7 +41,8 @@ struct gl_shader_program;
nir_shader *glsl_to_nir(const struct gl_constants *consts,
struct exec_list **ir, shader_info *si,
gl_shader_stage stage,
const nir_shader_compiler_options *options);
const nir_shader_compiler_options *options,
const uint8_t *src_blake3);
nir_shader *glsl_float64_funcs_to_nir(struct gl_context *ctx,
const nir_shader_compiler_options *options);

View file

@ -214,11 +214,13 @@ namespace
struct gl_linked_shader *sh = whole_program->_LinkedShaders[MESA_SHADER_VERTEX];
sh->Program->nir = glsl_to_nir(&ctx->Const, &sh->ir, &sh->Program->info,
MESA_SHADER_VERTEX, &compiler_options);
MESA_SHADER_VERTEX, &compiler_options,
NULL);
sh = whole_program->_LinkedShaders[MESA_SHADER_FRAGMENT];
sh->Program->nir = glsl_to_nir(&ctx->Const, &sh->ir, &sh->Program->info,
MESA_SHADER_FRAGMENT, &compiler_options);
MESA_SHADER_FRAGMENT, &compiler_options,
NULL);
nir = sh->Program->nir;
gl_nir_link_glsl(ctx, whole_program);

View file

@ -503,6 +503,7 @@ nir_function_create(nir_shader *shader, const char *name)
func->dont_inline = false;
func->should_inline = false;
func->is_subroutine = false;
func->is_tmp_globals_wrapper = false;
func->subroutine_index = 0;
func->num_subroutine_types = 0;
func->subroutine_types = NULL;

View file

@ -3646,6 +3646,11 @@ typedef struct nir_function {
*/
bool is_subroutine;
/* Temporary function created to wrap global instructions before they can
* be inlined into the main function.
*/
bool is_tmp_globals_wrapper;
/**
* Is this function associated to a subroutine type
* e.g. subroutine (type1, type2) function_name { function_body };

View file

@ -696,6 +696,7 @@ nir_function_clone(nir_shader *ns, const nir_function *fxn)
nfxn->should_inline = fxn->should_inline;
nfxn->dont_inline = fxn->dont_inline;
nfxn->is_subroutine = fxn->is_subroutine;
nfxn->is_tmp_globals_wrapper = fxn->is_tmp_globals_wrapper;
nfxn->num_subroutine_types = fxn->num_subroutine_types;
nfxn->subroutine_index = fxn->subroutine_index;
if (fxn->num_subroutine_types) {

View file

@ -1963,6 +1963,8 @@ write_function(write_ctx *ctx, const nir_function *fxn)
flags |= 0x20;
if (fxn->is_subroutine)
flags |= 0x40;
if (fxn->is_tmp_globals_wrapper)
flags |= 0x80;
blob_write_uint32(ctx->blob, flags);
if (fxn->name)
blob_write_string(ctx->blob, fxn->name);
@ -2023,6 +2025,7 @@ read_function(read_ctx *ctx)
fxn->should_inline = flags & 0x10;
fxn->dont_inline = flags & 0x20;
fxn->is_subroutine = flags & 0x40;
fxn->is_tmp_globals_wrapper = flags & 0x80;
}
static void

View file

@ -106,7 +106,7 @@ load_glsl(unsigned num_files, char *const *files, gl_shader_stage stage)
nir_shader *nir = glsl_to_nir(&local_ctx.Const,
&prog->_LinkedShaders[stage]->ir,
&prog->_LinkedShaders[stage]->Program->info,
stage, nir_options);
stage, nir_options, NULL);
if (nir->info.stage == MESA_SHADER_FRAGMENT) {
nir->info.fs.pixel_center_integer =

View file

@ -544,7 +544,8 @@ st_link_glsl_to_nir(struct gl_context *ctx,
}
prog->nir = glsl_to_nir(&st->ctx->Const, &shader->ir,
&shader->Program->info, shader->Stage, options);
&shader->Program->info, shader->Stage,
options, NULL);
prog->nir->info.name =
ralloc_asprintf(shader, "GLSL%d", shader_program->Name);