chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 / 107
0.0%
Branches:
0 / 87
0.0%
Functions:
0 / 13
0.0%

device/compute/runtime_compiler.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include "chrono_batch_render/device/compute/runtime_compiler.h"
3
4 #include <deque>
5 #include <optional>
6 #include <vector>
7
8 #include <fmt/format.h>
9
10 #include "chrono_batch_render/util/disk_cache.h"
11 #include "chrono_batch_render/util/error.h"
12 #include "chrono_batch_render/util/library.h"
13 #include "chrono_batch_render/util/log.h"
14 #include "chrono_batch_render/util/text.h"
15 #include "chrono_batch_render/util/version.h"
16
17 namespace chrono::batch_render::device::compute {
18
19 namespace {
20
21 using Program = RuntimeCompiler::Program;
22
23 ✗ void Check(const RuntimeCompiler& compiler, int result, const char* call) {
24
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (result == 0) {
25 ✗ return;
26 }
27 ✗ const char* text = compiler.getErrorString(result);
28
0/1
✗ Branch 1 not taken.
✗ throw ApiError(fmt::format("{}: {}", compiler.name, call), text != nullptr ? text : "unknown",
29
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ result);
30 }
31
32 ✗ Program CreateProgram(const RuntimeCompiler& compiler, std::string_view source,
33 std::span<const SourceHeader> headers) {
34 ✗ std::vector<std::string> texts;
35 ✗ std::vector<const char*> sources;
36 ✗ std::vector<const char*> names;
37
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (const SourceHeader& header : headers) {
38
0/1
✗ Branch 1 not taken.
✗ texts.emplace_back(header.text);
39 }
40
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (size_t i = 0; i < headers.size(); ++i) {
41
0/1
✗ Branch 1 not taken.
✗ sources.push_back(texts[i].c_str());
42
0/1
✗ Branch 1 not taken.
✗ names.push_back(headers[i].name);
43 }
44
45 ✗ Program program = nullptr;
46
0/1
✗ Branch 1 not taken.
✗ const std::string text(source);
47
0/1
✗ Branch 1 not taken.
✗ Check(compiler,
48
0/1
✗ Branch 1 not taken.
✗ compiler.createProgram(&program, text.c_str(), "kernel.cu", int(headers.size()),
49
0/1
✗ Branch 1 not taken.
✗ sources.data(), names.data()),
50 "createProgram");
51 ✗ return program;
52 ✗ }
53
54 ✗ std::string ReadOutput(const RuntimeCompiler& compiler, Program program,
55 int (*size)(Program, size_t*), int (*fill)(Program, char*),
56 const char* call) {
57 ✗ size_t bytes = 0;
58 ✗ Check(compiler, size(program, &bytes), call);
59
0/1
✗ Branch 2 not taken.
✗ std::string output(bytes, '\0');
60
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Check(compiler, fill(program, output.data()), call);
61 ✗ return output;
62 ✗ }
63
64 }
65
66 ✗ std::string RuntimeCompiler::Compile(std::string_view source, std::span<const SourceHeader> headers,
67 std::span<const std::string> options,
68 std::string_view what) const {
69 ✗ Program program = CreateProgram(*this, source, headers);
70
71 ✗ struct Destroy {
72 const RuntimeCompiler& compiler;
73 Program& program;
74
75 ✗ ~Destroy() {
76 ✗ compiler.destroyProgram(&program);
77 ✗ }
78 ✗ } destroy{*this, program};
79
80 ✗ std::vector<const char*> arguments;
81
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (const std::string& option : options) {
82
0/1
✗ Branch 1 not taken.
✗ arguments.push_back(option.c_str());
83 }
84
0/3
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ if (compileProgram(program, int(arguments.size()), arguments.data()) != 0) {
85
0/1
✗ Branch 1 not taken.
✗ throw Error("Compiling {} with {} {} failed:\n{}", what, name, version.ToString(),
86
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ ReadOutput(*this, program, getLogSize, getLog, "getProgramLog"));
87 }
88
0/1
✗ Branch 1 not taken.
✗ return ReadOutput(*this, program, getCodeSize, getCode, "getCode");
89 ✗ }
90
91 ✗ RuntimeCompiler::Compiled RuntimeCompiler::CompileCached(std::string_view source,
92 std::span<const SourceHeader> headers,
93 std::span<const std::string> options,
94 std::string_view what,
95 const DiskCache& cache) const {
96
0/1
✗ Branch 2 not taken.
✗ std::string key = fmt::format("{} {} {}", name, version.ToString(),
97
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Join({options.begin(), options.end()}, " "));
98
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (const SourceHeader& header : headers) {
99
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ key += fmt::format(" {} {}", header.name, Digest(header.text));
100 }
101
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ key += " source " + Digest(source);
102
103
0/3
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ if (std::optional<std::string> code = cache.Load(key)) {
104 ✗ return {*std::move(code), true};
105 ✗ }
106
107
0/1
✗ Branch 1 not taken.
✗ Compiled compiled{Compile(source, headers, options, what), false};
108
0/1
✗ Branch 1 not taken.
✗ cache.Store(key, compiled.code);
109 ✗ return compiled;
110 ✗ }
111
112 ✗ Loaded<RuntimeCompiler> LoadRuntimeCompiler(std::string_view name, std::string_view prefix,
113 std::string_view code,
114 std::initializer_list<const char*> names,
115 std::initializer_list<const char*> paths,
116 Version minimum, const std::filesystem::path& beside) {
117 ✗ const Library library = Library::Load(names, paths, beside);
118
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (!library) {
119
0/1
✗ Branch 1 not taken.
✗ return fmt::format("no {} was found", name);
120 }
121
122 ✗ RuntimeCompiler compiler;
123
0/1
✗ Branch 1 not taken.
✗ compiler.name = name;
124
0/1
✗ Branch 1 not taken.
✗ compiler.library = library.Name();
125
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ SymbolResolver resolve(library);
126
0/1
✗ Branch 1 not taken.
✗ std::deque<std::string> symbols;
127 ✗ const auto call = [&](std::string_view suffix, auto& function) {
128
0/14
auto chrono::batch_render::device::compute::LoadRuntimeCompiler(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::initializer_list<char const*>, std::initializer_list<char const*>, chrono::batch_render::Version, std::filesystem::__cxx11::path const&)::{lambda(std::basic_string_view<char, std::char_traits<char> >, auto:1&)#1}::operator()<char const* (*)(int)>(std::basic_string_view<char, std::char_traits<char> >, char const* (*&)(int)) const:
✗ Branch 2 not taken.
✗ Branch 5 not taken.
auto chrono::batch_render::device::compute::LoadRuntimeCompiler(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::initializer_list<char const*>, std::initializer_list<char const*>, chrono::batch_render::Version, std::filesystem::__cxx11::path const&)::{lambda(std::basic_string_view<char, std::char_traits<char> >, auto:1&)#1}::operator()<int (*)(chrono::batch_render::device::compute::CompilerProgram**)>(std::basic_string_view<char, std::char_traits<char> >, int (*&)(chrono::batch_render::device::compute::CompilerProgram**)) const:
✗ Branch 2 not taken.
✗ Branch 5 not taken.
auto chrono::batch_render::device::compute::LoadRuntimeCompiler(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::initializer_list<char const*>, std::initializer_list<char const*>, chrono::batch_render::Version, std::filesystem::__cxx11::path const&)::{lambda(std::basic_string_view<char, std::char_traits<char> >, auto:1&)#1}::operator()<int (*)(chrono::batch_render::device::compute::CompilerProgram**, char const*, char const*, int, char const* const*, char const* const*)>(std::basic_string_view<char, std::char_traits<char> >, int (*&)(chrono::batch_render::device::compute::CompilerProgram**, char const*, char const*, int, char const* const*, char const* const*)) const:
✗ Branch 2 not taken.
✗ Branch 5 not taken.
auto chrono::batch_render::device::compute::LoadRuntimeCompiler(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::initializer_list<char const*>, std::initializer_list<char const*>, chrono::batch_render::Version, std::filesystem::__cxx11::path const&)::{lambda(std::basic_string_view<char, std::char_traits<char> >, auto:1&)#1}::operator()<int (*)(chrono::batch_render::device::compute::CompilerProgram*, char*)>(std::basic_string_view<char, std::char_traits<char> >, int (*&)(chrono::batch_render::device::compute::CompilerProgram*, char*)) const:
✗ Branch 2 not taken.
✗ Branch 5 not taken.
auto chrono::batch_render::device::compute::LoadRuntimeCompiler(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::initializer_list<char const*>, std::initializer_list<char const*>, chrono::batch_render::Version, std::filesystem::__cxx11::path const&)::{lambda(std::basic_string_view<char, std::char_traits<char> >, auto:1&)#1}::operator()<int (*)(chrono::batch_render::device::compute::CompilerProgram*, int, char const* const*)>(std::basic_string_view<char, std::char_traits<char> >, int (*&)(chrono::batch_render::device::compute::CompilerProgram*, int, char const* const*)) const:
✗ Branch 2 not taken.
✗ Branch 5 not taken.
auto chrono::batch_render::device::compute::LoadRuntimeCompiler(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::initializer_list<char const*>, std::initializer_list<char const*>, chrono::batch_render::Version, std::filesystem::__cxx11::path const&)::{lambda(std::basic_string_view<char, std::char_traits<char> >, auto:1&)#1}::operator()<int (*)(chrono::batch_render::device::compute::CompilerProgram*, unsigned long*)>(std::basic_string_view<char, std::char_traits<char> >, int (*&)(chrono::batch_render::device::compute::CompilerProgram*, unsigned long*)) const:
✗ Branch 2 not taken.
✗ Branch 5 not taken.
auto chrono::batch_render::device::compute::LoadRuntimeCompiler(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, std::initializer_list<char const*>, std::initializer_list<char const*>, chrono::batch_render::Version, std::filesystem::__cxx11::path const&)::{lambda(std::basic_string_view<char, std::char_traits<char> >, auto:1&)#1}::operator()<int (*)(int*, int*)>(std::basic_string_view<char, std::char_traits<char> >, int (*&)(int*, int*)) const:
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ resolve(symbols.emplace_back(fmt::format("{}{}", prefix, suffix)).c_str(), function);
129 ✗ };
130
0/1
✗ Branch 1 not taken.
✗ call("Version", compiler.getVersion);
131
0/1
✗ Branch 1 not taken.
✗ call("GetErrorString", compiler.getErrorString);
132
0/1
✗ Branch 1 not taken.
✗ call("CreateProgram", compiler.createProgram);
133
0/1
✗ Branch 1 not taken.
✗ call("DestroyProgram", compiler.destroyProgram);
134
0/1
✗ Branch 1 not taken.
✗ call("CompileProgram", compiler.compileProgram);
135
0/1
✗ Branch 1 not taken.
✗ call("GetProgramLogSize", compiler.getLogSize);
136
0/1
✗ Branch 1 not taken.
✗ call("GetProgramLog", compiler.getLog);
137
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ call(fmt::format("Get{}Size", code), compiler.getCodeSize);
138
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ call(fmt::format("Get{}", code), compiler.getCode);
139
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (resolve.Missing() != nullptr) {
140
0/1
✗ Branch 1 not taken.
✗ return fmt::format("{} lacks {}", compiler.library, resolve.Missing());
141 }
142
143 ✗ int major = 0;
144 ✗ int minor = 0;
145
0/1
✗ Branch 1 not taken.
✗ compiler.getVersion(&major, &minor);
146 ✗ compiler.version = {major, minor};
147
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (compiler.version < minimum) {
148
0/1
✗ Branch 1 not taken.
✗ return TooOld(name, compiler.version, minimum);
149 }
150
151
0/2
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Log(LogLevel::Debug, "{} {} from {}", name, compiler.version.ToString(), compiler.library);
152 ✗ return compiler;
153 ✗ }
154
155 }
156