[Impeller] Implement support for RuntimeEffect samplers (flutter/engine#37026)

This commit is contained in:
Brandon DeRosier
2022-10-26 14:02:38 -07:00
committed by GitHub
parent 1add612e93
commit 3c733685da
3 changed files with 82 additions and 10 deletions

View File

@@ -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;

View File

@@ -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++;
}

View File

@@ -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