blob: 78a780bae143d969650f95d66f85c4d95e2c2033 [file] [log] [blame]
// 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.
#ifndef FLUTTER_IMPELLER_RENDERER_VERTEX_BUFFER_BUILDER_H_
#define FLUTTER_IMPELLER_RENDERER_VERTEX_BUFFER_BUILDER_H_
#include <initializer_list>
#include <map>
#include <vector>
#include "flutter/fml/macros.h"
#include "impeller/base/strings.h"
#include "impeller/core/allocator.h"
#include "impeller/core/device_buffer.h"
#include "impeller/core/formats.h"
#include "impeller/core/host_buffer.h"
#include "impeller/core/vertex_buffer.h"
#include "impeller/geometry/vector.h"
namespace impeller {
template <class VertexType_, class IndexType_ = uint16_t>
class VertexBufferBuilder {
public:
using VertexType = VertexType_;
using IndexType = IndexType_;
VertexBufferBuilder() = default;
~VertexBufferBuilder() = default;
constexpr impeller::IndexType GetIndexType() const {
if (indices_.size() == 0) {
return impeller::IndexType::kNone;
}
if constexpr (sizeof(IndexType) == 2) {
return impeller::IndexType::k16bit;
}
if (sizeof(IndexType) == 4) {
return impeller::IndexType::k32bit;
}
return impeller::IndexType::kUnknown;
}
void SetLabel(const std::string& label) { label_ = label; }
void Reserve(size_t count) { return vertices_.reserve(count); }
void ReserveIndices(size_t count) { return indices_.reserve(count); }
bool HasVertices() const { return !vertices_.empty(); }
size_t GetVertexCount() const { return vertices_.size(); }
size_t GetIndexCount() const {
return indices_.size() > 0 ? indices_.size() : vertices_.size();
}
const VertexType& Last() const {
FML_DCHECK(!vertices_.empty());
return vertices_.back();
}
VertexBufferBuilder& AppendVertex(VertexType_ vertex) {
vertices_.emplace_back(std::move(vertex));
return *this;
}
VertexBufferBuilder& AddVertices(
std::initializer_list<VertexType_> vertices) {
vertices_.reserve(vertices.size());
for (auto& vertex : vertices) {
vertices_.emplace_back(std::move(vertex));
}
return *this;
}
VertexBufferBuilder& AppendIndex(IndexType_ index) {
indices_.emplace_back(index);
return *this;
}
VertexBuffer CreateVertexBuffer(HostBuffer& host_buffer) const {
VertexBuffer buffer;
buffer.vertex_buffer = CreateVertexBufferView(host_buffer);
buffer.index_buffer = CreateIndexBufferView(host_buffer);
buffer.vertex_count = GetIndexCount();
buffer.index_type = GetIndexType();
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.vertex_count = GetIndexCount();
buffer.index_type = GetIndexType();
return buffer;
};
void IterateVertices(const std::function<void(VertexType&)>& iterator) {
for (auto& vertex : vertices_) {
iterator(vertex);
}
}
private:
std::vector<VertexType> vertices_;
std::vector<IndexType> indices_;
std::string label_;
BufferView CreateVertexBufferView(HostBuffer& buffer) const {
return buffer.Emplace(vertices_.data(),
vertices_.size() * sizeof(VertexType),
alignof(VertexType));
}
BufferView CreateVertexBufferView(Allocator& allocator) const {
auto buffer = allocator.CreateBufferWithCopy(
reinterpret_cast<const uint8_t*>(vertices_.data()),
vertices_.size() * sizeof(VertexType));
if (!buffer) {
return {};
}
if (!label_.empty()) {
buffer->SetLabel(SPrintF("%s Vertices", label_.c_str()));
}
return buffer->AsBufferView();
}
std::vector<IndexType> CreateIndexBuffer() const { return indices_; }
BufferView CreateIndexBufferView(HostBuffer& buffer) const {
const auto index_buffer = CreateIndexBuffer();
if (index_buffer.size() == 0) {
return {};
}
return buffer.Emplace(index_buffer.data(),
index_buffer.size() * sizeof(IndexType),
alignof(IndexType));
}
BufferView CreateIndexBufferView(Allocator& allocator) const {
const auto index_buffer = CreateIndexBuffer();
if (index_buffer.size() == 0) {
return {};
}
auto buffer = allocator.CreateBufferWithCopy(
reinterpret_cast<const uint8_t*>(index_buffer.data()),
index_buffer.size() * sizeof(IndexType));
if (!buffer) {
return {};
}
if (!label_.empty()) {
buffer->SetLabel(SPrintF("%s Indices", label_.c_str()));
}
return buffer->AsBufferView();
}
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_RENDERER_VERTEX_BUFFER_BUILDER_H_