Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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 <cstdint>
8#include <filesystem>
9#include <memory>
10#include <optional>
11#include <sstream>
12#include <string>
13#include <string_view>
14#include <utility>
15
16#include "flutter/fml/paths.h"
26#include "third_party/skia/include/core/SkString.h"
27#include "third_party/skia/include/effects/SkRuntimeEffect.h"
28
29namespace impeller {
30namespace compiler {
31
32namespace {
33constexpr const char* kEGLImageExternalExtension = "GL_OES_EGL_image_external";
34constexpr const char* kEGLImageExternalExtension300 =
35 "GL_OES_EGL_image_external_essl3";
36constexpr int kVerboseErrorLineThreshold = 6;
37} // namespace
38
39// This value should be <= 7372. UBOs can be larger on some devices but a
40// performance cost will be paid.
41// https://docs.qualcomm.com/bundle/publicresource/topics/80-78185-2/best_practices.html?product=1601111740035277#buffer-best-practices
42static const uint32_t kMaxUniformBufferSize = 6208;
43
44static uint32_t ParseMSLVersion(const std::string& msl_version) {
45 std::stringstream sstream(msl_version);
46 std::string version_part;
47 uint32_t major = 1;
48 uint32_t minor = 2;
49 uint32_t patch = 0;
50 if (std::getline(sstream, version_part, '.')) {
51 major = std::stoi(version_part);
52 if (std::getline(sstream, version_part, '.')) {
53 minor = std::stoi(version_part);
54 if (std::getline(sstream, version_part, '.')) {
55 patch = std::stoi(version_part);
56 }
57 }
58 }
59 if (major < 1 || (major == 1 && minor < 2)) {
60 std::cerr << "--metal-version version must be at least 1.2. Have "
61 << msl_version << std::endl;
62 }
63 return spirv_cross::CompilerMSL::Options::make_msl_version(major, minor,
64 patch);
65}
66
68 const spirv_cross::ParsedIR& ir,
69 const SourceOptions& source_options,
70 std::optional<uint32_t> msl_version_override = {}) {
71 auto sl_compiler = std::make_shared<spirv_cross::CompilerMSL>(ir);
72 spirv_cross::CompilerMSL::Options sl_options;
73 sl_options.platform =
75 sl_options.msl_version = msl_version_override.value_or(
76 ParseMSLVersion(source_options.metal_version));
77 sl_options.ios_use_simdgroup_functions =
78 sl_options.is_ios() &&
79 sl_options.msl_version >=
80 spirv_cross::CompilerMSL::Options::make_msl_version(2, 4, 0);
81 sl_options.use_framebuffer_fetch_subpasses = true;
82 sl_compiler->set_msl_options(sl_options);
83
84 // Sort the float and sampler uniforms according to their declared/decorated
85 // order. For user authored fragment shaders, the API for setting uniform
86 // values uses the index of the uniform in the declared order. By default, the
87 // metal backend of spirv-cross will order uniforms according to usage. To fix
88 // this, we use the sorted order and the add_msl_resource_binding API to force
89 // the ordering to match the declared order. Note that while this code runs
90 // for all compiled shaders, it will only affect vertex and fragment shaders
91 // due to the specified stage.
92 auto floats =
93 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::Float);
94 auto images =
95 SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::SampledImage);
96
97 spv::ExecutionModel execution_model =
98 spv::ExecutionModel::ExecutionModelFragment;
99 if (source_options.type == SourceType::kVertexShader) {
100 execution_model = spv::ExecutionModel::ExecutionModelVertex;
101 }
102
103 uint32_t buffer_offset = 0;
104 uint32_t sampler_offset = 0;
105 for (auto& float_id : floats) {
106 sl_compiler->add_msl_resource_binding(
107 {.stage = execution_model,
108 .basetype = spirv_cross::SPIRType::BaseType::Float,
109 .desc_set = sl_compiler->get_decoration(float_id,
110 spv::DecorationDescriptorSet),
111 .binding =
112 sl_compiler->get_decoration(float_id, spv::DecorationBinding),
113 .count = 1u,
114 .msl_buffer = buffer_offset});
115 buffer_offset++;
116 }
117 for (auto& image_id : images) {
118 sl_compiler->add_msl_resource_binding({
119 .stage = execution_model,
120 .basetype = spirv_cross::SPIRType::BaseType::SampledImage,
121 .desc_set =
122 sl_compiler->get_decoration(image_id, spv::DecorationDescriptorSet),
123 .binding =
124 sl_compiler->get_decoration(image_id, spv::DecorationBinding),
125 .count = 1u,
126 // A sampled image is both an image and a sampler, so both
127 // offsets need to be set or depending on the partiular shader
128 // the bindings may be incorrect.
129 .msl_texture = sampler_offset,
130 .msl_sampler = sampler_offset,
131 });
132 sampler_offset++;
133 }
134
135 return CompilerBackend(sl_compiler);
136}
137
139 const spirv_cross::ParsedIR& ir,
140 const SourceOptions& source_options) {
141 auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
142 spirv_cross::CompilerGLSL::Options sl_options;
143 sl_options.force_zero_initialized_variables = true;
144 sl_options.vertex.fixup_clipspace = true;
145 sl_options.vulkan_semantics = true;
146 gl_compiler->set_common_options(sl_options);
147 return CompilerBackend(gl_compiler);
148}
149
150static CompilerBackend CreateGLSLCompiler(const spirv_cross::ParsedIR& ir,
151 const SourceOptions& source_options) {
152 auto gl_compiler = std::make_shared<spirv_cross::CompilerGLSL>(ir);
153
154 // Walk the variables and insert the external image extension if any of them
155 // begins with the external texture prefix. Unfortunately, we can't walk
156 // `gl_compiler->get_shader_resources().separate_samplers` until the compiler
157 // is further along.
158 //
159 // Unfortunately, we can't just let the shader author add this extension and
160 // use `samplerExternalOES` directly because compiling to spirv requires the
161 // source language profile to be at least 310 ES, but this extension is
162 // incompatible with ES 310+.
163 for (auto& id : ir.ids_for_constant_or_variable) {
164 if (StringStartsWith(ir.get_name(id), kExternalTexturePrefix)) {
165 if (source_options.gles_language_version >= 300) {
166 gl_compiler->require_extension(kEGLImageExternalExtension300);
167 } else {
168 gl_compiler->require_extension(kEGLImageExternalExtension);
169 }
170 break;
171 }
172 }
173
174 spirv_cross::CompilerGLSL::Options sl_options;
175 sl_options.force_zero_initialized_variables = true;
176 sl_options.vertex.fixup_clipspace = true;
177 if (source_options.target_platform == TargetPlatform::kOpenGLES ||
180 sl_options.version = source_options.gles_language_version > 0
181 ? source_options.gles_language_version
182 : 100;
183 sl_options.es = true;
185 sl_options.version = 300;
186 }
187 if (source_options.require_framebuffer_fetch &&
188 source_options.type == SourceType::kFragmentShader) {
189 gl_compiler->remap_ext_framebuffer_fetch(0, 0, true);
190 }
191 gl_compiler->set_variable_type_remap_callback(
192 [&](const spirv_cross::SPIRType& type, const std::string& var_name,
193 std::string& name_of_type) {
195 name_of_type = "samplerExternalOES";
196 }
197 });
198 } else {
199 sl_options.version = source_options.gles_language_version > 0
200 ? source_options.gles_language_version
201 : 120;
202 sl_options.es = false;
203 }
204 gl_compiler->set_common_options(sl_options);
205 return CompilerBackend(gl_compiler);
206}
207
208static CompilerBackend CreateSkSLCompiler(const spirv_cross::ParsedIR& ir,
209 const SourceOptions& source_options) {
210 auto sksl_compiler = std::make_shared<CompilerSkSL>(ir);
211 return CompilerBackend(sksl_compiler);
212}
213
233
234static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR& ir,
235 const SourceOptions& source_options) {
236 CompilerBackend compiler;
237 switch (source_options.target_platform) {
241 compiler = CreateMSLCompiler(ir, source_options);
242 break;
245 compiler = CreateVulkanCompiler(ir, source_options);
246 break;
251 compiler = CreateGLSLCompiler(ir, source_options);
252 break;
254 compiler = CreateSkSLCompiler(ir, source_options);
255 break;
258 }
259 if (!compiler) {
260 return {};
261 }
262 auto* backend = compiler.GetCompiler();
263 if (!EntryPointMustBeNamedMain(source_options.target_platform) &&
264 source_options.source_language == SourceLanguage::kGLSL) {
265 backend->rename_entry_point("main", source_options.entry_point_name,
266 ToExecutionModel(source_options.type));
267 }
268 return compiler;
269}
270
271namespace {
272uint32_t CalculateUBOSize(const spirv_cross::Compiler* compiler) {
273 spirv_cross::ShaderResources resources = compiler->get_shader_resources();
274 uint32_t result = 0;
275 for (const spirv_cross::Resource& ubo : resources.uniform_buffers) {
276 const spirv_cross::SPIRType& ubo_type =
277 compiler->get_type(ubo.base_type_id);
278 uint32_t size = compiler->get_declared_struct_size(ubo_type);
279 result += size;
280 }
281 return result;
282}
283
284// Mirrors BufferBindingsGLES's uniform key normalization: ASCII uppercase
285// and drop underscores. GLSL identifiers are ASCII, so this is locale-safe.
286std::string StripUnderscoresAndUpper(std::string_view name) {
287 std::string result;
288 result.reserve(name.size());
289 for (char ch : name) {
290 if (ch == '_') {
291 continue;
292 }
293 if (ch >= 'a' && ch <= 'z') {
294 result.push_back(static_cast<char>(ch - 'a' + 'A'));
295 } else {
296 result.push_back(ch);
297 }
298 }
299 return result;
300}
301
302// On pre-`#version 140` GL targets, SPIRV-Cross lowers each uniform block to a
303// flat `uniform StructType instanceName;` and BufferBindingsGLES resolves
304// members by the block name modulo `StripUnderscoresAndUpper`. A
305// non-conforming instance name (e.g. `uniform ToonInfo { ... } toon;`) causes
306// every member to silently bind to GL location `-1`. Rename the instance to
307// `_<BlockName>`, which reduces to the block name under the same fold.
308// See flutter/flutter#186393.
309void CanonicalizeUniformBlockInstanceNamesForGL(
310 TargetPlatform target_platform,
311 spirv_cross::Compiler* compiler) {
312 if (target_platform != TargetPlatform::kOpenGLES &&
313 target_platform != TargetPlatform::kOpenGLDesktop) {
314 return;
315 }
316 for (const spirv_cross::Resource& ubo :
317 compiler->get_shader_resources().uniform_buffers) {
318 const std::string block_name = compiler->get_name(ubo.base_type_id);
319 const std::string instance_name = compiler->get_name(ubo.id);
320 if (StripUnderscoresAndUpper(instance_name) ==
321 StripUnderscoresAndUpper(block_name)) {
322 continue;
323 }
324 compiler->set_name(ubo.id, "_" + block_name);
325 }
326}
327
328} // namespace
329
330Compiler::Compiler(const std::shared_ptr<const fml::Mapping>& source_mapping,
331 const SourceOptions& source_options,
332 Reflector::Options reflector_options)
333 : options_(source_options) {
334 if (!source_mapping || source_mapping->GetMapping() == nullptr) {
335 COMPILER_ERROR(error_stream_)
336 << "Could not read shader source or shader source was empty.";
337 return;
338 }
339
340 if (source_options.target_platform == TargetPlatform::kUnknown) {
341 COMPILER_ERROR(error_stream_) << "Target platform not specified.";
342 return;
343 }
344
345 SPIRVCompilerOptions spirv_options;
346
347 // Make sure reflection is as effective as possible. The generated shaders
348 // will be processed later by backend specific compilers.
349 spirv_options.generate_debug_info = true;
350
351 switch (options_.source_language) {
353 // Expects GLSL 4.60 (Core Profile).
354 // https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf
355 spirv_options.source_langauge =
356 shaderc_source_language::shaderc_source_language_glsl;
358 shaderc_profile::shaderc_profile_core, //
359 460, //
360 };
361 break;
363 spirv_options.source_langauge =
364 shaderc_source_language::shaderc_source_language_hlsl;
365 break;
367 COMPILER_ERROR(error_stream_) << "Source language invalid.";
368 return;
369 }
370
371 switch (source_options.target_platform) {
375
376 if (source_options.use_half_textures) {
377 target.env = shaderc_target_env::shaderc_target_env_opengl;
378 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
379 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
380 } else {
381 target.env = shaderc_target_env::shaderc_target_env_vulkan;
382 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
383 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
384 }
385
386 spirv_options.target = target;
387 } break;
393
394 target.env = shaderc_target_env::shaderc_target_env_vulkan;
395 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
396 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
397
398 if (source_options.target_platform ==
400 spirv_options.macro_definitions.push_back("IMPELLER_GRAPHICS_BACKEND");
401 spirv_options.relaxed_vulkan_rules = true;
402 }
403 spirv_options.target = target;
404 } break;
409
410 target.env = shaderc_target_env::shaderc_target_env_opengl;
411 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
412 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
413
414 spirv_options.target = target;
415 spirv_options.macro_definitions.push_back("IMPELLER_GRAPHICS_BACKEND");
417 source_options.target_platform ==
419 spirv_options.macro_definitions.push_back("IMPELLER_TARGET_OPENGLES");
420 }
421 } break;
424
425 target.env = shaderc_target_env::shaderc_target_env_opengl;
426 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
427 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
428
429 // When any optimization level above 'zero' is enabled, the phi merges at
430 // loop continue blocks are rendered using syntax that is supported in
431 // GLSL, but not in SkSL.
432 // https://bugs.chromium.org/p/skia/issues/detail?id=13518.
433 spirv_options.optimization_level =
434 shaderc_optimization_level::shaderc_optimization_level_zero;
435 spirv_options.target = target;
436 spirv_options.macro_definitions.push_back("SKIA_GRAPHICS_BACKEND");
437 } break;
439 COMPILER_ERROR(error_stream_) << "Target platform invalid.";
440 return;
441 }
442
443 // Implicit definition that indicates that this compilation is for the device
444 // (instead of the host).
445 spirv_options.macro_definitions.push_back("IMPELLER_DEVICE");
446 for (const auto& define : source_options.defines) {
447 spirv_options.macro_definitions.push_back(define);
448 }
449
450 std::vector<std::string> included_file_names;
451 spirv_options.includer = std::make_shared<Includer>(
452 options_.working_directory, options_.include_dirs,
453 [&included_file_names](auto included_name) {
454 included_file_names.emplace_back(std::move(included_name));
455 });
456
457 // SPIRV Generation.
458 SPIRVCompiler spv_compiler(source_options, source_mapping);
459
460 spirv_assembly_ = spv_compiler.CompileToSPV(
461 error_stream_, spirv_options.BuildShadercOptions());
462
463 if (!spirv_assembly_) {
464 return;
465 } else {
466 included_file_names_ = std::move(included_file_names);
467 }
468
469 // SL Generation.
470 spirv_cross::Parser parser(
471 reinterpret_cast<const uint32_t*>(spirv_assembly_->GetMapping()),
472 spirv_assembly_->GetSize() / sizeof(uint32_t));
473 // The parser and compiler must be run separately because the parser contains
474 // meta information (like type member names) that are useful for reflection.
475 parser.parse();
476
477 const auto parsed_ir =
478 std::make_shared<spirv_cross::ParsedIR>(parser.get_parsed_ir());
479
480 auto sl_compiler = CreateCompiler(*parsed_ir, options_);
481
482 if (!sl_compiler) {
483 COMPILER_ERROR(error_stream_)
484 << "Could not create compiler for target platform.";
485 return;
486 }
487
488 CanonicalizeUniformBlockInstanceNamesForGL(source_options.target_platform,
489 sl_compiler.GetCompiler());
490
491 uint32_t ubo_size = CalculateUBOSize(sl_compiler.GetCompiler());
492 if (ubo_size > kMaxUniformBufferSize) {
493 COMPILER_ERROR(error_stream_) << "Uniform buffer size exceeds max ("
494 << kMaxUniformBufferSize << "): " << ubo_size;
495 return;
496 }
497
498 // We need to invoke the compiler even if we don't use the SL mapping later
499 // for Vulkan. The reflector needs information that is only valid after a
500 // successful compilation call.
501 auto sl_compilation_result_str = sl_compiler.GetCompiler()->compile();
502 auto sl_compilation_result =
503 CreateMappingWithString(sl_compilation_result_str);
504
505 // If the target is Vulkan, our shading language is SPIRV which we already
506 // have. We just need to strip it of debug information. If it isn't, we need
507 // to invoke the appropriate compiler to compile the SPIRV to the target SL.
508 if (source_options.target_platform == TargetPlatform::kVulkan ||
510 auto stripped_spirv_options = spirv_options;
511 stripped_spirv_options.generate_debug_info = false;
512 sl_mapping_ = spv_compiler.CompileToSPV(
513 error_stream_, stripped_spirv_options.BuildShadercOptions());
514 } else {
515 sl_mapping_ = sl_compilation_result;
516 }
517
518 if (!sl_mapping_) {
519 COMPILER_ERROR(error_stream_) << "Could not generate SL from SPIRV";
520 return;
521 }
522
523 if (sl_compiler.GetType() == CompilerBackend::Type::kSkSL &&
524 !ValidateSkSLResult(sl_compilation_result_str).ok()) {
525 return;
526 }
527
528 reflector_ = std::make_unique<Reflector>(std::move(reflector_options), //
529 parsed_ir, //
531 sl_compiler //
532 );
533
534 if (!reflector_->IsValid()) {
535 COMPILER_ERROR(error_stream_)
536 << "Could not complete reflection on generated shader.";
537 return;
538 }
539
540 is_valid_ = true;
541}
542
543absl::Status Compiler::ValidateSkSLResult(const std::string& sksl) {
544 // Validate compiled SkSL by trying to create a SkRuntimeEffect.
545 SkRuntimeEffect::Result result =
546 SkRuntimeEffect::MakeForShader(SkString(sksl));
547
548 if (result.effect != nullptr) {
549 return absl::OkStatus();
550 }
551
552 // SkSL is invalid. Output the SkSL and the error.
553
554 std::stringstream output;
555 bool is_truncated = false;
556
557 // Lambda to append text to the output stream, truncating if needed.
558 auto append_and_truncate = [&](const std::string& text) {
559 std::stringstream text_stream(text);
560 std::string line;
561 int lines_outputted = 0;
562 while (std::getline(text_stream, line)) {
563 output << "\n " << line;
564 if (++lines_outputted == kVerboseErrorLineThreshold) {
565 break;
566 }
567 }
568 if (lines_outputted == kVerboseErrorLineThreshold) {
569 auto full_line_count = std::count(text.begin(), text.end(), '\n') + 1;
570 output << "\n... (truncated " << full_line_count - lines_outputted
571 << " lines)";
572 is_truncated = true;
573 }
574 };
575
576 output << "\nCompiled to invalid SkSL:";
577 append_and_truncate(sksl);
578 output << "\nSkSL Error:";
579 std::string error_text(result.errorText.c_str());
580 append_and_truncate(error_text);
581
582 // Output maybe-truncated SkSL and error to error_stream_.
583 COMPILER_ERROR(error_stream_) << output.str();
584
585 // If the output was truncated, output the full SkSL and error to
586 // verbose_error_stream_.
587 if (is_truncated) {
588 COMPILER_ERROR(verbose_error_stream_) << "\nCompiled to invalid SkSL:\n"
589 << sksl << "\nSkSL Error:\n"
590 << error_text;
591 }
592
593 return absl::InternalError("SkSL validation failed.");
594}
595
596Compiler::~Compiler() = default;
597
598std::shared_ptr<fml::Mapping> Compiler::GetSPIRVAssembly() const {
599 return spirv_assembly_;
600}
601
602std::shared_ptr<fml::Mapping> Compiler::GetSLShaderSource() const {
603 return sl_mapping_;
604}
605
606bool Compiler::IsValid() const {
607 return is_valid_;
608}
609
610std::string Compiler::GetSourcePrefix() const {
611 std::stringstream stream;
612 stream << options_.file_name << ": ";
613 return stream.str();
614}
615
616std::string Compiler::GetErrorMessages() const {
617 return error_stream_.str();
618}
619
621 return verbose_error_stream_.str();
622}
623
624const std::vector<std::string>& Compiler::GetIncludedFileNames() const {
625 return included_file_names_;
626}
627
628static std::string JoinStrings(std::vector<std::string> items,
629 const std::string& separator) {
630 std::stringstream stream;
631 for (size_t i = 0, count = items.size(); i < count; i++) {
632 const auto is_last = (i == count - 1);
633
634 stream << items[i];
635 if (!is_last) {
636 stream << separator;
637 }
638 }
639 return stream.str();
640}
641
642std::string Compiler::GetDependencyNames(const std::string& separator) const {
643 std::vector<std::string> dependencies = included_file_names_;
644 dependencies.push_back(Utf8FromPath(options_.file_name));
645 return JoinStrings(dependencies, separator);
646}
647
648std::unique_ptr<fml::Mapping> Compiler::CreateDepfileContents(
649 std::initializer_list<std::string> targets_names) const {
650 // https://github.com/ninja-build/ninja/blob/master/src/depfile_parser.cc#L28
651 const auto targets = JoinStrings(targets_names, " ");
652 const auto dependencies = GetDependencyNames(" ");
653
654 std::stringstream stream;
655 stream << targets << ": " << dependencies << "\n";
656
657 auto contents = std::make_shared<std::string>(stream.str());
658 return std::make_unique<fml::NonOwnedMapping>(
659 reinterpret_cast<const uint8_t*>(contents->data()), contents->size(),
660 [contents](auto, auto) {});
661}
662
664 return reflector_.get();
665}
666
667} // namespace compiler
668} // namespace impeller
std::string GetVerboseErrorMessages() const
Definition compiler.cc:620
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
Definition compiler.cc:598
const Reflector * GetReflector() const
Definition compiler.cc:663
Compiler(const std::shared_ptr< const fml::Mapping > &source_mapping, const SourceOptions &options, Reflector::Options reflector_options)
Definition compiler.cc:330
const std::vector< std::string > & GetIncludedFileNames() const
Definition compiler.cc:624
std::unique_ptr< fml::Mapping > CreateDepfileContents(std::initializer_list< std::string > targets) const
Definition compiler.cc:648
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
Definition compiler.cc:602
std::string GetErrorMessages() const
Definition compiler.cc:616
std::shared_ptr< fml::Mapping > CompileToSPV(std::stringstream &error_stream, const shaderc::CompileOptions &spirv_options) const
uint32_t * target
#define FML_UNREACHABLE()
Definition logging.h:128
const char * name
Definition fuchsia.cc:50
std::u16string text
#define COMPILER_ERROR(stream)
Definition logger.h:39
std::array< MockImage, 3 > images
static CompilerBackend CreateSkSLCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
Definition compiler.cc:208
static const uint32_t kMaxUniformBufferSize
Definition compiler.cc:42
static CompilerBackend CreateVulkanCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
Definition compiler.cc:138
constexpr char kExternalTexturePrefix[]
Definition constants.h:11
static bool EntryPointMustBeNamedMain(TargetPlatform platform)
Definition compiler.cc:214
static CompilerBackend CreateMSLCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options, std::optional< uint32_t > msl_version_override={})
Definition compiler.cc:67
static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
Definition compiler.cc:234
std::string Utf8FromPath(const std::filesystem::path &path)
Converts a native format path to a utf8 string.
Definition utilities.cc:30
static std::string JoinStrings(std::vector< std::string > items, const std::string &separator)
Definition compiler.cc:628
spirv_cross::CompilerMSL::Options::Platform TargetPlatformToMSLPlatform(TargetPlatform platform)
Definition types.cc:183
static uint32_t ParseMSLVersion(const std::string &msl_version)
Definition compiler.cc:44
bool StringStartsWith(const std::string &target, const std::string &prefix)
Definition utilities.cc:86
static CompilerBackend CreateGLSLCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
Definition compiler.cc:150
spv::ExecutionModel ToExecutionModel(SourceType type)
Definition types.cc:169
std::vector< spirv_cross::ID > SortUniforms(const spirv_cross::ParsedIR *ir, const spirv_cross::Compiler *compiler, std::optional< spirv_cross::SPIRType::BaseType > type_filter, bool include)
Sorts uniform declarations in an IR according to decoration order.
std::shared_ptr< fml::Mapping > CreateMappingWithString(std::string string)
Creates a mapping with string data.
impeller::ShaderType type
spirv_cross::Compiler * GetCompiler()
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
bool use_half_textures
Whether half-precision textures should be supported, requiring opengl semantics. Only used on metal t...
std::vector< IncludeDir > include_dirs
std::filesystem::path file_name
bool require_framebuffer_fetch
Whether the GLSL framebuffer fetch extension will be required.
std::shared_ptr< fml::UniqueFD > working_directory
std::vector< std::string > defines