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 "vulkan/device_vk.h"
19 #include "vulkan/gpu_image_vk.h"
20 #include "vulkan/platform_hardware_buffer_util_vk.h"
21 #include "vulkan/validate_vk.h"
22 
23 RENDER_BEGIN_NAMESPACE()
24 namespace {
CreateYcbcrSamplerCreateInfo()25 VkSamplerCreateInfo CreateYcbcrSamplerCreateInfo()
26 {
27     return VkSamplerCreateInfo {
28         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
29         nullptr,                               // pNext
30         0,                                     // flags
31         VK_FILTER_NEAREST,                     // magFilter
32         VK_FILTER_NEAREST,                     // minFilter
33         VK_SAMPLER_MIPMAP_MODE_NEAREST,        // mipmapMode
34         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
35         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
36         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
37         0.0f,                                  // mipLodBias
38         false,                                 // anisotropyEnable
39         1.0f,                                  // maxAnisotropy
40         false,                                 // compareEnabled
41         VK_COMPARE_OP_NEVER,                   // compareOp
42         0.0f,                                  // minLod
43         0.0f,                                  // maxLod
44         VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,    // borderColor
45         false,                                 // unnormalizedCoordinates
46     };
47 }
48 } // namespace
49 
CreatePlatformHwBuffer()50 void GpuImageVk::CreatePlatformHwBuffer()
51 {
52     const DeviceVk& deviceVk = (const DeviceVk&)device_;
53     const PlatformDeviceExtensions& deviceExtensions = deviceVk.GetPlatformDeviceExtensions();
54     if ((hwBuffer_ != 0) && deviceExtensions.externalMemoryHardwareBuffer) {
55         const PlatformHardwareBufferUtil::HardwareBufferProperties hwBufferProperties =
56             PlatformHardwareBufferUtil::QueryHwBufferFormatProperties(deviceVk, hwBuffer_);
57         if (hwBufferProperties.allocationSize > 0) {
58             PlatformHardwareBufferUtil::HardwareBufferImage hwBufferImage =
59                 PlatformHardwareBufferUtil::CreateHwPlatformImage(deviceVk, hwBufferProperties, desc_, hwBuffer_);
60             PLUGIN_ASSERT((hwBufferImage.image != VK_NULL_HANDLE) && ((hwBufferImage.deviceMemory != VK_NULL_HANDLE)));
61             plat_.image = hwBufferImage.image;
62             mem_.allocationInfo.deviceMemory = hwBufferImage.deviceMemory;
63 
64             if (plat_.format == VK_FORMAT_UNDEFINED) {
65                 // with external format, chained conversion info is needed
66                 VkSamplerYcbcrConversionCreateInfo ycbcrConversionCreateInfo;
67                 PlatformHardwareBufferUtil::FillYcbcrConversionInfo(
68                     deviceVk, hwBufferProperties, ycbcrConversionCreateInfo);
69 
70                 VkExternalFormatOHOS externalFormat {
71                     VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS, // sType
72                     nullptr,                                // pNext
73                     hwBufferProperties.externalFormat,      // externalFormat
74                 };
75                 ycbcrConversionCreateInfo.pNext = &externalFormat;
76 
77                 const DevicePlatformDataVk& devicePlat = (const DevicePlatformDataVk&)device_.GetPlatformData();
78                 const VkDevice vkDevice = devicePlat.device;
79 
80                 VALIDATE_VK_RESULT(deviceVk.GetExtFunctions().vkCreateSamplerYcbcrConversion(
81                     vkDevice, &ycbcrConversionCreateInfo, nullptr, &platConversion_.samplerConversion));
82 
83                 const VkSamplerYcbcrConversionInfo yCbcrConversionInfo {
84                     VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, // sType
85                     nullptr,                                         // pNext
86                     platConversion_.samplerConversion,               // conversion
87                 };
88 
89                 VkSamplerCreateInfo samplerCreateInfo = CreateYcbcrSamplerCreateInfo();
90                 samplerCreateInfo.pNext = &yCbcrConversionInfo;
91                 VALIDATE_VK_RESULT(vkCreateSampler(vkDevice, // device
92                     &samplerCreateInfo,                      // pCreateInfo
93                     nullptr,                                 // pAllocator
94                     &platConversion_.sampler));              // pSampler
95 
96                 CreateVkImageViews(VK_IMAGE_ASPECT_COLOR_BIT, &yCbcrConversionInfo);
97             } else {
98                 CreateVkImageViews(VK_IMAGE_ASPECT_COLOR_BIT, nullptr);
99             }
100         } else {
101             hwBuffer_ = 0;
102         }
103     }
104 }
105 
DestroyPlatformHwBuffer()106 void GpuImageVk::DestroyPlatformHwBuffer()
107 {
108     const DeviceVk& deviceVk = (const DeviceVk&)device_;
109     PlatformHardwareBufferUtil::DestroyHwPlatformImage(deviceVk, plat_.image, mem_.allocationInfo.deviceMemory);
110     const DevicePlatformDataVk& devicePlat = (const DevicePlatformDataVk&)device_.GetPlatformData();
111     const VkDevice device = devicePlat.device;
112     if (platConversion_.samplerConversion != VK_NULL_HANDLE) {
113         deviceVk.GetExtFunctions().vkDestroySamplerYcbcrConversion(device, // device
114             platConversion_.samplerConversion,                             // ycbcrConversion
115             nullptr);                                                      // pAllocator
116     }
117     if (platConversion_.sampler != VK_NULL_HANDLE) {
118         vkDestroySampler(device,     // device
119             platConversion_.sampler, // sampler
120             nullptr);                // pAllocator
121     }
122 }
123 RENDER_END_NAMESPACE()
124