[vulkan] Allow custom logic in guest to access encoder/resourcetracker
bug: 120118806
+ do not alloc in guest if memory is not host visible.
+ extend host-visible allocs to be multiple of nonCoherentAtomSize if
necessary.
Change-Id: I4030d3f120627a18c7bc62da31e6db46a0544d9b
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index d827289..4def37d 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -17,6 +17,13 @@
#include "Resources.h"
+#include "android/base/synchronization/AndroidLock.h"
+
+#include <unordered_map>
+
+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) \
@@ -45,9 +52,9 @@
#define CREATE_MAPPING_IMPL_FOR_TYPE(type_name) \
MAKE_HANDLE_MAPPING_FOREACH(type_name, \
- handles[i] = new_from_host_##type_name(handles[i]), \
+ handles[i] = new_from_host_##type_name(handles[i]); ResourceTracker::get()->register_##type_name(handles[i]);, \
handle_u64s[i] = (uint64_t)(uintptr_t)new_from_host_##type_name(handles[i]), \
- handles[i] = (type_name)(uintptr_t)new_from_host_u64_##type_name(handle_u64s[i]))
+ handles[i] = (type_name)(uintptr_t)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, \
@@ -57,7 +64,7 @@
#define DESTROY_MAPPING_IMPL_FOR_TYPE(type_name) \
MAKE_HANDLE_MAPPING_FOREACH(type_name, \
- delete_goldfish_##type_name(handles[i]), \
+ 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)(uintptr_t)handle_u64s[i]))
@@ -72,6 +79,76 @@
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 VkDevice_Info {
+ VkPhysicalDevice physdev;
+ VkPhysicalDeviceProperties props;
+ VkPhysicalDeviceMemoryProperties memProps;
+ };
+
+ struct VkDeviceMemory_Info {
+ VkDeviceSize allocationSize;
+ uint32_t memoryTypeIndex;
+ };
+
+#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(); \
+ } \
+ void unregister_##type(type obj) { \
+ AutoLock lock(mLock); \
+ info_##type.erase(obj); \
+ } \
+
+ GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL_IMPL)
+
+ void setDeviceInfo(VkDevice device,
+ VkPhysicalDevice physdev,
+ VkPhysicalDeviceProperties props,
+ VkPhysicalDeviceMemoryProperties memProps) {
+ AutoLock lock(mLock);
+ auto& info = info_VkDevice[device];
+ info.physdev = physdev;
+ info.props = props;
+ info.memProps = memProps;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+private:
+ mutable Lock mLock;
+
};
ResourceTracker::ResourceTracker() : mImpl(new ResourceTracker::Impl()) { }
ResourceTracker::~ResourceTracker() { }
@@ -97,4 +174,31 @@
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)
+
+void ResourceTracker::setDeviceInfo(
+ VkDevice device,
+ VkPhysicalDevice physdev,
+ VkPhysicalDeviceProperties props,
+ VkPhysicalDeviceMemoryProperties memProps) {
+ mImpl->setDeviceInfo(device, physdev, props, memProps);
+}
+
+bool ResourceTracker::isMemoryTypeHostVisible(
+ VkDevice device, uint32_t typeIndex) const {
+ return mImpl->isMemoryTypeHostVisible(device, typeIndex);
+}
+
+VkDeviceSize ResourceTracker::getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const {
+ return mImpl->getNonCoherentExtendedSize(device, basicSize);
+}
+
} // namespace goldfish_vk
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index ed061f3..07dd421 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -17,6 +17,7 @@
#include <vulkan/vulkan.h>
#include "VulkanHandleMapping.h"
+#include "VulkanHandles.h"
#include <memory>
namespace goldfish_vk {
@@ -30,7 +31,18 @@
VulkanHandleMapping* unwrapMapping();
VulkanHandleMapping* destroyMapping();
VulkanHandleMapping* defaultMapping();
-private:
+
+#define HANDLE_REGISTER_DECL(type) \
+ void register_##type(type); \
+ void unregister_##type(type); \
+
+ GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_DECL)
+
+ void setDeviceInfo(VkDevice device, VkPhysicalDevice physdev, VkPhysicalDeviceProperties props, VkPhysicalDeviceMemoryProperties memProps);
+ bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const;
+ VkDeviceSize getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const;
+
+ private:
class Impl;
std::unique_ptr<Impl> mImpl;
};
diff --git a/system/vulkan_enc/Resources.cpp b/system/vulkan_enc/Resources.cpp
index ab5c7b7..2b8f890 100644
--- a/system/vulkan_enc/Resources.cpp
+++ b/system/vulkan_enc/Resources.cpp
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "Resources.h"
+#include "ResourceTracker.h"
+#include "VkEncoder.h"
#include "android/base/AlignedBuf.h"
@@ -29,6 +31,8 @@
#define D(fmt,...)
#endif
+using goldfish_vk::ResourceTracker;
+
extern "C" {
#define GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_IMPL(type) \
@@ -125,7 +129,10 @@
// Custom definitions///////////////////////////////////////////////////////////
-VkResult goldfish_vkEnumerateInstanceVersion(uint32_t* apiVersion) {
+VkResult goldfish_vkEnumerateInstanceVersion(
+ void*,
+ VkResult,
+ uint32_t* apiVersion) {
if (apiVersion) {
*apiVersion = VK_MAKE_VERSION(1, 0, 0);
}
@@ -133,6 +140,8 @@
}
VkResult goldfish_vkEnumerateDeviceExtensionProperties(
+ void*,
+ VkResult,
VkPhysicalDevice, const char*,
uint32_t *pPropertyCount, VkExtensionProperties *) {
*pPropertyCount = 0;
@@ -140,12 +149,35 @@
}
void goldfish_vkGetPhysicalDeviceProperties2(
+ void*,
VkPhysicalDevice,
VkPhysicalDeviceProperties2*)
{
// no-op
}
+VkResult goldfish_vkCreateDevice(
+ void* opaque,
+ VkResult host_return,
+ VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo*,
+ const VkAllocationCallbacks*,
+ VkDevice* pDevice) {
+
+ if (host_return != VK_SUCCESS) return host_return;
+
+ VkEncoder* enc = (VkEncoder*)opaque;
+
+ VkPhysicalDeviceProperties props;
+ VkPhysicalDeviceMemoryProperties memProps;
+ enc->vkGetPhysicalDeviceProperties(physicalDevice, &props);
+ enc->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps);
+
+ ResourceTracker::get()->setDeviceInfo(*pDevice, physicalDevice, props, memProps);
+
+ return host_return;
+}
+
VkDeviceMemory new_from_host_VkDeviceMemory(VkDeviceMemory mem) {
struct goldfish_VkDeviceMemory *res =
(struct goldfish_VkDeviceMemory *)malloc(sizeof(goldfish_VkDeviceMemory));
@@ -193,38 +225,55 @@
}
VkResult goldfish_vkAllocateMemory(
- VkDevice,
+ void*,
+ VkResult host_return,
+ VkDevice device,
const VkMemoryAllocateInfo* pAllocateInfo,
const VkAllocationCallbacks*,
VkDeviceMemory* pMemory) {
+
+ if (host_return != VK_SUCCESS) return host_return;
// Assumes pMemory has already been allocated.
goldfish_VkDeviceMemory* mem = as_goldfish_VkDeviceMemory(*pMemory);
-
VkDeviceSize size = pAllocateInfo->allocationSize;
+ // assume memory is not host visible.
+ mem->ptr = nullptr;
+ mem->size = size;
+ mem->mappedSize = ResourceTracker::get()->getNonCoherentExtendedSize(device, size);
+
+ if (!ResourceTracker::get()->isMemoryTypeHostVisible(device, pAllocateInfo->memoryTypeIndex)) {
+ return host_return;
+ }
+
// This is a strict alignment; we do not expect any
// actual device to have more stringent requirements
// than this.
- mem->ptr = (uint8_t*)aligned_buf_alloc(4096, size);
- mem->size = size;
+ mem->ptr = (uint8_t*)aligned_buf_alloc(4096, mem->mappedSize);
+ D("host visible alloc: size 0x%llx host ptr %p mapped size 0x%llx",
+ (unsigned long long)size, mem->ptr,
+ (unsigned long long)mem->mappedSize);
- return VK_SUCCESS;
+ return host_return;
}
VkResult goldfish_vkMapMemory(
+ void*,
+ VkResult host_result,
VkDevice,
VkDeviceMemory memory,
VkDeviceSize offset,
VkDeviceSize size,
VkMemoryMapFlags,
void** ppData) {
+
+ if (host_result != VK_SUCCESS) return host_result;
goldfish_VkDeviceMemory* mem = as_goldfish_VkDeviceMemory(memory);
if (!mem->ptr) {
- ALOGE("%s: Did not allocate host pointer for device memory!", __func__);
- abort();
+ return VK_ERROR_MEMORY_MAP_FAILED;
}
if (size != VK_WHOLE_SIZE &&
@@ -234,10 +283,11 @@
*ppData = mem->ptr + offset;
- return VK_SUCCESS;
+ return host_result;
}
void goldfish_vkUnmapMemory(
+ void*,
VkDevice,
VkDeviceMemory) {
// no-op
diff --git a/system/vulkan_enc/Resources.h b/system/vulkan_enc/Resources.h
index 30299f9..8928d73 100644
--- a/system/vulkan_enc/Resources.h
+++ b/system/vulkan_enc/Resources.h
@@ -75,29 +75,48 @@
// Custom definitions///////////////////////////////////////////////////////////
-VkResult goldfish_vkEnumerateInstanceVersion(uint32_t* apiVersion);
+VkResult goldfish_vkEnumerateInstanceVersion(
+ void* opaque,
+ VkResult host_return,
+ uint32_t* apiVersion);
VkResult goldfish_vkEnumerateDeviceExtensionProperties(
+ void* opaque,
+ VkResult host_return,
VkPhysicalDevice physicalDevice, const char *pLayerName,
uint32_t *pPropertyCount, VkExtensionProperties *pProperties);
void goldfish_vkGetPhysicalDeviceProperties2(
+ void* opaque,
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties2* pProperties);
+VkResult goldfish_vkCreateDevice(
+ void* opaque,
+ VkResult host_return,
+ VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice);
+
struct goldfish_VkDeviceMemory {
uint64_t underlying;
uint8_t* ptr;
VkDeviceSize size;
+ VkDeviceSize mappedSize;
};
VkResult goldfish_vkAllocateMemory(
+ void* opaque,
+ VkResult host_return,
VkDevice device,
const VkMemoryAllocateInfo* pAllocateInfo,
const VkAllocationCallbacks* pAllocator,
VkDeviceMemory* pMemory);
VkResult goldfish_vkMapMemory(
+ void* opaque,
+ VkResult host_return,
VkDevice device,
VkDeviceMemory memory,
VkDeviceSize offset,
@@ -106,7 +125,7 @@
void** ppData);
void goldfish_vkUnmapMemory(
+ void* opaque,
VkDevice device,
VkDeviceMemory memory);
-
} // extern "C"
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index cb51ac9..f51744c 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -721,6 +721,7 @@
countingStream->clearPool();
stream->clearPool();
pool->freeAll();
+ goldfish_vkCreateDevice(this, vkCreateDevice_VkResult_return, physicalDevice, pCreateInfo, pAllocator, pDevice);
return vkCreateDevice_VkResult_return;
}
@@ -874,7 +875,7 @@
VkExtensionProperties* pProperties)
{
VkResult vkEnumerateDeviceExtensionProperties_VkResult_return = (VkResult)0;
- vkEnumerateDeviceExtensionProperties_VkResult_return = goldfish_vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
+ vkEnumerateDeviceExtensionProperties_VkResult_return = goldfish_vkEnumerateDeviceExtensionProperties(this, vkEnumerateDeviceExtensionProperties_VkResult_return, physicalDevice, pLayerName, pPropertyCount, pProperties);
return vkEnumerateDeviceExtensionProperties_VkResult_return;
}
@@ -1305,12 +1306,12 @@
stream->read((uint64_t*)&cgen_var_92, 8);
stream->handleMapping()->mapHandles_u64_VkDeviceMemory(&cgen_var_92, (VkDeviceMemory*)pMemory, 1);
stream->unsetHandleMapping();
- goldfish_vkAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
VkResult vkAllocateMemory_VkResult_return = (VkResult)0;
stream->read(&vkAllocateMemory_VkResult_return, sizeof(VkResult));
countingStream->clearPool();
stream->clearPool();
pool->freeAll();
+ goldfish_vkAllocateMemory(this, vkAllocateMemory_VkResult_return, device, pAllocateInfo, pAllocator, pMemory);
return vkAllocateMemory_VkResult_return;
}
@@ -1382,7 +1383,7 @@
void** ppData)
{
VkResult vkMapMemory_VkResult_return = (VkResult)0;
- vkMapMemory_VkResult_return = goldfish_vkMapMemory(device, memory, offset, size, flags, ppData);
+ vkMapMemory_VkResult_return = goldfish_vkMapMemory(this, vkMapMemory_VkResult_return, device, memory, offset, size, flags, ppData);
return vkMapMemory_VkResult_return;
}
@@ -1390,7 +1391,7 @@
VkDevice device,
VkDeviceMemory memory)
{
- goldfish_vkUnmapMemory(device, memory);
+ goldfish_vkUnmapMemory(this, device, memory);
}
VkResult VkEncoder::vkFlushMappedMemoryRanges(
@@ -5033,15 +5034,15 @@
stream->write((uint64_t*)cgen_var_424, ((descriptorSetCount)) * 8);
}
}
- if (pDescriptorSets)
- {
- resources->destroyMapping()->mapHandles_VkDescriptorSet((VkDescriptorSet*)pDescriptorSets, ((descriptorSetCount)));
- }
VkResult vkFreeDescriptorSets_VkResult_return = (VkResult)0;
stream->read(&vkFreeDescriptorSets_VkResult_return, sizeof(VkResult));
countingStream->clearPool();
stream->clearPool();
pool->freeAll();
+ if (pDescriptorSets)
+ {
+ resources->destroyMapping()->mapHandles_VkDescriptorSet((VkDescriptorSet*)pDescriptorSets, ((descriptorSetCount)));
+ }
return vkFreeDescriptorSets_VkResult_return;
}
@@ -8310,7 +8311,7 @@
uint32_t* pApiVersion)
{
VkResult vkEnumerateInstanceVersion_VkResult_return = (VkResult)0;
- vkEnumerateInstanceVersion_VkResult_return = goldfish_vkEnumerateInstanceVersion(pApiVersion);
+ vkEnumerateInstanceVersion_VkResult_return = goldfish_vkEnumerateInstanceVersion(this, vkEnumerateInstanceVersion_VkResult_return, pApiVersion);
return vkEnumerateInstanceVersion_VkResult_return;
}
@@ -8862,7 +8863,7 @@
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties2* pProperties)
{
- goldfish_vkGetPhysicalDeviceProperties2(physicalDevice, pProperties);
+ goldfish_vkGetPhysicalDeviceProperties2(this, physicalDevice, pProperties);
}
void VkEncoder::vkGetPhysicalDeviceFormatProperties2(
diff --git a/system/vulkan_enc/VulkanHandles.h b/system/vulkan_enc/VulkanHandles.h
index 498fae2..af130eb 100644
--- a/system/vulkan_enc/VulkanHandles.h
+++ b/system/vulkan_enc/VulkanHandles.h
@@ -16,13 +16,16 @@
#include <vulkan/vulkan.h>
-#define GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(f) \
+#define GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f) \
f(VkInstance) \
f(VkPhysicalDevice) \
- f(VkDevice) \
f(VkQueue) \
f(VkCommandBuffer) \
+#define GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(f) \
+ f(VkDevice) \
+ GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f)
+
#define GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
f(VkBuffer) \
f(VkBufferView) \
@@ -62,3 +65,7 @@
#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)