Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
spirv_compiler.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <array>
8
12
13namespace impeller {
14namespace compiler {
15
17 std::shared_ptr<const fml::Mapping> sources)
18 : options_(options), sources_(std::move(sources)) {}
19
21
22std::shared_ptr<fml::Mapping> SPIRVCompiler::CompileToSPV(
23 std::stringstream& stream,
24 const shaderc::CompileOptions& spirv_options) const {
25 if (!sources_ || sources_->GetMapping() == nullptr) {
26 COMPILER_ERROR(stream) << "Invalid sources for SPIRV Compiler.";
27 return nullptr;
28 }
29
30 shaderc::Compiler spv_compiler;
31 if (!spv_compiler.IsValid()) {
32 COMPILER_ERROR(stream) << "Could not initialize the "
34 << " to SPIRV compiler.";
35 return nullptr;
36 }
37
38 const auto shader_kind = ToShaderCShaderKind(options_.type);
39
40 if (shader_kind == shaderc_shader_kind::shaderc_glsl_infer_from_source) {
41 COMPILER_ERROR(stream) << "Could not figure out shader stage.";
42 return nullptr;
43 }
44
45 auto result = std::make_shared<shaderc::SpvCompilationResult>(
46 spv_compiler.CompileGlslToSpv(
47 reinterpret_cast<const char*>(sources_->GetMapping()), // source_text
48 sources_->GetSize(), // source_text_size
49 shader_kind, // shader_kind
50 Utf8FromPath(options_.file_name).c_str(), // input_file_name
51 options_.entry_point_name.c_str(), // entry_point_name
52 spirv_options // options
53 ));
54 if (result->GetCompilationStatus() !=
55 shaderc_compilation_status::shaderc_compilation_status_success) {
57 << " to SPIRV failed; "
59 result->GetCompilationStatus())
60 << ". " << result->GetNumErrors() << " error(s) and "
61 << result->GetNumWarnings() << " warning(s).";
62 // It should normally be enough to check that there are errors or warnings,
63 // but some cases result in no errors or warnings and still have an error
64 // message. If there's a message we should print it.
65 if (result->GetNumErrors() > 0 || result->GetNumWarnings() > 0 ||
66 !result->GetErrorMessage().empty()) {
67 COMPILER_ERROR_NO_PREFIX(stream) << result->GetErrorMessage();
68 }
69 return nullptr;
70 }
71
72 if (!result) {
73 COMPILER_ERROR(stream) << "Could not fetch SPIRV from compile job.";
74 return nullptr;
75 }
76
77 const auto data_length = (result->cend() - result->cbegin()) *
78 sizeof(decltype(result)::element_type::element_type);
79
80 return std::make_unique<fml::NonOwnedMapping>(
81 reinterpret_cast<const uint8_t*>(result->cbegin()), //
82 data_length, //
83 [result](auto, auto) {} //
84 );
85}
86
87std::string SPIRVCompiler::GetSourcePrefix() const {
88 std::stringstream stream;
89 stream << options_.file_name << ": ";
90 return stream.str();
91}
92
93static void SetDefaultLimitations(shaderc::CompileOptions& compiler_opts) {
94 using Limit = std::pair<shaderc_limit, int>;
95 static constexpr std::array<Limit, 83> limits = {
96 Limit{shaderc_limit::shaderc_limit_max_lights, 8},
97 Limit{shaderc_limit::shaderc_limit_max_clip_planes, 6},
98 Limit{shaderc_limit::shaderc_limit_max_texture_units, 2},
99 Limit{shaderc_limit::shaderc_limit_max_texture_coords, 8},
100 Limit{shaderc_limit::shaderc_limit_max_vertex_attribs, 16},
101 Limit{shaderc_limit::shaderc_limit_max_vertex_uniform_components, 4096},
102 Limit{shaderc_limit::shaderc_limit_max_varying_floats, 60},
103 Limit{shaderc_limit::shaderc_limit_max_vertex_texture_image_units, 16},
104 Limit{shaderc_limit::shaderc_limit_max_combined_texture_image_units, 80},
105 Limit{shaderc_limit::shaderc_limit_max_texture_image_units, 16},
106 Limit{shaderc_limit::shaderc_limit_max_fragment_uniform_components, 1024},
107 Limit{shaderc_limit::shaderc_limit_max_draw_buffers, 8},
108 Limit{shaderc_limit::shaderc_limit_max_vertex_uniform_vectors, 256},
109 Limit{shaderc_limit::shaderc_limit_max_varying_vectors, 15},
110 Limit{shaderc_limit::shaderc_limit_max_fragment_uniform_vectors, 256},
111 Limit{shaderc_limit::shaderc_limit_max_vertex_output_vectors, 16},
112 Limit{shaderc_limit::shaderc_limit_max_fragment_input_vectors, 15},
113 Limit{shaderc_limit::shaderc_limit_min_program_texel_offset, -8},
114 Limit{shaderc_limit::shaderc_limit_max_program_texel_offset, 7},
115 Limit{shaderc_limit::shaderc_limit_max_clip_distances, 8},
116 Limit{shaderc_limit::shaderc_limit_max_compute_work_group_count_x, 65535},
117 Limit{shaderc_limit::shaderc_limit_max_compute_work_group_count_y, 65535},
118 Limit{shaderc_limit::shaderc_limit_max_compute_work_group_count_z, 65535},
119 Limit{shaderc_limit::shaderc_limit_max_compute_work_group_size_x, 1024},
120 Limit{shaderc_limit::shaderc_limit_max_compute_work_group_size_y, 1024},
121 Limit{shaderc_limit::shaderc_limit_max_compute_work_group_size_z, 64},
122 Limit{shaderc_limit::shaderc_limit_max_compute_uniform_components, 512},
123 Limit{shaderc_limit::shaderc_limit_max_compute_texture_image_units, 16},
124 Limit{shaderc_limit::shaderc_limit_max_compute_image_uniforms, 8},
125 Limit{shaderc_limit::shaderc_limit_max_compute_atomic_counters, 8},
126 Limit{shaderc_limit::shaderc_limit_max_compute_atomic_counter_buffers, 1},
127 Limit{shaderc_limit::shaderc_limit_max_varying_components, 60},
128 Limit{shaderc_limit::shaderc_limit_max_vertex_output_components, 64},
129 Limit{shaderc_limit::shaderc_limit_max_geometry_input_components, 64},
130 Limit{shaderc_limit::shaderc_limit_max_geometry_output_components, 128},
131 Limit{shaderc_limit::shaderc_limit_max_fragment_input_components, 128},
132 Limit{shaderc_limit::shaderc_limit_max_image_units, 8},
133 Limit{shaderc_limit::
134 shaderc_limit_max_combined_image_units_and_fragment_outputs,
135 8},
136 Limit{shaderc_limit::shaderc_limit_max_combined_shader_output_resources,
137 8},
138 Limit{shaderc_limit::shaderc_limit_max_image_samples, 0},
139 Limit{shaderc_limit::shaderc_limit_max_vertex_image_uniforms, 0},
140 Limit{shaderc_limit::shaderc_limit_max_tess_control_image_uniforms, 0},
141 Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_image_uniforms, 0},
142 Limit{shaderc_limit::shaderc_limit_max_geometry_image_uniforms, 0},
143 Limit{shaderc_limit::shaderc_limit_max_fragment_image_uniforms, 8},
144 Limit{shaderc_limit::shaderc_limit_max_combined_image_uniforms, 8},
145 Limit{shaderc_limit::shaderc_limit_max_geometry_texture_image_units, 16},
146 Limit{shaderc_limit::shaderc_limit_max_geometry_output_vertices, 256},
147 Limit{shaderc_limit::shaderc_limit_max_geometry_total_output_components,
148 1024},
149 Limit{shaderc_limit::shaderc_limit_max_geometry_uniform_components, 512},
150 Limit{shaderc_limit::shaderc_limit_max_geometry_varying_components, 60},
151 Limit{shaderc_limit::shaderc_limit_max_tess_control_input_components,
152 128},
153 Limit{shaderc_limit::shaderc_limit_max_tess_control_output_components,
154 128},
155 Limit{shaderc_limit::shaderc_limit_max_tess_control_texture_image_units,
156 16},
157 Limit{shaderc_limit::shaderc_limit_max_tess_control_uniform_components,
158 1024},
159 Limit{
160 shaderc_limit::shaderc_limit_max_tess_control_total_output_components,
161 4096},
162 Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_input_components,
163 128},
164 Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_output_components,
165 128},
166 Limit{
167 shaderc_limit::shaderc_limit_max_tess_evaluation_texture_image_units,
168 16},
169 Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_uniform_components,
170 1024},
171 Limit{shaderc_limit::shaderc_limit_max_tess_patch_components, 120},
172 Limit{shaderc_limit::shaderc_limit_max_patch_vertices, 32},
173 Limit{shaderc_limit::shaderc_limit_max_tess_gen_level, 64},
174 Limit{shaderc_limit::shaderc_limit_max_viewports, 16},
175 Limit{shaderc_limit::shaderc_limit_max_vertex_atomic_counters, 0},
176 Limit{shaderc_limit::shaderc_limit_max_tess_control_atomic_counters, 0},
177 Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_atomic_counters,
178 0},
179 Limit{shaderc_limit::shaderc_limit_max_geometry_atomic_counters, 0},
180 Limit{shaderc_limit::shaderc_limit_max_fragment_atomic_counters, 8},
181 Limit{shaderc_limit::shaderc_limit_max_combined_atomic_counters, 8},
182 Limit{shaderc_limit::shaderc_limit_max_atomic_counter_bindings, 1},
183 Limit{shaderc_limit::shaderc_limit_max_vertex_atomic_counter_buffers, 0},
184 Limit{
185 shaderc_limit::shaderc_limit_max_tess_control_atomic_counter_buffers,
186 0},
187 Limit{shaderc_limit::
188 shaderc_limit_max_tess_evaluation_atomic_counter_buffers,
189 0},
190 Limit{shaderc_limit::shaderc_limit_max_geometry_atomic_counter_buffers,
191 0},
192 Limit{shaderc_limit::shaderc_limit_max_fragment_atomic_counter_buffers,
193 0},
194 Limit{shaderc_limit::shaderc_limit_max_combined_atomic_counter_buffers,
195 1},
196 Limit{shaderc_limit::shaderc_limit_max_atomic_counter_buffer_size, 32},
197 Limit{shaderc_limit::shaderc_limit_max_transform_feedback_buffers, 4},
198 Limit{shaderc_limit::
199 shaderc_limit_max_transform_feedback_interleaved_components,
200 64},
201 Limit{shaderc_limit::shaderc_limit_max_cull_distances, 8},
202 Limit{shaderc_limit::shaderc_limit_max_combined_clip_and_cull_distances,
203 8},
204 Limit{shaderc_limit::shaderc_limit_max_samples, 4},
205 };
206 for (auto& [limit, value] : limits) {
207 compiler_opts.SetLimit(limit, value);
208 }
209}
210
211static void SetBindingBaseOffset(shaderc::CompileOptions& options) {
212 constexpr uint32_t kBindingBaseOffset = 64;
213 static const shaderc_uniform_kind kUniformKinds[] = {
214 shaderc_uniform_kind::shaderc_uniform_kind_sampler,
215 shaderc_uniform_kind::shaderc_uniform_kind_texture,
216 shaderc_uniform_kind::shaderc_uniform_kind_image,
217 shaderc_uniform_kind::shaderc_uniform_kind_buffer, // UBOs
218 shaderc_uniform_kind::shaderc_uniform_kind_storage_buffer, // SSBOs
219 };
220
221 for (size_t i = 0u; i < sizeof(kUniformKinds) / sizeof(shaderc_uniform_kind);
222 i++) {
223 options.SetBindingBaseForStage(
224 shaderc_shader_kind::shaderc_fragment_shader, //
225 kUniformKinds[i], //
226 kBindingBaseOffset //
227 );
228 }
229}
230
231//------------------------------------------------------------------------------
232/// @brief Wraps a shared includer so unique includers may be created to
233/// satisfy the shaderc API. This is a simple proxy object and does
234/// nothing.
235///
236class UniqueIncluder final : public shaderc::CompileOptions::IncluderInterface {
237 public:
238 static std::unique_ptr<UniqueIncluder> Make(
239 std::shared_ptr<Includer> includer) {
240 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
241 return std::unique_ptr<UniqueIncluder>(
242 new UniqueIncluder(std::move(includer)));
243 }
244
245 // |shaderc::CompileOptions::IncluderInterface|
246 ~UniqueIncluder() = default;
247
248 // |shaderc::CompileOptions::IncluderInterface|
249 shaderc_include_result* GetInclude(const char* requested_source,
250 shaderc_include_type type,
251 const char* requesting_source,
252 size_t include_depth) override {
253 return includer_->GetInclude(requested_source, //
254 type, //
255 requesting_source, //
256 include_depth //
257 );
258 }
259
260 // |shaderc::CompileOptions::IncluderInterface|
261 void ReleaseInclude(shaderc_include_result* data) override {
262 return includer_->ReleaseInclude(data);
263 }
264
265 private:
266 std::shared_ptr<Includer> includer_;
267
268 explicit UniqueIncluder(std::shared_ptr<Includer> includer)
269 : includer_(std::move(includer)) {
270 FML_CHECK(includer_);
271 }
272
273 UniqueIncluder(const UniqueIncluder&) = delete;
274
275 UniqueIncluder& operator=(const UniqueIncluder&) = delete;
276};
277
278shaderc::CompileOptions SPIRVCompilerOptions::BuildShadercOptions() const {
279 shaderc::CompileOptions options;
280
281 SetDefaultLimitations(options);
282 SetBindingBaseOffset(options);
283
284 options.SetAutoBindUniforms(true);
285 options.SetAutoMapLocations(true);
286 options.SetPreserveBindings(true);
287
288 options.SetOptimizationLevel(optimization_level);
289
291 options.SetGenerateDebugInfo();
292 }
293
294 if (source_langauge.has_value()) {
295 options.SetSourceLanguage(source_langauge.value());
296 }
297
298 if (source_profile.has_value()) {
299 options.SetForcedVersionProfile(source_profile->version,
300 source_profile->profile);
301 }
302
303 if (target.has_value()) {
304 options.SetTargetEnvironment(target->env, target->version);
305 options.SetTargetSpirv(target->spirv_version);
306 }
307
308 for (const auto& macro : macro_definitions) {
309 options.AddMacroDefinition(macro);
310 }
311
312 if (includer) {
313 options.SetIncluder(UniqueIncluder::Make(includer));
314 }
315
316 options.SetVulkanRulesRelaxed(relaxed_vulkan_rules);
317
318 return options;
319}
320
321} // namespace compiler
322} // namespace impeller
GLenum type
std::shared_ptr< fml::Mapping > CompileToSPV(std::stringstream &error_stream, const shaderc::CompileOptions &spirv_options) const
SPIRVCompiler(const SourceOptions &options, std::shared_ptr< const fml::Mapping > sources)
Wraps a shared includer so unique includers may be created to satisfy the shaderc API....
void ReleaseInclude(shaderc_include_result *data) override
shaderc_include_result * GetInclude(const char *requested_source, shaderc_include_type type, const char *requesting_source, size_t include_depth) override
static std::unique_ptr< UniqueIncluder > Make(std::shared_ptr< Includer > includer)
int32_t value
#define FML_CHECK(condition)
Definition logging.h:104
#define COMPILER_ERROR_NO_PREFIX(stream)
Definition logger.h:42
#define COMPILER_ERROR(stream)
Definition logger.h:39
std::string SourceLanguageToString(SourceLanguage source_language)
Definition types.cc:90
static void SetBindingBaseOffset(shaderc::CompileOptions &options)
shaderc_shader_kind ToShaderCShaderKind(SourceType type)
Definition types.cc:174
static void SetDefaultLimitations(shaderc::CompileOptions &compiler_opts)
std::string ShaderCErrorToString(shaderc_compilation_status status)
Definition types.cc:149
std::string Utf8FromPath(const std::filesystem::path &path)
Converts a native format path to a utf8 string.
Definition utilities.cc:30
Definition ref_ptr.h:261
std::optional< shaderc_source_language > source_langauge
std::vector< std::string > macro_definitions
shaderc_optimization_level optimization_level
std::optional< SPIRVCompilerSourceProfile > source_profile
std::shared_ptr< Includer > includer
shaderc::CompileOptions BuildShadercOptions() const
std::optional< SPIRVCompilerTargetEnv > target
std::filesystem::path file_name
std::shared_ptr< const fml::Mapping > data