Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
impeller::compiler::Compiler Class Reference

#include <compiler.h>

Public Member Functions

 Compiler (const std::shared_ptr< const fml::Mapping > &source_mapping, const SourceOptions &options, Reflector::Options reflector_options)
 
 ~Compiler ()
 
bool IsValid () const
 
std::shared_ptr< fml::MappingGetSPIRVAssembly () const
 
std::shared_ptr< fml::MappingGetSLShaderSource () const
 
std::string GetErrorMessages () const
 
std::string GetVerboseErrorMessages () const
 
const std::vector< std::string > & GetIncludedFileNames () const
 
std::unique_ptr< fml::MappingCreateDepfileContents (std::initializer_list< std::string > targets) const
 
const ReflectorGetReflector () const
 

Detailed Description

Definition at line 25 of file compiler.h.

Constructor & Destructor Documentation

◆ Compiler()

impeller::compiler::Compiler::Compiler ( const std::shared_ptr< const fml::Mapping > &  source_mapping,
const SourceOptions options,
Reflector::Options  reflector_options 
)

Definition at line 402 of file compiler.cc.

405 : options_(source_options) {
406 if (!source_mapping || source_mapping->GetMapping() == nullptr) {
407 COMPILER_ERROR(error_stream_)
408 << "Could not read shader source or shader source was empty.";
409 return;
410 }
411
412 if (source_options.target_platform == TargetPlatform::kUnknown) {
413 COMPILER_ERROR(error_stream_) << "Target platform not specified.";
414 return;
415 }
416
417 SPIRVCompilerOptions spirv_options;
418
419 // Make sure reflection is as effective as possible. The generated shaders
420 // will be processed later by backend specific compilers.
421 spirv_options.generate_debug_info = true;
422
423 switch (options_.source_language) {
425 // Expects GLSL 4.60 (Core Profile).
426 // https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf
427 spirv_options.source_langauge =
428 shaderc_source_language::shaderc_source_language_glsl;
429 spirv_options.source_profile = SPIRVCompilerSourceProfile{
430 shaderc_profile::shaderc_profile_core, //
431 460, //
432 };
433 break;
435 spirv_options.source_langauge =
436 shaderc_source_language::shaderc_source_language_hlsl;
437 break;
439 COMPILER_ERROR(error_stream_) << "Source language invalid.";
440 return;
441 }
442
443 switch (source_options.target_platform) {
446 SPIRVCompilerTargetEnv target;
447
448 if (source_options.use_half_textures) {
449 target.env = shaderc_target_env::shaderc_target_env_opengl;
450 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
451 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
452 } else {
453 target.env = shaderc_target_env::shaderc_target_env_vulkan;
454 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
455 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
456 }
457
458 spirv_options.target = target;
459 } break;
464 SPIRVCompilerTargetEnv target;
465
466 target.env = shaderc_target_env::shaderc_target_env_vulkan;
467 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
468 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
469
470 if (source_options.target_platform ==
472 spirv_options.macro_definitions.push_back("IMPELLER_GRAPHICS_BACKEND");
473 spirv_options.relaxed_vulkan_rules = true;
474 }
475 spirv_options.target = target;
476 } break;
480 SPIRVCompilerTargetEnv target;
481
482 target.env = shaderc_target_env::shaderc_target_env_opengl;
483 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
484 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
485
486 spirv_options.target = target;
487 spirv_options.macro_definitions.push_back("IMPELLER_GRAPHICS_BACKEND");
488 if (source_options.target_platform == TargetPlatform::kRuntimeStageGLES ||
489 source_options.target_platform ==
491 spirv_options.macro_definitions.push_back("IMPELLER_TARGET_OPENGLES");
492 // A temporary macro that allows fragment shader authors to target
493 // Flutter <= 3.44 before the OpenGLES flip was removed.
494 spirv_options.macro_definitions.push_back(
495 "IMPELLER_OPENGLES_UNFLIPPED_DEPRECATED");
496 }
497 } break;
499 SPIRVCompilerTargetEnv target;
500
501 target.env = shaderc_target_env::shaderc_target_env_opengl;
502 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
503 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
504
505 // When any optimization level above 'zero' is enabled, the phi merges at
506 // loop continue blocks are rendered using syntax that is supported in
507 // GLSL, but not in SkSL.
508 // https://bugs.chromium.org/p/skia/issues/detail?id=13518.
509 spirv_options.optimization_level =
510 shaderc_optimization_level::shaderc_optimization_level_zero;
511 spirv_options.target = target;
512 spirv_options.macro_definitions.push_back("SKIA_GRAPHICS_BACKEND");
513 } break;
515 COMPILER_ERROR(error_stream_) << "Target platform invalid.";
516 return;
517 }
518
519 // Implicit definition that indicates that this compilation is for the device
520 // (instead of the host).
521 spirv_options.macro_definitions.push_back("IMPELLER_DEVICE");
522 for (const auto& define : source_options.defines) {
523 spirv_options.macro_definitions.push_back(define);
524 }
525
526 std::vector<std::string> included_file_names;
527 spirv_options.includer = std::make_shared<Includer>(
528 options_.working_directory, options_.include_dirs,
529 [&included_file_names](auto included_name) {
530 included_file_names.emplace_back(std::move(included_name));
531 });
532
533 // SPIRV Generation.
534 SPIRVCompiler spv_compiler(source_options, source_mapping);
535
536 spirv_assembly_ = spv_compiler.CompileToSPV(
537 error_stream_, spirv_options.BuildShadercOptions());
538
539 if (!spirv_assembly_) {
540 return;
541 } else {
542 included_file_names_ = std::move(included_file_names);
543 }
544
545 // SL Generation.
546 spirv_cross::Parser parser(
547 reinterpret_cast<const uint32_t*>(spirv_assembly_->GetMapping()),
548 spirv_assembly_->GetSize() / sizeof(uint32_t));
549 // The parser and compiler must be run separately because the parser contains
550 // meta information (like type member names) that are useful for reflection.
551 parser.parse();
552
553 const auto parsed_ir =
554 std::make_shared<spirv_cross::ParsedIR>(parser.get_parsed_ir());
555
556 auto sl_compiler = CreateCompiler(*parsed_ir, options_);
557
558 if (!sl_compiler) {
559 COMPILER_ERROR(error_stream_)
560 << "Could not create compiler for target platform.";
561 return;
562 }
563
564 CanonicalizeUniformBlockInstanceNamesForGL(source_options.target_platform,
565 sl_compiler.GetCompiler());
566
567 uint32_t ubo_size = CalculateUBOSize(sl_compiler.GetCompiler());
568 if (ubo_size > kMaxUniformBufferSize) {
569 COMPILER_ERROR(error_stream_) << "Uniform buffer size exceeds max ("
570 << kMaxUniformBufferSize << "): " << ubo_size;
571 return;
572 }
573
574 // We need to invoke the compiler even if we don't use the SL mapping later
575 // for Vulkan. The reflector needs information that is only valid after a
576 // successful compilation call.
577 auto sl_compilation_result_str = sl_compiler.GetCompiler()->compile();
578
579 // GL vertex shaders get a y-flip epilogue; see
580 // https://github.com/flutter/flutter/issues/186554.
581 if (IsGLTargetPlatform(source_options.target_platform) &&
582 source_options.type == SourceType::kVertexShader) {
583 sl_compilation_result_str =
584 InjectYFlipForGLESVertexShader(std::move(sl_compilation_result_str));
585 }
586
587 auto sl_compilation_result =
588 CreateMappingWithString(sl_compilation_result_str);
589
590 // If the target is Vulkan, our shading language is SPIRV which we already
591 // have. We just need to strip it of debug information. If it isn't, we need
592 // to invoke the appropriate compiler to compile the SPIRV to the target SL.
593 if (source_options.target_platform == TargetPlatform::kVulkan ||
594 source_options.target_platform == TargetPlatform::kRuntimeStageVulkan) {
595 auto stripped_spirv_options = spirv_options;
596 stripped_spirv_options.generate_debug_info = false;
597 sl_mapping_ = spv_compiler.CompileToSPV(
598 error_stream_, stripped_spirv_options.BuildShadercOptions());
599 } else {
600 sl_mapping_ = sl_compilation_result;
601 }
602
603 if (!sl_mapping_) {
604 COMPILER_ERROR(error_stream_) << "Could not generate SL from SPIRV";
605 return;
606 }
607
608 if (sl_compiler.GetType() == CompilerBackend::Type::kSkSL &&
609 !ValidateSkSLResult(sl_compilation_result_str).ok()) {
610 return;
611 }
612
613 reflector_ = std::make_unique<Reflector>(std::move(reflector_options), //
614 parsed_ir, //
616 sl_compiler //
617 );
618
619 if (!reflector_->IsValid()) {
620 COMPILER_ERROR(error_stream_)
621 << "Could not complete reflection on generated shader.";
622 return;
623 }
624
625 is_valid_ = true;
626}
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
Definition compiler.cc:687
uint32_t * target
#define COMPILER_ERROR(stream)
Definition logger.h:39
static const uint32_t kMaxUniformBufferSize
Definition compiler.cc:103
static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
Definition compiler.cc:306
std::shared_ptr< fml::Mapping > CreateMappingWithString(std::string string)
Creates a mapping with string data.
std::vector< IncludeDir > include_dirs
std::shared_ptr< fml::UniqueFD > working_directory

