mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 02:58:05 +02:00
mesa: capture shaders to disk before invoking the linker
If there is an infinite loop in the GLSL linker, we want to write shaders to disk before that. Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32175>
This commit is contained in:
parent
3179c65a5a
commit
237ed6fd08
1 changed files with 56 additions and 47 deletions
|
|
@ -1276,6 +1276,60 @@ update_programs_in_pipeline(void *data, void *userData)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
capture_shader_program(struct gl_context *ctx,
|
||||
struct gl_shader_program *shProg)
|
||||
{
|
||||
#ifndef CUSTOM_SHADER_REPLACEMENT
|
||||
/* Capture .shader_test files. */
|
||||
const char *capture_path = _mesa_get_shader_capture_path();
|
||||
|
||||
if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) {
|
||||
/* Find an unused filename. */
|
||||
FILE *file = NULL;
|
||||
char *filename = NULL;
|
||||
|
||||
for (unsigned i = 0;; i++) {
|
||||
if (i) {
|
||||
filename = ralloc_asprintf(NULL, "%s/%u-%u.shader_test",
|
||||
capture_path, shProg->Name, i);
|
||||
} else {
|
||||
filename = ralloc_asprintf(NULL, "%s/%u.shader_test",
|
||||
capture_path, shProg->Name);
|
||||
}
|
||||
file = os_file_create_unique(filename, 0644);
|
||||
if (file)
|
||||
break;
|
||||
/* If we are failing for another reason than "this filename already
|
||||
* exists", we are likely to fail again with another filename, so
|
||||
* let's just give up */
|
||||
if (errno != EEXIST)
|
||||
break;
|
||||
ralloc_free(filename);
|
||||
}
|
||||
|
||||
if (file) {
|
||||
fprintf(file, "[require]\nGLSL%s >= %u.%02u\n",
|
||||
shProg->IsES ? " ES" : "", shProg->GLSL_Version / 100,
|
||||
shProg->GLSL_Version % 100);
|
||||
if (shProg->SeparateShader)
|
||||
fprintf(file, "GL_ARB_separate_shader_objects\nSSO ENABLED\n");
|
||||
fprintf(file, "\n");
|
||||
|
||||
for (unsigned i = 0; i < shProg->NumShaders; i++) {
|
||||
fprintf(file, "[%s shader]\n%s\n",
|
||||
_mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
|
||||
shProg->Shaders[i]->Source);
|
||||
}
|
||||
fclose(file);
|
||||
} else {
|
||||
_mesa_warning(ctx, "Failed to open %s", filename);
|
||||
}
|
||||
|
||||
ralloc_free(filename);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a program's shaders.
|
||||
|
|
@ -1302,6 +1356,8 @@ link_program(struct gl_context *ctx, struct gl_shader_program *shProg,
|
|||
}
|
||||
}
|
||||
|
||||
capture_shader_program(ctx, shProg);
|
||||
|
||||
unsigned programs_in_use = 0;
|
||||
if (ctx->_Shader)
|
||||
for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
|
||||
|
|
@ -1345,53 +1401,6 @@ link_program(struct gl_context *ctx, struct gl_shader_program *shProg,
|
|||
¶ms);
|
||||
}
|
||||
|
||||
#ifndef CUSTOM_SHADER_REPLACEMENT
|
||||
/* Capture .shader_test files. */
|
||||
const char *capture_path = _mesa_get_shader_capture_path();
|
||||
if (shProg->Name != 0 && shProg->Name != ~0 && capture_path != NULL) {
|
||||
/* Find an unused filename. */
|
||||
FILE *file = NULL;
|
||||
char *filename = NULL;
|
||||
for (unsigned i = 0;; i++) {
|
||||
if (i) {
|
||||
filename = ralloc_asprintf(NULL, "%s/%u-%u.shader_test",
|
||||
capture_path, shProg->Name, i);
|
||||
} else {
|
||||
filename = ralloc_asprintf(NULL, "%s/%u.shader_test",
|
||||
capture_path, shProg->Name);
|
||||
}
|
||||
file = os_file_create_unique(filename, 0644);
|
||||
if (file)
|
||||
break;
|
||||
/* If we are failing for another reason than "this filename already
|
||||
* exists", we are likely to fail again with another filename, so
|
||||
* let's just give up */
|
||||
if (errno != EEXIST)
|
||||
break;
|
||||
ralloc_free(filename);
|
||||
}
|
||||
if (file) {
|
||||
fprintf(file, "[require]\nGLSL%s >= %u.%02u\n",
|
||||
shProg->IsES ? " ES" : "", shProg->GLSL_Version / 100,
|
||||
shProg->GLSL_Version % 100);
|
||||
if (shProg->SeparateShader)
|
||||
fprintf(file, "GL_ARB_separate_shader_objects\nSSO ENABLED\n");
|
||||
fprintf(file, "\n");
|
||||
|
||||
for (unsigned i = 0; i < shProg->NumShaders; i++) {
|
||||
fprintf(file, "[%s shader]\n%s\n",
|
||||
_mesa_shader_stage_to_string(shProg->Shaders[i]->Stage),
|
||||
shProg->Shaders[i]->Source);
|
||||
}
|
||||
fclose(file);
|
||||
} else {
|
||||
_mesa_warning(ctx, "Failed to open %s", filename);
|
||||
}
|
||||
|
||||
ralloc_free(filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (shProg->data->LinkStatus == LINKING_FAILURE &&
|
||||
(ctx->_Shader->Flags & GLSL_REPORT_ERRORS)) {
|
||||
_mesa_debug(ctx, "Error linking program %u:\n%s\n",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue