Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/shaderc
Path: blob/main/libshaderc_util/src/spirv_tools_wrapper.cc
1560 views
1
// Copyright 2016 The Shaderc Authors. All rights reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include "libshaderc_util/spirv_tools_wrapper.h"
16
17
#include <algorithm>
18
#include <sstream>
19
20
#include "spirv-tools/libspirv.hpp"
21
#include "spirv-tools/optimizer.hpp"
22
23
namespace shaderc_util {
24
25
namespace {
26
27
// Gets the corresponding target environment used in SPIRV-Tools.
28
spv_target_env GetSpirvToolsTargetEnv(Compiler::TargetEnv env,
29
Compiler::TargetEnvVersion version) {
30
switch (env) {
31
case Compiler::TargetEnv::Vulkan:
32
switch (version) {
33
case Compiler::TargetEnvVersion::Default:
34
return SPV_ENV_VULKAN_1_0;
35
case Compiler::TargetEnvVersion::Vulkan_1_0:
36
return SPV_ENV_VULKAN_1_0;
37
case Compiler::TargetEnvVersion::Vulkan_1_1:
38
return SPV_ENV_VULKAN_1_1;
39
case Compiler::TargetEnvVersion::Vulkan_1_2:
40
return SPV_ENV_VULKAN_1_2;
41
case Compiler::TargetEnvVersion::Vulkan_1_3:
42
return SPV_ENV_VULKAN_1_3;
43
default:
44
break;
45
}
46
break;
47
case Compiler::TargetEnv::OpenGL:
48
return SPV_ENV_OPENGL_4_5;
49
case Compiler::TargetEnv::OpenGLCompat:
50
// Errors out before getting here. But the compiler wants us to handle
51
// enum anyway.
52
return SPV_ENV_OPENGL_4_5;
53
}
54
assert(false && "unexpected target environment or version");
55
return SPV_ENV_VULKAN_1_0;
56
}
57
58
} // anonymous namespace
59
60
bool SpirvToolsDisassemble(Compiler::TargetEnv env,
61
Compiler::TargetEnvVersion version,
62
const std::vector<uint32_t>& binary,
63
std::string* text_or_error) {
64
spvtools::SpirvTools tools(GetSpirvToolsTargetEnv(env, version));
65
std::ostringstream oss;
66
tools.SetMessageConsumer([&oss](spv_message_level_t, const char*,
67
const spv_position_t& position,
68
const char* message) {
69
oss << position.index << ": " << message;
70
});
71
const bool success =
72
tools.Disassemble(binary, text_or_error,
73
SPV_BINARY_TO_TEXT_OPTION_INDENT |
74
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
75
if (!success) {
76
*text_or_error = oss.str();
77
}
78
return success;
79
}
80
81
bool SpirvToolsAssemble(Compiler::TargetEnv env,
82
Compiler::TargetEnvVersion version,
83
const string_piece assembly, spv_binary* binary,
84
std::string* errors) {
85
auto spvtools_context =
86
spvContextCreate(GetSpirvToolsTargetEnv(env, version));
87
spv_diagnostic spvtools_diagnostic = nullptr;
88
89
*binary = nullptr;
90
errors->clear();
91
92
const bool success =
93
spvTextToBinary(spvtools_context, assembly.data(), assembly.size(),
94
binary, &spvtools_diagnostic) == SPV_SUCCESS;
95
if (!success) {
96
std::ostringstream oss;
97
oss << spvtools_diagnostic->position.line + 1 << ":"
98
<< spvtools_diagnostic->position.column + 1 << ": "
99
<< spvtools_diagnostic->error;
100
*errors = oss.str();
101
}
102
103
spvDiagnosticDestroy(spvtools_diagnostic);
104
spvContextDestroy(spvtools_context);
105
106
return success;
107
}
108
109
bool SpirvToolsOptimize(Compiler::TargetEnv env,
110
Compiler::TargetEnvVersion version,
111
const std::vector<PassId>& enabled_passes,
112
spvtools::OptimizerOptions& optimizer_options,
113
std::vector<uint32_t>* binary, std::string* errors) {
114
errors->clear();
115
if (enabled_passes.empty()) return true;
116
if (std::all_of(
117
enabled_passes.cbegin(), enabled_passes.cend(),
118
[](const PassId& pass) { return pass == PassId::kNullPass; })) {
119
return true;
120
}
121
122
spvtools::ValidatorOptions val_opts;
123
// This allows flexible memory layout for HLSL.
124
val_opts.SetSkipBlockLayout(true);
125
// This allows HLSL legalization regarding resources.
126
val_opts.SetRelaxLogicalPointer(true);
127
// This uses relaxed rules for pre-legalized HLSL.
128
val_opts.SetBeforeHlslLegalization(true);
129
130
// Set additional optimizer options.
131
optimizer_options.set_validator_options(val_opts);
132
optimizer_options.set_run_validator(true);
133
134
spvtools::Optimizer optimizer(GetSpirvToolsTargetEnv(env, version));
135
136
std::ostringstream oss;
137
optimizer.SetMessageConsumer(
138
[&oss](spv_message_level_t, const char*, const spv_position_t&,
139
const char* message) { oss << message << "\n"; });
140
141
for (const auto& pass : enabled_passes) {
142
switch (pass) {
143
case PassId::kLegalizationPasses:
144
optimizer.RegisterLegalizationPasses();
145
break;
146
case PassId::kPerformancePasses:
147
optimizer.RegisterPerformancePasses();
148
break;
149
case PassId::kSizePasses:
150
optimizer.RegisterSizePasses();
151
break;
152
case PassId::kNullPass:
153
// We actually don't need to do anything for null pass.
154
break;
155
case PassId::kStripDebugInfo:
156
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
157
break;
158
case PassId::kCompactIds:
159
optimizer.RegisterPass(spvtools::CreateCompactIdsPass());
160
break;
161
}
162
}
163
164
if (!optimizer.Run(binary->data(), binary->size(), binary,
165
optimizer_options)) {
166
*errors = oss.str();
167
return false;
168
}
169
return true;
170
}
171
172
} // namespace shaderc_util
173
174