Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] Encode directly to command buffer for Vulkan. #49780

Merged
merged 15 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions impeller/aiks/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impeller_component("context_spy") {
"testing/context_spy.h",
]
deps = [
"//flutter/impeller/entity:entity_test_helpers",
"//flutter/impeller/renderer",
"//flutter/testing:testing_lib",
]
Expand Down
21 changes: 13 additions & 8 deletions impeller/aiks/testing/context_spy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>

#include "impeller/aiks/testing/context_spy.h"

namespace impeller {
Expand Down Expand Up @@ -64,14 +66,17 @@ std::shared_ptr<ContextMock> ContextSpy::MakeContext(
});

ON_CALL(*spy, OnCreateRenderPass)
.WillByDefault(
[real_buffer, shared_this](const RenderTarget& render_target) {
std::shared_ptr<RenderPass> result =
CommandBufferMock::ForwardOnCreateRenderPass(
real_buffer.get(), render_target);
shared_this->render_passes_.push_back(result);
return result;
});
.WillByDefault([real_buffer, shared_this,
real_context](const RenderTarget& render_target) {
std::shared_ptr<RenderPass> result =
CommandBufferMock::ForwardOnCreateRenderPass(
real_buffer.get(), render_target);
std::shared_ptr<RecordingRenderPass> recorder =
std::make_shared<RecordingRenderPass>(result, real_context,
render_target);
shared_this->render_passes_.push_back(recorder);
return recorder;
});

