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 PixelFormat color_attachment_format = caps->GetDefaultColorFormat();
173 caps->GetDefaultDepthStencilFormat();
175 using VS = RuntimeEffectVertexShader;
177 PipelineDescriptor desc;
178 desc.SetLabel(
"Runtime Stage");
179 desc.AddStageEntrypoint(
181 desc.AddStageEntrypoint(library->GetFunction(runtime_stage_->GetEntrypoint(),
184 std::shared_ptr<VertexDescriptor> vertex_descriptor =
185 std::make_shared<VertexDescriptor>();
186 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
187 VS::kInterleavedBufferLayout);
188 vertex_descriptor->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
189 vertex_descriptor->RegisterDescriptorSetLayouts(
190 runtime_stage_->GetDescriptorSetLayouts().data(),
191 runtime_stage_->GetDescriptorSetLayouts().size());
192 desc.SetVertexDescriptor(std::move(vertex_descriptor));
193 desc.SetColorAttachmentDescriptor(
194 0u, {.format = color_attachment_format, .blending_enabled =
true});
196 desc.SetStencilAttachmentDescriptors(StencilAttachmentDescriptor{});
197 desc.SetStencilPixelFormat(stencil_attachment_format);
199 desc.SetDepthStencilAttachmentDescriptor(DepthAttachmentDescriptor{});
200 desc.SetDepthPixelFormat(stencil_attachment_format);
202 options.ApplyToPipelineDescriptor(desc);
204 context->GetPipelineLibrary()->GetPipeline(desc, async);
208 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc, async).Get();
210 VALIDATION_LOG <<
"Failed to get or create runtime effect pipeline.";
220 const std::shared_ptr<Context>& context = renderer.
GetContext();
221 const std::shared_ptr<ShaderLibrary>& library = context->GetShaderLibrary();
228 if (!RegisterShader(renderer)) {
237 size_t buffer_index = 0;
238 size_t buffer_offset = 0;
239 size_t sampler_location = 0;
240 size_t buffer_location = 0;
249 for (
const auto& uniform : runtime_stage_->GetUniforms()) {
251 switch (uniform.type) {
253 FML_DCHECK(sampler_location < texture_inputs_.size());
254 auto& input = texture_inputs_[sampler_location];
257 context->GetSamplerLibrary()->GetSampler(
258 input.sampler_descriptor);
261 image_slot.
name = uniform.name.c_str();
262 image_slot.
binding = uniform.binding;
266 std::move(metadata), input.texture, sampler);
271 FML_DCHECK(renderer.
GetContext()->GetBackendType() !=
273 <<
"Uniform " << uniform.name
274 <<
" had unexpected type kFloat for Vulkan backend.";
279 uniform_data_->data() + buffer_offset, uniform.GetSize(),
283 uniform_slot.
name = uniform.name.c_str();
284 uniform_slot.
ext_res_0 = buffer_location;
289 buffer_offset += uniform.GetSize();
294 FML_DCHECK(renderer.
GetContext()->GetBackendType() ==
297 uniform_slot.
binding = uniform.location;
298 uniform_slot.
name = uniform.name.c_str();
302 uniform_slot,
nullptr,
313 using VS = RuntimeEffectVertexShader;
319 runtime_stage_->GetEntrypoint(), options, [&]() {
320 return CreatePipeline(renderer, options,
false);
324 return ColorSourceContents::DrawGeometry<VS>(renderer, entity, pass,
326 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)
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
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.