(Reland) Use dedicated memory allocations when running with Mesa
... as otherwise Mesa expects linear tiling.
The attached guest side change updates the guest to always pass
through the VkMemoryDedicatedAllocateInfo as the guest does not
yet know if the host is using dedicated allocs for
Buffer/ColorBuffer. Then, VkDecoderGlobalState is updated to
check if Buffer/ColorBuffer used a dedicate alloc and use the
VkMemoryDedicatedAllocateInfo from the guest if needed.
Removes the extra page size alignment/padding of memory in
allocExternalMemory() to avoid VVL errors with dedicated allocs:
VUID-VkMemoryDedicatedAllocateInfo-image-01433 ... The Vulkan
spec states: If image is not VK_NULL_HANDLE,
VkMemoryAllocateInfo::allocationSize must equal the
VkMemoryRequirements::size of the image
Reland note: no changes from previous aosp/2385074.
Bug: b/265186355
Test: cvd start --gpu_mode=gfxstream (with AMD GPU)
Test: cvd start --gpu_mode=gfxstream (with Nvidia GPU)
Change-Id: Ie632ae56f98ea20e2ea9a170ea1fec2384067f48
diff --git a/stream-servers/vulkan/VkCommonOperations.cpp b/stream-servers/vulkan/VkCommonOperations.cpp
index d91cc44..764a30b 100644
--- a/stream-servers/vulkan/VkCommonOperations.cpp
+++ b/stream-servers/vulkan/VkCommonOperations.cpp
@@ -1190,6 +1190,7 @@
INFO(" enable ETC2 emulation: %s", features->enableEtc2Emulation ? "true" : "false");
INFO(" enable Ycbcr emulation: %s", features->enableYcbcrEmulation ? "true" : "false");
INFO(" guestUsesAngle: %s", features->guestUsesAngle ? "true" : "false");
+ INFO(" useDedicatedAllocations: %s", features->useDedicatedAllocations ? "true" : "false");
sVkEmulation->deviceInfo.glInteropSupported = features->glInteropSupported;
sVkEmulation->useDeferredCommands = features->deferredCommands;
sVkEmulation->useCreateResourcesWithRequirements = features->createResourceWithRequirements;
@@ -1198,6 +1199,7 @@
sVkEmulation->enableEtc2Emulation = features->enableEtc2Emulation;
sVkEmulation->enableYcbcrEmulation = features->enableYcbcrEmulation;
sVkEmulation->guestUsesAngle = features->guestUsesAngle;
+ sVkEmulation->useDedicatedAllocations = features->useDedicatedAllocations;
if (features->useVulkanComposition) {
if (sVkEmulation->compositorVk) {
@@ -1271,26 +1273,45 @@
// Precondition: sVkEmulation has valid device support info
bool allocExternalMemory(VulkanDispatch* vk, VkEmulation::ExternalMemoryInfo* info,
- bool actuallyExternal, Optional<uint64_t> deviceAlignment) {
+ bool actuallyExternal, Optional<uint64_t> deviceAlignment,
+ Optional<VkBuffer> bufferForDedicatedAllocation,
+ Optional<VkImage> imageForDedicatedAllocation) {
VkExportMemoryAllocateInfo exportAi = {
- VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
- 0,
- VK_EXT_MEMORY_HANDLE_TYPE_BIT,
+ .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
+ .pNext = nullptr,
+ .handleTypes = VK_EXT_MEMORY_HANDLE_TYPE_BIT,
};
- VkExportMemoryAllocateInfo* exportAiPtr = nullptr;
+ VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+ .pNext = nullptr,
+ .image = VK_NULL_HANDLE,
+ .buffer = VK_NULL_HANDLE,
+ };
+
+ VkMemoryAllocateInfo allocInfo = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = nullptr,
+ .allocationSize = info->size,
+ .memoryTypeIndex = info->typeIndex,
+ };
+
+ auto allocInfoChain = vk_make_chain_iterator(&allocInfo);
if (sVkEmulation->deviceInfo.supportsExternalMemory && actuallyExternal) {
- exportAiPtr = &exportAi;
+ vk_append_struct(&allocInfoChain, &exportAi);
}
- info->actualSize = (info->size + 2 * kPageSize - 1) / kPageSize * kPageSize;
- VkMemoryAllocateInfo allocInfo = {
- VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- exportAiPtr,
- info->actualSize,
- info->typeIndex,
- };
+ if (bufferForDedicatedAllocation.hasValue() || imageForDedicatedAllocation.hasValue()) {
+ info->dedicatedAllocation = true;
+ if (bufferForDedicatedAllocation.hasValue()) {
+ dedicatedAllocInfo.buffer = *bufferForDedicatedAllocation;
+ }
+ if (imageForDedicatedAllocation.hasValue()) {
+ dedicatedAllocInfo.image = *imageForDedicatedAllocation;
+ }
+ vk_append_struct(&allocInfoChain, &dedicatedAllocInfo);
+ }
bool memoryAllocated = false;
std::vector<VkDeviceMemory> allocationAttempts;
@@ -1308,8 +1329,8 @@
if (sVkEmulation->deviceInfo.memProps.memoryTypes[info->typeIndex].propertyFlags &
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
- VkResult mapRes = vk->vkMapMemory(sVkEmulation->device, info->memory, 0,
- info->actualSize, 0, &info->mappedPtr);
+ VkResult mapRes = vk->vkMapMemory(sVkEmulation->device, info->memory, 0, info->size, 0,
+ &info->mappedPtr);
if (mapRes != VK_SUCCESS) {
// LOG(VERBOSE) << "allocExternalMemory: failed in vkMapMemory: "
// << mapRes;
@@ -1446,7 +1467,7 @@
VkMemoryAllocateInfo allocInfo = {
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
&importInfo,
- info->actualSize,
+ info->size,
info->typeIndex,
};
@@ -1575,7 +1596,8 @@
}
bool getColorBufferAllocationInfo(uint32_t colorBufferHandle, VkDeviceSize* outSize,
- uint32_t* outMemoryTypeIndex, void** outMappedPtr) {
+ uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc,
+ void** outMappedPtr) {
if (!sVkEmulation || !sVkEmulation->live) {
GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Vulkan emulation not available.";
}
@@ -1595,6 +1617,10 @@
*outMemoryTypeIndex = info->memory.typeIndex;
}
+ if (outMemoryIsDedicatedAlloc) {
+ *outMemoryIsDedicatedAlloc = info->memory.dedicatedAllocation;
+ }
+
if (outMappedPtr) {
*outMappedPtr = info->memory.mappedPtr;
}
@@ -1827,8 +1853,10 @@
bool isHostVisible = memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Optional<uint64_t> deviceAlignment =
isHostVisible ? Optional<uint64_t>(res.memReqs.alignment) : kNullopt;
- bool allocRes =
- allocExternalMemory(vk, &res.memory, true /*actuallyExternal*/, deviceAlignment);
+ Optional<VkImage> dedicatedImage =
+ sVkEmulation->useDedicatedAllocations ? Optional<VkImage>(res.image) : kNullopt;
+ bool allocRes = allocExternalMemory(vk, &res.memory, true /*actuallyExternal*/, deviceAlignment,
+ kNullopt, dedicatedImage);
if (!allocRes) {
// LOG(VERBOSE) << "Failed to allocate ColorBuffer with Vulkan backing.";
@@ -1924,6 +1952,7 @@
.descriptor = std::move(descriptor),
.size = info->memory.size,
.linearTiling = info->imageCreateInfoShallow.tiling == VK_IMAGE_TILING_LINEAR,
+ .dedicatedAllocation = info->memory.dedicatedAllocation,
};
}
@@ -2484,7 +2513,7 @@
}
bool getBufferAllocationInfo(uint32_t bufferHandle, VkDeviceSize* outSize,
- uint32_t* outMemoryTypeIndex) {
+ uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc) {
if (!sVkEmulation || !sVkEmulation->live) {
GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Vulkan emulation not available.";
}
@@ -2504,6 +2533,10 @@
*outMemoryTypeIndex = info->memory.typeIndex;
}
+ if (outMemoryIsDedicatedAlloc) {
+ *outMemoryIsDedicatedAlloc = info->memory.dedicatedAllocation;
+ }
+
return true;
}