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 "platform_hardware_buffer_util_vk.h"
17 
18 #include <algorithm>
19 #include <vulkan/vulkan_core.h>
20 
21 #include <base/math/mathf.h>
22 #include <render/namespace.h>
23 
24 #include "device/device.h"
25 #include "util/log.h"
26 #include "vulkan/device_vk.h"
27 #include "vulkan/validate_vk.h"
28 
29 RENDER_BEGIN_NAMESPACE()
30 namespace PlatformHardwareBufferUtil {
GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties & physicalDeviceMemoryProperties,const uint32_t memoryTypeBits,const VkMemoryPropertyFlags memoryPropertyFlags)31 uint32_t GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& physicalDeviceMemoryProperties,
32     const uint32_t memoryTypeBits, const VkMemoryPropertyFlags memoryPropertyFlags)
33 {
34     uint32_t memTypeIndex = ~0u;
35     // first explicit check
36     for (uint32_t idx = 0; idx < physicalDeviceMemoryProperties.memoryTypeCount; ++idx) {
37         if ((memoryTypeBits & (1 << idx)) &&
38             (physicalDeviceMemoryProperties.memoryTypes[idx].propertyFlags == memoryPropertyFlags)) {
39             memTypeIndex = idx;
40         }
41     }
42     // then non explicit check
43     if (memTypeIndex == ~0u) {
44         for (uint32_t idx = 0; idx < physicalDeviceMemoryProperties.memoryTypeCount; ++idx) {
45             if ((memoryTypeBits & (1 << idx)) && ((physicalDeviceMemoryProperties.memoryTypes[idx].propertyFlags &
46                                                       memoryPropertyFlags) == memoryPropertyFlags)) {
47                 memTypeIndex = idx;
48             }
49         }
50     }
51     PLUGIN_ASSERT_MSG(memTypeIndex != ~0u, "requested memory not found for hwbuffer");
52     return memTypeIndex;
53 }
54 
GetHwBufferImageCreateInfo(const GpuImageDesc & desc)55 VkImageCreateInfo GetHwBufferImageCreateInfo(const GpuImageDesc& desc)
56 {
57     // NOTE: undefined layout
58     return VkImageCreateInfo {
59         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // sType
60         nullptr,                                        // pNext
61         0,                                              // flags
62         (VkImageType)desc.imageType,                    // imageType
63         (VkFormat)desc.format,                          // format
64         { desc.width, desc.height, desc.depth },        // extent
65         desc.mipCount,                                  // mipLevels
66         desc.layerCount,                                // arrayLayers
67         (VkSampleCountFlagBits)(desc.sampleCountFlags), // samples
68         (VkImageTiling)desc.imageTiling,                // tiling
69         (VkImageUsageFlags)desc.usageFlags,             // usage
70         VkSharingMode::VK_SHARING_MODE_EXCLUSIVE,       // sharingMode
71         0,                                              // queueFamilyIndexCount
72         nullptr,                                        // pQueueFamilyIndices
73         VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,       // initialLayout
74     };
75 }
76 
GetImageMemoryRequirements(const DeviceVk & deviceVk,const VkImage image,const VkImageAspectFlags imageAspectFlags,const bool useMemoryRequirements2)77 VkMemoryRequirements GetImageMemoryRequirements(const DeviceVk& deviceVk, const VkImage image,
78     const VkImageAspectFlags imageAspectFlags, const bool useMemoryRequirements2)
79 {
80     VkMemoryRequirements memoryRequirements {
81         0, // size
82         0, // alignment
83         0, // memoryTypeBits
84     };
85     const DevicePlatformDataVk& devicePlat = ((const DevicePlatformDataVk&)deviceVk.GetPlatformData());
86     VkDevice device = devicePlat.device;
87 
88     const DeviceVk::CommonDeviceExtensions& deviceExtensions = deviceVk.GetCommonDeviceExtensions();
89     const DeviceVk::ExtFunctions& extFunctions = deviceVk.GetExtFunctions();
90     if (deviceExtensions.getMemoryRequirements2 && useMemoryRequirements2) {
91         if (extFunctions.vkGetImageMemoryRequirements2) {
92             VkImagePlaneMemoryRequirementsInfo planeMemoryRequirementsInfo {
93                 VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO, // sType
94                 nullptr,                                                // pNext
95                 (VkImageAspectFlagBits)(imageAspectFlags),              // planeAspect
96             };
97             VkImageMemoryRequirementsInfo2 imageMemoryRequirementsInfo {
98                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, // sType
99                 &planeMemoryRequirementsInfo,                       // pNext
100                 image,                                              // image
101             };
102             VkMemoryRequirements2 memoryRequirements2 {
103                 VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, // sType
104                 nullptr,                                 // pNext
105                 {},                                      // memoryRequirements
106             };
107 
108             extFunctions.vkGetImageMemoryRequirements2(device, // device
109                 &imageMemoryRequirementsInfo,                  // pInfo
110                 &memoryRequirements2);                         // pMemoryRequirements
111             memoryRequirements = memoryRequirements2.memoryRequirements;
112         }
113     } else {
114         vkGetImageMemoryRequirements(device, // device
115             image,                           // image
116             &memoryRequirements);            // pMemoryRequirements
117     }
118 
119     return memoryRequirements;
120 }
121 
DestroyHwPlatformImage(const DeviceVk & deviceVk,VkImage image,VkDeviceMemory deviceMemory)122 void DestroyHwPlatformImage(const DeviceVk& deviceVk, VkImage image, VkDeviceMemory deviceMemory)
123 {
124     VkDevice device = ((const DevicePlatformDataVk&)deviceVk.GetPlatformData()).device;
125     vkDestroyImage(device, // device
126         image,             // image
127         nullptr);          // pAllocator
128     vkFreeMemory(device,   // device
129         deviceMemory,      // memory
130         nullptr);          // pAllocator
131 }
132 
FillYcbcrConversionInfo(const DeviceVk & deviceVk,const HardwareBufferProperties & hwBufferProperties,VkSamplerYcbcrConversionCreateInfo & ycbcrConversionCreateInfo)133 void FillYcbcrConversionInfo(const DeviceVk& deviceVk, const HardwareBufferProperties& hwBufferProperties,
134     VkSamplerYcbcrConversionCreateInfo& ycbcrConversionCreateInfo)
135 {
136     constexpr VkComponentMapping componentMapping {
137         VK_COMPONENT_SWIZZLE_IDENTITY, // r
138         VK_COMPONENT_SWIZZLE_IDENTITY, // g
139         VK_COMPONENT_SWIZZLE_IDENTITY, // b
140         VK_COMPONENT_SWIZZLE_IDENTITY, // a
141     };
142     // NOTE: might not support linear (needs to be checked)
143     constexpr VkFilter hardcodedFilter = VK_FILTER_NEAREST;
144     ycbcrConversionCreateInfo = {
145         VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, // sType
146         nullptr,                                                // pNext
147         hwBufferProperties.format,                              // format
148         hwBufferProperties.suggestedYcbcrModel,                 // ycbcrModel
149         hwBufferProperties.suggestedYcbcrRange,                 // ycbcrRange
150         componentMapping,                                       // components
151         hwBufferProperties.suggestedXChromaOffset,              // xChromaOffset
152         hwBufferProperties.suggestedYChromaOffset,              // yChromaOffset
153         hardcodedFilter,                                        // chromaFilter
154         false,                                                  // forceExplicitReconstruction
155     };
156 }
157 } // namespace PlatformHardwareBufferUtil
158 RENDER_END_NAMESPACE()
159