• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "VkStringify.hpp"
16 
17 #include "System/Debug.hpp"
18 
19 #include <zircon/process.h>
20 #include <zircon/syscalls.h>
21 
22 namespace zircon {
23 
24 class VmoExternalMemory : public vk::DeviceMemory::ExternalBase
25 {
26 public:
27 	// Helper struct to parse the VkMemoryAllocateInfo.pNext chain and
28 	// extract relevant information related to the handle type supported
29 	// by this DeviceMemory::ExternalBase subclass.
30 	struct AllocateInfo
31 	{
32 		bool importHandle = false;
33 		bool exportHandle = false;
34 		zx_handle_t handle = ZX_HANDLE_INVALID;
35 
36 		AllocateInfo() = default;
37 
38 		// Parse the VkMemoryAllocateInfo->pNext chain to initialize a AllocateInfo.
AllocateInfozircon::VmoExternalMemory::AllocateInfo39 		AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
40 		{
41 			const auto *extInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
42 			while(extInfo)
43 			{
44 				switch(extInfo->sType)
45 				{
46 					case VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA:
47 					{
48 						const auto *importInfo = reinterpret_cast<const VkImportMemoryZirconHandleInfoFUCHSIA *>(extInfo);
49 
50 						if(importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA)
51 						{
52 							UNSUPPORTED("importInfo->handleType");
53 						}
54 						importHandle = true;
55 						handle = importInfo->handle;
56 						break;
57 					}
58 					case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
59 					{
60 						const auto *exportInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(extInfo);
61 
62 						if(exportInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA)
63 						{
64 							UNSUPPORTED("exportInfo->handleTypes");
65 						}
66 						exportHandle = true;
67 						break;
68 					}
69 					case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
70 						// This can safely be ignored, as the Vulkan spec mentions:
71 						// "If the pNext chain includes a VkMemoryDedicatedAllocateInfo structure, then that structure
72 						//  includes a handle of the sole buffer or image resource that the memory *can* be bound to."
73 						break;
74 
75 					default:
76 						WARN("VkMemoryAllocateInfo->pNext sType = %s", vk::Stringify(extInfo->sType).c_str());
77 				}
78 				extInfo = extInfo->pNext;
79 			}
80 		}
81 	};
82 
83 	static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
84 
supportsAllocateInfo(const VkMemoryAllocateInfo * pAllocateInfo)85 	static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
86 	{
87 		AllocateInfo info(pAllocateInfo);
88 		return info.importHandle || info.exportHandle;
89 	}
90 
VmoExternalMemory(const VkMemoryAllocateInfo * pAllocateInfo)91 	explicit VmoExternalMemory(const VkMemoryAllocateInfo *pAllocateInfo)
92 	    : allocateInfo(pAllocateInfo)
93 	{
94 	}
95 
~VmoExternalMemory()96 	~VmoExternalMemory()
97 	{
98 		closeVmo();
99 	}
100 
allocate(size_t size,void ** pBuffer)101 	VkResult allocate(size_t size, void **pBuffer) override
102 	{
103 		if(allocateInfo.importHandle)
104 		{
105 			// NOTE: handle ownership is passed to the VkDeviceMemory.
106 			vmoHandle = allocateInfo.handle;
107 		}
108 		else
109 		{
110 			ASSERT(allocateInfo.exportHandle);
111 			zx_status_t status = zx_vmo_create(size, 0, &vmoHandle);
112 			if(status != ZX_OK)
113 			{
114 				TRACE("zx_vmo_create() returned %d", status);
115 				return VK_ERROR_OUT_OF_DEVICE_MEMORY;
116 			}
117 		}
118 
119 		// Now map it directly.
120 		zx_vaddr_t addr = 0;
121 		zx_status_t status = zx_vmar_map(zx_vmar_root_self(),
122 		                                 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
123 		                                 0,  // vmar_offset
124 		                                 vmoHandle,
125 		                                 0,  // vmo_offset
126 		                                 size,
127 		                                 &addr);
128 		if(status != ZX_OK)
129 		{
130 			TRACE("zx_vmar_map() failed with %d", status);
131 			return VK_ERROR_MEMORY_MAP_FAILED;
132 		}
133 		*pBuffer = reinterpret_cast<void *>(addr);
134 		return VK_SUCCESS;
135 	}
136 
deallocate(void * buffer,size_t size)137 	void deallocate(void *buffer, size_t size) override
138 	{
139 		zx_status_t status = zx_vmar_unmap(zx_vmar_root_self(),
140 		                                   reinterpret_cast<zx_vaddr_t>(buffer),
141 		                                   size);
142 		if(status != ZX_OK)
143 		{
144 			TRACE("zx_vmar_unmap() failed with %d", status);
145 		}
146 		closeVmo();
147 	}
148 
getFlagBit() const149 	VkExternalMemoryHandleTypeFlagBits getFlagBit() const override
150 	{
151 		return typeFlagBit;
152 	}
153 
exportHandle(zx_handle_t * pHandle) const154 	VkResult exportHandle(zx_handle_t *pHandle) const override
155 	{
156 		if(vmoHandle == ZX_HANDLE_INVALID)
157 		{
158 			return VK_ERROR_INVALID_EXTERNAL_HANDLE;
159 		}
160 		zx_status_t status = zx_handle_duplicate(vmoHandle, ZX_RIGHT_SAME_RIGHTS, pHandle);
161 		if(status != ZX_OK)
162 		{
163 			TRACE("zx_handle_duplicate() returned %d", status);
164 			return VK_ERROR_INVALID_EXTERNAL_HANDLE;
165 		}
166 		return VK_SUCCESS;
167 	}
168 
169 private:
closeVmo()170 	void closeVmo()
171 	{
172 		if(vmoHandle != ZX_HANDLE_INVALID)
173 		{
174 			zx_handle_close(vmoHandle);
175 			vmoHandle = ZX_HANDLE_INVALID;
176 		}
177 	}
178 
179 	zx_handle_t vmoHandle = ZX_HANDLE_INVALID;
180 	AllocateInfo allocateInfo;
181 };
182 
183 }  // namespace zircon
184