mesa/st: Add an optional GLSL link fail msg to finalize_nir.

GLES2 drivers are allowed to reject some GLSL constructs, like dynamic
loop bounds (which neither i915g nor vc4 can fully support), but gallium
hasn't had any way to trigger a link failure.  Add a return msg to the
finalize_nir hook, which is called at the end of GLSL linking, and use
that.  This means that some other callers of finalize need to do something
with the msg, and we (for now) just throw it away.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12218>
This commit is contained in:
Emma Anholt 2021-08-03 10:20:18 -07:00 committed by Marge Bot
parent 1b4b9a9eff
commit 17332ceb0f
17 changed files with 69 additions and 37 deletions

View file

@ -414,12 +414,12 @@ dd_screen_memobj_destroy(struct pipe_screen *_screen,
* screen
*/
static void
static char *
dd_screen_finalize_nir(struct pipe_screen *_screen, void *nir)
{
struct pipe_screen *screen = dd_screen(_screen)->screen;
screen->finalize_nir(screen, nir);
return screen->finalize_nir(screen, nir);
}
static void

View file

@ -599,11 +599,11 @@ static const void *noop_get_compiler_options(struct pipe_screen *pscreen,
return screen->get_compiler_options(screen, ir, shader);
}
static void noop_finalize_nir(struct pipe_screen *pscreen, void *nir)
static char *noop_finalize_nir(struct pipe_screen *pscreen, void *nir)
{
struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
screen->finalize_nir(screen, nir);
return screen->finalize_nir(screen, nir);
}
static bool noop_check_resource_capability(struct pipe_screen *screen,

View file

@ -410,12 +410,12 @@ rbug_screen_fence_get_fd(struct pipe_screen *_screen,
return screen->fence_get_fd(screen, fence);
}
static void
static char *
rbug_screen_finalize_nir(struct pipe_screen *_screen, void *nir)
{
struct pipe_screen *screen = rbug_screen(_screen)->screen;
screen->finalize_nir(screen, nir);
return screen->finalize_nir(screen, nir);
}
bool

View file

@ -919,12 +919,12 @@ trace_screen_get_timestamp(struct pipe_screen *_screen)
return result;
}
static void
static char *
trace_screen_finalize_nir(struct pipe_screen *_screen, void *nir)
{
struct pipe_screen *screen = trace_screen(_screen)->screen;
screen->finalize_nir(screen, nir);
return screen->finalize_nir(screen, nir);
}
static void

View file

@ -2486,7 +2486,8 @@ ttn_finalize_nir(struct ttn_compile *c, struct pipe_screen *screen)
NIR_PASS_V(nir, nir_lower_samplers);
if (screen->finalize_nir) {
screen->finalize_nir(screen, nir);
char *msg = screen->finalize_nir(screen, nir);
free(msg);
} else {
ttn_optimize_nir(nir);
nir_shader_gather_info(nir, c->build.impl);

View file

@ -462,13 +462,15 @@ ir3_fixup_shader_state(struct pipe_context *pctx, struct ir3_shader_key *key)
}
}
static void
static char *
ir3_screen_finalize_nir(struct pipe_screen *pscreen, void *nir)
{
struct fd_screen *screen = fd_screen(pscreen);
ir3_nir_lower_io_to_temporaries(nir);
ir3_finalize_nir(screen->compiler, nir);
return NULL;
}
static void

View file

@ -211,7 +211,7 @@ i915_optimize_nir(struct nir_shader *s)
NULL);
}
static void
static char *
i915_finalize_nir(struct pipe_screen *pscreen, void *nir)
{
nir_shader *s = nir;
@ -237,6 +237,8 @@ i915_finalize_nir(struct pipe_screen *pscreen, void *nir)
nir_validate_shader(s, "after uniform var removal");
nir_sweep(s);
return NULL;
}
static int

View file

@ -601,12 +601,13 @@ static const struct nir_shader_compiler_options gallivm_nir_options = {
.lower_fisnormal = true,
};
static void
static char *
llvmpipe_finalize_nir(struct pipe_screen *screen,
void *nirptr)
{
struct nir_shader *nir = (struct nir_shader *)nirptr;
lp_build_opt_nir(nir);
return NULL;
}
static inline const void *

View file

