~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/frontends/clover/core/printf.cpp

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
// Copyright 2020 Serge Martin
3
 
//
4
 
// Permission is hereby granted, free of charge, to any person obtaining a
5
 
// copy of this software and associated documentation files (the "Software"),
6
 
// to deal in the Software without restriction, including without limitation
7
 
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 
// and/or sell copies of the Software, and to permit persons to whom the
9
 
// Software is furnished to do so, subject to the following conditions:
10
 
//
11
 
// The above copyright notice and this permission notice shall be included in
12
 
// all copies or substantial portions of the Software.
13
 
//
14
 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17
 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
 
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
 
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
 
// OTHER DEALINGS IN THE SOFTWARE.
21
 
//
22
 
 
23
 
#include <cstring>
24
 
#include <cstdio>
25
 
#include <string>
26
 
#include <iostream>
27
 
 
28
 
#include "util/u_math.h"
29
 
#include "core/printf.hpp"
30
 
 
31
 
#include "util/u_printf.h"
32
 
using namespace clover;
33
 
 
34
 
namespace {
35
 
 
36
 
   const cl_uint hdr_dwords = 2;
37
 
   const cl_uint initial_buffer_offset = hdr_dwords * sizeof(cl_uint);
38
 
 
39
 
   /* all valid chars that can appear in CL C printf string. */
40
 
   const std::string clc_printf_whitelist = "%0123456789-+ #.AacdeEfFgGhilopsuvxX";
41
 
 
42
 
   void
43
 
   print_formatted(const std::vector<binary::printf_info> &formatters,
44
 
                   bool _strings_in_buffer,
45
 
                   const std::vector<char> &buffer) {
46
 
 
47
 
      static std::atomic<unsigned> warn_count;
48
 
      if (buffer.empty() && !warn_count++)
49
 
         std::cerr << "Printf used but no printf occurred - may cause perfomance issue." << std::endl;
50
 
 
51
 
      for (size_t buf_pos = 0; buf_pos < buffer.size(); ) {
52
 
         cl_uint fmt_idx = *(cl_uint*)&buffer[buf_pos];
53
 
         assert(fmt_idx > 0);
54
 
         binary::printf_info fmt = formatters[fmt_idx-1];
55
 
 
56
 
         std::string format = (char *)fmt.strings.data();
57
 
         buf_pos += sizeof(cl_uint);
58
 
 
59
 
         if (fmt.arg_sizes.empty()) {
60
 
            printf("%s", format.c_str());
61
 
 
62
 
         } else {
63
 
            size_t fmt_last_pos = 0;
64
 
            size_t fmt_pos = 0;
65
 
            for (int arg_size : fmt.arg_sizes) {
66
 
               const size_t spec_pos = util_printf_next_spec_pos(format.c_str(), fmt_pos);
67
 
               const size_t cur_tok = format.rfind('%', spec_pos);
68
 
               const size_t next_spec = util_printf_next_spec_pos(format.c_str(), spec_pos);
69
 
               const size_t next_tok = next_spec == std::string::npos ? std::string::npos :
70
 
                  format.rfind('%', next_spec);
71
 
 
72
 
               size_t vec_pos = format.find_first_of("v", cur_tok + 1);
73
 
               size_t mod_pos = format.find_first_of("hl", cur_tok + 1);
74
 
 
75
 
               // print the part before the format token
76
 
               if (cur_tok != fmt_last_pos) {
77
 
                  std::string s = format.substr(fmt_last_pos,
78
 
                                                cur_tok - fmt_last_pos);
79
 
                  printf("%s", s.c_str());
80
 
               }
81
 
 
82
 
               std::string print_str;
83
 
               print_str = format.substr(cur_tok, spec_pos + 1 - cur_tok);
84
 
 
85
 
               /* Never pass a 'n' spec to the host printf */
86
 
               bool valid_str = print_str.find_first_not_of(clc_printf_whitelist) ==
87
 
                  std::string::npos;
88
 
 
89
 
               // print the formated part
90
 
               if (spec_pos != std::string::npos && valid_str) {
91
 
                  bool is_vector = vec_pos != std::string::npos &&
92
 
                     vec_pos + 1 < spec_pos;
93
 
                  bool is_string = format[spec_pos] == 's';
94
 
                  bool is_float = std::string("fFeEgGaA")
95
 
                     .find(format[spec_pos]) != std::string::npos;
96
 
 
97
 
                  if (is_string) {
98
 
                     if (_strings_in_buffer)
99
 
                        printf(print_str.c_str(), &buffer[buf_pos]);
100
 
                     else {
101
 
                        uint64_t idx;
102
 
                        memcpy(&idx, &buffer[buf_pos], 8);
103
 
                        printf(print_str.c_str(), &fmt.strings[idx]);
104
 
                     }
105
 
                  } else {
106
 
                     int component_count = 1;
107
 
 
108
 
                     if (is_vector) {
109
 
                        size_t l = std::min(mod_pos, spec_pos) - vec_pos - 1;
110
 
                        std::string s = format.substr(vec_pos + 1, l);
111
 
                        component_count = std::stoi(s);
112
 
                        if (mod_pos != std::string::npos) {
113
 
                           // CL C has hl specifier for 32-bit vectors, C doesn't have it
114
 
                           // just remove it.
115
 
                           std::string mod = format.substr(mod_pos, 2);
116
 
                           if (mod == "hl")
117
 
                              mod_pos = std::string::npos;
118
 
                        }
119
 
                        print_str.erase(vec_pos - cur_tok, std::min(mod_pos, spec_pos) - vec_pos);
120
 
                        print_str.push_back(',');
121
 
                     }
122
 
 
123
 
                     //in fact vec3 are vec4
124
 
                     int men_components =
125
 
                        component_count == 3 ? 4 : component_count;
126
 
                     size_t elmt_size = arg_size / men_components;
127
 
 
128
 
                     for (int i = 0; i < component_count; i++) {
129
 
                        size_t elmt_buf_pos = buf_pos + i * elmt_size;
130
 
                        if (is_vector && i + 1 == component_count)
131
 
                           print_str.pop_back();
132
 
 
133
 
                        if (is_float) {
134
 
                           switch (elmt_size) {
135
 
                           case 2:
136
 
                              cl_half h;
137
 
                              std::memcpy(&h, &buffer[elmt_buf_pos], elmt_size);
138
 
                              printf(print_str.c_str(), h);
139
 
                              break;
140
 
                           case 4:
141
 
                              cl_float f;
142
 
                              std::memcpy(&f, &buffer[elmt_buf_pos], elmt_size);
143
 
                              printf(print_str.c_str(), f);
144
 
                              break;
145
 
                           default:
146
 
                              cl_double d;
147
 
                              std::memcpy(&d, &buffer[elmt_buf_pos], elmt_size);
148
 
                              printf(print_str.c_str(), d);
149
 
                           }
150
 
                        } else {
151
 
                           cl_long l = 0;
152
 
                           std::memcpy(&l, &buffer[elmt_buf_pos], elmt_size);
153
 
                           printf(print_str.c_str(), l);
154
 
                        }
155
 
                     }
156
 
                  }
157
 
                  // print the remaining
158
 
                  if (next_tok != spec_pos) {
159
 
                     std::string s = format.substr(spec_pos + 1,
160
 
                                                   next_tok - spec_pos - 1);
161
 
                     printf("%s", s.c_str());
162
 
                  }
163
 
               }
164
 
 
165
 
               fmt_pos = spec_pos;
166
 
               fmt_last_pos = next_tok;
167
 
 
168
 
               buf_pos += arg_size;
169
 
               buf_pos = ALIGN(buf_pos, 4);
170
 
            }
171
 
         }
172
 
      }
173
 
   }
174
 
}
175
 
 
176
 
