From c16e58eabd94573d94b8c75d35fb0306d4831eae Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 27 Feb 2024 18:45:46 +0200 Subject: [PATCH] nir: add a low level printf emission helper Uses the same memory layout as the print intrinsic lowering. This one just let's you do the emission without having to deal with variables. This useful for debug traces. Signed-off-by: Lionel Landwerlin Reviewed-by: Karol Herbst Reviewed-by: Ivan Briano Part-of: --- src/compiler/nir/nir_builder.h | 8 +++ src/compiler/nir/nir_lower_printf.c | 93 +++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h index 8e7490c1ef6..d588dd65a51 100644 --- a/src/compiler/nir/nir_builder.h +++ b/src/compiler/nir/nir_builder.h @@ -2165,6 +2165,14 @@ nir_scoped_memory_barrier(nir_builder *b, nir_def * nir_gen_rect_vertices(nir_builder *b, nir_def *z, nir_def *w); +/* Emits a printf in the same way nir_lower_printf(). Each of the variadic + * argument is a pointer to a nir_def value. + */ +void nir_printf_fmt(nir_builder *b, + bool use_printf_base_identifier, + unsigned ptr_bit_size, + const char *fmt, ...); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/compiler/nir/nir_lower_printf.c b/src/compiler/nir/nir_lower_printf.c index c655c7ec068..fb51dae0d1b 100644 --- a/src/compiler/nir/nir_lower_printf.c +++ b/src/compiler/nir/nir_lower_printf.c @@ -132,3 +132,96 @@ nir_lower_printf(nir_shader *nir, const nir_lower_printf_options *options) nir_metadata_none, (void *)options); } + +void +nir_printf_fmt(nir_builder *b, + bool use_printf_base_identifier, + unsigned ptr_bit_size, + const char *fmt, ...) +{ + b->shader->printf_info_count++; + b->shader->printf_info = reralloc(b->shader, + b->shader->printf_info, + u_printf_info, + b->shader->printf_info_count); + + u_printf_info *info = + &b->shader->printf_info[b->shader->printf_info_count - 1]; + + *info = (u_printf_info) { + .strings = ralloc_strdup(b->shader, fmt), + .string_size = strlen(fmt) + 1, + }; + + va_list ap; + size_t pos = 0; + size_t args_size = 0; + + va_start(ap, fmt); + while ((pos = util_printf_next_spec_pos(fmt, pos)) != -1) { + unsigned arg_size; + switch (fmt[pos]) { + case 'c': arg_size = 1; break; + case 'd': arg_size = 4; break; + case 'e': arg_size = 4; break; + case 'E': arg_size = 4; break; + case 'f': arg_size = 4; break; + case 'F': arg_size = 4; break; + case 'G': arg_size = 4; break; + case 'a': arg_size = 4; break; + case 'A': arg_size = 4; break; + case 'i': arg_size = 4; break; + case 'u': arg_size = 4; break; + case 'x': arg_size = 4; break; + case 'X': arg_size = 4; break; + case 'p': arg_size = 8; break; + default: unreachable("invalid"); + } + + nir_def *def = va_arg(ap, nir_def*); + assert(def->bit_size / 8 == arg_size); + + info->num_args++; + info->arg_sizes = reralloc(b->shader, + info->arg_sizes, + unsigned, info->num_args); + info->arg_sizes[info->num_args - 1] = arg_size; + + args_size += arg_size; + } + va_end(ap); + + nir_def *buffer_addr = + nir_load_printf_buffer_address( + b, ptr_bit_size ? ptr_bit_size : nir_get_ptr_bitsize(b->shader)); + nir_def *buffer_offset = + nir_global_atomic(b, 32, buffer_addr, + nir_imm_int(b, args_size + sizeof(uint32_t)), + .atomic_op = nir_atomic_op_iadd); + + /* Identifier */ + nir_def *identifier = + use_printf_base_identifier ? + nir_iadd_imm(b, + nir_load_printf_base_identifier(b), + b->shader->printf_info_count) : + nir_imm_int(b, b->shader->printf_info_count); + + nir_def *store_addr = + nir_iadd(b, buffer_addr, nir_i2iN(b, buffer_offset, + buffer_addr->bit_size)); + nir_store_global(b, store_addr, 4, identifier, 0x1); + + /* Arguments */ + va_start(ap, fmt); + unsigned store_offset = sizeof(uint32_t); + for (unsigned a = 0; a < info->num_args; a++) { + nir_def *def = va_arg(ap, nir_def*); + + nir_store_global(b, nir_iadd_imm(b, store_addr, store_offset), + 4, def, 0x1); + + store_offset += info->arg_sizes[a]; + } + va_end(ap); +}