4
4
5
5
#include " impeller/entity/contents/runtime_effect_contents.h"
6
6
7
+ #include < algorithm>
7
8
#include < future>
8
9
#include < memory>
9
10
19
20
#include " impeller/renderer/pipeline_library.h"
20
21
#include " impeller/renderer/render_pass.h"
21
22
#include " impeller/renderer/shader_function.h"
23
+ #include " impeller/renderer/vertex_descriptor.h"
22
24
23
25
namespace impeller {
24
26
@@ -65,18 +67,22 @@ static std::shared_ptr<ShaderMetadata> MakeShaderMetadata(
65
67
return metadata;
66
68
}
67
69
68
- bool RuntimeEffectContents::Render (const ContentContext& renderer,
69
- const Entity& entity,
70
- RenderPass& pass) const {
70
+ bool RuntimeEffectContents::BootstrapShader (
71
+ const ContentContext& renderer) const {
72
+ if (!RegisterShader (renderer)) {
73
+ return false ;
74
+ }
75
+ ContentContextOptions options;
76
+ options.color_attachment_pixel_format =
77
+ renderer.GetContext ()->GetCapabilities ()->GetDefaultColorFormat ();
78
+ return !!CreatePipeline (renderer, options);
79
+ }
80
+
81
+ bool RuntimeEffectContents::RegisterShader (
82
+ const ContentContext& renderer) const {
71
83
const std::shared_ptr<Context>& context = renderer.GetContext ();
72
84
const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary ();
73
85
74
- // --------------------------------------------------------------------------
75
- // / Get or register shader.
76
- // /
77
-
78
- // TODO(113719): Register the shader function earlier.
79
-
80
86
std::shared_ptr<const ShaderFunction> function = library->GetFunction (
81
87
runtime_stage_->GetEntrypoint (), ShaderStage::kFragment );
82
88
@@ -123,29 +129,75 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
123
129
124
130
runtime_stage_->SetClean ();
125
131
}
132
+ return true ;
133
+ }
126
134
127
- // --------------------------------------------------------------------------
128
- // / Set up the command. Defer setting up the pipeline until the descriptor set
129
- // / layouts are known from the uniforms.
130
- // /
131
-
135
+ std::shared_ptr<Pipeline<PipelineDescriptor>>
136
+ RuntimeEffectContents::CreatePipeline ( const ContentContext& renderer,
137
+ ContentContextOptions options) const {
138
+ const std::shared_ptr<Context>& context = renderer. GetContext ();
139
+ const std::shared_ptr<ShaderLibrary>& library = context-> GetShaderLibrary ();
132
140
const std::shared_ptr<const Capabilities>& caps = context->GetCapabilities ();
133
141
const auto color_attachment_format = caps->GetDefaultColorFormat ();
134
142
const auto stencil_attachment_format = caps->GetDefaultDepthStencilFormat ();
135
143
136
144
using VS = RuntimeEffectVertexShader;
137
145
138
- // --------------------------------------------------------------------------
139
- // / Fragment stage uniforms.
140
- // /
146
+ PipelineDescriptor desc;
147
+ desc.SetLabel (" Runtime Stage" );
148
+ desc.AddStageEntrypoint (
149
+ library->GetFunction (VS::kEntrypointName , ShaderStage::kVertex ));
150
+ desc.AddStageEntrypoint (library->GetFunction (runtime_stage_->GetEntrypoint (),
151
+ ShaderStage::kFragment ));
152
+
153
+ std::shared_ptr<VertexDescriptor> vertex_descriptor =
154
+ std::make_shared<VertexDescriptor>();
155
+ vertex_descriptor->SetStageInputs (VS::kAllShaderStageInputs ,
156
+ VS::kInterleavedBufferLayout );
157
+ vertex_descriptor->RegisterDescriptorSetLayouts (VS::kDescriptorSetLayouts );
158
+ vertex_descriptor->RegisterDescriptorSetLayouts (
159
+ runtime_stage_->GetDescriptorSetLayouts ().data (),
160
+ runtime_stage_->GetDescriptorSetLayouts ().size ());
161
+ desc.SetVertexDescriptor (std::move (vertex_descriptor));
162
+ desc.SetColorAttachmentDescriptor (
163
+ 0u , {.format = color_attachment_format, .blending_enabled = true });
164
+
165
+ desc.SetStencilAttachmentDescriptors (StencilAttachmentDescriptor{});
166
+ desc.SetStencilPixelFormat (stencil_attachment_format);
167
+
168
+ desc.SetDepthStencilAttachmentDescriptor (DepthAttachmentDescriptor{});
169
+ desc.SetDepthPixelFormat (stencil_attachment_format);
170
+
171
+ options.ApplyToPipelineDescriptor (desc);
172
+ auto pipeline = context->GetPipelineLibrary ()->GetPipeline (desc).Get ();
173
+ if (!pipeline) {
174
+ VALIDATION_LOG << " Failed to get or create runtime effect pipeline." ;
175
+ return nullptr ;
176
+ }
141
177
142
- std::vector<DescriptorSetLayout> descriptor_set_layouts;
178
+ return pipeline;
179
+ }
143
180
144
- BindFragmentCallback bind_callback = [this , &renderer, &context,
145
- &descriptor_set_layouts](
146
- RenderPass& pass) {
147
- descriptor_set_layouts.clear ();
181
+ bool RuntimeEffectContents::Render (const ContentContext& renderer,
182
+ const Entity& entity,
183
+ RenderPass& pass) const {
184
+ const std::shared_ptr<Context>& context = renderer.GetContext ();
185
+ const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary ();
148
186
187
+ // --------------------------------------------------------------------------
188
+ // / Get or register shader. Flutter will do this when the runtime effect
189
+ // / is first loaded, but this check is added to supporting testing of the
190
+ // / Aiks API and non-flutter usage of Impeller.
191
+ // /
192
+ if (!RegisterShader (renderer)) {
193
+ return false ;
194
+ }
195
+
196
+ // --------------------------------------------------------------------------
197
+ // / Fragment stage uniforms.
198
+ // /
199
+ BindFragmentCallback bind_callback = [this , &renderer,
200
+ &context](RenderPass& pass) {
149
201
size_t minimum_sampler_index = 100000000 ;
150
202
size_t buffer_index = 0 ;
151
203
size_t buffer_offset = 0 ;
@@ -173,9 +225,10 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
173
225
Context::BackendType::kVulkan )
174
226
<< " Uniform " << uniform.name
175
227
<< " had unexpected type kFloat for Vulkan backend." ;
228
+
176
229
size_t alignment =
177
230
std::max (uniform.bit_width / 8 , DefaultUniformAlignment ());
178
- auto buffer_view = renderer.GetTransientsBuffer ().Emplace (
231
+ BufferView buffer_view = renderer.GetTransientsBuffer ().Emplace (
179
232
uniform_data_->data () + buffer_offset, uniform.GetSize (),
180
233
alignment);
181
234
@@ -184,23 +237,20 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
184
237
uniform_slot.ext_res_0 = uniform.location ;
185
238
pass.BindResource (ShaderStage::kFragment ,
186
239
DescriptorType::kUniformBuffer , uniform_slot,
187
- metadata, buffer_view);
240
+ metadata, std::move ( buffer_view) );
188
241
buffer_index++;
189
242
buffer_offset += uniform.GetSize ();
190
243
break ;
191
244
}
192
245
case kStruct : {
193
246
FML_DCHECK (renderer.GetContext ()->GetBackendType () ==
194
247
Context::BackendType::kVulkan );
195
- descriptor_set_layouts.emplace_back (DescriptorSetLayout{
196
- static_cast <uint32_t >(uniform.location ),
197
- DescriptorType::kUniformBuffer ,
198
- ShaderStage::kFragment ,
199
- });
200
248
ShaderUniformSlot uniform_slot;
201
249
uniform_slot.name = uniform.name .c_str ();
202
250
uniform_slot.binding = uniform.location ;
203
251
252
+ // TODO(jonahwilliams): rewrite this to emplace directly into
253
+ // HostBuffer.
204
254
std::vector<float > uniform_buffer;
205
255
uniform_buffer.reserve (uniform.struct_layout .size ());
206
256
size_t uniform_byte_index = 0u ;
@@ -214,16 +264,15 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
214
264
FML_UNREACHABLE ();
215
265
}
216
266
}
217
-
218
267
size_t alignment = std::max (sizeof (float ) * uniform_buffer.size (),
219
268
DefaultUniformAlignment ());
220
269
221
- auto buffer_view = renderer.GetTransientsBuffer ().Emplace (
270
+ BufferView buffer_view = renderer.GetTransientsBuffer ().Emplace (
222
271
reinterpret_cast <const void *>(uniform_buffer.data ()),
223
272
sizeof (float ) * uniform_buffer.size (), alignment);
224
273
pass.BindResource (ShaderStage::kFragment ,
225
274
DescriptorType::kUniformBuffer , uniform_slot,
226
- ShaderMetadata{}, buffer_view);
275
+ ShaderMetadata{}, std::move ( buffer_view) );
227
276
}
228
277
}
229
278
}
@@ -243,20 +292,7 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
243
292
244
293
SampledImageSlot image_slot;
245
294
image_slot.name = uniform.name .c_str ();
246
-
247
- uint32_t sampler_binding_location = 0u ;
248
- if (!descriptor_set_layouts.empty ()) {
249
- sampler_binding_location =
250
- descriptor_set_layouts.back ().binding + 1 ;
251
- }
252
-
253
- descriptor_set_layouts.emplace_back (DescriptorSetLayout{
254
- sampler_binding_location,
255
- DescriptorType::kSampledImage ,
256
- ShaderStage::kFragment ,
257
- });
258
-
259
- image_slot.binding = sampler_binding_location;
295
+ image_slot.binding = uniform.binding ;
260
296
image_slot.texture_index = uniform.location - minimum_sampler_index;
261
297
pass.BindResource (ShaderStage::kFragment ,
262
298
DescriptorType::kSampledImage , image_slot,
@@ -273,47 +309,15 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
273
309
};
274
310
275
311
// / Now that the descriptor set layouts are known, get the pipeline.
312
+ using VS = RuntimeEffectVertexShader;
276
313
277
- PipelineBuilderCallback pipeline_callback = [&](ContentContextOptions
278
- options) {
279
- // Pipeline creation callback for the cache handler to call.
280
- auto create_callback =
281
- [&]() -> std::shared_ptr<Pipeline<PipelineDescriptor>> {
282
- PipelineDescriptor desc;
283
- desc.SetLabel (" Runtime Stage" );
284
- desc.AddStageEntrypoint (
285
- library->GetFunction (VS::kEntrypointName , ShaderStage::kVertex ));
286
- desc.AddStageEntrypoint (library->GetFunction (
287
- runtime_stage_->GetEntrypoint (), ShaderStage::kFragment ));
288
- auto vertex_descriptor = std::make_shared<VertexDescriptor>();
289
- vertex_descriptor->SetStageInputs (VS::kAllShaderStageInputs ,
290
- VS::kInterleavedBufferLayout );
291
- vertex_descriptor->RegisterDescriptorSetLayouts (
292
- VS::kDescriptorSetLayouts );
293
- vertex_descriptor->RegisterDescriptorSetLayouts (
294
- descriptor_set_layouts.data (), descriptor_set_layouts.size ());
295
- desc.SetVertexDescriptor (std::move (vertex_descriptor));
296
- desc.SetColorAttachmentDescriptor (
297
- 0u , {.format = color_attachment_format, .blending_enabled = true });
298
-
299
- desc.SetStencilAttachmentDescriptors (StencilAttachmentDescriptor{});
300
- desc.SetStencilPixelFormat (stencil_attachment_format);
301
-
302
- desc.SetDepthStencilAttachmentDescriptor (DepthAttachmentDescriptor{});
303
- desc.SetDepthPixelFormat (stencil_attachment_format);
304
-
305
- options.ApplyToPipelineDescriptor (desc);
306
- auto pipeline = context->GetPipelineLibrary ()->GetPipeline (desc).Get ();
307
- if (!pipeline) {
308
- VALIDATION_LOG << " Failed to get or create runtime effect pipeline." ;
309
- return nullptr ;
310
- }
311
-
312
- return pipeline;
313
- };
314
- return renderer.GetCachedRuntimeEffectPipeline (
315
- runtime_stage_->GetEntrypoint (), options, create_callback);
316
- };
314
+ PipelineBuilderCallback pipeline_callback =
315
+ [&](ContentContextOptions options) {
316
+ // Pipeline creation callback for the cache handler to call.
317
+ return renderer.GetCachedRuntimeEffectPipeline (
318
+ runtime_stage_->GetEntrypoint (), options,
319
+ [&]() { return CreatePipeline (renderer, options); });
320
+ };
317
321
318
322
return ColorSourceContents::DrawGeometry<VS>(renderer, entity, pass,
319
323
pipeline_callback,
0 commit comments