References impeller::compiler::SPIRVCompilerOptions::BuildShadercOptions(), COMPILER_ERROR, impeller::compiler::SPIRVCompiler::CompileToSPV(), impeller::compiler::CreateCompiler(), impeller::CreateMappingWithString(), impeller::compiler::SourceOptions::defines, impeller::compiler::SPIRVCompilerTargetEnv::env, impeller::compiler::SPIRVCompilerOptions::generate_debug_info, GetSLShaderSource(), impeller::compiler::SourceOptions::include_dirs, impeller::compiler::SPIRVCompilerOptions::includer, impeller::compiler::kGLSL, impeller::compiler::kHLSL, impeller::compiler::kMaxUniformBufferSize, impeller::compiler::kMetalDesktop, impeller::compiler::kMetalIOS, impeller::compiler::kOpenGLDesktop, impeller::compiler::kOpenGLES, impeller::compiler::kRuntimeStageGLES, impeller::compiler::kRuntimeStageGLES3, impeller::compiler::kRuntimeStageMetal, impeller::compiler::kRuntimeStageVulkan, impeller::compiler::CompilerBackend::kSkSL, impeller::compiler::kSkSL, impeller::compiler::kUnknown, impeller::compiler::kVertexShader, impeller::compiler::kVulkan, impeller::compiler::SPIRVCompilerOptions::macro_definitions, impeller::compiler::SPIRVCompilerOptions::optimization_level, impeller::compiler::SPIRVCompilerOptions::relaxed_vulkan_rules, impeller::compiler::SPIRVCompilerOptions::source_langauge, impeller::compiler::SourceOptions::source_language, impeller::compiler::SPIRVCompilerOptions::source_profile, impeller::compiler::SPIRVCompilerOptions::target, target, impeller::compiler::SourceOptions::target_platform, impeller::compiler::SourceOptions::type, impeller::compiler::SourceOptions::use_half_textures, and impeller::compiler::SourceOptions::working_directory.

