11 #include "flutter/fml/logging.h"
12 #include "flutter/fml/make_copyable.h"
18 #include "impeller/entity/runtime_effect.vert.h"
28 constexpr
char kPaddingType = 0;
29 constexpr
char kFloatType = 1;
34 const std::shared_ptr<
const std::vector<uint8_t>>& input_data,
39 std::vector<float> uniform_buffer;
41 size_t uniform_byte_index = 0u;
43 if (byte_type == kPaddingType) {
44 uniform_buffer.push_back(0.f);
46 FML_DCHECK(byte_type == kFloatType);
47 uniform_buffer.push_back(
reinterpret_cast<const float*
>(
48 input_data->data())[uniform_byte_index++]);
51 size_t alignment = std::max(
sizeof(
float) * uniform_buffer.size(),
55 reinterpret_cast<const void*
>(uniform_buffer.data()),
56 sizeof(
float) * uniform_buffer.size(), alignment);
60 std::shared_ptr<RuntimeStage> runtime_stage) {
61 runtime_stage_ = std::move(runtime_stage);
65 std::shared_ptr<std::vector<uint8_t>> uniform_data) {
66 uniform_data_ = std::move(uniform_data);
70 std::vector<TextureInput> texture_inputs) {
71 texture_inputs_ = std::move(texture_inputs);
87 std::unique_ptr<ShaderMetadata> metadata = std::make_unique<ShaderMetadata>();
88 metadata->name = uniform.
name;
100 if (!RegisterShader(renderer)) {
105 renderer.
GetContext()->GetCapabilities()->GetDefaultColorFormat();
106 CreatePipeline(renderer, options,
true);
110 bool RuntimeEffectContents::RegisterShader(
112 const std::shared_ptr<Context>& context = renderer.
GetContext();
113 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
115 std::shared_ptr<const ShaderFunction>
function = library->GetFunction(
122 if (
function && runtime_stage_->IsDirty()) {
124 context->GetPipelineLibrary()->RemovePipelinesWithEntryPoint(
function);
125 library->UnregisterFunction(runtime_stage_->GetEntrypoint(),
132 std::promise<bool> promise;
133 auto future = promise.get_future();
135 library->RegisterFunction(
136 runtime_stage_->GetEntrypoint(),
138 runtime_stage_->GetCodeMapping(),
139 fml::MakeCopyable([promise = std::move(promise)](
bool result)
mutable {
140 promise.set_value(result);
145 << runtime_stage_->GetEntrypoint() <<
")";
149 function = library->GetFunction(runtime_stage_->GetEntrypoint(),
153 <<
"Failed to fetch runtime effect function immediately after "
154 "registering it (entry point: "
155 << runtime_stage_->GetEntrypoint() <<
")";
159 runtime_stage_->SetClean();
164 std::shared_ptr<Pipeline<PipelineDescriptor>>
165 RuntimeEffectContents::CreatePipeline(
const ContentContext& renderer,
166 ContentContextOptions options,
168 const std::shared_ptr<Context>& context = renderer.GetContext();
169 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
170 const std::shared_ptr<const Capabilities>& caps = context->GetCapabilities();
171 const auto color_attachment_format = caps->GetDefaultColorFormat();
172 const auto stencil_attachment_format = caps->GetDefaultDepthStencilFormat();
174 using VS = RuntimeEffectVertexShader;
176 PipelineDescriptor desc;
177 desc.SetLabel(
"Runtime Stage");
178 desc.AddStageEntrypoint(
180 desc.AddStageEntrypoint(library->GetFunction(runtime_stage_->GetEntrypoint(),
183 std::shared_ptr<VertexDescriptor> vertex_descriptor =
184 std::make_shared<VertexDescriptor>();
185 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
186 VS::kInterleavedBufferLayout);
187 vertex_descriptor->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
188 vertex_descriptor->RegisterDescriptorSetLayouts(
189 runtime_stage_->GetDescriptorSetLayouts().data(),
190 runtime_stage_->GetDescriptorSetLayouts().size());
191 desc.SetVertexDescriptor(std::move(vertex_descriptor));
192 desc.SetColorAttachmentDescriptor(
193 0u, {.format = color_attachment_format, .blending_enabled =
true});
195 desc.SetStencilAttachmentDescriptors(StencilAttachmentDescriptor{});
196 desc.SetStencilPixelFormat(stencil_attachment_format);
198 desc.SetDepthStencilAttachmentDescriptor(DepthAttachmentDescriptor{});
199 desc.SetDepthPixelFormat(stencil_attachment_format);
201 options.ApplyToPipelineDescriptor(desc);
203 context->GetPipelineLibrary()->GetPipeline(desc, async);
207 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc, async).Get();
209 VALIDATION_LOG <<
"Failed to get or create runtime effect pipeline.";
219 const std::shared_ptr<Context>& context = renderer.
GetContext();
220 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
227 if (!RegisterShader(renderer)) {
236 size_t minimum_sampler_index = 100000000;
237 size_t buffer_index = 0;
238 size_t buffer_offset = 0;
240 for (
const auto& uniform : runtime_stage_->GetUniforms()) {
242 switch (uniform.type) {
253 minimum_sampler_index =
254 std::min(minimum_sampler_index, uniform.location);
258 FML_DCHECK(renderer.
GetContext()->GetBackendType() !=
260 <<
"Uniform " << uniform.name
261 <<
" had unexpected type kFloat for Vulkan backend.";
266 uniform_data_->data() + buffer_offset, uniform.GetSize(),
270 uniform_slot.
name = uniform.name.c_str();
271 uniform_slot.
ext_res_0 = uniform.location;
276 buffer_offset += uniform.GetSize();
280 FML_DCHECK(renderer.
GetContext()->GetBackendType() ==
283 uniform_slot.
binding = uniform.location;
284 uniform_slot.
name = uniform.name.c_str();
288 uniform_slot,
nullptr,
295 size_t sampler_index = 0;
296 for (
const auto& uniform : runtime_stage_->GetUniforms()) {
299 switch (uniform.type) {
301 FML_DCHECK(sampler_index < texture_inputs_.size());
302 auto& input = texture_inputs_[sampler_index];
305 context->GetSamplerLibrary()->GetSampler(
306 input.sampler_descriptor);
309 image_slot.
name = uniform.name.c_str();
310 image_slot.
binding = uniform.binding;
311 image_slot.
texture_index = uniform.location - minimum_sampler_index;
314 std::move(metadata), input.texture, sampler);
327 using VS = RuntimeEffectVertexShader;
333 runtime_stage_->GetEntrypoint(), options, [&]() {
334 return CreatePipeline(renderer, options,
false);
338 return ColorSourceContents::DrawGeometry<VS>(renderer, entity, pass,
340 VS::FrameInfo{}, bind_callback);
std::function< PipelineRef(ContentContextOptions)> PipelineBuilderCallback
std::function< bool(RenderPass &pass)> BindFragmentCallback
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
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.
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 EmplaceVulkanUniform(const std::shared_ptr< const std::vector< uint8_t >> &input_data, HostBuffer &host_buffer, const RuntimeUniformDescription &uniform)
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)
GlyphAtlasPipeline::VertexShader VS
static std::unique_ptr< ShaderMetadata > MakeShaderMetadata(const RuntimeUniformDescription &uniform)
static ShaderType GetShaderType(RuntimeUniformType type)
constexpr size_t DefaultUniformAlignment()
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.