Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
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 244 of file compiler.cc.

247 : options_(source_options) {
248 if (!source_mapping || source_mapping->GetMapping() == nullptr) {
249 COMPILER_ERROR(error_stream_)
250 << "Could not read shader source or shader source was empty.";
251 return;
252 }
253
254 if (source_options.target_platform == TargetPlatform::kUnknown) {
255 COMPILER_ERROR(error_stream_) << "Target platform not specified.";
256 return;
257 }
258
259 SPIRVCompilerOptions spirv_options;
260
261 // Make sure reflection is as effective as possible. The generated shaders
262 // will be processed later by backend specific compilers.
263 spirv_options.generate_debug_info = true;
264
265 switch (options_.source_language) {
267 // Expects GLSL 4.60 (Core Profile).
268 // https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf
269 spirv_options.source_langauge =
270 shaderc_source_language::shaderc_source_language_glsl;
271 spirv_options.source_profile = SPIRVCompilerSourceProfile{
272 shaderc_profile::shaderc_profile_core, //
273 460, //
274 };
275 break;
277 spirv_options.source_langauge =
278 shaderc_source_language::shaderc_source_language_hlsl;
279 break;
281 COMPILER_ERROR(error_stream_) << "Source language invalid.";
282 return;
283 }
284
285 switch (source_options.target_platform) {
288 SPIRVCompilerTargetEnv target;
289
290 if (source_options.use_half_textures) {
291 target.env = shaderc_target_env::shaderc_target_env_opengl;
292 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
293 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
294 } else {
295 target.env = shaderc_target_env::shaderc_target_env_vulkan;
296 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
297 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
298 }
299
300 spirv_options.target = target;
301 } break;
306 SPIRVCompilerTargetEnv target;
307
308 target.env = shaderc_target_env::shaderc_target_env_vulkan;
309 target.version = shaderc_env_version::shaderc_env_version_vulkan_1_1;
310 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_3;
311
312 if (source_options.target_platform ==
314 spirv_options.macro_definitions.push_back("IMPELLER_GRAPHICS_BACKEND");
315 spirv_options.relaxed_vulkan_rules = true;
316 }
317 spirv_options.target = target;
318 } break;
321 SPIRVCompilerTargetEnv target;
322
323 target.env = shaderc_target_env::shaderc_target_env_opengl;
324 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
325 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
326
327 spirv_options.target = target;
328 spirv_options.macro_definitions.push_back("IMPELLER_GRAPHICS_BACKEND");
329 } break;
331 SPIRVCompilerTargetEnv target;
332
333 target.env = shaderc_target_env::shaderc_target_env_opengl;
334 target.version = shaderc_env_version::shaderc_env_version_opengl_4_5;
335 target.spirv_version = shaderc_spirv_version::shaderc_spirv_version_1_0;
336
337 // When any optimization level above 'zero' is enabled, the phi merges at
338 // loop continue blocks are rendered using syntax that is supported in
339 // GLSL, but not in SkSL.
340 // https://bugs.chromium.org/p/skia/issues/detail?id=13518.
341 spirv_options.optimization_level =
342 shaderc_optimization_level::shaderc_optimization_level_zero;
343 spirv_options.target = target;
344 spirv_options.macro_definitions.push_back("SKIA_GRAPHICS_BACKEND");
345 } break;
347 COMPILER_ERROR(error_stream_) << "Target platform invalid.";
348 return;
349 }
350
351 // Implicit definition that indicates that this compilation is for the device
352 // (instead of the host).
353 spirv_options.macro_definitions.push_back("IMPELLER_DEVICE");
354 for (const auto& define : source_options.defines) {
355 spirv_options.macro_definitions.push_back(define);
356 }
357
358 std::vector<std::string> included_file_names;
359 spirv_options.includer = std::make_shared<Includer>(
360 options_.working_directory, options_.include_dirs,
361 [&included_file_names](auto included_name) {
362 included_file_names.emplace_back(std::move(included_name));
363 });
364
365 // SPIRV Generation.
366 SPIRVCompiler spv_compiler(source_options, source_mapping);
367
368 spirv_assembly_ = spv_compiler.CompileToSPV(
369 error_stream_, spirv_options.BuildShadercOptions());
370
371 if (!spirv_assembly_) {
372 return;
373 } else {
374 included_file_names_ = std::move(included_file_names);
375 }
376
377 // SL Generation.
378 spirv_cross::Parser parser(
379 reinterpret_cast<const uint32_t*>(spirv_assembly_->GetMapping()),
380 spirv_assembly_->GetSize() / sizeof(uint32_t));
381 // The parser and compiler must be run separately because the parser contains
382 // meta information (like type member names) that are useful for reflection.
383 parser.parse();
384
385 const auto parsed_ir =
386 std::make_shared<spirv_cross::ParsedIR>(parser.get_parsed_ir());
387
388 auto sl_compiler = CreateCompiler(*parsed_ir, options_);
389
390 if (!sl_compiler) {
391 COMPILER_ERROR(error_stream_)
392 << "Could not create compiler for target platform.";
393 return;
394 }
395
396 // We need to invoke the compiler even if we don't use the SL mapping later
397 // for Vulkan. The reflector needs information that is only valid after a
398 // successful compilation call.
399 auto sl_compilation_result =
400 CreateMappingWithString(sl_compiler.GetCompiler()->compile());
401
402 // If the target is Vulkan, our shading language is SPIRV which we already
403 // have. We just need to strip it of debug information. If it isn't, we need
404 // to invoke the appropriate compiler to compile the SPIRV to the target SL.
405 if (source_options.target_platform == TargetPlatform::kVulkan ||
406 source_options.target_platform == TargetPlatform::kRuntimeStageVulkan) {
407 auto stripped_spirv_options = spirv_options;
408 stripped_spirv_options.generate_debug_info = false;
409 sl_mapping_ = spv_compiler.CompileToSPV(
410 error_stream_, stripped_spirv_options.BuildShadercOptions());
411 } else {
412 sl_mapping_ = sl_compilation_result;
413 }
414
415 if (!sl_mapping_) {
416 COMPILER_ERROR(error_stream_) << "Could not generate SL from SPIRV";
417 return;
418 }
419
420 reflector_ = std::make_unique<Reflector>(std::move(reflector_options), //
421 parsed_ir, //
423 sl_compiler //
424 );
425
426 if (!reflector_->IsValid()) {
427 COMPILER_ERROR(error_stream_)
428 << "Could not complete reflection on generated shader.";
429 return;
430 }
431
432 is_valid_ = true;
433}
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
Definition: compiler.cc:441
uint32_t * target
#define COMPILER_ERROR(stream)
Definition: logger.h:39
static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR &ir, const SourceOptions &source_options)
Definition: compiler.cc:210
std::shared_ptr< fml::Mapping > CreateMappingWithString(std::string string)
Definition: allocation.cc:111
parser
Definition: zip.py:78
std::vector< IncludeDir > include_dirs
std::shared_ptr< fml::UniqueFD > 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 483 of file compiler.cc.

