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:
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user