Flutter Impeller
shader_archive.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 <sstream>
9 #include <string>
10 #include <utility>
11 
13 #include "impeller/shader_archive/shader_archive_flatbuffers.h"
14 
15 namespace impeller {
16 
17 constexpr ArchiveShaderType ToShaderType(fb::Stage stage) {
18  switch (stage) {
19  case fb::Stage::kVertex:
21  case fb::Stage::kFragment:
23  case fb::Stage::kCompute:
25  }
26  FML_UNREACHABLE();
27 }
28 
29 absl::StatusOr<ShaderArchive> ShaderArchive::Create(
30  std::shared_ptr<fml::Mapping> payload) {
31  if (!payload || payload->GetMapping() == nullptr) {
32  return absl::InvalidArgumentError("Shader mapping was absent.");
33  }
34 
35  if (!fb::ShaderArchiveBufferHasIdentifier(payload->GetMapping())) {
36  return absl::InvalidArgumentError("Invalid shader magic.");
37  }
38 
39  flatbuffers::Verifier verifier(payload->GetMapping(), payload->GetSize());
40  if (!fb::VerifyShaderArchiveBuffer(verifier)) {
41  return absl::InvalidArgumentError(
42  "Shader archive buffer failed verification.");
43  }
44 
45  auto shader_archive = fb::GetShaderArchive(payload->GetMapping());
46  if (!shader_archive) {
47  return absl::InvalidArgumentError("Could not read shader archive.");
48  }
49 
50  const auto version = shader_archive->format_version();
51  const auto expected =
52  static_cast<uint32_t>(fb::ShaderArchiveFormatVersion::kVersion);
53  if (version != expected) {
54  std::stringstream stream;
55  stream << "Unsupported shader archive format version. Expected: "
56  << expected << ", Got: " << version;
57  return absl::InvalidArgumentError(stream.str());
58  }
59 
60  Shaders shaders;
61  if (auto items = shader_archive->items()) {
62  for (auto i = items->begin(), end = items->end(); i != end; i++) {
63  ShaderKey key;
64  key.name = i->name()->str();
65  key.type = ToShaderType(i->stage());
66  shaders[key] = std::make_shared<fml::NonOwnedMapping>(
67  i->mapping()->Data(), i->mapping()->size(), [payload](auto, auto) {
68  // The pointers are into the base payload. Instead of copying the
69  // data, just hold onto the payload.
70  });
71  }
72  }
73 
74  return ShaderArchive(std::move(payload), std::move(shaders));
75 }
76 
77 ShaderArchive::ShaderArchive(std::shared_ptr<fml::Mapping> payload,
78  Shaders shaders)
79  : payload_(std::move(payload)), shaders_(std::move(shaders)) {}
80 
81 ShaderArchive::ShaderArchive(ShaderArchive&&) = default;
82 
84 
86  return shaders_.size();
87 }
88 
89 std::shared_ptr<fml::Mapping> ShaderArchive::GetMapping(
90  ArchiveShaderType type,
91  std::string name) const {
92  ShaderKey key;
93  key.type = type;
94  key.name = std::move(name);
95  auto found = shaders_.find(key);
96  return found == shaders_.end() ? nullptr : found->second;
97 }
98 
100  const std::function<bool(ArchiveShaderType type,
101  const std::string& name,
102  const std::shared_ptr<fml::Mapping>& mapping)>&
103  callback) const {
104  if (!callback) {
105  return 0u;
106  }
107  size_t count = 0u;
108  for (const auto& shader : shaders_) {
109  count++;
110  if (!callback(shader.first.type, shader.first.name, shader.second)) {
111  break;
112  }
113  }
114  return count;
115 }
116 
117 } // namespace impeller
ShaderArchive(ShaderArchive &&)
size_t IterateAllShaders(const std::function< bool(ArchiveShaderType type, const std::string &name, const std::shared_ptr< fml::Mapping > &mapping)> &) const
static absl::StatusOr< ShaderArchive > Create(std::shared_ptr< fml::Mapping > payload)
size_t GetShaderCount() const
std::shared_ptr< fml::Mapping > GetMapping(ArchiveShaderType type, std::string name) const
constexpr ArchiveShaderType ToShaderType(fb::Stage stage)
Definition: comparable.h:93
const size_t end