484 {
485 // https://github.com/ninja-build/ninja/blob/master/src/depfile_parser.cc#L28
486 const auto targets = JoinStrings(targets_names, " ");
487 const auto dependencies = GetDependencyNames(" ");
488
489 std::stringstream stream;
490 stream << targets << ": " << dependencies << "\n";
491
492 auto contents = std::make_shared<std::string>(stream.str());
493 return std::make_unique<fml::NonOwnedMapping>(
494 reinterpret_cast<const uint8_t*>(contents->data()), contents->size(),
495 [contents](auto, auto) {});
496}
dictionary dependencies
Definition: minify_sksl.py:17
static std::string JoinStrings(std::vector< std::string > items, const std::string &separator)
Definition: compiler.cc:463

◆ GetErrorMessages()

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

Definition at line 455 of file compiler.cc.

455 {
456 return error_stream_.str();
457}

◆ GetIncludedFileNames()

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

Definition at line 459 of file compiler.cc.

459 {
460 return included_file_names_;
461}

◆ GetReflector()

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

Definition at line 498 of file compiler.cc.

498 {
499 return reflector_.get();
500}

◆ GetSLShaderSource()

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

Definition at line 441 of file compiler.cc.

441 {
442 return sl_mapping_;
443}

◆ GetSPIRVAssembly()

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

Definition at line 437 of file compiler.cc.

437 {
438 return spirv_assembly_;
439}

◆ IsValid()

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

Definition at line 445 of file compiler.cc.

445 {
446 return is_valid_;
447}

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