std::unique_ptr<printf_handler>
177
 
printf_handler::create(const intrusive_ptr<command_queue> &q,
178
 
                       const std::vector<binary::printf_info> &infos,
179
 
                       bool strings_in_buffer,
180
 
                       cl_uint size) {
181
 
   return std::unique_ptr<printf_handler>(
182
 
                                       new printf_handler(q, infos, strings_in_buffer, size));
183
 
}
184
 
 
185
 
printf_handler::printf_handler(const intrusive_ptr<command_queue> &q,
186
 
                               const std::vector<binary::printf_info> &infos,
187
 
                               bool strings_in_buffer,
188
 
                               cl_uint size) :
189
 
   _q(q), _formatters(infos), _strings_in_buffer(strings_in_buffer), _size(size), _buffer() {
190
 
 
191
 
   if (_size) {
192
 
      std::string data;
193
 
      data.reserve(_size);
194
 
      cl_uint header[2] = { 0 };
195
 
 
196
 
      header[0] = initial_buffer_offset;
197
 
      header[1] = _size;
198
 
 
199
 
      data.append((char *)header, (char *)(header+hdr_dwords));
200
 
      _buffer = std::unique_ptr<root_buffer>(new root_buffer(_q->context,
201
 
                                             std::vector<cl_mem_properties>(),
202
 
                                             CL_MEM_COPY_HOST_PTR,
203
 
                                             _size, (char*)data.data()));
204
 
   }
205
 
}
206
 
 
207
 
cl_mem
208
 
printf_handler::get_mem() {
209
 
   return (cl_mem)(_buffer.get());
210
 
}
211
 
 
212
 
void
213
 
printf_handler::print() {
214
 
   if (!_buffer)
215
 
      return;
216
 
 
217
 
   mapping src = { *_q, _buffer->resource_in(*_q), CL_MAP_READ, true,
218
 
                  {{ 0 }}, {{ _size, 1, 1 }} };
219
 
 
220
 
   cl_uint header[2] = { 0 };
221
 
   std::memcpy(header,
222
 
               static_cast<const char *>(src),
223
 
               initial_buffer_offset);
224
 
 
225
 
   cl_uint buffer_size = header[0];
226
 
   buffer_size -= initial_buffer_offset;
227
 
   std::vector<char> buf;
228
 
   buf.resize(buffer_size);
229
 
 
230
 
   std::memcpy(buf.data(),
231
 
               static_cast<const char *>(src) + initial_buffer_offset,
232
 
               buffer_size);
233
 
 
234
 
   // mixed endian isn't going to work, sort it out if anyone cares later.
235
 
   assert(_q->device().endianness() == PIPE_ENDIAN_NATIVE);
236
 
   print_formatted(_formatters, _strings_in_buffer, buf);
237
 
}