• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/gpu/graphite/vk/VulkanYcbcrConversion.h"
9 
10 #include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
11 #include "src/gpu/graphite/vk/VulkanCaps.h"
12 #include "src/gpu/graphite/vk/VulkanGraphiteUtils.h"
13 #include "src/gpu/graphite/vk/VulkanSharedContext.h"
14 
15 namespace skgpu::graphite {
16 
17 namespace {
18 
19 static constexpr int kUsesExternalFormatBits  = 1;
20 static constexpr int kYcbcrModelBits          = 3;
21 static constexpr int kYcbcrRangeBits          = 1;
22 static constexpr int kXChromaOffsetBits       = 1;
23 static constexpr int kYChromaOffsetBits       = 1;
24 static constexpr int kChromaFilterBits        = 1;
25 static constexpr int kForceExplicitReconBits  = 1;
26 static constexpr int kComponentBits           = 3;
27 
28 static constexpr int kUsesExternalFormatShift = 0;
29 static constexpr int kYcbcrModelShift         = kUsesExternalFormatShift +
30                                                 kUsesExternalFormatBits;
31 static constexpr int kYcbcrRangeShift         = kYcbcrModelShift         + kYcbcrModelBits;
32 static constexpr int kXChromaOffsetShift      = kYcbcrRangeShift         + kYcbcrRangeBits;
33 static constexpr int kYChromaOffsetShift      = kXChromaOffsetShift      + kXChromaOffsetBits;
34 static constexpr int kChromaFilterShift       = kYChromaOffsetShift      + kYChromaOffsetBits;
35 static constexpr int kForceExplicitReconShift = kChromaFilterShift       + kChromaFilterBits;
36 static constexpr int kComponentRShift         = kForceExplicitReconShift + kComponentBits;
37 static constexpr int kComponentGShift         = kComponentRShift         + kComponentBits;
38 static constexpr int kComponentBShift         = kComponentGShift         + kComponentBits;
39 static constexpr int kComponentAShift         = kComponentBShift         + kComponentBits;
40 
41 static constexpr uint32_t kUseExternalFormatMask =
42         ((1 << kUsesExternalFormatBits) - 1) << kUsesExternalFormatShift;
43 static constexpr uint32_t kYcbcrModelMask =
44         ((1 << kYcbcrModelBits) - 1) << kYcbcrModelShift;
45 static constexpr uint32_t kYcbcrRangeMask =
46         ((1 << kYcbcrRangeBits) - 1) << kYcbcrRangeShift;
47 static constexpr uint32_t kXChromaOffsetMask =
48         ((1 << kXChromaOffsetBits) - 1) << kXChromaOffsetShift;
49 static constexpr uint32_t kYChromaOffsetMask =
50         ((1 << kYChromaOffsetBits) - 1) << kYChromaOffsetShift;
51 static constexpr uint32_t kChromaFilterMask =
52         ((1 << kChromaFilterBits) - 1) << kChromaFilterShift;
53 static constexpr uint32_t kForceExplicitReconMask =
54         ((1 << kForceExplicitReconBits) - 1) << kForceExplicitReconShift;
55 static constexpr uint32_t kComponentRMask = ((1 << kComponentBits) - 1) << kComponentRShift;
56 static constexpr uint32_t kComponentBMask = ((1 << kComponentBits) - 1) << kComponentGShift;
57 static constexpr uint32_t kComponentGMask = ((1 << kComponentBits) - 1) << kComponentBShift;
58 static constexpr uint32_t kComponentAMask = ((1 << kComponentBits) - 1) << kComponentAShift;
59 
60 }  // anonymous namespace
61 
Make(const VulkanSharedContext * context,const VulkanYcbcrConversionInfo & conversionInfo)62 sk_sp<VulkanYcbcrConversion> VulkanYcbcrConversion::Make(
63         const VulkanSharedContext* context, const VulkanYcbcrConversionInfo& conversionInfo) {
64     if (!context->vulkanCaps().supportsYcbcrConversion()) {
65         return nullptr;
66     }
67 
68     VkSamplerYcbcrConversionCreateInfo ycbcrCreateInfo;
69     skgpu::SetupSamplerYcbcrConversionInfo(&ycbcrCreateInfo, conversionInfo);
70 
71 #ifdef SK_BUILD_FOR_ANDROID
72     VkExternalFormatANDROID externalFormat;
73     if (conversionInfo.fExternalFormat) {
74         // Format must not be specified for external images.
75         SkASSERT(conversionInfo.fFormat == VK_FORMAT_UNDEFINED);
76         externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
77         externalFormat.pNext = nullptr;
78         externalFormat.externalFormat = conversionInfo.fExternalFormat;
79         SkASSERT(ycbcrCreateInfo.pNext == nullptr);
80         ycbcrCreateInfo.pNext = &externalFormat;
81     }
82 #else
83     // External images are supported only on Android.
84     SkASSERT(!conversionInfo.fExternalFormat);
85 #endif
86 
87     if (!conversionInfo.fExternalFormat) {
88         SkASSERT(conversionInfo.fFormat != VK_FORMAT_UNDEFINED);
89     }
90 
91     VkSamplerYcbcrConversion conversion;
92     VkResult result;
93     VULKAN_CALL_RESULT(context,
94                        result,
95                        CreateSamplerYcbcrConversion(
96                                context->device(), &ycbcrCreateInfo, nullptr, &conversion));
97     if (result != VK_SUCCESS) {
98         return nullptr;
99     }
100     return sk_sp<VulkanYcbcrConversion>(new VulkanYcbcrConversion(context, conversion));
101 }
102 
ToImmutableSamplerInfo(const VulkanYcbcrConversionInfo & conversionInfo)103 ImmutableSamplerInfo VulkanYcbcrConversion::ToImmutableSamplerInfo(
104         const VulkanYcbcrConversionInfo& conversionInfo) {
105     SkASSERT(conversionInfo.isValid());
106 
107     static_assert(kComponentAShift + kComponentBits <= 32);
108 
109     SkASSERT(conversionInfo.fYcbcrModel                  < (1u << kYcbcrModelBits        ));
110     SkASSERT(conversionInfo.fYcbcrRange                  < (1u << kYcbcrRangeBits        ));
111     SkASSERT(conversionInfo.fXChromaOffset               < (1u << kXChromaOffsetBits     ));
112     SkASSERT(conversionInfo.fYChromaOffset               < (1u << kYChromaOffsetBits     ));
113     SkASSERT(conversionInfo.fChromaFilter                < (1u << kChromaFilterBits      ));
114     SkASSERT(conversionInfo.fForceExplicitReconstruction < (1u << kForceExplicitReconBits));
115     SkASSERT(conversionInfo.fComponents.r                < (1u << kComponentBits         ));
116     SkASSERT(conversionInfo.fComponents.g                < (1u << kComponentBits         ));
117     SkASSERT(conversionInfo.fComponents.b                < (1u << kComponentBits         ));
118     SkASSERT(conversionInfo.fComponents.a                < (1u << kComponentBits         ));
119 
120     const bool usesExternalFormat = conversionInfo.fFormat == VK_FORMAT_UNDEFINED;
121 
122     ImmutableSamplerInfo info;
123     info.fNonFormatYcbcrConversionInfo =
124             (((uint32_t)(usesExternalFormat                         ) << kUsesExternalFormatShift) |
125              ((uint32_t)(conversionInfo.fYcbcrModel                 ) << kYcbcrModelShift        ) |
126              ((uint32_t)(conversionInfo.fYcbcrRange                 ) << kYcbcrRangeShift        ) |
127              ((uint32_t)(conversionInfo.fXChromaOffset              ) << kXChromaOffsetShift     ) |
128              ((uint32_t)(conversionInfo.fYChromaOffset              ) << kYChromaOffsetShift     ) |
129              ((uint32_t)(conversionInfo.fChromaFilter               ) << kChromaFilterShift      ) |
130              ((uint32_t)(conversionInfo.fForceExplicitReconstruction) << kForceExplicitReconShift) |
131              ((uint32_t)(conversionInfo.fComponents.r               ) << kComponentRShift        ) |
132              ((uint32_t)(conversionInfo.fComponents.g               ) << kComponentGShift        ) |
133              ((uint32_t)(conversionInfo.fComponents.b               ) << kComponentBShift        ) |
134              ((uint32_t)(conversionInfo.fComponents.a               ) << kComponentAShift        ));
135     info.fFormat = usesExternalFormat  ? conversionInfo.fExternalFormat : conversionInfo.fFormat;
136     return info;
137 }
138 
FromImmutableSamplerInfo(ImmutableSamplerInfo info)139 VulkanYcbcrConversionInfo VulkanYcbcrConversion::FromImmutableSamplerInfo(
140         ImmutableSamplerInfo info) {
141     const uint32_t nonFormatInfo = info.fNonFormatYcbcrConversionInfo;
142 
143     VulkanYcbcrConversionInfo vkInfo;
144     const bool usesExternalFormat =
145             (nonFormatInfo >> kUsesExternalFormatShift) & kUseExternalFormatMask;
146     if (usesExternalFormat) {
147         vkInfo.fFormat = VK_FORMAT_UNDEFINED;
148         vkInfo.fExternalFormat = info.fFormat;
149     } else {
150         vkInfo.fFormat = static_cast<VkFormat>(info.fFormat);
151         vkInfo.fExternalFormat = 0;
152     }
153 
154     vkInfo.fYcbcrModel    =   static_cast<VkSamplerYcbcrModelConversion>(
155                                       (nonFormatInfo & kYcbcrModelMask) >> kYcbcrModelShift);
156     vkInfo.fYcbcrRange    =   static_cast<VkSamplerYcbcrRange>(
157                                       (nonFormatInfo & kYcbcrRangeMask) >> kYcbcrRangeShift);
158     vkInfo.fComponents    = { static_cast<VkComponentSwizzle>(
159                                       (nonFormatInfo & kComponentRMask) >> kComponentRShift),
160                               static_cast<VkComponentSwizzle>(
161                                       (nonFormatInfo & kComponentGMask) >> kComponentGShift),
162                               static_cast<VkComponentSwizzle>(
163                                       (nonFormatInfo & kComponentBMask) >> kComponentBShift),
164                               static_cast<VkComponentSwizzle>(
165                                       (nonFormatInfo & kComponentAMask) >> kComponentAShift) };
166     vkInfo.fXChromaOffset =   static_cast<VkChromaLocation>(
167                                       (nonFormatInfo & kXChromaOffsetMask) >> kXChromaOffsetShift);
168     vkInfo.fYChromaOffset =   static_cast<VkChromaLocation>(
169                                       (nonFormatInfo & kYChromaOffsetMask) >> kYChromaOffsetShift);
170     vkInfo.fChromaFilter  =   static_cast<VkFilter>(
171                                       (nonFormatInfo & kChromaFilterMask) >> kChromaFilterShift);
172 
173     vkInfo.fForceExplicitReconstruction = static_cast<VkBool32>(
174                     (nonFormatInfo & kForceExplicitReconMask) >> kForceExplicitReconShift);
175 
176     return vkInfo;
177 }
178 
VulkanYcbcrConversion(const VulkanSharedContext * context,VkSamplerYcbcrConversion ycbcrConversion)179 VulkanYcbcrConversion::VulkanYcbcrConversion(const VulkanSharedContext* context,
180                                              VkSamplerYcbcrConversion ycbcrConversion)
181         : Resource(context,
182                    Ownership::kOwned,
183                    /*gpuMemorySize=*/0)
184         , fYcbcrConversion (ycbcrConversion) {}
185 
freeGpuData()186 void VulkanYcbcrConversion::freeGpuData() {
187     auto sharedContext = static_cast<const VulkanSharedContext*>(this->sharedContext());
188     SkASSERT(fYcbcrConversion != VK_NULL_HANDLE);
189     VULKAN_CALL(sharedContext->interface(),
190                 DestroySamplerYcbcrConversion(sharedContext->device(), fYcbcrConversion, nullptr));
191 }
192 
193 } // namespace skgpu::graphite
194