• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Google LLC
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 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
8 
9 #include "include/core/SkRefCnt.h"
10 #include "include/core/SkTextureCompressionType.h"
11 #include "include/gpu/GpuTypes.h"
12 #include "include/gpu/GrBackendSurface.h"
13 #include "include/gpu/GrTypes.h"
14 #include "include/gpu/MutableTextureState.h"
15 #include "include/gpu/vk/GrVkTypes.h"
16 #include "include/gpu/vk/VulkanMutableTextureState.h"
17 #include "include/private/base/SkAssert.h"
18 #include "include/private/base/SkTo.h"
19 #include "include/private/gpu/ganesh/GrTypesPriv.h"
20 #include "src/gpu/ganesh/GrBackendSurfacePriv.h"
21 #include "src/gpu/ganesh/vk/GrVkTypesPriv.h"
22 #include "src/gpu/ganesh/vk/GrVkUtil.h"
23 #include "src/gpu/vk/VulkanMutableTextureStatePriv.h"
24 #include "src/gpu/vk/VulkanUtilsPriv.h"
25 
26 #include <algorithm>
27 #include <cstddef>
28 #include <cstdint>
29 #include <string>
30 
31 class GrVkBackendFormatData final : public GrBackendFormatData {
32 public:
GrVkBackendFormatData(VkFormat format,const GrVkYcbcrConversionInfo & ycbcrInfo)33     GrVkBackendFormatData(VkFormat format, const GrVkYcbcrConversionInfo& ycbcrInfo)
34             : fFormat(format), fYcbcrConversionInfo(ycbcrInfo) {}
35 
asVkFormat() const36     VkFormat asVkFormat() const { return fFormat; }
getYcbcrConversionInfo() const37     const GrVkYcbcrConversionInfo* getYcbcrConversionInfo() const { return &fYcbcrConversionInfo; }
38 
39 private:
compressionType() const40     SkTextureCompressionType compressionType() const override {
41         switch (fFormat) {
42             case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
43                 return SkTextureCompressionType::kETC2_RGB8_UNORM;
44             case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
45                 return SkTextureCompressionType::kBC1_RGB8_UNORM;
46             case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
47                 return SkTextureCompressionType::kBC1_RGBA8_UNORM;
48             default:
49                 return SkTextureCompressionType::kNone;
50         }
51     }
52 
bytesPerBlock() const53     size_t bytesPerBlock() const override {
54         return skgpu::VkFormatBytesPerBlock(fFormat);
55     }
56 
stencilBits() const57     int stencilBits() const override {
58         return skgpu::VkFormatStencilBits(fFormat);
59     }
60 
channelMask() const61     uint32_t channelMask() const override {
62         return skgpu::VkFormatChannels(fFormat);
63     }
64 
desc() const65     GrColorFormatDesc desc() const override {
66         return GrVkFormatDesc(fFormat);
67     }
68 
equal(const GrBackendFormatData * that) const69     bool equal(const GrBackendFormatData* that) const override {
70         SkASSERT(!that || that->type() == GrBackendApi::kVulkan);
71         if (auto otherVk = static_cast<const GrVkBackendFormatData*>(that)) {
72             return fFormat == otherVk->fFormat &&
73                    fYcbcrConversionInfo == otherVk->fYcbcrConversionInfo;
74         }
75         return false;
76     }
77 
toString() const78     std::string toString() const override {
79 #if defined(SK_DEBUG) || GR_TEST_UTILS
80         return skgpu::VkFormatToStr(fFormat);
81 #else
82         return "";
83 #endif
84     }
85 
copyTo(AnyFormatData & formatData) const86     void copyTo(AnyFormatData& formatData) const override {
87         formatData.emplace<GrVkBackendFormatData>(fFormat, fYcbcrConversionInfo);
88     }
89 
makeTexture2D()90     void makeTexture2D() override {
91         // If we have a ycbcr we remove it from the backend format and set the VkFormat to
92         // R8G8B8A8_UNORM
93         if (fYcbcrConversionInfo.isValid()) {
94             fYcbcrConversionInfo = GrVkYcbcrConversionInfo();
95             fFormat = VK_FORMAT_R8G8B8A8_UNORM;
96         }
97     }
98 
99 #if defined(SK_DEBUG)
type() const100     GrBackendApi type() const override { return GrBackendApi::kVulkan; }
101 #endif
102 
103     VkFormat fFormat;
104     GrVkYcbcrConversionInfo fYcbcrConversionInfo;
105 };
106 
get_and_cast_data(const GrBackendFormat & format)107 static const GrVkBackendFormatData* get_and_cast_data(const GrBackendFormat& format) {
108     auto data = GrBackendSurfacePriv::GetBackendData(format);
109     SkASSERT(!data || data->type() == GrBackendApi::kVulkan);
110     return static_cast<const GrVkBackendFormatData*>(data);
111 }
112 
113 namespace GrBackendFormats {
114 
MakeVk(VkFormat format,bool willUseDRMFormatModifiers)115 GrBackendFormat MakeVk(VkFormat format, bool willUseDRMFormatModifiers) {
116     return GrBackendSurfacePriv::MakeGrBackendFormat(
117             GrTextureType::k2D,
118             GrBackendApi::kVulkan,
119             GrVkBackendFormatData(format, GrVkYcbcrConversionInfo{}));
120 }
121 
MakeVk(const GrVkYcbcrConversionInfo & ycbcrInfo,bool willUseDRMFormatModifiers)122 GrBackendFormat MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo, bool willUseDRMFormatModifiers) {
123     SkASSERT(ycbcrInfo.isValid());
124     GrTextureType textureType =
125             ((ycbcrInfo.isValid() && ycbcrInfo.fExternalFormat) || willUseDRMFormatModifiers)
126                     ? GrTextureType::kExternal
127                     : GrTextureType::k2D;
128     return GrBackendSurfacePriv::MakeGrBackendFormat(
129             textureType,
130             GrBackendApi::kVulkan,
131             GrVkBackendFormatData(ycbcrInfo.fFormat, ycbcrInfo));
132 }
133 
AsVkFormat(const GrBackendFormat & format,VkFormat * vkFormat)134 bool AsVkFormat(const GrBackendFormat& format, VkFormat* vkFormat) {
135     SkASSERT(vkFormat);
136     if (format.isValid() && format.backend() == GrBackendApi::kVulkan) {
137         const GrVkBackendFormatData* data = get_and_cast_data(format);
138         SkASSERT(data);
139         *vkFormat = data->asVkFormat();
140         return true;
141     }
142     return false;
143 }
144 
GetVkYcbcrConversionInfo(const GrBackendFormat & format)145 const GrVkYcbcrConversionInfo* GetVkYcbcrConversionInfo(const GrBackendFormat& format) {
146     if (format.isValid() && format.backend() == GrBackendApi::kVulkan) {
147         const GrVkBackendFormatData* data = get_and_cast_data(format);
148         SkASSERT(data);
149         return data->getYcbcrConversionInfo();
150     }
151     return nullptr;
152 }
153 
154 }  // namespace GrBackendFormats
155 
156 
157 class GrVkBackendTextureData final : public GrBackendTextureData {
158 public:
GrVkBackendTextureData(const GrVkImageInfo & info,sk_sp<skgpu::MutableTextureState> mutableState=nullptr)159     GrVkBackendTextureData(const GrVkImageInfo& info,
160                            sk_sp<skgpu::MutableTextureState> mutableState = nullptr)
161             : fVkInfo(info) {
162         if (mutableState) {
163             fMutableState = std::move(mutableState);
164         } else {
165             fMutableState =
166                     sk_make_sp<skgpu::MutableTextureState>(skgpu::MutableTextureStates::MakeVulkan(
167                             info.fImageLayout, info.fCurrentQueueFamily));
168         }
169     }
170 
info() const171     const GrVkImageInfo& info() const { return fVkInfo; }
172 
getMutableState() const173     sk_sp<skgpu::MutableTextureState> getMutableState() const override {
174         return fMutableState;
175     }
setMutableState(const skgpu::MutableTextureState & state)176     void setMutableState(const skgpu::MutableTextureState& state) override {
177         fMutableState->set(state);
178     }
179 
mutableState()180     skgpu::MutableTextureState* mutableState() { return fMutableState.get(); }
mutableState() const181     const skgpu::MutableTextureState* mutableState() const { return fMutableState.get(); }
182 
183 private:
copyTo(AnyTextureData & textureData) const184     void copyTo(AnyTextureData& textureData) const override {
185         textureData.emplace<GrVkBackendTextureData>(fVkInfo, fMutableState);
186     }
187 
isProtected() const188     bool isProtected() const override { return fVkInfo.fProtected == skgpu::Protected::kYes; }
189 
equal(const GrBackendTextureData * that) const190     bool equal(const GrBackendTextureData* that) const override {
191         SkASSERT(!that || that->type() == GrBackendApi::kVulkan);
192         if (auto otherVk = static_cast<const GrVkBackendTextureData*>(that)) {
193             // For our tests when checking equality we are assuming both backendTexture objects will
194             // be using the same mutable state object.
195             if (fMutableState != otherVk->fMutableState) {
196                 return false;
197             }
198             return GrVkImageInfoWithMutableState(fVkInfo, fMutableState.get()) ==
199                    GrVkImageInfoWithMutableState(otherVk->fVkInfo, fMutableState.get());
200         }
201         return false;
202     }
203 
isSameTexture(const GrBackendTextureData * that) const204     bool isSameTexture(const GrBackendTextureData* that) const override {
205         SkASSERT(!that || that->type() == GrBackendApi::kVulkan);
206         if (auto otherVk = static_cast<const GrVkBackendTextureData*>(that)) {
207             return fVkInfo.fImage == otherVk->fVkInfo.fImage;
208         }
209         return false;
210 
211     }
212 
getBackendFormat() const213     GrBackendFormat getBackendFormat() const override {
214         auto info = GrVkImageInfoWithMutableState(fVkInfo, fMutableState.get());
215         bool usesDRMModifier = info.fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
216         if (info.fYcbcrConversionInfo.isValid()) {
217             SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
218             return GrBackendFormats::MakeVk(info.fYcbcrConversionInfo, usesDRMModifier);
219         }
220         return GrBackendFormats::MakeVk(info.fFormat, usesDRMModifier);
221     }
222 
223 #if defined(SK_DEBUG)
type() const224     GrBackendApi type() const override { return GrBackendApi::kVulkan; }
225 #endif
226 
227     GrVkImageInfo fVkInfo;
228     sk_sp<skgpu::MutableTextureState> fMutableState;
229 };
230 
get_and_cast_data(const GrBackendTexture & texture)231 static const GrVkBackendTextureData* get_and_cast_data(const GrBackendTexture& texture) {
232     auto data = GrBackendSurfacePriv::GetBackendData(texture);
233     SkASSERT(!data || data->type() == GrBackendApi::kVulkan);
234     return static_cast<const GrVkBackendTextureData*>(data);
235 }
236 
get_and_cast_data(GrBackendTexture * texture)237 static GrVkBackendTextureData* get_and_cast_data(GrBackendTexture* texture) {
238     auto data = GrBackendSurfacePriv::GetBackendData(texture);
239     SkASSERT(!data || data->type() == GrBackendApi::kVulkan);
240     return static_cast<GrVkBackendTextureData*>(data);
241 }
242 
vk_image_info_to_texture_type(const GrVkImageInfo & info)243 static GrTextureType vk_image_info_to_texture_type(const GrVkImageInfo& info) {
244     if ((info.fYcbcrConversionInfo.isValid() && info.fYcbcrConversionInfo.fExternalFormat != 0) ||
245         info.fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
246         return GrTextureType::kExternal;
247     }
248     return GrTextureType::k2D;
249 }
250 
251 static const VkImageUsageFlags kDefaultUsageFlags =
252         VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
253 
254 static const VkImageUsageFlags kDefaultRTUsageFlags =
255         kDefaultUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
256 
257 // We don't know if the backend texture is made renderable or not, so we default the usage flags
258 // to include color attachment as well.
259 static const VkImageUsageFlags kDefaultTexRTUsageFlags =
260         kDefaultUsageFlags | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
261 
apply_default_usage_flags(const GrVkImageInfo & info,VkImageUsageFlags defaultFlags)262 static GrVkImageInfo apply_default_usage_flags(const GrVkImageInfo& info,
263                                                VkImageUsageFlags defaultFlags) {
264     if (info.fImageUsageFlags == 0) {
265         GrVkImageInfo newInfo = info;
266         newInfo.fImageUsageFlags = defaultFlags;
267         return newInfo;
268     }
269     return info;
270 }
271 
272 namespace GrBackendTextures {
273 
MakeVk(int width,int height,const GrVkImageInfo & vkInfo,std::string_view label)274 GrBackendTexture MakeVk(int width,
275                         int height,
276                         const GrVkImageInfo& vkInfo,
277                         std::string_view label) {
278     return GrBackendSurfacePriv::MakeGrBackendTexture(
279             width,
280             height,
281             label,
282             skgpu::Mipmapped(vkInfo.fLevelCount > 1),
283             GrBackendApi::kVulkan,
284             vk_image_info_to_texture_type(vkInfo),
285             GrVkBackendTextureData(apply_default_usage_flags(vkInfo, kDefaultTexRTUsageFlags)));
286 }
287 
MakeVk(int width,int height,const GrVkImageInfo & vkInfo,sk_sp<skgpu::MutableTextureState> mutableState)288 GrBackendTexture MakeVk(int width,
289                         int height,
290                         const GrVkImageInfo& vkInfo,
291                         sk_sp<skgpu::MutableTextureState> mutableState) {
292     return GrBackendSurfacePriv::MakeGrBackendTexture(
293             width,
294             height,
295             /*label=*/{},
296             skgpu::Mipmapped(vkInfo.fLevelCount > 1),
297             GrBackendApi::kVulkan,
298             vk_image_info_to_texture_type(vkInfo),
299             GrVkBackendTextureData(apply_default_usage_flags(vkInfo, kDefaultTexRTUsageFlags),
300                                    std::move(mutableState)));
301 }
302 
GetVkImageInfo(const GrBackendTexture & tex,GrVkImageInfo * outInfo)303 bool GetVkImageInfo(const GrBackendTexture& tex, GrVkImageInfo* outInfo) {
304     if (!tex.isValid() || tex.backend() != GrBackendApi::kVulkan) {
305         return false;
306     }
307     const GrVkBackendTextureData* data = get_and_cast_data(tex);
308     SkASSERT(data);
309     *outInfo = GrVkImageInfoWithMutableState(data->info(), data->mutableState());
310     return true;
311 }
312 
SetVkImageLayout(GrBackendTexture * tex,VkImageLayout layout)313 void SetVkImageLayout(GrBackendTexture* tex, VkImageLayout layout) {
314     if (tex && tex->isValid() && tex->backend() == GrBackendApi::kVulkan) {
315         GrVkBackendTextureData* data = get_and_cast_data(tex);
316         SkASSERT(data);
317         skgpu::MutableTextureStates::SetVkImageLayout(data->mutableState(), layout);
318     }
319 }
320 
321 }  // namespace GrBackendTextures
322 
323 
324 class GrVkBackendRenderTargetData final : public GrBackendRenderTargetData {
325 public:
GrVkBackendRenderTargetData(const GrVkImageInfo & info,sk_sp<skgpu::MutableTextureState> mutableState=nullptr)326     GrVkBackendRenderTargetData(const GrVkImageInfo& info,
327                                 sk_sp<skgpu::MutableTextureState> mutableState = nullptr)
328             : fVkInfo(info) {
329         if (mutableState) {
330             fMutableState = std::move(mutableState);
331         } else {
332             fMutableState =
333                     sk_make_sp<skgpu::MutableTextureState>(skgpu::MutableTextureStates::MakeVulkan(
334                             info.fImageLayout, info.fCurrentQueueFamily));
335         }
336     }
337 
info() const338     const GrVkImageInfo& info() const { return fVkInfo; }
339 
getMutableState() const340     sk_sp<skgpu::MutableTextureState> getMutableState() const override {
341         return fMutableState;
342     }
setMutableState(const skgpu::MutableTextureState & state)343     void setMutableState(const skgpu::MutableTextureState& state) override {
344         fMutableState->set(state);
345     }
346 
mutableState()347     skgpu::MutableTextureState* mutableState() { return fMutableState.get(); }
mutableState() const348     const skgpu::MutableTextureState* mutableState() const { return fMutableState.get(); }
349 
350 private:
getBackendFormat() const351     GrBackendFormat getBackendFormat() const override {
352         auto info = GrVkImageInfoWithMutableState(fVkInfo, fMutableState.get());
353         if (info.fYcbcrConversionInfo.isValid()) {
354             SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
355             return GrBackendFormats::MakeVk(info.fYcbcrConversionInfo);
356         }
357         return GrBackendFormats::MakeVk(info.fFormat);
358     }
359 
isProtected() const360     bool isProtected() const override { return fVkInfo.fProtected == skgpu::Protected::kYes; }
361 
equal(const GrBackendRenderTargetData * that) const362     bool equal(const GrBackendRenderTargetData* that) const override {
363         SkASSERT(!that || that->type() == GrBackendApi::kVulkan);
364         if (auto otherVk = static_cast<const GrVkBackendRenderTargetData*>(that)) {
365             // For our tests when checking equality we are assuming both objects will be using the
366             // same mutable state object.
367             if (fMutableState != otherVk->fMutableState) {
368                 return false;
369             }
370             return GrVkImageInfoWithMutableState(fVkInfo, fMutableState.get()) ==
371                    GrVkImageInfoWithMutableState(otherVk->fVkInfo, fMutableState.get());
372         }
373         return false;
374     }
375 
copyTo(AnyRenderTargetData & rtData) const376     void copyTo(AnyRenderTargetData& rtData) const override {
377         rtData.emplace<GrVkBackendRenderTargetData>(fVkInfo, fMutableState);
378     }
379 
380 #if defined(SK_DEBUG)
type() const381     GrBackendApi type() const override { return GrBackendApi::kVulkan; }
382 #endif
383 
384     GrVkImageInfo fVkInfo;
385     sk_sp<skgpu::MutableTextureState> fMutableState;
386 };
387 
get_and_cast_data(const GrBackendRenderTarget & rt)388 static const GrVkBackendRenderTargetData* get_and_cast_data(const GrBackendRenderTarget& rt) {
389     auto data = GrBackendSurfacePriv::GetBackendData(rt);
390     SkASSERT(!data || data->type() == GrBackendApi::kVulkan);
391     return static_cast<const GrVkBackendRenderTargetData*>(data);
392 }
393 
get_and_cast_data(GrBackendRenderTarget * rt)394 static GrVkBackendRenderTargetData* get_and_cast_data(GrBackendRenderTarget* rt) {
395     auto data = GrBackendSurfacePriv::GetBackendData(rt);
396     SkASSERT(!data || data->type() == GrBackendApi::kVulkan);
397     return static_cast<GrVkBackendRenderTargetData*>(data);
398 }
399 
400 namespace GrBackendRenderTargets {
401 
MakeVk(int width,int height,const GrVkImageInfo & vkInfo)402 GrBackendRenderTarget MakeVk(int width, int height, const GrVkImageInfo& vkInfo) {
403     return GrBackendSurfacePriv::MakeGrBackendRenderTarget(
404             width,
405             height,
406             std::max(1U, vkInfo.fSampleCount),
407             /*stencilBits=*/0,
408             GrBackendApi::kVulkan,
409             /*framebufferOnly=*/false,
410             GrVkBackendRenderTargetData(apply_default_usage_flags(vkInfo, kDefaultRTUsageFlags)));
411 }
412 
MakeVk(int width,int height,const GrVkImageInfo & vkInfo,sk_sp<skgpu::MutableTextureState> mutableState)413 GrBackendRenderTarget MakeVk(int width,
414                              int height,
415                              const GrVkImageInfo& vkInfo,
416                              sk_sp<skgpu::MutableTextureState> mutableState) {
417     return GrBackendSurfacePriv::MakeGrBackendRenderTarget(
418             width,
419             height,
420             std::max(1U, vkInfo.fSampleCount),
421             /*stencilBits=*/0,
422             GrBackendApi::kVulkan,
423             /*framebufferOnly=*/false,
424             GrVkBackendRenderTargetData(apply_default_usage_flags(vkInfo, kDefaultRTUsageFlags),
425                                         std::move(mutableState)));
426 }
427 
GetVkImageInfo(const GrBackendRenderTarget & rt,GrVkImageInfo * outInfo)428 bool GetVkImageInfo(const GrBackendRenderTarget& rt, GrVkImageInfo* outInfo) {
429     if (!rt.isValid() || rt.backend() != GrBackendApi::kVulkan) {
430         return false;
431     }
432     const GrVkBackendRenderTargetData* data = get_and_cast_data(rt);
433     SkASSERT(data);
434     *outInfo = GrVkImageInfoWithMutableState(data->info(), data->mutableState());
435     return true;
436 }
437 
SetVkImageLayout(GrBackendRenderTarget * rt,VkImageLayout layout)438 void SetVkImageLayout(GrBackendRenderTarget* rt, VkImageLayout layout) {
439     if (rt && rt->isValid() && rt->backend() == GrBackendApi::kVulkan) {
440         GrVkBackendRenderTargetData* data = get_and_cast_data(rt);
441         skgpu::MutableTextureStates::SetVkImageLayout(data->mutableState(), layout);
442     }
443 }
444 
445 }  // namespace GrBackendRenderTargets
446