[Impeller] Implement support for RuntimeEffect samplers (flutter/engine#37026)
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "display_list/display_list_blend_mode.h"
|
||||
#include "display_list/display_list_color_filter.h"
|
||||
@@ -436,11 +437,28 @@ void DisplayListDispatcher::setColorSource(
|
||||
auto runtime_stage =
|
||||
runtime_effect_color_source->runtime_effect()->runtime_stage();
|
||||
auto uniform_data = runtime_effect_color_source->uniform_data();
|
||||
auto samplers = runtime_effect_color_source->samplers();
|
||||
|
||||
paint_.color_source = [runtime_stage, uniform_data]() {
|
||||
std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
|
||||
|
||||
for (auto& sampler : samplers) {
|
||||
auto* image = sampler->asImage();
|
||||
if (!sampler->asImage()) {
|
||||
UNIMPLEMENTED;
|
||||
return;
|
||||
}
|
||||
FML_DCHECK(image->image()->impeller_texture());
|
||||
texture_inputs.push_back({
|
||||
.sampler_descriptor = ToSamplerDescriptor(image->sampling()),
|
||||
.texture = image->image()->impeller_texture(),
|
||||
});
|
||||
}
|
||||
|
||||
paint_.color_source = [runtime_stage, uniform_data, texture_inputs]() {
|
||||
auto contents = std::make_shared<RuntimeEffectContents>();
|
||||
contents->SetRuntimeStage(runtime_stage);
|
||||
contents->SetUniformData(uniform_data);
|
||||
contents->SetTextureInputs(texture_inputs);
|
||||
return contents;
|
||||
};
|
||||
return;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "impeller/renderer/formats.h"
|
||||
#include "impeller/renderer/pipeline_library.h"
|
||||
#include "impeller/renderer/render_pass.h"
|
||||
#include "impeller/renderer/sampler_library.h"
|
||||
#include "impeller/renderer/shader_function.h"
|
||||
#include "impeller/renderer/shader_types.h"
|
||||
|
||||
@@ -31,6 +32,11 @@ void RuntimeEffectContents::SetUniformData(
|
||||
uniform_data_ = std::move(uniform_data);
|
||||
}
|
||||
|
||||
void RuntimeEffectContents::SetTextureInputs(
|
||||
std::vector<TextureInput> texture_inputs) {
|
||||
texture_inputs_ = std::move(texture_inputs);
|
||||
}
|
||||
|
||||
bool RuntimeEffectContents::Render(const ContentContext& renderer,
|
||||
const Entity& entity,
|
||||
RenderPass& pass) const {
|
||||
@@ -136,21 +142,59 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
|
||||
///
|
||||
|
||||
size_t buffer_index = 0;
|
||||
size_t sampler_index = 0;
|
||||
for (auto uniform : runtime_stage_->GetUniforms()) {
|
||||
// TODO(113715): Populate this metadata once GLES is able to handle
|
||||
// non-struct uniform names.
|
||||
ShaderMetadata metadata;
|
||||
|
||||
size_t alignment =
|
||||
std::max(uniform.bit_width / 8, DefaultUniformAlignment());
|
||||
auto buffer_view = pass.GetTransientsBuffer().Emplace(
|
||||
uniform_data_->data() + uniform.location * sizeof(float),
|
||||
uniform.GetSize(), alignment);
|
||||
switch (uniform.type) {
|
||||
case kSampledImage: {
|
||||
FML_DCHECK(sampler_index < texture_inputs_.size());
|
||||
auto& input = texture_inputs_[sampler_index];
|
||||
|
||||
ShaderUniformSlot slot;
|
||||
slot.name = uniform.name.c_str();
|
||||
slot.ext_res_0 = buffer_index;
|
||||
cmd.BindResource(ShaderStage::kFragment, slot, metadata, buffer_view);
|
||||
auto sampler =
|
||||
context->GetSamplerLibrary()->GetSampler(input.sampler_descriptor);
|
||||
|
||||
SampledImageSlot image_slot;
|
||||
image_slot.name = uniform.name.c_str();
|
||||
image_slot.texture_index = sampler_index;
|
||||
image_slot.sampler_index = sampler_index;
|
||||
cmd.BindResource(ShaderStage::kFragment, image_slot, metadata,
|
||||
input.texture, sampler);
|
||||
|
||||
sampler_index++;
|
||||
break;
|
||||
}
|
||||
case kFloat: {
|
||||
size_t alignment =
|
||||
std::max(uniform.bit_width / 8, DefaultUniformAlignment());
|
||||
auto buffer_view = pass.GetTransientsBuffer().Emplace(
|
||||
uniform_data_->data() + uniform.location * sizeof(float),
|
||||
uniform.GetSize(), alignment);
|
||||
|
||||
ShaderUniformSlot uniform_slot;
|
||||
uniform_slot.name = uniform.name.c_str();
|
||||
uniform_slot.ext_res_0 = buffer_index;
|
||||
cmd.BindResource(ShaderStage::kFragment, uniform_slot, metadata,
|
||||
buffer_view);
|
||||
break;
|
||||
}
|
||||
case kBoolean:
|
||||
case kSignedByte:
|
||||
case kUnsignedByte:
|
||||
case kSignedShort:
|
||||
case kUnsignedShort:
|
||||
case kSignedInt:
|
||||
case kUnsignedInt:
|
||||
case kSignedInt64:
|
||||
case kUnsignedInt64:
|
||||
case kHalfFloat:
|
||||
case kDouble:
|
||||
VALIDATION_LOG << "Unsupported uniform type for " << uniform.name
|
||||
<< ".";
|
||||
return true;
|
||||
}
|
||||
|
||||
buffer_index++;
|
||||
}
|
||||
|
||||
@@ -4,18 +4,27 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "impeller/entity/contents/color_source_contents.h"
|
||||
#include "impeller/renderer/sampler_descriptor.h"
|
||||
#include "impeller/runtime_stage/runtime_stage.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
class RuntimeEffectContents final : public ColorSourceContents {
|
||||
public:
|
||||
struct TextureInput {
|
||||
SamplerDescriptor sampler_descriptor;
|
||||
std::shared_ptr<Texture> texture;
|
||||
};
|
||||
|
||||
void SetRuntimeStage(std::shared_ptr<RuntimeStage> runtime_stage);
|
||||
|
||||
void SetUniformData(std::shared_ptr<std::vector<uint8_t>> uniform_data);
|
||||
|
||||
void SetTextureInputs(std::vector<TextureInput> texture_inputs);
|
||||
|
||||
// |Contents|
|
||||
bool Render(const ContentContext& renderer,
|
||||
const Entity& entity,
|
||||
@@ -24,6 +33,7 @@ class RuntimeEffectContents final : public ColorSourceContents {
|
||||
private:
|
||||
std::shared_ptr<RuntimeStage> runtime_stage_;
|
||||
std::shared_ptr<std::vector<uint8_t>> uniform_data_;
|
||||
std::vector<TextureInput> texture_inputs_;
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
Reference in New Issue
Block a user