From aa82808645fb9932ce6f9d2115dcdc9edce98cd8 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Sat, 16 Apr 2022 10:48:08 +0200 Subject: [PATCH] printf: extract clovers printf impl Also make the code cleaner and simplier. Signed-off-by: Karol Herbst Acked-by: Jesse Natalie Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/nir/nir.h | 10 +- src/compiler/spirv/vtn_opencl.c | 6 +- src/gallium/frontends/clover/core/binary.hpp | 2 +- src/gallium/frontends/clover/core/printf.cpp | 134 ++-------------- .../frontends/clover/nir/invocation.cpp | 2 +- src/util/u_printf.c | 146 ++++++++++++++++++ src/util/u_printf.h | 10 ++ 7 files changed, 176 insertions(+), 134 deletions(-) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 89b9c79df09..85c40db0420 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -39,6 +39,7 @@ #include "util/compiler.h" #include "util/enum_operators.h" #include "util/macros.h" +#include "util/u_printf.h" #include "util/format/u_format.h" #include "compiler/nir_types.h" #include "compiler/shader_enums.h" @@ -3157,13 +3158,6 @@ typedef struct { uint8_t bit_size; } nir_parameter; -typedef struct nir_printf_info { - unsigned num_args; - unsigned *arg_sizes; - unsigned string_size; - char *strings; -} nir_printf_info; - typedef struct nir_function { struct exec_node node; @@ -3732,7 +3726,7 @@ typedef struct nir_shader { struct nir_xfb_info *xfb_info; unsigned printf_info_count; - nir_printf_info *printf_info; + u_printf_info *printf_info; } nir_shader; #define nir_foreach_function(func, shader) \ diff --git a/src/compiler/spirv/vtn_opencl.c b/src/compiler/spirv/vtn_opencl.c index befb6eaf3b3..0cf715c01ca 100644 --- a/src/compiler/spirv/vtn_opencl.c +++ b/src/compiler/spirv/vtn_opencl.c @@ -726,7 +726,7 @@ vtn_handle_opencl_vstore_half_r(struct vtn_builder *b, enum OpenCLstd_Entrypoint } static unsigned -vtn_add_printf_string(struct vtn_builder *b, uint32_t id, nir_printf_info *info) +vtn_add_printf_string(struct vtn_builder *b, uint32_t id, u_printf_info *info) { nir_deref_instr *deref = vtn_nir_deref(b, id); @@ -783,8 +783,8 @@ handle_printf(struct vtn_builder *b, uint32_t opcode, unsigned info_idx = b->shader->printf_info_count; b->shader->printf_info = reralloc(b->shader, b->shader->printf_info, - nir_printf_info, info_idx); - nir_printf_info *info = &b->shader->printf_info[info_idx - 1]; + u_printf_info, info_idx); + u_printf_info *info = &b->shader->printf_info[info_idx - 1]; info->strings = NULL; info->string_size = 0; diff --git a/src/gallium/frontends/clover/core/binary.hpp b/src/gallium/frontends/clover/core/binary.hpp index 951ddc48a47..a854453b550 100644 --- a/src/gallium/frontends/clover/core/binary.hpp +++ b/src/gallium/frontends/clover/core/binary.hpp @@ -57,7 +57,7 @@ namespace clover { struct printf_info { std::vector arg_sizes; - std::vector strings; + std::vector strings; }; struct arg_info { diff --git a/src/gallium/frontends/clover/core/printf.cpp b/src/gallium/frontends/clover/core/printf.cpp index c6231f19d83..6a5b7fb5152 100644 --- a/src/gallium/frontends/clover/core/printf.cpp +++ b/src/gallium/frontends/clover/core/printf.cpp @@ -40,136 +40,28 @@ namespace { const std::string clc_printf_whitelist = "%0123456789-+ #.AacdeEfFgGhilopsuvxX"; void - print_formatted(const std::vector &formatters, + print_formatted(std::vector &formatters, bool _strings_in_buffer, const std::vector &buffer) { static std::atomic warn_count; + if (buffer.empty() && !warn_count++) - std::cerr << "Printf used but no printf occurred - may cause perfomance issue." << std::endl; + std::cerr << "Printf used but no printf occurred - may cause perfomance issue." << std::endl; - for (size_t buf_pos = 0; buf_pos < buffer.size(); ) { - cl_uint fmt_idx = *(cl_uint*)&buffer[buf_pos]; - assert(fmt_idx > 0); - binary::printf_info fmt = formatters[fmt_idx-1]; + std::vector infos; + for (auto &f : formatters) { + u_printf_info info; - std::string format = (char *)fmt.strings.data(); - buf_pos += sizeof(cl_uint); + info.num_args = f.arg_sizes.size(); + info.arg_sizes = f.arg_sizes.data(); + info.string_size = f.strings.size(); + info.strings = f.strings.data(); - if (fmt.arg_sizes.empty()) { - printf("%s", format.c_str()); - - } else { - size_t fmt_last_pos = 0; - size_t fmt_pos = 0; - for (int arg_size : fmt.arg_sizes) { - const size_t spec_pos = util_printf_next_spec_pos(format.c_str(), fmt_pos); - const size_t cur_tok = format.rfind('%', spec_pos); - const size_t next_spec = util_printf_next_spec_pos(format.c_str(), spec_pos); - const size_t next_tok = next_spec == std::string::npos ? std::string::npos : - format.rfind('%', next_spec); - - size_t vec_pos = format.find_first_of("v", cur_tok + 1); - size_t mod_pos = format.find_first_of("hl", cur_tok + 1); - - // print the part before the format token - if (cur_tok != fmt_last_pos) { - std::string s = format.substr(fmt_last_pos, - cur_tok - fmt_last_pos); - printf("%s", s.c_str()); - } - - std::string print_str; - print_str = format.substr(cur_tok, spec_pos + 1 - cur_tok); - - /* Never pass a 'n' spec to the host printf */ - bool valid_str = print_str.find_first_not_of(clc_printf_whitelist) == - std::string::npos; - - // print the formated part - if (spec_pos != std::string::npos && valid_str) { - bool is_vector = vec_pos != std::string::npos && - vec_pos + 1 < spec_pos; - bool is_string = format[spec_pos] == 's'; - bool is_float = std::string("fFeEgGaA") - .find(format[spec_pos]) != std::string::npos; - - if (is_string) { - if (_strings_in_buffer) - printf(print_str.c_str(), &buffer[buf_pos]); - else { - uint64_t idx; - memcpy(&idx, &buffer[buf_pos], 8); - printf(print_str.c_str(), &fmt.strings[idx]); - } - } else { - int component_count = 1; - - if (is_vector) { - size_t l = std::min(mod_pos, spec_pos) - vec_pos - 1; - std::string s = format.substr(vec_pos + 1, l); - component_count = std::stoi(s); - if (mod_pos != std::string::npos) { - // CL C has hl specifier for 32-bit vectors, C doesn't have it - // just remove it. - std::string mod = format.substr(mod_pos, 2); - if (mod == "hl") - mod_pos = std::string::npos; - } - print_str.erase(vec_pos - cur_tok, std::min(mod_pos, spec_pos) - vec_pos); - print_str.push_back(','); - } - - //in fact vec3 are vec4 - int men_components = - component_count == 3 ? 4 : component_count; - size_t elmt_size = arg_size / men_components; - - for (int i = 0; i < component_count; i++) { - size_t elmt_buf_pos = buf_pos + i * elmt_size; - if (is_vector && i + 1 == component_count) - print_str.pop_back(); - - if (is_float) { - switch (elmt_size) { - case 2: - cl_half h; - std::memcpy(&h, &buffer[elmt_buf_pos], elmt_size); - printf(print_str.c_str(), h); - break; - case 4: - cl_float f; - std::memcpy(&f, &buffer[elmt_buf_pos], elmt_size); - printf(print_str.c_str(), f); - break; - default: - cl_double d; - std::memcpy(&d, &buffer[elmt_buf_pos], elmt_size); - printf(print_str.c_str(), d); - } - } else { - cl_long l = 0; - std::memcpy(&l, &buffer[elmt_buf_pos], elmt_size); - printf(print_str.c_str(), l); - } - } - } - // print the remaining - if (next_tok != spec_pos) { - std::string s = format.substr(spec_pos + 1, - next_tok - spec_pos - 1); - printf("%s", s.c_str()); - } - } - - fmt_pos = spec_pos; - fmt_last_pos = next_tok; - - buf_pos += arg_size; - buf_pos = ALIGN(buf_pos, 4); - } - } + infos.push_back(info); } + + u_printf(stdout, buffer.data(), buffer.size(), infos.data(), infos.size()); } } diff --git a/src/gallium/frontends/clover/nir/invocation.cpp b/src/gallium/frontends/clover/nir/invocation.cpp index b741a0a184c..e84123d961d 100644 --- a/src/gallium/frontends/clover/nir/invocation.cpp +++ b/src/gallium/frontends/clover/nir/invocation.cpp @@ -588,7 +588,7 @@ binary clover::nir::spirv_to_nir(const binary &mod, const device &dev, void *mem_ctx = ralloc_context(NULL); unsigned printf_info_count = nir->printf_info_count; - nir_printf_info *printf_infos = nir->printf_info; + u_printf_info *printf_infos = nir->printf_info; ralloc_steal(mem_ctx, printf_infos); diff --git a/src/util/u_printf.c b/src/util/u_printf.c index ff579988adf..b4ea39d86e3 100644 --- a/src/util/u_printf.c +++ b/src/util/u_printf.c @@ -23,9 +23,13 @@ #include #include +#include +#include #include #include "macros.h" +#include "strndup.h" +#include "u_math.h" #include "u_printf.h" /* Some versions of MinGW are missing _vscprintf's declaration, although they @@ -42,6 +46,14 @@ _CRTIMP int _vscprintf(const char *format, va_list argptr); #endif #endif +static const char* +util_printf_prev_tok(const char *str) +{ + while (*str != '%') + str--; + return str; +} + size_t util_printf_next_spec_pos(const char *str, size_t pos) { if (str == NULL) @@ -94,3 +106,137 @@ size_t u_printf_length(const char *fmt, va_list untouched_args) return size; } + +void u_printf(FILE *out, const char *buffer, size_t buffer_size, + const u_printf_info *info, unsigned info_size) +{ + for (size_t buf_pos = 0; buf_pos < buffer_size;) { + uint32_t fmt_idx = *(uint32_t*)&buffer[buf_pos]; + + /* the idx is 1 based */ + assert(fmt_idx > 0); + fmt_idx -= 1; + + /* The API allows more arguments than the format uses */ + if (fmt_idx >= info_size) + return; + + const u_printf_info *fmt = &info[fmt_idx]; + const char *format = fmt->strings; + buf_pos += sizeof(fmt_idx); + + if (!fmt->num_args) { + fprintf(out, "%s", format); + continue; + } + + for (int i = 0; i < fmt->num_args; i++) { + int arg_size = fmt->arg_sizes[i]; + size_t spec_pos = util_printf_next_spec_pos(format, 0); + + if (spec_pos == -1) { + fprintf(out, "%s", format); + continue; + } + + const char *token = util_printf_prev_tok(&format[spec_pos]); + const char *next_format = &format[spec_pos + 1]; + + /* print the part before the format token */ + if (token != format) + fwrite(format, token - format, 1, out); + + char *print_str = strndup(token, next_format - token); + /* rebase spec_pos so we can use it with print_str */ + spec_pos += format - token; + + /* print the formated part */ + if (print_str[spec_pos] == 's') { + uint64_t idx; + memcpy(&idx, &buffer[buf_pos], 8); + fprintf(out, print_str, &fmt->strings[idx]); + + /* Never pass a 'n' spec to the host printf */ + } else if (print_str[spec_pos] != 'n') { + char *vec_pos = strchr(print_str, 'v'); + char *mod_pos = strpbrk(print_str, "hl"); + + int component_count = 1; + if (vec_pos != NULL) { + /* non vector part of the format */ + size_t base = mod_pos ? mod_pos - print_str : spec_pos; + size_t l = base - (vec_pos - print_str) - 1; + char *vec = strndup(&vec_pos[1], l); + component_count = atoi(vec); + free(vec); + + /* remove the vector and precision stuff */ + memmove(&print_str[vec_pos - print_str], &print_str[spec_pos], 2); + } + + /* in fact vec3 are vec4 */ + int men_components = component_count == 3 ? 4 : component_count; + size_t elmt_size = arg_size / men_components; + bool is_float = strpbrk(print_str, "fFeEgGaA") != NULL; + + for (int i = 0; i < component_count; i++) { + size_t elmt_buf_pos = buf_pos + i * elmt_size; + switch (elmt_size) { + case 1: { + uint8_t v; + memcpy(&v, &buffer[elmt_buf_pos], elmt_size); + fprintf(out, print_str, v); + break; + } + case 2: { + uint16_t v; + memcpy(&v, &buffer[elmt_buf_pos], elmt_size); + fprintf(out, print_str, v); + break; + } + case 4: { + if (is_float) { + float v; + memcpy(&v, &buffer[elmt_buf_pos], elmt_size); + fprintf(out, print_str, v); + } else { + uint32_t v; + memcpy(&v, &buffer[elmt_buf_pos], elmt_size); + fprintf(out, print_str, v); + } + break; + } + case 8: { + if (is_float) { + double v; + memcpy(&v, &buffer[elmt_buf_pos], elmt_size); + fprintf(out, print_str, v); + } else { + uint64_t v; + memcpy(&v, &buffer[elmt_buf_pos], elmt_size); + fprintf(out, print_str, v); + } + break; + } + default: + assert(false); + break; + } + + if (i < component_count - 1) + fprintf(out, ","); + } + } + + /* rebase format */ + format = next_format; + free(print_str); + + buf_pos += arg_size; + buf_pos = ALIGN(buf_pos, 4); + } + + /* print remaining */ + fprintf(out, "%s", format); + } +} diff --git a/src/util/u_printf.h b/src/util/u_printf.h index 63c212e63f3..d0f6b4dabf8 100644 --- a/src/util/u_printf.h +++ b/src/util/u_printf.h @@ -29,6 +29,13 @@ extern "C" { #endif +typedef struct u_printf_info { + unsigned num_args; + unsigned *arg_sizes; + unsigned string_size; + char *strings; +} u_printf_info; + /* find next valid printf specifier in a C string wrapper */ size_t util_printf_next_spec_pos(const char *str, size_t pos); @@ -39,6 +46,9 @@ size_t util_printf_next_spec_pos(const char *str, size_t pos); */ size_t u_printf_length(const char *fmt, va_list untouched_args); +void u_printf(FILE *out, const char *buffer, size_t buffer_size, + const u_printf_info*, unsigned info_size); + #ifdef __cplusplus } #endif