Rename imported system directory to guest
Reviewed-by: Aaron Ruby <aruby@blackberry.com> Acked-by: Yonggang Luo <luoyonggang@gmail.com> Acked-by: Adam Jackson <ajax@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27246>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# Copyright 2022 Android Open Source Project
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
vk_api_xml = files('vk.xml')
|
||||
vk_icd_gen = files('vk_icd_gen.py')
|
||||
|
||||
files_lib_vulkan_cereal = files(
|
||||
'goldfish_vulkan.cpp',
|
||||
)
|
||||
|
||||
lib_vulkan_cereal = shared_library(
|
||||
'vulkan_cereal',
|
||||
files_lib_vulkan_cereal,
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [inc_android_emu, inc_android_compat, inc_opengl_system,
|
||||
inc_host, inc_opengl_codec, inc_render_enc,
|
||||
inc_vulkan_enc],
|
||||
link_with: [lib_android_compat, lib_emu_android_base, lib_stream,
|
||||
lib_vulkan_enc],
|
||||
install: true,
|
||||
)
|
||||
|
||||
cereal_icd = custom_target(
|
||||
'cereal_icd',
|
||||
input : [vk_icd_gen, vk_api_xml],
|
||||
output : 'cereal_icd.@0@.json'.format(host_machine.cpu()),
|
||||
command : [
|
||||
prog_python, '@INPUT0@',
|
||||
'--api-version', '1.0', '--xml', '@INPUT1@',
|
||||
'--lib-path', join_paths(get_option('prefix'), get_option('libdir'),
|
||||
'libvulkan_cereal.so'),
|
||||
'--out', '@OUTPUT@',
|
||||
],
|
||||
build_by_default : true,
|
||||
install_dir : with_vulkan_icd_dir,
|
||||
install : true,
|
||||
)
|
||||
@@ -0,0 +1,348 @@
|
||||
/// Copyright (C) 2019 The Android Open Source Project
|
||||
// Copyright (C) 2019 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.
|
||||
#include "AndroidHardwareBuffer.h"
|
||||
|
||||
#if !defined(HOST_BUILD)
|
||||
#if defined(__ANDROID__) || defined(__linux__)
|
||||
#include <drm_fourcc.h>
|
||||
#define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7')
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../OpenglSystemCommon/HostConnection.h"
|
||||
|
||||
#include "vk_format_info.h"
|
||||
#include "vk_util.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
// From Intel ANV implementation.
|
||||
/* Construct ahw usage mask from image usage bits, see
|
||||
* 'AHardwareBuffer Usage Equivalence' in Vulkan spec.
|
||||
*/
|
||||
uint64_t
|
||||
getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,
|
||||
const VkImageUsageFlags vk_usage)
|
||||
{
|
||||
uint64_t ahw_usage = 0;
|
||||
|
||||
if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
|
||||
|
||||
if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
|
||||
ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
|
||||
|
||||
if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
|
||||
ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
|
||||
|
||||
if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
|
||||
ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
|
||||
|
||||
if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT)
|
||||
ahw_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
|
||||
|
||||
/* No usage bits set - set at least one GPU usage. */
|
||||
if (ahw_usage == 0)
|
||||
ahw_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
|
||||
|
||||
return ahw_usage;
|
||||
}
|
||||
|
||||
void updateMemoryTypeBits(uint32_t* memoryTypeBits, uint32_t colorBufferMemoryIndex) {
|
||||
*memoryTypeBits = 1u << colorBufferMemoryIndex;
|
||||
}
|
||||
|
||||
VkResult getAndroidHardwareBufferPropertiesANDROID(
|
||||
Gralloc* grallocHelper,
|
||||
const AHardwareBuffer* buffer,
|
||||
VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
|
||||
|
||||
const native_handle_t *handle =
|
||||
AHardwareBuffer_getNativeHandle(buffer);
|
||||
|
||||
VkAndroidHardwareBufferFormatPropertiesANDROID* ahbFormatProps =
|
||||
vk_find_struct<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties);
|
||||
|
||||
if (ahbFormatProps) {
|
||||
AHardwareBuffer_Desc desc;
|
||||
AHardwareBuffer_describe(buffer, &desc);
|
||||
|
||||
const uint64_t gpu_usage =
|
||||
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
|
||||
AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
|
||||
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
|
||||
|
||||
if (!(desc.usage & (gpu_usage))) {
|
||||
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
||||
}
|
||||
switch(desc.format) {
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
|
||||
ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
|
||||
ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
|
||||
ahbFormatProps->format = VK_FORMAT_R8G8B8_UNORM;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
|
||||
ahbFormatProps->format = VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
|
||||
ahbFormatProps->format = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
|
||||
ahbFormatProps->format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D16_UNORM:
|
||||
ahbFormatProps->format = VK_FORMAT_D16_UNORM;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D24_UNORM:
|
||||
ahbFormatProps->format = VK_FORMAT_X8_D24_UNORM_PACK32;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
|
||||
ahbFormatProps->format = VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
|
||||
ahbFormatProps->format = VK_FORMAT_D32_SFLOAT;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
|
||||
ahbFormatProps->format = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
break;
|
||||
case AHARDWAREBUFFER_FORMAT_S8_UINT:
|
||||
ahbFormatProps->format = VK_FORMAT_S8_UINT;
|
||||
break;
|
||||
default:
|
||||
ahbFormatProps->format = VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
ahbFormatProps->externalFormat = desc.format;
|
||||
|
||||
// The formatFeatures member must include
|
||||
// VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
|
||||
// VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
|
||||
// VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, and should include
|
||||
// VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT and
|
||||
// VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.
|
||||
|
||||
// org.skia.skqp.SkQPRunner#UnitTest_VulkanHardwareBuffer* requires the following:
|
||||
// VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
||||
// VK_FORMAT_FEATURE_TRANSFER_DST_BIT
|
||||
// VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
|
||||
ahbFormatProps->formatFeatures =
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
|
||||
VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT |
|
||||
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
|
||||
VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
|
||||
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
// "Implementations may not always be able to determine the color model,
|
||||
// numerical range, or chroma offsets of the image contents, so the values in
|
||||
// VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
|
||||
// Applications should treat these values as sensible defaults to use in the
|
||||
// absence of more reliable information obtained through some other means."
|
||||
|
||||
ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
ahbFormatProps->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
ahbFormatProps->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
|
||||
#if !defined(HOST_BUILD)
|
||||
#if defined(__ANDROID__) || defined(__linux__)
|
||||
if (android_format_is_yuv(desc.format)) {
|
||||
uint32_t drmFormat = grallocHelper->getFormatDrmFourcc(handle);
|
||||
if (drmFormat) {
|
||||
// The host renderer is not aware of the plane ordering for YUV formats used
|
||||
// in the guest and simply knows that the format "layout" is one of:
|
||||
//
|
||||
// * VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
|
||||
// * VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
|
||||
// * VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
|
||||
//
|
||||
// With this, the guest needs to adjust the component swizzle based on plane
|
||||
// ordering to ensure that the channels are interpreted correctly.
|
||||
//
|
||||
// From the Vulkan spec's "Sampler Y'CBCR Conversion" section:
|
||||
//
|
||||
// * Y comes from the G-channel (after swizzle)
|
||||
// * U (CB) comes from the B-channel (after swizzle)
|
||||
// * V (CR) comes from the R-channel (after swizzle)
|
||||
//
|
||||
// See https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#textures-sampler-YCbCr-conversion
|
||||
//
|
||||
// To match the above, the guest needs to swizzle such that:
|
||||
//
|
||||
// * Y ends up in the G-channel
|
||||
// * U (CB) ends up in the B-channel
|
||||
// * V (CB) ends up in the R-channel
|
||||
switch (drmFormat) {
|
||||
case DRM_FORMAT_NV12:
|
||||
// NV12 is a Y-plane followed by a interleaved UV-plane and is
|
||||
// VK_FORMAT_G8_B8R8_2PLANE_420_UNORM on the host.
|
||||
case DRM_FORMAT_P010:
|
||||
// P010 is a Y-plane followed by a interleaved UV-plane and is
|
||||
// VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 on the host.
|
||||
break;
|
||||
|
||||
case DRM_FORMAT_NV21:
|
||||
// NV21 is a Y-plane followed by a interleaved VU-plane and is
|
||||
// VK_FORMAT_G8_B8R8_2PLANE_420_UNORM on the host.
|
||||
case DRM_FORMAT_YVU420:
|
||||
// YV12 is a Y-plane, then a V-plane, and then a U-plane and is
|
||||
// VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM on the host.
|
||||
case DRM_FORMAT_YVU420_ANDROID:
|
||||
// DRM_FORMAT_YVU420_ANDROID is the same as DRM_FORMAT_YVU420 with
|
||||
// Android's extra alignement requirements.
|
||||
ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_B;
|
||||
ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_R;
|
||||
break;
|
||||
|
||||
default:
|
||||
ALOGE("%s: Unhandled YUV drm format:%" PRIu32, __FUNCTION__, drmFormat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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;
|
||||
ahbFormatProps->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
|
||||
}
|
||||
|
||||
uint32_t colorBufferHandle =
|
||||
grallocHelper->getHostHandle(handle);
|
||||
if (!colorBufferHandle) {
|
||||
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
||||
}
|
||||
|
||||
pProperties->allocationSize =
|
||||
grallocHelper->getAllocatedSize(handle);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
// Based on Intel ANV implementation.
|
||||
VkResult getMemoryAndroidHardwareBufferANDROID(struct AHardwareBuffer **pBuffer) {
|
||||
|
||||
/* Some quotes from Vulkan spec:
|
||||
*
|
||||
* "If the device memory was created by importing an Android hardware
|
||||
* buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
|
||||
* Android hardware buffer object."
|
||||
*
|
||||
* "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
|
||||
* have been included in VkExportMemoryAllocateInfo::handleTypes when
|
||||
* memory was created."
|
||||
*/
|
||||
|
||||
if (!pBuffer) return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
if (!(*pBuffer)) return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
|
||||
AHardwareBuffer_acquire(*pBuffer);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult importAndroidHardwareBuffer(
|
||||
Gralloc* grallocHelper,
|
||||
const VkImportAndroidHardwareBufferInfoANDROID* info,
|
||||
struct AHardwareBuffer **importOut) {
|
||||
|
||||
if (!info || !info->buffer) {
|
||||
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
||||
}
|
||||
|
||||
uint32_t colorBufferHandle =
|
||||
grallocHelper->getHostHandle(
|
||||
AHardwareBuffer_getNativeHandle(info->buffer));
|
||||
if (!colorBufferHandle) {
|
||||
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
||||
}
|
||||
|
||||
auto ahb = info->buffer;
|
||||
|
||||
AHardwareBuffer_acquire(ahb);
|
||||
|
||||
if (importOut) *importOut = ahb;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult createAndroidHardwareBuffer(
|
||||
bool hasDedicatedImage,
|
||||
bool hasDedicatedBuffer,
|
||||
const VkExtent3D& imageExtent,
|
||||
uint32_t imageLayers,
|
||||
VkFormat imageFormat,
|
||||
VkImageUsageFlags imageUsage,
|
||||
VkImageCreateFlags imageCreateFlags,
|
||||
VkDeviceSize bufferSize,
|
||||
VkDeviceSize allocationInfoAllocSize,
|
||||
struct AHardwareBuffer **out) {
|
||||
|
||||
uint32_t w = 0;
|
||||
uint32_t h = 1;
|
||||
uint32_t layers = 1;
|
||||
uint32_t format = 0;
|
||||
uint64_t usage = 0;
|
||||
|
||||
/* If caller passed dedicated information. */
|
||||
if (hasDedicatedImage) {
|
||||
w = imageExtent.width;
|
||||
h = imageExtent.height;
|
||||
layers = imageLayers;
|
||||
format = android_format_from_vk(imageFormat);
|
||||
usage = getAndroidHardwareBufferUsageFromVkUsage(imageCreateFlags, imageUsage);
|
||||
} else if (hasDedicatedBuffer) {
|
||||
w = bufferSize;
|
||||
format = AHARDWAREBUFFER_FORMAT_BLOB;
|
||||
usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
|
||||
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
|
||||
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
|
||||
} else {
|
||||
w = allocationInfoAllocSize;
|
||||
format = AHARDWAREBUFFER_FORMAT_BLOB;
|
||||
usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
|
||||
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
|
||||
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
|
||||
}
|
||||
|
||||
struct AHardwareBuffer *ahw = NULL;
|
||||
struct AHardwareBuffer_Desc desc = {
|
||||
.width = w,
|
||||
.height = h,
|
||||
.layers = layers,
|
||||
.format = format,
|
||||
.usage = usage,
|
||||
};
|
||||
|
||||
if (AHardwareBuffer_allocate(&desc, &ahw) != 0) {
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
*out = ahw;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,63 @@
|
||||
/// Copyright (C) 2019 The Android Open Source Project
|
||||
// Copyright (C) 2019 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 "HostVisibleMemoryVirtualization.h"
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vndk/hardware_buffer.h>
|
||||
|
||||
// Structure similar to
|
||||
// https://github.com/mesa3d/mesa/blob/master/src/intel/vulkan/anv_android.c
|
||||
|
||||
class Gralloc;
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
uint64_t
|
||||
getAndroidHardwareBufferUsageFromVkUsage(
|
||||
const VkImageCreateFlags vk_create,
|
||||
const VkImageUsageFlags vk_usage);
|
||||
|
||||
void updateMemoryTypeBits(uint32_t* memoryTypeBits, uint32_t colorBufferMemoryIndex);
|
||||
|
||||
VkResult getAndroidHardwareBufferPropertiesANDROID(
|
||||
Gralloc* grallocHelper,
|
||||
const AHardwareBuffer* buffer,
|
||||
VkAndroidHardwareBufferPropertiesANDROID* pProperties);
|
||||
|
||||
VkResult getMemoryAndroidHardwareBufferANDROID(
|
||||
struct AHardwareBuffer **pBuffer);
|
||||
|
||||
VkResult importAndroidHardwareBuffer(
|
||||
Gralloc* grallocHelper,
|
||||
const VkImportAndroidHardwareBufferInfoANDROID* info,
|
||||
struct AHardwareBuffer **importOut);
|
||||
|
||||
VkResult createAndroidHardwareBuffer(
|
||||
bool hasDedicatedImage,
|
||||
bool hasDedicatedBuffer,
|
||||
const VkExtent3D& imageExtent,
|
||||
uint32_t imageLayers,
|
||||
VkFormat imageFormat,
|
||||
VkImageUsageFlags imageUsage,
|
||||
VkImageCreateFlags imageCreateFlags,
|
||||
VkDeviceSize bufferSize,
|
||||
VkDeviceSize allocationInfoAllocSize,
|
||||
struct AHardwareBuffer **out);
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 "CommandBufferStagingStream.h"
|
||||
|
||||
#if PLATFORM_SDK_VERSION < 26
|
||||
#include <cutils/log.h>
|
||||
#else
|
||||
#include <log/log.h>
|
||||
#endif
|
||||
#include <cutils/properties.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
static const size_t kReadSize = 512 * 1024;
|
||||
static const size_t kWriteOffset = kReadSize;
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
CommandBufferStagingStream::CommandBufferStagingStream()
|
||||
: IOStream(1048576), m_size(0), m_writePos(0) {
|
||||
// use default allocators
|
||||
m_alloc = [](size_t size) -> Memory {
|
||||
return {
|
||||
.deviceMemory = VK_NULL_HANDLE, // no device memory for malloc
|
||||
.ptr = malloc(size),
|
||||
};
|
||||
};
|
||||
m_free = [](const Memory& mem) { free(mem.ptr); };
|
||||
m_realloc = [](const Memory& mem, size_t size) -> Memory {
|
||||
return {.deviceMemory = VK_NULL_HANDLE, .ptr = realloc(mem.ptr, size)};
|
||||
};
|
||||
}
|
||||
|
||||
CommandBufferStagingStream::CommandBufferStagingStream(const Alloc& allocFn, const Free& freeFn)
|
||||
: CommandBufferStagingStream() {
|
||||
m_usingCustomAlloc = true;
|
||||
// for custom allocation, allocate metadata memory at the beginning.
|
||||
// m_alloc, m_free and m_realloc wraps sync data logic
|
||||
|
||||
// \param size to allocate
|
||||
// \return ptr starting at data
|
||||
m_alloc = [&allocFn](size_t size) -> Memory {
|
||||
// allocation requested size + sync data size
|
||||
|
||||
// <---sync bytes--><----Data--->
|
||||
// |———————————————|————————————|
|
||||
// |0|1|2|3|4|5|6|7|............|
|
||||
// |———————————————|————————————|
|
||||
// ꜛ ꜛ
|
||||
// allocated ptr ptr to data [dataPtr]
|
||||
|
||||
Memory memory;
|
||||
if (!allocFn) {
|
||||
ALOGE("Custom allocation (%zu bytes) failed\n", size);
|
||||
return memory;
|
||||
}
|
||||
|
||||
// custom allocation/free requires metadata for sync between host/guest
|
||||
const size_t totalSize = size + kSyncDataSize;
|
||||
memory = allocFn(totalSize);
|
||||
if (!memory.ptr) {
|
||||
ALOGE("Custom allocation (%zu bytes) failed\n", size);
|
||||
return memory;
|
||||
}
|
||||
|
||||
// set sync data to read complete
|
||||
uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(memory.ptr);
|
||||
__atomic_store_n(syncDWordPtr, kSyncDataReadComplete, __ATOMIC_RELEASE);
|
||||
return memory;
|
||||
};
|
||||
|
||||
m_free = [&freeFn](const Memory& mem) {
|
||||
if (!freeFn) {
|
||||
ALOGE("Custom free for memory(%p) failed\n", mem.ptr);
|
||||
return;
|
||||
}
|
||||
freeFn(mem);
|
||||
};
|
||||
|
||||
// \param ptr is the data pointer currently allocated
|
||||
// \return dataPtr starting at data
|
||||
m_realloc = [this](const Memory& mem, size_t size) -> Memory {
|
||||
// realloc requires freeing previously allocated memory
|
||||
// read sync DWORD to ensure host is done reading this memory
|
||||
// before releasing it.
|
||||
|
||||
size_t hostWaits = 0;
|
||||
|
||||
uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(mem.ptr);
|
||||
while (__atomic_load_n(syncDWordPtr, __ATOMIC_ACQUIRE) != kSyncDataReadComplete) {
|
||||
hostWaits++;
|
||||
usleep(10);
|
||||
if (hostWaits > 1000) {
|
||||
ALOGD("%s: warning, stalled on host decoding on this command buffer stream\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
||||
// for custom allocation/free, memory holding metadata must be copied
|
||||
// along with stream data
|
||||
// <---sync bytes--><----Data--->
|
||||
// |———————————————|————————————|
|
||||
// |0|1|2|3|4|5|6|7|............|
|
||||
// |———————————————|————————————|
|
||||
// ꜛ ꜛ
|
||||
// [copyLocation] ptr to data [ptr]
|
||||
|
||||
const size_t toCopySize = m_writePos + kSyncDataSize;
|
||||
unsigned char* copyLocation = static_cast<unsigned char*>(mem.ptr);
|
||||
std::vector<uint8_t> tmp(copyLocation, copyLocation + toCopySize);
|
||||
m_free(mem);
|
||||
|
||||
// get new buffer and copy previous stream data to it
|
||||
Memory newMemory = m_alloc(size);
|
||||
unsigned char* newBuf = static_cast<unsigned char*>(newMemory.ptr);
|
||||
if (!newBuf) {
|
||||
ALOGE("Custom allocation (%zu bytes) failed\n", size);
|
||||
return newMemory;
|
||||
}
|
||||
// copy previous data
|
||||
memcpy(newBuf, tmp.data(), toCopySize);
|
||||
|
||||
return newMemory;
|
||||
};
|
||||
}
|
||||
|
||||
CommandBufferStagingStream::~CommandBufferStagingStream() {
|
||||
flush();
|
||||
if (m_mem.ptr) m_free(m_mem);
|
||||
}
|
||||
|
||||
unsigned char* CommandBufferStagingStream::getDataPtr() {
|
||||
if (!m_mem.ptr) return nullptr;
|
||||
const size_t metadataSize = m_usingCustomAlloc ? kSyncDataSize : 0;
|
||||
return static_cast<unsigned char*>(m_mem.ptr) + metadataSize;
|
||||
}
|
||||
|
||||
void CommandBufferStagingStream::markFlushing() {
|
||||
if (!m_usingCustomAlloc) {
|
||||
return;
|
||||
}
|
||||
uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(m_mem.ptr);
|
||||
__atomic_store_n(syncDWordPtr, kSyncDataReadPending, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
size_t CommandBufferStagingStream::idealAllocSize(size_t len) {
|
||||
if (len > 1048576) return len;
|
||||
return 1048576;
|
||||
}
|
||||
|
||||
void* CommandBufferStagingStream::allocBuffer(size_t minSize) {
|
||||
size_t allocSize = (1048576 < minSize ? minSize : 1048576);
|
||||
// Initial case: blank
|
||||
if (!m_mem.ptr) {
|
||||
m_mem = m_alloc(allocSize);
|
||||
m_size = allocSize;
|
||||
return getDataPtr();
|
||||
}
|
||||
|
||||
// Calculate remaining
|
||||
size_t remaining = m_size - m_writePos;
|
||||
// check if there is at least minSize bytes left in buffer
|
||||
// if not, reallocate a buffer of big enough size
|
||||
if (remaining < minSize) {
|
||||
size_t newAllocSize = m_size * 2 + allocSize;
|
||||
m_mem = m_realloc(m_mem, newAllocSize);
|
||||
m_size = newAllocSize;
|
||||
|
||||
return (void*)(getDataPtr() + m_writePos);
|
||||
}
|
||||
|
||||
// for custom allocations, host should have finished reading
|
||||
// data from command buffer since command buffers are flushed
|
||||
// on queue submit.
|
||||
// allocBuffer should not be called on command buffers that are currently
|
||||
// being read by the host
|
||||
if (m_usingCustomAlloc) {
|
||||
uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(m_mem.ptr);
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
__atomic_load_n(syncDWordPtr, __ATOMIC_ACQUIRE) != kSyncDataReadComplete,
|
||||
"FATAL: allocBuffer() called but previous read not complete");
|
||||
}
|
||||
|
||||
return (void*)(getDataPtr() + m_writePos);
|
||||
}
|
||||
|
||||
int CommandBufferStagingStream::commitBuffer(size_t size)
|
||||
{
|
||||
m_writePos += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned char *CommandBufferStagingStream::readFully(void*, size_t) {
|
||||
// Not supported
|
||||
ALOGE("CommandBufferStagingStream::%s: Fatal: not supported\n", __func__);
|
||||
abort();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const unsigned char *CommandBufferStagingStream::read(void*, size_t*) {
|
||||
// Not supported
|
||||
ALOGE("CommandBufferStagingStream::%s: Fatal: not supported\n", __func__);
|
||||
abort();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int CommandBufferStagingStream::writeFully(const void*, size_t)
|
||||
{
|
||||
// Not supported
|
||||
ALOGE("CommandBufferStagingStream::%s: Fatal: not supported\n", __func__);
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned char *CommandBufferStagingStream::commitBufferAndReadFully(
|
||||
size_t, void *, size_t) {
|
||||
|
||||
// Not supported
|
||||
ALOGE("CommandBufferStagingStream::%s: Fatal: not supported\n", __func__);
|
||||
abort();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CommandBufferStagingStream::getWritten(unsigned char** bufOut, size_t* sizeOut) {
|
||||
*bufOut = getDataPtr();
|
||||
*sizeOut = m_writePos;
|
||||
}
|
||||
|
||||
void CommandBufferStagingStream::reset() {
|
||||
m_writePos = 0;
|
||||
IOStream::rewind();
|
||||
}
|
||||
|
||||
VkDeviceMemory CommandBufferStagingStream::getDeviceMemory() { return m_mem.deviceMemory; }
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
#ifndef __COMMAND_BUFFER_STAGING_STREAM_H
|
||||
#define __COMMAND_BUFFER_STAGING_STREAM_H
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "IOStream.h"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
class CommandBufferStagingStream : public IOStream {
|
||||
public:
|
||||
// host will write kSyncDataReadComplete to the sync bytes to indicate memory is no longer being
|
||||
// used by host. This is only used with custom allocators. The sync bytes are used to ensure that,
|
||||
// during reallocations the guest does not free memory being read by the host. The guest ensures
|
||||
// that the sync bytes are marked as read complete before releasing the memory.
|
||||
static constexpr size_t kSyncDataSize = 8;
|
||||
// indicates read is complete
|
||||
static constexpr uint32_t kSyncDataReadComplete = 0X0;
|
||||
// indicates read is pending
|
||||
static constexpr uint32_t kSyncDataReadPending = 0X1;
|
||||
|
||||
// \struct backing memory structure
|
||||
struct Memory {
|
||||
VkDeviceMemory deviceMemory =
|
||||
VK_NULL_HANDLE; // device memory associated with allocated memory
|
||||
void* ptr = nullptr; // pointer to allocated memory
|
||||
bool operator==(const Memory& rhs) const {
|
||||
return (deviceMemory == rhs.deviceMemory) && (ptr == rhs.ptr);
|
||||
}
|
||||
};
|
||||
|
||||
// allocator
|
||||
// param size to allocate
|
||||
// return allocated memory
|
||||
using Alloc = std::function<Memory(size_t)>;
|
||||
// free function
|
||||
// param memory to free
|
||||
using Free = std::function<void(const Memory&)>;
|
||||
// constructor
|
||||
// \param allocFn is the allocation function provided.
|
||||
// \param freeFn is the free function provided
|
||||
explicit CommandBufferStagingStream(const Alloc& allocFn, const Free& freeFn);
|
||||
// constructor
|
||||
explicit CommandBufferStagingStream();
|
||||
~CommandBufferStagingStream();
|
||||
|
||||
virtual size_t idealAllocSize(size_t len);
|
||||
virtual void* allocBuffer(size_t minSize);
|
||||
virtual int commitBuffer(size_t size);
|
||||
virtual const unsigned char* readFully(void* buf, size_t len);
|
||||
virtual const unsigned char* read(void* buf, size_t* inout_len);
|
||||
virtual int writeFully(const void* buf, size_t len);
|
||||
virtual const unsigned char* commitBufferAndReadFully(size_t size, void* buf, size_t len);
|
||||
|
||||
void getWritten(unsigned char** bufOut, size_t* sizeOut);
|
||||
void reset();
|
||||
|
||||
// marks the command buffer stream as flushing. The owner of CommandBufferStagingStream
|
||||
// should call markFlushing after finishing writing to the stream.
|
||||
// This will mark the sync data to kSyncDataReadPending. This is only applicable when
|
||||
// using custom allocators. markFlushing will be a no-op if called
|
||||
// when not using custom allocators
|
||||
void markFlushing();
|
||||
|
||||
// gets the device memory associated with the stream. This is VK_NULL_HANDLE for default allocation
|
||||
// \return device memory
|
||||
VkDeviceMemory getDeviceMemory();
|
||||
|
||||
private:
|
||||
// underlying memory for data
|
||||
Memory m_mem;
|
||||
// size of portion of memory available for data.
|
||||
// for custom allocation, this size excludes size of sync data.
|
||||
size_t m_size;
|
||||
// current write position in data buffer
|
||||
uint32_t m_writePos;
|
||||
|
||||
// alloc function
|
||||
Alloc m_alloc;
|
||||
// free function
|
||||
Free m_free;
|
||||
|
||||
// realloc function
|
||||
// \param size of memory to be allocated
|
||||
// \ param reference size to update with actual size allocated. This size can be < requested size
|
||||
// for custom allocation to account for sync data
|
||||
using Realloc = std::function<Memory(const Memory&, size_t)>;
|
||||
Realloc m_realloc;
|
||||
|
||||
// flag tracking use of custom allocation/free
|
||||
bool m_usingCustomAlloc = false;
|
||||
|
||||
// adjusted memory location to point to start of data after accounting for metadata
|
||||
// \return pointer to data start
|
||||
unsigned char* getDataPtr();
|
||||
};
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,499 @@
|
||||
// Copyright (C) 2021 The Android Open Source Project
|
||||
// Copyright (C) 2021 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.
|
||||
#include "DescriptorSetVirtualization.h"
|
||||
#include "Resources.h"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
void clearReifiedDescriptorSet(ReifiedDescriptorSet* set) {
|
||||
set->pool = VK_NULL_HANDLE;
|
||||
set->setLayout = VK_NULL_HANDLE;
|
||||
set->poolId = -1;
|
||||
set->allocationPending = false;
|
||||
set->allWrites.clear();
|
||||
set->pendingWriteArrayRanges.clear();
|
||||
}
|
||||
|
||||
void initDescriptorWriteTable(const std::vector<VkDescriptorSetLayoutBinding>& layoutBindings, DescriptorWriteTable& table) {
|
||||
uint32_t highestBindingNumber = 0;
|
||||
|
||||
for (uint32_t i = 0; i < layoutBindings.size(); ++i) {
|
||||
if (layoutBindings[i].binding > highestBindingNumber) {
|
||||
highestBindingNumber = layoutBindings[i].binding;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32_t> countsEachBinding(highestBindingNumber + 1, 0);
|
||||
|
||||
for (uint32_t i = 0; i < layoutBindings.size(); ++i) {
|
||||
countsEachBinding[layoutBindings[i].binding] =
|
||||
layoutBindings[i].descriptorCount;
|
||||
}
|
||||
|
||||
table.resize(countsEachBinding.size());
|
||||
|
||||
for (uint32_t i = 0; i < table.size(); ++i) {
|
||||
table[i].resize(countsEachBinding[i]);
|
||||
|
||||
for (uint32_t j = 0; j < countsEachBinding[i]; ++j) {
|
||||
table[i][j].type = DescriptorWriteType::Empty;
|
||||
table[i][j].dstArrayElement = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void initializeReifiedDescriptorSet(VkDescriptorPool pool, VkDescriptorSetLayout setLayout, ReifiedDescriptorSet* set) {
|
||||
|
||||
set->pendingWriteArrayRanges.clear();
|
||||
|
||||
const auto& layoutInfo = *(as_goldfish_VkDescriptorSetLayout(setLayout)->layoutInfo);
|
||||
|
||||
initDescriptorWriteTable(layoutInfo.bindings, set->allWrites);
|
||||
|
||||
for (size_t i = 0; i < layoutInfo.bindings.size(); ++i) {
|
||||
// Bindings can be sparsely defined
|
||||
const auto& binding = layoutInfo.bindings[i];
|
||||
uint32_t bindingIndex = binding.binding;
|
||||
if (set->bindingIsImmutableSampler.size() <= bindingIndex) {
|
||||
set->bindingIsImmutableSampler.resize(bindingIndex + 1, false);
|
||||
}
|
||||
set->bindingIsImmutableSampler[bindingIndex] =
|
||||
binding.descriptorCount > 0 &&
|
||||
(binding.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
||||
binding.descriptorType ==
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
|
||||
binding.pImmutableSamplers;
|
||||
}
|
||||
|
||||
set->pool = pool;
|
||||
set->setLayout = setLayout;
|
||||
set->allocationPending = true;
|
||||
set->bindings = layoutInfo.bindings;
|
||||
}
|
||||
|
||||
bool isDescriptorTypeImageInfo(VkDescriptorType descType) {
|
||||
return (descType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
|
||||
(descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
|
||||
(descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
|
||||
(descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
|
||||
(descType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
|
||||
}
|
||||
|
||||
bool isDescriptorTypeBufferInfo(VkDescriptorType descType) {
|
||||
return (descType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
|
||||
(descType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
|
||||
(descType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
|
||||
(descType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
|
||||
}
|
||||
|
||||
bool isDescriptorTypeBufferView(VkDescriptorType descType) {
|
||||
return (descType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
|
||||
(descType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
|
||||
}
|
||||
|
||||
bool isDescriptorTypeInlineUniformBlock(VkDescriptorType descType) {
|
||||
return descType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
|
||||
}
|
||||
|
||||
bool isDescriptorTypeAccelerationStructure(VkDescriptorType descType) {
|
||||
return descType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
|
||||
}
|
||||
|
||||
void doEmulatedDescriptorWrite(const VkWriteDescriptorSet* write, ReifiedDescriptorSet* toWrite) {
|
||||
VkDescriptorType descType = write->descriptorType;
|
||||
uint32_t dstBinding = write->dstBinding;
|
||||
uint32_t dstArrayElement = write->dstArrayElement;
|
||||
uint32_t descriptorCount = write->descriptorCount;
|
||||
|
||||
DescriptorWriteTable& table = toWrite->allWrites;
|
||||
|
||||
uint32_t arrOffset = dstArrayElement;
|
||||
|
||||
if (isDescriptorTypeImageInfo(descType)) {
|
||||
for (uint32_t i = 0; i < descriptorCount; ++i, ++arrOffset) {
|
||||
if (arrOffset >= table[dstBinding].size()) {
|
||||
++dstBinding;
|
||||
arrOffset = 0;
|
||||
}
|
||||
auto& entry = table[dstBinding][arrOffset];
|
||||
entry.imageInfo = write->pImageInfo[i];
|
||||
entry.type = DescriptorWriteType::ImageInfo;
|
||||
entry.descriptorType = descType;
|
||||
}
|
||||
} else if (isDescriptorTypeBufferInfo(descType)) {
|
||||
for (uint32_t i = 0; i < descriptorCount; ++i, ++arrOffset) {
|
||||
if (arrOffset >= table[dstBinding].size()) {
|
||||
++dstBinding;
|
||||
arrOffset = 0;
|
||||
}
|
||||
auto& entry = table[dstBinding][arrOffset];
|
||||
entry.bufferInfo = write->pBufferInfo[i];
|
||||
entry.type = DescriptorWriteType::BufferInfo;
|
||||
entry.descriptorType = descType;
|
||||
}
|
||||
} else if (isDescriptorTypeBufferView(descType)) {
|
||||
for (uint32_t i = 0; i < descriptorCount; ++i, ++arrOffset) {
|
||||
if (arrOffset >= table[dstBinding].size()) {
|
||||
++dstBinding;
|
||||
arrOffset = 0;
|
||||
}
|
||||
auto& entry = table[dstBinding][arrOffset];
|
||||
entry.bufferView = write->pTexelBufferView[i];
|
||||
entry.type = DescriptorWriteType::BufferView;
|
||||
entry.descriptorType = descType;
|
||||
}
|
||||
} else if (isDescriptorTypeInlineUniformBlock(descType) ||
|
||||
isDescriptorTypeAccelerationStructure(descType)) {
|
||||
// TODO
|
||||
// Look for pNext inline uniform block or acceleration structure.
|
||||
// Append new DescriptorWrite entry that holds the buffer
|
||||
ALOGW("%s: Ignoring emulated write for descriptor type 0x%x\n", __func__, descType);
|
||||
}
|
||||
}
|
||||
|
||||
void doEmulatedDescriptorCopy(const VkCopyDescriptorSet* copy, const ReifiedDescriptorSet* src, ReifiedDescriptorSet* dst) {
|
||||
const DescriptorWriteTable& srcTable = src->allWrites;
|
||||
DescriptorWriteTable& dstTable = dst->allWrites;
|
||||
|
||||
// src/dst may be the same descriptor set, so we need to create a temporary array for that case.
|
||||
// (TODO: Maybe just notice the pointers are the same? can aliasing in any other way happen?)
|
||||
|
||||
std::vector<DescriptorWrite> toCopy;
|
||||
uint32_t currBinding = copy->srcBinding;
|
||||
uint32_t arrOffset = copy->srcArrayElement;
|
||||
for (uint32_t i = 0; i < copy->descriptorCount; ++i, ++arrOffset) {
|
||||
if (arrOffset >= srcTable[currBinding].size()) {
|
||||
++currBinding;
|
||||
arrOffset = 0;
|
||||
}
|
||||
toCopy.push_back(srcTable[currBinding][arrOffset]);
|
||||
}
|
||||
|
||||
currBinding = copy->dstBinding;
|
||||
arrOffset = copy->dstArrayElement;
|
||||
for (uint32_t i = 0; i < copy->descriptorCount; ++i, ++arrOffset) {
|
||||
if (arrOffset >= dstTable[currBinding].size()) {
|
||||
++currBinding;
|
||||
arrOffset = 0;
|
||||
}
|
||||
dstTable[currBinding][arrOffset] = toCopy[i];
|
||||
}
|
||||
}
|
||||
|
||||
void doEmulatedDescriptorImageInfoWriteFromTemplate(
|
||||
VkDescriptorType descType,
|
||||
uint32_t binding,
|
||||
uint32_t dstArrayElement,
|
||||
uint32_t count,
|
||||
const VkDescriptorImageInfo* imageInfos,
|
||||
ReifiedDescriptorSet* set) {
|
||||
|
||||
DescriptorWriteTable& table = set->allWrites;
|
||||
|
||||
uint32_t currBinding = binding;
|
||||
uint32_t arrOffset = dstArrayElement;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i, ++arrOffset) {
|
||||
if (arrOffset >= table[currBinding].size()) {
|
||||
++currBinding;
|
||||
arrOffset = 0;
|
||||
}
|
||||
auto& entry = table[currBinding][arrOffset];
|
||||
entry.imageInfo = imageInfos[i];
|
||||
entry.type = DescriptorWriteType::ImageInfo;
|
||||
entry.descriptorType = descType;
|
||||
}
|
||||
}
|
||||
|
||||
void doEmulatedDescriptorBufferInfoWriteFromTemplate(
|
||||
VkDescriptorType descType,
|
||||
uint32_t binding,
|
||||
uint32_t dstArrayElement,
|
||||
uint32_t count,
|
||||
const VkDescriptorBufferInfo* bufferInfos,
|
||||
ReifiedDescriptorSet* set) {
|
||||
|
||||
DescriptorWriteTable& table = set->allWrites;
|
||||
|
||||
uint32_t currBinding = binding;
|
||||
uint32_t arrOffset = dstArrayElement;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i, ++arrOffset) {
|
||||
if (arrOffset >= table[currBinding].size()) {
|
||||
++currBinding;
|
||||
arrOffset = 0;
|
||||
}
|
||||
auto& entry = table[currBinding][dstArrayElement + i];
|
||||
entry.bufferInfo = bufferInfos[i];
|
||||
entry.type = DescriptorWriteType::BufferInfo;
|
||||
entry.descriptorType = descType;
|
||||
}
|
||||
}
|
||||
|
||||
void doEmulatedDescriptorBufferViewWriteFromTemplate(
|
||||
VkDescriptorType descType,
|
||||
uint32_t binding,
|
||||
uint32_t dstArrayElement,
|
||||
uint32_t count,
|
||||
const VkBufferView* bufferViews,
|
||||
ReifiedDescriptorSet* set) {
|
||||
|
||||
DescriptorWriteTable& table = set->allWrites;
|
||||
|
||||
uint32_t currBinding = binding;
|
||||
uint32_t arrOffset = dstArrayElement;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i, ++arrOffset) {
|
||||
if (arrOffset >= table[currBinding].size()) {
|
||||
++currBinding;
|
||||
arrOffset = 0;
|
||||
}
|
||||
auto& entry = table[currBinding][dstArrayElement + i];
|
||||
entry.bufferView = bufferViews[i];
|
||||
entry.type = DescriptorWriteType::BufferView;
|
||||
entry.descriptorType = descType;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isBindingFeasibleForAlloc(
|
||||
const DescriptorPoolAllocationInfo::DescriptorCountInfo& countInfo,
|
||||
const VkDescriptorSetLayoutBinding& binding) {
|
||||
|
||||
if (binding.descriptorCount && (countInfo.type != binding.descriptorType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t availDescriptorCount =
|
||||
countInfo.descriptorCount - countInfo.used;
|
||||
|
||||
if (availDescriptorCount < binding.descriptorCount) {
|
||||
ALOGV("%s: Ran out of descriptors of type 0x%x. "
|
||||
"Wanted %u from layout but "
|
||||
"we only have %u free (total in pool: %u)\n", __func__,
|
||||
binding.descriptorType,
|
||||
binding.descriptorCount,
|
||||
countInfo.descriptorCount - countInfo.used,
|
||||
countInfo.descriptorCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isBindingFeasibleForFree(
|
||||
const DescriptorPoolAllocationInfo::DescriptorCountInfo& countInfo,
|
||||
const VkDescriptorSetLayoutBinding& binding) {
|
||||
|
||||
if (countInfo.type != binding.descriptorType) return false;
|
||||
if (countInfo.used < binding.descriptorCount) {
|
||||
ALOGV("%s: Was a descriptor set double freed? "
|
||||
"Ran out of descriptors of type 0x%x. "
|
||||
"Wanted to free %u from layout but "
|
||||
"we only have %u used (total in pool: %u)\n", __func__,
|
||||
binding.descriptorType,
|
||||
binding.descriptorCount,
|
||||
countInfo.used,
|
||||
countInfo.descriptorCount);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void allocBindingFeasible(
|
||||
const VkDescriptorSetLayoutBinding& binding,
|
||||
DescriptorPoolAllocationInfo::DescriptorCountInfo& poolState) {
|
||||
poolState.used += binding.descriptorCount;
|
||||
}
|
||||
|
||||
static void freeBindingFeasible(
|
||||
const VkDescriptorSetLayoutBinding& binding,
|
||||
DescriptorPoolAllocationInfo::DescriptorCountInfo& poolState) {
|
||||
poolState.used -= binding.descriptorCount;
|
||||
}
|
||||
|
||||
static VkResult validateDescriptorSetAllocation(const VkDescriptorSetAllocateInfo* pAllocateInfo) {
|
||||
VkDescriptorPool pool = pAllocateInfo->descriptorPool;
|
||||
DescriptorPoolAllocationInfo* poolInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
|
||||
|
||||
// Check the number of sets available.
|
||||
auto setsAvailable = poolInfo->maxSets - poolInfo->usedSets;
|
||||
|
||||
if (setsAvailable < pAllocateInfo->descriptorSetCount) {
|
||||
ALOGV("%s: Error: VkDescriptorSetAllocateInfo wants %u sets "
|
||||
"but we only have %u available. "
|
||||
"Bailing with VK_ERROR_OUT_OF_POOL_MEMORY.\n", __func__,
|
||||
pAllocateInfo->descriptorSetCount,
|
||||
setsAvailable);
|
||||
return VK_ERROR_OUT_OF_POOL_MEMORY;
|
||||
}
|
||||
|
||||
// Perform simulated allocation and error out with
|
||||
// VK_ERROR_OUT_OF_POOL_MEMORY if it fails.
|
||||
std::vector<DescriptorPoolAllocationInfo::DescriptorCountInfo> descriptorCountCopy =
|
||||
poolInfo->descriptorCountInfo;
|
||||
|
||||
for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i) {
|
||||
if (!pAllocateInfo->pSetLayouts[i]) {
|
||||
ALOGV("%s: Error: Tried to allocate a descriptor set with null set layout.\n", __func__);
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
auto setLayoutInfo = as_goldfish_VkDescriptorSetLayout(pAllocateInfo->pSetLayouts[i])->layoutInfo;
|
||||
if (!setLayoutInfo) {
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
for (const auto& binding : setLayoutInfo->bindings) {
|
||||
bool success = false;
|
||||
for (auto& pool : descriptorCountCopy) {
|
||||
if (!isBindingFeasibleForAlloc(pool, binding)) continue;
|
||||
|
||||
success = true;
|
||||
allocBindingFeasible(binding, pool);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return VK_ERROR_OUT_OF_POOL_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void applyDescriptorSetAllocation(VkDescriptorPool pool, VkDescriptorSetLayout setLayout) {
|
||||
auto allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
|
||||
auto setLayoutInfo = as_goldfish_VkDescriptorSetLayout(setLayout)->layoutInfo;
|
||||
|
||||
++allocInfo->usedSets;
|
||||
|
||||
for (const auto& binding : setLayoutInfo->bindings) {
|
||||
for (auto& countForPool : allocInfo->descriptorCountInfo) {
|
||||
if (!isBindingFeasibleForAlloc(countForPool, binding)) continue;
|
||||
allocBindingFeasible(binding, countForPool);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void removeDescriptorSetAllocation(VkDescriptorPool pool, const std::vector<VkDescriptorSetLayoutBinding>& bindings) {
|
||||
auto allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
|
||||
|
||||
if (0 == allocInfo->usedSets) {
|
||||
ALOGV("%s: Warning: a descriptor set was double freed.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
--allocInfo->usedSets;
|
||||
|
||||
for (const auto& binding : bindings) {
|
||||
for (auto& countForPool : allocInfo->descriptorCountInfo) {
|
||||
if (!isBindingFeasibleForFree(countForPool, binding)) continue;
|
||||
freeBindingFeasible(binding, countForPool);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fillDescriptorSetInfoForPool(VkDescriptorPool pool, VkDescriptorSetLayout setLayout, VkDescriptorSet set) {
|
||||
DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
|
||||
|
||||
ReifiedDescriptorSet* newReified = new ReifiedDescriptorSet;
|
||||
newReified->poolId = as_goldfish_VkDescriptorSet(set)->underlying;
|
||||
newReified->allocationPending = true;
|
||||
|
||||
as_goldfish_VkDescriptorSet(set)->reified = newReified;
|
||||
|
||||
allocInfo->allocedPoolIds.insert(newReified->poolId);
|
||||
allocInfo->allocedSets.insert(set);
|
||||
|
||||
initializeReifiedDescriptorSet(pool, setLayout, newReified);
|
||||
}
|
||||
|
||||
VkResult validateAndApplyVirtualDescriptorSetAllocation(const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pSets) {
|
||||
VkResult validateRes = validateDescriptorSetAllocation(pAllocateInfo);
|
||||
|
||||
if (validateRes != VK_SUCCESS) return validateRes;
|
||||
|
||||
for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; ++i) {
|
||||
applyDescriptorSetAllocation(pAllocateInfo->descriptorPool, pAllocateInfo->pSetLayouts[i]);
|
||||
}
|
||||
|
||||
VkDescriptorPool pool = pAllocateInfo->descriptorPool;
|
||||
DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
|
||||
|
||||
if (allocInfo->freePoolIds.size() < pAllocateInfo->descriptorSetCount) {
|
||||
ALOGE("%s: FATAL: Somehow out of descriptor pool IDs. Wanted %u IDs but only have %u free IDs remaining. The count for maxSets was %u and used was %u\n", __func__,
|
||||
pAllocateInfo->descriptorSetCount,
|
||||
(uint32_t)allocInfo->freePoolIds.size(),
|
||||
allocInfo->maxSets,
|
||||
allocInfo->usedSets);
|
||||
abort();
|
||||
}
|
||||
|
||||
for (uint32_t i = 0 ; i < pAllocateInfo->descriptorSetCount; ++i) {
|
||||
uint64_t id = allocInfo->freePoolIds.back();
|
||||
allocInfo->freePoolIds.pop_back();
|
||||
|
||||
VkDescriptorSet newSet = new_from_host_VkDescriptorSet((VkDescriptorSet)id);
|
||||
pSets[i] = newSet;
|
||||
|
||||
fillDescriptorSetInfoForPool(pool, pAllocateInfo->pSetLayouts[i], newSet);
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
bool removeDescriptorSetFromPool(VkDescriptorSet set, bool usePoolIds) {
|
||||
ReifiedDescriptorSet* reified = as_goldfish_VkDescriptorSet(set)->reified;
|
||||
|
||||
VkDescriptorPool pool = reified->pool;
|
||||
DescriptorPoolAllocationInfo* allocInfo = as_goldfish_VkDescriptorPool(pool)->allocInfo;
|
||||
|
||||
if (usePoolIds) {
|
||||
// Look for the set's pool Id in the pool. If not found, then this wasn't really allocated, and bail.
|
||||
if (allocInfo->allocedPoolIds.find(reified->poolId) == allocInfo->allocedPoolIds.end()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<VkDescriptorSetLayoutBinding>& bindings = reified->bindings;
|
||||
removeDescriptorSetAllocation(pool, bindings);
|
||||
|
||||
if (usePoolIds) {
|
||||
allocInfo->freePoolIds.push_back(reified->poolId);
|
||||
allocInfo->allocedPoolIds.erase(reified->poolId);
|
||||
}
|
||||
allocInfo->allocedSets.erase(set);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<VkDescriptorSet> clearDescriptorPool(VkDescriptorPool pool, bool usePoolIds) {
|
||||
std::vector<VkDescriptorSet> toClear;
|
||||
for (auto set : as_goldfish_VkDescriptorPool(pool)->allocInfo->allocedSets) {
|
||||
toClear.push_back(set);
|
||||
}
|
||||
|
||||
for (auto set: toClear) {
|
||||
removeDescriptorSetFromPool(set, usePoolIds);
|
||||
}
|
||||
|
||||
return toClear;
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,153 @@
|
||||
// Copyright (C) 2021 The Android Open Source Project
|
||||
// Copyright (C) 2021 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 "aemu/base/containers/EntityManager.h"
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
enum DescriptorWriteType {
|
||||
Empty = 0,
|
||||
ImageInfo = 1,
|
||||
BufferInfo = 2,
|
||||
BufferView = 3,
|
||||
InlineUniformBlock = 4,
|
||||
AccelerationStructure = 5,
|
||||
};
|
||||
|
||||
struct DescriptorWrite {
|
||||
DescriptorWriteType type;
|
||||
VkDescriptorType descriptorType;
|
||||
|
||||
uint32_t dstArrayElement; // Only used for inlineUniformBlock and accelerationStructure.
|
||||
|
||||
union {
|
||||
VkDescriptorImageInfo imageInfo;
|
||||
VkDescriptorBufferInfo bufferInfo;
|
||||
VkBufferView bufferView;
|
||||
VkWriteDescriptorSetInlineUniformBlockEXT inlineUniformBlock;
|
||||
VkWriteDescriptorSetAccelerationStructureKHR accelerationStructure;
|
||||
};
|
||||
|
||||
std::vector<uint8_t> inlineUniformBlockBuffer;
|
||||
};
|
||||
|
||||
using DescriptorWriteTable = std::vector<std::vector<DescriptorWrite>>;
|
||||
|
||||
struct DescriptorWriteArrayRange {
|
||||
uint32_t begin;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
using DescriptorWriteDstArrayRangeTable = std::vector<std::vector<DescriptorWriteArrayRange>>;
|
||||
|
||||
struct ReifiedDescriptorSet {
|
||||
VkDescriptorPool pool;
|
||||
VkDescriptorSetLayout setLayout;
|
||||
uint64_t poolId;
|
||||
bool allocationPending;
|
||||
|
||||
// Indexed first by binding number
|
||||
DescriptorWriteTable allWrites;
|
||||
|
||||
// Indexed first by binding number
|
||||
DescriptorWriteDstArrayRangeTable pendingWriteArrayRanges;
|
||||
|
||||
// Indexed by binding number
|
||||
std::vector<bool> bindingIsImmutableSampler;
|
||||
|
||||
// Copied from the descriptor set layout
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||
};
|
||||
|
||||
struct DescriptorPoolAllocationInfo {
|
||||
VkDevice device;
|
||||
VkDescriptorPoolCreateFlags createFlags;
|
||||
|
||||
// TODO: This should be in a single fancy data structure of some kind.
|
||||
std::vector<uint64_t> freePoolIds;
|
||||
std::unordered_set<uint32_t> allocedPoolIds;
|
||||
std::unordered_set<VkDescriptorSet> allocedSets;
|
||||
uint32_t maxSets;
|
||||
uint32_t usedSets;
|
||||
|
||||
// Fine-grained tracking of descriptor counts in individual pools
|
||||
struct DescriptorCountInfo {
|
||||
VkDescriptorType type;
|
||||
uint32_t descriptorCount;
|
||||
uint32_t used;
|
||||
};
|
||||
std::vector<DescriptorCountInfo> descriptorCountInfo;
|
||||
};
|
||||
|
||||
struct DescriptorSetLayoutInfo {
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||
uint32_t refcount;
|
||||
};
|
||||
|
||||
void clearReifiedDescriptorSet(ReifiedDescriptorSet* set);
|
||||
|
||||
void initDescriptorWriteTable(const std::vector<VkDescriptorSetLayoutBinding>& layoutBindings, DescriptorWriteTable& table);
|
||||
|
||||
bool isDescriptorTypeImageInfo(VkDescriptorType descType);
|
||||
bool isDescriptorTypeBufferInfo(VkDescriptorType descType);
|
||||
bool isDescriptorTypeBufferView(VkDescriptorType descType);
|
||||
bool isDescriptorTypeInlineUniformBlock(VkDescriptorType descType);
|
||||
bool isDescriptorTypeAccelerationStructure(VkDescriptorType descType);
|
||||
|
||||
void doEmulatedDescriptorWrite(const VkWriteDescriptorSet* write, ReifiedDescriptorSet* toWrite);
|
||||
void doEmulatedDescriptorCopy(const VkCopyDescriptorSet* copy, const ReifiedDescriptorSet* src, ReifiedDescriptorSet* dst);
|
||||
|
||||
void doEmulatedDescriptorImageInfoWriteFromTemplate(
|
||||
VkDescriptorType descType,
|
||||
uint32_t binding,
|
||||
uint32_t dstArrayElement,
|
||||
uint32_t count,
|
||||
const VkDescriptorImageInfo* imageInfos,
|
||||
ReifiedDescriptorSet* set);
|
||||
|
||||
void doEmulatedDescriptorBufferInfoWriteFromTemplate(
|
||||
VkDescriptorType descType,
|
||||
uint32_t binding,
|
||||
uint32_t dstArrayElement,
|
||||
uint32_t count,
|
||||
const VkDescriptorBufferInfo* bufferInfos,
|
||||
ReifiedDescriptorSet* set);
|
||||
|
||||
void doEmulatedDescriptorBufferViewWriteFromTemplate(
|
||||
VkDescriptorType descType,
|
||||
uint32_t binding,
|
||||
uint32_t dstArrayElement,
|
||||
uint32_t count,
|
||||
const VkBufferView* bufferViews,
|
||||
ReifiedDescriptorSet* set);
|
||||
|
||||
void applyDescriptorSetAllocation(VkDescriptorPool pool, VkDescriptorSetLayout setLayout);
|
||||
void fillDescriptorSetInfoForPool(VkDescriptorPool pool, VkDescriptorSetLayout setLayout, VkDescriptorSet set);
|
||||
VkResult validateAndApplyVirtualDescriptorSetAllocation(const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pSets);
|
||||
|
||||
// Returns false if set wasn't found in its pool.
|
||||
bool removeDescriptorSetFromPool(VkDescriptorSet set, bool usePoolIds);
|
||||
|
||||
std::vector<VkDescriptorSet> clearDescriptorPool(VkDescriptorPool pool, bool usePoolIds);
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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.
|
||||
#include "HostVisibleMemoryVirtualization.h"
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "../OpenglSystemCommon/EmulatorFeatureInfo.h"
|
||||
#include "ResourceTracker.h"
|
||||
#include "Resources.h"
|
||||
#include "VkEncoder.h"
|
||||
#include "aemu/base/AndroidSubAllocator.h"
|
||||
|
||||
using android::base::guest::SubAllocator;
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
bool isHostVisible(const VkPhysicalDeviceMemoryProperties* memoryProps, uint32_t index) {
|
||||
return memoryProps->memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
}
|
||||
|
||||
CoherentMemory::CoherentMemory(VirtGpuBlobMappingPtr blobMapping, uint64_t size, VkDevice device,
|
||||
VkDeviceMemory memory)
|
||||
: mSize(size), mBlobMapping(blobMapping), mDevice(device), mMemory(memory) {
|
||||
mAllocator =
|
||||
std::make_unique<android::base::guest::SubAllocator>(blobMapping->asRawPtr(), mSize, 4096);
|
||||
}
|
||||
|
||||
CoherentMemory::CoherentMemory(GoldfishAddressSpaceBlockPtr block, uint64_t gpuAddr, uint64_t size,
|
||||
VkDevice device, VkDeviceMemory memory)
|
||||
: mSize(size), mBlock(block), mDevice(device), mMemory(memory) {
|
||||
void* address = block->mmap(gpuAddr);
|
||||
mAllocator =
|
||||
std::make_unique<android::base::guest::SubAllocator>(address, mSize, kLargestPageSize);
|
||||
}
|
||||
|
||||
CoherentMemory::~CoherentMemory() {
|
||||
ResourceTracker::getThreadLocalEncoder()->vkFreeMemorySyncGOOGLE(mDevice, mMemory, nullptr,
|
||||
false);
|
||||
}
|
||||
|
||||
VkDeviceMemory CoherentMemory::getDeviceMemory() const { return mMemory; }
|
||||
|
||||
bool CoherentMemory::subAllocate(uint64_t size, uint8_t** ptr, uint64_t& offset) {
|
||||
auto address = mAllocator->alloc(size);
|
||||
if (!address) return false;
|
||||
|
||||
*ptr = (uint8_t*)address;
|
||||
offset = mAllocator->getOffset(address);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoherentMemory::release(uint8_t* ptr) {
|
||||
mAllocator->free(ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,70 @@
|
||||
// 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 "VirtGpu.h"
|
||||
#include "aemu/base/AndroidSubAllocator.h"
|
||||
#include "goldfish_address_space.h"
|
||||
|
||||
constexpr uint64_t kMegaByte = 1048576;
|
||||
|
||||
// This needs to be a power of 2 that is at least the min alignment needed
|
||||
// in HostVisibleMemoryVirtualization.cpp.
|
||||
// Some Windows drivers require a 64KB alignment for suballocated memory (b:152769369) for YUV
|
||||
// images.
|
||||
constexpr uint64_t kLargestPageSize = 65536;
|
||||
|
||||
constexpr uint64_t kDefaultHostMemBlockSize = 16 * kMegaByte; // 16 mb
|
||||
constexpr uint64_t kHostVisibleHeapSize = 512 * kMegaByte; // 512 mb
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
bool isHostVisible(const VkPhysicalDeviceMemoryProperties* memoryProps, uint32_t index);
|
||||
|
||||
using GoldfishAddressSpaceBlockPtr = std::shared_ptr<GoldfishAddressSpaceBlock>;
|
||||
using SubAllocatorPtr = std::unique_ptr<android::base::guest::SubAllocator>;
|
||||
|
||||
class CoherentMemory {
|
||||
public:
|
||||
CoherentMemory(VirtGpuBlobMappingPtr blobMapping, uint64_t size, VkDevice device,
|
||||
VkDeviceMemory memory);
|
||||
CoherentMemory(GoldfishAddressSpaceBlockPtr block, uint64_t gpuAddr, uint64_t size,
|
||||
VkDevice device, VkDeviceMemory memory);
|
||||
~CoherentMemory();
|
||||
|
||||
VkDeviceMemory getDeviceMemory() const;
|
||||
|
||||
bool subAllocate(uint64_t size, uint8_t** ptr, uint64_t& offset);
|
||||
bool release(uint8_t* ptr);
|
||||
|
||||
private:
|
||||
CoherentMemory(CoherentMemory const&);
|
||||
void operator=(CoherentMemory const&);
|
||||
|
||||
uint64_t mSize;
|
||||
VirtGpuBlobMappingPtr mBlobMapping = nullptr;
|
||||
GoldfishAddressSpaceBlockPtr mBlock = nullptr;
|
||||
VkDevice mDevice;
|
||||
VkDeviceMemory mMemory;
|
||||
SubAllocatorPtr mAllocator;
|
||||
};
|
||||
|
||||
using CoherentMemoryPtr = std::shared_ptr<CoherentMemory>;
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,687 @@
|
||||
// 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 <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "CommandBufferStagingStream.h"
|
||||
#include "VulkanHandleMapping.h"
|
||||
#include "VulkanHandles.h"
|
||||
#include "aemu/base/Tracing.h"
|
||||
#include "goldfish_vk_transform_guest.h"
|
||||
|
||||
struct EmulatorFeatureInfo;
|
||||
|
||||
class HostConnection;
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
class VkEncoder;
|
||||
|
||||
class ResourceTracker {
|
||||
public:
|
||||
ResourceTracker();
|
||||
virtual ~ResourceTracker();
|
||||
static ResourceTracker* get();
|
||||
|
||||
VulkanHandleMapping* createMapping();
|
||||
VulkanHandleMapping* unwrapMapping();
|
||||
VulkanHandleMapping* destroyMapping();
|
||||
VulkanHandleMapping* defaultMapping();
|
||||
|
||||
using HostConnectionGetFunc = HostConnection* (*)();
|
||||
using VkEncoderGetFunc = VkEncoder* (*)(HostConnection*);
|
||||
using CleanupCallback = std::function<void()>;
|
||||
|
||||
struct ThreadingCallbacks {
|
||||
HostConnectionGetFunc hostConnectionGetFunc = 0;
|
||||
VkEncoderGetFunc vkEncoderGetFunc = 0;
|
||||
};
|
||||
|
||||
static uint32_t streamFeatureBits;
|
||||
static ThreadingCallbacks threadingCallbacks;
|
||||
|
||||
#define HANDLE_REGISTER_DECL(type) \
|
||||
void register_##type(type); \
|
||||
void unregister_##type(type); \
|
||||
|
||||
GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_DECL)
|
||||
|
||||
VkResult on_vkEnumerateInstanceExtensionProperties(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
const char* pLayerName,
|
||||
uint32_t* pPropertyCount,
|
||||
VkExtensionProperties* pProperties);
|
||||
|
||||
VkResult on_vkEnumerateDeviceExtensionProperties(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const char* pLayerName,
|
||||
uint32_t* pPropertyCount,
|
||||
VkExtensionProperties* pProperties);
|
||||
|
||||
VkResult on_vkEnumeratePhysicalDevices(
|
||||
void* context, VkResult input_result,
|
||||
VkInstance instance, uint32_t* pPhysicalDeviceCount,
|
||||
VkPhysicalDevice* pPhysicalDevices);
|
||||
|
||||
void on_vkGetPhysicalDeviceFeatures2(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceFeatures2* pFeatures);
|
||||
void on_vkGetPhysicalDeviceFeatures2KHR(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceFeatures2* pFeatures);
|
||||
void on_vkGetPhysicalDeviceProperties(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceProperties* pProperties);
|
||||
void on_vkGetPhysicalDeviceProperties2(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceProperties2* pProperties);
|
||||
void on_vkGetPhysicalDeviceProperties2KHR(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceProperties2* pProperties);
|
||||
|
||||
void on_vkGetPhysicalDeviceMemoryProperties(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceMemoryProperties* pMemoryProperties);
|
||||
void on_vkGetPhysicalDeviceMemoryProperties2(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
|
||||
void on_vkGetPhysicalDeviceMemoryProperties2KHR(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
|
||||
void on_vkGetDeviceQueue(void* context,
|
||||
VkDevice device,
|
||||
uint32_t queueFamilyIndex,
|
||||
uint32_t queueIndex,
|
||||
VkQueue* pQueue);
|
||||
void on_vkGetDeviceQueue2(void* context,
|
||||
VkDevice device,
|
||||
const VkDeviceQueueInfo2* pQueueInfo,
|
||||
VkQueue* pQueue);
|
||||
|
||||
VkResult on_vkCreateInstance(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
const VkInstanceCreateInfo* createInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkInstance* pInstance);
|
||||
VkResult on_vkCreateDevice(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkDeviceCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDevice* pDevice);
|
||||
void on_vkDestroyDevice_pre(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VkResult on_vkAllocateMemory(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkMemoryAllocateInfo* pAllocateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDeviceMemory* pMemory);
|
||||
void on_vkFreeMemory(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
VkDeviceMemory memory,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VkResult on_vkMapMemory(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkDeviceMemory memory,
|
||||
VkDeviceSize offset,
|
||||
VkDeviceSize size,
|
||||
VkMemoryMapFlags,
|
||||
void** ppData);
|
||||
|
||||
void on_vkUnmapMemory(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
VkDeviceMemory memory);
|
||||
|
||||
VkResult on_vkCreateImage(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device, const VkImageCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkImage *pImage);
|
||||
void on_vkDestroyImage(
|
||||
void* context,
|
||||
VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator);
|
||||
|
||||
void on_vkGetImageMemoryRequirements(
|
||||
void *context, VkDevice device, VkImage image,
|
||||
VkMemoryRequirements *pMemoryRequirements);
|
||||
void on_vkGetImageMemoryRequirements2(
|
||||
void *context, VkDevice device, const VkImageMemoryRequirementsInfo2 *pInfo,
|
||||
VkMemoryRequirements2 *pMemoryRequirements);
|
||||
void on_vkGetImageMemoryRequirements2KHR(
|
||||
void *context, VkDevice device, const VkImageMemoryRequirementsInfo2 *pInfo,
|
||||
VkMemoryRequirements2 *pMemoryRequirements);
|
||||
|
||||
VkResult on_vkBindImageMemory(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device, VkImage image, VkDeviceMemory memory,
|
||||
VkDeviceSize memoryOffset);
|
||||
VkResult on_vkBindImageMemory2(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device, uint32_t bindingCount, const VkBindImageMemoryInfo* pBindInfos);
|
||||
VkResult on_vkBindImageMemory2KHR(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device, uint32_t bindingCount, const VkBindImageMemoryInfo* pBindInfos);
|
||||
|
||||
VkResult on_vkCreateBuffer(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device, const VkBufferCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkBuffer *pBuffer);
|
||||
void on_vkDestroyBuffer(
|
||||
void* context,
|
||||
VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator);
|
||||
|
||||
void on_vkGetBufferMemoryRequirements(
|
||||
void* context, VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements);
|
||||
void on_vkGetBufferMemoryRequirements2(
|
||||
void* context, VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo,
|
||||
VkMemoryRequirements2* pMemoryRequirements);
|
||||
void on_vkGetBufferMemoryRequirements2KHR(
|
||||
void* context, VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo,
|
||||
VkMemoryRequirements2* pMemoryRequirements);
|
||||
|
||||
VkResult on_vkBindBufferMemory(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset);
|
||||
VkResult on_vkBindBufferMemory2(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo *pBindInfos);
|
||||
VkResult on_vkBindBufferMemory2KHR(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo *pBindInfos);
|
||||
|
||||
VkResult on_vkCreateSemaphore(
|
||||
void* context, VkResult,
|
||||
VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkSemaphore* pSemaphore);
|
||||
void on_vkDestroySemaphore(
|
||||
void* context,
|
||||
VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator);
|
||||
VkResult on_vkGetSemaphoreFdKHR(
|
||||
void* context, VkResult,
|
||||
VkDevice device,
|
||||
const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
|
||||
int* pFd);
|
||||
VkResult on_vkImportSemaphoreFdKHR(
|
||||
void* context, VkResult,
|
||||
VkDevice device,
|
||||
const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo);
|
||||
|
||||
VkResult on_vkQueueSubmit(
|
||||
void* context, VkResult input_result,
|
||||
VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
|
||||
|
||||
VkResult on_vkQueueWaitIdle(
|
||||
void* context, VkResult input_result,
|
||||
VkQueue queue);
|
||||
|
||||
void unwrap_VkNativeBufferANDROID(
|
||||
const VkImageCreateInfo* pCreateInfo,
|
||||
VkImageCreateInfo* local_pCreateInfo);
|
||||
void unwrap_vkAcquireImageANDROID_nativeFenceFd(int fd, int* fd_out);
|
||||
|
||||
#ifdef VK_USE_PLATFORM_FUCHSIA
|
||||
VkResult on_vkGetMemoryZirconHandleFUCHSIA(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkMemoryGetZirconHandleInfoFUCHSIA* pInfo,
|
||||
uint32_t* pHandle);
|
||||
VkResult on_vkGetMemoryZirconHandlePropertiesFUCHSIA(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
VkExternalMemoryHandleTypeFlagBits handleType,
|
||||
uint32_t handle,
|
||||
VkMemoryZirconHandlePropertiesFUCHSIA* pProperties);
|
||||
VkResult on_vkGetSemaphoreZirconHandleFUCHSIA(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkSemaphoreGetZirconHandleInfoFUCHSIA* pInfo,
|
||||
uint32_t* pHandle);
|
||||
VkResult on_vkImportSemaphoreZirconHandleFUCHSIA(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkImportSemaphoreZirconHandleInfoFUCHSIA* pInfo);
|
||||
VkResult on_vkCreateBufferCollectionFUCHSIA(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkBufferCollectionCreateInfoFUCHSIA* pInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkBufferCollectionFUCHSIA* pCollection);
|
||||
void on_vkDestroyBufferCollectionFUCHSIA(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkBufferCollectionFUCHSIA collection,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
VkResult on_vkSetBufferCollectionBufferConstraintsFUCHSIA(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkBufferCollectionFUCHSIA collection,
|
||||
const VkBufferConstraintsInfoFUCHSIA* pBufferConstraintsInfo);
|
||||
VkResult on_vkSetBufferCollectionImageConstraintsFUCHSIA(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkBufferCollectionFUCHSIA collection,
|
||||
const VkImageConstraintsInfoFUCHSIA* pImageConstraintsInfo);
|
||||
VkResult on_vkGetBufferCollectionPropertiesFUCHSIA(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkBufferCollectionFUCHSIA collection,
|
||||
VkBufferCollectionPropertiesFUCHSIA* pProperties);
|
||||
#endif
|
||||
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
VkResult on_vkGetAndroidHardwareBufferPropertiesANDROID(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const AHardwareBuffer* buffer,
|
||||
VkAndroidHardwareBufferPropertiesANDROID* pProperties);
|
||||
VkResult on_vkGetMemoryAndroidHardwareBufferANDROID(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
|
||||
struct AHardwareBuffer** pBuffer);
|
||||
#endif
|
||||
|
||||
VkResult on_vkCreateSamplerYcbcrConversion(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkSamplerYcbcrConversion* pYcbcrConversion);
|
||||
void on_vkDestroySamplerYcbcrConversion(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
VkSamplerYcbcrConversion ycbcrConversion,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
VkResult on_vkCreateSamplerYcbcrConversionKHR(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkSamplerYcbcrConversion* pYcbcrConversion);
|
||||
void on_vkDestroySamplerYcbcrConversionKHR(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
VkSamplerYcbcrConversion ycbcrConversion,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VkResult on_vkCreateSampler(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkSamplerCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkSampler* pSampler);
|
||||
|
||||
void on_vkGetPhysicalDeviceExternalFenceProperties(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
|
||||
VkExternalFenceProperties* pExternalFenceProperties);
|
||||
|
||||
void on_vkGetPhysicalDeviceExternalFencePropertiesKHR(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
|
||||
VkExternalFenceProperties* pExternalFenceProperties);
|
||||
|
||||
VkResult on_vkCreateFence(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkFenceCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator, VkFence* pFence);
|
||||
|
||||
void on_vkDestroyFence(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
VkFence fence,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VkResult on_vkResetFences(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
uint32_t fenceCount,
|
||||
const VkFence* pFences);
|
||||
|
||||
VkResult on_vkImportFenceFdKHR(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkImportFenceFdInfoKHR* pImportFenceFdInfo);
|
||||
|
||||
VkResult on_vkGetFenceFdKHR(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkFenceGetFdInfoKHR* pGetFdInfo,
|
||||
int* pFd);
|
||||
|
||||
VkResult on_vkWaitForFences(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
uint32_t fenceCount,
|
||||
const VkFence* pFences,
|
||||
VkBool32 waitAll,
|
||||
uint64_t timeout);
|
||||
|
||||
VkResult on_vkCreateDescriptorPool(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkDescriptorPoolCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDescriptorPool* pDescriptorPool);
|
||||
|
||||
void on_vkDestroyDescriptorPool(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
VkDescriptorPool descriptorPool,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VkResult on_vkResetDescriptorPool(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkDescriptorPool descriptorPool,
|
||||
VkDescriptorPoolResetFlags flags);
|
||||
|
||||
VkResult on_vkAllocateDescriptorSets(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkDescriptorSetAllocateInfo* pAllocateInfo,
|
||||
VkDescriptorSet* pDescriptorSets);
|
||||
|
||||
VkResult on_vkFreeDescriptorSets(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkDescriptorPool descriptorPool,
|
||||
uint32_t descriptorSetCount,
|
||||
const VkDescriptorSet* pDescriptorSets);
|
||||
|
||||
VkResult on_vkCreateDescriptorSetLayout(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDescriptorSetLayout* pSetLayout);
|
||||
|
||||
void on_vkUpdateDescriptorSets(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
uint32_t descriptorWriteCount,
|
||||
const VkWriteDescriptorSet* pDescriptorWrites,
|
||||
uint32_t descriptorCopyCount,
|
||||
const VkCopyDescriptorSet* pDescriptorCopies);
|
||||
|
||||
VkResult on_vkMapMemoryIntoAddressSpaceGOOGLE_pre(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkDeviceMemory memory,
|
||||
uint64_t* pAddress);
|
||||
VkResult on_vkMapMemoryIntoAddressSpaceGOOGLE(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkDeviceMemory memory,
|
||||
uint64_t* pAddress);
|
||||
|
||||
VkResult on_vkCreateDescriptorUpdateTemplate(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
|
||||
|
||||
VkResult on_vkCreateDescriptorUpdateTemplateKHR(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
|
||||
|
||||
void on_vkUpdateDescriptorSetWithTemplate(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
VkDescriptorSet descriptorSet,
|
||||
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
|
||||
const void* pData);
|
||||
|
||||
VkResult on_vkGetPhysicalDeviceImageFormatProperties2(
|
||||
void* context, VkResult input_result,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
|
||||
VkImageFormatProperties2* pImageFormatProperties);
|
||||
|
||||
VkResult on_vkGetPhysicalDeviceImageFormatProperties2KHR(
|
||||
void* context, VkResult input_result,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
|
||||
VkImageFormatProperties2* pImageFormatProperties);
|
||||
|
||||
void on_vkGetPhysicalDeviceExternalSemaphoreProperties(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
|
||||
VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
|
||||
|
||||
void on_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
|
||||
void* context,
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
|
||||
VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
|
||||
|
||||
void registerEncoderCleanupCallback(const VkEncoder* encoder, void* handle, CleanupCallback callback);
|
||||
void unregisterEncoderCleanupCallback(const VkEncoder* encoder, void* handle);
|
||||
void onEncoderDeleted(const VkEncoder* encoder);
|
||||
|
||||
uint32_t syncEncodersForCommandBuffer(VkCommandBuffer commandBuffer, VkEncoder* current);
|
||||
uint32_t syncEncodersForQueue(VkQueue queue, VkEncoder* current);
|
||||
|
||||
CommandBufferStagingStream::Alloc getAlloc();
|
||||
CommandBufferStagingStream::Free getFree();
|
||||
|
||||
VkResult on_vkBeginCommandBuffer(
|
||||
void* context, VkResult input_result,
|
||||
VkCommandBuffer commandBuffer,
|
||||
const VkCommandBufferBeginInfo* pBeginInfo);
|
||||
VkResult on_vkEndCommandBuffer(
|
||||
void* context, VkResult input_result,
|
||||
VkCommandBuffer commandBuffer);
|
||||
VkResult on_vkResetCommandBuffer(
|
||||
void* context, VkResult input_result,
|
||||
VkCommandBuffer commandBuffer,
|
||||
VkCommandBufferResetFlags flags);
|
||||
|
||||
VkResult on_vkCreateImageView(
|
||||
void* context, VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkImageViewCreateInfo* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkImageView* pView);
|
||||
|
||||
void on_vkCmdExecuteCommands(
|
||||
void* context,
|
||||
VkCommandBuffer commandBuffer,
|
||||
uint32_t commandBufferCount,
|
||||
const VkCommandBuffer* pCommandBuffers);
|
||||
|
||||
void on_vkCmdBindDescriptorSets(
|
||||
void* context,
|
||||
VkCommandBuffer commandBuffer,
|
||||
VkPipelineBindPoint pipelineBindPoint,
|
||||
VkPipelineLayout layout,
|
||||
uint32_t firstSet,
|
||||
uint32_t descriptorSetCount,
|
||||
const VkDescriptorSet* pDescriptorSets,
|
||||
uint32_t dynamicOffsetCount,
|
||||
const uint32_t* pDynamicOffsets);
|
||||
|
||||
void on_vkCmdPipelineBarrier(
|
||||
void* context,
|
||||
VkCommandBuffer commandBuffer,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask,
|
||||
VkDependencyFlags dependencyFlags,
|
||||
uint32_t memoryBarrierCount,
|
||||
const VkMemoryBarrier* pMemoryBarriers,
|
||||
uint32_t bufferMemoryBarrierCount,
|
||||
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
|
||||
uint32_t imageMemoryBarrierCount,
|
||||
const VkImageMemoryBarrier* pImageMemoryBarriers);
|
||||
|
||||
void on_vkDestroyDescriptorSetLayout(
|
||||
void* context,
|
||||
VkDevice device,
|
||||
VkDescriptorSetLayout descriptorSetLayout,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VkResult on_vkAllocateCommandBuffers(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
const VkCommandBufferAllocateInfo* pAllocateInfo,
|
||||
VkCommandBuffer* pCommandBuffers);
|
||||
|
||||
VkResult on_vkQueueSignalReleaseImageANDROID(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkQueue queue,
|
||||
uint32_t waitSemaphoreCount,
|
||||
const VkSemaphore* pWaitSemaphores,
|
||||
VkImage image,
|
||||
int* pNativeFenceFd);
|
||||
|
||||
VkResult on_vkCreateGraphicsPipelines(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
VkPipelineCache pipelineCache,
|
||||
uint32_t createInfoCount,
|
||||
const VkGraphicsPipelineCreateInfo* pCreateInfos,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkPipeline* pPipelines);
|
||||
|
||||
uint8_t* getMappedPointer(VkDeviceMemory memory);
|
||||
VkDeviceSize getMappedSize(VkDeviceMemory memory);
|
||||
VkDeviceSize getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const;
|
||||
bool isValidMemoryRange(const VkMappedMemoryRange& range) const;
|
||||
|
||||
void setupFeatures(const EmulatorFeatureInfo* features);
|
||||
void setupCaps(void);
|
||||
|
||||
void setThreadingCallbacks(const ThreadingCallbacks& callbacks);
|
||||
bool hostSupportsVulkan() const;
|
||||
bool usingDirectMapping() const;
|
||||
uint32_t getStreamFeatures() const;
|
||||
uint32_t getApiVersionFromInstance(VkInstance instance) const;
|
||||
uint32_t getApiVersionFromDevice(VkDevice device) const;
|
||||
bool hasInstanceExtension(VkInstance instance, const std::string& name) const;
|
||||
bool hasDeviceExtension(VkDevice instance, const std::string& name) const;
|
||||
VkDevice getDevice(VkCommandBuffer commandBuffer) const;
|
||||
void addToCommandPool(VkCommandPool commandPool,
|
||||
uint32_t commandBufferCount,
|
||||
VkCommandBuffer* pCommandBuffers);
|
||||
void resetCommandPoolStagingInfo(VkCommandPool commandPool);
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ALWAYS_INLINE
|
||||
#elif
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
static VkEncoder* getCommandBufferEncoder(VkCommandBuffer commandBuffer);
|
||||
static VkEncoder* getQueueEncoder(VkQueue queue);
|
||||
static VkEncoder* getThreadLocalEncoder();
|
||||
|
||||
static void setSeqnoPtr(uint32_t* seqnoptr);
|
||||
static ALWAYS_INLINE uint32_t nextSeqno();
|
||||
static ALWAYS_INLINE uint32_t getSeqno();
|
||||
|
||||
// Transforms
|
||||
void deviceMemoryTransform_tohost(
|
||||
VkDeviceMemory* memory, uint32_t memoryCount,
|
||||
VkDeviceSize* offset, uint32_t offsetCount,
|
||||
VkDeviceSize* size, uint32_t sizeCount,
|
||||
uint32_t* typeIndex, uint32_t typeIndexCount,
|
||||
uint32_t* typeBits, uint32_t typeBitsCount);
|
||||
void deviceMemoryTransform_fromhost(
|
||||
VkDeviceMemory* memory, uint32_t memoryCount,
|
||||
VkDeviceSize* offset, uint32_t offsetCount,
|
||||
VkDeviceSize* size, uint32_t sizeCount,
|
||||
uint32_t* typeIndex, uint32_t typeIndexCount,
|
||||
uint32_t* typeBits, uint32_t typeBitsCount);
|
||||
|
||||
void transformImpl_VkExternalMemoryProperties_fromhost(
|
||||
VkExternalMemoryProperties* pProperties,
|
||||
uint32_t);
|
||||
void transformImpl_VkExternalMemoryProperties_tohost(
|
||||
VkExternalMemoryProperties* pProperties,
|
||||
uint32_t);
|
||||
void transformImpl_VkImageCreateInfo_fromhost(const VkImageCreateInfo*, uint32_t);
|
||||
void transformImpl_VkImageCreateInfo_tohost(const VkImageCreateInfo*, uint32_t);
|
||||
|
||||
#define DEFINE_TRANSFORMED_TYPE_PROTOTYPE(type) \
|
||||
void transformImpl_##type##_tohost(type*, uint32_t); \
|
||||
void transformImpl_##type##_fromhost(type*, uint32_t);
|
||||
|
||||
LIST_TRIVIAL_TRANSFORMED_TYPES(DEFINE_TRANSFORMED_TYPE_PROTOTYPE)
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> mImpl;
|
||||
};
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,266 @@
|
||||
// Copyright (C) 2018 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 "Resources.h"
|
||||
|
||||
#include <log/log.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GOLDFISH_VK_OBJECT_DEBUG 0
|
||||
|
||||
#if GOLDFISH_VK_OBJECT_DEBUG
|
||||
#define D(fmt,...) ALOGD("%s: " fmt, __func__, ##__VA_ARGS__);
|
||||
#else
|
||||
#ifndef D
|
||||
#define D(fmt,...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
#define GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_IMPL(type) \
|
||||
type new_from_host_##type(type underlying) { \
|
||||
struct goldfish_##type* res = \
|
||||
static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
|
||||
if (!res) { \
|
||||
ALOGE("FATAL: Failed to alloc " #type " handle"); \
|
||||
abort(); \
|
||||
} \
|
||||
res->dispatch.magic = HWVULKAN_DISPATCH_MAGIC; \
|
||||
res->underlying = (uint64_t)underlying; \
|
||||
res->lastUsedEncoder = nullptr; \
|
||||
res->sequenceNumber = 0; \
|
||||
res->privateEncoder = 0; \
|
||||
res->privateStream = 0; \
|
||||
res->flags = 0; \
|
||||
res->poolObjects = 0; \
|
||||
res->subObjects = 0; \
|
||||
res->superObjects = 0; \
|
||||
res->userPtr = 0; \
|
||||
return reinterpret_cast<type>(res); \
|
||||
} \
|
||||
|
||||
#define GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_IMPL(type) \
|
||||
type new_from_host_##type(type underlying) { \
|
||||
struct goldfish_##type* res = \
|
||||
static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
|
||||
res->underlying = (uint64_t)underlying; \
|
||||
res->poolObjects = 0; \
|
||||
res->subObjects = 0; \
|
||||
res->superObjects = 0; \
|
||||
res->userPtr = 0; \
|
||||
return reinterpret_cast<type>(res); \
|
||||
} \
|
||||
|
||||
#define GOLDFISH_VK_AS_GOLDFISH_IMPL(type) \
|
||||
struct goldfish_##type* as_goldfish_##type(type toCast) { \
|
||||
return reinterpret_cast<goldfish_##type*>(toCast); \
|
||||
} \
|
||||
|
||||
#define GOLDFISH_VK_GET_HOST_IMPL(type) \
|
||||
type get_host_##type(type toUnwrap) { \
|
||||
if (!toUnwrap) return VK_NULL_HANDLE; \
|
||||
auto as_goldfish = as_goldfish_##type(toUnwrap); \
|
||||
return (type)(as_goldfish->underlying); \
|
||||
} \
|
||||
|
||||
#define GOLDFISH_VK_DELETE_GOLDFISH_IMPL(type) \
|
||||
void delete_goldfish_##type(type toDelete) { \
|
||||
D("guest %p", toDelete); \
|
||||
free(as_goldfish_##type(toDelete)); \
|
||||
} \
|
||||
|
||||
#define GOLDFISH_VK_IDENTITY_IMPL(type) \
|
||||
type vk_handle_identity_##type(type handle) { \
|
||||
return handle; \
|
||||
} \
|
||||
|
||||
#define GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_U64_IMPL(type) \
|
||||
type new_from_host_u64_##type(uint64_t underlying) { \
|
||||
struct goldfish_##type* res = \
|
||||
static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
|
||||
if (!res) { \
|
||||
ALOGE("FATAL: Failed to alloc " #type " handle"); \
|
||||
abort(); \
|
||||
} \
|
||||
res->dispatch.magic = HWVULKAN_DISPATCH_MAGIC; \
|
||||
res->underlying = underlying; \
|
||||
res->lastUsedEncoder = nullptr; \
|
||||
res->sequenceNumber = 0; \
|
||||
res->privateEncoder = 0; \
|
||||
res->privateStream = 0; \
|
||||
res->flags = 0; \
|
||||
res->poolObjects = 0; \
|
||||
res->subObjects = 0; \
|
||||
res->superObjects = 0; \
|
||||
res->userPtr = 0; \
|
||||
return reinterpret_cast<type>(res); \
|
||||
} \
|
||||
|
||||
#define GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_U64_IMPL(type) \
|
||||
type new_from_host_u64_##type(uint64_t underlying) { \
|
||||
struct goldfish_##type* res = \
|
||||
static_cast<goldfish_##type*>(malloc(sizeof(goldfish_##type))); \
|
||||
res->underlying = underlying; \
|
||||
D("guest %p: host u64: 0x%llx", res, (unsigned long long)res->underlying); \
|
||||
res->poolObjects = 0; \
|
||||
res->subObjects = 0; \
|
||||
res->superObjects = 0; \
|
||||
res->userPtr = 0; \
|
||||
return reinterpret_cast<type>(res); \
|
||||
} \
|
||||
|
||||
#define GOLDFISH_VK_GET_HOST_U64_IMPL(type) \
|
||||
uint64_t get_host_u64_##type(type toUnwrap) { \
|
||||
if (!toUnwrap) return 0; \
|
||||
auto as_goldfish = as_goldfish_##type(toUnwrap); \
|
||||
D("guest %p: host u64: 0x%llx", toUnwrap, (unsigned long long)as_goldfish->underlying); \
|
||||
return as_goldfish->underlying; \
|
||||
} \
|
||||
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_IMPL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_IMPL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_IMPL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DELETE_GOLDFISH_IMPL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_IDENTITY_IMPL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_U64_IMPL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_U64_IMPL)
|
||||
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_IMPL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_IMPL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_IDENTITY_IMPL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_U64_IMPL)
|
||||
GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_IMPL)
|
||||
GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_TRIVIAL_NON_DISPATCHABLE_FROM_HOST_U64_IMPL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DELETE_GOLDFISH_IMPL)
|
||||
|
||||
VkDescriptorPool new_from_host_VkDescriptorPool(VkDescriptorPool underlying) {
|
||||
struct goldfish_VkDescriptorPool* res =
|
||||
static_cast<goldfish_VkDescriptorPool*>(malloc(sizeof(goldfish_VkDescriptorPool)));
|
||||
res->underlying = (uint64_t)underlying;
|
||||
res->allocInfo = nullptr;
|
||||
return reinterpret_cast<VkDescriptorPool>(res);
|
||||
}
|
||||
|
||||
VkDescriptorPool new_from_host_u64_VkDescriptorPool(uint64_t underlying) {
|
||||
return new_from_host_VkDescriptorPool((VkDescriptorPool)underlying);
|
||||
}
|
||||
|
||||
VkDescriptorSet new_from_host_VkDescriptorSet(VkDescriptorSet underlying) {
|
||||
struct goldfish_VkDescriptorSet* res =
|
||||
static_cast<goldfish_VkDescriptorSet*>(malloc(sizeof(goldfish_VkDescriptorSet)));
|
||||
res->underlying = (uint64_t)underlying;
|
||||
res->reified = nullptr;
|
||||
return reinterpret_cast<VkDescriptorSet>(res);
|
||||
}
|
||||
|
||||
VkDescriptorSet new_from_host_u64_VkDescriptorSet(uint64_t underlying) {
|
||||
return new_from_host_VkDescriptorSet((VkDescriptorSet)underlying);
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout new_from_host_VkDescriptorSetLayout(VkDescriptorSetLayout underlying) {
|
||||
struct goldfish_VkDescriptorSetLayout* res =
|
||||
static_cast<goldfish_VkDescriptorSetLayout*>(malloc(sizeof(goldfish_VkDescriptorSetLayout)));
|
||||
res->underlying = (uint64_t)underlying;
|
||||
res->layoutInfo = nullptr;
|
||||
return reinterpret_cast<VkDescriptorSetLayout>(res);
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout new_from_host_u64_VkDescriptorSetLayout(uint64_t underlying) {
|
||||
return new_from_host_VkDescriptorSetLayout((VkDescriptorSetLayout)underlying);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
void appendObject(struct goldfish_vk_object_list** begin, void* val) {
|
||||
D("for %p", val);
|
||||
struct goldfish_vk_object_list* o = new goldfish_vk_object_list;
|
||||
o->next = nullptr;
|
||||
o->obj = val;
|
||||
D("new ptr: %p", o);
|
||||
if (!*begin) { D("first"); *begin = o; return; }
|
||||
|
||||
struct goldfish_vk_object_list* q = *begin;
|
||||
struct goldfish_vk_object_list* p = q;
|
||||
|
||||
while (q) {
|
||||
p = q;
|
||||
q = q->next;
|
||||
}
|
||||
|
||||
D("set next of %p to %p", p, o);
|
||||
p->next = o;
|
||||
}
|
||||
|
||||
void eraseObject(struct goldfish_vk_object_list** begin, void* val) {
|
||||
D("for val %p", val);
|
||||
if (!*begin) {
|
||||
D("val %p notfound", val);
|
||||
return;
|
||||
}
|
||||
|
||||
struct goldfish_vk_object_list* q = *begin;
|
||||
struct goldfish_vk_object_list* p = q;
|
||||
|
||||
while (q) {
|
||||
struct goldfish_vk_object_list* n = q->next;
|
||||
if (val == q->obj) {
|
||||
D("val %p found, delete", val);
|
||||
delete q;
|
||||
if (*begin == q) {
|
||||
D("val %p set begin to %p:", val, n);
|
||||
*begin = n;
|
||||
} else {
|
||||
D("val %p set pnext to %p:", val, n);
|
||||
p->next = n;
|
||||
}
|
||||
return;
|
||||
}
|
||||
p = q;
|
||||
q = n;
|
||||
}
|
||||
|
||||
D("val %p notfound after looping", val);
|
||||
}
|
||||
|
||||
void eraseObjects(struct goldfish_vk_object_list** begin) {
|
||||
struct goldfish_vk_object_list* q = *begin;
|
||||
struct goldfish_vk_object_list* p = q;
|
||||
|
||||
while (q) {
|
||||
p = q;
|
||||
q = q->next;
|
||||
delete p;
|
||||
}
|
||||
|
||||
*begin = nullptr;
|
||||
}
|
||||
|
||||
void forAllObjects(struct goldfish_vk_object_list* begin, std::function<void(void*)> func) {
|
||||
struct goldfish_vk_object_list* q = begin;
|
||||
struct goldfish_vk_object_list* p = q;
|
||||
|
||||
D("call");
|
||||
while (q) {
|
||||
D("iter");
|
||||
p = q;
|
||||
q = q->next;
|
||||
func(p->obj);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,148 @@
|
||||
// Copyright (C) 2018 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.
|
||||
#pragma once
|
||||
|
||||
#include <hardware/hwvulkan.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "VulkanHandles.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace gfxstream {
|
||||
class IOStream;
|
||||
namespace vk {
|
||||
class VkEncoder;
|
||||
struct DescriptorPoolAllocationInfo;
|
||||
struct ReifiedDescriptorSet;
|
||||
struct DescriptorSetLayoutInfo;
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct goldfish_vk_object_list {
|
||||
void* obj;
|
||||
struct goldfish_vk_object_list* next;
|
||||
};
|
||||
|
||||
#define GOLDFISH_VK_DEFINE_DISPATCHABLE_HANDLE_STRUCT(type) \
|
||||
struct goldfish_##type { \
|
||||
hwvulkan_dispatch_t dispatch; \
|
||||
uint64_t underlying; \
|
||||
gfxstream::vk::VkEncoder* lastUsedEncoder; \
|
||||
uint32_t sequenceNumber; \
|
||||
gfxstream::vk::VkEncoder* privateEncoder; \
|
||||
gfxstream::IOStream* privateStream; \
|
||||
uint32_t flags; \
|
||||
struct goldfish_vk_object_list* poolObjects; \
|
||||
struct goldfish_vk_object_list* subObjects; \
|
||||
struct goldfish_vk_object_list* superObjects; \
|
||||
void* userPtr; \
|
||||
}; \
|
||||
|
||||
#define GOLDFISH_VK_DEFINE_TRIVIAL_NON_DISPATCHABLE_HANDLE_STRUCT(type) \
|
||||
struct goldfish_##type { \
|
||||
uint64_t underlying; \
|
||||
struct goldfish_vk_object_list* poolObjects; \
|
||||
struct goldfish_vk_object_list* subObjects; \
|
||||
struct goldfish_vk_object_list* superObjects; \
|
||||
void* userPtr; \
|
||||
}; \
|
||||
|
||||
#define GOLDFISH_VK_NEW_FROM_HOST_DECL(type) \
|
||||
type new_from_host_##type(type);
|
||||
|
||||
#define GOLDFISH_VK_AS_GOLDFISH_DECL(type) \
|
||||
struct goldfish_##type* as_goldfish_##type(type);
|
||||
|
||||
#define GOLDFISH_VK_GET_HOST_DECL(type) \
|
||||
type get_host_##type(type);
|
||||
|
||||
#define GOLDFISH_VK_DELETE_GOLDFISH_DECL(type) \
|
||||
void delete_goldfish_##type(type);
|
||||
|
||||
#define GOLDFISH_VK_IDENTITY_DECL(type) \
|
||||
type vk_handle_identity_##type(type);
|
||||
|
||||
#define GOLDFISH_VK_NEW_FROM_HOST_U64_DECL(type) \
|
||||
type new_from_host_u64_##type(uint64_t);
|
||||
|
||||
#define GOLDFISH_VK_GET_HOST_U64_DECL(type) \
|
||||
uint64_t get_host_u64_##type(type);
|
||||
|
||||
GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DEFINE_DISPATCHABLE_HANDLE_STRUCT)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_FROM_HOST_DECL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_DECL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_DECL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DELETE_GOLDFISH_DECL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_IDENTITY_DECL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_FROM_HOST_U64_DECL)
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_U64_DECL)
|
||||
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_FROM_HOST_DECL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_AS_GOLDFISH_DECL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_DECL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DELETE_GOLDFISH_DECL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_IDENTITY_DECL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_NEW_FROM_HOST_U64_DECL)
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_GET_HOST_U64_DECL)
|
||||
GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(GOLDFISH_VK_DEFINE_TRIVIAL_NON_DISPATCHABLE_HANDLE_STRUCT)
|
||||
|
||||
struct goldfish_VkDescriptorPool {
|
||||
uint64_t underlying;
|
||||
gfxstream::vk::DescriptorPoolAllocationInfo* allocInfo;
|
||||
};
|
||||
|
||||
struct goldfish_VkDescriptorSet {
|
||||
uint64_t underlying;
|
||||
gfxstream::vk::ReifiedDescriptorSet* reified;
|
||||
};
|
||||
|
||||
struct goldfish_VkDescriptorSetLayout {
|
||||
uint64_t underlying;
|
||||
gfxstream::vk::DescriptorSetLayoutInfo* layoutInfo;
|
||||
};
|
||||
|
||||
struct goldfish_VkCommandBuffer {
|
||||
hwvulkan_dispatch_t dispatch;
|
||||
uint64_t underlying;
|
||||
gfxstream::vk::VkEncoder* lastUsedEncoder;
|
||||
uint32_t sequenceNumber;
|
||||
gfxstream::vk::VkEncoder* privateEncoder;
|
||||
gfxstream::IOStream* privateStream;
|
||||
uint32_t flags;
|
||||
struct goldfish_vk_object_list* poolObjects;
|
||||
struct goldfish_vk_object_list* subObjects;
|
||||
struct goldfish_vk_object_list* superObjects;
|
||||
void* userPtr;
|
||||
bool isSecondary;
|
||||
VkDevice device;
|
||||
};
|
||||
|
||||
} // extern "C"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
void appendObject(struct goldfish_vk_object_list** begin, void* val);
|
||||
void eraseObject(struct goldfish_vk_object_list** begin, void* val);
|
||||
void eraseObjects(struct goldfish_vk_object_list** begin);
|
||||
void forAllObjects(struct goldfish_vk_object_list* begin, std::function<void(void*)> func);
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2018 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 "Validation.h"
|
||||
|
||||
#include "Resources.h"
|
||||
#include "ResourceTracker.h"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
VkResult Validation::on_vkFlushMappedMemoryRanges(
|
||||
void*,
|
||||
VkResult,
|
||||
VkDevice,
|
||||
uint32_t memoryRangeCount,
|
||||
const VkMappedMemoryRange* pMemoryRanges) {
|
||||
|
||||
auto resources = ResourceTracker::get();
|
||||
|
||||
for (uint32_t i = 0; i < memoryRangeCount; ++i) {
|
||||
if (!resources->isValidMemoryRange(pMemoryRanges[i])) {
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult Validation::on_vkInvalidateMappedMemoryRanges(
|
||||
void*,
|
||||
VkResult,
|
||||
VkDevice,
|
||||
uint32_t memoryRangeCount,
|
||||
const VkMappedMemoryRange* pMemoryRanges) {
|
||||
|
||||
auto resources = ResourceTracker::get();
|
||||
|
||||
for (uint32_t i = 0; i < memoryRangeCount; ++i) {
|
||||
if (!resources->isValidMemoryRange(pMemoryRanges[i])) {
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2018 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.
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
class Validation {
|
||||
public:
|
||||
VkResult on_vkFlushMappedMemoryRanges(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
uint32_t memoryRangeCount,
|
||||
const VkMappedMemoryRange* pMemoryRanges);
|
||||
VkResult on_vkInvalidateMappedMemoryRanges(
|
||||
void* context,
|
||||
VkResult input_result,
|
||||
VkDevice device,
|
||||
uint32_t memoryRangeCount,
|
||||
const VkMappedMemoryRange* pMemoryRanges);
|
||||
};
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,90 @@
|
||||
static ResourceTracker* sResourceTracker = nullptr;
|
||||
static uint32_t sFeatureBits = 0;
|
||||
static constexpr uint32_t kWatchdogBufferMax = 1'000;
|
||||
|
||||
class VkEncoder::Impl {
|
||||
public:
|
||||
Impl(IOStream* stream) : m_stream(stream), m_logEncodes(false) {
|
||||
if (!sResourceTracker) sResourceTracker = ResourceTracker::get();
|
||||
m_stream.incStreamRef();
|
||||
const char* emuVkLogEncodesPropName = "qemu.vk.log";
|
||||
char encodeProp[PROPERTY_VALUE_MAX];
|
||||
if (property_get(emuVkLogEncodesPropName, encodeProp, nullptr) > 0) {
|
||||
m_logEncodes = atoi(encodeProp) > 0;
|
||||
}
|
||||
sFeatureBits = m_stream.getFeatureBits();
|
||||
}
|
||||
|
||||
~Impl() { m_stream.decStreamRef(); }
|
||||
|
||||
VulkanCountingStream* countingStream() { return &m_countingStream; }
|
||||
VulkanStreamGuest* stream() { return &m_stream; }
|
||||
BumpPool* pool() { return &m_pool; }
|
||||
ResourceTracker* resources() { return ResourceTracker::get(); }
|
||||
Validation* validation() { return &m_validation; }
|
||||
|
||||
void log(const char* text) {
|
||||
if (!m_logEncodes) return;
|
||||
ALOGD("encoder log: %s", text);
|
||||
}
|
||||
|
||||
void flush() {
|
||||
lock();
|
||||
m_stream.flush();
|
||||
unlock();
|
||||
}
|
||||
|
||||
// can be recursive
|
||||
void lock() {
|
||||
while (mLock.test_and_set(std::memory_order_acquire))
|
||||
;
|
||||
}
|
||||
|
||||
void unlock() { mLock.clear(std::memory_order_release); }
|
||||
|
||||
private:
|
||||
VulkanCountingStream m_countingStream;
|
||||
VulkanStreamGuest m_stream;
|
||||
BumpPool m_pool;
|
||||
|
||||
Validation m_validation;
|
||||
bool m_logEncodes;
|
||||
std::atomic_flag mLock = ATOMIC_FLAG_INIT;
|
||||
};
|
||||
|
||||
VkEncoder::~VkEncoder() {}
|
||||
|
||||
struct EncoderAutoLock {
|
||||
EncoderAutoLock(VkEncoder* enc) : mEnc(enc) { mEnc->lock(); }
|
||||
~EncoderAutoLock() { mEnc->unlock(); }
|
||||
VkEncoder* mEnc;
|
||||
};
|
||||
|
||||
VkEncoder::VkEncoder(IOStream* stream, android::base::guest::HealthMonitor<>* healthMonitor)
|
||||
: mImpl(new VkEncoder::Impl(stream)), mHealthMonitor(healthMonitor) {}
|
||||
|
||||
void VkEncoder::flush() { mImpl->flush(); }
|
||||
|
||||
void VkEncoder::lock() { mImpl->lock(); }
|
||||
|
||||
void VkEncoder::unlock() { mImpl->unlock(); }
|
||||
|
||||
void VkEncoder::incRef() { __atomic_add_fetch(&refCount, 1, __ATOMIC_SEQ_CST); }
|
||||
|
||||
bool VkEncoder::decRef() {
|
||||
if (0 == __atomic_sub_fetch(&refCount, 1, __ATOMIC_SEQ_CST)) {
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string VkEncoder::getPacketContents(const uint8_t* ptr, size_t len) {
|
||||
std::string result;
|
||||
std::unique_ptr<char[]> buf(new char[3]);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
std::snprintf(buf.get(), 3, "%02X", ptr[i]);
|
||||
result += " " + std::string(buf.get(), buf.get() + 2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
void flush();
|
||||
void lock();
|
||||
void unlock();
|
||||
void incRef();
|
||||
bool decRef();
|
||||
std::string getPacketContents(const uint8_t* ptr, size_t len);
|
||||
uint32_t refCount = 1;
|
||||
#define POOL_CLEAR_INTERVAL 10
|
||||
uint32_t encodeCount = 0;
|
||||
uint32_t featureBits = 0;
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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.
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "VulkanHandleMapping.h"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
#define DEFAULT_HANDLE_MAP_DEFINE(type) \
|
||||
void DefaultHandleMapping::mapHandles_##type(type*, size_t) { return; } \
|
||||
void DefaultHandleMapping::mapHandles_##type##_u64(const type* handles, uint64_t* handle_u64s, size_t count) { \
|
||||
for (size_t i = 0; i < count; ++i) { handle_u64s[i] = (uint64_t)(uintptr_t)handles[i]; } \
|
||||
} \
|
||||
void DefaultHandleMapping::mapHandles_u64_##type(const uint64_t* handle_u64s, type* handles, size_t count) { \
|
||||
for (size_t i = 0; i < count; ++i) { handles[i] = (type)(uintptr_t)handle_u64s[i]; } \
|
||||
} \
|
||||
|
||||
GOLDFISH_VK_LIST_HANDLE_TYPES(DEFAULT_HANDLE_MAP_DEFINE)
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// 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 "VulkanHandles.h"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
class VulkanHandleMapping {
|
||||
public:
|
||||
VulkanHandleMapping() = default;
|
||||
virtual ~VulkanHandleMapping() { }
|
||||
|
||||
#define DECLARE_HANDLE_MAP_PURE_VIRTUAL_METHOD(type) \
|
||||
virtual void mapHandles_##type(type* handles, size_t count = 1) = 0; \
|
||||
virtual void mapHandles_##type##_u64(const type* handles, uint64_t* handle_u64s, size_t count = 1) = 0; \
|
||||
virtual void mapHandles_u64_##type(const uint64_t* handle_u64s, type* handles, size_t count = 1) = 0; \
|
||||
|
||||
GOLDFISH_VK_LIST_HANDLE_TYPES(DECLARE_HANDLE_MAP_PURE_VIRTUAL_METHOD)
|
||||
};
|
||||
|
||||
class DefaultHandleMapping : public VulkanHandleMapping {
|
||||
public:
|
||||
virtual ~DefaultHandleMapping() { }
|
||||
|
||||
#define DECLARE_HANDLE_MAP_OVERRIDE(type) \
|
||||
void mapHandles_##type(type* handles, size_t count) override; \
|
||||
void mapHandles_##type##_u64(const type* handles, uint64_t* handle_u64s, size_t count) override; \
|
||||
void mapHandles_u64_##type(const uint64_t* handle_u64s, type* handles, size_t count) override; \
|
||||
|
||||
GOLDFISH_VK_LIST_HANDLE_TYPES(DECLARE_HANDLE_MAP_OVERRIDE)
|
||||
};
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,172 @@
|
||||
// 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>
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
#define GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
f(VkPhysicalDevice) \
|
||||
|
||||
#define GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
f(VkInstance) \
|
||||
f(VkDevice) \
|
||||
f(VkCommandBuffer) \
|
||||
f(VkQueue) \
|
||||
GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f)
|
||||
|
||||
#ifdef VK_NVX_binary_import
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_BINARY_IMPORT(f) \
|
||||
f(VkCuModuleNVX) \
|
||||
f(VkCuFunctionNVX) \
|
||||
|
||||
#else
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_BINARY_IMPORT(f)
|
||||
|
||||
#endif // VK_NVX_binary_import
|
||||
|
||||
#ifdef VK_NVX_device_generated_commands
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_DEVICE_GENERATED_COMMANDS(f) \
|
||||
f(VkObjectTableNVX) \
|
||||
f(VkIndirectCommandsLayoutNVX) \
|
||||
|
||||
#else
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_DEVICE_GENERATED_COMMANDS(f)
|
||||
|
||||
#endif // VK_NVX_device_generated_commands
|
||||
|
||||
#ifdef VK_NV_device_generated_commands
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NV_DEVICE_GENERATED_COMMANDS(f) \
|
||||
f(VkIndirectCommandsLayoutNV) \
|
||||
|
||||
#else
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NV_DEVICE_GENERATED_COMMANDS(f)
|
||||
|
||||
#endif // VK_NV_device_generated_commands
|
||||
|
||||
#ifdef VK_NV_ray_tracing
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NV_RAY_TRACING(f) \
|
||||
f(VkAccelerationStructureNV) \
|
||||
|
||||
#else
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NV_RAY_TRACING(f)
|
||||
|
||||
#endif // VK_NV_ray_tracing
|
||||
|
||||
#ifdef VK_KHR_acceleration_structure
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_KHR_ACCELERATION_STRUCTURE(f) \
|
||||
f(VkAccelerationStructureKHR) \
|
||||
|
||||
#else
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_KHR_ACCELERATION_STRUCTURE(f)
|
||||
|
||||
#endif // VK_KHR_acceleration_structure
|
||||
|
||||
#ifdef VK_USE_PLATFORM_FUCHSIA
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_FUCHSIA(f) \
|
||||
f(VkBufferCollectionFUCHSIA)
|
||||
|
||||
#else
|
||||
|
||||
#define __GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_FUCHSIA(f)
|
||||
|
||||
#endif // VK_USE_PLATFORM_FUCHSIA
|
||||
|
||||
#define GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
f(VkBufferView) \
|
||||
f(VkImageView) \
|
||||
f(VkShaderModule) \
|
||||
f(VkPipeline) \
|
||||
f(VkPipelineCache) \
|
||||
f(VkPipelineLayout) \
|
||||
f(VkRenderPass) \
|
||||
f(VkFramebuffer) \
|
||||
f(VkEvent) \
|
||||
f(VkQueryPool) \
|
||||
f(VkSamplerYcbcrConversion) \
|
||||
f(VkSurfaceKHR) \
|
||||
f(VkSwapchainKHR) \
|
||||
f(VkDisplayKHR) \
|
||||
f(VkDisplayModeKHR) \
|
||||
f(VkValidationCacheEXT) \
|
||||
f(VkDebugReportCallbackEXT) \
|
||||
f(VkDebugUtilsMessengerEXT) \
|
||||
__GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_BINARY_IMPORT(f) \
|
||||
__GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NVX_DEVICE_GENERATED_COMMANDS(f) \
|
||||
__GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NV_DEVICE_GENERATED_COMMANDS(f) \
|
||||
__GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_NV_RAY_TRACING(f) \
|
||||
__GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_KHR_ACCELERATION_STRUCTURE(f) \
|
||||
|
||||
#define GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
f(VkDeviceMemory) \
|
||||
f(VkBuffer) \
|
||||
f(VkImage) \
|
||||
f(VkSemaphore) \
|
||||
f(VkDescriptorUpdateTemplate) \
|
||||
f(VkFence) \
|
||||
f(VkDescriptorPool) \
|
||||
f(VkDescriptorSet) \
|
||||
f(VkDescriptorSetLayout) \
|
||||
f(VkCommandPool) \
|
||||
f(VkSampler) \
|
||||
__GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_FUCHSIA(f) \
|
||||
GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
|
||||
#define GOLDFISH_VK_LIST_HANDLE_TYPES(f) \
|
||||
GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(f)
|
||||
|
||||
#define GOLDFISH_VK_LIST_TRIVIAL_HANDLE_TYPES(f) \
|
||||
GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f)
|
||||
|
||||
#define GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
f(VkInstance) \
|
||||
f(VkDevice) \
|
||||
f(VkQueue) \
|
||||
GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f)
|
||||
|
||||
#define GOLDFISH_VK_LIST_AUTODEFINED_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
f(VkDeviceMemory) \
|
||||
f(VkBuffer) \
|
||||
f(VkImage) \
|
||||
f(VkSemaphore) \
|
||||
f(VkFence) \
|
||||
f(VkDescriptorUpdateTemplate) \
|
||||
f(VkCommandPool) \
|
||||
f(VkSampler) \
|
||||
__GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES_FUCHSIA(f) \
|
||||
GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
|
||||
#define GOLDFISH_VK_LIST_MANUAL_STRUCT_NON_DISPATCHABLE_HANDLE_TYPES(f) \
|
||||
f(VkDescriptorPool) \
|
||||
f(VkDescriptorSetLayout) \
|
||||
f(VkDescriptorSet) \
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2018 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 "VulkanStreamGuest.h"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
VulkanStreamGuest::VulkanStreamGuest(IOStream *stream): mStream(stream) {
|
||||
unsetHandleMapping();
|
||||
mFeatureBits = ResourceTracker::get()->getStreamFeatures();
|
||||
}
|
||||
|
||||
VulkanStreamGuest::~VulkanStreamGuest() = default;
|
||||
|
||||
bool VulkanStreamGuest::valid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::alloc(void** ptrAddr, size_t bytes) {
|
||||
if (!bytes) {
|
||||
*ptrAddr = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
*ptrAddr = mPool.alloc(bytes);
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::loadStringInPlace(char** forOutput) {
|
||||
size_t len = getBe32();
|
||||
|
||||
alloc((void**)forOutput, len + 1);
|
||||
|
||||
memset(*forOutput, 0x0, len + 1);
|
||||
|
||||
if (len > 0) read(*forOutput, len);
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::loadStringArrayInPlace(char*** forOutput) {
|
||||
size_t count = getBe32();
|
||||
|
||||
if (!count) {
|
||||
*forOutput = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
alloc((void**)forOutput, count * sizeof(char*));
|
||||
|
||||
char **stringsForOutput = *forOutput;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
loadStringInPlace(stringsForOutput + i);
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::loadStringInPlaceWithStreamPtr(char** forOutput, uint8_t** streamPtr) {
|
||||
uint32_t len;
|
||||
memcpy(&len, *streamPtr, sizeof(uint32_t));
|
||||
*streamPtr += sizeof(uint32_t);
|
||||
android::base::Stream::fromBe32((uint8_t*)&len);
|
||||
|
||||
alloc((void**)forOutput, len + 1);
|
||||
|
||||
memset(*forOutput, 0x0, len + 1);
|
||||
|
||||
if (len > 0) {
|
||||
memcpy(*forOutput, *streamPtr, len);
|
||||
*streamPtr += len;
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::loadStringArrayInPlaceWithStreamPtr(char*** forOutput, uint8_t** streamPtr) {
|
||||
uint32_t count;
|
||||
memcpy(&count, *streamPtr, sizeof(uint32_t));
|
||||
*streamPtr += sizeof(uint32_t);
|
||||
android::base::Stream::fromBe32((uint8_t*)&count);
|
||||
if (!count) {
|
||||
*forOutput = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
alloc((void**)forOutput, count * sizeof(char*));
|
||||
|
||||
char **stringsForOutput = *forOutput;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
loadStringInPlaceWithStreamPtr(stringsForOutput + i, streamPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ssize_t VulkanStreamGuest::read(void *buffer, size_t size) {
|
||||
if (!mStream->readback(buffer, size)) {
|
||||
ALOGE("FATAL: Could not read back %zu bytes", size);
|
||||
abort();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
ssize_t VulkanStreamGuest::write(const void *buffer, size_t size) {
|
||||
uint8_t* streamBuf = (uint8_t*)mStream->alloc(size);
|
||||
memcpy(streamBuf, buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::writeLarge(const void* buffer, size_t size) {
|
||||
mStream->writeFullyAsync(buffer, size);
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::clearPool() {
|
||||
mPool.freeAll();
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::setHandleMapping(VulkanHandleMapping* mapping) {
|
||||
mCurrentHandleMapping = mapping;
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::unsetHandleMapping() {
|
||||
mCurrentHandleMapping = &mDefaultHandleMapping;
|
||||
}
|
||||
|
||||
VulkanHandleMapping* VulkanStreamGuest::handleMapping() const {
|
||||
return mCurrentHandleMapping;
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::flush() {
|
||||
AEMU_SCOPED_TRACE("VulkanStreamGuest device write");
|
||||
mStream->flush();
|
||||
}
|
||||
|
||||
uint32_t VulkanStreamGuest::getFeatureBits() const {
|
||||
return mFeatureBits;
|
||||
}
|
||||
|
||||
void VulkanStreamGuest::incStreamRef() {
|
||||
mStream->incRef();
|
||||
}
|
||||
|
||||
bool VulkanStreamGuest::decStreamRef() {
|
||||
return mStream->decRef();
|
||||
}
|
||||
|
||||
uint8_t* VulkanStreamGuest::reserve(size_t size) {
|
||||
return (uint8_t*)mStream->alloc(size);
|
||||
}
|
||||
|
||||
VulkanCountingStream::VulkanCountingStream() : VulkanStreamGuest(nullptr) { }
|
||||
VulkanCountingStream::~VulkanCountingStream() = default;
|
||||
|
||||
ssize_t VulkanCountingStream::read(void*, size_t size) {
|
||||
m_read += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
ssize_t VulkanCountingStream::write(const void*, size_t size) {
|
||||
m_written += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
void VulkanCountingStream::rewind() {
|
||||
m_written = 0;
|
||||
m_read = 0;
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright (C) 2018 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.
|
||||
#pragma once
|
||||
|
||||
#include "aemu/base/files/Stream.h"
|
||||
#include "aemu/base/files/StreamSerializing.h"
|
||||
|
||||
#include "goldfish_vk_private_defs.h"
|
||||
|
||||
#include "VulkanHandleMapping.h"
|
||||
|
||||
#include "IOStream.h"
|
||||
#include "ResourceTracker.h"
|
||||
|
||||
#include "aemu/base/BumpPool.h"
|
||||
#include "aemu/base/Tracing.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include <log/log.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
class IOStream;
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
class VulkanStreamGuest : public android::base::Stream {
|
||||
public:
|
||||
VulkanStreamGuest(IOStream* stream);
|
||||
~VulkanStreamGuest();
|
||||
|
||||
// Returns whether the connection is valid.
|
||||
bool valid();
|
||||
|
||||
// General allocation function
|
||||
void alloc(void** ptrAddr, size_t bytes);
|
||||
|
||||
// Utility functions to load strings or
|
||||
// string arrays in place with allocation.
|
||||
void loadStringInPlace(char** forOutput);
|
||||
void loadStringArrayInPlace(char*** forOutput);
|
||||
|
||||
// When we load a string and are using a reserved pointer.
|
||||
void loadStringInPlaceWithStreamPtr(char** forOutput, uint8_t** streamPtr);
|
||||
void loadStringArrayInPlaceWithStreamPtr(char*** forOutput, uint8_t** streamPtr);
|
||||
|
||||
ssize_t read(void *buffer, size_t size) override;
|
||||
ssize_t write(const void *buffer, size_t size) override;
|
||||
|
||||
void writeLarge(const void* buffer, size_t size);
|
||||
|
||||
// Frees everything that got alloc'ed.
|
||||
void clearPool();
|
||||
|
||||
void setHandleMapping(VulkanHandleMapping* mapping);
|
||||
void unsetHandleMapping();
|
||||
VulkanHandleMapping* handleMapping() const;
|
||||
|
||||
void flush();
|
||||
|
||||
uint32_t getFeatureBits() const;
|
||||
|
||||
void incStreamRef();
|
||||
bool decStreamRef();
|
||||
|
||||
uint8_t* reserve(size_t size);
|
||||
private:
|
||||
android::base::BumpPool mPool;
|
||||
std::vector<uint8_t> mWriteBuffer;
|
||||
IOStream* mStream = nullptr;
|
||||
DefaultHandleMapping mDefaultHandleMapping;
|
||||
VulkanHandleMapping* mCurrentHandleMapping;
|
||||
uint32_t mFeatureBits = 0;
|
||||
};
|
||||
|
||||
class VulkanCountingStream : public VulkanStreamGuest {
|
||||
public:
|
||||
VulkanCountingStream();
|
||||
~VulkanCountingStream();
|
||||
|
||||
ssize_t read(void *buffer, size_t size) override;
|
||||
ssize_t write(const void *buffer, size_t size) override;
|
||||
|
||||
size_t bytesWritten() const { return m_written; }
|
||||
size_t bytesRead() const { return m_read; }
|
||||
|
||||
void rewind();
|
||||
private:
|
||||
size_t m_written = 0;
|
||||
size_t m_read = 0;
|
||||
};
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
// VulkanStream features
|
||||
#define VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT (1 << 0)
|
||||
#define VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT (1 << 1)
|
||||
#define VULKAN_STREAM_FEATURE_SHADER_FLOAT16_INT8_BIT (1 << 2)
|
||||
#define VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT (1 << 3)
|
||||
|
||||
#define VK_YCBCR_CONVERSION_DO_NOTHING ((VkSamplerYcbcrConversion)0x1111111111111111)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
template<class T, typename F>
|
||||
bool arrayany(const T* arr, uint32_t begin, uint32_t end, const F& func) {
|
||||
const T* e = arr + end;
|
||||
return std::find_if(arr + begin, e, func) != e;
|
||||
}
|
||||
|
||||
#define DEFINE_ALIAS_FUNCTION(ORIGINAL_FN, ALIAS_FN) \
|
||||
template <typename... Args> \
|
||||
inline auto ALIAS_FN(Args&&... args) -> decltype(ORIGINAL_FN(std::forward<Args>(args)...)) { \
|
||||
return ORIGINAL_FN(std::forward<Args>(args)...); \
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
# Copyright 2022 Android Open Source Project
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
files_lib_vulkan_enc = files(
|
||||
'CommandBufferStagingStream.cpp',
|
||||
'DescriptorSetVirtualization.cpp',
|
||||
'HostVisibleMemoryVirtualization.cpp',
|
||||
'ResourceTracker.cpp',
|
||||
'Resources.cpp',
|
||||
'Validation.cpp',
|
||||
'VkEncoder.cpp',
|
||||
'VulkanHandleMapping.cpp',
|
||||
'VulkanStreamGuest.cpp',
|
||||
'func_table.cpp',
|
||||
'goldfish_vk_counting_guest.cpp',
|
||||
'goldfish_vk_counting_guest.h',
|
||||
'goldfish_vk_deepcopy_guest.cpp',
|
||||
'goldfish_vk_extension_structs_guest.cpp',
|
||||
'goldfish_vk_marshaling_guest.cpp',
|
||||
'goldfish_vk_reserved_marshaling_guest.cpp',
|
||||
'goldfish_vk_transform_guest.cpp',
|
||||
)
|
||||
|
||||
lib_vulkan_enc = static_library(
|
||||
'vulkan_enc',
|
||||
files_lib_vulkan_enc,
|
||||
cpp_args: cpp_args,
|
||||
include_directories: [inc_android_emu, inc_host, inc_android_compat,
|
||||
inc_opengl_codec, inc_render_enc, inc_system,
|
||||
inc_goldfish_address_space, inc_platform],
|
||||
link_with: [lib_platform],
|
||||
dependencies: dependency('libdrm'),
|
||||
)
|
||||
@@ -0,0 +1,67 @@
|
||||
// Manual inline for
|
||||
// void VkEncoder::vkQueueFlushCommandsGOOGLE( VkQueue queue, VkCommandBuffer commandBuffer, VkDeviceSize dataSize, const void* pData, uint32_t doLock);
|
||||
|
||||
// We won't use the lock if this command is used (VulkanQueueSubmitWithCommands is enabled)
|
||||
(void)doLock;
|
||||
|
||||
auto stream = mImpl->stream();
|
||||
auto pool = mImpl->pool();
|
||||
VkQueue local_queue;
|
||||
VkCommandBuffer local_commandBuffer;
|
||||
VkDeviceSize local_dataSize;
|
||||
void* local_pData;
|
||||
local_queue = queue;
|
||||
local_commandBuffer = commandBuffer;
|
||||
local_dataSize = dataSize;
|
||||
// Avoiding deepcopy for pData
|
||||
local_pData = (void*)pData;
|
||||
size_t count = 0;
|
||||
size_t* countPtr = &count;
|
||||
{
|
||||
uint64_t cgen_var_1405;
|
||||
*countPtr += 1 * 8;
|
||||
uint64_t cgen_var_1406;
|
||||
*countPtr += 1 * 8;
|
||||
*countPtr += sizeof(VkDeviceSize);
|
||||
*countPtr += ((dataSize)) * sizeof(uint8_t);
|
||||
}
|
||||
bool queueSubmitWithCommandsEnabled = sFeatureBits & VULKAN_STREAM_FEATURE_QUEUE_SUBMIT_WITH_COMMANDS_BIT;
|
||||
uint32_t packetSize_vkQueueFlushCommandsGOOGLE = 4 + 4 + (queueSubmitWithCommandsEnabled ? 4 : 0) + count;
|
||||
healthMonitorAnnotation_packetSize =
|
||||
std::make_optional(packetSize_vkQueueFlushCommandsGOOGLE);
|
||||
uint8_t* streamPtr = stream->reserve(packetSize_vkQueueFlushCommandsGOOGLE - local_dataSize);
|
||||
uint8_t* packetBeginPtr = streamPtr;
|
||||
uint8_t** streamPtrPtr = &streamPtr;
|
||||
uint32_t opcode_vkQueueFlushCommandsGOOGLE = OP_vkQueueFlushCommandsGOOGLE;
|
||||
uint32_t seqno = ResourceTracker::nextSeqno();
|
||||
healthMonitorAnnotation_seqno = std::make_optional(seqno);
|
||||
memcpy(streamPtr, &opcode_vkQueueFlushCommandsGOOGLE, sizeof(uint32_t)); streamPtr += sizeof(uint32_t);
|
||||
memcpy(streamPtr, &packetSize_vkQueueFlushCommandsGOOGLE, sizeof(uint32_t)); streamPtr += sizeof(uint32_t);
|
||||
memcpy(streamPtr, &seqno, sizeof(uint32_t)); streamPtr += sizeof(uint32_t);
|
||||
uint64_t cgen_var_1407;
|
||||
*&cgen_var_1407 = get_host_u64_VkQueue((*&local_queue));
|
||||
memcpy(*streamPtrPtr, (uint64_t*)&cgen_var_1407, 1 * 8);
|
||||
*streamPtrPtr += 1 * 8;
|
||||
uint64_t cgen_var_1408;
|
||||
*&cgen_var_1408 = get_host_u64_VkCommandBuffer((*&local_commandBuffer));
|
||||
memcpy(*streamPtrPtr, (uint64_t*)&cgen_var_1408, 1 * 8);
|
||||
*streamPtrPtr += 1 * 8;
|
||||
memcpy(*streamPtrPtr, (VkDeviceSize*)&local_dataSize, sizeof(VkDeviceSize));
|
||||
*streamPtrPtr += sizeof(VkDeviceSize);
|
||||
if (watchdog) {
|
||||
size_t watchdogBufSize = std::min<size_t>(
|
||||
static_cast<size_t>(packetSize_vkQueueFlushCommandsGOOGLE), kWatchdogBufferMax);
|
||||
healthMonitorAnnotation_packetContents.resize(watchdogBufSize);
|
||||
memcpy(&healthMonitorAnnotation_packetContents[0], packetBeginPtr, watchdogBufSize);
|
||||
}
|
||||
|
||||
AEMU_SCOPED_TRACE("vkQueueFlush large xfer");
|
||||
stream->flush();
|
||||
stream->writeLarge(local_pData, dataSize);
|
||||
|
||||
++encodeCount;;
|
||||
if (0 == encodeCount % POOL_CLEAR_INTERVAL)
|
||||
{
|
||||
pool->freeAll();
|
||||
stream->clearPool();
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright © 2016 Intel Corporation
|
||||
* Copyright © 2019 The Android Open Source Project
|
||||
* Copyright © 2019 Google Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef VK_FORMAT_INFO_H
|
||||
#define VK_FORMAT_INFO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
#include <system/graphics.h>
|
||||
#else
|
||||
/* See system/graphics.h. */
|
||||
enum {
|
||||
HAL_PIXEL_FORMAT_YV12 = 842094169,
|
||||
};
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vndk/hardware_buffer.h>
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
/* See i915_private_android_types.h in minigbm. */
|
||||
#define HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL 0x100
|
||||
|
||||
// TODO(b/167698976): We should not use OMX_COLOR_FormatYUV420Planar
|
||||
// but we seem to miss a format translation somewhere.
|
||||
|
||||
#define OMX_COLOR_FormatYUV420Planar 0x13
|
||||
|
||||
// TODO: update users of this function to query the DRM fourcc
|
||||
// code using the standard Gralloc4 metadata type and instead
|
||||
// translate the DRM fourcc code to a Vulkan format as Android
|
||||
// formats such as AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 could be
|
||||
// either VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM or
|
||||
// VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
|
||||
static inline VkFormat
|
||||
vk_format_from_android(unsigned android_format)
|
||||
{
|
||||
switch (android_format) {
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
|
||||
return VK_FORMAT_R8G8B8_UNORM;
|
||||
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
|
||||
return VK_FORMAT_R5G6B5_UNORM_PACK16;
|
||||
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
|
||||
return VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
|
||||
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL:
|
||||
case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
|
||||
return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
|
||||
#if __ANDROID_API__ >= 30
|
||||
case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
|
||||
return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
|
||||
#endif
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
case HAL_PIXEL_FORMAT_YV12:
|
||||
case OMX_COLOR_FormatYUV420Planar:
|
||||
return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
|
||||
case AHARDWAREBUFFER_FORMAT_BLOB:
|
||||
#endif
|
||||
default:
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
android_format_from_vk(VkFormat vk_format)
|
||||
{
|
||||
switch (vk_format) {
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
|
||||
case VK_FORMAT_R8G8B8_UNORM:
|
||||
return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
|
||||
case VK_FORMAT_R5G6B5_UNORM_PACK16:
|
||||
return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
|
||||
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
||||
return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
|
||||
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
|
||||
return HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL;
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
|
||||
return HAL_PIXEL_FORMAT_YV12;
|
||||
default:
|
||||
return AHARDWAREBUFFER_FORMAT_BLOB;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
android_format_is_yuv(unsigned android_format)
|
||||
{
|
||||
switch (android_format) {
|
||||
case AHARDWAREBUFFER_FORMAT_BLOB:
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
|
||||
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
|
||||
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
|
||||
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
|
||||
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
|
||||
case AHARDWAREBUFFER_FORMAT_D16_UNORM:
|
||||
case AHARDWAREBUFFER_FORMAT_D24_UNORM:
|
||||
case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
|
||||
case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
|
||||
case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
|
||||
case AHARDWAREBUFFER_FORMAT_S8_UINT:
|
||||
return false;
|
||||
case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL:
|
||||
case OMX_COLOR_FormatYUV420Planar:
|
||||
case HAL_PIXEL_FORMAT_YV12:
|
||||
#if __ANDROID_API__ >= 30
|
||||
case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
|
||||
#endif
|
||||
case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
|
||||
return true;
|
||||
default:
|
||||
ALOGE("%s: unhandled format: %d", __FUNCTION__, android_format);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline VkImageAspectFlags
|
||||
vk_format_aspects(VkFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case VK_FORMAT_UNDEFINED:
|
||||
return 0;
|
||||
|
||||
case VK_FORMAT_S8_UINT:
|
||||
return VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||
case VK_FORMAT_D32_SFLOAT:
|
||||
return VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
|
||||
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
|
||||
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
|
||||
case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
|
||||
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
|
||||
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
|
||||
case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
|
||||
case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
|
||||
case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
|
||||
case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
|
||||
return (VK_IMAGE_ASPECT_PLANE_0_BIT |
|
||||
VK_IMAGE_ASPECT_PLANE_1_BIT |
|
||||
VK_IMAGE_ASPECT_PLANE_2_BIT);
|
||||
|
||||
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
|
||||
case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
|
||||
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
|
||||
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
|
||||
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
|
||||
case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
|
||||
case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
|
||||
case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
|
||||
return (VK_IMAGE_ASPECT_PLANE_0_BIT |
|
||||
VK_IMAGE_ASPECT_PLANE_1_BIT);
|
||||
|
||||
default:
|
||||
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_color(VkFormat format)
|
||||
{
|
||||
return vk_format_aspects(format) == VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_is_depth_or_stencil(VkFormat format)
|
||||
{
|
||||
const VkImageAspectFlags aspects = vk_format_aspects(format);
|
||||
return aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
vk_format_has_depth(VkFormat format)
|
||||
{
|
||||
const VkImageAspectFlags aspects = vk_format_aspects(format);
|
||||
return aspects & VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
|
||||
#endif /* VK_FORMAT_INFO_H */
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2018 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.
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#if VK_HEADER_VERSION < 76
|
||||
|
||||
typedef struct VkBaseOutStructure {
|
||||
VkStructureType sType;
|
||||
struct VkBaseOutStructure* pNext;
|
||||
} VkBaseOutStructure;
|
||||
|
||||
typedef struct VkBaseInStructure {
|
||||
VkStructureType sType;
|
||||
const struct VkBaseInStructure* pNext;
|
||||
} VkBaseInStructure;
|
||||
|
||||
#endif // VK_HEADER_VERSION < 76
|
||||
@@ -0,0 +1,82 @@
|
||||
// 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"
|
||||
#include "vulkan_gfxstream.h"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
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; }
|
||||
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
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);
|
||||
#endif
|
||||
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);
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
REGISTER_VK_STRUCT_ID(VkNativeBufferANDROID, VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID);
|
||||
REGISTER_VK_STRUCT_ID(VkExternalFormatANDROID, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID);
|
||||
#endif
|
||||
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);
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
REGISTER_VK_STRUCT_ID(VkImportAndroidHardwareBufferInfoANDROID, VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID);
|
||||
#endif
|
||||
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_FUCHSIA
|
||||
REGISTER_VK_STRUCT_ID(VkImportMemoryBufferCollectionFUCHSIA, VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA);
|
||||
REGISTER_VK_STRUCT_ID(VkImportMemoryZirconHandleInfoFUCHSIA, VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA);
|
||||
REGISTER_VK_STRUCT_ID(VkBufferCollectionImageCreateInfoFUCHSIA, VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA);
|
||||
REGISTER_VK_STRUCT_ID(VkBufferCollectionBufferCreateInfoFUCHSIA, VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA);
|
||||
#endif // VK_USE_PLATFORM_FUCHSIA
|
||||
REGISTER_VK_STRUCT_ID(VkSamplerCreateInfo, VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
|
||||
REGISTER_VK_STRUCT_ID(VkSamplerCustomBorderColorCreateInfoEXT, VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);
|
||||
REGISTER_VK_STRUCT_ID(VkSamplerYcbcrConversionInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO);
|
||||
REGISTER_VK_STRUCT_ID(VkFenceCreateInfo, VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
|
||||
REGISTER_VK_STRUCT_ID(VkExportFenceCreateInfo, VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO);
|
||||
REGISTER_VK_STRUCT_ID(VkImportBufferGOOGLE, VK_STRUCTURE_TYPE_IMPORT_BUFFER_GOOGLE);
|
||||
REGISTER_VK_STRUCT_ID(VkCreateBlobGOOGLE, VK_STRUCTURE_TYPE_CREATE_BLOB_GOOGLE);
|
||||
REGISTER_VK_STRUCT_ID(VkExternalImageFormatProperties, VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
|
||||
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceImageFormatInfo2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2);
|
||||
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceExternalImageFormatInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO);
|
||||
REGISTER_VK_STRUCT_ID(VkSemaphoreTypeCreateInfo, VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO);
|
||||
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceFeatures2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2);
|
||||
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceProperties2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2);
|
||||
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceDeviceMemoryReportFeaturesEXT, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT);
|
||||
REGISTER_VK_STRUCT_ID(VkMemoryAllocateFlagsInfo, VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO);
|
||||
REGISTER_VK_STRUCT_ID(VkMemoryOpaqueCaptureAddressAllocateInfo, VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO);
|
||||
|
||||
#undef REGISTER_VK_STRUCT_ID
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright © 2017 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef VK_UTIL_H
|
||||
#define VK_UTIL_H
|
||||
|
||||
/* common inlines and macros for vulkan drivers */
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <stdlib.h>
|
||||
#include "vk_struct_id.h"
|
||||
|
||||
namespace gfxstream {
|
||||
namespace vk {
|
||||
|
||||
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)
|
||||
|
||||
#define vk_foreach_struct_const(__iter, __start) \
|
||||
for (const struct vk_struct_common *__iter = (const struct vk_struct_common *)(__start); \
|
||||
__iter; __iter = __iter->pNext)
|
||||
|
||||
/**
|
||||
* A wrapper for a Vulkan output array. A Vulkan output array is one that
|
||||
* follows the convention of the parameters to
|
||||
* vkGetPhysicalDeviceQueueFamilyProperties().
|
||||
*
|
||||
* Example Usage:
|
||||
*
|
||||
* VkResult
|
||||
* vkGetPhysicalDeviceQueueFamilyProperties(
|
||||
* VkPhysicalDevice physicalDevice,
|
||||
* uint32_t* pQueueFamilyPropertyCount,
|
||||
* VkQueueFamilyProperties* pQueueFamilyProperties)
|
||||
* {
|
||||
* VK_OUTARRAY_MAKE(props, pQueueFamilyProperties,
|
||||
* pQueueFamilyPropertyCount);
|
||||
*
|
||||
* vk_outarray_append(&props, p) {
|
||||
* p->queueFlags = ...;
|
||||
* p->queueCount = ...;
|
||||
* }
|
||||
*
|
||||
* vk_outarray_append(&props, p) {
|
||||
* p->queueFlags = ...;
|
||||
* p->queueCount = ...;
|
||||
* }
|
||||
*
|
||||
* return vk_outarray_status(&props);
|
||||
* }
|
||||
*/
|
||||
struct __vk_outarray {
|
||||
/** May be null. */
|
||||
void *data;
|
||||
|
||||
/**
|
||||
* Capacity, in number of elements. Capacity is unlimited (UINT32_MAX) if
|
||||
* data is null.
|
||||
*/
|
||||
uint32_t cap;
|
||||
|
||||
/**
|
||||
* Count of elements successfully written to the array. Every write is
|
||||
* considered successful if data is null.
|
||||
*/
|
||||
uint32_t *filled_len;
|
||||
|
||||
/**
|
||||
* Count of elements that would have been written to the array if its
|
||||
* capacity were sufficient. Vulkan functions often return VK_INCOMPLETE
|
||||
* when `*filled_len < wanted_len`.
|
||||
*/
|
||||
uint32_t wanted_len;
|
||||
};
|
||||
|
||||
static inline void
|
||||
__vk_outarray_init(struct __vk_outarray *a,
|
||||
void *data, uint32_t * len)
|
||||
{
|
||||
a->data = data;
|
||||
a->cap = *len;
|
||||
a->filled_len = len;
|
||||
*a->filled_len = 0;
|
||||
a->wanted_len = 0;
|
||||
|
||||
if (a->data == NULL)
|
||||
a->cap = UINT32_MAX;
|
||||
}
|
||||
|
||||
static inline VkResult
|
||||
__vk_outarray_status(const struct __vk_outarray *a)
|
||||
{
|
||||
if (*a->filled_len < a->wanted_len)
|
||||
return VK_INCOMPLETE;
|
||||
else
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
__vk_outarray_next(struct __vk_outarray *a, size_t elem_size)
|
||||
{
|
||||
void *p = NULL;
|
||||
|
||||
a->wanted_len += 1;
|
||||
|
||||
if (*a->filled_len >= a->cap)
|
||||
return NULL;
|
||||
|
||||
if (a->data != NULL)
|
||||
p = ((uint8_t*)a->data) + (*a->filled_len) * elem_size;
|
||||
|
||||
*a->filled_len += 1;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#define vk_outarray(elem_t) \
|
||||
struct { \
|
||||
struct __vk_outarray base; \
|
||||
elem_t meta[]; \
|
||||
}
|
||||
|
||||
#define vk_outarray_typeof_elem(a) __typeof__((a)->meta[0])
|
||||
#define vk_outarray_sizeof_elem(a) sizeof((a)->meta[0])
|
||||
|
||||
#define vk_outarray_init(a, data, len) \
|
||||
__vk_outarray_init(&(a)->base, (data), (len))
|
||||
|
||||
#define VK_OUTARRAY_MAKE(name, data, len) \
|
||||
vk_outarray(__typeof__((data)[0])) name; \
|
||||
vk_outarray_init(&name, (data), (len))
|
||||
|
||||
#define vk_outarray_status(a) \
|
||||
__vk_outarray_status(&(a)->base)
|
||||
|
||||
#define vk_outarray_next(a) \
|
||||
((vk_outarray_typeof_elem(a) *) \
|
||||
__vk_outarray_next(&(a)->base, vk_outarray_sizeof_elem(a)))
|
||||
|
||||
/**
|
||||
* Append to a Vulkan output array.
|
||||
*
|
||||
* This is a block-based macro. For example:
|
||||
*
|
||||
* vk_outarray_append(&a, elem) {
|
||||
* elem->foo = ...;
|
||||
* elem->bar = ...;
|
||||
* }
|
||||
*
|
||||
* The array `a` has type `vk_outarray(elem_t) *`. It is usually declared with
|
||||
* VK_OUTARRAY_MAKE(). The variable `elem` is block-scoped and has type
|
||||
* `elem_t *`.
|
||||
*
|
||||
* The macro unconditionally increments the array's `wanted_len`. If the array
|
||||
* is not full, then the macro also increment its `filled_len` and then
|
||||
* executes the block. When the block is executed, `elem` is non-null and
|
||||
* points to the newly appended element.
|
||||
*/
|
||||
#define vk_outarray_append(a, elem) \
|
||||
for (vk_outarray_typeof_elem(a) *elem = vk_outarray_next(a); \
|
||||
elem != NULL; elem = NULL)
|
||||
|
||||
static inline void *
|
||||
__vk_find_struct(void *start, VkStructureType sType)
|
||||
{
|
||||
vk_foreach_struct(s, start) {
|
||||
if (s->sType == sType)
|
||||
return s;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <class T, class H> T* vk_find_struct(H* head)
|
||||
{
|
||||
(void)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));
|
||||
}
|
||||
|
||||
template <class T, class H> const T* vk_find_struct(const H* head)
|
||||
{
|
||||
(void)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);
|
||||
|
||||
uint32_t vk_get_version_override(void);
|
||||
|
||||
#define VK_EXT_OFFSET (1000000000UL)
|
||||
#define VK_ENUM_EXTENSION(__enum) \
|
||||
((__enum) >= VK_EXT_OFFSET ? ((((__enum) - VK_EXT_OFFSET) / 1000UL) + 1) : 0)
|
||||
#define VK_ENUM_OFFSET(__enum) \
|
||||
((__enum) >= VK_EXT_OFFSET ? ((__enum) % 1000) : (__enum))
|
||||
|
||||
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)
|
||||
{
|
||||
(void)vk_get_vk_struct_id<T>::id;
|
||||
vk_struct_chain_iterator result = { reinterpret_cast<vk_struct_common*>(vk_struct) };
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> void vk_append_struct(vk_struct_chain_iterator* i, T* vk_struct)
|
||||
{
|
||||
(void)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);
|
||||
}
|
||||
|
||||
} // namespace vk
|
||||
} // namespace gfxstream
|
||||
|
||||
#endif /* VK_UTIL_H */
|
||||
Reference in New Issue
Block a user