Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions common/base/SharedMemory_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ int SharedMemory::openInternal(int oflag, int mode, bool doMapping) {
}

if (oflag & O_CREAT) {
#if defined(__APPLE__)
// The descriptor keeps the object alive; the name is only a leak if the process dies.
if (mShareType == ShareType::SHARED_MEMORY) {
shm_unlink(mName.c_str());
}
#endif
if (HANDLE_EINTR(fstat(mFd, &sb)) == -1) {
err = -errno;
close();
Expand Down
5 changes: 4 additions & 1 deletion host/vulkan/vk_decoder_global_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6716,7 +6716,10 @@ class VkDecoderGlobalState::Impl {
static_cast<unsigned long long>(alignedSize));
}
localAllocInfo.allocationSize = alignedSize;
auto memory = SharedMemory("shared-memory-vk-" + std::to_string(sUniqueShmemId++),
// The name is per process: a server that was killed can leave its objects
// behind, and a name that already has a size cannot be resized.
auto memory = SharedMemory("shared-memory-vk-" + std::to_string(getpid()) + "-" +
std::to_string(sUniqueShmemId++),
localAllocInfo.allocationSize);

if (m_vkEmulation->getFeatures().VulkanAllocateHostVisibleAsUdmabuf.enabled()) {
Expand Down
53 changes: 53 additions & 0 deletions host/vulkan/vk_emulated_physical_device_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,42 @@ EmulatedPhysicalDeviceMemoryProperties::EmulatedPhysicalDeviceMemoryProperties(
}
mGuestColorBufferMemoryTypeIndex = hostColorBufferMemoryTypeIndex;

// With system blobs, host visible memory is shared memory imported as a host pointer, and

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you put this behind #ifdef MACOS just so we know in the future what uses this?

// a tiled image cannot be bound to that. A device whose every memory type is host visible
// leaves images nowhere else to go, so the guest gets a device local only type that
// allocates from the same host type without the sharing. It goes first: a strict subset
// of flags has to precede its superset, which is also what makes it the type an image
// is given.
if (features.SystemBlob.enabled() && mHostMemoryProperties.memoryTypeCount > 0 &&
mHostMemoryProperties.memoryTypeCount < VK_MAX_MEMORY_TYPES) {
bool allHostVisible = true;
uint32_t hostDeviceLocalIndex = 0;
for (uint32_t i = 0; i < mHostMemoryProperties.memoryTypeCount; i++) {
const VkMemoryPropertyFlags flags = mHostMemoryProperties.memoryTypes[i].propertyFlags;
if (!(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
allHostVisible = false;
}
if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) && hostDeviceLocalIndex == 0) {
hostDeviceLocalIndex = i;
}
}
if (allHostVisible) {
for (uint32_t i = mGuestMemoryProperties.memoryTypeCount; i > 0; i--) {
mGuestMemoryProperties.memoryTypes[i] = mGuestMemoryProperties.memoryTypes[i - 1];
mGuestToHostMemoryTypeIndexMap[i] = i - 1;
mHostToGuestMemoryTypeIndexMap[i - 1] = i;
}
mGuestMemoryProperties.memoryTypes[0] = VkMemoryType{
.propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.heapIndex = mHostMemoryProperties.memoryTypes[hostDeviceLocalIndex].heapIndex,
};
mGuestMemoryProperties.memoryTypeCount++;
mGuestToHostMemoryTypeIndexMap[0] = hostDeviceLocalIndex;
mGuestDeviceOnlyMemoryTypeIndex = 0;
mGuestColorBufferMemoryTypeIndex = hostColorBufferMemoryTypeIndex + 1;
}
}

// Limit max safe memory heap size if the VulkanMaxSafeHeapSize feature is set to a non-zero
// value.
const uint64_t maxSafeHeapSizeLimit = features.VulkanMaxSafeHeapSize.getValue().value_or(0);
Expand Down Expand Up @@ -179,6 +215,15 @@ EmulatedPhysicalDeviceMemoryProperties::getHostMemoryInfoFromGuestMemoryTypeInde
return std::nullopt;
}

// The device only type is the host type with its host visibility withheld, so that an
// allocation from it is not given host visible emulation.
if (mGuestDeviceOnlyMemoryTypeIndex == guestMemoryTypeIndex) {
return HostMemoryInfo{
.index = hostMemoryTypeIndex,
.memoryType = mGuestMemoryProperties.memoryTypes[guestMemoryTypeIndex],
};
}

return getHostMemoryInfoFromHostMemoryTypeIndex(hostMemoryTypeIndex);
}

