From 7c5b21c032309a726144bbb77352251b9fd0a235 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Wed, 22 May 2024 15:32:02 +1000 Subject: [PATCH] glsl: add support for converting global instructions to NIR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Part-of: --- src/compiler/glsl/glsl_to_nir.cpp | 39 +++++++++++++++---- src/compiler/glsl/glsl_to_nir.h | 3 +- .../glsl/tests/test_gl_lower_mediump.cpp | 6 ++- src/compiler/nir/nir.c | 1 + src/compiler/nir/nir.h | 5 +++ src/compiler/nir/nir_clone.c | 1 + src/compiler/nir/nir_serialize.c | 3 ++ .../drivers/freedreno/ir3/ir3_cmdline.c | 2 +- src/mesa/state_tracker/st_glsl_to_nir.cpp | 3 +- 9 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index 0b5b65f16f9..f1d6ee85105 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -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); diff --git a/src/compiler/glsl/glsl_to_nir.h b/src/compiler/glsl/glsl_to_nir.h index 50f2ae79082..08165f3abb8 100644 --- a/src/compiler/glsl/glsl_to_nir.h +++ b/src/compiler/glsl/glsl_to_nir.h @@ -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); diff --git a/src/compiler/glsl/tests/test_gl_lower_mediump.cpp b/src/compiler/glsl/tests/test_gl_lower_mediump.cpp index 5ad2387ac53..1ec2056404f 100644 --- a/src/compiler/glsl/tests/test_gl_lower_mediump.cpp +++ b/src/compiler/glsl/tests/test_gl_lower_mediump.cpp @@ -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); diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 96309cf9a4b..a65c9b1ebab 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -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; diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 2ef2b7dce26..9306104f22e 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -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 }; diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c index c41318fab56..b684fe9e5a2 100644 --- a/src/compiler/nir/nir_clone.c +++ b/src/compiler/nir/nir_clone.c @@ -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) { diff --git a/src/compiler/nir/nir_serialize.c b/src/compiler/nir/nir_serialize.c index 943c51944c0..2bb6a9ad7ac 100644 --- a/src/compiler/nir/nir_serialize.c +++ b/src/compiler/nir/nir_serialize.c @@ -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 diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c b/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c index ca2abd8960e..93fb1db713f 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c @@ -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 = diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp index 19944a2be48..91d602b5ac4 100644 --- a/src/mesa/state_tracker/st_glsl_to_nir.cpp +++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp @@ -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);