diff --git a/BUILD.gn b/BUILD.gn index 5e63b1923eb2a8a361aaca626eab448197d8031b..348ab87c46af21a98e704da82ad1a25b67b92f33 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1,4 +1,4 @@ -source_set("goldfish_vulkan") { +shared_library("vulkan_goldfish") { sources = [ "android-emu/android/base/AlignedBuf.cpp", "android-emu/android/base/AlignedBuf.h", @@ -84,8 +84,14 @@ source_set("goldfish_vulkan") { "-Wno-missing-field-initializers", ] + ldflags = [ "-static-libstdc++" ] + if (target_os == "fuchsia") { - sources += [ "fuchsia/port.cc" ] + sources -= [ "system/OpenglSystemCommon/QemuPipeStream.cpp" ] + sources += [ + "fuchsia/port.cc", + "system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp", + ] include_dirs += [ "//third_party/vulkan_loader_and_validation_layers/include", @@ -97,16 +103,17 @@ source_set("goldfish_vulkan") { ] deps = [ - "//zircon/public/fidl/fuchsia-hardware-goldfish:fuchsia-hardware-goldfish_c", + "//zircon/public/fidl/fuchsia-hardware-goldfish-address-space:fuchsia-hardware-goldfish-address-space_c", + "//zircon/public/fidl/fuchsia-hardware-goldfish-control:fuchsia-hardware-goldfish-control_c", + "//zircon/public/fidl/fuchsia-hardware-goldfish-pipe:fuchsia-hardware-goldfish-pipe_c", "//zircon/public/fidl/fuchsia-sysmem", "//zircon/public/lib/fdio", - "//zircon/public/lib/fzl", "//zircon/public/lib/trace", ] defines += [ - "QEMU_PIPE_PATH=\"/dev/sys/platform/acpi/goldfish/goldfish-pipe\"", - "GOLDFISH_ADDRESS_SPACE_DEVICE_NAME=\"/dev/sys/platform/acpi/goldfish/goldfish-pipe\"", + "QEMU_PIPE_PATH=\"/dev/class/goldfish-pipe/000\"", + "GOLDFISH_ADDRESS_SPACE_DEVICE_NAME=\"/dev/class/goldfish-address-space/000\"", ] } } diff --git a/shared/OpenglCodecCommon/goldfish_address_space.cpp b/shared/OpenglCodecCommon/goldfish_address_space.cpp index afa6b85dcf158e1b6f90614ac650333abc7d4d24..bbc59c618d539949dc5769805ab3bc9d446d9f52 100644 --- a/shared/OpenglCodecCommon/goldfish_address_space.cpp +++ b/shared/OpenglCodecCommon/goldfish_address_space.cpp @@ -127,8 +127,9 @@ void GoldfishAddressSpaceBlock::replace(GoldfishAddressSpaceBlock *other) } #elif __Fuchsia__ #include <fcntl.h> -#include <fuchsia/hardware/goldfish/c/fidl.h> -#include <lib/fzl/fdio.h> +#include <fuchsia/hardware/goldfish/address/space/c/fidl.h> +#include <lib/fdio/fdio.h> +#include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -136,22 +137,23 @@ void GoldfishAddressSpaceBlock::replace(GoldfishAddressSpaceBlock *other) #include <zircon/syscalls.h> #include <zircon/syscalls/object.h> -GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider() - : m_fd(::open(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, O_RDWR)) {} +GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider() { + fdio_get_service_handle(::open(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, O_RDWR), &m_channel); +} GoldfishAddressSpaceBlockProvider::~GoldfishAddressSpaceBlockProvider() { - ::close(m_fd); + zx_handle_close(m_channel); } GoldfishAddressSpaceBlock::GoldfishAddressSpaceBlock() : m_vmo(ZX_HANDLE_INVALID) + , m_channel(ZX_HANDLE_INVALID) , m_mmaped_ptr(NULL) , m_phys_addr(0) , m_host_addr(0) , m_offset(0) - , m_size(0) - , m_fd(-1) {} + , m_size(0) {} GoldfishAddressSpaceBlock::~GoldfishAddressSpaceBlock() { @@ -166,7 +168,7 @@ GoldfishAddressSpaceBlock &GoldfishAddressSpaceBlock::operator=(const GoldfishAd m_host_addr = rhs.m_host_addr; m_offset = rhs.m_offset; m_size = rhs.m_size; - m_fd = rhs.m_fd; + m_channel = rhs.m_channel; return *this; } @@ -182,36 +184,13 @@ bool GoldfishAddressSpaceBlock::allocate(GoldfishAddressSpaceBlockProvider *prov return false; } - { - fzl::FdioCaller caller{fbl::unique_fd(provider->m_fd)}; - - int32_t res = ZX_OK; - zx_status_t status = - fuchsia_hardware_goldfish_DeviceAllocateVmo(caller.borrow_channel(), - size, &res, &m_vmo); - if (status != ZX_OK || res != ZX_OK) { - ALOGE("%s: allocate vmo failed: %d:%d", __func__, status, res); - provider->m_fd = caller.release().release(); - return false; - } - - zx_handle_t vmo_out; - status = zx_handle_duplicate(m_vmo, ZX_DEFAULT_VMO_RIGHTS, &vmo_out); - if (status != ZX_OK) { - ALOGE("%s: vmo dup failed: %d:%d", __func__, status); - provider->m_fd = caller.release().release(); - return false; - } - - status = fuchsia_hardware_goldfish_DeviceGetPhysicalAddress( - caller.borrow_channel(), - vmo_out, &res, &m_phys_addr); - provider->m_fd = caller.release().release(); - - if (status != ZX_OK || res != ZX_OK) { - ALOGE("%s: pin vmo failed: %d:%d", __func__, status, res); - return false; - } + int32_t res = ZX_OK; + zx_status_t status = + fuchsia_hardware_goldfish_address_space_DeviceAllocateBlock( + provider->m_channel, size, &res, &m_phys_addr, &m_vmo); + if (status != ZX_OK || res != ZX_OK) { + ALOGE("%s: allocate block failed: %d:%d", __func__, status, res); + return false; } m_offset = 0; @@ -221,7 +200,7 @@ bool GoldfishAddressSpaceBlock::allocate(GoldfishAddressSpaceBlockProvider *prov (unsigned long long)m_offset, (unsigned long long)m_size); - m_fd = provider->m_fd; + m_channel = provider->m_channel; return true; } @@ -284,6 +263,14 @@ void GoldfishAddressSpaceBlock::destroy() if (m_size) { zx_handle_close(m_vmo); m_vmo = ZX_HANDLE_INVALID; + int32_t res = ZX_OK; + zx_status_t status = + fuchsia_hardware_goldfish_address_space_DeviceDeallocateBlock( + m_channel, m_phys_addr, &res); + if (status != ZX_OK || res != ZX_OK) { + ALOGE("%s: deallocate block failed: %d:%d", __func__, status, res); + } + m_channel = ZX_HANDLE_INVALID; m_phys_addr = 0; m_host_addr = 0; m_offset = 0; @@ -303,7 +290,7 @@ void GoldfishAddressSpaceBlock::replace(GoldfishAddressSpaceBlock *other) bool GoldfishAddressSpaceBlockProvider::is_opened() { - return m_fd >= 0; + return m_channel != ZX_HANDLE_INVALID; } #else #include <linux/types.h> diff --git a/shared/OpenglCodecCommon/goldfish_address_space.h b/shared/OpenglCodecCommon/goldfish_address_space.h index 637e20dfe38921dc5a48a1f82a4688532b1f015e..7ebb4517b5d65a66ceab03a3347b13e4750129d7 100644 --- a/shared/OpenglCodecCommon/goldfish_address_space.h +++ b/shared/OpenglCodecCommon/goldfish_address_space.h @@ -45,7 +45,11 @@ private: GoldfishAddressSpaceBlockProvider &operator=(const GoldfishAddressSpaceBlockProvider &rhs); bool is_opened(); +#ifdef __Fuchsia__ + uint32_t m_channel; +#else int m_fd; +#endif friend class GoldfishAddressSpaceBlock; }; @@ -75,13 +79,15 @@ private: #else #ifdef __Fuchsia__ uint32_t m_vmo; + uint32_t m_channel; +#else + int m_fd; #endif void *m_mmaped_ptr; uint64_t m_phys_addr; uint64_t m_host_addr; uint64_t m_offset; size_t m_size; - int m_fd; #endif }; diff --git a/system/OpenglSystemCommon/QemuPipeStream.h b/system/OpenglSystemCommon/QemuPipeStream.h index 0884d5740eff21f5a633ee305df52e6f3efe0ad6..8d64ab8419aa90c7845b9cfefe7342add9715ca7 100644 --- a/system/OpenglSystemCommon/QemuPipeStream.h +++ b/system/OpenglSystemCommon/QemuPipeStream.h @@ -25,6 +25,12 @@ #include "qemu_pipe.h" +#ifdef __Fuchsia__ +#include <lib/zx/channel.h> +#include <lib/zx/event.h> +#include <lib/zx/vmo.h> +#endif + class QemuPipeStream : public IOStream { public: typedef enum { ERR_INVALID_SOCKET = -1000 } QemuPipeStreamError; @@ -48,6 +54,11 @@ private: QEMU_PIPE_HANDLE m_sock; size_t m_bufsize; unsigned char *m_buf; +#ifdef __Fuchsia__ + zx::channel m_channel; + zx::event m_event; + zx::vmo m_vmo; +#endif QemuPipeStream(QEMU_PIPE_HANDLE sock, size_t bufSize); }; diff --git a/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp b/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4ee61c5e332b1fc04e4e342560ecaa707c802ed --- /dev/null +++ b/system/OpenglSystemCommon/QemuPipeStreamFuchsia.cpp @@ -0,0 +1,296 @@ +/* +* Copyright (C) 2019 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "QemuPipeStream.h" + +#include <cutils/log.h> +#include <errno.h> +#include <fuchsia/hardware/goldfish/pipe/c/fidl.h> +#include <lib/fdio/fdio.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <zircon/process.h> + +#include <utility> + +QemuPipeStream::QemuPipeStream(size_t bufSize) : + IOStream(bufSize), + m_sock(-1), + m_bufsize(bufSize), + m_buf(nullptr) +{ +} + +QemuPipeStream::QemuPipeStream(QEMU_PIPE_HANDLE sock, size_t bufSize) : + IOStream(bufSize), + m_sock(sock), + m_bufsize(bufSize), + m_buf(nullptr) +{ +} + +QemuPipeStream::~QemuPipeStream() +{ + if (m_channel.is_valid()) { + flush(); + } + if (m_buf) { + zx_status_t status = zx_vmar_unmap(zx_vmar_root_self(), + reinterpret_cast<zx_vaddr_t>(m_buf), + m_bufsize); + if (status != ZX_OK) { + ALOGE("zx_vmar_unmap failed: %d\n", status); + abort(); + } + } +} + +int QemuPipeStream::connect(void) +{ + int fd = TEMP_FAILURE_RETRY(open(QEMU_PIPE_PATH, O_RDWR)); + if (fd < 0) { + ALOGE("%s: failed to open " QEMU_PIPE_PATH ": %s", + __FUNCTION__, strerror(errno)); + return -1; + } + + zx::channel channel; + zx_status_t status = fdio_get_service_handle( + fd, channel.reset_and_get_address()); + if (status != ZX_OK) { + ALOGE("%s: failed to get service handle for " QEMU_PIPE_PATH ": %d", + __FUNCTION__, status); + close(fd); + return -1; + } + + zx::event event; + status = zx::event::create(0, &event); + if (status != ZX_OK) { + ALOGE("%s: failed to create event: %d", __FUNCTION__, status); + return -1; + } + zx::event event_copy; + status = event.duplicate(ZX_RIGHT_SAME_RIGHTS, &event_copy); + if (status != ZX_OK) { + ALOGE("%s: failed to duplicate event: %d", __FUNCTION__, status); + return -1; + } + + status = fuchsia_hardware_goldfish_pipe_DeviceSetEvent( + channel.get(), event_copy.release()); + if (status != ZX_OK) { + ALOGE("%s: failed to set event: %d:%d", __FUNCTION__, status); + return -1; + } + + zx_status_t status2 = ZX_OK; + zx::vmo vmo; + status = fuchsia_hardware_goldfish_pipe_DeviceGetBuffer( + channel.get(), &status2, vmo.reset_and_get_address()); + if (status != ZX_OK || status2 != ZX_OK) { + ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2); + return -1; + } + + size_t len = strlen("pipe:opengles"); + status = vmo.write("pipe:opengles", 0, len + 1); + if (status != ZX_OK) { + ALOGE("%s: failed write pipe name", __FUNCTION__); + return -1; + } + + uint64_t actual; + status = fuchsia_hardware_goldfish_pipe_DeviceWrite( + channel.get(), len + 1, 0, &status2, &actual); + if (status != ZX_OK || status2 != ZX_OK) { + ALOGD("%s: connecting to pipe service failed: %d:%d", __FUNCTION__, + status, status2); + return -1; + } + + m_channel = std::move(channel); + m_event = std::move(event); + m_vmo = std::move(vmo); + return 0; +} + +void *QemuPipeStream::allocBuffer(size_t minSize) +{ + zx_status_t status; + if (m_buf) { + if (minSize <= m_bufsize) { + return m_buf; + } + status = zx_vmar_unmap(zx_vmar_root_self(), + reinterpret_cast<zx_vaddr_t>(m_buf), + m_bufsize); + if (status != ZX_OK) { + ALOGE("zx_vmar_unmap failed: %d\n", status); + abort(); + } + m_buf = nullptr; + } + + size_t allocSize = m_bufsize < minSize ? minSize : m_bufsize; + + zx_status_t status2 = ZX_OK; + status = fuchsia_hardware_goldfish_pipe_DeviceSetBufferSize( + m_channel.get(), allocSize, &status2); + if (status != ZX_OK || status2 != ZX_OK) { + ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2); + return nullptr; + } + + zx::vmo vmo; + status = fuchsia_hardware_goldfish_pipe_DeviceGetBuffer( + m_channel.get(), &status2, vmo.reset_and_get_address()); + if (status != ZX_OK || status2 != ZX_OK) { + ALOGE("%s: failed to get buffer: %d:%d", __FUNCTION__, status, status2); + return nullptr; + } + + zx_vaddr_t mapped_addr; + status = zx_vmar_map(zx_vmar_root_self(), + ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, + 0, vmo.get(), 0, allocSize, &mapped_addr); + if (status != ZX_OK) { + ALOGE("%s: failed to map buffer: %d:%d", __FUNCTION__, status); + return nullptr; + } + + m_buf = reinterpret_cast<unsigned char*>(mapped_addr); + m_bufsize = allocSize; + m_vmo = std::move(vmo); + return m_buf; +} + +int QemuPipeStream::commitBuffer(size_t size) +{ + if (size == 0) return 0; + + size_t remaining = size; + while (remaining) { + zx_status_t status2 = ZX_OK; + uint64_t actual = 0; + zx_status_t status = fuchsia_hardware_goldfish_pipe_DeviceWrite( + m_channel.get(), remaining, size - remaining, &status2, &actual); + if (status != ZX_OK) { + ALOGD("%s: Failed writing to pipe: %d", __FUNCTION__, status); + return -1; + } + if (actual) { + remaining -= actual; + continue; + } + if (status2 != ZX_ERR_SHOULD_WAIT) { + ALOGD("%s: Error writing to pipe: %d", __FUNCTION__, status2); + return -1; + } + zx_signals_t observed = ZX_SIGNAL_NONE; + status = m_event.wait_one( + fuchsia_hardware_goldfish_pipe_SIGNAL_WRITABLE | + fuchsia_hardware_goldfish_pipe_SIGNAL_HANGUP, + zx::time::infinite(), &observed); + if (status != ZX_OK) { + ALOGD("%s: wait_one failed: %d", __FUNCTION__, status); + return -1; + } + if (observed & fuchsia_hardware_goldfish_pipe_SIGNAL_HANGUP) { + ALOGD("%s: Remote end hungup", __FUNCTION__); + return -1; + } + } + + return 0; +} + +int QemuPipeStream::writeFully(const void *buf, size_t len) +{ + ALOGE("%s: unsupported", __FUNCTION__); + abort(); + return -1; +} + +QEMU_PIPE_HANDLE QemuPipeStream::getSocket() const { + return m_sock; +} + +const unsigned char *QemuPipeStream::readFully(void *buf, size_t len) +{ + if (!m_channel.is_valid()) return nullptr; + + if (!buf) { + if (len > 0) { + ALOGE("QemuPipeStream::readFully failed, buf=NULL, len %zu, lethal" + " error, exiting.", len); + abort(); + } + return nullptr; + } + + size_t remaining = len; + while (remaining) { + size_t readSize = m_bufsize < remaining ? m_bufsize : remaining; + zx_status_t status2 = ZX_OK; + uint64_t actual = 0; + zx_status_t status = fuchsia_hardware_goldfish_pipe_DeviceRead( + m_channel.get(), readSize, 0, &status2, &actual); + if (status != ZX_OK) { + ALOGD("%s: Failed reading from pipe: %d", __FUNCTION__, status); + return nullptr; + } + if (actual) { + m_vmo.read(static_cast<char *>(buf) + (len - remaining), 0, actual); + remaining -= actual; + continue; + } + if (status2 != ZX_ERR_SHOULD_WAIT) { + ALOGD("%s: Error reading from pipe: %d", __FUNCTION__, status2); + return nullptr; + } + zx_signals_t observed = ZX_SIGNAL_NONE; + status = m_event.wait_one( + fuchsia_hardware_goldfish_pipe_SIGNAL_READABLE | + fuchsia_hardware_goldfish_pipe_SIGNAL_HANGUP, + zx::time::infinite(), &observed); + if (status != ZX_OK) { + ALOGD("%s: wait_one failed: %d", __FUNCTION__, status); + return nullptr; + } + if (observed & fuchsia_hardware_goldfish_pipe_SIGNAL_HANGUP) { + ALOGD("%s: Remote end hungup", __FUNCTION__); + return nullptr; + } + } + + return static_cast<const unsigned char *>(buf); +} + +const unsigned char *QemuPipeStream::read(void *buf, size_t *inout_len) +{ + ALOGE("%s: unsupported", __FUNCTION__); + abort(); + return nullptr; +} + +int QemuPipeStream::recv(void *buf, size_t len) +{ + ALOGE("%s: unsupported", __FUNCTION__); + abort(); + return -1; +} diff --git a/system/gralloc/gralloc.cpp b/system/gralloc/gralloc.cpp index aace8e3f3c8fab8138d03d63146c7c949c281fae..d39d99ab807dcfa29d2ec17f493fd14a197f1e5d 100644 --- a/system/gralloc/gralloc.cpp +++ b/system/gralloc/gralloc.cpp @@ -506,10 +506,6 @@ static int gralloc_alloc(alloc_device_t* dev, } else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { // Camera-to-encoder is NV21 format = HAL_PIXEL_FORMAT_YCrCb_420_SP; - } else if ((usage & GRALLOC_USAGE_HW_CAMERA_MASK) == - GRALLOC_USAGE_HW_CAMERA_ZSL) { - // Camera-to-ZSL-queue is RGB_888 - format = HAL_PIXEL_FORMAT_RGB_888; } } @@ -545,11 +541,6 @@ static int gralloc_alloc(alloc_device_t* dev, glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break; - case HAL_PIXEL_FORMAT_RGB_888: - bpp = 3; - glFormat = GL_RGB; - glType = GL_UNSIGNED_BYTE; - break; case HAL_PIXEL_FORMAT_RGB_565: bpp = 2; // Workaround: distinguish vs the RGB8/RGBA8 diff --git a/system/vulkan/Android.mk b/system/vulkan/Android.mk index 30037a243b33c598c5e45637bacd46edaa420388..ebaa3c0cb8c8b6264b6a7c6eb36f39472ae84032 100644 --- a/system/vulkan/Android.mk +++ b/system/vulkan/Android.mk @@ -20,6 +20,7 @@ ifneq (true,$(GOLDFISH_OPENGL_BUILD_FOR_HOST)) $(call emugl-import,libandroidemu) LOCAL_HEADER_LIBRARIES += \ + hwvulkan_headers \ vulkan_headers \ endif diff --git a/system/vulkan/CMakeLists.txt b/system/vulkan/CMakeLists.txt index e7fd9bb4271b007d165f96d83ab8044ec9125649..68a62d670b49e25e780a29a3cee4b58f649078c6 100644 --- a/system/vulkan/CMakeLists.txt +++ b/system/vulkan/CMakeLists.txt @@ -1,7 +1,7 @@ # This is an autogenerated file! Do not edit! # instead run make from .../device/generic/goldfish-opengl # which will re-generate this file. -android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan/Android.mk" "dbe5f184561a1505d6ed26216fe645508b64bf2f3800f67946428077045c8166") +android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan/Android.mk" "7ec8946bc369a60407913f2257120f701fa2c6e2ce30e3f7148a8e7b0abca46a") set(vulkan.ranchu_src func_table.cpp goldfish_vulkan.cpp) android_add_shared_library(vulkan.ranchu) target_include_directories(vulkan.ranchu PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/OpenglSystemCommon ${GOLDFISH_DEVICE_ROOT}/bionic/libc/private ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv2_enc ${GOLDFISH_DEVICE_ROOT}/system/GLESv1_enc ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/system/vulkan ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include) diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp index 14c8c323930fa65077df9a967f225108e52eab8f..f5b380e23c6df69a7ddf52a9c4b1ffa71f9299cf 100644 --- a/system/vulkan/func_table.cpp +++ b/system/vulkan/func_table.cpp @@ -666,7 +666,8 @@ static VkResult entry_vkCreateImageView( AEMU_SCOPED_TRACE("vkCreateImageView"); auto vkEnc = HostConnection::get()->vkEncoder(); VkResult vkCreateImageView_VkResult_return = (VkResult)0; - vkCreateImageView_VkResult_return = vkEnc->vkCreateImageView(device, pCreateInfo, pAllocator, pView); + auto resources = ResourceTracker::get(); + vkCreateImageView_VkResult_return = resources->on_vkCreateImageView(vkEnc, VK_SUCCESS, device, pCreateInfo, pAllocator, pView); return vkCreateImageView_VkResult_return; } static void entry_vkDestroyImageView( @@ -1095,7 +1096,7 @@ static void entry_vkCmdSetDepthBias( } static void entry_vkCmdSetBlendConstants( VkCommandBuffer commandBuffer, - const float blendConstants) + const float blendConstants[4]) { AEMU_SCOPED_TRACE("vkCmdSetBlendConstants"); auto vkEnc = HostConnection::get()->vkEncoder(); diff --git a/system/vulkan/goldfish_vulkan.cpp b/system/vulkan/goldfish_vulkan.cpp index 18a9424580b0ec4f5c0580063822eef1e49b2b87..bf170e1cd9390b075884d32e48bbbb23fc37c8c4 100644 --- a/system/vulkan/goldfish_vulkan.cpp +++ b/system/vulkan/goldfish_vulkan.cpp @@ -161,6 +161,14 @@ SetBufferCollectionConstraintsFUCHSIA(VkDevice /*device*/, AEMU_SCOPED_TRACE("vkstubhal::SetBufferCollectionConstraintsFUCHSIA"); return VK_SUCCESS; } + +VkResult +GetBufferCollectionPropertiesFUCHSIA(VkDevice /*device*/, + VkBufferCollectionFUCHSIA /*collection*/, + VkBufferCollectionPropertiesFUCHSIA* /*pProperties*/) { + AEMU_SCOPED_TRACE("vkstubhal::GetBufferCollectionPropertiesFUCHSIA"); + return VK_SUCCESS; +} #endif PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, @@ -195,6 +203,8 @@ PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, return reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferCollectionFUCHSIA); if (strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA") == 0) return reinterpret_cast<PFN_vkVoidFunction>(SetBufferCollectionConstraintsFUCHSIA); + if (strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA") == 0) + return reinterpret_cast<PFN_vkVoidFunction>(GetBufferCollectionPropertiesFUCHSIA); #endif // Per the spec, return NULL if instance is NULL. if (!instance) @@ -208,6 +218,8 @@ PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, namespace { +#ifdef VK_USE_PLATFORM_ANDROID_KHR + int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device); hw_module_methods_t goldfish_vulkan_module_methods = { @@ -232,6 +244,8 @@ int CloseDevice(struct hw_device_t* /*device*/) { return 0; } +#endif + #define VK_HOST_CONNECTION(ret) \ HostConnection *hostCon = HostConnection::get(); \ if (!hostCon) { \ @@ -436,6 +450,26 @@ VkResult SetBufferCollectionConstraintsFUCHSIA( return res; } + +VKAPI_ATTR +VkResult GetBufferCollectionPropertiesFUCHSIA( + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties) { + AEMU_SCOPED_TRACE("goldfish_vulkan::GetBufferCollectionPropertiesFUCHSIA"); + + VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST) + + if (!hostSupportsVulkan) { + return vkstubhal::GetBufferCollectionPropertiesFUCHSIA(device, collection, pProperties); + } + + VkResult res = goldfish_vk::ResourceTracker::get()-> + on_vkGetBufferCollectionPropertiesFUCHSIA( + vkEnc, VK_SUCCESS, device, collection, pProperties); + + return res; +} #endif static PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) { @@ -469,6 +503,9 @@ static PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) { if (!strcmp(name, "vkSetBufferCollectionConstraintsFUCHSIA")) { return (PFN_vkVoidFunction)SetBufferCollectionConstraintsFUCHSIA; } + if (!strcmp(name, "vkGetBufferCollectionPropertiesFUCHSIA")) { + return (PFN_vkVoidFunction)GetBufferCollectionPropertiesFUCHSIA; + } #endif if (!strcmp(name, "vkGetDeviceProcAddr")) { return (PFN_vkVoidFunction)(GetDeviceProcAddr); @@ -498,6 +535,8 @@ PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) { return (PFN_vkVoidFunction)(goldfish_vk::goldfish_vulkan_get_instance_proc_address(instance, name)); } +#ifdef VK_USE_PLATFORM_ANDROID_KHR + hwvulkan_device_t goldfish_vulkan_device = { .common = { .tag = HARDWARE_DEVICE_TAG, @@ -517,27 +556,43 @@ int OpenDevice(const hw_module_t* /*module*/, if (strcmp(id, HWVULKAN_DEVICE_0) == 0) { *device = &goldfish_vulkan_device.common; -#ifdef VK_USE_PLATFORM_FUCHSIA - goldfish_vk::ResourceTracker::get()->setColorBufferFunctions( - [](uint32_t width, uint32_t height, uint32_t format) { - VK_HOST_CONNECTION((uint32_t)0) - uint32_t r = rcEnc->rcCreateColorBuffer(rcEnc, width, height, format); - return r; - }, - [](uint32_t id) { - VK_HOST_CONNECTION() - rcEnc->rcOpenColorBuffer(rcEnc, id); - }, - [](uint32_t id){ - VK_HOST_CONNECTION() - rcEnc->rcCloseColorBuffer(rcEnc, id); - }); -#else goldfish_vk::ResourceTracker::get(); -#endif return 0; } return -ENOENT; } +#endif + +#ifdef VK_USE_PLATFORM_FUCHSIA + +class VulkanDevice { +public: + VulkanDevice() { + goldfish_vk::ResourceTracker::get(); + } + + static VulkanDevice& GetInstance() { + static VulkanDevice g_instance; + return g_instance; + } + + PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) { + return ::GetInstanceProcAddr(instance, name); + } +}; + +extern "C" __attribute__((visibility("default"))) PFN_vkVoidFunction +vk_icdGetInstanceProcAddr(VkInstance instance, const char* name) { + return VulkanDevice::GetInstance().GetInstanceProcAddr(instance, name); +} + +extern "C" __attribute__((visibility("default"))) VkResult +vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) { + *pSupportedVersion = std::min(*pSupportedVersion, 3u); + return VK_SUCCESS; +} + +#endif + } // namespace diff --git a/system/vulkan_enc/Android.mk b/system/vulkan_enc/Android.mk index 86d9a4ca90cf5584fa2c1fb059187e044b1d9780..c51aa7eb679fb5d52cda6c8aba39f8d7a114c7c1 100644 --- a/system/vulkan_enc/Android.mk +++ b/system/vulkan_enc/Android.mk @@ -28,6 +28,7 @@ LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/../vulkan_enc \ LOCAL_HEADER_LIBRARIES += \ + hwvulkan_headers \ vulkan_headers \ endif diff --git a/system/vulkan_enc/AndroidHardwareBuffer.cpp b/system/vulkan_enc/AndroidHardwareBuffer.cpp index a4478306863e15006d8e578f92edce2a8a7cbe59..5cebdc28ebad9881024a9afa30a149bd401ed2d1 100644 --- a/system/vulkan_enc/AndroidHardwareBuffer.cpp +++ b/system/vulkan_enc/AndroidHardwareBuffer.cpp @@ -59,15 +59,13 @@ VkResult getAndroidHardwareBufferPropertiesANDROID( VkAndroidHardwareBufferPropertiesANDROID* pProperties) { VkAndroidHardwareBufferFormatPropertiesANDROID* ahbFormatProps = - (VkAndroidHardwareBufferFormatPropertiesANDROID*)vk_find_struct( - (vk_struct_common*)pProperties->pNext, - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID); + vk_find_struct<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties); if (ahbFormatProps) { AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); - uint64_t gpu_usage = + const uint64_t gpu_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER; @@ -76,10 +74,8 @@ VkResult getAndroidHardwareBufferPropertiesANDROID( return VK_ERROR_INVALID_EXTERNAL_HANDLE; } - ahbFormatProps->format = - vk_format_from_android(desc.format); - - ahbFormatProps->externalFormat = VK_FORMAT_G8B8G8R8_422_UNORM; + ahbFormatProps->format = vk_format_from_android(desc.format); + ahbFormatProps->externalFormat = desc.format; // The formatFeatures member must include // VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of @@ -103,7 +99,10 @@ VkResult getAndroidHardwareBufferPropertiesANDROID( ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY; ahbFormatProps->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY; - ahbFormatProps->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601; + ahbFormatProps->suggestedYcbcrModel = + android_format_is_yuv(desc.format) ? + VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 : + VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; ahbFormatProps->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT; diff --git a/system/vulkan_enc/CMakeLists.txt b/system/vulkan_enc/CMakeLists.txt index 9d98562c964450501b724b95e1a70a666ccefe1f..9d4e7e952b4a294ef76f1eff22248ba52023899e 100644 --- a/system/vulkan_enc/CMakeLists.txt +++ b/system/vulkan_enc/CMakeLists.txt @@ -1,7 +1,7 @@ # This is an autogenerated file! Do not edit! # instead run make from .../device/generic/goldfish-opengl # which will re-generate this file. -android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc/Android.mk" "694b4f97bb916f16f52b9b2f2287d248de5271e6113ae367cf8bf360637659c5") +android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc/Android.mk" "4e4982fe274cdee96492d57f444a19d3a979720f17df5d289961d77cbdb4054b") set(vulkan_enc_src AndroidHardwareBuffer.cpp HostVisibleMemoryVirtualization.cpp Resources.cpp Validation.cpp VulkanStreamGuest.cpp VulkanHandleMapping.cpp ResourceTracker.cpp VkEncoder.cpp goldfish_vk_extension_structs_guest.cpp goldfish_vk_marshaling_guest.cpp goldfish_vk_deepcopy_guest.cpp goldfish_vk_handlemap_guest.cpp goldfish_vk_transform_guest.cpp) android_add_shared_library(vulkan_enc) target_include_directories(vulkan_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include/vulkan) diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp index 01ad42b77cd9831a324bef06c3733eedf81ed255..4e86c20adb518da9c8ab150e029f2070d6239a1b 100644 --- a/system/vulkan_enc/ResourceTracker.cpp +++ b/system/vulkan_enc/ResourceTracker.cpp @@ -14,6 +14,7 @@ // limitations under the License. #include "ResourceTracker.h" +#include "goldfish_vk_private_defs.h" #include "../OpenglSystemCommon/EmulatorFeatureInfo.h" @@ -26,31 +27,6 @@ typedef uint32_t zx_handle_t; void zx_handle_close(zx_handle_t) { } void zx_event_create(int, zx_handle_t*) { } -typedef struct VkImportMemoryZirconHandleInfoFUCHSIA { - VkStructureType sType; - const void* pNext; - VkExternalMemoryHandleTypeFlagBits handleType; - uint32_t handle; -} VkImportMemoryZirconHandleInfoFUCHSIA; - -typedef uint32_t VkBufferCollectionFUCHSIA; - -typedef struct VkImportMemoryBufferCollectionFUCHSIA { - VkStructureType sType; - const void* pNext; - VkBufferCollectionFUCHSIA collection; - uint32_t index; -} VkImportMemoryBufferCollectionFUCHSIA; - -#define VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA \ - ((VkStructureType)1001000000) -#define VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA \ - ((VkStructureType)1001000000) -#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA \ - ((VkStructureType)0x00000800) -#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA \ - ((VkStructureType)0x00000020) - #include "AndroidHardwareBuffer.h" #endif // VK_USE_PLATFORM_ANDROID_KHR @@ -58,7 +34,7 @@ typedef struct VkImportMemoryBufferCollectionFUCHSIA { #ifdef VK_USE_PLATFORM_FUCHSIA #include <cutils/native_handle.h> -#include <fuchsia/hardware/goldfish/c/fidl.h> +#include <fuchsia/hardware/goldfish/control/c/fidl.h> #include <fuchsia/sysmem/cpp/fidl.h> #include <lib/fdio/directory.h> #include <lib/fdio/fd.h> @@ -273,7 +249,6 @@ public: SubAlloc subAlloc; AHardwareBuffer* ahw = nullptr; zx_handle_t vmoHandle = ZX_HANDLE_INVALID; - uint32_t cbHandle = 0; }; // custom guest-side structs for images/buffers because of AHardwareBuffer :(( @@ -285,7 +260,6 @@ public: VkDeviceMemory currentBacking = VK_NULL_HANDLE; VkDeviceSize currentBackingOffset = 0; VkDeviceSize currentBackingSize = 0; - uint32_t cbHandle = 0; }; struct VkBuffer_Info { @@ -364,10 +338,6 @@ public: AHardwareBuffer_release(memInfo.ahw); } - if (memInfo.cbHandle) { - (*mCloseColorBuffer)(memInfo.cbHandle); - } - if (memInfo.vmoHandle != ZX_HANDLE_INVALID) { zx_handle_close(memInfo.vmoHandle); } @@ -394,9 +364,6 @@ public: if (it == info_VkImage.end()) return; auto& imageInfo = it->second; - if (imageInfo.cbHandle) { - (*mCloseColorBuffer)(imageInfo.cbHandle); - } info_VkImage.erase(img); } @@ -479,8 +446,7 @@ public: uint8_t* ptr, uint32_t memoryTypeIndex, AHardwareBuffer* ahw = nullptr, - zx_handle_t vmoHandle = ZX_HANDLE_INVALID, - uint32_t cbHandle = 0) { + zx_handle_t vmoHandle = ZX_HANDLE_INVALID) { AutoLock lock(mLock); auto& deviceInfo = info_VkDevice[device]; auto& info = info_VkDeviceMemory[memory]; @@ -491,7 +457,6 @@ public: info.memoryTypeIndex = memoryTypeIndex; info.ahw = ahw; info.vmoHandle = vmoHandle; - info.cbHandle = cbHandle; } void setImageInfo(VkImage image, @@ -575,11 +540,24 @@ public: } #ifdef VK_USE_PLATFORM_FUCHSIA - zx_status_t status = fdio_service_connect( - "/svc/fuchsia.sysmem.Allocator", - mSysmemAllocator.NewRequest().TakeChannel().release()); - if (status != ZX_OK) { - ALOGE("failed to connect to sysmem service, status %d", status); + if (mFeatureInfo->hasVulkan) { + int fd = open("/dev/class/goldfish-control/000", O_RDWR); + if (fd < 0) { + ALOGE("failed to open control device"); + abort(); + } + zx_status_t status = fdio_get_service_handle(fd, &mControlDevice); + if (status != ZX_OK) { + ALOGE("failed to get control service handle, status %d", status); + abort(); + } + status = fuchsia_hardware_goldfish_control_DeviceConnectSysmem( + mControlDevice, + mSysmemAllocator.NewRequest().TakeChannel().release()); + if (status != ZX_OK) { + ALOGE("failed to get sysmem connection, status %d", status); + abort(); + } } #endif } @@ -621,14 +599,6 @@ public: return -1; } - void setColorBufferFunctions(PFN_CreateColorBuffer create, - PFN_OpenColorBuffer open, - PFN_CloseColorBuffer close) { - mCreateColorBuffer = create; - mOpenColorBuffer = open; - mCloseColorBuffer = close; - } - void deviceMemoryTransform_tohost( VkDeviceMemory* memory, uint32_t memoryCount, VkDeviceSize* offset, uint32_t offsetCount, @@ -1210,7 +1180,7 @@ public: for (uint32_t i = 0; i < info.memProps.memoryTypeCount; ++i) { if (info.memProps.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { - pProperties->memoryTypeBits = 1ull << i; + pProperties->memoryTypeBits |= 1ull << i; } } return VK_SUCCESS; @@ -1319,10 +1289,9 @@ public: delete sysmem_collection; } - VkResult on_vkSetBufferCollectionConstraintsFUCHSIA( - void*, VkResult, VkDevice, - VkBufferCollectionFUCHSIA collection, - const VkImageCreateInfo* pImageInfo) { + void setBufferCollectionConstraints(fuchsia::sysmem::BufferCollectionSyncPtr* collection, + const VkImageCreateInfo* pImageInfo, + size_t min_size_bytes) { fuchsia::sysmem::BufferCollectionConstraints constraints = {}; constraints.usage.vulkan = fuchsia::sysmem::vulkanUsageColorAttachment | fuchsia::sysmem::vulkanUsageTransferSrc | @@ -1332,13 +1301,14 @@ public: constraints.has_buffer_memory_constraints = true; fuchsia::sysmem::BufferMemoryConstraints& buffer_constraints = constraints.buffer_memory_constraints; - buffer_constraints.min_size_bytes = pImageInfo->extent.width * pImageInfo->extent.height * 4; + buffer_constraints.min_size_bytes = min_size_bytes; buffer_constraints.max_size_bytes = 0xffffffff; buffer_constraints.physically_contiguous_required = false; buffer_constraints.secure_required = false; buffer_constraints.secure_permitted = false; - buffer_constraints.ram_domain_supported = true; + buffer_constraints.ram_domain_supported = false; buffer_constraints.cpu_domain_supported = false; + buffer_constraints.gpu_domain_supported = true; constraints.image_format_constraints_count = 1; fuchsia::sysmem::ImageFormatConstraints& image_constraints = constraints.image_format_constraints[0]; @@ -1360,8 +1330,57 @@ public: image_constraints.display_width_divisor = 1; image_constraints.display_height_divisor = 1; + (*collection)->SetConstraints(true, constraints); + } + + VkResult on_vkSetBufferCollectionConstraintsFUCHSIA( + void*, VkResult, VkDevice, + VkBufferCollectionFUCHSIA collection, + const VkImageCreateInfo* pImageInfo) { + auto sysmem_collection = + reinterpret_cast<fuchsia::sysmem::BufferCollectionSyncPtr*>(collection); + setBufferCollectionConstraints( + sysmem_collection, pImageInfo, + pImageInfo->extent.width * pImageInfo->extent.height * 4); + return VK_SUCCESS; + } + + VkResult on_vkGetBufferCollectionPropertiesFUCHSIA( + void*, VkResult, + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties) { auto sysmem_collection = reinterpret_cast<fuchsia::sysmem::BufferCollectionSyncPtr*>(collection); - (*sysmem_collection)->SetConstraints(true, constraints); + fuchsia::sysmem::BufferCollectionInfo_2 info; + zx_status_t status2; + zx_status_t status = (*sysmem_collection)->WaitForBuffersAllocated(&status2, &info); + if (status != ZX_OK || status2 != ZX_OK) { + ALOGE("Failed wait for allocation: %d %d", status, status2); + return VK_ERROR_INITIALIZATION_FAILED; + } + if (!info.settings.has_image_format_constraints) { + return VK_ERROR_INITIALIZATION_FAILED; + } + pProperties->count = info.buffer_count; + + AutoLock lock(mLock); + + auto deviceIt = info_VkDevice.find(device); + + if (deviceIt == info_VkDevice.end()) { + return VK_ERROR_INITIALIZATION_FAILED; + } + + auto& deviceInfo = deviceIt->second; + + // Device local memory type supported. + pProperties->memoryTypeBits = 0; + for (uint32_t i = 0; i < deviceInfo.memProps.memoryTypeCount; ++i) { + if (deviceInfo.memProps.memoryTypes[i].propertyFlags & + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) { + pProperties->memoryTypeBits |= 1ull << i; + } + } return VK_SUCCESS; } #endif @@ -1493,7 +1512,9 @@ public: VkEncoder* enc = (VkEncoder*)context; - VkMemoryAllocateInfo finalAllocInfo = *pAllocateInfo; + VkMemoryAllocateInfo finalAllocInfo = vk_make_orphan_copy(*pAllocateInfo); + vk_struct_chain_iterator structChainIter = vk_make_chain_iterator(&finalAllocInfo); + VkMemoryDedicatedAllocateInfo dedicatedAllocInfo; VkImportColorBufferGOOGLE importCbInfo = { VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE, 0, @@ -1502,30 +1523,20 @@ public: // VK_STRUCTURE_TYPE_IMPORT_PHYSICAL_ADDRESS_GOOGLE, 0, // }; - vk_struct_common* structChain = - structChain = vk_init_struct_chain( - (vk_struct_common*)(&finalAllocInfo)); - structChain->pNext = nullptr; - - VkExportMemoryAllocateInfo* exportAllocateInfoPtr = - (VkExportMemoryAllocateInfo*)vk_find_struct((vk_struct_common*)pAllocateInfo, - VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO); + const VkExportMemoryAllocateInfo* exportAllocateInfoPtr = + vk_find_struct<VkExportMemoryAllocateInfo>(pAllocateInfo); - VkImportAndroidHardwareBufferInfoANDROID* importAhbInfoPtr = - (VkImportAndroidHardwareBufferInfoANDROID*)vk_find_struct((vk_struct_common*)pAllocateInfo, - VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID); + const VkImportAndroidHardwareBufferInfoANDROID* importAhbInfoPtr = + vk_find_struct<VkImportAndroidHardwareBufferInfoANDROID>(pAllocateInfo); - VkImportMemoryBufferCollectionFUCHSIA* importBufferCollectionInfoPtr = - (VkImportMemoryBufferCollectionFUCHSIA*)vk_find_struct((vk_struct_common*)pAllocateInfo, - VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA); + const VkImportMemoryBufferCollectionFUCHSIA* importBufferCollectionInfoPtr = + vk_find_struct<VkImportMemoryBufferCollectionFUCHSIA>(pAllocateInfo); - VkImportMemoryZirconHandleInfoFUCHSIA* importVmoInfoPtr = - (VkImportMemoryZirconHandleInfoFUCHSIA*)vk_find_struct((vk_struct_common*)pAllocateInfo, - VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA); + const VkImportMemoryZirconHandleInfoFUCHSIA* importVmoInfoPtr = + vk_find_struct<VkImportMemoryZirconHandleInfoFUCHSIA>(pAllocateInfo); - VkMemoryDedicatedAllocateInfo* dedicatedAllocInfoPtr = - (VkMemoryDedicatedAllocateInfo*)vk_find_struct((vk_struct_common*)pAllocateInfo, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + const VkMemoryDedicatedAllocateInfo* dedicatedAllocInfoPtr = + vk_find_struct<VkMemoryDedicatedAllocateInfo>(pAllocateInfo); bool shouldPassThroughDedicatedAllocInfo = !exportAllocateInfoPtr && @@ -1549,12 +1560,8 @@ public: if (shouldPassThroughDedicatedAllocInfo && dedicatedAllocInfoPtr) { - dedicatedAllocInfo = *dedicatedAllocInfoPtr; - structChain->pNext = - (vk_struct_common*)(&dedicatedAllocInfo); - structChain = - (vk_struct_common*)(&dedicatedAllocInfo); - structChain->pNext = nullptr; + dedicatedAllocInfo = vk_make_orphan_copy(*dedicatedAllocInfoPtr); + vk_append_struct(&structChainIter, &dedicatedAllocInfo); } // State needed for import/export. @@ -1575,8 +1582,6 @@ public: // and then we attach a new VkDeviceMemory // to the AHardwareBuffer on the host via an "import" operation. AHardwareBuffer* ahw = nullptr; - zx_handle_t vmo_handle = ZX_HANDLE_INVALID; - uint32_t cbHandle = 0; if (exportAllocateInfoPtr) { exportAhb = @@ -1667,10 +1672,11 @@ public: const cb_handle_t* cb_handle = reinterpret_cast<const cb_handle_t*>(handle); importCbInfo.colorBuffer = cb_handle->hostHandle; - structChain = - vk_append_struct(structChain, (vk_struct_common*)(&importCbInfo)); + vk_append_struct(&structChainIter, &importCbInfo); } + zx_handle_t vmo_handle = ZX_HANDLE_INVALID; + if (importBufferCollection) { #ifdef VK_USE_PLATFORM_FUCHSIA @@ -1697,28 +1703,104 @@ public: vmo_handle = importVmoInfoPtr->handle; } - if (vmo_handle != ZX_HANDLE_INVALID) { - uint64_t cb = 0; - #ifdef VK_USE_PLATFORM_FUCHSIA - zx_object_get_cookie(vmo_handle, vmo_handle, &cb); -#endif + if (vmo_handle == ZX_HANDLE_INVALID && + !isHostVisibleMemoryTypeIndexForGuest( + &mHostVisibleMemoryVirtInfo, finalAllocInfo.memoryTypeIndex)) { + bool hasDedicatedImage = dedicatedAllocInfoPtr && + (dedicatedAllocInfoPtr->image != VK_NULL_HANDLE); + VkImageCreateInfo imageCreateInfo = {}; + + if (hasDedicatedImage) { + AutoLock lock(mLock); + + auto it = info_VkImage.find(dedicatedAllocInfoPtr->image); + if (it == info_VkImage.end()) return VK_ERROR_INITIALIZATION_FAILED; + const auto& imageInfo = it->second; + + imageCreateInfo = imageInfo.createInfo; + } + + if (imageCreateInfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { + fuchsia::sysmem::BufferCollectionTokenSyncPtr token; + zx_status_t status = mSysmemAllocator->AllocateSharedCollection( + token.NewRequest()); + if (status != ZX_OK) { + ALOGE("AllocateSharedCollection failed: %d", status); + abort(); + } + + fuchsia::sysmem::BufferCollectionSyncPtr collection; + status = mSysmemAllocator->BindSharedCollection( + std::move(token), collection.NewRequest()); + if (status != ZX_OK) { + ALOGE("BindSharedCollection failed: %d", status); + abort(); + } + setBufferCollectionConstraints(&collection, + &imageCreateInfo, + finalAllocInfo.allocationSize); + + fuchsia::sysmem::BufferCollectionInfo_2 info; + zx_status_t status2; + status = collection->WaitForBuffersAllocated(&status2, &info); + if (status == ZX_OK && status2 == ZX_OK) { + if (!info.buffer_count) { + ALOGE("WaitForBuffersAllocated returned invalid count: %d", status); + abort(); + } + vmo_handle = info.buffers[0].vmo.release(); + } else { + ALOGE("WaitForBuffersAllocated failed: %d %d", status, status2); + abort(); + } + + collection->Close(); - if (cb) { - cbHandle = importCbInfo.colorBuffer = cb; - structChain = - vk_append_struct(structChain, (vk_struct_common*)(&importCbInfo)); + zx_handle_t vmo_copy; + status = zx_handle_duplicate(vmo_handle, ZX_RIGHT_SAME_RIGHTS, &vmo_copy); + if (status != ZX_OK) { + ALOGE("Failed to duplicate VMO: %d", status); + abort(); + } + status = fuchsia_hardware_goldfish_control_DeviceCreateColorBuffer( + mControlDevice, + vmo_copy, + imageCreateInfo.extent.width, + imageCreateInfo.extent.height, + fuchsia_hardware_goldfish_control_FormatType_BGRA, + &status2); + if (status != ZX_OK || status2 != ZX_OK) { + ALOGE("CreateColorBuffer failed: %d:%d", status, status2); + abort(); + } } } + if (vmo_handle != ZX_HANDLE_INVALID) { + zx_handle_t vmo_copy; + zx_status_t status = zx_handle_duplicate(vmo_handle, + ZX_RIGHT_SAME_RIGHTS, + &vmo_copy); + if (status != ZX_OK) { + ALOGE("Failed to duplicate VMO: %d", status); + abort(); + } + zx_status_t status2 = ZX_OK; + status = fuchsia_hardware_goldfish_control_DeviceGetColorBuffer( + mControlDevice, vmo_copy, &status2, &importCbInfo.colorBuffer); + if (status != ZX_OK || status2 != ZX_OK) { + ALOGE("GetColorBuffer failed: %d:%d", status, status2); + } + vk_append_struct(&structChainIter, &importCbInfo); + } +#endif + // TODO if (exportVmo) { } if (!isHostVisibleMemoryTypeIndexForGuest( &mHostVisibleMemoryVirtInfo, finalAllocInfo.memoryTypeIndex)) { - if (cbHandle) { - (*mOpenColorBuffer)(cbHandle); - } input_result = enc->vkAllocateMemory( device, &finalAllocInfo, pAllocator, pMemory); @@ -1732,8 +1814,7 @@ public: 0, nullptr, finalAllocInfo.memoryTypeIndex, ahw, - vmo_handle, - cbHandle); + vmo_handle); return VK_SUCCESS; } @@ -2006,10 +2087,7 @@ public: transformExternalResourceMemoryRequirementsForGuest(&reqs2->memoryRequirements); VkMemoryDedicatedRequirements* dedicatedReqs = - (VkMemoryDedicatedRequirements*) - vk_find_struct( - (vk_struct_common*)reqs2, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS); + vk_find_struct<VkMemoryDedicatedRequirements>(reqs2); if (!dedicatedReqs) return; @@ -2038,10 +2116,7 @@ public: transformExternalResourceMemoryRequirementsForGuest(&reqs2->memoryRequirements); VkMemoryDedicatedRequirements* dedicatedReqs = - (VkMemoryDedicatedRequirements*) - vk_find_struct( - (vk_struct_common*)reqs2, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS); + vk_find_struct<VkMemoryDedicatedRequirements>(reqs2); if (!dedicatedReqs) return; @@ -2056,164 +2131,91 @@ public: VkImage *pImage) { VkEncoder* enc = (VkEncoder*)context; - uint32_t cbHandle = 0; - - VkImageCreateInfo localCreateInfo = *pCreateInfo; - VkNativeBufferANDROID localAnb; + VkImageCreateInfo localCreateInfo = vk_make_orphan_copy(*pCreateInfo); + vk_struct_chain_iterator structChainIter = vk_make_chain_iterator(&localCreateInfo); VkExternalMemoryImageCreateInfo localExtImgCi; - VkImageCreateInfo* pCreateInfo_mut = &localCreateInfo; - - VkNativeBufferANDROID* anbInfoPtr = - (VkNativeBufferANDROID*) - vk_find_struct( - (vk_struct_common*)pCreateInfo_mut, - VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID); - - if (anbInfoPtr) { - localAnb = *anbInfoPtr; - } - - VkExternalMemoryImageCreateInfo* extImgCiPtr = - (VkExternalMemoryImageCreateInfo*) - vk_find_struct( - (vk_struct_common*)pCreateInfo_mut, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); - + const VkExternalMemoryImageCreateInfo* extImgCiPtr = + vk_find_struct<VkExternalMemoryImageCreateInfo>(pCreateInfo); if (extImgCiPtr) { - localExtImgCi = *extImgCiPtr; - } - -#ifdef VK_USE_PLATFORM_ANDROID_KHR - VkExternalFormatANDROID localExtFormatAndroid; - VkExternalFormatANDROID* extFormatAndroidPtr = - (VkExternalFormatANDROID*) - vk_find_struct( - (vk_struct_common*)pCreateInfo_mut, - VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID); - if (extFormatAndroidPtr) { - localExtFormatAndroid = *extFormatAndroidPtr; - } -#endif - -#ifdef VK_USE_PLATFORM_FUCHSIA - VkFuchsiaImageFormatFUCHSIA* extFuchsiaImageFormatPtr = - (VkFuchsiaImageFormatFUCHSIA*) - vk_find_struct( - (vk_struct_common*)pCreateInfo_mut, - VK_STRUCTURE_TYPE_FUCHSIA_IMAGE_FORMAT_FUCHSIA); - - VkBufferCollectionImageCreateInfoFUCHSIA* extBufferCollectionPtr = - (VkBufferCollectionImageCreateInfoFUCHSIA*) - vk_find_struct( - (vk_struct_common*)pCreateInfo_mut, - VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA); -#endif - - vk_struct_common* structChain = - vk_init_struct_chain((vk_struct_common*)pCreateInfo_mut); - - if (extImgCiPtr) { - structChain = - vk_append_struct( - structChain, (vk_struct_common*)(&localExtImgCi)); + localExtImgCi = vk_make_orphan_copy(*extImgCiPtr); + vk_append_struct(&structChainIter, &localExtImgCi); } #ifdef VK_USE_PLATFORM_ANDROID_KHR + VkNativeBufferANDROID localAnb; + const VkNativeBufferANDROID* anbInfoPtr = + vk_find_struct<VkNativeBufferANDROID>(pCreateInfo); if (anbInfoPtr) { - structChain = - vk_append_struct( - structChain, (vk_struct_common*)(&localAnb)); + localAnb = vk_make_orphan_copy(*anbInfoPtr); + vk_append_struct(&structChainIter, &localAnb); } + VkExternalFormatANDROID localExtFormatAndroid; + const VkExternalFormatANDROID* extFormatAndroidPtr = + vk_find_struct<VkExternalFormatANDROID>(pCreateInfo); if (extFormatAndroidPtr) { + localExtFormatAndroid = vk_make_orphan_copy(*extFormatAndroidPtr); + // Do not append external format android; - // instead, replace the local image pCreateInfo_mut format + // instead, replace the local image localCreateInfo format // with the corresponding Vulkan format if (extFormatAndroidPtr->externalFormat) { - pCreateInfo_mut->format = + localCreateInfo.format = vk_format_from_android(extFormatAndroidPtr->externalFormat); + if (localCreateInfo.format == VK_FORMAT_UNDEFINED) + return VK_ERROR_VALIDATION_FAILED_EXT; } } #endif - #ifdef VK_USE_PLATFORM_FUCHSIA - VkNativeBufferANDROID native_info = { - .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID, - .pNext = NULL, - }; - cb_handle_t native_handle( - 0, 0, 0, 0, 0, 0, 0, 0, 0, FRAMEWORK_FORMAT_GL_COMPATIBLE); - - if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { - // Create color buffer. - cbHandle = (*mCreateColorBuffer)(pCreateInfo_mut->extent.width, - pCreateInfo_mut->extent.height, - 0x1908 /*GL_RGBA*/); - native_handle.hostHandle = cbHandle; - native_info.handle = (uint32_t*)&native_handle; - native_info.stride = 0; - native_info.format = 1; // RGBA - native_info.usage = GRALLOC_USAGE_HW_FB; - if (pCreateInfo_mut->pNext) { - abort(); + const VkBufferCollectionImageCreateInfoFUCHSIA* extBufferCollectionPtr = + vk_find_struct<VkBufferCollectionImageCreateInfoFUCHSIA>(pCreateInfo); + if (extBufferCollectionPtr) { + auto collection = reinterpret_cast<fuchsia::sysmem::BufferCollectionSyncPtr*>( + extBufferCollectionPtr->collection); + uint32_t index = extBufferCollectionPtr->index; + zx_handle_t vmo_handle = ZX_HANDLE_INVALID; + + fuchsia::sysmem::BufferCollectionInfo_2 info; + zx_status_t status2; + zx_status_t status = (*collection)->WaitForBuffersAllocated(&status2, &info); + if (status == ZX_OK && status2 == ZX_OK) { + if (index < info.buffer_count) { + vmo_handle = info.buffers[index].vmo.release(); + } + } else { + ALOGE("WaitForBuffersAllocated failed: %d %d", status, status2); } - pCreateInfo_mut->pNext = &native_info; - - bool is_physically_contiguous = false; - if (extBufferCollectionPtr) { - auto collection = reinterpret_cast<fuchsia::sysmem::BufferCollectionSyncPtr*>( - extBufferCollectionPtr->collection); - fuchsia::sysmem::BufferCollectionInfo_2 info; - zx_status_t status2; - zx_status_t status = (*collection)->WaitForBuffersAllocated(&status2, &info); - if (status == ZX_OK && status2 == ZX_OK) { - is_physically_contiguous = - info.settings.has_image_format_constraints && - info.settings.buffer_settings.is_physically_contiguous; - } else { - ALOGE("WaitForBuffersAllocated failed: %d %d", status, status2); - } - } else if (extFuchsiaImageFormatPtr) { - auto imageFormat = static_cast<const uint8_t*>( - extFuchsiaImageFormatPtr->imageFormat); - size_t imageFormatSize = - extFuchsiaImageFormatPtr->imageFormatSize; - std::vector<uint8_t> message( - imageFormat, imageFormat + imageFormatSize); - fidl::Message msg(fidl::BytePart(message.data(), - imageFormatSize, - imageFormatSize), - fidl::HandlePart()); - const char* err_msg = nullptr; - zx_status_t status = msg.Decode( - fuchsia::sysmem::SingleBufferSettings::FidlType, &err_msg); - if (status != ZX_OK) { - ALOGE("Invalid SingleBufferSettings: %d %s", status, - err_msg); - abort(); + + if (vmo_handle != ZX_HANDLE_INVALID) { + zx_status_t status2 = ZX_OK; + status = fuchsia_hardware_goldfish_control_DeviceCreateColorBuffer( + mControlDevice, + vmo_handle, + localCreateInfo.extent.width, + localCreateInfo.extent.height, + fuchsia_hardware_goldfish_control_FormatType_BGRA, + &status2); + if (status != ZX_OK || status2 != ZX_OK) { + ALOGE("CreateColorBuffer failed: %d:%d", status, status2); } - fidl::Decoder decoder(std::move(msg)); - fuchsia::sysmem::SingleBufferSettings settings; - fuchsia::sysmem::SingleBufferSettings::Decode( - &decoder, &settings, 0); - is_physically_contiguous = - settings.buffer_settings.is_physically_contiguous; } + } - if (is_physically_contiguous) { - // Replace the local image pCreateInfo_mut format - // with the color buffer format if physically contiguous - // and a potential display layer candidate. - // TODO(reveman): Remove this after adding BGRA color - // buffer support. - pCreateInfo_mut->format = VK_FORMAT_R8G8B8A8_UNORM; + // Allow external memory for all color attachments on fuchsia. + if (localCreateInfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { + if (!extImgCiPtr) { + localExtImgCi.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + localExtImgCi.pNext = nullptr; + localExtImgCi.handleTypes = ~0; // handle type just needs to be non-zero + extImgCiPtr = &localExtImgCi; // no vk_append_struct required } } #endif - VkResult res = enc->vkCreateImage(device, pCreateInfo_mut, pAllocator, pImage); + VkResult res = enc->vkCreateImage(device, &localCreateInfo, pAllocator, pImage); if (res != VK_SUCCESS) return res; @@ -2225,9 +2227,8 @@ public: auto& info = it->second; info.device = device; - info.createInfo = *pCreateInfo_mut; + info.createInfo = *pCreateInfo; info.createInfo.pNext = nullptr; - info.cbHandle = cbHandle; if (!extImgCiPtr) return res; @@ -2244,28 +2245,14 @@ public: const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) { - VkSamplerYcbcrConversionCreateInfo localCreateInfo = *pCreateInfo; - VkSamplerYcbcrConversionCreateInfo* pCreateInfo_mut = &localCreateInfo; - -#ifdef VK_USE_PLATFORM_ANDROID_KHR - VkExternalFormatANDROID localExtFormatAndroid; - VkExternalFormatANDROID* extFormatAndroidPtr = - (VkExternalFormatANDROID*) - vk_find_struct( - (vk_struct_common*)pCreateInfo_mut, - VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID); - if (extFormatAndroidPtr) { - localExtFormatAndroid = *extFormatAndroidPtr; - } -#endif - - vk_struct_common* structChain = - vk_init_struct_chain((vk_struct_common*)pCreateInfo_mut); + VkSamplerYcbcrConversionCreateInfo localCreateInfo = vk_make_orphan_copy(*pCreateInfo); #ifdef VK_USE_PLATFORM_ANDROID_KHR + const VkExternalFormatANDROID* extFormatAndroidPtr = + vk_find_struct<VkExternalFormatANDROID>(pCreateInfo); if (extFormatAndroidPtr) { if (extFormatAndroidPtr->externalFormat) { - pCreateInfo_mut->format = + localCreateInfo.format = vk_format_from_android(extFormatAndroidPtr->externalFormat); } } @@ -2273,7 +2260,7 @@ public: VkEncoder* enc = (VkEncoder*)context; return enc->vkCreateSamplerYcbcrConversion( - device, pCreateInfo, pAllocator, pYcbcrConversion); + device, &localCreateInfo, pAllocator, pYcbcrConversion); } VkResult on_vkCreateSamplerYcbcrConversionKHR( @@ -2283,34 +2270,22 @@ public: const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) { - VkSamplerYcbcrConversionCreateInfo localCreateInfo = *pCreateInfo; - VkSamplerYcbcrConversionCreateInfo* pCreateInfo_mut = &localCreateInfo; - -#ifdef VK_USE_PLATFORM_ANDROID_KHR - VkExternalFormatANDROID localExtFormatAndroid; - VkExternalFormatANDROID* extFormatAndroidPtr = - (VkExternalFormatANDROID*) - vk_find_struct( - (vk_struct_common*)pCreateInfo_mut, - VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID); - if (extFormatAndroidPtr) { - localExtFormatAndroid = *extFormatAndroidPtr; - } -#endif - - vk_struct_common* structChain = - vk_init_struct_chain((vk_struct_common*)pCreateInfo_mut); + VkSamplerYcbcrConversionCreateInfo localCreateInfo = vk_make_orphan_copy(*pCreateInfo); #ifdef VK_USE_PLATFORM_ANDROID_KHR + const VkExternalFormatANDROID* extFormatAndroidPtr = + vk_find_struct<VkExternalFormatANDROID>(pCreateInfo); if (extFormatAndroidPtr) { - pCreateInfo_mut->format = - vk_format_from_android(extFormatAndroidPtr->externalFormat); + if (extFormatAndroidPtr->externalFormat) { + localCreateInfo.format = + vk_format_from_android(extFormatAndroidPtr->externalFormat); + } } #endif VkEncoder* enc = (VkEncoder*)context; return enc->vkCreateSamplerYcbcrConversionKHR( - device, pCreateInfo, pAllocator, pYcbcrConversion); + device, &localCreateInfo, pAllocator, pYcbcrConversion); } void on_vkDestroyImage( @@ -2354,41 +2329,6 @@ public: void* context, VkResult, VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) { -#ifdef VK_USE_PLATFORM_FUCHSIA - auto imageIt = info_VkImage.find(image); - if (imageIt == info_VkImage.end()) { - return VK_ERROR_INITIALIZATION_FAILED; - } - auto& imageInfo = imageIt->second; - - if (imageInfo.cbHandle) { - auto memoryIt = info_VkDeviceMemory.find(memory); - if (memoryIt == info_VkDeviceMemory.end()) { - return VK_ERROR_INITIALIZATION_FAILED; - } - auto& memoryInfo = memoryIt->second; - - zx_status_t status; - if (memoryInfo.vmoHandle == ZX_HANDLE_INVALID) { - status = zx_vmo_create(memoryInfo.allocationSize, 0, - &memoryInfo.vmoHandle); - if (status != ZX_OK) { - ALOGE("%s: failed to alloc vmo", __func__); - abort(); - } - } - status = zx_object_set_cookie(memoryInfo.vmoHandle, - memoryInfo.vmoHandle, - imageInfo.cbHandle); - if (status != ZX_OK) { - ALOGE("%s: failed to set color buffer cookie", __func__); - abort(); - } - // Color buffer backed images are already bound. - return VK_SUCCESS; - } -#endif - VkEncoder* enc = (VkEncoder*)context; return enc->vkBindImageMemory(device, image, memory, memoryOffset); } @@ -2428,9 +2368,8 @@ public: info.createInfo = *pCreateInfo; info.createInfo.pNext = nullptr; - VkExternalMemoryBufferCreateInfo* extBufCi = - (VkExternalMemoryBufferCreateInfo*)vk_find_struct((vk_struct_common*)pCreateInfo, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO); + const VkExternalMemoryBufferCreateInfo* extBufCi = + vk_find_struct<VkExternalMemoryBufferCreateInfo>(pCreateInfo); if (!extBufCi) return res; @@ -2520,10 +2459,8 @@ public: VkSemaphoreCreateInfo finalCreateInfo = *pCreateInfo; - VkExportSemaphoreCreateInfoKHR* exportSemaphoreInfoPtr = - (VkExportSemaphoreCreateInfoKHR*)vk_find_struct( - (vk_struct_common*)pCreateInfo, - VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR); + const VkExportSemaphoreCreateInfoKHR* exportSemaphoreInfoPtr = + vk_find_struct<VkExportSemaphoreCreateInfoKHR>(pCreateInfo); #ifdef VK_USE_PLATFORM_FUCHSIA bool exportEvent = exportSemaphoreInfoPtr && @@ -3092,9 +3029,7 @@ public: (void)input_result; VkAndroidHardwareBufferUsageANDROID* output_ahw_usage = - (VkAndroidHardwareBufferUsageANDROID*)vk_find_struct( - (vk_struct_common*)pImageFormatProperties, - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID); + vk_find_struct<VkAndroidHardwareBufferUsageANDROID>(pImageFormatProperties); VkResult hostRes; @@ -3187,6 +3122,32 @@ public: return VK_SUCCESS; } + VkResult on_vkCreateImageView( + void* context, VkResult input_result, + VkDevice device, + const VkImageViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImageView* pView) { + + VkEncoder* enc = (VkEncoder*)context; + (void)input_result; + + VkImageViewCreateInfo localCreateInfo = vk_make_orphan_copy(*pCreateInfo); + +#ifdef VK_USE_PLATFORM_ANDROID_KHR + const VkExternalFormatANDROID* extFormatAndroidPtr = + vk_find_struct<VkExternalFormatANDROID>(pCreateInfo); + if (extFormatAndroidPtr) { + if (extFormatAndroidPtr->externalFormat) { + localCreateInfo.format = + vk_format_from_android(extFormatAndroidPtr->externalFormat); + } + } +#endif + + return enc->vkCreateImageView(device, &localCreateInfo, pAllocator, pView); + } + uint32_t getApiVersionFromInstance(VkInstance instance) const { AutoLock lock(mLock); uint32_t api = kMinApiVersion; @@ -3237,9 +3198,6 @@ private: HostVisibleMemoryVirtualizationInfo mHostVisibleMemoryVirtInfo; std::unique_ptr<EmulatorFeatureInfo> mFeatureInfo; std::unique_ptr<GoldfishAddressSpaceBlockProvider> mGoldfishAddressSpaceBlockProvider; - PFN_CreateColorBuffer mCreateColorBuffer; - PFN_OpenColorBuffer mOpenColorBuffer; - PFN_CloseColorBuffer mCloseColorBuffer; std::vector<VkExtensionProperties> mHostInstanceExtensions; std::vector<VkExtensionProperties> mHostDeviceExtensions; @@ -3247,6 +3205,7 @@ private: int mSyncDeviceFd = -1; #ifdef VK_USE_PLATFORM_FUCHSIA + zx_handle_t mControlDevice = ZX_HANDLE_INVALID; fuchsia::sysmem::AllocatorSyncPtr mSysmemAllocator; #endif }; @@ -3332,13 +3291,6 @@ bool ResourceTracker::hasDeviceExtension(VkDevice device, const std::string &nam return mImpl->hasDeviceExtension(device, name); } -void ResourceTracker::setColorBufferFunctions( - PFN_CreateColorBuffer create, - PFN_OpenColorBuffer open, - PFN_CloseColorBuffer close) { - mImpl->setColorBufferFunctions(create, open, close); -} - VkResult ResourceTracker::on_vkEnumerateInstanceExtensionProperties( void* context, VkResult input_result, @@ -3692,6 +3644,15 @@ VkResult ResourceTracker::on_vkSetBufferCollectionConstraintsFUCHSIA( return mImpl->on_vkSetBufferCollectionConstraintsFUCHSIA( context, input_result, device, collection, pImageInfo); } + +VkResult ResourceTracker::on_vkGetBufferCollectionPropertiesFUCHSIA( + void* context, VkResult input_result, + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties) { + return mImpl->on_vkGetBufferCollectionPropertiesFUCHSIA( + context, input_result, device, collection, pProperties); +} #endif VkResult ResourceTracker::on_vkGetAndroidHardwareBufferPropertiesANDROID( @@ -3828,6 +3789,16 @@ VkResult ResourceTracker::on_vkResetCommandBuffer( context, input_result, commandBuffer, flags); } +VkResult ResourceTracker::on_vkCreateImageView( + void* context, VkResult input_result, + VkDevice device, + const VkImageViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImageView* pView) { + return mImpl->on_vkCreateImageView( + context, input_result, device, pCreateInfo, pAllocator, pView); +} + void ResourceTracker::deviceMemoryTransform_tohost( VkDeviceMemory* memory, uint32_t memoryCount, VkDeviceSize* offset, uint32_t offsetCount, diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h index 200bfb6870dcb756d280eff4dfd080173ff822c8..6429d6f4be713e016c22df07eb3b16d339ab0836 100644 --- a/system/vulkan_enc/ResourceTracker.h +++ b/system/vulkan_enc/ResourceTracker.h @@ -28,10 +28,6 @@ struct EmulatorFeatureInfo; namespace goldfish_vk { -typedef uint32_t (*PFN_CreateColorBuffer)(uint32_t width, uint32_t height, uint32_t format); -typedef void (*PFN_OpenColorBuffer)(uint32_t id); -typedef void (*PFN_CloseColorBuffer)(uint32_t id); - class ResourceTracker { public: ResourceTracker(); @@ -249,6 +245,11 @@ public: VkDevice device, VkBufferCollectionFUCHSIA collection, const VkImageCreateInfo* pImageInfo); + VkResult on_vkGetBufferCollectionPropertiesFUCHSIA( + void* context, VkResult input_result, + VkDevice device, + VkBufferCollectionFUCHSIA collection, + VkBufferCollectionPropertiesFUCHSIA* pProperties); #endif VkResult on_vkGetAndroidHardwareBufferPropertiesANDROID( @@ -333,6 +334,13 @@ public: VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); + VkResult on_vkCreateImageView( + void* context, VkResult input_result, + VkDevice device, + const VkImageViewCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImageView* pView); + bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const; uint8_t* getMappedPointer(VkDeviceMemory memory); VkDeviceSize getMappedSize(VkDeviceMemory memory); @@ -345,9 +353,6 @@ public: uint32_t getApiVersionFromDevice(VkDevice device) const; bool hasInstanceExtension(VkInstance instance, const std::string& name) const; bool hasDeviceExtension(VkDevice instance, const std::string& name) const; - void setColorBufferFunctions(PFN_CreateColorBuffer create, - PFN_OpenColorBuffer open, - PFN_CloseColorBuffer close); // Transforms void deviceMemoryTransform_tohost( diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp index b97f120e8650c9c3f4a5231c4b3a5654d5ed84bf..42487ea1b686672b86fdb0023b40e4cb9d02db0a 100644 --- a/system/vulkan_enc/VkEncoder.cpp +++ b/system/vulkan_enc/VkEncoder.cpp @@ -7137,7 +7137,7 @@ void VkEncoder::vkCmdSetDepthBias( void VkEncoder::vkCmdSetBlendConstants( VkCommandBuffer commandBuffer, - const float blendConstants) + const float blendConstants[4]) { AEMU_SCOPED_TRACE("vkCmdSetBlendConstants encode"); mImpl->log("start vkCmdSetBlendConstants"); diff --git a/system/vulkan_enc/VkEncoder.h b/system/vulkan_enc/VkEncoder.h index 16df497f6f881c0a8e609e93f6770cbb1be6b5e7..8328b321edb5f431bf3e411d8c50134318cf58ca 100644 --- a/system/vulkan_enc/VkEncoder.h +++ b/system/vulkan_enc/VkEncoder.h @@ -473,7 +473,7 @@ public: float depthBiasSlopeFactor); void vkCmdSetBlendConstants( VkCommandBuffer commandBuffer, - const float blendConstants); + const float blendConstants[4]); void vkCmdSetDepthBounds( VkCommandBuffer commandBuffer, float minDepthBounds, diff --git a/system/vulkan_enc/goldfish_vk_private_defs.h b/system/vulkan_enc/goldfish_vk_private_defs.h index 3eed2442ed3805998e3dc53e7c1f42bfce6a99bd..15d30e141cd6f187ad28fd793a61f1acc4c169a7 100644 --- a/system/vulkan_enc/goldfish_vk_private_defs.h +++ b/system/vulkan_enc/goldfish_vk_private_defs.h @@ -425,6 +425,53 @@ typedef void (VKAPI_PTR *PFN_vkResetCommandBufferAsyncGOOGLE)( VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags); +#ifdef VK_USE_PLATFORM_FUCHSIA +#define VK_FUCHSIA_buffer_collection 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA) + +#define VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION 1 +#define VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME "VK_FUCHSIA_buffer_collection" + +typedef struct VkBufferCollectionImageCreateInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkBufferCollectionImageCreateInfoFUCHSIA; + +#define VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA \ + ((VkStructureType)1001004005) +#endif // VK_USE_PLATFORM_FUCHSIA + +#ifdef VK_USE_PLATFORM_ANDROID_KHR + +typedef struct VkImportMemoryZirconHandleInfoFUCHSIA { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + uint32_t handle; +} VkImportMemoryZirconHandleInfoFUCHSIA; + +typedef uint32_t VkBufferCollectionFUCHSIA; + +typedef struct VkImportMemoryBufferCollectionFUCHSIA { + VkStructureType sType; + const void* pNext; + VkBufferCollectionFUCHSIA collection; + uint32_t index; +} VkImportMemoryBufferCollectionFUCHSIA; + +#define VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA \ + ((VkStructureType)1001000000) +#define VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA \ + ((VkStructureType)1001000000) +#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA \ + ((VkStructureType)0x00000800) +#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA \ + ((VkStructureType)0x00000020) + +#endif // VK_USE_PLATFORM_ANDROID_KHR + #ifdef __cplusplus } // extern "C" #endif diff --git a/system/vulkan_enc/vk_format_info.h b/system/vulkan_enc/vk_format_info.h index 3bac828aab8089d82e9bd112d96a5f0225921991..c70f45ff72a5651d3811433eafdb235ab836f345 100644 --- a/system/vulkan_enc/vk_format_info.h +++ b/system/vulkan_enc/vk_format_info.h @@ -58,7 +58,7 @@ vk_format_from_android(unsigned android_format) } static inline unsigned -android_format_from_vk(unsigned vk_format) +android_format_from_vk(VkFormat vk_format) { switch (vk_format) { case VK_FORMAT_R8G8B8A8_UNORM: @@ -78,6 +78,18 @@ android_format_from_vk(unsigned vk_format) } } +static inline bool +android_format_is_yuv(unsigned android_format) +{ + switch (android_format) { + case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL: + return true; + + default: + return false; + } +} + static inline VkImageAspectFlags vk_format_aspects(VkFormat format) { diff --git a/system/vulkan_enc/vk_struct_id.h b/system/vulkan_enc/vk_struct_id.h new file mode 100644 index 0000000000000000000000000000000000000000..893389c7e064ed616081237a970b5d8d61124c33 --- /dev/null +++ b/system/vulkan_enc/vk_struct_id.h @@ -0,0 +1,57 @@ +// Copyright (C) 2018 The Android Open Source Project +// Copyright (C) 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include <vulkan/vulkan.h> +#include "goldfish_vk_private_defs.h" + +template <class T> struct vk_get_vk_struct_id; + +#define REGISTER_VK_STRUCT_ID(T, ID) \ + template <> struct vk_get_vk_struct_id<T> { static constexpr VkStructureType id = ID; }; + +REGISTER_VK_STRUCT_ID(VkAndroidHardwareBufferPropertiesANDROID, VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID); +REGISTER_VK_STRUCT_ID(VkAndroidHardwareBufferFormatPropertiesANDROID, VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID); +REGISTER_VK_STRUCT_ID(VkAndroidHardwareBufferUsageANDROID, VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID); +REGISTER_VK_STRUCT_ID(VkBufferCreateInfo, VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO); +REGISTER_VK_STRUCT_ID(VkImageCreateInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO); +REGISTER_VK_STRUCT_ID(VkImageFormatProperties2, VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2); +REGISTER_VK_STRUCT_ID(VkNativeBufferANDROID, VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID); +REGISTER_VK_STRUCT_ID(VkExternalFormatANDROID, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID); +REGISTER_VK_STRUCT_ID(VkExternalMemoryBufferCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO); +REGISTER_VK_STRUCT_ID(VkExternalMemoryImageCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); +REGISTER_VK_STRUCT_ID(VkMemoryAllocateInfo, VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); +REGISTER_VK_STRUCT_ID(VkMemoryDedicatedAllocateInfo, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); +REGISTER_VK_STRUCT_ID(VkMemoryDedicatedRequirements, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS); +REGISTER_VK_STRUCT_ID(VkImportAndroidHardwareBufferInfoANDROID, VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID); +REGISTER_VK_STRUCT_ID(VkExportMemoryAllocateInfo, VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO); +REGISTER_VK_STRUCT_ID(VkMemoryRequirements2, VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2); +REGISTER_VK_STRUCT_ID(VkSemaphoreCreateInfo, VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO); +REGISTER_VK_STRUCT_ID(VkExportSemaphoreCreateInfoKHR, VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR); +REGISTER_VK_STRUCT_ID(VkSamplerYcbcrConversionCreateInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO); +REGISTER_VK_STRUCT_ID(VkImportColorBufferGOOGLE, VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE); +REGISTER_VK_STRUCT_ID(VkImageViewCreateInfo, VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO); + +#ifdef VK_USE_PLATFORM_ANDROID_KHR +// These two should be under Android +REGISTER_VK_STRUCT_ID(VkImportMemoryBufferCollectionFUCHSIA, VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA); +REGISTER_VK_STRUCT_ID(VkImportMemoryZirconHandleInfoFUCHSIA, VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA); +#endif // VK_USE_PLATFORM_ANDROID_KHR + +#ifdef VK_USE_PLATFORM_FUCHSIA +REGISTER_VK_STRUCT_ID(VkBufferCollectionImageCreateInfoFUCHSIA, VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA); +#endif // VK_USE_PLATFORM_FUCHSIA + +#undef REGISTER_VK_STRUCT_ID diff --git a/system/vulkan_enc/vk_util.h b/system/vulkan_enc/vk_util.h index 0c7f4b9823c13dcd645d74da6557608a7fe4ea36..39de99189d6fd696f230a44c0a9e881efb2da872 100644 --- a/system/vulkan_enc/vk_util.h +++ b/system/vulkan_enc/vk_util.h @@ -26,12 +26,18 @@ /* common inlines and macros for vulkan drivers */ #include <vulkan/vulkan.h> +#include <stdlib.h> +#include "vk_struct_id.h" struct vk_struct_common { VkStructureType sType; struct vk_struct_common *pNext; }; +struct vk_struct_chain_iterator { + vk_struct_common* value; +}; + #define vk_foreach_struct(__iter, __start) \ for (struct vk_struct_common *__iter = (struct vk_struct_common *)(__start); \ __iter; __iter = __iter->pNext) @@ -191,11 +197,18 @@ __vk_find_struct(void *start, VkStructureType sType) return NULL; } -#define vk_find_struct(__start, __sType) \ - __vk_find_struct((__start), __sType) +template <class T, class H> T* vk_find_struct(H* head) +{ + vk_get_vk_struct_id<H>::id; + return static_cast<T*>(__vk_find_struct(static_cast<void*>(head), vk_get_vk_struct_id<T>::id)); +} -#define vk_find_struct_const(__start, __sType) \ - (const void *)__vk_find_struct((void *)(__start), __sType) +template <class T, class H> const T* vk_find_struct(const H* head) +{ + vk_get_vk_struct_id<H>::id; + return static_cast<const T*>(__vk_find_struct(const_cast<void*>(static_cast<const void*>(head)), + vk_get_vk_struct_id<T>::id)); +} uint32_t vk_get_driver_version(void); @@ -207,19 +220,32 @@ uint32_t vk_get_version_override(void); #define VK_ENUM_OFFSET(__enum) \ ((__enum) >= VK_EXT_OFFSET ? ((__enum) % 1000) : (__enum)) -static inline vk_struct_common* -vk_init_struct_chain(vk_struct_common* start) +template <class T> T vk_make_orphan_copy(const T& vk_struct) { + T copy = vk_struct; + copy.pNext = NULL; + return copy; +} + +template <class T> vk_struct_chain_iterator vk_make_chain_iterator(T* vk_struct) { - start->pNext = nullptr; - return start; + vk_get_vk_struct_id<T>::id; + vk_struct_chain_iterator result = { reinterpret_cast<vk_struct_common*>(vk_struct) }; + return result; } -static inline vk_struct_common* -vk_append_struct(vk_struct_common* current, vk_struct_common* next) +template <class T> void vk_append_struct(vk_struct_chain_iterator* i, T* vk_struct) { - current->pNext = next; - next->pNext = nullptr; - return next; + vk_get_vk_struct_id<T>::id; + + vk_struct_common* p = i->value; + if (p->pNext) { + ::abort(); + } + + p->pNext = reinterpret_cast<vk_struct_common *>(vk_struct); + vk_struct->pNext = NULL; + + *i = vk_make_chain_iterator(vk_struct); } #endif /* VK_UTIL_H */