blob: 53890559e1b0b9c253fff7bd8b320aacdd042fe0 [file] [log] [blame]
// Copyright 2020 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/scenic/lib/flatland/renderer/gpu_mem.h"
#include "src/ui/lib/escher/util/bit_ops.h"
namespace {
escher::GpuMemPtr CreateGPUMem(const vk::Device& device, vk::MemoryAllocateInfo* alloc_info) {
FX_DCHECK(device);
vk::DeviceMemory memory = nullptr;
vk::Result err = device.allocateMemory(alloc_info, nullptr, &memory);
if (err != vk::Result::eSuccess) {
FX_LOGS(ERROR) << "Could not successfully allocate memory.";
return nullptr;
}
return escher::GpuMem::AdoptVkMemory(device, vk::DeviceMemory(memory), alloc_info->allocationSize,
/*needs_mapped_ptr*/ false);
}
} // anonymous namespace
namespace flatland {
vk::ImageCreateInfo GpuImageInfo::NewVkImageCreateInfo(uint32_t width, uint32_t height,
vk::ImageUsageFlags usage) const {
vk::ImageCreateInfo create_info;
create_info.imageType = vk::ImageType::e2D;
create_info.extent = vk::Extent3D{width, height, 1};
create_info.flags = vk::ImageCreateFlagBits::eMutableFormat;
// Hardcode a single viable pixel format. We want to be able to test every single possible
// format that is allowed into Flatland, and so we start with just one.
create_info.format = vk::Format::eB8G8R8A8Unorm;
create_info.mipLevels = 1;
create_info.arrayLayers = 1;
create_info.samples = vk::SampleCountFlagBits::e1;
create_info.tiling = vk::ImageTiling::eOptimal;
create_info.usage = usage;
create_info.sharingMode = vk::SharingMode::eExclusive;
create_info.initialLayout = vk::ImageLayout::eUndefined;
if (p_extension_) {
create_info.setPNext(&(*p_extension_));
}
if (is_protected_) {
create_info.flags = vk::ImageCreateFlagBits::eProtected;
}
return create_info;
}
GpuImageInfo GpuImageInfo::New(const vk::Device& device, const vk::DispatchLoaderDynamic& vk_loader,
const fuchsia::sysmem::BufferCollectionInfo_2& info,
const vk::BufferCollectionFUCHSIA& vk_buffer_collection,
uint32_t index) {
FX_DCHECK(device);
FX_DCHECK(vk_loader.vkGetBufferCollectionPropertiesFUCHSIA);
// Check the provided index against actually allocated number of buffers.
if (info.buffer_count <= index) {
FX_LOGS(ERROR) << "Specified vmo index is out of bounds: " << index;
return GpuImageInfo();
}
// Currently only support a single format.
FX_DCHECK(info.settings.image_format_constraints.pixel_format.type ==
fuchsia::sysmem::PixelFormatType::BGRA32);
// Get a handle to the vmo and extract the size of its buffer.
zx::vmo vmo;
zx_status_t status = info.buffers[index].vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &vmo);
FX_DCHECK(status == ZX_OK);
uint64_t vmo_size;
status = vmo.get_size(&vmo_size);
FX_DCHECK(status == ZX_OK);
auto collection_properties =
device.getBufferCollectionPropertiesFUCHSIA(vk_buffer_collection, vk_loader);
if (collection_properties.result != vk::Result::eSuccess) {
FX_LOGS(ERROR) << "Could not get collection properties for vk_buffer_collection.h";
return GpuImageInfo();
}
// We are setting up the information here to import the buffer collection vmo at the
// specified index into GPU memory.
const uint32_t memory_type_index =
escher::CountTrailingZeros(collection_properties.value.memoryTypeBits);
vk::ImportMemoryBufferCollectionFUCHSIA import_info;
import_info.collection = vk_buffer_collection;
import_info.index = index;
vk::MemoryAllocateInfo alloc_info;
alloc_info.setPNext(&import_info);
alloc_info.memoryTypeIndex = memory_type_index;
alloc_info.allocationSize = vmo_size;
return GpuImageInfo(CreateGPUMem(device, &alloc_info), vk_buffer_collection, index,
info.settings.buffer_settings.is_secure);
}
GpuImageInfo::GpuImageInfo(escher::GpuMemPtr mem, vk::BufferCollectionFUCHSIA vk_buffer_collection,
uint32_t vmo_index, bool is_protected)
: mem_(mem), is_protected_(is_protected) {
vk::BufferCollectionImageCreateInfoFUCHSIA p_extension;
p_extension.collection = vk_buffer_collection;
p_extension.index = vmo_index;
p_extension_ = p_extension;
}
} // namespace flatland