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

285 : options_(source_options) {
286 if (!source_mapping || source_mapping->GetMapping() == nullptr) {
287 COMPILER_ERROR(error_stream_)
288 << "Could not read shader source or shader source was empty.";
289 return;
290 }
291
292 if (source_options.target_platform == TargetPlatform::kUnknown) {
293 COMPILER_ERROR(error_stream_) << "Target platform not specified.";
294 return;
295 }
296
297 SPIRVCompilerOptions spirv_options;
298
299 // Make sure reflection is as effective as possible. The generated shaders
300 // will be processed later by backend specific compilers.
301 spirv_options.generate_debug_info = true;
302
303 switch (options_.source_language) {
305 // Expects GLSL 4.60 (Core Profile).
306 // https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf
307 spirv_options.source_langauge =
308 shaderc_source_language::shaderc_source_language_glsl;
309 spirv_options.source_profile = SPIRVCompilerSourceProfile{
310 shaderc_profile::shaderc_profile_core, //
311 460, //
312 };
313 break;
315 spirv_options.source_langauge =
316 shaderc_source_language::shaderc_source_language_hlsl;
317 break;
319 COMPILER_ERROR(error_stream_) << "Source language invalid.";
320 return;
321 }
322
323 switch (source_options.target_platform) {
326 SPIRVCompilerTargetEnv target;
327
328 if (source_options.use_half_textures) {
329 target.env = shaderc_target_env::shaderc_target_env_opengl;
330 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
331 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
332 } else {
333 target.env = shaderc_target_env::shaderc_target_env_vulkan;
334 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
335 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
336 }
337
338 spirv_options.target = target;
339 } break;
344 SPIRVCompilerTargetEnv target;
345
346 target.env = shaderc_target_env::shaderc_target_env_vulkan;
347 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
348 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
349
350 if (source_options.target_platform ==
352 spirv_options.macro_definitions.push_back("IMPELLER_GRAPHICS_BACKEND");
353 spirv_options.relaxed_vulkan_rules = true;
354 }
355 spirv_options.target = target;
356 } break;
360 SPIRVCompilerTargetEnv target;
361
362 target.env = shaderc_target_env::shaderc_target_env_opengl;
363 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
364 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
365
366 spirv_options.target = target;
367 spirv_options.macro_definitions.push_back("IMPELLER_GRAPHICS_BACKEND");
368 if (source_options.target_platform == TargetPlatform::kRuntimeStageGLES ||
369 source_options.target_platform ==
371 spirv_options.macro_definitions.push_back("IMPELLER_TARGET_OPENGLES");
372 }
373 } break;
375 SPIRVCompilerTargetEnv target;
376
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
381 // When any optimization level above 'zero' is enabled, the phi merges at
382 // loop continue blocks are rendered using syntax that is supported in
383 // GLSL, but not in SkSL.
384 // https://bugs.chromium.org/p/skia/issues/detail?id=13518.
385 spirv_options.optimization_level =
386 shaderc_optimization_level::shaderc_optimization_level_zero;
387 spirv_options.target = target;
388 spirv_options.macro_definitions.push_back("SKIA_GRAPHICS_BACKEND");
389 } break;
391 COMPILER_ERROR(error_stream_) << "Target platform invalid.";
392 return;
393 }
394
395 // Implicit definition that indicates that this compilation is for the device
396 // (instead of the host).
397 spirv_options.macro_definitions.push_back("IMPELLER_DEVICE");
398 for (const auto& define : source_options.defines) {
399 spirv_options.macro_definitions.push_back(define);
400 }
401
402 std::vector<std::string> included_file_names;
403 spirv_options.includer = std::make_shared<Includer>(
404 options_.working_directory, options_.include_dirs,
405 [&included_file_names](auto included_name) {
406 included_file_names.emplace_back(std::move(included_name));
407 });
408
409 // SPIRV Generation.
410 SPIRVCompiler spv_compiler(source_options, source_mapping);
411
412 spirv_assembly_ = spv_compiler.CompileToSPV(
413 error_stream_, spirv_options.BuildShadercOptions());
414
415 if (!spirv_assembly_) {
416 return;
417 } else {
418 included_file_names_ = std::move(included_file_names);
419 }
420
421 // SL Generation.
422 spirv_cross::Parser parser(
423 reinterpret_cast<const uint32_t*>(spirv_assembly_->GetMapping()),
424 spirv_assembly_->GetSize() / sizeof(uint32_t));
425 // The parser and compiler must be run separately because the parser contains
426 // meta information (like type member names) that are useful for reflection.
427 parser.parse();
428
429 const auto parsed_ir =
430 std::make_shared<spirv_cross::ParsedIR>(parser.get_parsed_ir());
431
432 auto sl_compiler = CreateCompiler(*parsed_ir, options_);
433
434 if (!sl_compiler) {
435 COMPILER_ERROR(error_stream_)
436 << "Could not create compiler for target platform.";
437 return;
438 }
439
440 uint32_t ubo_size = CalculateUBOSize(sl_compiler.GetCompiler());
441 if (ubo_size > kMaxUniformBufferSize) {
442 COMPILER_ERROR(error_stream_) << "Uniform buffer size exceeds max ("
443 << kMaxUniformBufferSize << "): " << ubo_size;
444 return;
445 }
446
447 // We need to invoke the compiler even if we don't use the SL mapping later
448 // for Vulkan. The reflector needs information that is only valid after a
449 // successful compilation call.
450 auto sl_compilation_result_str = sl_compiler.GetCompiler()->compile();
451 auto sl_compilation_result =
452 CreateMappingWithString(sl_compilation_result_str);
453
454 // If the target is Vulkan, our shading language is SPIRV which we already
455 // have. We just need to strip it of debug information. If it isn't, we need
456 // to invoke the appropriate compiler to compile the SPIRV to the target SL.
457 if (source_options.target_platform == TargetPlatform::kVulkan ||
458 source_options.target_platform == TargetPlatform::kRuntimeStageVulkan) {
459 auto stripped_spirv_options = spirv_options;
460 stripped_spirv_options.generate_debug_info = false;
461 sl_mapping_ = spv_compiler.CompileToSPV(
462 error_stream_, stripped_spirv_options.BuildShadercOptions());
463 } else {
464 sl_mapping_ = sl_compilation_result;
465 }
466
467 if (!sl_mapping_) {
468 COMPILER_ERROR(error_stream_) << "Could not generate SL from SPIRV";
469 return;
470 }
471
472 if (sl_compiler.GetType() == CompilerBackend::Type::kSkSL) {
473 // Validate compiled SkSL by trying to create a SkRuntimeEffect.
474 SkRuntimeEffect::Result result =
475 SkRuntimeEffect::MakeForShader(SkString(sl_compilation_result_str));
476 if (result.effect == nullptr) {
477 COMPILER_ERROR(error_stream_)
478 << "Compiled to invalid SkSL:\n"
479 << sl_compilation_result_str << "\nSkSL Error:\n"
480 << result.errorText.c_str();
481 return;
482 }
483 }
484
485 reflector_ = std::make_unique<Reflector>(std::move(reflector_options), //
486 parsed_ir, //
488 sl_compiler //
489 );
490
491 if (!reflector_->IsValid()) {
492 COMPILER_ERROR(error_stream_)
493 << "Could not complete reflection on generated shader.";
494 return;
495 }
496
497 is_valid_ = true;
498}
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
Definition compiler.cc:506
uint32_t * target
#define COMPILER_ERROR(stream)
Definition logger.h:39
static const uint32_t kMaxUniformBufferSize
Definition compiler.cc:40
static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
Definition compiler.cc:232
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 548 of file compiler.cc.

549 {
550 // https://github.com/ninja-build/ninja/blob/master/src/depfile_parser.cc#L28
551 const auto targets = JoinStrings(targets_names, " ");
552 const auto dependencies = GetDependencyNames(" ");
553
554 std::stringstream stream;
555 stream << targets << ": " << dependencies << "\n";
556
557 auto contents = std::make_shared<std::string>(stream.str());
558 return std::make_unique<fml::NonOwnedMapping>(
559 reinterpret_cast<const uint8_t*>(contents->data()), contents->size(),
560 [contents](auto, auto) {});
561}
static std::string JoinStrings(std::vector< std::string > items, const std::string &separator)
Definition compiler.cc:528

References impeller::compiler::JoinStrings().

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

◆ GetErrorMessages()

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

◆ GetIncludedFileNames()

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

Definition at line 524 of file compiler.cc.

524 {
525 return included_file_names_;
526}

◆ GetReflector()

◆ GetSLShaderSource()

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

Definition at line 506 of file compiler.cc.

506 {
507 return sl_mapping_;
508}

Referenced by impeller::compiler::testing::CompilerTestBase::CanCompileAndReflect(), Compiler(), and impeller::compiler::OutputSLFile().

◆ GetSPIRVAssembly()

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

◆ IsValid()


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