Flutter Impeller
shader_archive_writer.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 <array>
8 #include <filesystem>
9 #include <optional>
10 
11 #include "flutter/fml/build_config.h"
12 #include "impeller/shader_archive/shader_archive_flatbuffers.h"
13 
14 namespace impeller {
15 
17 
19 
20 void ShaderArchiveWriter::SetEntryPointPrefix(std::string prefix) {
21  prefix_ = std::move(prefix);
22 }
23 
24 std::optional<ArchiveShaderType> InferShaderTypefromFileExtension(
25  const std::filesystem::path& path) {
26 #if FML_OS_QNX
27  return std::nullopt;
28 #else // FML_OS_QNX
29  if (path == ".vert") {
31  } else if (path == ".frag") {
33  } else if (path == ".comp") {
35  }
36  return std::nullopt;
37 #endif // FML_OS_QNX
38 }
39 
40 bool ShaderArchiveWriter::AddShaderAtPath(const std::string& std_path) {
41 #if FML_OS_QNX
42  return false;
43 #else // FML_OS_QNX
44  std::filesystem::path path(std_path);
45 
46  if (path.stem().empty()) {
47  FML_LOG(ERROR) << "File path stem was empty for " << path;
48  return false;
49  }
50 
51  if (path.extension() != ".gles" && path.extension() != ".vkspv") {
52  FML_LOG(ERROR) << "File path doesn't have a known shader extension "
53  << path;
54  return false;
55  }
56 
57  // Get rid of .gles
58  path = path.replace_extension();
59 
60  auto shader_type = InferShaderTypefromFileExtension(path.extension());
61 
62  if (!shader_type.has_value()) {
63  FML_LOG(ERROR) << "Could not infer shader type from file extension: "
64  << path.extension().string();
65  return false;
66  }
67 
68  // Get rid of the shader type extension (.vert, .frag, etc..).
69  path = path.replace_extension();
70 
71  const auto shader_name = prefix_ + path.stem().string();
72  if (shader_name.empty()) {
73  FML_LOG(ERROR) << "Shader name was empty.";
74  return false;
75  }
76 
77  auto file_mapping = fml::FileMapping::CreateReadOnly(std_path);
78  if (!file_mapping) {
79  FML_LOG(ERROR) << "File doesn't exist at path: " << path;
80  return false;
81  }
82 
83  return AddShader(shader_type.value(), shader_name, std::move(file_mapping));
84 #endif // FML_OS_QNX
85 }
86 
88  std::string name,
89  std::shared_ptr<fml::Mapping> mapping) {
90  if (name.empty() || !mapping || mapping->GetMapping() == nullptr) {
91  return false;
92  }
93 
94  shader_descriptions_.emplace_back(
95  ShaderDescription{type, std::move(name), std::move(mapping)});
96  return true;
97 }
98 
99 constexpr fb::Stage ToStage(ArchiveShaderType type) {
100  switch (type) {
102  return fb::Stage::kVertex;
104  return fb::Stage::kFragment;
106  return fb::Stage::kCompute;
107  }
108  FML_UNREACHABLE();
109 }
110 
111 std::shared_ptr<fml::Mapping> ShaderArchiveWriter::CreateMapping() const {
112  fb::ShaderArchiveT shader_archive;
113  shader_archive.format_version =
114  static_cast<uint32_t>(fb::ShaderArchiveFormatVersion::kVersion);
115  for (const auto& shader_description : shader_descriptions_) {
116  auto mapping = shader_description.mapping;
117  if (!mapping) {
118  return nullptr;
119  }
120  auto desc = std::make_unique<fb::ShaderBlobT>();
121  desc->name = shader_description.name;
122  desc->stage = ToStage(shader_description.type);
123  desc->mapping = {mapping->GetMapping(),
124  mapping->GetMapping() + mapping->GetSize()};
125  shader_archive.items.emplace_back(std::move(desc));
126  }
127  auto builder = std::make_shared<flatbuffers::FlatBufferBuilder>();
128  builder->Finish(fb::ShaderArchive::Pack(*builder.get(), &shader_archive),
129  fb::ShaderArchiveIdentifier());
130  return std::make_shared<fml::NonOwnedMapping>(builder->GetBufferPointer(),
131  builder->GetSize(),
132  [builder](auto, auto) {});
133 }
134 
135 } // namespace impeller
GLenum type
bool AddShaderAtPath(const std::string &path)
bool AddShader(ArchiveShaderType type, std::string name, std::shared_ptr< fml::Mapping > mapping)
std::shared_ptr< fml::Mapping > CreateMapping() const
void SetEntryPointPrefix(std::string prefix)
std::optional< ArchiveShaderType > InferShaderTypefromFileExtension(const std::filesystem::path &path)
constexpr fb::Stage ToStage(ArchiveShaderType type)