This commit reworks the way that logging works in SPIR-V to provide richer and more detailed logging infrastructure. This commit contains several improvements over the old mechanism:
1) Log messages are now more detailed. They contain the SPIR-V byte offset as well as source language information from OpSource and OpLine. 2) There is now a logging callback mechanism so that errors can get propagated to the client through debug callbak extensions. --- src/amd/vulkan/radv_pipeline.c | 2 +- src/compiler/spirv/nir_spirv.h | 17 ++++++- src/compiler/spirv/spirv2nir.c | 3 +- src/compiler/spirv/spirv_to_nir.c | 100 ++++++++++++++++++++++++++++++++------ src/compiler/spirv/vtn_private.h | 22 +++++++-- src/intel/vulkan/anv_pipeline.c | 2 +- 6 files changed, 124 insertions(+), 22 deletions(-) diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index bd5eeb7..2bf0e99 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -234,7 +234,7 @@ radv_shader_compile_to_nir(struct radv_device *device, }; entry_point = spirv_to_nir(spirv, module->size / 4, spec_entries, num_spec_entries, - stage, entrypoint_name, &supported_ext, &nir_options); + stage, entrypoint_name, &supported_ext, &nir_options, NULL); nir = entry_point->shader; assert(nir->stage == stage); nir_validate_shader(nir); diff --git a/src/compiler/spirv/nir_spirv.h b/src/compiler/spirv/nir_spirv.h index 83577fb..9c92eb1 100644 --- a/src/compiler/spirv/nir_spirv.h +++ b/src/compiler/spirv/nir_spirv.h @@ -54,12 +54,27 @@ struct nir_spirv_supported_extensions { bool variable_pointers; }; +enum nir_spirv_debug_level { + NIR_SPIRV_DEBUG_LEVEL_INFO, + NIR_SPIRV_DEBUG_LEVEL_WARNING, + NIR_SPIRV_DEBUG_LEVEL_ERROR, +}; + +struct nir_spirv_debug_callback { + void (*func)(void *private_data, + enum nir_spirv_debug_level level, + size_t spirv_offset, + const char *message); + void *private_data; +}; + nir_function *spirv_to_nir(const uint32_t *words, size_t word_count, struct nir_spirv_specialization *specializations, unsigned num_specializations, gl_shader_stage stage, const char *entry_point_name, const struct nir_spirv_supported_extensions *ext, - const nir_shader_compiler_options *options); + const nir_shader_compiler_options *options, + struct nir_spirv_debug_callback *debug_cb); #ifdef __cplusplus } diff --git a/src/compiler/spirv/spirv2nir.c b/src/compiler/spirv/spirv2nir.c index 0ae14fb..2b1c0e8 100644 --- a/src/compiler/spirv/spirv2nir.c +++ b/src/compiler/spirv/spirv2nir.c @@ -73,7 +73,8 @@ int main(int argc, char **argv) } nir_function *func = spirv_to_nir(map, word_count, NULL, 0, - MESA_SHADER_FRAGMENT, "main", NULL, NULL); + MESA_SHADER_FRAGMENT, "main", + NULL, NULL, NULL); nir_print_shader(func->shader, stderr); return 0; diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index a3e143a..6174ec7 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -31,29 +31,87 @@ #include "nir/nir_constant_expressions.h" #include "spirv_info.h" -struct spec_constant_value { - bool is_double; - union { - uint32_t data32; - uint64_t data64; - }; -}; +void +vtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level, + size_t spirv_offset, const char *message) +{ + if (b->debug && b->debug->func) + b->debug->func(b->debug->private_data, level, spirv_offset, message); + +#ifndef NDEBUG + if (level >= NIR_SPIRV_DEBUG_LEVEL_WARNING) + fprintf(stderr, "%s\n", message); +#endif +} void -_vtn_warn(const char *file, int line, const char *msg, ...) +vtn_logf(struct vtn_builder *b, enum nir_spirv_debug_level level, + size_t spirv_offset, const char *fmt, ...) { - char *formatted; va_list args; + char *msg; - va_start(args, msg); - formatted = ralloc_vasprintf(NULL, msg, args); + va_start(args, fmt); + msg = ralloc_vasprintf(NULL, fmt, args); va_end(args); - fprintf(stderr, "%s:%d WARNING: %s\n", file, line, formatted); + vtn_log(b, level, spirv_offset, msg); + + ralloc_free(msg); +} + +static void +vtn_log_err(struct vtn_builder *b, + enum nir_spirv_debug_level level, const char *prefix, + const char *file, unsigned line, + const char *fmt, va_list args) +{ + char *msg; + + msg = ralloc_strdup(NULL, prefix); + +#ifndef NDEBUG + ralloc_asprintf_append(&msg, " In file %s:%u\n", file, line); +#endif + + ralloc_asprintf_append(&msg, " "); + + ralloc_vasprintf_append(&msg, fmt, args); + + ralloc_asprintf_append(&msg, "\n %zu bytes into the SPIR-V binary", + b->spirv_offset); + + if (b->file) { + ralloc_asprintf_append(&msg, + "\n in SPIR-V source file %s, line %d, col %d", + b->file, b->line, b->col); + } + + vtn_log(b, level, b->spirv_offset, msg); - ralloc_free(formatted); + ralloc_free(msg); } +void +_vtn_warn(struct vtn_builder *b, const char *file, unsigned line, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_WARNING, "SPIR-V WARNING:\n", + file, line, fmt, args); + va_end(args); +} + +struct spec_constant_value { + bool is_double; + union { + uint32_t data32; + uint64_t data64; + }; +}; + static struct vtn_ssa_value * vtn_undef_ssa_value(struct vtn_builder *b, const struct glsl_type *type) { @@ -224,6 +282,8 @@ vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start, unsigned count = w[0] >> SpvWordCountShift; assert(count >= 1 && w + count <= end); + b->spirv_offset = (uint8_t *)w - (uint8_t *)b->spirv; + switch (opcode) { case SpvOpNop: break; /* Do nothing */ @@ -248,6 +308,12 @@ vtn_foreach_instruction(struct vtn_builder *b, const uint32_t *start, w += count; } + + b->spirv_offset = 0; + b->file = NULL; + b->line = -1; + b->col = -1; + assert(w == end); return w; } @@ -3319,10 +3385,16 @@ spirv_to_nir(const uint32_t *words, size_t word_count, struct nir_spirv_specialization *spec, unsigned num_spec, gl_shader_stage stage, const char *entry_point_name, const struct nir_spirv_supported_extensions *ext, - const nir_shader_compiler_options *options) + const nir_shader_compiler_options *options, + struct nir_spirv_debug_callback *debug_cb) { /* Initialize the stn_builder object */ struct vtn_builder *b = rzalloc(NULL, struct vtn_builder); + b->debug = debug_cb; + b->spirv = words; + b->file = NULL; + b->line = -1; + b->col = -1; exec_list_make_empty(&b->functions); b->entry_point_stage = stage; b->entry_point_name = entry_point_name; diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index 8458462..3eb601d 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -37,6 +37,18 @@ struct vtn_builder; struct vtn_decoration; +void vtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level, + size_t spirv_offset, const char *message); + +void vtn_logf(struct vtn_builder *b, enum nir_spirv_debug_level level, + size_t spirv_offset, const char *fmt, ...) PRINTFLIKE(4, 5); + +#define vtn_info(...) vtn_logf(b, NIR_SPIRV_DEBUG_LEVEL_INFO, 0, __VA_ARGS__) + +void _vtn_warn(struct vtn_builder *b, const char *file, unsigned line, + const char *fmt, ...) PRINTFLIKE(4, 5); +#define vtn_warn(...) _vtn_warn(b, __FILE__, __LINE__, __VA_ARGS__) + enum vtn_value_type { vtn_value_type_invalid = 0, vtn_value_type_undef, @@ -462,17 +474,22 @@ struct vtn_decoration { struct vtn_builder { nir_builder nb; + const uint32_t *spirv; + nir_shader *shader; nir_function_impl *impl; const struct nir_spirv_supported_extensions *ext; struct vtn_block *block; - /* Current file, line, and column. Useful for debugging. Set + /* Current offset, file, line, and column. Useful for debugging. Set * automatically by vtn_foreach_instruction. */ + size_t spirv_offset; char *file; int line, col; + struct nir_spirv_debug_callback *debug; + /* * In SPIR-V, constants are global, whereas in NIR, the load_const * instruction we use is per-function. So while we parse each function, we @@ -557,9 +574,6 @@ vtn_value(struct vtn_builder *b, uint32_t value_id, return val; } -void _vtn_warn(const char *file, int line, const char *msg, ...); -#define vtn_warn(...) _vtn_warn(__FILE__, __LINE__, __VA_ARGS__) - struct vtn_ssa_value *vtn_ssa_value(struct vtn_builder *b, uint32_t value_id); struct vtn_ssa_value *vtn_create_ssa_value(struct vtn_builder *b, diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 6ae682f..7c19e6c 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -135,7 +135,7 @@ anv_shader_compile_to_nir(struct anv_pipeline *pipeline, nir_function *entry_point = spirv_to_nir(spirv, module->size / 4, spec_entries, num_spec_entries, - stage, entrypoint_name, &supported_ext, nir_options); + stage, entrypoint_name, &supported_ext, nir_options, NULL); nir_shader *nir = entry_point->shader; assert(nir->stage == stage); nir_validate_shader(nir); -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev