| /// 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 "ResourceTracker.h" |
| |
| #include "../OpenglSystemCommon/EmulatorFeatureInfo.h" |
| #include "AndroidHardwareBuffer.h" |
| #include "HostVisibleMemoryVirtualization.h" |
| #include "Resources.h" |
| #include "VkEncoder.h" |
| |
| #include "android/base/AlignedBuf.h" |
| #include "android/base/synchronization/AndroidLock.h" |
| |
| #include "gralloc_cb.h" |
| #include "goldfish_address_space.h" |
| #include "goldfish_vk_private_defs.h" |
| |
| #include <string> |
| #include <unordered_map> |
| #include <set> |
| |
| #include <vndk/hardware_buffer.h> |
| #include <log/log.h> |
| #include <stdlib.h> |
| #include <sync/sync.h> |
| |
| #define RESOURCE_TRACKER_DEBUG 0 |
| |
| #if RESOURCE_TRACKER_DEBUG |
| #undef D |
| #define D(fmt,...) ALOGD("%s: " fmt, __func__, ##__VA_ARGS__); |
| #else |
| #ifndef D |
| #define D(fmt,...) |
| #endif |
| #endif |
| |
| using android::aligned_buf_alloc; |
| using android::aligned_buf_free; |
| using android::base::guest::AutoLock; |
| using android::base::guest::Lock; |
| |
| namespace goldfish_vk { |
| |
| #define MAKE_HANDLE_MAPPING_FOREACH(type_name, map_impl, map_to_u64_impl, map_from_u64_impl) \ |
| void mapHandles_##type_name(type_name* handles, size_t count) override { \ |
| for (size_t i = 0; i < count; ++i) { \ |
| map_impl; \ |
| } \ |
| } \ |
| void mapHandles_##type_name##_u64(const type_name* handles, uint64_t* handle_u64s, size_t count) override { \ |
| for (size_t i = 0; i < count; ++i) { \ |
| map_to_u64_impl; \ |
| } \ |
| } \ |
| void mapHandles_u64_##type_name(const uint64_t* handle_u64s, type_name* handles, size_t count) override { \ |
| for (size_t i = 0; i < count; ++i) { \ |
| map_from_u64_impl; \ |
| } \ |
| } \ |
| |
| #define DEFINE_RESOURCE_TRACKING_CLASS(class_name, impl) \ |
| class class_name : public VulkanHandleMapping { \ |
| public: \ |
| virtual ~class_name() { } \ |
| GOLDFISH_VK_LIST_HANDLE_TYPES(impl) \ |
| }; \ |
| |
| #define CREATE_MAPPING_IMPL_FOR_TYPE(type_name) \ |
| MAKE_HANDLE_MAPPING_FOREACH(type_name, \ |
| handles[i] = new_from_host_##type_name(handles[i]); ResourceTracker::get()->register_##type_name(handles[i]);, \ |
| handle_u64s[i] = (uint64_t)new_from_host_##type_name(handles[i]), \ |
| handles[i] = (type_name)new_from_host_u64_##type_name(handle_u64s[i]); ResourceTracker::get()->register_##type_name(handles[i]);) |
| |
| #define UNWRAP_MAPPING_IMPL_FOR_TYPE(type_name) \ |
| MAKE_HANDLE_MAPPING_FOREACH(type_name, \ |
| handles[i] = get_host_##type_name(handles[i]), \ |
| handle_u64s[i] = (uint64_t)get_host_u64_##type_name(handles[i]), \ |
| handles[i] = (type_name)get_host_##type_name((type_name)handle_u64s[i])) |
| |
| #define DESTROY_MAPPING_IMPL_FOR_TYPE(type_name) \ |
| MAKE_HANDLE_MAPPING_FOREACH(type_name, \ |
| ResourceTracker::get()->unregister_##type_name(handles[i]); delete_goldfish_##type_name(handles[i]), \ |
| (void)handle_u64s[i]; delete_goldfish_##type_name(handles[i]), \ |
| (void)handles[i]; delete_goldfish_##type_name((type_name)handle_u64s[i])) |
| |
| DEFINE_RESOURCE_TRACKING_CLASS(CreateMapping, CREATE_MAPPING_IMPL_FOR_TYPE) |
| DEFINE_RESOURCE_TRACKING_CLASS(UnwrapMapping, UNWRAP_MAPPING_IMPL_FOR_TYPE) |
| DEFINE_RESOURCE_TRACKING_CLASS(DestroyMapping, DESTROY_MAPPING_IMPL_FOR_TYPE) |
| |
| class ResourceTracker::Impl { |
| public: |
| Impl() = default; |
| CreateMapping createMapping; |
| UnwrapMapping unwrapMapping; |
| DestroyMapping destroyMapping; |
| DefaultHandleMapping defaultMapping; |
| |
| #define HANDLE_DEFINE_TRIVIAL_INFO_STRUCT(type) \ |
| struct type##_Info { \ |
| uint32_t unused; \ |
| }; \ |
| |
| GOLDFISH_VK_LIST_TRIVIAL_HANDLE_TYPES(HANDLE_DEFINE_TRIVIAL_INFO_STRUCT) |
| |
| struct VkInstance_Info { |
| uint32_t highestApiVersion; |
| std::set<std::string> enabledExtensions; |
| }; |
| |
| struct VkDevice_Info { |
| VkPhysicalDevice physdev; |
| VkPhysicalDeviceProperties props; |
| VkPhysicalDeviceMemoryProperties memProps; |
| HostMemAlloc hostMemAllocs[VK_MAX_MEMORY_TYPES] = {}; |
| uint32_t apiVersion; |
| std::set<std::string> enabledExtensions; |
| }; |
| |
| struct VkDeviceMemory_Info { |
| VkDeviceSize allocationSize = 0; |
| VkDeviceSize mappedSize = 0; |
| uint8_t* mappedPtr = nullptr; |
| uint32_t memoryTypeIndex = 0; |
| bool virtualHostVisibleBacking = false; |
| bool directMapped = false; |
| GoldfishAddressSpaceBlock* |
| goldfishAddressSpaceBlock = nullptr; |
| SubAlloc subAlloc; |
| AHardwareBuffer** ahbHandle = nullptr; |
| }; |
| |
| #define HANDLE_REGISTER_IMPL_IMPL(type) \ |
| std::unordered_map<type, type##_Info> info_##type; \ |
| void register_##type(type obj) { \ |
| AutoLock lock(mLock); \ |
| info_##type[obj] = type##_Info(); \ |
| } \ |
| |
| #define HANDLE_UNREGISTER_IMPL_IMPL(type) \ |
| void unregister_##type(type obj) { \ |
| AutoLock lock(mLock); \ |
| info_##type.erase(obj); \ |
| } \ |
| |
| GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL_IMPL) |
| GOLDFISH_VK_LIST_TRIVIAL_HANDLE_TYPES(HANDLE_UNREGISTER_IMPL_IMPL) |
| |
| void unregister_VkInstance(VkInstance instance) { |
| AutoLock lock(mLock); |
| |
| auto it = info_VkInstance.find(instance); |
| if (it == info_VkInstance.end()) return; |
| auto info = it->second; |
| info_VkInstance.erase(instance); |
| lock.unlock(); |
| } |
| |
| void unregister_VkDevice(VkDevice device) { |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDevice.find(device); |
| if (it == info_VkDevice.end()) return; |
| auto info = it->second; |
| info_VkDevice.erase(device); |
| lock.unlock(); |
| } |
| |
| void unregister_VkDeviceMemory(VkDeviceMemory mem) { |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDeviceMemory.find(mem); |
| if (it == info_VkDeviceMemory.end()) return; |
| |
| auto& memInfo = it->second; |
| |
| if (memInfo.mappedPtr && |
| !memInfo.virtualHostVisibleBacking && |
| !memInfo.directMapped) { |
| aligned_buf_free(memInfo.mappedPtr); |
| } |
| |
| if (memInfo.directMapped) { |
| subFreeHostMemory(&memInfo.subAlloc); |
| } |
| |
| delete memInfo.goldfishAddressSpaceBlock; |
| |
| info_VkDeviceMemory.erase(mem); |
| } |
| |
| // TODO: Upgrade to 1.1 |
| static constexpr uint32_t kMaxApiVersion = VK_MAKE_VERSION(1, 0, 65); |
| static constexpr uint32_t kMinApiVersion = VK_MAKE_VERSION(1, 0, 0); |
| |
| void setInstanceInfo(VkInstance instance, |
| uint32_t enabledExtensionCount, |
| const char* const* ppEnabledExtensionNames) { |
| AutoLock lock(mLock); |
| auto& info = info_VkInstance[instance]; |
| info.highestApiVersion = kMaxApiVersion; |
| |
| if (!ppEnabledExtensionNames) return; |
| |
| for (uint32_t i = 0; i < enabledExtensionCount; ++i) { |
| info.enabledExtensions.insert(ppEnabledExtensionNames[i]); |
| } |
| } |
| |
| void setDeviceInfo(VkDevice device, |
| VkPhysicalDevice physdev, |
| VkPhysicalDeviceProperties props, |
| VkPhysicalDeviceMemoryProperties memProps, |
| uint32_t enabledExtensionCount, |
| const char* const* ppEnabledExtensionNames) { |
| AutoLock lock(mLock); |
| auto& info = info_VkDevice[device]; |
| info.physdev = physdev; |
| info.props = props; |
| info.memProps = memProps; |
| initHostVisibleMemoryVirtualizationInfo( |
| physdev, &memProps, |
| mFeatureInfo->hasDirectMem, |
| &mHostVisibleMemoryVirtInfo); |
| info.apiVersion = props.apiVersion; |
| |
| if (!ppEnabledExtensionNames) return; |
| |
| for (uint32_t i = 0; i < enabledExtensionCount; ++i) { |
| info.enabledExtensions.insert(ppEnabledExtensionNames[i]); |
| } |
| } |
| |
| void setDeviceMemoryInfo(VkDevice device, |
| VkDeviceMemory memory, |
| VkDeviceSize allocationSize, |
| VkDeviceSize mappedSize, |
| uint8_t* ptr, |
| uint32_t memoryTypeIndex) { |
| AutoLock lock(mLock); |
| auto& deviceInfo = info_VkDevice[device]; |
| auto& info = info_VkDeviceMemory[memory]; |
| |
| info.allocationSize = allocationSize; |
| info.mappedSize = mappedSize; |
| info.mappedPtr = ptr; |
| info.memoryTypeIndex = memoryTypeIndex; |
| } |
| |
| bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const { |
| AutoLock lock(mLock); |
| const auto it = info_VkDevice.find(device); |
| |
| if (it == info_VkDevice.end()) return false; |
| |
| const auto& info = it->second; |
| return info.memProps.memoryTypes[typeIndex].propertyFlags & |
| VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; |
| } |
| |
| uint8_t* getMappedPointer(VkDeviceMemory memory) { |
| AutoLock lock(mLock); |
| const auto it = info_VkDeviceMemory.find(memory); |
| if (it == info_VkDeviceMemory.end()) return nullptr; |
| |
| const auto& info = it->second; |
| return info.mappedPtr; |
| } |
| |
| VkDeviceSize getMappedSize(VkDeviceMemory memory) { |
| AutoLock lock(mLock); |
| const auto it = info_VkDeviceMemory.find(memory); |
| if (it == info_VkDeviceMemory.end()) return 0; |
| |
| const auto& info = it->second; |
| return info.mappedSize; |
| } |
| |
| VkDeviceSize getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const { |
| AutoLock lock(mLock); |
| const auto it = info_VkDevice.find(device); |
| if (it == info_VkDevice.end()) return basicSize; |
| const auto& info = it->second; |
| |
| VkDeviceSize nonCoherentAtomSize = |
| info.props.limits.nonCoherentAtomSize; |
| VkDeviceSize atoms = |
| (basicSize + nonCoherentAtomSize - 1) / nonCoherentAtomSize; |
| return atoms * nonCoherentAtomSize; |
| } |
| |
| bool isValidMemoryRange(const VkMappedMemoryRange& range) const { |
| AutoLock lock(mLock); |
| const auto it = info_VkDeviceMemory.find(range.memory); |
| if (it == info_VkDeviceMemory.end()) return false; |
| const auto& info = it->second; |
| |
| if (!info.mappedPtr) return false; |
| |
| VkDeviceSize offset = range.offset; |
| VkDeviceSize size = range.size; |
| |
| if (size == VK_WHOLE_SIZE) { |
| return offset <= info.mappedSize; |
| } |
| |
| return offset + size <= info.mappedSize; |
| } |
| |
| void setupFeatures(const EmulatorFeatureInfo* features) { |
| if (!features || mFeatureInfo) return; |
| mFeatureInfo.reset(new EmulatorFeatureInfo); |
| *mFeatureInfo = *features; |
| |
| if (mFeatureInfo->hasDirectMem) { |
| mGoldfishAddressSpaceBlockProvider.reset( |
| new GoldfishAddressSpaceBlockProvider); |
| } |
| } |
| |
| bool hostSupportsVulkan() const { |
| if (!mFeatureInfo) return false; |
| |
| return mFeatureInfo->hasVulkan; |
| } |
| |
| bool usingDirectMapping() const { |
| return mHostVisibleMemoryVirtInfo.virtualizationSupported; |
| } |
| |
| int getHostInstanceExtensionIndex(const std::string& extName) const { |
| int i = 0; |
| for (const auto& prop : mHostInstanceExtensions) { |
| if (extName == std::string(prop.extensionName)) { |
| return i; |
| } |
| ++i; |
| } |
| return -1; |
| } |
| |
| int getHostDeviceExtensionIndex(const std::string& extName) const { |
| int i = 0; |
| for (const auto& prop : mHostDeviceExtensions) { |
| if (extName == std::string(prop.extensionName)) { |
| return i; |
| } |
| ++i; |
| } |
| return -1; |
| } |
| |
| 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)memoryCount; |
| (void)offsetCount; |
| (void)sizeCount; |
| |
| const auto& hostVirt = |
| mHostVisibleMemoryVirtInfo; |
| |
| if (!hostVirt.virtualizationSupported) return; |
| |
| if (memory) { |
| AutoLock lock (mLock); |
| |
| for (uint32_t i = 0; i < memoryCount; ++i) { |
| VkDeviceMemory mem = memory[i]; |
| |
| auto it = info_VkDeviceMemory.find(mem); |
| if (it == info_VkDeviceMemory.end()) return; |
| |
| const auto& info = it->second; |
| |
| if (!info.directMapped) continue; |
| |
| memory[i] = info.subAlloc.baseMemory; |
| |
| if (offset) { |
| offset[i] = info.subAlloc.baseOffset + offset[i]; |
| } |
| |
| if (size) { |
| if (size[i] == VK_WHOLE_SIZE) { |
| size[i] = info.subAlloc.subMappedSize; |
| } |
| } |
| |
| // TODO |
| (void)memory; |
| (void)offset; |
| (void)size; |
| } |
| } |
| |
| for (uint32_t i = 0; i < typeIndexCount; ++i) { |
| typeIndex[i] = |
| hostVirt.memoryTypeIndexMappingToHost[typeIndex[i]]; |
| } |
| |
| for (uint32_t i = 0; i < typeBitsCount; ++i) { |
| uint32_t bits = 0; |
| for (uint32_t j = 0; j < VK_MAX_MEMORY_TYPES; ++j) { |
| bool guestHas = typeBits[i] & (1 << j); |
| uint32_t hostIndex = |
| hostVirt.memoryTypeIndexMappingToHost[j]; |
| bits |= guestHas ? (1 << hostIndex) : 0; |
| } |
| typeBits[i] = bits; |
| } |
| } |
| |
| 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)memoryCount; |
| (void)offsetCount; |
| (void)sizeCount; |
| |
| const auto& hostVirt = |
| mHostVisibleMemoryVirtInfo; |
| |
| if (!hostVirt.virtualizationSupported) return; |
| |
| AutoLock lock (mLock); |
| |
| for (uint32_t i = 0; i < memoryCount; ++i) { |
| // TODO |
| (void)memory; |
| (void)offset; |
| (void)size; |
| } |
| |
| for (uint32_t i = 0; i < typeIndexCount; ++i) { |
| typeIndex[i] = |
| hostVirt.memoryTypeIndexMappingFromHost[typeIndex[i]]; |
| } |
| |
| for (uint32_t i = 0; i < typeBitsCount; ++i) { |
| uint32_t bits = 0; |
| for (uint32_t j = 0; j < VK_MAX_MEMORY_TYPES; ++j) { |
| bool hostHas = typeBits[i] & (1 << j); |
| uint32_t guestIndex = |
| hostVirt.memoryTypeIndexMappingFromHost[j]; |
| bits |= hostHas ? (1 << guestIndex) : 0; |
| |
| if (hostVirt.memoryTypeBitsShouldAdvertiseBoth[j]) { |
| bits |= hostHas ? (1 << j) : 0; |
| } |
| } |
| typeBits[i] = bits; |
| } |
| } |
| |
| VkResult on_vkEnumerateInstanceVersion( |
| void*, |
| VkResult, |
| uint32_t* apiVersion) { |
| if (apiVersion) { |
| *apiVersion = kMaxApiVersion; |
| } |
| return VK_SUCCESS; |
| } |
| |
| VkResult on_vkEnumerateInstanceExtensionProperties( |
| void* context, |
| VkResult, |
| const char*, |
| uint32_t* pPropertyCount, |
| VkExtensionProperties* pProperties) { |
| |
| std::vector<const char*> allowedExtensionNames = { |
| "VK_KHR_get_physical_device_properties2", |
| // TODO: |
| // VK_KHR_external_memory_capabilities |
| }; |
| |
| VkEncoder* enc = (VkEncoder*)context; |
| |
| // Only advertise a select set of extensions. |
| if (mHostInstanceExtensions.empty()) { |
| uint32_t hostPropCount = 0; |
| enc->vkEnumerateInstanceExtensionProperties(nullptr, &hostPropCount, nullptr); |
| mHostInstanceExtensions.resize(hostPropCount); |
| |
| VkResult hostRes = |
| enc->vkEnumerateInstanceExtensionProperties( |
| nullptr, &hostPropCount, mHostInstanceExtensions.data()); |
| |
| if (hostRes != VK_SUCCESS) { |
| return hostRes; |
| } |
| } |
| |
| std::vector<VkExtensionProperties> filteredExts; |
| |
| for (size_t i = 0; i < allowedExtensionNames.size(); ++i) { |
| auto extIndex = getHostInstanceExtensionIndex(allowedExtensionNames[i]); |
| if (extIndex != -1) { |
| filteredExts.push_back(mHostInstanceExtensions[extIndex]); |
| } |
| } |
| |
| VkExtensionProperties anbExtProp = { |
| "VK_ANDROID_native_buffer", 7, |
| }; |
| |
| filteredExts.push_back(anbExtProp); |
| |
| if (pPropertyCount) { |
| *pPropertyCount = filteredExts.size(); |
| } |
| |
| if (pPropertyCount && pProperties) { |
| for (size_t i = 0; i < *pPropertyCount; ++i) { |
| pProperties[i] = filteredExts[i]; |
| } |
| } |
| |
| return VK_SUCCESS; |
| } |
| |
| VkResult on_vkEnumerateDeviceExtensionProperties( |
| void* context, |
| VkResult, |
| VkPhysicalDevice physdev, |
| const char*, |
| uint32_t* pPropertyCount, |
| VkExtensionProperties* pProperties) { |
| |
| std::vector<const char*> allowedExtensionNames = { |
| "VK_KHR_maintenance1", |
| "VK_KHR_get_memory_requirements2", |
| // "VK_KHR_maintenance2", |
| // "VK_KHR_maintenance3", |
| // TODO: |
| // VK_KHR_external_memory_capabilities |
| }; |
| |
| VkEncoder* enc = (VkEncoder*)context; |
| |
| if (mHostDeviceExtensions.empty()) { |
| uint32_t hostPropCount = 0; |
| enc->vkEnumerateDeviceExtensionProperties(physdev, nullptr, &hostPropCount, nullptr); |
| mHostDeviceExtensions.resize(hostPropCount); |
| |
| VkResult hostRes = |
| enc->vkEnumerateDeviceExtensionProperties( |
| physdev, nullptr, &hostPropCount, mHostDeviceExtensions.data()); |
| |
| if (hostRes != VK_SUCCESS) { |
| return hostRes; |
| } |
| } |
| |
| std::vector<VkExtensionProperties> filteredExts; |
| |
| for (size_t i = 0; i < allowedExtensionNames.size(); ++i) { |
| auto extIndex = getHostDeviceExtensionIndex(allowedExtensionNames[i]); |
| if (extIndex != -1) { |
| filteredExts.push_back(mHostDeviceExtensions[extIndex]); |
| } |
| } |
| |
| VkExtensionProperties anbExtProp = { |
| "VK_ANDROID_native_buffer", 7, |
| }; |
| |
| filteredExts.push_back(anbExtProp); |
| |
| if (pPropertyCount) { |
| *pPropertyCount = filteredExts.size(); |
| } |
| |
| if (pPropertyCount && pProperties) { |
| for (size_t i = 0; i < *pPropertyCount; ++i) { |
| pProperties[i] = filteredExts[i]; |
| } |
| } |
| |
| return VK_SUCCESS; |
| } |
| |
| void on_vkGetPhysicalDeviceMemoryProperties( |
| void*, |
| VkPhysicalDevice physdev, |
| VkPhysicalDeviceMemoryProperties* out) { |
| |
| initHostVisibleMemoryVirtualizationInfo( |
| physdev, |
| out, |
| mFeatureInfo->hasDirectMem, |
| &mHostVisibleMemoryVirtInfo); |
| |
| if (mHostVisibleMemoryVirtInfo.virtualizationSupported) { |
| *out = mHostVisibleMemoryVirtInfo.guestMemoryProperties; |
| } |
| } |
| |
| void on_vkGetPhysicalDeviceMemoryProperties2( |
| void*, |
| VkPhysicalDevice physdev, |
| VkPhysicalDeviceMemoryProperties2* out) { |
| |
| initHostVisibleMemoryVirtualizationInfo( |
| physdev, |
| &out->memoryProperties, |
| mFeatureInfo->hasDirectMem, |
| &mHostVisibleMemoryVirtInfo); |
| |
| if (mHostVisibleMemoryVirtInfo.virtualizationSupported) { |
| out->memoryProperties = mHostVisibleMemoryVirtInfo.guestMemoryProperties; |
| } |
| } |
| |
| VkResult on_vkCreateInstance( |
| void*, |
| VkResult input_result, |
| const VkInstanceCreateInfo* createInfo, |
| const VkAllocationCallbacks*, |
| VkInstance* pInstance) { |
| |
| if (input_result != VK_SUCCESS) return input_result; |
| |
| setInstanceInfo( |
| *pInstance, |
| createInfo->enabledExtensionCount, |
| createInfo->ppEnabledExtensionNames); |
| |
| return input_result; |
| } |
| |
| VkResult on_vkCreateDevice( |
| void* context, |
| VkResult input_result, |
| VkPhysicalDevice physicalDevice, |
| const VkDeviceCreateInfo* pCreateInfo, |
| const VkAllocationCallbacks*, |
| VkDevice* pDevice) { |
| |
| if (input_result != VK_SUCCESS) return input_result; |
| |
| VkEncoder* enc = (VkEncoder*)context; |
| |
| VkPhysicalDeviceProperties props; |
| VkPhysicalDeviceMemoryProperties memProps; |
| enc->vkGetPhysicalDeviceProperties(physicalDevice, &props); |
| enc->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); |
| |
| setDeviceInfo( |
| *pDevice, physicalDevice, props, memProps, |
| pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); |
| |
| return input_result; |
| } |
| |
| void on_vkDestroyDevice_pre( |
| void* context, |
| VkDevice device, |
| const VkAllocationCallbacks*) { |
| |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDevice.find(device); |
| if (it == info_VkDevice.end()) return; |
| auto info = it->second; |
| |
| lock.unlock(); |
| |
| VkEncoder* enc = (VkEncoder*)context; |
| |
| for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) { |
| destroyHostMemAlloc(enc, device, &info.hostMemAllocs[i]); |
| } |
| } |
| |
| VkResult on_vkGetAndroidHardwareBufferPropertiesANDROID( |
| VkDevice device, |
| const AHardwareBuffer* buffer, |
| VkAndroidHardwareBufferPropertiesANDROID* pProperties) { |
| return getAndroidHardwareBufferPropertiesANDROID( |
| &mHostVisibleMemoryVirtInfo, |
| device, buffer, pProperties); |
| } |
| |
| VkResult on_vkGetMemoryAndroidHardwareBufferANDROID( |
| VkDevice device, |
| const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo, |
| struct AHardwareBuffer** pBuffer) { |
| |
| if (!pInfo) return VK_ERROR_INITIALIZATION_FAILED; |
| if (!pInfo->memory) return VK_ERROR_INITIALIZATION_FAILED; |
| |
| AutoLock lock(mLock); |
| |
| auto deviceIt = info_VkDevice.find(device); |
| |
| if (deviceIt == info_VkDevice.end()) { |
| return VK_ERROR_INITIALIZATION_FAILED; |
| } |
| |
| auto memoryIt = info_VkDeviceMemory.find(pInfo->memory); |
| |
| if (memoryIt == info_VkDeviceMemory.end()) { |
| return VK_ERROR_INITIALIZATION_FAILED; |
| } |
| |
| auto& info = memoryIt->second; |
| |
| VkResult queryRes = |
| getMemoryAndroidHardwareBufferANDROID(info.ahbHandle); |
| |
| if (queryRes != VK_SUCCESS) return queryRes; |
| |
| *pBuffer = *(info.ahbHandle); |
| |
| return queryRes; |
| } |
| |
| VkResult on_vkAllocateMemory( |
| void* context, |
| VkResult input_result, |
| VkDevice device, |
| const VkMemoryAllocateInfo* pAllocateInfo, |
| const VkAllocationCallbacks* pAllocator, |
| VkDeviceMemory* pMemory) { |
| |
| if (input_result != VK_SUCCESS) return input_result; |
| |
| VkEncoder* enc = (VkEncoder*)context; |
| |
| // Device local memory: pass through |
| if (!isHostVisibleMemoryTypeIndexForGuest( |
| &mHostVisibleMemoryVirtInfo, |
| pAllocateInfo->memoryTypeIndex)) { |
| |
| input_result = |
| enc->vkAllocateMemory( |
| device, pAllocateInfo, pAllocator, pMemory); |
| |
| if (input_result != VK_SUCCESS) return input_result; |
| |
| VkDeviceSize allocationSize = pAllocateInfo->allocationSize; |
| setDeviceMemoryInfo( |
| device, *pMemory, |
| pAllocateInfo->allocationSize, |
| 0, nullptr, |
| pAllocateInfo->memoryTypeIndex); |
| |
| return VK_SUCCESS; |
| } |
| |
| // Host visible memory with no direct mapping support |
| bool directMappingSupported = usingDirectMapping(); |
| if (!directMappingSupported) { |
| input_result = |
| enc->vkAllocateMemory( |
| device, pAllocateInfo, pAllocator, pMemory); |
| |
| if (input_result != VK_SUCCESS) return input_result; |
| |
| VkDeviceSize mappedSize = |
| getNonCoherentExtendedSize(device, |
| pAllocateInfo->allocationSize); |
| uint8_t* mappedPtr = (uint8_t*)aligned_buf_alloc(4096, mappedSize); |
| D("host visible alloc (non-direct): " |
| "size 0x%llx host ptr %p mapped size 0x%llx", |
| (unsigned long long)pAllocateInfo->allocationSize, mappedPtr, |
| (unsigned long long)mappedSize); |
| setDeviceMemoryInfo( |
| device, *pMemory, |
| pAllocateInfo->allocationSize, |
| mappedSize, mappedPtr, |
| pAllocateInfo->memoryTypeIndex); |
| return VK_SUCCESS; |
| } |
| |
| // Host visible memory with direct mapping |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDevice.find(device); |
| if (it == info_VkDevice.end()) return VK_ERROR_DEVICE_LOST; |
| auto& deviceInfo = it->second; |
| |
| HostMemAlloc* hostMemAlloc = |
| &deviceInfo.hostMemAllocs[pAllocateInfo->memoryTypeIndex]; |
| |
| if (!hostMemAlloc->initialized) { |
| VkMemoryAllocateInfo allocInfoForHost = *pAllocateInfo; |
| allocInfoForHost.allocationSize = VIRTUAL_HOST_VISIBLE_HEAP_SIZE; |
| // TODO: Support dedicated allocation |
| allocInfoForHost.pNext = nullptr; |
| |
| lock.unlock(); |
| VkResult host_res = |
| enc->vkAllocateMemory( |
| device, |
| &allocInfoForHost, |
| nullptr, |
| &hostMemAlloc->memory); |
| lock.lock(); |
| |
| if (host_res != VK_SUCCESS) { |
| ALOGE("Could not allocate backing for virtual host visible memory: %d", |
| host_res); |
| hostMemAlloc->initialized = true; |
| hostMemAlloc->initResult = host_res; |
| return host_res; |
| } |
| |
| auto& hostMemInfo = info_VkDeviceMemory[hostMemAlloc->memory]; |
| hostMemInfo.allocationSize = allocInfoForHost.allocationSize; |
| VkDeviceSize nonCoherentAtomSize = |
| deviceInfo.props.limits.nonCoherentAtomSize; |
| hostMemInfo.mappedSize = hostMemInfo.allocationSize; |
| hostMemInfo.memoryTypeIndex = |
| pAllocateInfo->memoryTypeIndex; |
| hostMemAlloc->nonCoherentAtomSize = nonCoherentAtomSize; |
| |
| uint64_t directMappedAddr = 0; |
| lock.unlock(); |
| VkResult directMapResult = |
| enc->vkMapMemoryIntoAddressSpaceGOOGLE( |
| device, hostMemAlloc->memory, &directMappedAddr); |
| lock.lock(); |
| |
| if (directMapResult != VK_SUCCESS) { |
| hostMemAlloc->initialized = true; |
| hostMemAlloc->initResult = directMapResult; |
| return directMapResult; |
| } |
| |
| hostMemInfo.mappedPtr = |
| (uint8_t*)(uintptr_t)directMappedAddr; |
| hostMemInfo.virtualHostVisibleBacking = true; |
| |
| VkResult hostMemAllocRes = |
| finishHostMemAllocInit( |
| enc, |
| device, |
| pAllocateInfo->memoryTypeIndex, |
| nonCoherentAtomSize, |
| hostMemInfo.allocationSize, |
| hostMemInfo.mappedSize, |
| hostMemInfo.mappedPtr, |
| hostMemAlloc); |
| |
| if (hostMemAllocRes != VK_SUCCESS) { |
| return hostMemAllocRes; |
| } |
| } |
| |
| VkDeviceMemory_Info virtualMemInfo; |
| |
| subAllocHostMemory( |
| hostMemAlloc, |
| pAllocateInfo, |
| &virtualMemInfo.subAlloc); |
| |
| virtualMemInfo.allocationSize = virtualMemInfo.subAlloc.subAllocSize; |
| virtualMemInfo.mappedSize = virtualMemInfo.subAlloc.subMappedSize; |
| virtualMemInfo.mappedPtr = virtualMemInfo.subAlloc.mappedPtr; |
| virtualMemInfo.memoryTypeIndex = pAllocateInfo->memoryTypeIndex; |
| virtualMemInfo.directMapped = true; |
| |
| D("host visible alloc (direct, suballoc): " |
| "size 0x%llx ptr %p mapped size 0x%llx", |
| (unsigned long long)virtualMemInfo.allocationSize, virtualMemInfo.mappedPtr, |
| (unsigned long long)virtualMemInfo.mappedSize); |
| |
| info_VkDeviceMemory[ |
| virtualMemInfo.subAlloc.subMemory] = virtualMemInfo; |
| |
| *pMemory = virtualMemInfo.subAlloc.subMemory; |
| |
| return VK_SUCCESS; |
| } |
| |
| void on_vkFreeMemory( |
| void* context, |
| VkDevice device, |
| VkDeviceMemory memory, |
| const VkAllocationCallbacks* pAllocateInfo) { |
| |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDeviceMemory.find(memory); |
| if (it == info_VkDeviceMemory.end()) return; |
| auto& info = it->second; |
| |
| if (!info.directMapped) { |
| lock.unlock(); |
| VkEncoder* enc = (VkEncoder*)context; |
| enc->vkFreeMemory(device, memory, pAllocateInfo); |
| return; |
| } |
| |
| subFreeHostMemory(&info.subAlloc); |
| } |
| |
| VkResult on_vkMapMemory( |
| void*, |
| VkResult host_result, |
| VkDevice, |
| VkDeviceMemory memory, |
| VkDeviceSize offset, |
| VkDeviceSize size, |
| VkMemoryMapFlags, |
| void** ppData) { |
| |
| if (host_result != VK_SUCCESS) return host_result; |
| |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDeviceMemory.find(memory); |
| if (it == info_VkDeviceMemory.end()) return VK_ERROR_MEMORY_MAP_FAILED; |
| |
| auto& info = it->second; |
| |
| if (!info.mappedPtr) return VK_ERROR_MEMORY_MAP_FAILED; |
| |
| if (size != VK_WHOLE_SIZE && |
| (info.mappedPtr + offset + size > info.mappedPtr + info.allocationSize)) { |
| return VK_ERROR_MEMORY_MAP_FAILED; |
| } |
| |
| *ppData = info.mappedPtr + offset; |
| |
| return host_result; |
| } |
| |
| void on_vkUnmapMemory( |
| void*, |
| VkDevice, |
| VkDeviceMemory) { |
| // no-op |
| } |
| |
| void unwrap_VkNativeBufferANDROID( |
| const VkImageCreateInfo* pCreateInfo, |
| VkImageCreateInfo* local_pCreateInfo) { |
| |
| if (!pCreateInfo->pNext) return; |
| |
| const VkNativeBufferANDROID* nativeInfo = |
| reinterpret_cast<const VkNativeBufferANDROID*>(pCreateInfo->pNext); |
| |
| if (VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID != nativeInfo->sType) { |
| return; |
| } |
| |
| const cb_handle_t* cb_handle = |
| reinterpret_cast<const cb_handle_t*>(nativeInfo->handle); |
| |
| if (!cb_handle) return; |
| |
| VkNativeBufferANDROID* nativeInfoOut = |
| reinterpret_cast<VkNativeBufferANDROID*>( |
| const_cast<void*>( |
| local_pCreateInfo->pNext)); |
| |
| if (!nativeInfoOut->handle) { |
| ALOGE("FATAL: Local native buffer info not properly allocated!"); |
| abort(); |
| } |
| |
| *(uint32_t*)(nativeInfoOut->handle) = cb_handle->hostHandle; |
| } |
| |
| void unwrap_vkAcquireImageANDROID_nativeFenceFd(int fd, int*) { |
| if (fd != -1) { |
| sync_wait(fd, 3000); |
| } |
| } |
| |
| // Action of vkMapMemoryIntoAddressSpaceGOOGLE: |
| // 1. preprocess (on_vkMapMemoryIntoAddressSpaceGOOGLE_pre): |
| // uses address space device to reserve the right size of |
| // memory. |
| // 2. the reservation results in a physical address. the physical |
| // address is set as |*pAddress|. |
| // 3. after pre, the API call is encoded to the host, where the |
| // value of pAddress is also sent (the physical address). |
| // 4. the host will obtain the actual gpu pointer and send it |
| // back out in |*pAddress|. |
| // 5. postprocess (on_vkMapMemoryIntoAddressSpaceGOOGLE) will run, |
| // using the mmap() method of GoldfishAddressSpaceBlock to obtain |
| // a pointer in guest userspace corresponding to the host pointer. |
| VkResult on_vkMapMemoryIntoAddressSpaceGOOGLE_pre( |
| void*, |
| VkResult, |
| VkDevice, |
| VkDeviceMemory memory, |
| uint64_t* pAddress) { |
| |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDeviceMemory.find(memory); |
| if (it == info_VkDeviceMemory.end()) { |
| return VK_ERROR_OUT_OF_HOST_MEMORY; |
| } |
| |
| auto& memInfo = it->second; |
| memInfo.goldfishAddressSpaceBlock = |
| new GoldfishAddressSpaceBlock; |
| auto& block = *(memInfo.goldfishAddressSpaceBlock); |
| |
| block.allocate( |
| mGoldfishAddressSpaceBlockProvider.get(), |
| memInfo.mappedSize); |
| |
| *pAddress = block.physAddr(); |
| |
| return VK_SUCCESS; |
| } |
| |
| VkResult on_vkMapMemoryIntoAddressSpaceGOOGLE( |
| void*, |
| VkResult input_result, |
| VkDevice, |
| VkDeviceMemory memory, |
| uint64_t* pAddress) { |
| |
| if (input_result != VK_SUCCESS) { |
| return input_result; |
| } |
| |
| // Now pAddress points to the gpu addr from host. |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDeviceMemory.find(memory); |
| if (it == info_VkDeviceMemory.end()) { |
| return VK_ERROR_OUT_OF_HOST_MEMORY; |
| } |
| |
| auto& memInfo = it->second; |
| auto& block = *(memInfo.goldfishAddressSpaceBlock); |
| |
| uint64_t gpuAddr = *pAddress; |
| |
| void* userPtr = block.mmap(gpuAddr); |
| |
| D("%s: Got new host visible alloc. " |
| "Sizeof void: %zu map size: %zu Range: [%p %p]", |
| __func__, |
| sizeof(void*), (size_t)memInfo.mappedSize, |
| userPtr, |
| (unsigned char*)userPtr + memInfo.mappedSize); |
| |
| *pAddress = (uint64_t)(uintptr_t)userPtr; |
| |
| return input_result; |
| } |
| |
| uint32_t getApiVersionFromInstance(VkInstance instance) const { |
| AutoLock lock(mLock); |
| uint32_t api = kMinApiVersion; |
| |
| auto it = info_VkInstance.find(instance); |
| if (it == info_VkInstance.end()) return api; |
| |
| api = it->second.highestApiVersion; |
| |
| return api; |
| } |
| |
| uint32_t getApiVersionFromDevice(VkDevice device) const { |
| AutoLock lock(mLock); |
| |
| uint32_t api = kMinApiVersion; |
| |
| auto it = info_VkDevice.find(device); |
| if (it == info_VkDevice.end()) return api; |
| |
| api = it->second.apiVersion; |
| |
| return api; |
| } |
| |
| bool hasInstanceExtension(VkInstance instance, const std::string& name) const { |
| AutoLock lock(mLock); |
| |
| auto it = info_VkInstance.find(instance); |
| if (it == info_VkInstance.end()) return false; |
| |
| return it->second.enabledExtensions.find(name) != |
| it->second.enabledExtensions.end(); |
| } |
| |
| bool hasDeviceExtension(VkDevice device, const std::string& name) const { |
| AutoLock lock(mLock); |
| |
| auto it = info_VkDevice.find(device); |
| if (it == info_VkDevice.end()) return false; |
| |
| return it->second.enabledExtensions.find(name) != |
| it->second.enabledExtensions.end(); |
| } |
| |
| private: |
| mutable Lock mLock; |
| HostVisibleMemoryVirtualizationInfo mHostVisibleMemoryVirtInfo; |
| std::unique_ptr<EmulatorFeatureInfo> mFeatureInfo; |
| std::unique_ptr<GoldfishAddressSpaceBlockProvider> mGoldfishAddressSpaceBlockProvider; |
| |
| std::vector<VkExtensionProperties> mHostInstanceExtensions; |
| std::vector<VkExtensionProperties> mHostDeviceExtensions; |
| }; |
| |
| ResourceTracker::ResourceTracker() : mImpl(new ResourceTracker::Impl()) { } |
| ResourceTracker::~ResourceTracker() { } |
| VulkanHandleMapping* ResourceTracker::createMapping() { |
| return &mImpl->createMapping; |
| } |
| VulkanHandleMapping* ResourceTracker::unwrapMapping() { |
| return &mImpl->unwrapMapping; |
| } |
| VulkanHandleMapping* ResourceTracker::destroyMapping() { |
| return &mImpl->destroyMapping; |
| } |
| VulkanHandleMapping* ResourceTracker::defaultMapping() { |
| return &mImpl->defaultMapping; |
| } |
| static ResourceTracker* sTracker = nullptr; |
| // static |
| ResourceTracker* ResourceTracker::get() { |
| if (!sTracker) { |
| // To be initialized once on vulkan device open. |
| sTracker = new ResourceTracker; |
| } |
| return sTracker; |
| } |
| |
| #define HANDLE_REGISTER_IMPL(type) \ |
| void ResourceTracker::register_##type(type obj) { \ |
| mImpl->register_##type(obj); \ |
| } \ |
| void ResourceTracker::unregister_##type(type obj) { \ |
| mImpl->unregister_##type(obj); \ |
| } \ |
| |
| GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL) |
| |
| bool ResourceTracker::isMemoryTypeHostVisible( |
| VkDevice device, uint32_t typeIndex) const { |
| return mImpl->isMemoryTypeHostVisible(device, typeIndex); |
| } |
| |
| uint8_t* ResourceTracker::getMappedPointer(VkDeviceMemory memory) { |
| return mImpl->getMappedPointer(memory); |
| } |
| |
| VkDeviceSize ResourceTracker::getMappedSize(VkDeviceMemory memory) { |
| return mImpl->getMappedSize(memory); |
| } |
| |
| VkDeviceSize ResourceTracker::getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const { |
| return mImpl->getNonCoherentExtendedSize(device, basicSize); |
| } |
| |
| bool ResourceTracker::isValidMemoryRange(const VkMappedMemoryRange& range) const { |
| return mImpl->isValidMemoryRange(range); |
| } |
| |
| void ResourceTracker::setupFeatures(const EmulatorFeatureInfo* features) { |
| mImpl->setupFeatures(features); |
| } |
| |
| bool ResourceTracker::hostSupportsVulkan() const { |
| return mImpl->hostSupportsVulkan(); |
| } |
| |
| bool ResourceTracker::usingDirectMapping() const { |
| return mImpl->usingDirectMapping(); |
| } |
| |
| uint32_t ResourceTracker::getApiVersionFromInstance(VkInstance instance) const { |
| return mImpl->getApiVersionFromInstance(instance); |
| } |
| |
| uint32_t ResourceTracker::getApiVersionFromDevice(VkDevice device) const { |
| return mImpl->getApiVersionFromDevice(device); |
| } |
| bool ResourceTracker::hasInstanceExtension(VkInstance instance, const std::string &name) const { |
| return mImpl->hasInstanceExtension(instance, name); |
| } |
| bool ResourceTracker::hasDeviceExtension(VkDevice device, const std::string &name) const { |
| return mImpl->hasDeviceExtension(device, name); |
| } |
| |
| VkResult ResourceTracker::on_vkEnumerateInstanceVersion( |
| void* context, |
| VkResult input_result, |
| uint32_t* apiVersion) { |
| return mImpl->on_vkEnumerateInstanceVersion(context, input_result, apiVersion); |
| } |
| |
| VkResult ResourceTracker::on_vkEnumerateInstanceExtensionProperties( |
| void* context, |
| VkResult input_result, |
| const char* pLayerName, |
| uint32_t* pPropertyCount, |
| VkExtensionProperties* pProperties) { |
| return mImpl->on_vkEnumerateInstanceExtensionProperties( |
| context, input_result, pLayerName, pPropertyCount, pProperties); |
| } |
| |
| VkResult ResourceTracker::on_vkEnumerateDeviceExtensionProperties( |
| void* context, |
| VkResult input_result, |
| VkPhysicalDevice physicalDevice, |
| const char* pLayerName, |
| uint32_t* pPropertyCount, |
| VkExtensionProperties* pProperties) { |
| return mImpl->on_vkEnumerateDeviceExtensionProperties( |
| context, input_result, physicalDevice, pLayerName, pPropertyCount, pProperties); |
| } |
| |
| void ResourceTracker::on_vkGetPhysicalDeviceMemoryProperties( |
| void* context, |
| VkPhysicalDevice physicalDevice, |
| VkPhysicalDeviceMemoryProperties* pMemoryProperties) { |
| mImpl->on_vkGetPhysicalDeviceMemoryProperties( |
| context, physicalDevice, pMemoryProperties); |
| } |
| |
| void ResourceTracker::on_vkGetPhysicalDeviceMemoryProperties2( |
| void* context, |
| VkPhysicalDevice physicalDevice, |
| VkPhysicalDeviceMemoryProperties2* pMemoryProperties) { |
| mImpl->on_vkGetPhysicalDeviceMemoryProperties2( |
| context, physicalDevice, pMemoryProperties); |
| } |
| |
| void ResourceTracker::on_vkGetPhysicalDeviceMemoryProperties2KHR( |
| void* context, |
| VkPhysicalDevice physicalDevice, |
| VkPhysicalDeviceMemoryProperties2* pMemoryProperties) { |
| mImpl->on_vkGetPhysicalDeviceMemoryProperties2( |
| context, physicalDevice, pMemoryProperties); |
| } |
| |
| VkResult ResourceTracker::on_vkCreateInstance( |
| void* context, |
| VkResult input_result, |
| const VkInstanceCreateInfo* pCreateInfo, |
| const VkAllocationCallbacks* pAllocator, |
| VkInstance* pInstance) { |
| return mImpl->on_vkCreateInstance( |
| context, input_result, pCreateInfo, pAllocator, pInstance); |
| } |
| |
| VkResult ResourceTracker::on_vkCreateDevice( |
| void* context, |
| VkResult input_result, |
| VkPhysicalDevice physicalDevice, |
| const VkDeviceCreateInfo* pCreateInfo, |
| const VkAllocationCallbacks* pAllocator, |
| VkDevice* pDevice) { |
| return mImpl->on_vkCreateDevice( |
| context, input_result, physicalDevice, pCreateInfo, pAllocator, pDevice); |
| } |
| |
| void ResourceTracker::on_vkDestroyDevice_pre( |
| void* context, |
| VkDevice device, |
| const VkAllocationCallbacks* pAllocator) { |
| mImpl->on_vkDestroyDevice_pre(context, device, pAllocator); |
| } |
| |
| VkResult ResourceTracker::on_vkAllocateMemory( |
| void* context, |
| VkResult input_result, |
| VkDevice device, |
| const VkMemoryAllocateInfo* pAllocateInfo, |
| const VkAllocationCallbacks* pAllocator, |
| VkDeviceMemory* pMemory) { |
| return mImpl->on_vkAllocateMemory( |
| context, input_result, device, pAllocateInfo, pAllocator, pMemory); |
| } |
| |
| void ResourceTracker::on_vkFreeMemory( |
| void* context, |
| VkDevice device, |
| VkDeviceMemory memory, |
| const VkAllocationCallbacks* pAllocator) { |
| return mImpl->on_vkFreeMemory( |
| context, device, memory, pAllocator); |
| } |
| |
| VkResult ResourceTracker::on_vkMapMemory( |
| void* context, |
| VkResult input_result, |
| VkDevice device, |
| VkDeviceMemory memory, |
| VkDeviceSize offset, |
| VkDeviceSize size, |
| VkMemoryMapFlags flags, |
| void** ppData) { |
| return mImpl->on_vkMapMemory( |
| context, input_result, device, memory, offset, size, flags, ppData); |
| } |
| |
| void ResourceTracker::on_vkUnmapMemory( |
| void* context, |
| VkDevice device, |
| VkDeviceMemory memory) { |
| mImpl->on_vkUnmapMemory(context, device, memory); |
| } |
| |
| void ResourceTracker::unwrap_VkNativeBufferANDROID( |
| const VkImageCreateInfo* pCreateInfo, |
| VkImageCreateInfo* local_pCreateInfo) { |
| mImpl->unwrap_VkNativeBufferANDROID(pCreateInfo, local_pCreateInfo); |
| } |
| |
| void ResourceTracker::unwrap_vkAcquireImageANDROID_nativeFenceFd(int fd, int* fd_out) { |
| mImpl->unwrap_vkAcquireImageANDROID_nativeFenceFd(fd, fd_out); |
| } |
| |
| VkResult ResourceTracker::on_vkMapMemoryIntoAddressSpaceGOOGLE_pre( |
| void* context, |
| VkResult input_result, |
| VkDevice device, |
| VkDeviceMemory memory, |
| uint64_t* pAddress) { |
| return mImpl->on_vkMapMemoryIntoAddressSpaceGOOGLE_pre( |
| context, input_result, device, memory, pAddress); |
| } |
| |
| VkResult ResourceTracker::on_vkMapMemoryIntoAddressSpaceGOOGLE( |
| void* context, |
| VkResult input_result, |
| VkDevice device, |
| VkDeviceMemory memory, |
| uint64_t* pAddress) { |
| return mImpl->on_vkMapMemoryIntoAddressSpaceGOOGLE( |
| context, input_result, device, memory, pAddress); |
| } |
| |
| void ResourceTracker::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) { |
| mImpl->deviceMemoryTransform_tohost( |
| memory, memoryCount, |
| offset, offsetCount, |
| size, sizeCount, |
| typeIndex, typeIndexCount, |
| typeBits, typeBitsCount); |
| } |
| |
| void ResourceTracker::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) { |
| mImpl->deviceMemoryTransform_fromhost( |
| memory, memoryCount, |
| offset, offsetCount, |
| size, sizeCount, |
| typeIndex, typeIndexCount, |
| typeBits, typeBitsCount); |
| } |
| |
| #define DEFINE_TRANSFORMED_TYPE_IMPL(type) \ |
| void ResourceTracker::transformImpl_##type##_tohost(const type*, uint32_t) { } \ |
| void ResourceTracker::transformImpl_##type##_fromhost(const type*, uint32_t) { } \ |
| |
| LIST_TRANSFORMED_TYPES(DEFINE_TRANSFORMED_TYPE_IMPL) |
| |
| } // namespace goldfish_vk |