ON_CALL(*spy, OnCreateBlitPass).WillByDefault([real_buffer]() {
return CommandBufferMock::ForwardOnCreateBlitPass(real_buffer.get());
Expand Down
4 changes: 3 additions & 1 deletion impeller/aiks/testing/context_spy.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#define FLUTTER_IMPELLER_AIKS_TESTING_CONTEXT_SPY_H_

#include <memory>

#include "impeller/aiks/testing/context_mock.h"
#include "impeller/entity/contents/test/recording_render_pass.h"

namespace impeller {
namespace testing {
Expand All @@ -20,7 +22,7 @@ class ContextSpy : public std::enable_shared_from_this<ContextSpy> {
std::shared_ptr<ContextMock> MakeContext(
const std::shared_ptr<Context>& real_context);

std::vector<std::shared_ptr<RenderPass>> render_passes_;
std::vector<std::shared_ptr<RecordingRenderPass>> render_passes_;

private:
ContextSpy() = default;
Expand Down
2 changes: 1 addition & 1 deletion impeller/compiler/code_gen_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader {
{% endfor %}) {
return {{ proto.args.0.argument_name }}.BindResource({% for arg in proto.args %}
{% if loop.is_first %}
{{to_shader_stage(shader_stage)}}, kResource{{ proto.name }}, kMetadata{{ proto.name }}, {% else %}
{{to_shader_stage(shader_stage)}}, {{ proto.descriptor_type }}, kResource{{ proto.name }}, kMetadata{{ proto.name }}, {% else %}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the descriptor type so that bind calls don't need to look up the layout information to determine if a BufferView is a uniform buffer or storage buffer.

std::move({{ arg.argument_name }}){% if not loop.is_last %}, {% endif %}
{% endif %}
{% endfor %});
Expand Down
6 changes: 6 additions & 0 deletions impeller/compiler/reflector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,7 @@ std::vector<Reflector::BindPrototype> Reflector::ReflectBindPrototypes(
auto& proto = prototypes.emplace_back(BindPrototype{});
proto.return_type = "bool";
proto.name = ToCamelCase(uniform_buffer.name);
proto.descriptor_type = "DescriptorType::kUniformBuffer";
{
std::stringstream stream;
stream << "Bind uniform buffer for resource named " << uniform_buffer.name
Expand All @@ -1327,6 +1328,7 @@ std::vector<Reflector::BindPrototype> Reflector::ReflectBindPrototypes(
auto& proto = prototypes.emplace_back(BindPrototype{});
proto.return_type = "bool";
proto.name = ToCamelCase(storage_buffer.name);
proto.descriptor_type = "DescriptorType::kStorageBuffer";
{
std::stringstream stream;
stream << "Bind storage buffer for resource named " << storage_buffer.name
Expand All @@ -1346,6 +1348,7 @@ std::vector<Reflector::BindPrototype> Reflector::ReflectBindPrototypes(
auto& proto = prototypes.emplace_back(BindPrototype{});
proto.return_type = "bool";
proto.name = ToCamelCase(sampled_image.name);
proto.descriptor_type = "DescriptorType::kSampledImage";
{
std::stringstream stream;
stream << "Bind combined image sampler for resource named "
Expand All @@ -1369,6 +1372,7 @@ std::vector<Reflector::BindPrototype> Reflector::ReflectBindPrototypes(
auto& proto = prototypes.emplace_back(BindPrototype{});
proto.return_type = "bool";
proto.name = ToCamelCase(separate_image.name);
proto.descriptor_type = "DescriptorType::kImage";
{
std::stringstream stream;
stream << "Bind separate image for resource named " << separate_image.name
Expand All @@ -1388,6 +1392,7 @@ std::vector<Reflector::BindPrototype> Reflector::ReflectBindPrototypes(
auto& proto = prototypes.emplace_back(BindPrototype{});
proto.return_type = "bool";
proto.name = ToCamelCase(separate_sampler.name);
proto.descriptor_type = "DescriptorType::kSampler";
{
std::stringstream stream;
stream << "Bind separate sampler for resource named "
Expand Down Expand Up @@ -1416,6 +1421,7 @@ nlohmann::json::array_t Reflector::EmitBindPrototypes(
item["return_type"] = res.return_type;
item["name"] = res.name;
item["docstring"] = res.docstring;
item["descriptor_type"] = res.descriptor_type;
auto& args = item["args"] = nlohmann::json::array_t{};
for (const auto& arg : res.args) {
auto& json_arg = args.emplace_back(nlohmann::json::object_t{});
Expand Down
1 change: 1 addition & 0 deletions impeller/compiler/reflector.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ class Reflector {
std::string name;
std::string return_type;
std::string docstring;
std::string descriptor_type = "";
std::vector<BindPrototypeArgument> args;
};

Expand Down
2 changes: 2 additions & 0 deletions impeller/core/resource_binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ struct ResourceBinder {
virtual ~ResourceBinder() = default;

virtual bool BindResource(ShaderStage stage,
DescriptorType type,
const ShaderUniformSlot& slot,
const ShaderMetadata& metadata,
BufferView view) = 0;

virtual bool BindResource(ShaderStage stage,
DescriptorType type,
const SampledImageSlot& slot,
const ShaderMetadata& metadata,
std::shared_ptr<const Texture> texture,
Expand Down
2 changes: 2 additions & 0 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ impeller_component("entity_test_helpers") {
sources = [
"contents/test/contents_test_helpers.cc",
"contents/test/contents_test_helpers.h",
"contents/test/recording_render_pass.cc",
"contents/test/recording_render_pass.h",
]

deps = [ ":entity" ]
Expand Down
10 changes: 7 additions & 3 deletions impeller/entity/contents/checkerboard_contents_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "impeller/entity/contents/checkerboard_contents.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/test/recording_render_pass.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/entity_playground.h"
#include "impeller/renderer/render_target.h"
Expand Down Expand Up @@ -38,11 +39,14 @@ TEST_P(EntityTest, RendersWithoutError) {
*GetContentContext()->GetRenderTargetCache(), {100, 100},
/*mip_count=*/1);
auto render_pass = buffer->CreateRenderPass(render_target);
auto recording_pass = std::make_shared<RecordingRenderPass>(
render_pass, GetContext(), render_target);

Entity entity;

ASSERT_TRUE(render_pass->GetCommands().empty());
ASSERT_TRUE(contents->Render(*content_context, entity, *render_pass));
ASSERT_FALSE(render_pass->GetCommands().empty());
ASSERT_TRUE(recording_pass->GetCommands().empty());
ASSERT_TRUE(contents->Render(*content_context, entity, *recording_pass));
ASSERT_FALSE(recording_pass->GetCommands().empty());
}
#endif // IMPELLER_DEBUG

Expand Down
12 changes: 7 additions & 5 deletions impeller/entity/contents/runtime_effect_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,9 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
ShaderUniformSlot uniform_slot;
uniform_slot.name = uniform.name.c_str();
uniform_slot.ext_res_0 = uniform.location;
pass.BindResource(ShaderStage::kFragment, uniform_slot, metadata,
buffer_view);
pass.BindResource(ShaderStage::kFragment,
DescriptorType::kUniformBuffer, uniform_slot,
metadata, buffer_view);
buffer_index++;
buffer_offset += uniform.GetSize();
break;
Expand Down Expand Up @@ -229,7 +230,8 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,
auto buffer_view = renderer.GetTransientsBuffer().Emplace(
reinterpret_cast<const void*>(uniform_buffer.data()),
sizeof(float) * uniform_buffer.size(), alignment);
pass.BindResource(ShaderStage::kFragment, uniform_slot,
pass.BindResource(ShaderStage::kFragment,
DescriptorType::kUniformBuffer, uniform_slot,
ShaderMetadata{}, buffer_view);
}
}
Expand Down Expand Up @@ -263,8 +265,8 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer,

image_slot.binding = sampler_binding_location;
image_slot.texture_index = uniform.location - minimum_sampler_index;
pass.BindResource(ShaderStage::kFragment, image_slot, *metadata,
input.texture, sampler);
pass.BindResource(ShaderStage::kFragment, DescriptorType::kSampledImage,
image_slot, *metadata, input.texture, sampler);

sampler_index++;
break;
Expand Down
116 changes: 116 additions & 0 deletions impeller/entity/contents/test/recording_render_pass.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "impeller/entity/contents/test/recording_render_pass.h"

#include <utility>

namespace impeller {

RecordingRenderPass::RecordingRenderPass(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a test only class that lets us inspect individual commands.

std::shared_ptr<RenderPass> delegate,
const std::shared_ptr<Context>& context,
const RenderTarget& render_target)
: RenderPass(context, render_target), delegate_(std::move(delegate)) {}

// |RenderPass|
void RecordingRenderPass::SetPipeline(
const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
pending_.pipeline = pipeline;
delegate_->SetPipeline(pipeline);
}

void RecordingRenderPass::SetCommandLabel(std::string_view label) {
#ifdef IMPELLER_DEBUG
pending_.label = std::string(label);
#endif // IMPELLER_DEBUG
delegate_->SetCommandLabel(label);
}

// |RenderPass|
void RecordingRenderPass::SetStencilReference(uint32_t value) {
pending_.stencil_reference = value;
delegate_->SetStencilReference(value);
}

// |RenderPass|
void RecordingRenderPass::SetBaseVertex(uint64_t value) {
pending_.base_vertex = value;
delegate_->SetBaseVertex(value);
}

// |RenderPass|
void RecordingRenderPass::SetViewport(Viewport viewport) {
pending_.viewport = viewport;
delegate_->SetViewport(viewport);
}

// |RenderPass|
void RecordingRenderPass::SetScissor(IRect scissor) {
pending_.scissor = scissor;
delegate_->SetScissor(scissor);
}

// |RenderPass|
void RecordingRenderPass::SetInstanceCount(size_t count) {
pending_.instance_count = count;
delegate_->SetInstanceCount(count);
}

// |RenderPass|
bool RecordingRenderPass::SetVertexBuffer(VertexBuffer buffer) {
pending_.vertex_buffer = buffer;
return delegate_->SetVertexBuffer(buffer);
}

// |RenderPass|
fml::Status RecordingRenderPass::Draw() {
commands_.emplace_back(std::move(pending_));
pending_ = {};
return delegate_->Draw();
}

// |RenderPass|
void RecordingRenderPass::OnSetLabel(std::string label) {
return;
}

// |RenderPass|
bool RecordingRenderPass::OnEncodeCommands(const Context& context) const {
return true;
}

// |RenderPass|
bool RecordingRenderPass::BindResource(ShaderStage stage,
DescriptorType type,
const ShaderUniformSlot& slot,
const ShaderMetadata& metadata,
BufferView view) {
pending_.BindResource(stage, type, slot, metadata, view);
return delegate_->BindResource(stage, type, slot, metadata, view);
}

// |RenderPass|
bool RecordingRenderPass::BindResource(
ShaderStage stage,
DescriptorType type,
const ShaderUniformSlot& slot,
const std::shared_ptr<const ShaderMetadata>& metadata,
BufferView view) {
pending_.BindResource(stage, type, slot, metadata, view);
return delegate_->BindResource(stage, type, slot, metadata, view);
}

// |RenderPass|
bool RecordingRenderPass::BindResource(ShaderStage stage,
DescriptorType type,
const SampledImageSlot& slot,
const ShaderMetadata& metadata,
std::shared_ptr<const Texture> texture,
std::shared_ptr<const Sampler> sampler) {
pending_.BindResource(stage, type, slot, metadata, texture, sampler);
return delegate_->BindResource(stage, type, slot, metadata, texture, sampler);
}

} // namespace impeller
Loading