Also make the code cleaner and simplier.
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Acked-by: Jesse Natalie <jenatali@microsoft.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17334>
#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"
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;
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) \
}
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);
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;
struct printf_info {
std::vector<uint32_t> arg_sizes;
- std::vector<uint8_t> strings;
+ std::vector<char> strings;
};
struct arg_info {
const std::string clc_printf_whitelist = "%0123456789-+ #.AacdeEfFgGhilopsuvxX";
void
- print_formatted(const std::vector<binary::printf_info> &formatters,
+ print_formatted(std::vector<binary::printf_info> &formatters,
bool _strings_in_buffer,
const std::vector<char> &buffer) {
static std::atomic<unsigned> warn_count;
+
if (buffer.empty() && !warn_count++)
- 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::string format = (char *)fmt.strings.data();
- buf_pos += sizeof(cl_uint);
-
- 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);
- }
- }
+ std::cerr << "Printf used but no printf occurred - may cause perfomance issue." << std::endl;
+
+ std::vector<u_printf_info> infos;
+ for (auto &f : formatters) {
+ u_printf_info info;
+
+ 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();
+
+ infos.push_back(info);
}
+
+ u_printf(stdout, buffer.data(), buffer.size(), infos.data(), infos.size());
}
}
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);
#include <assert.h>
#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
#include <string.h>
#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
#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)
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);
+ }
+}
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);
*/
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