blob: 920ab5759c3d22f99aa31e01d89b4b5da3bc7f4b [file] [log] [blame]
// Copyright 2017 The Fuchsia 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 "garnet/bin/ui/sketchy/buffer/mesh_buffer.h"
#include "garnet/bin/ui/sketchy/buffer/shared_buffer_pool.h"
#include "lib/ui/scenic/cpp/commands.h"
namespace {
constexpr vk::DeviceSize kVertexStride = sizeof(float) * 4;
constexpr vk::DeviceSize kIndexStride = sizeof(uint32_t);
constexpr auto kMeshVertexPositionType = fuchsia::ui::gfx::ValueType::kVector2;
constexpr auto kMeshVertexNormalType = fuchsia::ui::gfx::ValueType::kNone;
constexpr auto kMeshVertexTexCoodType = fuchsia::ui::gfx::ValueType::kVector2;
constexpr auto kMeshIndexFormat = fuchsia::ui::gfx::MeshIndexFormat::kUint32;
} // namespace
namespace sketchy_service {
void MeshBuffer::Prepare(Frame* frame, bool from_scratch,
uint32_t delta_vertex_count,
uint32_t delta_index_count) {
from_scratch |= !vertex_buffer_ || !index_buffer_;
// Multi-buffering for vertex buffer.
vk::DeviceSize vertex_size = (from_scratch ? 0 : vertex_buffer_->size()) +
delta_vertex_count * kVertexStride;
ReplaceBuffer(frame, vertex_buffer_, vertex_size, !from_scratch);
// Multi-buffering for index buffer.
vk::DeviceSize index_size = (from_scratch ? 0 : index_buffer_->size()) +
delta_index_count * kIndexStride;
ReplaceBuffer(frame, index_buffer_, index_size, !from_scratch);
if (from_scratch) {
vertex_buffer_->Reset();
index_buffer_->Reset();
vertex_count_ = 0;
index_count_ = 0;
bbox_ = escher::BoundingBox();
}
}
std::pair<escher::impl::BufferRange, escher::impl::BufferRange>
MeshBuffer::Reserve(Frame* frame, uint32_t vertex_count, uint32_t index_count,
const escher::BoundingBox& bbox) {
vertex_count_ += vertex_count;
index_count_ += index_count;
bbox_.Join(bbox);
vk::DeviceSize vertex_size = kVertexStride * vertex_count;
vk::DeviceSize total_vertex_size = vertex_buffer_->size() + vertex_size;
if (vertex_buffer_->capacity() < total_vertex_size) {
ReplaceBuffer(frame, vertex_buffer_, total_vertex_size,
/* keep_content= */ true);
}
vk::DeviceSize index_size = kIndexStride * index_count;
vk::DeviceSize total_index_size = index_buffer_->size() + index_size;
if (index_buffer_->capacity() < total_index_size) {
ReplaceBuffer(frame, index_buffer_, total_index_size,
/* keep_content= */ true);
}
return {vertex_buffer_->Reserve(vertex_size),
index_buffer_->Reserve(index_size)};
};
void MeshBuffer::ProvideBuffersToScenicMesh(scenic::Mesh* scenic_mesh) {
auto bb_min = bbox_.min();
auto bb_max = bbox_.max();
float bb_min_arr[] = {bb_min.x, bb_min.y, bb_min.z};
float bb_max_arr[] = {bb_max.x, bb_max.y, bb_max.z};
scenic_mesh->BindBuffers(
index_buffer_->scenic_buffer(), kMeshIndexFormat, /* index_offset= */ 0,
index_count_, vertex_buffer_->scenic_buffer(),
scenic::NewMeshVertexFormat(kMeshVertexPositionType,
kMeshVertexNormalType,
kMeshVertexTexCoodType),
/* vertex_offset= */ 0, vertex_count_, bb_min_arr, bb_max_arr);
}
void MeshBuffer::ReplaceBuffer(Frame* frame, SharedBufferPtr& shared_buffer,
vk::DeviceSize capacity_req, bool keep_content) {
auto shared_buffer_pool = frame->shared_buffer_pool();
if (!shared_buffer) {
shared_buffer = shared_buffer_pool->GetBuffer(capacity_req);
return;
}
auto new_buffer = shared_buffer_pool->GetBuffer(capacity_req);
if (keep_content && shared_buffer->size() > 0) {
new_buffer->Copy(frame, shared_buffer);
}
shared_buffer_pool->ReturnBuffer(std::move(shared_buffer),
frame->DuplicateReleaseFence());
shared_buffer = std::move(new_buffer);
}
} // namespace sketchy_service