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 "gpu_sampler_vk.h"
17 
18 #include <vulkan/vulkan_core.h>
19 
20 #include <render/device/gpu_resource_desc.h>
21 #include <render/namespace.h>
22 
23 #include "device/device.h"
24 #include "vulkan/device_vk.h"
25 #include "vulkan/platform_hardware_buffer_util_vk.h"
26 #include "vulkan/validate_vk.h"
27 
28 RENDER_BEGIN_NAMESPACE()
29 namespace {
CreateYcbcrConversion(const DeviceVk & deviceVk,const GpuSamplerDesc & desc)30 VkSamplerYcbcrConversion CreateYcbcrConversion(const DeviceVk& deviceVk, const GpuSamplerDesc& desc)
31 {
32     const DevicePlatformDataVk& devicePlat = (const DevicePlatformDataVk&)deviceVk.GetPlatformData();
33     VkSamplerYcbcrConversion samplerYcbcrConversion = VK_NULL_HANDLE;
34     const VkDevice vkDevice = devicePlat.device;
35     // NOTE: should be queried from image (hwbuffer)
36     PlatformHardwareBufferUtil::HardwareBufferProperties hwBufferProperties;
37     VkSamplerYcbcrConversionCreateInfo ycbcrConversionInfo;
38     PlatformHardwareBufferUtil::FillYcbcrConversionInfo(deviceVk, hwBufferProperties, ycbcrConversionInfo);
39     VALIDATE_VK_RESULT(deviceVk.GetExtFunctions().vkCreateSamplerYcbcrConversion(
40         vkDevice, &ycbcrConversionInfo, nullptr, &samplerYcbcrConversion));
41 
42     return samplerYcbcrConversion;
43 }
44 } // namespace
45 
GpuSamplerVk(Device & device,const GpuSamplerDesc & desc)46 GpuSamplerVk::GpuSamplerVk(Device& device, const GpuSamplerDesc& desc) : device_(device), desc_(desc)
47 {
48     VkSamplerCreateInfo samplerCreateInfo = {
49         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // sType
50         nullptr,                                 // pNext
51         0,                                       // flags
52         (VkFilter)desc.magFilter,                // magFilter
53         (VkFilter)desc.minFilter,                // minFilter
54         (VkSamplerMipmapMode)desc.mipMapMode,    // mipmapMode
55         (VkSamplerAddressMode)desc.addressModeU, // addressModeU
56         (VkSamplerAddressMode)desc.addressModeV, // addressModeV
57         (VkSamplerAddressMode)desc.addressModeW, // addressModeW
58         desc.mipLodBias,                         // mipLodBias
59         desc.enableAnisotropy,                   // anisotropyEnable
60         desc.maxAnisotropy,                      // maxAnisotropy
61         desc.enableCompareOp,                    // compareEnabled
62         (VkCompareOp)desc.compareOp,             // compareOp
63         desc.minLod,                             // minLod
64         desc.maxLod,                             // maxLod
65         (VkBorderColor)desc.borderColor,         // borderColor
66         desc.enableUnnormalizedCoordinates,      // unnormalizedCoordinates
67     };
68 
69     const DeviceVk& deviceVk = (const DeviceVk&)device_;
70     const DevicePlatformDataVk& devicePlat = (const DevicePlatformDataVk&)device_.GetPlatformData();
71     const VkDevice vkDevice = devicePlat.device;
72     if ((desc.engineCreationFlags & CORE_ENGINE_SAMPLER_CREATION_YCBCR) &&
73         deviceVk.GetCommonDeviceExtensions().samplerYcbcrConversion) {
74         samplerConversion_ = CreateYcbcrConversion(deviceVk, desc_);
75         VkSamplerYcbcrConversionInfo yCbcrConversionInfo {
76             VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, // sType
77             nullptr,                                         // pNext
78             samplerConversion_,                              // conversion
79         };
80         samplerCreateInfo.pNext = &yCbcrConversionInfo;
81         VALIDATE_VK_RESULT(vkCreateSampler(vkDevice, // device
82             &samplerCreateInfo,                      // pCreateInfo
83             nullptr,                                 // pAllocator
84             &plat_.sampler));                        // pSampler
85     } else {
86         VALIDATE_VK_RESULT(vkCreateSampler(vkDevice, // device
87             &samplerCreateInfo,                      // pCreateInfo
88             nullptr,                                 // pAllocator
89             &plat_.sampler));                        // pSampler
90     }
91 }
92 
~GpuSamplerVk()93 GpuSamplerVk::~GpuSamplerVk()
94 {
95     const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
96     if (samplerConversion_ != VK_NULL_HANDLE) {
97         ((const DeviceVk&)device_)
98             .GetExtFunctions()
99             .vkDestroySamplerYcbcrConversion(device, // device
100                 samplerConversion_,                  // ycbcrConversion
101                 nullptr);                            // pAllocator
102     }
103     vkDestroySampler(device, // device
104         plat_.sampler,       // sampler
105         nullptr);            // pAllocator
106 }
107 
GetDesc() const108 const GpuSamplerDesc& GpuSamplerVk::GetDesc() const
109 {
110     return desc_;
111 }
112 
GetPlatformData() const113 const GpuSamplerPlatformDataVk& GpuSamplerVk::GetPlatformData() const
114 {
115     return plat_;
116 }
117 RENDER_END_NAMESPACE()
118