1 /*
2 * Copyright (c) 2024 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 bufferFormatProperties.pNext = nullptr;
41
42 VkNativeBufferPropertiesOHOS bufferProperties {
43 VK_STRUCTURE_TYPE_NATIVE_BUFFER_PROPERTIES_OHOS, // sType
44 &bufferFormatProperties, // pNext
45 0, // allocationSize
46 0, // memoryTypeBits
47 };
48 VALIDATE_VK_RESULT(extFunctions.vkGetNativeBufferPropertiesOHOS(device, // device
49 nativeBuffer, // buffer
50 &bufferProperties)); // pProperties
51
52 PLUGIN_ASSERT_MSG(bufferProperties.allocationSize > 0, "ohos native buffer allocation size is zero");
53 PLUGIN_ASSERT_MSG(bufferFormatProperties.externalFormat != 0, "ohos native buffer externalFormat cannot be 0");
54
55 hardwareBufferProperties.allocationSize = bufferProperties.allocationSize;
56 hardwareBufferProperties.memoryTypeBits = bufferProperties.memoryTypeBits;
57
58 hardwareBufferProperties.format = bufferFormatProperties.format;
59 hardwareBufferProperties.externalFormat = bufferFormatProperties.externalFormat;
60 hardwareBufferProperties.formatFeatures = bufferFormatProperties.formatFeatures;
61 hardwareBufferProperties.samplerYcbcrConversionComponents =
62 bufferFormatProperties.samplerYcbcrConversionComponents;
63 hardwareBufferProperties.suggestedYcbcrModel = bufferFormatProperties.suggestedYcbcrModel;
64 hardwareBufferProperties.suggestedYcbcrRange = bufferFormatProperties.suggestedYcbcrRange;
65 hardwareBufferProperties.suggestedXChromaOffset = bufferFormatProperties.suggestedXChromaOffset;
66 hardwareBufferProperties.suggestedYChromaOffset = bufferFormatProperties.suggestedYChromaOffset;
67 }
68
69 return hardwareBufferProperties;
70 }
71
CreateHwPlatformImage(const DeviceVk & deviceVk,const HardwareBufferProperties & hwBufferProperties,const GpuImageDesc & desc,uintptr_t hwBuffer)72 HardwareBufferImage CreateHwPlatformImage(const DeviceVk& deviceVk, const HardwareBufferProperties& hwBufferProperties,
73 const GpuImageDesc& desc, uintptr_t hwBuffer)
74 {
75 HardwareBufferImage hwBufferImage;
76 GpuImageDesc validDesc = desc;
77 const bool useExternalFormat = (validDesc.format == BASE_NS::BASE_FORMAT_UNDEFINED);
78 if (useExternalFormat) {
79 validDesc.usageFlags = CORE_IMAGE_USAGE_SAMPLED_BIT;
80 }
81 VkImageCreateInfo imageCreateInfo = GetHwBufferImageCreateInfo(validDesc);
82
83 VkExternalFormatOHOS externalFormat {
84 VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS, // sType
85 nullptr, // pNext
86 hwBufferProperties.externalFormat, // externalFormat
87 };
88 VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo {
89 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, // sType
90 nullptr, // pNext
91 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OHOS_NATIVE_BUFFER_BIT_OHOS, // handleTypes
92 };
93 imageCreateInfo.pNext = &externalMemoryImageCreateInfo;
94 if (useExternalFormat) { // chain external format
95 externalMemoryImageCreateInfo.pNext = &externalFormat;
96 }
97
98 const DevicePlatformDataVk& platData = (const DevicePlatformDataVk&)deviceVk.GetPlatformData();
99 VkDevice device = platData.device;
100 VALIDATE_VK_RESULT(vkCreateImage(device, // device
101 &imageCreateInfo, // pCreateInfo
102 nullptr, // pAllocator
103 &hwBufferImage.image)); // pImage
104
105 // some older version of validation layers required calling vkGetImageMemoryRequirements before
106 // vkAllocateMemory. with at least 1.3.224.1 it's an error to call vkGetImageMemoryRequirements:
107 // "If image was created with the VK_EXTERNAL_MEMORY_HANDLE_TYPE_OHOS_NATIVE_BUFFER_BIT_OPENHARMONY external memory
108 // handle type, then image must be bound to memory."
109
110 // get memory type index based on
111 const uint32_t memoryTypeIndex =
112 GetMemoryTypeIndex(platData.physicalDeviceProperties.physicalDeviceMemoryProperties,
113 hwBufferProperties.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
114 VkMemoryAllocateInfo memoryAllocateInfo {
115 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
116 nullptr, // pNext
117 hwBufferProperties.allocationSize, // allocationSize
118 memoryTypeIndex, // memoryTypeIndex
119 };
120
121 OH_NativeBuffer* nativeBuffer = static_cast<OH_NativeBuffer*>(reinterpret_cast<void*>(hwBuffer));
122 PLUGIN_ASSERT(nativeBuffer);
123 VkMemoryDedicatedAllocateInfo dedicatedMemoryAllocateInfo {
124 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, // sType;
125 nullptr, // pNext
126 hwBufferImage.image, // image
127 VK_NULL_HANDLE, // buffer
128 };
129 VkImportNativeBufferInfoOHOS importHardwareBufferInfo {
130 VK_STRUCTURE_TYPE_IMPORT_NATIVE_BUFFER_INFO_OHOS, // sType
131 &dedicatedMemoryAllocateInfo, // pNext
132 nativeBuffer, // buffer
133 };
134 memoryAllocateInfo.pNext = &importHardwareBufferInfo;
135
136 VALIDATE_VK_RESULT(vkAllocateMemory(device, // device
137 &memoryAllocateInfo, // pAllocateInfo
138 nullptr, // pAllocator
139 &hwBufferImage.deviceMemory)); // pMemory
140 VALIDATE_VK_RESULT(vkBindImageMemory(device, // device
141 hwBufferImage.image, // image
142 hwBufferImage.deviceMemory, // memory
143 0)); // memoryOffset
144
145 return hwBufferImage;
146 }
147 } // namespace PlatformHardwareBufferUtil
148 RENDER_END_NAMESPACE()
149