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 330 of file compiler.cc.

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;
357 spirv_options.source_profile = SPIRVCompilerSourceProfile{
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) {
374 SPIRVCompilerTargetEnv target;
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;
392 SPIRVCompilerTargetEnv target;
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;
408 SPIRVCompilerTargetEnv target;
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");
416 if (source_options.target_platform == TargetPlatform::kRuntimeStageGLES ||
417 source_options.target_platform ==
419 spirv_options.macro_definitions.push_back("IMPELLER_TARGET_OPENGLES");
420 }
421 } break;
423 SPIRVCompilerTargetEnv target;
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 ||
509 source_options.target_platform == TargetPlatform::kRuntimeStageVulkan) {
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}
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
Definition compiler.cc:602
uint32_t * target
#define COMPILER_ERROR(stream)
Definition logger.h:39
static const uint32_t kMaxUniformBufferSize
Definition compiler.cc:42
static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
Definition compiler.cc:234
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::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::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 648 of file compiler.cc.

649 {
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}
static std::string JoinStrings(std::vector< std::string > items, const std::string &separator)
Definition compiler.cc:628

References impeller::compiler::JoinStrings().

◆ GetErrorMessages()

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

Definition at line 616 of file compiler.cc.

616 {
617 return error_stream_.str();
618}

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 624 of file compiler.cc.

624 {
625 return included_file_names_;
626}

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

◆ GetReflector()

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

Definition at line 663 of file compiler.cc.

663 {
664 return reflector_.get();
665}

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

◆ GetSLShaderSource()

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

Definition at line 602 of file compiler.cc.

602 {
603 return sl_mapping_;
604}

Referenced by Compiler().

◆ GetSPIRVAssembly()

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

Definition at line 598 of file compiler.cc.

598 {
599 return spirv_assembly_;
600}

Referenced by 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 620 of file compiler.cc.

620 {
621 return verbose_error_stream_.str();
622}

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

◆ IsValid()

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

Definition at line 606 of file compiler.cc.

606 {
607 return is_valid_;
608}

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


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