◆ ~Compiler()

impeller::compiler::Compiler::~Compiler ( )
default

Member Function Documentation

◆ CreateDepfileContents()

std::unique_ptr< fml::Mapping > impeller::compiler::Compiler::CreateDepfileContents ( std::initializer_list< std::string >  targets) const

Definition at line 733 of file compiler.cc.

734 {
735 // https://github.com/ninja-build/ninja/blob/master/src/depfile_parser.cc#L28
736 const auto targets = JoinStrings(targets_names, " ");
737 const auto dependencies = GetDependencyNames(" ");
738
739 std::stringstream stream;
740 stream << targets << ": " << dependencies << "\n";
741
742 auto contents = std::make_shared<std::string>(stream.str());
743 return std::make_unique<fml::NonOwnedMapping>(
744 reinterpret_cast<const uint8_t*>(contents->data()), contents->size(),
745 [contents](auto, auto) {});
746}
static std::string JoinStrings(std::vector< std::string > items, const std::string &separator)
Definition compiler.cc:713

References impeller::compiler::JoinStrings().

◆ GetErrorMessages()

std::string impeller::compiler::Compiler::GetErrorMessages ( ) const

Definition at line 701 of file compiler.cc.

701 {
702 return error_stream_.str();
703}

Referenced by impeller::compiler::GenerateShaderBackendFB(), and impeller::compiler::testing::TEST_P().

◆ GetIncludedFileNames()

const std::vector< std::string > & impeller::compiler::Compiler::GetIncludedFileNames ( ) const

Definition at line 709 of file compiler.cc.

709 {
710 return included_file_names_;
711}

Referenced by impeller::compiler::GenerateShaderBackendFB().

◆ GetReflector()

const Reflector * impeller::compiler::Compiler::GetReflector ( ) const

Definition at line 748 of file compiler.cc.

748 {
749 return reflector_.get();
750}

Referenced by impeller::compiler::GenerateShaderBackendFB().

◆ GetSLShaderSource()

std::shared_ptr< fml::Mapping > impeller::compiler::Compiler::GetSLShaderSource ( ) const

Definition at line 687 of file compiler.cc.

687 {
688 return sl_mapping_;
689}

Referenced by Compiler(), impeller::compiler::testing::TEST(), and impeller::compiler::testing::TEST().

◆ GetSPIRVAssembly()

std::shared_ptr< fml::Mapping > impeller::compiler::Compiler::GetSPIRVAssembly ( ) const

Definition at line 683 of file compiler.cc.

683 {
684 return spirv_assembly_;
685}

Referenced by impeller::compiler::testing::TEST(), and impeller::compiler::testing::TEST().

◆ GetVerboseErrorMessages()

std::string impeller::compiler::Compiler::GetVerboseErrorMessages ( ) const

Gets verbose error messages if available.

This is only populated when GetErrorMessages() returns a truncated error message. If GetErrorMessages() did not have to be truncated, this will return an empty string.

Definition at line 705 of file compiler.cc.

705 {
706 return verbose_error_stream_.str();
707}

Referenced by impeller::compiler::testing::TEST_P().

◆ IsValid()

bool impeller::compiler::Compiler::IsValid ( ) const

Definition at line 691 of file compiler.cc.

691 {
692 return is_valid_;
693}

Referenced by impeller::compiler::GenerateShaderBackendFB(), impeller::compiler::testing::TEST(), and impeller::compiler::testing::TEST().


The documentation for this class was generated from the following files: