1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
//
// Copyright 2020 Serge Martin
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include <cstring>
#include <cstdio>
#include <string>
#include <iostream>
#include "util/u_math.h"
#include "core/printf.hpp"
#include "util/u_printf.h"
using namespace clover;
namespace {
const cl_uint hdr_dwords = 2;
const cl_uint initial_buffer_offset = hdr_dwords * sizeof(cl_uint);
/* all valid chars that can appear in CL C printf string. */
const std::string clc_printf_whitelist = "%0123456789-+ #.AacdeEfFgGhilopsuvxX";
void
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;
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());
}
}
std::unique_ptr<printf_handler>
printf_handler::create(const intrusive_ptr<command_queue> &q,
const std::vector<binary::printf_info> &infos,
bool strings_in_buffer,
cl_uint size) {
return std::unique_ptr<printf_handler>(
new printf_handler(q, infos, strings_in_buffer, size));
}
printf_handler::printf_handler(const intrusive_ptr<command_queue> &q,
const std::vector<binary::printf_info> &infos,
bool strings_in_buffer,
cl_uint size) :
_q(q), _formatters(infos), _strings_in_buffer(strings_in_buffer), _size(size), _buffer() {
if (_size) {
std::string data;
data.reserve(_size);
cl_uint header[2] = { 0 };
header[0] = initial_buffer_offset;
header[1] = _size;
data.append((char *)header, (char *)(header+hdr_dwords));
_buffer = std::unique_ptr<root_buffer>(new root_buffer(_q->context,
std::vector<cl_mem_properties>(),
CL_MEM_COPY_HOST_PTR,
_size, (char*)data.data()));
}
}
cl_mem
printf_handler::get_mem() {
return (cl_mem)(_buffer.get());
}
void
printf_handler::print() {
if (!_buffer)
return;
mapping src = { *_q, _buffer->resource_in(*_q), CL_MAP_READ, true,
{{ 0 }}, {{ _size, 1, 1 }} };
cl_uint header[2] = { 0 };
std::memcpy(header,
static_cast<const char *>(src),
initial_buffer_offset);
cl_uint buffer_size = header[0];
buffer_size -= initial_buffer_offset;
std::vector<char> buf;
buf.resize(buffer_size);
std::memcpy(buf.data(),
static_cast<const char *>(src) + initial_buffer_offset,
buffer_size);
// mixed endian isn't going to work, sort it out if anyone cares later.
assert(_q->device().endianness() == PIPE_ENDIAN_NATIVE);
print_formatted(_formatters, _strings_in_buffer, buf);
}
|