1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
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
16 #include <vulkan/vulkan.h>
17
18 #include <base/util/formats.h>
19
20 #include "vulkan/device_vk.h"
21 #include "vulkan/platform_hardware_buffer_util_vk.h"
22 #include "vulkan/validate_vk.h"
23
24 struct OH_NativeBuffer;
25
26 RENDER_BEGIN_NAMESPACE()
27 namespace PlatformHardwareBufferUtil {
QueryHwBufferFormatProperties(const DeviceVk & deviceVk,uintptr_t hwBuffer)28 HardwareBufferProperties QueryHwBufferFormatProperties(const DeviceVk& deviceVk, uintptr_t hwBuffer)
29 {
30 HardwareBufferProperties hardwareBufferProperties;
31
32 const DevicePlatformDataVk& devicePlat = ((const DevicePlatformDataVk&)deviceVk.GetPlatformData());
33 const VkDevice device = devicePlat.device;
34 const PlatformExtFunctions& extFunctions = deviceVk.GetPlatformExtFunctions();
35
36 OH_NativeBuffer* nativeBuffer = static_cast<OH_NativeBuffer*>(reinterpret_cast<void*>(hwBuffer));
37 if (nativeBuffer && extFunctions.vkGetNativeBufferPropertiesOHOS && extFunctions.vkGetMemoryNativeBufferOHOS) {
38 VkNativeBufferFormatPropertiesOHOS bufferFormatProperties {};
39 bufferFormatProperties.sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_FORMAT_PROPERTIES_OHOS;
40
41 VkNativeBufferPropertiesOHOS bufferProperties {};
42 bufferProperties.sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_PROPERTIES_OHOS;
43 bufferProperties.pNext = &bufferFormatProperties;
44
45 VALIDATE_VK_RESULT(extFunctions.vkGetNativeBufferPropertiesOHOS(device, // device
46 nativeBuffer, // buffer
47 &bufferProperties)); // pProperties
48
49 PLUGIN_ASSERT_MSG(bufferProperties.allocationSize > 0, "ohos native buffer allocation size is zero");
50 PLUGIN_ASSERT_MSG(bufferFormatProperties.externalFormat != 0, "ohos native buffer externalFormat cannot be 0");
51
52 hardwareBufferProperties.allocationSize = bufferProperties.allocationSize;
53 hardwareBufferProperties.memoryTypeBits = bufferProperties.memoryTypeBits;
54
55 hardwareBufferProperties.format = bufferFormatProperties.format;
56 hardwareBufferProperties.externalFormat = bufferFormatProperties.externalFormat;
57 hardwareBufferProperties.formatFeatures = bufferFormatProperties.formatFeatures;
58 hardwareBufferProperties.samplerYcbcrConversionComponents =
59 bufferFormatProperties.samplerYcbcrConversionComponents;
60 hardwareBufferProperties.suggestedYcbcrModel = bufferFormatProperties.suggestedYcbcrModel;
61 hardwareBufferProperties.suggestedYcbcrRange = bufferFormatProperties.suggestedYcbcrRange;
62 hardwareBufferProperties.suggestedXChromaOffset = bufferFormatProperties.suggestedXChromaOffset;
63 hardwareBufferProperties.suggestedYChromaOffset = bufferFormatProperties.suggestedYChromaOffset;
64 }
65
66 return hardwareBufferProperties;
67 }
68
CreateHwPlatformImage(const DeviceVk & deviceVk,const HardwareBufferProperties & hwBufferProperties,const GpuImageDesc & desc,uintptr_t hwBuffer)69 HardwareBufferImage CreateHwPlatformImage(const DeviceVk& deviceVk, const HardwareBufferProperties& hwBufferProperties,
70 const GpuImageDesc& desc, uintptr_t hwBuffer)
71 {
72 HardwareBufferImage hwBufferImage;
73 GpuImageDesc validDesc = desc;
74 const bool useExternalFormat = hwBufferProperties.externalFormat != 0U;
75 if (useExternalFormat) {
76 validDesc.usageFlags = CORE_IMAGE_USAGE_SAMPLED_BIT;
77 }
78 VkImageCreateInfo imageCreateInfo = GetHwBufferImageCreateInfo(validDesc);
79
80 VkExternalFormatOHOS externalFormat {
81 VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS, // sType
82 nullptr, // pNext
83 hwBufferProperties.externalFormat, // externalFormat
84 };
85 VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo {
86 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
87 nullptr, // pNext
88 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OHOS_NATIVE_BUFFER_BIT_OHOS, // handleTypes
89 };
90 imageCreateInfo.pNext = &externalMemoryImageCreateInfo;
91 if (useExternalFormat) { // chain external format
92 externalMemoryImageCreateInfo.pNext = &externalFormat;
93 }
94
95 const DevicePlatformDataVk& platData = (const DevicePlatformDataVk&)deviceVk.GetPlatformData();
96 VkDevice device = platData.device;
97 VALIDATE_VK_RESULT(vkCreateImage(device, // device
98 &imageCreateInfo, // pCreateInfo
99 nullptr, // pAllocator
100 &hwBufferImage.image)); // pImage
101
102 // some older version of validation layers required calling vkGetImageMemoryRequirements before
103 // vkAllocateMemory. with at least 1.3.224.1 it's an error to call vkGetImageMemoryRequirements:
104 // "If image was created with the VK_EXTERNAL_MEMORY_HANDLE_TYPE_OHOS_NATIVE_BUFFER_BIT_OPENHARMONY external memory
105 // handle type, then image must be bound to memory."
106
107 // get memory type index based on
108 const uint32_t memoryTypeIndex =
109 GetMemoryTypeIndex(platData.physicalDeviceProperties.physicalDeviceMemoryProperties,
110 hwBufferProperties.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
111 VkMemoryAllocateInfo memoryAllocateInfo {
112 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
113 nullptr, // pNext
114 hwBufferProperties.allocationSize, // allocationSize
115 memoryTypeIndex, // memoryTypeIndex
116 };
117
118 OH_NativeBuffer* nativeBuffer = static_cast<OH_NativeBuffer*>(reinterpret_cast<void*>(hwBuffer));
119 PLUGIN_ASSERT(nativeBuffer);
120 VkMemoryDedicatedAllocateInfo dedicatedMemoryAllocateInfo {
121 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, // sType;
122 nullptr, // pNext
123 hwBufferImage.image, // image
124 VK_NULL_HANDLE, // buffer
125 };
126 VkImportNativeBufferInfoOHOS importHardwareBufferInfo {
127 VK_STRUCTURE_TYPE_IMPORT_NATIVE_BUFFER_INFO_OHOS, // sType
128 &dedicatedMemoryAllocateInfo, // pNext
129 nativeBuffer, // buffer
130 };
131 memoryAllocateInfo.pNext = &importHardwareBufferInfo;
132
133 VALIDATE_VK_RESULT(vkAllocateMemory(device, // device
134 &memoryAllocateInfo, // pAllocateInfo
135 nullptr, // pAllocator
136 &hwBufferImage.deviceMemory)); // pMemory
137 VALIDATE_VK_RESULT(vkBindImageMemory(device, // device
138 hwBufferImage.image, // image
139 hwBufferImage.deviceMemory, // memory
140 0)); // memoryOffset
141
142 return hwBufferImage;
143 }
144
CreateHwPlatformBuffer(const DeviceVk & deviceVk,const HardwareBufferProperties & hwBufferProperties,const GpuBufferDesc & desc,uintptr_t hwBuffer)145 HardwareBufferBuffer CreateHwPlatformBuffer(const DeviceVk& deviceVk,
146 const HardwareBufferProperties& hwBufferProperties, const GpuBufferDesc& desc, uintptr_t hwBuffer)
147 {
148 constexpr VkBufferCreateFlags bufferCreateFlags { 0 };
149
150 VkBufferCreateInfo bufferCreateInfo {
151 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
152 nullptr, // pNext
153 bufferCreateFlags, // flags
154 hwBufferProperties.allocationSize, // size
155 desc.usageFlags, // usage
156 VkSharingMode::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
157 0, // queueFamilyIndexCount
158 nullptr, // pQueueFamilyIndices
159 };
160 VkExternalMemoryBufferCreateInfo externalMemoryBufferCreateInfo {
161 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, // sType
162 nullptr, // pNext
163 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, // handleTypes
164 };
165 bufferCreateInfo.pNext = &externalMemoryBufferCreateInfo;
166
167 const auto& platData = (const DevicePlatformDataVk&)deviceVk.GetPlatformData();
168 VkDevice device = platData.device;
169 HardwareBufferBuffer hwBufferBuffer { VK_NULL_HANDLE, VK_NULL_HANDLE };
170 VALIDATE_VK_RESULT(vkCreateBuffer(device, // device
171 &bufferCreateInfo, // pCreateInfo
172 nullptr, // pAllocator
173 &hwBufferBuffer.buffer)); // pImage
174 // get memory type index based on
175 const uint32_t memoryTypeIndex =
176 GetMemoryTypeIndex(platData.physicalDeviceProperties.physicalDeviceMemoryProperties,
177 hwBufferProperties.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
178 VkMemoryAllocateInfo memoryAllocateInfo {
179 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
180 nullptr, // pNext
181 hwBufferProperties.allocationSize, // allocationSize
182 memoryTypeIndex, // memoryTypeIndex
183 };
184
185 OH_NativeBuffer* nativeBuffer = static_cast<OH_NativeBuffer*>(reinterpret_cast<void*>(hwBuffer));
186 PLUGIN_ASSERT(nativeBuffer);
187
188 VkImportNativeBufferInfoOHOS importHardwareBufferInfo {
189 VK_STRUCTURE_TYPE_IMPORT_NATIVE_BUFFER_INFO_OHOS, // sType
190 nullptr, // pNext
191 nativeBuffer, // buffer
192 };
193 memoryAllocateInfo.pNext = &importHardwareBufferInfo;
194
195 VALIDATE_VK_RESULT(vkAllocateMemory(device, // device
196 &memoryAllocateInfo, // pAllocateInfo
197 nullptr, // pAllocator
198 &hwBufferBuffer.deviceMemory)); // pMemory
199 VALIDATE_VK_RESULT(vkBindBufferMemory(device, // device
200 hwBufferBuffer.buffer, // image
201 hwBufferBuffer.deviceMemory, // memory
202 0)); // memoryOffset
203 return hwBufferBuffer;
204 }
205 } // namespace PlatformHardwareBufferUtil
206 RENDER_END_NAMESPACE()
207