@ -887,7 +887,7 @@ struct si_shader *si_generate_gs_copy_shader(struct si_screen *sscreen,
void si_nir_scan_shader(const struct nir_shader *nir, struct si_shader_info *info);
void si_nir_opts(struct si_screen *sscreen, struct nir_shader *nir, bool first);
void si_nir_late_opts(nir_shader *nir);
void si_finalize_nir(struct pipe_screen *screen, void *nirptr);
char *si_finalize_nir(struct pipe_screen *screen, void *nirptr);
/* si_state_shaders.c */
void gfx9_get_gs_info(struct si_shader_selector *es, struct si_shader_selector *gs,

View file

@ -903,7 +903,7 @@ static void si_lower_nir(struct si_screen *sscreen, struct nir_shader *nir)
NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL);
}
void si_finalize_nir(struct pipe_screen *screen, void *nirptr)
char *si_finalize_nir(struct pipe_screen *screen, void *nirptr)
{
struct si_screen *sscreen = (struct si_screen *)screen;
struct nir_shader *nir = (struct nir_shader *)nirptr;
@ -914,4 +914,6 @@ void si_finalize_nir(struct pipe_screen *screen, void *nirptr)
if (sscreen->options.inline_uniforms)
nir_find_inlinable_uniforms(nir);
return NULL;
}

View file

@ -1103,7 +1103,7 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
return ret;
}
void
char *
zink_shader_finalize(struct pipe_screen *pscreen, void *nirptr)
{
struct zink_screen *screen = zink_screen(pscreen);
@ -1123,6 +1123,8 @@ zink_shader_finalize(struct pipe_screen *pscreen, void *nirptr)
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
if (screen->driconf.inline_uniforms)
nir_find_inlinable_uniforms(nir);
return NULL;
}
void

View file

@ -105,7 +105,7 @@ struct zink_shader *
zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
const struct pipe_stream_output_info *so_info);
void
char *
zink_shader_finalize(struct pipe_screen *pscreen, void *nirptr);
void

View file

