Flutter Impeller
shader_library_vk.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 "flutter/fml/logging.h"
8 #include "flutter/fml/trace_event.h"
12 
13 namespace impeller {
14 
16  switch (type) {
18  return ShaderStage::kVertex;
22  return ShaderStage::kCompute;
23  }
24  FML_UNREACHABLE();
25 }
26 
27 static std::string VKShaderNameToShaderKeyName(const std::string& name,
28  ShaderStage stage) {
29  std::stringstream stream;
30  stream << name;
31  switch (stage) {
33  stream << "_unknown_";
34  break;
36  stream << "_vertex_";
37  break;
39  stream << "_fragment_";
40  break;
42  stream << "_tessellation_control_";
43  break;
45  stream << "_tessellation_evaluation_";
46  break;
48  stream << "_compute_";
49  break;
50  }
51  stream << "main";
52  return stream.str();
53 }
54 
55 ShaderLibraryVK::ShaderLibraryVK(
56  std::weak_ptr<DeviceHolder> device_holder,
57  const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data)
58  : device_holder_(std::move(device_holder)) {
59  TRACE_EVENT0("impeller", "CreateShaderLibrary");
60  bool success = true;
61  auto iterator = [&](auto type, //
62  const auto& name, //
63  const auto& code //
64  ) -> bool {
65  if (!RegisterFunction(name, ToShaderStage(type), code)) {
66  success = false;
67  return false;
68  }
69  return true;
70  };
71  for (const auto& library_data : shader_libraries_data) {
72  auto blob_library = BlobLibrary{library_data};
73  if (!blob_library.IsValid()) {
74  VALIDATION_LOG << "Could not construct shader blob library.";
75  return;
76  }
77  blob_library.IterateAllBlobs(iterator);
78  }
79 
80  if (!success) {
81  VALIDATION_LOG << "Could not create shader modules for all shader blobs.";
82  return;
83  }
84  is_valid_ = true;
85 }
86 
87 ShaderLibraryVK::~ShaderLibraryVK() = default;
88 
89 bool ShaderLibraryVK::IsValid() const {
90  return is_valid_;
91 }
92 
93 // |ShaderLibrary|
94 std::shared_ptr<const ShaderFunction> ShaderLibraryVK::GetFunction(
95  std::string_view name,
96  ShaderStage stage) {
97  ReaderLock lock(functions_mutex_);
98 
99  const auto key = ShaderKey{{name.data(), name.size()}, stage};
100  auto found = functions_.find(key);
101  if (found != functions_.end()) {
102  return found->second;
103  }
104  return nullptr;
105 }
106 
107 // |ShaderLibrary|
108 void ShaderLibraryVK::RegisterFunction(std::string name,
109  ShaderStage stage,
110  std::shared_ptr<fml::Mapping> code,
111  RegistrationCallback callback) {
112  const auto result = RegisterFunction(name, stage, code);
113  if (callback) {
114  callback(result);
115  }
116 }
117 
118 static bool IsMappingSPIRV(const fml::Mapping& mapping) {
119  // https://registry.khronos.org/SPIR-V/specs/1.0/SPIRV.html#Magic
120  const uint32_t kSPIRVMagic = 0x07230203;
121  if (mapping.GetSize() < sizeof(kSPIRVMagic)) {
122  return false;
123  }
124  uint32_t magic = 0u;
125  ::memcpy(&magic, mapping.GetMapping(), sizeof(magic));
126  return magic == kSPIRVMagic;
127 }
128 
129 bool ShaderLibraryVK::RegisterFunction(
130  const std::string& name,
131  ShaderStage stage,
132  const std::shared_ptr<fml::Mapping>& code) {
133  if (!code) {
134  return false;
135  }
136 
137  if (!IsMappingSPIRV(*code)) {
138  VALIDATION_LOG << "Shader is not valid SPIRV.";
139  return false;
140  }
141 
142  vk::ShaderModuleCreateInfo shader_module_info;
143 
144  shader_module_info.setPCode(
145  reinterpret_cast<const uint32_t*>(code->GetMapping()));
146  shader_module_info.setCodeSize(code->GetSize());
147 
148  auto device_holder = device_holder_.lock();
149  if (!device_holder) {
150  return false;
151  }
152  FML_DCHECK(device_holder->GetDevice());
153  auto module =
154  device_holder->GetDevice().createShaderModuleUnique(shader_module_info);
155 
156  if (module.result != vk::Result::eSuccess) {
157  VALIDATION_LOG << "Could not create shader module: "
158  << vk::to_string(module.result);
159  return false;
160  }
161 
162  const auto key_name = VKShaderNameToShaderKeyName(name, stage);
163 
164  vk::UniqueShaderModule shader_module = std::move(module.value);
165  ContextVK::SetDebugName(device_holder->GetDevice(), *shader_module,
166  "Shader " + name);
167 
168  WriterLock lock(functions_mutex_);
169  functions_[ShaderKey{key_name, stage}] = std::shared_ptr<ShaderFunctionVK>(
170  new ShaderFunctionVK(device_holder_,
171  library_id_, //
172  key_name, //
173  stage, //
174  std::move(shader_module) //
175  ));
176 
177  return true;
178 }
179 
180 // |ShaderLibrary|
181 void ShaderLibraryVK::UnregisterFunction(std::string name, ShaderStage stage) {
182  WriterLock lock(functions_mutex_);
183 
184  const auto key = ShaderKey{name, stage};
185 
186  auto found = functions_.find(key);
187  if (found != functions_.end()) {
188  VALIDATION_LOG << "Library function named " << name
189  << " was not found, so it couldn't be unregistered.";
190  return;
191  }
192 
193  functions_.erase(found);
194 
195  return;
196 }
197 
198 } // namespace impeller
impeller::ShaderStage::kUnknown
@ kUnknown
blob_library.h
impeller::ShaderStage
ShaderStage
Definition: shader_types.h:20
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
impeller::ReaderLock
Definition: thread.h:68
impeller::ShaderStage::kTessellationEvaluation
@ kTessellationEvaluation
impeller::BlobShaderType::kVertex
@ kVertex
impeller::ShaderStage::kFragment
@ kFragment
impeller::IsMappingSPIRV
static bool IsMappingSPIRV(const fml::Mapping &mapping)
Definition: shader_library_vk.cc:118
impeller::BlobShaderType
BlobShaderType
Definition: blob_types.h:9
impeller::BlobShaderType::kFragment
@ kFragment
shader_library_vk.h
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::ShaderKey
Definition: shader_key.h:17
std
Definition: comparable.h:98
impeller::ShaderStage::kVertex
@ kVertex
impeller::BlobShaderType::kCompute
@ kCompute
impeller::VKShaderNameToShaderKeyName
static std::string VKShaderNameToShaderKeyName(const std::string &name, ShaderStage stage)
Definition: shader_library_vk.cc:27
impeller::ShaderStage::kCompute
@ kCompute
impeller::ShaderStage::kTessellationControl
@ kTessellationControl
context_vk.h
shader_function_vk.h
impeller
Definition: aiks_context.cc:10