i915: Do a test compile at glLinkShader() time.

This lets us throw errors back to the app for shaders that are too
complex.  The X server would really like to have this instead of guessing
based on renderer strings when shaders might be too complicated.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25533>
This commit is contained in:
Emma Anholt
2023-10-03 12:53:24 -07:00
committed by Marge Bot
parent 2432f14d00
commit 4f78c27330
4 changed files with 53 additions and 10 deletions

View File

@@ -281,6 +281,9 @@ struct i915_token_list {
unsigned NumTokens;
};
char *i915_test_fragment_shader_compile(struct pipe_screen *screen,
struct nir_shader *s);
extern struct i915_token_list *i915_optimize(const struct tgsi_token *tokens);
extern void i915_optimize_free(struct i915_token_list *tokens);

View File

@@ -1039,12 +1039,15 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p)
memcpy(&ifs->program[decl_size], p->program,
program_size * sizeof(uint32_t));
util_debug_message(
&i915->debug, SHADER_INFO,
"%s shader: %d inst, %d tex, %d tex_indirect, %d temps, %d const",
_mesa_shader_stage_to_abbrev(MESA_SHADER_FRAGMENT), (int)program_size,
p->nr_tex_insn, p->nr_tex_indirect,
p->shader->info.file_max[TGSI_FILE_TEMPORARY] + 1, ifs->num_constants);
if (i915) {
util_debug_message(
&i915->debug, SHADER_INFO,
"%s shader: %d inst, %d tex, %d tex_indirect, %d temps, %d const",
_mesa_shader_stage_to_abbrev(MESA_SHADER_FRAGMENT),
(int)program_size, p->nr_tex_insn, p->nr_tex_indirect,
p->shader->info.file_max[TGSI_FILE_TEMPORARY] + 1,
ifs->num_constants);
}
}
if (strlen(p->error) != 0)

View File

@@ -27,6 +27,7 @@
#include "compiler/nir/nir.h"
#include "draw/draw_context.h"
#include "nir/nir_to_tgsi.h"
#include "util/format/u_format.h"
#include "util/format/u_format_s3tc.h"
#include "util/os_misc.h"
@@ -37,6 +38,7 @@
#include "i915_context.h"
#include "i915_debug.h"
#include "i915_fpc.h"
#include "i915_public.h"
#include "i915_reg.h"
#include "i915_resource.h"
@@ -277,7 +279,10 @@ i915_finalize_nir(struct pipe_screen *pscreen, void *nir)
if (msg)
return strdup(msg);
return NULL;
if (s->info.stage == MESA_SHADER_FRAGMENT)
return i915_test_fragment_shader_compile(pscreen, s);
else
return NULL;
}
static int

View File

@@ -534,6 +534,10 @@ i915_set_polygon_stipple(struct pipe_context *pipe,
{
}
static const struct nir_to_tgsi_options ntt_options = {
.lower_fabs = true,
};
static void *
i915_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
@@ -549,9 +553,6 @@ i915_create_fs_state(struct pipe_context *pipe,
nir_shader *s = templ->ir.nir;
ifs->internal = s->info.internal;
static const struct nir_to_tgsi_options ntt_options = {
.lower_fabs = true,
};
ifs->state.tokens = nir_to_tgsi_options(s, pipe->screen, &ntt_options);
} else {
assert(templ->type == PIPE_SHADER_IR_TGSI);
@@ -606,6 +607,37 @@ i915_delete_fs_state(struct pipe_context *pipe, void *shader)
FREE(ifs);
}
/* Does a test compile at link time to see if we'll be able to run this shader
* at runtime. Return a string to the GLSL compiler for anything we should
* report as link failure.
*/
char *
i915_test_fragment_shader_compile(struct pipe_screen *screen, nir_shader *s)
{
struct i915_fragment_shader *ifs = CALLOC_STRUCT(i915_fragment_shader);
if (!ifs)
return NULL;
/* NTT takes ownership of the shader, give it a clone. */
s = nir_shader_clone(NULL, s);
ifs->internal = s->info.internal;
ifs->state.tokens = nir_to_tgsi_options(s, screen, &ntt_options);
ifs->state.type = PIPE_SHADER_IR_TGSI;
tgsi_scan_shader(ifs->state.tokens, &ifs->info);
i915_translate_fragment_program(NULL, ifs);
char *msg = NULL;
if (ifs->error)
msg = strdup(ifs->error);
i915_delete_fs_state(NULL, ifs);
return msg;
}
static void *
i915_create_vs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)