Make device resident vertex buffers easier to use.

This commit is contained in:
Chinmay Garde 2021-06-29 14:02:06 -07:00 committed by Dan Field
parent 703a269481
commit 167150a45f
11 changed files with 133 additions and 20 deletions

View File

@ -52,6 +52,8 @@ impeller_component("compositor") {
"surface.mm",
"texture.h",
"texture.mm",
"vertex_buffer.h",
"vertex_buffer.mm",
"vertex_buffer_builder.h",
"vertex_buffer_builder.mm",
"vertex_descriptor.h",

View File

@ -11,7 +11,7 @@
namespace impeller {
struct BufferView {
std::shared_ptr<Buffer> buffer;
std::shared_ptr<const Buffer> buffer;
Range range;
constexpr operator bool() const { return static_cast<bool>(buffer); }

View File

@ -25,6 +25,16 @@ class Context {
bool IsValid() const;
//----------------------------------------------------------------------------
/// @return An allocator suitable for allocations that persist between
/// frames.
///
std::shared_ptr<Allocator> GetPermanentsAllocator() const;
//----------------------------------------------------------------------------
/// @return An allocator suitable for allocations that used only for one
/// frame or render pass.
///
std::shared_ptr<Allocator> GetTransientsAllocator() const;
std::shared_ptr<ShaderLibrary> GetShaderLibrary() const;
@ -39,6 +49,7 @@ class Context {
id<MTLCommandQueue> transfer_queue_ = nullptr;
std::shared_ptr<ShaderLibrary> shader_library_;
std::shared_ptr<PipelineLibrary> pipeline_library_;
std::shared_ptr<Allocator> permanents_allocator_;
std::shared_ptr<Allocator> transients_allocator_;
bool is_valid_ = false;

View File

@ -61,6 +61,12 @@ Context::Context(std::string shaders_directory)
if (!transients_allocator_) {
return;
}
permanents_allocator_ = std::shared_ptr<Allocator>(
new Allocator(device_, "Impeller Permanents Allocator"));
if (!permanents_allocator_) {
return;
}
}
is_valid_ = true;
@ -93,6 +99,10 @@ std::shared_ptr<CommandBuffer> Context::CreateRenderCommandBuffer() const {
return buffer;
}
std::shared_ptr<Allocator> Context::GetPermanentsAllocator() const {
return permanents_allocator_;
}
std::shared_ptr<Allocator> Context::GetTransientsAllocator() const {
return transients_allocator_;
}

View File

@ -12,6 +12,7 @@
#include "flutter/fml/macros.h"
#include "impeller/compositor/allocator.h"
#include "impeller/compositor/buffer.h"
#include "impeller/compositor/buffer_view.h"
#include "impeller/compositor/range.h"
namespace impeller {
@ -31,6 +32,8 @@ class DeviceBuffer final : public Buffer,
bool SetLabel(const std::string& label, Range range);
BufferView AsBufferView() const;
private:
friend class Allocator;

View File

@ -62,4 +62,11 @@ bool DeviceBuffer::SetLabel(const std::string& label, Range range) {
return true;
}
BufferView DeviceBuffer::AsBufferView() const {
BufferView view;
view.buffer = shared_from_this();
view.range = {0u, size_};
return view;
}
} // namespace impeller

View File

@ -0,0 +1,21 @@
// 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.
#pragma once
#include "impeller/compositor/buffer_view.h"
namespace impeller {
struct VertexBuffer {
BufferView vertex_buffer;
BufferView index_buffer;
size_t index_count = 0u;
constexpr operator bool() const {
return static_cast<bool>(vertex_buffer) && static_cast<bool>(index_buffer);
}
};
} // namespace impeller

View File

@ -0,0 +1,11 @@
// 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/compositor/vertex_buffer.h"
namespace impeller {
//
} // namespace impeller

View File

@ -9,7 +9,11 @@
#include <vector>
#include "flutter/fml/macros.h"
#include "impeller/compositor/allocator.h"
#include "impeller/compositor/device_buffer.h"
#include "impeller/compositor/formats.h"
#include "impeller/compositor/host_buffer.h"
#include "impeller/compositor/vertex_buffer.h"
#include "impeller/geometry/vector.h"
namespace impeller {
@ -32,30 +36,67 @@ class VertexBufferBuilder {
return *this;
}
BufferView CreateVertexBuffer(HostBuffer& buffer) const {
VertexBuffer CreateVertexBuffer(HostBuffer& host) const {
VertexBuffer buffer;
buffer.vertex_buffer = CreateVertexBufferView(host);
buffer.index_buffer = CreateIndexBufferView(host);
buffer.index_count = GetIndexCount();
return buffer;
};
VertexBuffer CreateVertexBuffer(Allocator& device_allocator) const {
VertexBuffer buffer;
// This can be merged into a single allocation.
buffer.vertex_buffer = CreateVertexBufferView(device_allocator);
buffer.index_buffer = CreateIndexBufferView(device_allocator);
buffer.index_count = GetIndexCount();
return buffer;
};
private:
// This is a placeholder till vertex de-duplication can be implemented. The
// current implementation is a very dumb placeholder.
std::vector<VertexType> vertices_;
BufferView CreateVertexBufferView(HostBuffer& buffer) const {
return buffer.Emplace(vertices_.data(),
vertices_.size() * sizeof(VertexType),
alignof(VertexType));
}
BufferView CreateIndexBuffer(HostBuffer& buffer) const {
BufferView CreateVertexBufferView(Allocator& allocator) const {
auto buffer = allocator.CreateBufferWithCopy(
reinterpret_cast<const uint8_t*>(vertices_.data()),
vertices_.size() * sizeof(VertexType));
return buffer ? buffer->AsBufferView() : BufferView{};
}
std::vector<IndexType> CreateIndexBuffer() const {
// So dumb! We don't actually need an index buffer right now. But we will
// once de-duplication is done. So assume this is always done.
std::vector<IndexType> index_buffer;
for (size_t i = 0; i < vertices_.size(); i++) {
index_buffer.push_back(i);
}
return index_buffer;
}
BufferView CreateIndexBufferView(HostBuffer& buffer) const {
const auto index_buffer = CreateIndexBuffer();
return buffer.Emplace(index_buffer.data(),
index_buffer.size() * sizeof(IndexType),
alignof(IndexType));
}
size_t GetIndexCount() const { return vertices_.size(); }
BufferView CreateIndexBufferView(Allocator& allocator) const {
const auto index_buffer = CreateIndexBuffer();
auto buffer = allocator.CreateBufferWithCopy(
reinterpret_cast<const uint8_t*>(index_buffer.data()),
index_buffer.size() * sizeof(IndexType));
return buffer ? buffer->AsBufferView() : BufferView{};
}
private:
// This is a placeholder till vertex de-duplication can be implemented. The
// current implementation is a very dumb placeholder.
std::vector<VertexType> vertices_;
size_t GetIndexCount() const { return vertices_.size(); }
};
} // namespace impeller

View File

@ -6,6 +6,7 @@
#include "flutter/fml/macros.h"
#include "impeller/compositor/renderer.h"
#include "impeller/compositor/vertex_buffer.h"
#include "impeller/entity/entity.h"
#include "impeller/primitives/box_primitive.h"
@ -20,6 +21,7 @@ class EntityRenderer final : public Renderer {
private:
std::shared_ptr<Entity> root_;
std::shared_ptr<BoxPrimitive> box_primitive_;
VertexBuffer vertex_buffer_;
bool is_valid_ = false;
// |Renderer|

View File

@ -29,6 +29,20 @@ EntityRenderer::EntityRenderer(std::string shaders_directory)
return;
}
VertexBufferBuilder<shader::BoxVertexInfo::PerVertexData> vertex_builder;
vertex_builder.AddVertices({
{{0, 0, 0.0}, {Color::Red()}}, //
{{800, 0.0, 0.0}, {Color::Green()}}, //
{{0.0, 600, 0.0}, {Color::Blue()}}, //
});
vertex_buffer_ =
vertex_builder.CreateVertexBuffer(*context->GetPermanentsAllocator());
if (!vertex_buffer_) {
return;
}
is_valid_ = true;
}
@ -45,25 +59,16 @@ bool EntityRenderer::OnRender(const Surface& surface, RenderPass& pass) {
uniforms.mvp = Matrix::MakeOrthographic(surface.GetSize());
VertexBufferBuilder<shader::BoxVertexInfo::PerVertexData> vertex_builder;
vertex_builder.AddVertices({
{{0, 0, 0.0}, {Color::Red()}}, //
{{800, 0.0, 0.0}, {Color::Green()}}, //
{{0.0, 600, 0.0}, {Color::Blue()}}, //
});
Command cmd;
cmd.label = "Box";
cmd.pipeline = box_primitive_->GetPipeline();
cmd.vertex_bindings.buffers[box_primitive_->GetVertexBufferIndex()] =
vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer());
vertex_buffer_.vertex_buffer;
cmd.vertex_bindings
.buffers[shader::BoxVertexInfo::kUniformUniformBuffer.binding] =
pass.GetTransientsBuffer().EmplaceUniform(uniforms);
cmd.index_buffer =
vertex_builder.CreateIndexBuffer(pass.GetTransientsBuffer());
cmd.index_count = vertex_builder.GetIndexCount();
cmd.index_buffer = vertex_buffer_.index_buffer;
cmd.index_count = vertex_buffer_.index_count;
cmd.primitive_type = PrimitiveType::kTriange;
if (!pass.RecordCommand(std::move(cmd))) {
return false;