| 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 "flutter/fml/logging.h"
8 #include "flutter/fml/trace_event.h"
9 #include "impeller/blobcat/blob_library.h"
10 #include "impeller/renderer/backend/vulkan/context_vk.h"
11 #include "impeller/renderer/backend/vulkan/shader_function_vk.h"
12
13 namespace impeller {
14
15 static ShaderStage ToShaderStage(BlobShaderType type) {
16 switch (type) {
17 case BlobShaderType::kVertex:
18 return ShaderStage::kVertex;
19 case BlobShaderType::kFragment:
20 return ShaderStage::kFragment;
21 case BlobShaderType::kCompute:
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) {
32 case ShaderStage::kUnknown:
33 stream << "_unknown_";
34 break;
35 case ShaderStage::kVertex:
36 stream << "_vertex_";
37 break;
38 case ShaderStage::kFragment:
39 stream << "_fragment_";
40 break;
41 case ShaderStage::kTessellationControl:
42 stream << "_tessellation_control_";
43 break;
44 case ShaderStage::kTessellationEvaluation:
45 stream << "_tessellation_evaluation_";
46 break;
47 case ShaderStage::kCompute:
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