[Mesa-dev] [PATCH 4/9] spirv: Rework logging
Jason Ekstrand
jason at jlekstrand.net
Thu Aug 17 17:22:18 UTC 2017
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
More information about the mesa-dev
mailing list