@ -520,8 +520,11 @@ struct pipe_screen {
*
* gallium frontends should call this before passing shaders to drivers,
* and ideally also before shader caching.
*
* The driver may return a non-NULL string to trigger GLSL link failure and
* logging of that message in the GLSL linker log.
*/
void (*finalize_nir)(struct pipe_screen *screen, void *nir);
char *(*finalize_nir)(struct pipe_screen *screen, void *nir);
/*Separated memory/resource allocations interfaces for Vulkan */

View file

@ -50,6 +50,7 @@
#include "compiler/glsl/gl_nir_linker.h"
#include "compiler/glsl/ir.h"
#include "compiler/glsl/ir_optimization.h"
#include "compiler/glsl/linker_util.h"
#include "compiler/glsl/string_to_uint_map.h"
static int
@ -468,7 +469,7 @@ filter_64_bit_instr(const nir_instr *const_instr, UNUSED const void *data)
/* Second third of converting glsl_to_nir. This creates uniforms, gathers
* info on varyings, etc after NIR link time opts have been applied.
*/
static void
static char *
st_glsl_to_nir_post_opts(struct st_context *st, struct gl_program *prog,
struct gl_shader_program *shader_program)
{
@ -572,8 +573,9 @@ st_glsl_to_nir_post_opts(struct st_context *st, struct gl_program *prog,
st_finalize_nir_before_variants(nir);
char *msg = NULL;
if (st->allow_st_finalize_nir_twice)
st_finalize_nir(st, prog, shader_program, nir, true, true);
msg = st_finalize_nir(st, prog, shader_program, nir, true, true);
if (st->ctx->_Shader->Flags & GLSL_DUMP) {
_mesa_log("\n");
@ -583,6 +585,8 @@ st_glsl_to_nir_post_opts(struct st_context *st, struct gl_program *prog,
nir_print_shader(nir, _mesa_get_log_file());
_mesa_log("\n\n");
}
return msg;
}
static void
@ -890,7 +894,11 @@ st_link_nir(struct gl_context *ctx,
struct gl_linked_shader *shader = linked_shader[i];
struct shader_info *info = &shader->Program->nir->info;
st_glsl_to_nir_post_opts(st, shader->Program, shader_program);
char *msg = st_glsl_to_nir_post_opts(st, shader->Program, shader_program);
if (msg) {
linker_error(shader_program, msg);
break;
}
if (prev_info &&
ctx->Const.ShaderCompilerOptions[shader->Stage].NirOptions->unify_interfaces) {
@ -1032,7 +1040,7 @@ st_nir_lower_uniforms(struct st_context *st, nir_shader *nir)
/* Last third of preparing nir from glsl, which happens after shader
* variant lowering.
*/
void
char *
st_finalize_nir(struct st_context *st, struct gl_program *prog,
struct gl_shader_program *shader_program,
nir_shader *nir, bool finalize_by_driver,
@ -1071,8 +1079,11 @@ st_finalize_nir(struct st_context *st, struct gl_program *prog,
if (!screen->get_param(screen, PIPE_CAP_NIR_IMAGES_AS_DEREF))
NIR_PASS_V(nir, gl_nir_lower_images, false);
char *msg = NULL;
if (finalize_by_driver && screen->finalize_nir)
screen->finalize_nir(screen, nir);
msg = screen->finalize_nir(screen, nir);
return msg;
}
} /* extern "C" */

View file

@ -41,10 +41,10 @@ void st_nir_lower_wpos_ytransform(struct nir_shader *nir,
struct gl_program *prog,
struct pipe_screen *pscreen);
void st_finalize_nir(struct st_context *st, struct gl_program *prog,
struct gl_shader_program *shader_program,
struct nir_shader *nir, bool finalize_by_driver,
bool is_before_variants);
char *st_finalize_nir(struct st_context *st, struct gl_program *prog,
struct gl_shader_program *shader_program,
struct nir_shader *nir, bool finalize_by_driver,
bool is_before_variants);
void st_nir_opts(struct nir_shader *nir);

View file

@ -68,10 +68,12 @@ st_nir_finish_builtin_shader(struct st_context *st,
if (!screen->get_param(screen, PIPE_CAP_NIR_IMAGES_AS_DEREF))
NIR_PASS_V(nir, gl_nir_lower_images, false);
if (screen->finalize_nir)
screen->finalize_nir(screen, nir);
else
if (screen->finalize_nir) {
char *msg = screen->finalize_nir(screen, nir);
free(msg);
} else {
st_nir_opts(nir);
}
struct pipe_shader_state state = {
.type = PIPE_SHADER_IR_NIR,

View file

@ -390,8 +390,10 @@ st_prog_to_nir_postprocess(struct st_context *st, nir_shader *nir,
st_nir_opts(nir);
st_finalize_nir_before_variants(nir);
if (st->allow_st_finalize_nir_twice)
st_finalize_nir(st, prog, NULL, nir, true, true);
if (st->allow_st_finalize_nir_twice) {
char *msg = st_finalize_nir(st, prog, NULL, nir, true, true);
free(msg);
}
nir_validate_shader(nir, "after st/glsl finalize_nir");
}
@ -828,8 +830,9 @@ st_create_common_variant(struct st_context *st,
}
if (finalize || !st->allow_st_finalize_nir_twice) {
st_finalize_nir(st, &stp->Base, stp->shader_program, state.ir.nir,
true, false);
char *msg = st_finalize_nir(st, &stp->Base, stp->shader_program, state.ir.nir,
true, false);
free(msg);
/* Clip lowering and edgeflags may have introduced new varyings, so
* update the inputs_read/outputs_written. However, with
@ -1491,8 +1494,9 @@ st_create_fp_variant(struct st_context *st,
}
if (finalize || !st->allow_st_finalize_nir_twice) {
st_finalize_nir(st, &stfp->Base, stfp->shader_program, state.ir.nir,
false, false);
char *msg = st_finalize_nir(st, &stfp->Base, stfp->shader_program, state.ir.nir,
false, false);
free(msg);
}
/* This pass needs to happen *after* nir_lower_sampler */
@ -1511,8 +1515,10 @@ st_create_fp_variant(struct st_context *st,
nir_shader_get_entrypoint(state.ir.nir));
struct pipe_screen *screen = st->screen;
if (screen->finalize_nir)
screen->finalize_nir(screen, state.ir.nir);
if (screen->finalize_nir) {
char *msg = screen->finalize_nir(screen, state.ir.nir);
free(msg);
}
}
variant->base.driver_shader = st_create_nir_shader(st, &state);