Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
shader.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 <cstring>
8#include <utility>
9
11#include "fml/make_copyable.h"
18
19namespace flutter {
20namespace gpu {
21
24 auto result =
25 std::find_if(metadata.members.begin(), metadata.members.end(),
27 return member.name == name;
28 });
29 if (result == metadata.members.end()) {
30 return nullptr;
31 }
32 return &(*result);
33}
34
36
37Shader::Shader() = default;
38
39Shader::~Shader() = default;
40
42 std::string library_id,
43 std::string entrypoint,
45 std::shared_ptr<fml::Mapping> code_mapping,
46 std::vector<impeller::ShaderStageIOSlot> inputs,
47 std::vector<impeller::ShaderStageBufferLayout> layouts,
48 std::unordered_map<std::string, UniformBinding> uniform_structs,
49 std::unordered_map<std::string, TextureBinding> uniform_textures,
50 std::vector<impeller::DescriptorSetLayout> descriptor_set_layouts) {
51 auto shader = fml::MakeRefCounted<Shader>();
52 shader->library_id_ = std::move(library_id);
53 shader->entrypoint_ = std::move(entrypoint);
54 shader->stage_ = stage;
55 shader->code_mapping_ = std::move(code_mapping);
56 shader->inputs_ = std::move(inputs);
57 shader->layouts_ = std::move(layouts);
58 shader->uniform_structs_ = std::move(uniform_structs);
59 shader->uniform_textures_ = std::move(uniform_textures);
60 shader->descriptor_set_layouts_ = std::move(descriptor_set_layouts);
61 return shader;
62}
63
64std::string Shader::GetScopedName() const {
66 impeller::ShaderKey::kScopeFlutterGPU, library_id_, entrypoint_);
67}
68
69std::shared_ptr<const impeller::ShaderFunction> Shader::GetFunctionFromLibrary(
70 impeller::ShaderLibrary& library) {
71 return library.GetFunction(GetScopedName(), stage_);
72}
73
75 auto& lib = *context.GetContext().GetShaderLibrary();
76 return GetFunctionFromLibrary(lib) != nullptr;
77}
78
79bool Shader::IsDirty() const {
80 return is_dirty_;
81}
82
84 is_dirty_ = false;
85}
86
88 // Compare the compiled bytes against the freshly-parsed mapping before
89 // moving anything. A shader bundle is the unit of asset distribution, so
90 // editing one shader recompiles the whole bundle; without this dedupe
91 // every unchanged shader in the bundle would still be evicted and
92 // re-registered on reload. Code-byte equality is sufficient because
93 // impellerc derives reflection metadata (uniforms, inputs, layouts)
94 // deterministically from the compiled output.
95 const bool code_changed =
96 code_mapping_ == nullptr || other.code_mapping_ == nullptr ||
97 code_mapping_->GetSize() != other.code_mapping_->GetSize() ||
98 std::memcmp(code_mapping_->GetMapping(),
99 other.code_mapping_->GetMapping(),
100 code_mapping_->GetSize()) != 0;
101
102 // library_id_ is intentionally preserved: the scoped registry key
103 // (library_id + entrypoint) must remain stable across reloads so the
104 // eviction triple-call in `RegisterSync` lands at the same slot.
105 entrypoint_ = std::move(other.entrypoint_);
106 stage_ = other.stage_;
107 code_mapping_ = std::move(other.code_mapping_);
108 inputs_ = std::move(other.inputs_);
109 layouts_ = std::move(other.layouts_);
110 uniform_structs_ = std::move(other.uniform_structs_);
111 uniform_textures_ = std::move(other.uniform_textures_);
112 descriptor_set_layouts_ = std::move(other.descriptor_set_layouts_);
113 if (code_changed) {
114 is_dirty_ = true;
115 }
116}
117
119 auto& lib = *context.GetContext().GetShaderLibrary();
120 const std::string scoped_name = GetScopedName();
121
122 std::shared_ptr<const impeller::ShaderFunction> existing =
123 lib.GetFunction(scoped_name, stage_);
124 if (existing && !is_dirty_) {
125 return true; // Already registered and current.
126 }
127
128 // Dirty path: an earlier asset version still occupies the scoped slot.
129 // Evict it (and any pipelines that referenced it) before registering the
130 // new code mapping. Mirrors `RuntimeEffectContents::RegisterShader`.
131 if (existing && is_dirty_) {
132 context.GetContext().GetPipelineLibrary()->RemovePipelinesWithEntryPoint(
133 existing);
134 lib.UnregisterFunction(scoped_name, stage_);
135 }
136
137 std::promise<bool> promise;
138 auto future = promise.get_future();
139 lib.RegisterFunction(
140 scoped_name, stage_, code_mapping_,
141 fml::MakeCopyable([promise = std::move(promise)](bool result) mutable {
142 promise.set_value(result);
143 }));
144 if (!future.get()) {
145 return false; // Registration failed.
146 }
147 is_dirty_ = false;
148 return true;
149}
150
151std::shared_ptr<impeller::VertexDescriptor> Shader::CreateVertexDescriptor()
152 const {
153 auto vertex_descriptor = std::make_shared<impeller::VertexDescriptor>();
154 vertex_descriptor->SetStageInputs(inputs_, layouts_);
155 return vertex_descriptor;
156}
157
158const std::vector<impeller::ShaderStageIOSlot>& Shader::GetStageInputs() const {
159 return inputs_;
160}
161
162const std::vector<impeller::ShaderStageBufferLayout>&
164 return layouts_;
165}
166
168 return stage_;
169}
170
171const std::vector<impeller::DescriptorSetLayout>&
173 return descriptor_set_layouts_;
174}
175
177 const std::string& name) const {
178 auto uniform = uniform_structs_.find(name);
179 if (uniform == uniform_structs_.end()) {
180 return nullptr;
181 }
182 return &uniform->second;
183}
184
186 const std::string& name) const {
187 auto uniform = uniform_textures_.find(name);
188 if (uniform == uniform_textures_.end()) {
189 return nullptr;
190 }
191 return &uniform->second;
192}
193
194} // namespace gpu
195} // namespace flutter
196
197//----------------------------------------------------------------------------
198/// Exports
199///
200
202 flutter::gpu::Shader* wrapper,
203 Dart_Handle struct_name_handle) {
204 auto name = tonic::StdStringFromDart(struct_name_handle);
205 const auto* uniform = wrapper->GetUniformStruct(name);
206 if (uniform == nullptr) {
207 return -1;
208 }
209
210 return uniform->size_in_bytes;
211}
212
214 flutter::gpu::Shader* wrapper,
215 Dart_Handle struct_name_handle,
216 Dart_Handle member_name_handle) {
217 auto struct_name = tonic::StdStringFromDart(struct_name_handle);
218 const auto* uniform = wrapper->GetUniformStruct(struct_name);
219 if (uniform == nullptr) {
220 return -1;
221 }
222
223 auto member_name = tonic::StdStringFromDart(member_name_handle);
224 const auto* member = uniform->GetMemberMetadata(member_name);
225 if (member == nullptr) {
226 return -1;
227 }
228
229 return member->offset;
230}
231
233 return wrapper->IsDirty();
234}
An immutable collection of shaders loaded from a shader bundle asset.
Definition shader.h:23
const Shader::UniformBinding * GetUniformStruct(const std::string &name) const
Definition shader.cc:176
impeller::ShaderStage GetShaderStage() const
Definition shader.cc:167
bool IsRegistered(Context &context)
Definition shader.cc:74
bool RegisterSync(Context &context)
Definition shader.cc:118
void ResetFrom(Shader &other)
Definition shader.cc:87
const std::vector< impeller::ShaderStageIOSlot > & GetStageInputs() const
Definition shader.cc:158
std::shared_ptr< impeller::VertexDescriptor > CreateVertexDescriptor() const
Definition shader.cc:151
static fml::RefPtr< Shader > Make(std::string library_id, std::string entrypoint, impeller::ShaderStage stage, std::shared_ptr< fml::Mapping > code_mapping, std::vector< impeller::ShaderStageIOSlot > inputs, std::vector< impeller::ShaderStageBufferLayout > layouts, std::unordered_map< std::string, UniformBinding > uniform_structs, std::unordered_map< std::string, TextureBinding > uniform_textures, std::vector< impeller::DescriptorSetLayout > descriptor_set_layouts)
Definition shader.cc:41
const std::vector< impeller::ShaderStageBufferLayout > & GetStageBufferLayouts() const
Definition shader.cc:163
const std::vector< impeller::DescriptorSetLayout > & GetDescriptorSetLayouts() const
Definition shader.cc:172
bool IsDirty() const
Definition shader.cc:79
const Shader::TextureBinding * GetUniformTexture(const std::string &name) const
Definition shader.cc:185
std::shared_ptr< const impeller::ShaderFunction > GetFunctionFromLibrary(impeller::ShaderLibrary &library)
Definition shader.cc:69
virtual std::shared_ptr< const ShaderFunction > GetFunction(std::string_view name, ShaderStage stage)=0
#define IMPLEMENT_WRAPPERTYPEINFO(LibraryName, ClassName)
int InternalFlutterGpu_Shader_GetUniformStructSize(flutter::gpu::Shader *wrapper, Dart_Handle struct_name_handle)
Definition shader.cc:201
bool InternalFlutterGpu_Shader_DebugIsDirty(flutter::gpu::Shader *wrapper)
Definition shader.cc:232
int InternalFlutterGpu_Shader_GetUniformMemberOffset(flutter::gpu::Shader *wrapper, Dart_Handle struct_name_handle, Dart_Handle member_name_handle)
Definition shader.cc:213
DEF_SWITCHES_START aot vmservice shared library name
Definition switch_defs.h:27
internal::CopyableLambda< T > MakeCopyable(T lambda)
std::string StdStringFromDart(Dart_Handle handle)
std::shared_ptr< ContextGLES > context
impeller::ShaderMetadata metadata
Definition shader.h:30
const impeller::ShaderStructMemberMetadata * GetMemberMetadata(const std::string &name) const
Definition shader.cc:23
static constexpr std::string_view kScopeFlutterGPU
Scope tag for Flutter GPU user shader bundles.
Definition shader_key.h:59
static std::string MakeUserScopedName(std::string_view scope, std::string_view library_id, std::string_view entrypoint)
Definition shader_key.cc:19
std::vector< ShaderStructMemberMetadata > members