• 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 "VkDeviceMemory.hpp"
16 #include "VkStringify.hpp"
17 
18 #include "System/Debug.hpp"
19 
20 #include <zircon/process.h>
21 #include <zircon/syscalls.h>
22 
23 namespace zircon {
24 
25 class VmoExternalMemory : public vk::DeviceMemory, public vk::ObjectBase<VmoExternalMemory, VkDeviceMemory>
26 {
27 public:
28 	// Helper struct which reads the parsed allocation info and
29 	// extracts relevant information related to the handle type
30 	// supported by this DeviceMemory subclass.
31 	struct AllocateInfo
32 	{
33 		bool importHandle = false;
34 		bool exportHandle = false;
35 		zx_handle_t handle = ZX_HANDLE_INVALID;
36 
37 		AllocateInfo() = default;
38 
39 		// Use the parsed allocation info to initialize a AllocateInfo.
AllocateInfozircon::VmoExternalMemory::AllocateInfo40 		AllocateInfo(const vk::DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo)
41 		{
42 			if(extendedAllocationInfo.importMemoryZirconHandleInfo)
43 			{
44 				if(extendedAllocationInfo.importMemoryZirconHandleInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA)
45 				{
46 					UNSUPPORTED("extendedAllocationInfo.importMemoryZirconHandleInfo->handleType");
47 				}
48 				importHandle = true;
49 				handle = extendedAllocationInfo.importMemoryZirconHandleInfo->handle;
50 			}
51 
52 			if(extendedAllocationInfo.exportMemoryAllocateInfo)
53 			{
54 				if(extendedAllocationInfo.exportMemoryAllocateInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA)
55 				{
56 					UNSUPPORTED("extendedAllocationInfo.exportMemoryAllocateInfo->handleTypes");
57 				}
58 				exportHandle = true;
59 			}
60 		}
61 	};
62 
63 	static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
64 
supportsAllocateInfo(const vk::DeviceMemory::ExtendedAllocationInfo & extendedAllocationInfo)65 	static bool supportsAllocateInfo(const vk::DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo)
66 	{
67 		AllocateInfo info(extendedAllocationInfo);
68 		return info.importHandle || info.exportHandle;
69 	}
70 
VmoExternalMemory(const VkMemoryAllocateInfo * pCreateInfo,void * mem,const vk::DeviceMemory::ExtendedAllocationInfo & extendedAllocationInfo,vk::Device * pDevice)71 	explicit VmoExternalMemory(const VkMemoryAllocateInfo *pCreateInfo, void *mem, const vk::DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo, vk::Device *pDevice)
72 	    : vk::DeviceMemory(pCreateInfo, pDevice)
73 	    , allocateInfo(extendedAllocationInfo)
74 	{
75 	}
76 
~VmoExternalMemory()77 	~VmoExternalMemory()
78 	{
79 		closeVmo();
80 	}
81 
allocateBuffer()82 	VkResult allocateBuffer() override
83 	{
84 		if(allocateInfo.importHandle)
85 		{
86 			// NOTE: handle ownership is passed to the VkDeviceMemory.
87 			vmoHandle = allocateInfo.handle;
88 		}
89 		else
90 		{
91 			ASSERT(allocateInfo.exportHandle);
92 			zx_status_t status = zx_vmo_create(allocationSize, 0, &vmoHandle);
93 			if(status != ZX_OK)
94 			{
95 				TRACE("zx_vmo_create() returned %d", status);
96 				return VK_ERROR_OUT_OF_DEVICE_MEMORY;
97 			}
98 		}
99 
100 		// Now map it directly.
101 		zx_vaddr_t addr = 0;
102 		zx_status_t status = zx_vmar_map(zx_vmar_root_self(),
103 		                                 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
104 		                                 0,  // vmar_offset
105 		                                 vmoHandle,
106 		                                 0,  // vmo_offset
107 		                                 allocationSize,
108 		                                 &addr);
109 		if(status != ZX_OK)
110 		{
111 			TRACE("zx_vmar_map() failed with %d", status);
112 			return VK_ERROR_MEMORY_MAP_FAILED;
113 		}
114 		buffer = reinterpret_cast<void *>(addr);
115 		return VK_SUCCESS;
116 	}
117 
freeBuffer()118 	void freeBuffer() override
119 	{
120 		zx_status_t status = zx_vmar_unmap(zx_vmar_root_self(),
121 		                                   reinterpret_cast<zx_vaddr_t>(buffer),
122 		                                   allocationSize);
123 		if(status != ZX_OK)
124 		{
125 			TRACE("zx_vmar_unmap() failed with %d", status);
126 		}
127 		closeVmo();
128 	}
129 
getFlagBit() const130 	VkExternalMemoryHandleTypeFlagBits getFlagBit() const override
131 	{
132 		return typeFlagBit;
133 	}
134 
exportHandle(zx_handle_t * pHandle) const135 	VkResult exportHandle(zx_handle_t *pHandle) const override
136 	{
137 		if(vmoHandle == ZX_HANDLE_INVALID)
138 		{
139 			return VK_ERROR_INVALID_EXTERNAL_HANDLE;
140 		}
141 		zx_status_t status = zx_handle_duplicate(vmoHandle, ZX_RIGHT_SAME_RIGHTS, pHandle);
142 		if(status != ZX_OK)
143 		{
144 			TRACE("zx_handle_duplicate() returned %d", status);
145 			return VK_ERROR_INVALID_EXTERNAL_HANDLE;
146 		}
147 		return VK_SUCCESS;
148 	}
149 
150 private:
closeVmo()151 	void closeVmo()
152 	{
153 		if(vmoHandle != ZX_HANDLE_INVALID)
154 		{
155 			zx_handle_close(vmoHandle);
156 			vmoHandle = ZX_HANDLE_INVALID;
157 		}
158 	}
159 
160 	zx_handle_t vmoHandle = ZX_HANDLE_INVALID;
161 	AllocateInfo allocateInfo;
162 };
163 
164 }  // namespace zircon
165