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++) {
60 float_destination[struct_float_index++] = 0.f;
63 float_destination[struct_float_index++] =
64 float_source[uniform_byte_index++];
71void RuntimeEffectContents::SetRuntimeStage(
72 std::shared_ptr<RuntimeStage> runtime_stage) {
73 runtime_stage_ = std::move(runtime_stage);
76void RuntimeEffectContents::SetUniformData(
77 std::shared_ptr<std::vector<uint8_t>> uniform_data) {
78 uniform_data_ = std::move(uniform_data);
81void RuntimeEffectContents::SetTextureInputs(
82 std::vector<TextureInput> texture_inputs) {
83 texture_inputs_ = std::move(texture_inputs);
89 return ShaderType::kSampledImage;
91 return ShaderType::kFloat;
93 return ShaderType::kStruct;
99 std::unique_ptr<ShaderMetadata> metadata = std::make_unique<ShaderMetadata>();
100 metadata->name = uniform.
name;
104 std::optional<size_t> array_elements;
114 .byte_length = member_size * array_elements.value_or(1),
115 .array_elements = array_elements
121bool RuntimeEffectContents::BootstrapShader(
123 if (!RegisterShader(renderer)) {
128 renderer.
GetContext()->GetCapabilities()->GetDefaultColorFormat();
129 CreatePipeline(renderer, options,
true);
133bool RuntimeEffectContents::RegisterShader(
135 const std::shared_ptr<Context>& context = renderer.
GetContext();
136 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
138 std::shared_ptr<const ShaderFunction>
function = library->GetFunction(
139 runtime_stage_->GetEntrypoint(), ShaderStage::kFragment);
145 if (function && runtime_stage_->IsDirty()) {
147 context->GetPipelineLibrary()->RemovePipelinesWithEntryPoint(function);
148 library->UnregisterFunction(runtime_stage_->GetEntrypoint(),
149 ShaderStage::kFragment);
155 std::promise<bool> promise;
156 auto future = promise.get_future();
158 library->RegisterFunction(
159 runtime_stage_->GetEntrypoint(),
160 ToShaderStage(runtime_stage_->GetShaderStage()),
161 runtime_stage_->GetCodeMapping(),
163 promise.set_value(result);
168 << runtime_stage_->GetEntrypoint() <<
")";
172 function = library->GetFunction(runtime_stage_->GetEntrypoint(),
173 ShaderStage::kFragment);
176 <<
"Failed to fetch runtime effect function immediately after "
177 "registering it (entry point: "
178 << runtime_stage_->GetEntrypoint() <<
")";
182 runtime_stage_->SetClean();
187std::shared_ptr<Pipeline<PipelineDescriptor>>
188RuntimeEffectContents::CreatePipeline(
const ContentContext& renderer,
189 ContentContextOptions options,
191 const std::shared_ptr<Context>& context = renderer.GetContext();
192 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
193 const std::shared_ptr<const Capabilities>& caps = context->GetCapabilities();
194 const PixelFormat color_attachment_format = caps->GetDefaultColorFormat();
196 caps->GetDefaultDepthStencilFormat();
198 using VS = RuntimeEffectVertexShader;
200 PipelineDescriptor desc;
201 desc.SetLabel(
"Runtime Stage");
202 desc.AddStageEntrypoint(
203 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
204 desc.AddStageEntrypoint(library->GetFunction(runtime_stage_->GetEntrypoint(),
205 ShaderStage::kFragment));
207 std::shared_ptr<VertexDescriptor> vertex_descriptor =
208 std::make_shared<VertexDescriptor>();
209 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
210 VS::kInterleavedBufferLayout);
211 vertex_descriptor->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
212 vertex_descriptor->RegisterDescriptorSetLayouts(
213 runtime_stage_->GetDescriptorSetLayouts().data(),
214 runtime_stage_->GetDescriptorSetLayouts().size());
215 desc.SetVertexDescriptor(std::move(vertex_descriptor));
216 desc.SetColorAttachmentDescriptor(
217 0u, {.format = color_attachment_format, .blending_enabled =
true});
219 desc.SetStencilAttachmentDescriptors(StencilAttachmentDescriptor{});
220 desc.SetStencilPixelFormat(stencil_attachment_format);
222 desc.SetDepthStencilAttachmentDescriptor(DepthAttachmentDescriptor{});
223 desc.SetDepthPixelFormat(stencil_attachment_format);
225 options.ApplyToPipelineDescriptor(desc);
227 context->GetPipelineLibrary()->GetPipeline(desc, async);
231 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc, async).Get();
233 VALIDATION_LOG <<
"Failed to get or create runtime effect pipeline.";
243 const std::shared_ptr<Context>& context = renderer.
GetContext();
244 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
251 if (!RegisterShader(renderer)) {
260 size_t buffer_index = 0;
261 size_t buffer_offset = 0;
262 size_t sampler_location = 0;
263 size_t buffer_location = 0;
273 for (
const auto& uniform : runtime_stage_->GetUniforms()) {
275 switch (uniform.type) {
277 FML_DCHECK(sampler_location < texture_inputs_.size());
278 auto&
input = texture_inputs_[sampler_location];
281 context->GetSamplerLibrary()->GetSampler(
282 input.sampler_descriptor);
285 image_slot.
name = uniform.name.c_str();
286 image_slot.
binding = uniform.binding;
289 DescriptorType::kSampledImage, image_slot,
290 std::move(metadata),
input.texture, sampler);
296 Context::BackendType::kVulkan)
297 <<
"Uniform " << uniform.name
298 <<
" had unexpected type kFloat for Vulkan backend.";
301 uniform_data_->data() + buffer_offset, data_host_buffer, uniform);
304 uniform_slot.
name = uniform.name.c_str();
305 uniform_slot.
ext_res_0 = buffer_location;
307 DescriptorType::kUniformBuffer, uniform_slot,
310 buffer_offset += uniform.GetDartSize();
316 Context::BackendType::kVulkan);
318 uniform_slot.
binding = uniform.location;
319 uniform_slot.
name = uniform.name.c_str();
322 ShaderStage::kFragment, DescriptorType::kUniformBuffer,
323 uniform_slot,
nullptr,
324 EmplaceUniform(uniform_data_->data(), data_host_buffer, uniform));
333 using VS = RuntimeEffectVertexShader;
339 runtime_stage_->GetEntrypoint(), options, [&]() {
340 return CreatePipeline(renderer, options,
false);
344 return ColorSourceContents::DrawGeometry<VS>(renderer, entity, pass,
346 VS::FrameInfo{}, bind_callback);
std::function< PipelineRef(ContentContextOptions)> PipelineBuilderCallback
std::function< bool(RenderPass &pass)> BindFragmentCallback
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
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
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
static BufferView EmplaceUniform(const uint8_t *source_data, HostBuffer &host_buffer, const RuntimeUniformDescription &uniform)
A wrapper around a raw ptr that adds additional unopt mode only checks.
#define FML_DCHECK(condition)
Dart_NativeFunction function
internal::CopyableLambda< T > MakeCopyable(T lambda)
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
static ShaderType GetShaderType(RuntimeUniformType type)
static std::unique_ptr< ShaderMetadata > MakeShaderMetadata(const RuntimeUniformDescription &uniform)
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.