11 #include "flutter/fml/logging.h"
12 #include "flutter/fml/make_copyable.h"
18 #include "impeller/entity/runtime_effect.vert.h"
29 const uint8_t* source_data,
32 size_t minimum_uniform_alignment =
34 size_t alignment = std::max(uniform.
bit_width / 8, minimum_uniform_alignment);
44 return data_host_buffer.
Emplace(
46 [&uniform, source_data](uint8_t* destination) {
47 size_t count = uniform.array_elements.value_or(1);
52 size_t uniform_byte_index = 0u;
53 size_t struct_float_index = 0u;
54 auto* float_destination =
reinterpret_cast<float*
>(destination);
55 auto* float_source =
reinterpret_cast<const float*
>(source_data);
57 for (
size_t i = 0; i < count; i++) {
59 if (byte_type == RuntimePaddingType::kPadding) {
60 float_destination[struct_float_index++] = 0.f;
62 FML_DCHECK(byte_type == RuntimePaddingType::kFloat);
63 float_destination[struct_float_index++] =
64 float_source[uniform_byte_index++];
71 RuntimeEffectContents::RuntimeEffectContents(
const Geometry* geometry)
72 : geometry_(geometry) {}
81 std::shared_ptr<RuntimeStage> runtime_stage) {
82 runtime_stage_ = std::move(runtime_stage);
86 std::shared_ptr<std::vector<uint8_t>> uniform_data) {
87 uniform_data_ = std::move(uniform_data);
91 std::vector<TextureInput> texture_inputs) {
92 texture_inputs_ = std::move(texture_inputs);
108 std::unique_ptr<ShaderMetadata> metadata = std::make_unique<ShaderMetadata>();
109 metadata->name = uniform.
name;
113 std::optional<size_t> array_elements;
122 std::optional<ShaderFloatType> float_type;
157 .byte_length = member_size * array_elements.value_or(1),
158 .array_elements = array_elements,
159 .float_type = float_type,
167 if (!RegisterShader(renderer)) {
172 renderer.
GetContext()->GetCapabilities()->GetDefaultColorFormat();
173 CreatePipeline(renderer, options,
true);
177 bool RuntimeEffectContents::RegisterShader(
179 const std::shared_ptr<Context>& context = renderer.
GetContext();
180 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
182 std::shared_ptr<const ShaderFunction>
function = library->GetFunction(
189 if (
function && runtime_stage_->IsDirty()) {
191 context->GetPipelineLibrary()->RemovePipelinesWithEntryPoint(
function);
192 library->UnregisterFunction(runtime_stage_->GetEntrypoint(),
199 std::promise<bool> promise;
200 auto future = promise.get_future();
202 library->RegisterFunction(
203 runtime_stage_->GetEntrypoint(),
205 runtime_stage_->GetCodeMapping(),
206 fml::MakeCopyable([promise = std::move(promise)](
bool result)
mutable {
207 promise.set_value(result);
212 << runtime_stage_->GetEntrypoint() <<
")";
216 function = library->GetFunction(runtime_stage_->GetEntrypoint(),
220 <<
"Failed to fetch runtime effect function immediately after "
221 "registering it (entry point: "
222 << runtime_stage_->GetEntrypoint() <<
")";
226 runtime_stage_->SetClean();
231 std::shared_ptr<Pipeline<PipelineDescriptor>>
232 RuntimeEffectContents::CreatePipeline(
const ContentContext& renderer,
233 ContentContextOptions options,
235 const std::shared_ptr<Context>& context = renderer.GetContext();
236 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
237 const std::shared_ptr<const Capabilities>& caps = context->GetCapabilities();
238 const PixelFormat color_attachment_format = caps->GetDefaultColorFormat();
240 caps->GetDefaultDepthStencilFormat();
242 using VS = RuntimeEffectVertexShader;
244 PipelineDescriptor desc;
245 desc.SetLabel(
"Runtime Stage");
246 desc.AddStageEntrypoint(
248 desc.AddStageEntrypoint(library->GetFunction(runtime_stage_->GetEntrypoint(),
251 std::shared_ptr<VertexDescriptor> vertex_descriptor =
252 std::make_shared<VertexDescriptor>();
253 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
254 VS::kInterleavedBufferLayout);
255 vertex_descriptor->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
256 vertex_descriptor->RegisterDescriptorSetLayouts(
257 runtime_stage_->GetDescriptorSetLayouts().data(),
258 runtime_stage_->GetDescriptorSetLayouts().size());
259 desc.SetVertexDescriptor(std::move(vertex_descriptor));
260 desc.SetColorAttachmentDescriptor(
261 0u, {.format = color_attachment_format, .blending_enabled =
true});
263 desc.SetStencilAttachmentDescriptors(StencilAttachmentDescriptor{});
264 desc.SetStencilPixelFormat(stencil_attachment_format);
266 desc.SetDepthStencilAttachmentDescriptor(DepthAttachmentDescriptor{});
267 desc.SetDepthPixelFormat(stencil_attachment_format);
269 options.ApplyToPipelineDescriptor(desc);
271 context->GetPipelineLibrary()->GetPipeline(desc, async);
275 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc, async).Get();
277 VALIDATION_LOG <<
"Failed to get or create runtime effect pipeline.";
287 const std::shared_ptr<Context>& context = renderer.
GetContext();
288 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
295 if (!RegisterShader(renderer)) {
304 size_t buffer_index = 0;
305 size_t buffer_offset = 0;
306 size_t sampler_location = 0;
307 size_t buffer_location = 0;
317 for (
const auto& uniform : runtime_stage_->GetUniforms()) {
319 switch (uniform.type) {
321 FML_DCHECK(sampler_location < texture_inputs_.size());
322 auto& input = texture_inputs_[sampler_location];
325 context->GetSamplerLibrary()->GetSampler(
326 input.sampler_descriptor);
329 image_slot.
name = uniform.name.c_str();
330 image_slot.
binding = uniform.binding;
334 std::move(metadata), input.texture, sampler);
339 FML_DCHECK(renderer.
GetContext()->GetBackendType() !=
341 <<
"Uniform " << uniform.name
342 <<
" had unexpected type kFloat for Vulkan backend.";
345 uniform_data_->data() + buffer_offset, data_host_buffer, uniform);
348 uniform_slot.
name = uniform.name.c_str();
349 uniform_slot.
ext_res_0 = buffer_location;
352 std::move(metadata), std::move(buffer_view));
354 buffer_offset += uniform.GetDartSize();
359 FML_DCHECK(renderer.
GetContext()->GetBackendType() ==
362 uniform_slot.
binding = uniform.location;
363 uniform_slot.
name = uniform.name.c_str();
367 uniform_slot,
nullptr,
368 EmplaceUniform(uniform_data_->data(), data_host_buffer, uniform));
377 using VS = RuntimeEffectVertexShader;
383 runtime_stage_->GetEntrypoint(), options, [&]() {
384 return CreatePipeline(renderer, options,
false);
388 return ColorSourceContents::DrawGeometry<VS>(renderer, entity, pass,
390 VS::FrameInfo{}, bind_callback);
std::function< PipelineRef(ContentContextOptions)> PipelineBuilderCallback
std::function< bool(RenderPass &pass)> BindFragmentCallback
void ClearCachedRuntimeEffectPipeline(const std::string &unique_entrypoint_name) const
PipelineRef GetCachedRuntimeEffectPipeline(const std::string &unique_entrypoint_name, const ContentContextOptions &options, const std::function< std::shared_ptr< Pipeline< PipelineDescriptor >>()> &create_callback) const
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
std::shared_ptr< Context > GetContext() const
BufferView Emplace(const BufferType &buffer, size_t alignment=0)
Emplace non-uniform data (like contiguous vertices) onto the host buffer.
size_t GetMinimumUniformAlignment() const
Retrieve the minimum uniform buffer alignment in bytes.
Render passes encode render commands directed as one specific render target into an underlying comman...
virtual bool BindDynamicResource(ShaderStage stage, DescriptorType type, const SampledImageSlot &slot, std::unique_ptr< ShaderMetadata > metadata, std::shared_ptr< const Texture > texture, raw_ptr< const Sampler >)
Bind with dynamically generated shader metadata.
virtual bool BindResource(ShaderStage stage, DescriptorType type, const ShaderUniformSlot &slot, const ShaderMetadata *metadata, BufferView view) override
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
bool BootstrapShader(const ContentContext &renderer) const
Load the runtime effect and ensure a default PSO is initialized.
void SetRuntimeStage(std::shared_ptr< RuntimeStage > runtime_stage)
void SetTextureInputs(std::vector< TextureInput > texture_inputs)
static BufferView EmplaceUniform(const uint8_t *source_data, HostBuffer &host_buffer, const RuntimeUniformDescription &uniform)
const Geometry * GetGeometry() const override
Get the geometry that this contents will use to render.
~RuntimeEffectContents() override
void SetUniformData(std::shared_ptr< std::vector< uint8_t >> uniform_data)
A wrapper around a raw ptr that adds additional unopt mode only checks.
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
static std::unique_ptr< ShaderMetadata > MakeShaderMetadata(const RuntimeUniformDescription &uniform)
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
static ShaderType GetShaderType(RuntimeUniformType type)
LinePipeline::VertexShader VS
PixelFormat color_attachment_pixel_format
Metadata required to bind a combined texture and sampler.
size_t texture_index
ext_res_0 is the Metal binding value.
const char * name
The name of the uniform slot.
size_t binding
The Vulkan binding value.