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,
37 size_t minimum_uniform_alignment) {
40 std::vector<float> uniform_buffer;
42 size_t uniform_byte_index = 0u;
44 if (byte_type == kPaddingType) {
45 uniform_buffer.push_back(0.f);
47 FML_DCHECK(byte_type == kFloatType);
48 uniform_buffer.push_back(
reinterpret_cast<const float*
>(
49 input_data->data())[uniform_byte_index++]);
52 size_t alignment = std::max(
sizeof(
float) * uniform_buffer.size(),
53 minimum_uniform_alignment);
56 reinterpret_cast<const void*
>(uniform_buffer.data()),
57 sizeof(
float) * uniform_buffer.size(), alignment);
61 std::shared_ptr<RuntimeStage> runtime_stage) {
62 runtime_stage_ = std::move(runtime_stage);
66 std::shared_ptr<std::vector<uint8_t>> uniform_data) {
67 uniform_data_ = std::move(uniform_data);
71 std::vector<TextureInput> texture_inputs) {
72 texture_inputs_ = std::move(texture_inputs);
88 std::unique_ptr<ShaderMetadata> metadata = std::make_unique<ShaderMetadata>();
89 metadata->name = uniform.
name;
104 if (!RegisterShader(renderer)) {
109 renderer.
GetContext()->GetCapabilities()->GetDefaultColorFormat();
110 CreatePipeline(renderer, options,
true);
114 bool RuntimeEffectContents::RegisterShader(
116 const std::shared_ptr<Context>& context = renderer.
GetContext();
117 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
119 std::shared_ptr<const ShaderFunction>
function = library->GetFunction(
126 if (
function && runtime_stage_->IsDirty()) {
128 context->GetPipelineLibrary()->RemovePipelinesWithEntryPoint(
function);
129 library->UnregisterFunction(runtime_stage_->GetEntrypoint(),
136 std::promise<bool> promise;
137 auto future = promise.get_future();
139 library->RegisterFunction(
140 runtime_stage_->GetEntrypoint(),
142 runtime_stage_->GetCodeMapping(),
143 fml::MakeCopyable([promise = std::move(promise)](
bool result)
mutable {
144 promise.set_value(result);
149 << runtime_stage_->GetEntrypoint() <<
")";
153 function = library->GetFunction(runtime_stage_->GetEntrypoint(),
157 <<
"Failed to fetch runtime effect function immediately after "
158 "registering it (entry point: "
159 << runtime_stage_->GetEntrypoint() <<
")";
163 runtime_stage_->SetClean();
168 std::shared_ptr<Pipeline<PipelineDescriptor>>
169 RuntimeEffectContents::CreatePipeline(
const ContentContext& renderer,
170 ContentContextOptions options,
172 const std::shared_ptr<Context>& context = renderer.GetContext();
173 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
174 const std::shared_ptr<const Capabilities>& caps = context->GetCapabilities();
175 const PixelFormat color_attachment_format = caps->GetDefaultColorFormat();
177 caps->GetDefaultDepthStencilFormat();
179 using VS = RuntimeEffectVertexShader;
181 PipelineDescriptor desc;
182 desc.SetLabel(
"Runtime Stage");
183 desc.AddStageEntrypoint(
185 desc.AddStageEntrypoint(library->GetFunction(runtime_stage_->GetEntrypoint(),
188 std::shared_ptr<VertexDescriptor> vertex_descriptor =
189 std::make_shared<VertexDescriptor>();
190 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
191 VS::kInterleavedBufferLayout);
192 vertex_descriptor->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
193 vertex_descriptor->RegisterDescriptorSetLayouts(
194 runtime_stage_->GetDescriptorSetLayouts().data(),
195 runtime_stage_->GetDescriptorSetLayouts().size());
196 desc.SetVertexDescriptor(std::move(vertex_descriptor));
197 desc.SetColorAttachmentDescriptor(
198 0u, {.format = color_attachment_format, .blending_enabled =
true});
200 desc.SetStencilAttachmentDescriptors(StencilAttachmentDescriptor{});
201 desc.SetStencilPixelFormat(stencil_attachment_format);
203 desc.SetDepthStencilAttachmentDescriptor(DepthAttachmentDescriptor{});
204 desc.SetDepthPixelFormat(stencil_attachment_format);
206 options.ApplyToPipelineDescriptor(desc);
208 context->GetPipelineLibrary()->GetPipeline(desc, async);
212 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc, async).Get();
214 VALIDATION_LOG <<
"Failed to get or create runtime effect pipeline.";
224 const std::shared_ptr<Context>& context = renderer.
GetContext();
225 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
232 if (!RegisterShader(renderer)) {
241 size_t buffer_index = 0;
242 size_t buffer_offset = 0;
243 size_t sampler_location = 0;
244 size_t buffer_location = 0;
254 for (
const auto& uniform : runtime_stage_->GetUniforms()) {
256 switch (uniform.type) {
258 FML_DCHECK(sampler_location < texture_inputs_.size());
259 auto& input = texture_inputs_[sampler_location];
262 context->GetSamplerLibrary()->GetSampler(
263 input.sampler_descriptor);
266 image_slot.
name = uniform.name.c_str();
267 image_slot.
binding = uniform.binding;
271 std::move(metadata), input.texture, sampler);
276 FML_DCHECK(renderer.
GetContext()->GetBackendType() !=
278 <<
"Uniform " << uniform.name
279 <<
" had unexpected type kFloat for Vulkan backend.";
281 size_t alignment = std::max(uniform.bit_width / 8,
282 host_buffer.GetMinimumUniformAlignment());
284 host_buffer.Emplace(uniform_data_->data() + buffer_offset,
285 uniform.GetSize(), alignment);
288 uniform_slot.
name = uniform.name.c_str();
289 uniform_slot.
ext_res_0 = buffer_location;
294 buffer_offset += uniform.GetSize();
299 FML_DCHECK(renderer.
GetContext()->GetBackendType() ==
302 uniform_slot.
binding = uniform.location;
303 uniform_slot.
name = uniform.name.c_str();
307 uniform_slot,
nullptr,
309 host_buffer.GetMinimumUniformAlignment()));
318 using VS = RuntimeEffectVertexShader;
324 runtime_stage_->GetEntrypoint(), options, [&]() {
325 return CreatePipeline(renderer, options,
false);
329 return ColorSourceContents::DrawGeometry<VS>(renderer, entity, pass,
331 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
static BufferView EmplaceVulkanUniform(const std::shared_ptr< const std::vector< uint8_t >> &input_data, HostBuffer &host_buffer, const RuntimeUniformDescription &uniform, size_t minimum_uniform_alignment)
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)
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.