blob: 8a138dbd0038eeaf067c80811b520665d17e7861 [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.h"
#include "lib/escher/escher.h"
#include "lib/escher/impl/command_buffer_pool.h"
#include "lib/escher/util/fuchsia_utils.h"
#include "lib/escher/vk/gpu_mem.h"
namespace {
const vk::BufferUsageFlags kVertexBufferUsageFlags =
vk::BufferUsageFlagBits::eVertexBuffer |
vk::BufferUsageFlagBits::eStorageBuffer |
vk::BufferUsageFlagBits::eTransferSrc |
vk::BufferUsageFlagBits::eTransferDst;
const vk::BufferUsageFlags kIndexBufferUsageFlags =
vk::BufferUsageFlagBits::eIndexBuffer |
vk::BufferUsageFlagBits::eTransferSrc |
vk::BufferUsageFlagBits::eTransferDst;
const vk::MemoryPropertyFlags kMemoryPropertyFlags =
vk::MemoryPropertyFlagBits::eDeviceLocal;
std::unique_ptr<scenic_lib::Buffer> NewScenicBufferFromEscherBuffer(
const escher::BufferPtr& buffer,
scenic_lib::Session* session) {
zx::vmo vmo =
escher::ExportMemoryAsVmo(buffer->escher(), buffer->mem());
scenic_lib::Memory memory(session, std::move(vmo),
scenic::MemoryType::VK_DEVICE_MEMORY);
return std::make_unique<scenic_lib::Buffer>(memory, 0, buffer->size());
}
} // namespace
namespace sketchy_service {
std::unique_ptr<Buffer> Buffer::New(scenic_lib::Session* session,
escher::BufferFactory* factory,
BufferType type,
vk::DeviceSize capacity) {
return std::make_unique<Buffer>(session, factory, capacity,
type == BufferType::kVertex
? kVertexBufferUsageFlags
: kIndexBufferUsageFlags);
}
Buffer::Buffer(scenic_lib::Session* session,
escher::BufferFactory* factory,
vk::DeviceSize capacity,
vk::BufferUsageFlags flags)
: session_(session),
escher_buffer_(factory->NewBuffer(capacity, flags, kMemoryPropertyFlags)),
scenic_buffer_(NewScenicBufferFromEscherBuffer(escher_buffer_, session)),
size_(0),
flags_(flags) {}
void Buffer::Merge(escher::impl::CommandBuffer* command,
escher::BufferFactory* factory,
escher::BufferPtr new_escher_buffer) {
PreserveSize(command, factory, new_escher_buffer->size());
command->CopyBuffer(new_escher_buffer, escher_buffer_,
{0, size_ - new_escher_buffer->size(),
new_escher_buffer->size()});
}
escher::BufferPtr Buffer::PreserveBuffer(escher::impl::CommandBuffer* command,
escher::BufferFactory* factory,
vk::DeviceSize size) {
PreserveSize(command, factory, size);
return factory->NewBuffer(escher_buffer_->mem(), flags_, size, size_ - size);
}
void Buffer::PreserveSize(escher::impl::CommandBuffer* command,
escher::BufferFactory* factory,
vk::DeviceSize size) {
// Determine the capacity required to preserve for |size|.
vk::DeviceSize new_capacity = capacity();
while (size_ + size > new_capacity) {
new_capacity <<= 1;
}
// If there was not enough capacity, a new buffer must be allocated, and the
// previously-existing data must be copied into it.
if (new_capacity > capacity()) {
auto expanded_escher_buffer =
factory->NewBuffer(new_capacity, flags_, kMemoryPropertyFlags);
command->CopyBuffer(escher_buffer_, expanded_escher_buffer, {0, 0, size_});
escher_buffer_ = std::move(expanded_escher_buffer);
scenic_buffer_ = NewScenicBufferFromEscherBuffer(escher_buffer_, session_);
}
// Preserve the size for use.
size_ += size;
}
} // namespace sketchy_service