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