spirv: Add MESA_SPIRV_DEBUG=values to dump all values

Dumps the value associated with each SPIR-V ID after parsing the module.
This will show the intermediate vtn_* values that spirv_to_nir uses.
Only a subset of detailed information is printed at the moment (focus on
pointers and pointer types), but it is easy to add for other value types
later.

Example output when running crucible with the debug option enabled.

```
    crucible: start  : func.compute.num-workgroups.basic.q0
    === SPIR-V values
           1 = extension
           2 = type void glsl_type=void
           3 = type function
           4 = function
           5 = block
           6 = type scalar glsl_type=uint
           7 = type vector glsl_type=uvec3
           8 = type array glsl_type=uvec3[]
           9 = type struct glsl_type=Storage
          10 = type pointer deref=9 SpvStorageClassUniform glsl_type=uvec4
          11 = pointer ptr_type=10 (pointed-)type=9
          12 = type scalar glsl_type=int
          13 = constant type=12
          14 = type pointer deref=7 SpvStorageClassInput glsl_type=uint
          15 = pointer ptr_type=14 (pointed-)type=7
          16 = constant type=6
          17 = type pointer deref=6 SpvStorageClassInput glsl_type=uint
          18 = pointer ptr_type=17 (pointed-)type=6
               NIR: 32    %2 = deref_array &(*%0)[0] (system uint)  // &gl_LocalInvocationID[0]
          19 = ssa glsl_type=uint
          20 = pointer ptr_type=14 (pointed-)type=7
          21 = ssa glsl_type=uvec3
          22 = type pointer deref=7 SpvStorageClassUniform glsl_type=uint
          23 = pointer ptr_type=22 (pointed-)type=7
               NIR: 32x4  %12 = deref_array &(*%11)[%4] (ssbo uvec3)  // &((Storage *)%9)->uv3a[%4]
          24 = constant type=6
          25 = constant type=6
          26 = constant type=7
    ===
    crucible: pass   : func.compute.num-workgroups.basic.q0
```

When the environment variable is set, this dump will also be printed
during vtn_fail and its helpers.

Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29295>
This commit is contained in:
Caio Oliveira 2024-05-20 15:18:24 -07:00 committed by Marge Bot
parent 0effbc625c
commit e3099fc839
2 changed files with 119 additions and 0 deletions

View File

@ -202,6 +202,8 @@ uint32_t mesa_spirv_debug = 0;
static const struct debug_named_value mesa_spirv_debug_control[] = {
{ "structured", MESA_SPIRV_DEBUG_STRUCTURED,
"Print information of the SPIR-V structured control flow parsing" },
{ "values", MESA_SPIRV_DEBUG_VALUES,
"Print information of the SPIR-V values" },
DEBUG_NAMED_VALUE_END,
};
@ -352,6 +354,9 @@ _vtn_fail(struct vtn_builder *b, const char *file, unsigned line,
{
va_list args;
if (MESA_SPIRV_DEBUG(VALUES))
vtn_dump_values(b, stderr);
va_start(args, fmt);
vtn_log_err(b, NIR_SPIRV_DEBUG_LEVEL_ERROR, "SPIR-V parsing FAILED:\n",
file, line, fmt, args);
@ -392,6 +397,33 @@ vtn_value_type_to_string(enum vtn_value_type t)
return "UNKNOWN";
}
static const char *
vtn_base_type_to_string(enum vtn_base_type t)
{
#define CASE(typ) case vtn_base_type_##typ: return #typ
switch (t) {
CASE(void);
CASE(scalar);
CASE(vector);
CASE(matrix);
CASE(array);
CASE(struct);
CASE(pointer);
CASE(image);
CASE(sampler);
CASE(sampled_image);
CASE(accel_struct);
CASE(ray_query);
CASE(function);
CASE(event);
CASE(cooperative_matrix);
}
#undef CASE
unreachable("unknown base type");
return "UNKNOWN";
}
void
_vtn_fail_value_type_mismatch(struct vtn_builder *b, uint32_t value_id,
enum vtn_value_type value_type)
@ -6851,6 +6883,10 @@ spirv_to_nir(const uint32_t *words, size_t word_count,
entry_point->is_entrypoint = true;
}
if (MESA_SPIRV_DEBUG(VALUES)) {
vtn_dump_values(b, stdout);
}
/* structurize the CFG */
nir_lower_goto_ifs(b->shader);
@ -7144,3 +7180,82 @@ spirv_library_to_nir_builder(FILE *fp, const uint32_t *words, size_t word_count,
ralloc_free(b);
return true;
}
static unsigned
vtn_id_for_type(struct vtn_builder *b, struct vtn_type *type)
{
for (unsigned i = 0; i < b->value_id_bound; i++) {
struct vtn_value *v = &b->values[i];
if (v->value_type == vtn_value_type_type &&
v->type == type)
return i;
}
return 0;
}
void
vtn_print_value(struct vtn_builder *b, struct vtn_value *val, FILE *f)
{
fprintf(f, "%s", vtn_value_type_to_string(val->value_type));
switch (val->value_type) {
case vtn_value_type_ssa: {
struct vtn_ssa_value *ssa = val->ssa;
fprintf(f, " glsl_type=%s", glsl_get_type_name(ssa->type));
break;
}
case vtn_value_type_constant: {
fprintf(f, " type=%d", vtn_id_for_type(b, val->type));
if (val->is_null_constant)
fprintf(f, " null");
else if (val->is_undef_constant)
fprintf(f, " undef");
break;
}
case vtn_value_type_pointer: {
struct vtn_pointer *pointer = val->pointer;
fprintf(f, " ptr_type=%u", vtn_id_for_type(b, pointer->ptr_type));
fprintf(f, " (pointed-)type=%u", vtn_id_for_type(b, val->pointer->type));
if (pointer->deref) {
fprintf(f, "\n NIR: ");
nir_print_instr(&pointer->deref->instr, f);
}
break;
}
case vtn_value_type_type: {
struct vtn_type *type = val->type;
fprintf(f, " %s", vtn_base_type_to_string(type->base_type));
switch (type->base_type) {
case vtn_base_type_pointer:
fprintf(f, " deref=%d", vtn_id_for_type(b, type->deref));
fprintf(f, " %s", spirv_storageclass_to_string(val->type->storage_class));
break;
default:
break;
}
if (type->type)
fprintf(f, " glsl_type=%s", glsl_get_type_name(type->type));
break;
}
default:
break;
}
fprintf(f, "\n");
}
void
vtn_dump_values(struct vtn_builder *b, FILE *f)
{
fprintf(f, "=== SPIR-V values\n");
for (unsigned i = 1; i < b->value_id_bound; i++) {
struct vtn_value *val = &b->values[i];
fprintf(f, "%8d = ", i);
vtn_print_value(b, val, f);
}
fprintf(f, "===\n");
}

View File

@ -43,6 +43,7 @@ extern uint32_t mesa_spirv_debug;
#endif
#define MESA_SPIRV_DEBUG_STRUCTURED (1u << 0)
#define MESA_SPIRV_DEBUG_VALUES (1u << 1)
struct vtn_builder;
struct vtn_decoration;
@ -733,6 +734,9 @@ vtn_untyped_value(struct vtn_builder *b, uint32_t value_id)
return &b->values[value_id];
}
void vtn_print_value(struct vtn_builder *b, struct vtn_value *val, FILE *f);
void vtn_dump_values(struct vtn_builder *b, FILE *f);
static inline uint32_t
vtn_id_for_value(struct vtn_builder *b, struct vtn_value *value)
{