blob: f056eca9fc012762cb2c326f747d681da3be1a6d [file] [log] [blame]
// Copyright 2018 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.
#ifndef SRC_UI_LIB_ESCHER_MESH_INDEXED_TRIANGLE_MESH_UPLOAD_H_
#define SRC_UI_LIB_ESCHER_MESH_INDEXED_TRIANGLE_MESH_UPLOAD_H_
#include "src/ui/lib/escher/escher.h"
#include "src/ui/lib/escher/geometry/bounding_box.h"
#include "src/ui/lib/escher/mesh/indexed_triangle_mesh.h"
#include "src/ui/lib/escher/renderer/batch_gpu_uploader.h"
#include "src/ui/lib/escher/shape/mesh.h"
#include "src/ui/lib/escher/util/trace_macros.h"
namespace escher {
// Uploads the contents of an IndexedTriangleMesh<> to a Vulkan buffer, and
// returns a new Mesh that is bound to this buffer.
template <typename IndexedTriangleMeshT>
MeshPtr IndexedTriangleMeshUpload(Escher* escher, BatchGpuUploader* uploader,
const MeshSpec& mesh_spec, const BoundingBox& bounding_box,
IndexedTriangleMeshT mesh) {
TRACE_DURATION("gfx", "escher::IndexedTriangleMeshUpload", "triangles", mesh.triangle_count(),
"vertices", mesh.vertex_count());
if (mesh.index_count() == 0)
return MeshPtr();
const size_t ind_bytes = mesh.total_index_bytes();
const size_t pos_bytes = mesh.total_position_bytes();
const size_t attr1_bytes = mesh.total_attribute1_bytes();
const size_t attr2_bytes = mesh.total_attribute2_bytes();
const size_t attr3_bytes = mesh.total_attribute3_bytes();
const size_t total_bytes = ind_bytes + pos_bytes + attr1_bytes + attr2_bytes + attr3_bytes;
const size_t ind_offset = 0;
const size_t pos_offset = ind_bytes;
const size_t attr1_offset = pos_offset + pos_bytes;
const size_t attr2_offset = attr1_offset + attr1_bytes;
const size_t attr3_offset = attr2_offset + attr2_bytes;
auto vertex_count = mesh.vertex_count();
auto index_count = mesh.index_count();
// Use a single buffer, but don't interleave the position and attribute
// data.
auto buffer = escher->NewBuffer(
total_bytes,
// |eTransferSrc| needed for glTF Exporter.
vk::BufferUsageFlagBits::eTransferSrc | vk::BufferUsageFlagBits::eIndexBuffer |
vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eTransferDst,
vk::MemoryPropertyFlagBits::eDeviceLocal);
uploader->ScheduleWriteBuffer(
buffer,
[ind_bytes, pos_bytes, pos_offset, attr1_offset, attr2_offset, attr3_offset, attr1_bytes,
attr2_bytes, attr3_bytes,
mesh = std::move(mesh)](uint8_t* host_buffer_ptr, size_t copy_size) {
TRACE_DURATION("gfx", "escher::IndexedTriangleMeshUpload[memcpy]");
memcpy(host_buffer_ptr + ind_offset, mesh.indices.data(), ind_bytes);
memcpy(host_buffer_ptr + pos_offset, mesh.positions.data(), pos_bytes);
if (attr1_bytes > 0) {
memcpy(host_buffer_ptr + attr1_offset, mesh.attributes1.data(), attr1_bytes);
}
if (attr2_bytes > 0) {
memcpy(host_buffer_ptr + attr2_offset, mesh.attributes2.data(), attr2_bytes);
}
if (attr3_bytes > 0) {
memcpy(host_buffer_ptr + attr3_offset, mesh.attributes3.data(), attr3_bytes);
}
},
/* target_offset */ 0, /* copy_size */ total_bytes);
return fxl::MakeRefCounted<Mesh>(escher->resource_recycler(), mesh_spec, bounding_box,
index_count, buffer, ind_offset, vertex_count, buffer,
pos_offset, (attr1_bytes ? buffer : nullptr), attr1_offset,
(attr2_bytes ? buffer : nullptr), attr2_offset,
(attr3_bytes ? buffer : nullptr), attr3_offset);
}
} // namespace escher
#endif // SRC_UI_LIB_ESCHER_MESH_INDEXED_TRIANGLE_MESH_UPLOAD_H_