blob: ae5fe7cdb6c2d9cf5c9036749e9fc55e96e136ea [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.
#include "src/ui/lib/escher/impl/naive_buffer.h"
#include "src/ui/lib/escher/impl/vulkan_utils.h"
#include "src/ui/lib/escher/resources/resource_manager.h"
#include "src/ui/lib/escher/util/trace_macros.h"
namespace escher {
namespace impl {
namespace {
bool CheckBufferMemoryRequirements(ResourceManager* manager, vk::Buffer vk_buffer,
const GpuMemPtr& mem) {
auto mem_requirements = manager->vk_device().getBufferMemoryRequirements(vk_buffer);
auto size_required = mem_requirements.size;
auto alignment_required = mem_requirements.alignment;
if (mem->size() < size_required) {
FX_LOGS(ERROR) << "Memory requirements check failed: Buffer requires " << size_required
<< " bytes of memory, while the provided mem size is " << mem->size()
<< " bytes.";
return false;
}
if (mem->offset() % alignment_required != 0) {
FX_LOGS(ERROR) << "Memory requirements check failed: Buffer requires alignment of "
<< alignment_required << " bytes, while the provided mem offset is "
<< mem->offset();
return false;
}
return true;
}
} // namespace
BufferPtr NaiveBuffer::New(ResourceManager* manager, GpuMemPtr mem,
vk::BufferUsageFlags usage_flags) {
TRACE_DURATION("gfx", "escher::NaiveBuffer::New");
auto device = manager->vulkan_context().device;
auto size = mem->size();
// Create buffer.
vk::BufferCreateInfo buffer_create_info;
buffer_create_info.size = mem->size();
buffer_create_info.usage = usage_flags;
buffer_create_info.sharingMode = vk::SharingMode::eExclusive;
auto vk_buffer = ESCHER_CHECKED_VK_RESULT(device.createBuffer(buffer_create_info));
// Check buffer memory requirements before binding the buffer to memory.
if (!CheckBufferMemoryRequirements(manager, vk_buffer, mem)) {
FX_LOGS(ERROR) << "NaiveBuffer::New() Failed: cannot satisfy memory requirements.";
return nullptr;
}
return fxl::AdoptRef(new NaiveBuffer(manager, std::move(mem), size, vk_buffer));
}
BufferPtr NaiveBuffer::AdoptVkBuffer(ResourceManager* manager, GpuMemPtr mem,
vk::DeviceSize vk_buffer_size, vk::Buffer vk_buffer) {
TRACE_DURATION("gfx", "escher::NaiveBuffer::AdoptVkBuffer");
// Check buffer memory requirements before binding the buffer to memory.
if (!CheckBufferMemoryRequirements(manager, vk_buffer, mem)) {
FX_LOGS(ERROR) << "NaiveBuffer::AdoptVkBuffer() Failed: cannot satisfy memory requirements.";
return nullptr;
}
return fxl::AdoptRef(new NaiveBuffer(manager, std::move(mem), vk_buffer_size, vk_buffer));
}
NaiveBuffer::NaiveBuffer(ResourceManager* manager, GpuMemPtr mem, vk::DeviceSize vk_buffer_size,
vk::Buffer buffer)
: Buffer(manager, buffer, vk_buffer_size, mem->mapped_ptr()), mem_(std::move(mem)) {
FX_CHECK(vk());
FX_CHECK(mem_);
auto status = vulkan_context().device.bindBufferMemory(vk(), mem_->base(), mem_->offset());
FX_CHECK(status == vk::Result::eSuccess)
<< "bindBufferMemory failed with status " << (VkResult)status;
}
NaiveBuffer::~NaiveBuffer() { vulkan_context().device.destroyBuffer(vk()); }
} // namespace impl
} // namespace escher