Expand All @@ -201,6 +246,14 @@ void EmulatedPhysicalDeviceMemoryProperties::transformToGuestMemoryRequirements(
guestMemoryTypeBits |= (1u << guestMemoryTypeIndex);
}

if (mGuestDeviceOnlyMemoryTypeIndex) {
const uint32_t hostMemoryTypeIndex =
mGuestToHostMemoryTypeIndexMap[*mGuestDeviceOnlyMemoryTypeIndex];
if (hostMemoryTypeBits & (1u << hostMemoryTypeIndex)) {
guestMemoryTypeBits |= (1u << *mGuestDeviceOnlyMemoryTypeIndex);
}
}

memoryRequirements->memoryTypeBits = guestMemoryTypeBits;
}

Expand Down
5 changes: 5 additions & 0 deletions host/vulkan/vk_emulated_physical_device_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ class EmulatedPhysicalDeviceMemoryProperties {
// try to import host ColorBuffer allocations
// (e.g. vkGetAndroidHardwareBufferPropertiesANDROID()).
uint32_t mGuestColorBufferMemoryTypeIndex;

// A guest only memory type that allocates from a host visible host type without host
// visible emulation, so that images have somewhere to go on a device whose every memory
// type is host visible.
std::optional<uint32_t> mGuestDeviceOnlyMemoryTypeIndex;
};

} // namespace vk
Expand Down
61 changes: 61 additions & 0 deletions host/vulkan/vk_emulated_physical_device_memory_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,67 @@ TEST(VkGuestMemoryUtilsTest, Passthrough) {
EqsVkPhysicalDeviceMemoryProperties(hostMemoryProperties));
}

TEST(VkGuestMemoryUtilsTest, SystemBlobDeviceOnlyTypeWhenEverythingIsHostVisible) {
// A unified memory device, as Metal reports it.
const VkPhysicalDeviceMemoryProperties hostMemoryProperties = {
.memoryTypeCount = 1,
.memoryTypes =
{
{
.propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
.heapIndex = 0,
},
},
.memoryHeapCount = 1,
.memoryHeaps =
{
{
.size = 0x1000000,
.flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
},
},
};

gfxstream::host::FeatureSet features;
features.SystemBlob.setEnabled(true);
features.GlDirectMem.setEnabled(true);

EmulatedPhysicalDeviceMemoryProperties helper(hostMemoryProperties, 0, features);

// The guest sees a device local only type first, then the host type.
VkPhysicalDeviceMemoryProperties expectedGuestMemoryProperties = hostMemoryProperties;
expectedGuestMemoryProperties.memoryTypeCount = 2;
expectedGuestMemoryProperties.memoryTypes[0] = {
.propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
.heapIndex = 0,
};
expectedGuestMemoryProperties.memoryTypes[1] = hostMemoryProperties.memoryTypes[0];
EXPECT_THAT(helper.getGuestMemoryProperties(),
EqsVkPhysicalDeviceMemoryProperties(expectedGuestMemoryProperties));

// Both allocate from the one host type; the device only one is not host visible.
EXPECT_THAT(helper.getHostMemoryInfoFromGuestMemoryTypeIndex(0),
Optional(EqsHostMemoryInfo(EmulatedPhysicalDeviceMemoryProperties::HostMemoryInfo{
.index = 0,
.memoryType = expectedGuestMemoryProperties.memoryTypes[0],
})));
EXPECT_THAT(helper.getHostMemoryInfoFromGuestMemoryTypeIndex(1),
Optional(EqsHostMemoryInfo(EmulatedPhysicalDeviceMemoryProperties::HostMemoryInfo{
.index = 0,
.memoryType = hostMemoryProperties.memoryTypes[0],
})));

// Anything the host type can hold, either guest type can.
VkMemoryRequirements requirements = {.memoryTypeBits = 0b1};
helper.transformToGuestMemoryRequirements(&requirements);
EXPECT_EQ(requirements.memoryTypeBits, 0b11u);

EXPECT_EQ(helper.getGuestColorBufferMemoryTypeIndex(), 1u);
}

TEST(VkGuestMemoryUtilsTest, ReserveAHardwareBuffer) {
const VkPhysicalDeviceMemoryProperties hostMemoryProperties = {
.memoryTypeCount = 2,
Expand Down