Skip to content

Commit 3aa442e

Browse files
lhkbobSkCQ
authored andcommitted
[graphite] Lift colortype to format choice out of backends
Adds a new PreferredFormatForColorType static function that takes an SkColorType and removes the temporary `Caps::getFormatForColorType()` function that took a color type and Renderable. The PreferredFormatForColorType does not need to be filtered on renderability. Instead, the Caps::getDefaultSampledTextureInfo() impl filters the returned span by whether or not the WriteSwizzleForCT function returns a non-empty swizzle. We could have the definition of PreferredFormatForColorType have two separate tables, one for renderable and one for non-renderable, which would make the getDefaultSampledTextureInfo() function simpler but at the expense of two nearly identical lookup tables. The details of the PreferredFormatForColorType lookup table is the union of all the different backend's setColorType() blocks from their format table initialization. The internal `Caps::getDefaultTextureInfo` function is updated to iterate over a span of texture formats to automatically use the first that is supported. Bug: b/390473370 Change-Id: I554a1b6a09bbcc64d5bf732bc563e2cb8d0db286 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1165836 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
1 parent ea4fd0e commit 3aa442e

File tree

12 files changed

+151
-326
lines changed

12 files changed

+151
-326
lines changed

src/gpu/graphite/Caps.cpp

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "include/gpu/ShaderErrorHandler.h"
1111
#include "include/gpu/graphite/ContextOptions.h"
1212
#include "include/gpu/graphite/TextureInfo.h"
13+
#include "include/private/base/SkTArray.h"
1314
#include "include/private/base/SkTo.h"
1415
#include "src/gpu/graphite/ContextOptionsPriv.h"
1516
#include "src/gpu/graphite/RenderPassDesc.h"
@@ -187,7 +188,7 @@ bool Caps::isRenderableWithMSRTSS(const TextureInfo& info) const {
187188
}
188189

189190
TextureInfo Caps::getDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage,
190-
TextureFormat format,
191+
SkSpan<const TextureFormat> formats,
191192
SampleCount sampleCount,
192193
Mipmapped mipmapped,
193194
Protected isProtected,
@@ -201,40 +202,45 @@ TextureInfo Caps::getDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage,
201202
return {}; // Cannot handle protected content on this Context
202203
}
203204

204-
auto [supportedUsage, supportedSampleCounts] =
205-
this->getTextureSupport(format, Tiling::kOptimal);
206-
if ((supportedUsage & usage) != usage || !SkToBool(supportedSampleCounts & sampleCount)) {
207-
return {}; // unsupported
208-
}
205+
for (TextureFormat format : formats) {
206+
auto [supportedUsage, supportedSampleCounts] =
207+
this->getTextureSupport(format, Tiling::kOptimal);
208+
if ((supportedUsage & usage) != usage || !SkToBool(supportedSampleCounts & sampleCount)) {
209+
continue; // unsupported, move on to the next possible format
210+
}
209211

210-
if (SkToBool(usage & TextureUsage::kRender) &&
211-
SkToBool(supportedUsage & TextureUsage::kMSRTSS) &&
212-
sampleCount == SampleCount::k1) {
213-
// Proactively prepare a single-sampled image for use with MSRTSS if it's supported by the
214-
// format and kRender is requested. This flag is expected to be harmless (if not, it's a
215-
// driver bug).
216-
usage |= TextureUsage::kMSRTSS;
217-
}
212+
if (SkToBool(usage & TextureUsage::kRender) &&
213+
SkToBool(supportedUsage & TextureUsage::kMSRTSS) &&
214+
sampleCount == SampleCount::k1) {
215+
// Proactivately prepare a single-sampled image for use with MSRTSS if it's supported by
216+
// the format and kRender is requested. This flag is expected to be harmless (if not,
217+
// it's a driver bug).
218+
usage |= TextureUsage::kMSRTSS;
219+
}
218220

219-
if (SkToBool(usage & TextureUsage::kCopyDst) &&
220-
SkToBool(supportedUsage & TextureUsage::kHostCopy) &&
221-
!SkToBool(usage & TextureUsage::kRender) &&
222-
isProtected == Protected::kNo) {
223-
// Proactively enable kHostCopy when supported by the format and kCopyDst is requested, so
224-
// long as it's not going to be protected or rendered into. On every known driver where
225-
// VK_EXT_host_image_copy is used by Skia, it's known that using the host-image-copy flag
226-
// reduces the performance of renderable images.
227-
usage |= TextureUsage::kHostCopy;
221+
if (SkToBool(usage & TextureUsage::kCopyDst) &&
222+
SkToBool(supportedUsage & TextureUsage::kHostCopy) &&
223+
!SkToBool(usage & TextureUsage::kRender) &&
224+
isProtected == Protected::kNo) {
225+
// Proactively enable kHostCopy when supported by the format and kCopyDst is requested,
226+
// so long as it's not going to be protected or rendered into. On every known driver
227+
// where VK_EXT_host_image_copy is used by Skia, it's known that using the
228+
// host-image-copy flag reduces the performance of renderable images.
229+
usage |= TextureUsage::kHostCopy;
230+
}
231+
return this->onGetDefaultTextureInfo(usage, format, sampleCount, mipmapped,
232+
isProtected, discardable);
228233
}
229-
return this->onGetDefaultTextureInfo(usage, format, sampleCount, mipmapped,
230-
isProtected, discardable);
234+
235+
// None of the possible formats were supported
236+
return {};
231237
}
232238

233239
TextureInfo Caps::getDefaultAttachmentTextureInfo(AttachmentDesc desc,
234240
Protected isProtected,
235241
Discardable discardable) const {
236242
return this->getDefaultTextureInfo(TextureUsage::kRender,
237-
desc.fFormat,
243+
SkSpan(&desc.fFormat, 1),
238244
desc.fSampleCount,
239245
Mipmapped::kNo,
240246
isProtected,
@@ -250,21 +256,32 @@ TextureInfo Caps::getDefaultSampledTextureInfo(SkColorType colorType,
250256
Protected isProtected,
251257
Renderable renderable) const {
252258
SkEnumBitMask<TextureUsage> usage = kDefaultSampledUsage;
259+
SkSpan<const TextureFormat> formats = PreferredTextureFormats(colorType);
260+
skia_private::STArray<3, TextureFormat> validFormats;
253261
if (renderable == Renderable::kYes) {
254262
usage |= TextureUsage::kRender;
263+
// Any possible preferred format must also have a valid write swizzle for the requested
264+
// color type.
265+
for (TextureFormat f : formats) {
266+
if (WriteSwizzleForColorType(colorType, f).has_value()) {
267+
validFormats.push_back(f);
268+
}
269+
}
270+
formats = validFormats;
255271
}
256272

257273
return this->getDefaultTextureInfo(usage,
258-
this->getFormatForColorType(colorType, renderable),
274+
formats,
259275
SampleCount::k1,
260276
mipmapped,
261277
isProtected,
262278
Discardable::kNo);
263279
}
264280

265281
TextureInfo Caps::getTextureInfoForSampledCopy(const TextureInfo& info, Mipmapped mipmapped) const {
282+
const TextureFormat format = TextureInfoPriv::ViewFormat(info);
266283
return this->getDefaultTextureInfo(kDefaultSampledUsage,
267-
TextureInfoPriv::ViewFormat(info),
284+
SkSpan(&format, 1),
268285
SampleCount::k1,
269286
mipmapped,
270287
info.isProtected(),
@@ -275,8 +292,9 @@ TextureInfo Caps::getDefaultCompressedTextureInfo(SkTextureCompressionType compr
275292
Mipmapped mipmapped,
276293
Protected isProtected) const {
277294
// Remove CopySrc for compressed textures
295+
const TextureFormat format = CompressionTypeToTextureFormat(compressionType);
278296
return this->getDefaultTextureInfo(kDefaultSampledUsage & ~TextureUsage::kCopySrc,
279-
CompressionTypeToTextureFormat(compressionType),
297+
SkSpan(&format, 1),
280298
SampleCount::k1,
281299
mipmapped,
282300
isProtected,
@@ -289,7 +307,7 @@ TextureInfo Caps::getDefaultStorageTextureInfo(SkColorType colorType) const {
289307
return this->getDefaultTextureInfo(TextureUsage::kStorage |
290308
TextureUsage::kSample |
291309
TextureUsage::kCopySrc,
292-
this->getFormatForColorType(colorType, Renderable::kNo),
310+
PreferredTextureFormats(colorType),
293311
SampleCount::k1,
294312
Mipmapped::kNo,
295313
Protected::kNo,

src/gpu/graphite/Caps.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,15 @@ class Caps {
553553
// approach to textures and color types.
554554
const ColorTypeInfo* getColorTypeInfo(SkColorType, const TextureInfo&) const;
555555
virtual SkSpan<const ColorTypeInfo> getColorTypeInfos(const TextureInfo&) const = 0;
556-
virtual TextureFormat getFormatForColorType(SkColorType, Renderable) const = 0;
556+
557+
// Validates format support and calls onGetDefaultTextureInfo if it would be valid, returning
558+
// a TextureInfo for the first format that is supported.
559+
TextureInfo getDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage,
560+
SkSpan<const TextureFormat>,
561+
SampleCount,
562+
Mipmapped,
563+
Protected,
564+
Discardable) const;
557565

558566
// Return a TextureInfo that is configured to support the given usages with the requested format
559567
// and other properties. This is only called if getTextureSupport() matches for kOptimal tiling.
@@ -563,13 +571,6 @@ class Caps {
563571
Mipmapped,
564572
Protected,
565573
Discardable) const = 0;
566-
// Validates format support and calls onGetDefaultTextureInfo if it would be valid
567-
TextureInfo getDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage,
568-
TextureFormat,
569-
SampleCount,
570-
Mipmapped,
571-
Protected,
572-
Discardable) const;
573574

574575
// Return the supported TextureUsages and SampleCounts for a texture of the given format and
575576
// tiling, assuming the textures are created with the requisite usages.

src/gpu/graphite/Context.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -793,10 +793,18 @@ Context::PixelTransferResult Context::transferPixels(Recorder* recorder,
793793
// which may be different; dstColorInfo is what we have to transform it into when invoking the
794794
// async callbacks.
795795
SkColorInfo readColorInfo = srcColorInfo.makeColorType(supportedColorType);
796-
if (readColorInfo != dstColorInfo || isRGB888Format) {
796+
if (readColorInfo.alphaType() == kUnknown_SkAlphaType) {
797+
readColorInfo = readColorInfo.makeAlphaType(kOpaque_SkAlphaType);
798+
}
799+
SkColorInfo outColorInfo = dstColorInfo;
800+
if (outColorInfo.alphaType() == kUnknown_SkAlphaType) {
801+
outColorInfo = outColorInfo.makeAlphaType(kOpaque_SkAlphaType);
802+
}
803+
if (readColorInfo != outColorInfo || isRGB888Format) {
797804
SkISize dims = srcRect.size();
798805
SkImageInfo srcInfo = SkImageInfo::Make(dims, readColorInfo);
799-
SkImageInfo dstInfo = SkImageInfo::Make(dims, dstColorInfo);
806+
SkImageInfo dstInfo = SkImageInfo::Make(dims, outColorInfo);
807+
800808
result.fRowBytes = dstInfo.minRowBytes();
801809
result.fPixelConverter = [dstInfo, srcInfo, rowBytes, isRGB888Format](
802810
void* dst, const void* src) {

src/gpu/graphite/TextureFormat.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,4 +423,57 @@ std::optional<skgpu::Swizzle> WriteSwizzleForColorType(SkColorType ct, TextureFo
423423
}
424424
}
425425

426+
SkSpan<const TextureFormat> PreferredTextureFormats(SkColorType ct) {
427+
#define N(...) std::size({__VA_ARGS__})
428+
#define CASE(C, ...) case C: { \
429+
static const std::array<TextureFormat, N(__VA_ARGS__)> kFormats{{__VA_ARGS__}}; \
430+
return SkSpan(kFormats); }
431+
432+
switch (ct) {
433+
case kUnknown_SkColorType: return {};
434+
// NOTE: Not all backends support all TextureFormats. Some of the more advanced formats
435+
// may not be supported at all and have no viable fallback. For color types that have
436+
// equivalent texture formats differing only in RGB vs. BGR swizzle, we allow both
437+
// format variations to maximize color types that have some format. For alpha-only color
438+
// types, we only match to red-channel formats as they have the broadest support.
439+
440+
CASE(kAlpha_8_SkColorType, TextureFormat::kR8)
441+
// NOTE: kRGB_565_SkColorType is misnamed and natively matches B5_G6_R5
442+
CASE(kRGB_565_SkColorType, TextureFormat::kB5_G6_R5, TextureFormat::kR5_G6_B5)
443+
// NOTE: kARGB_4444_SkColorType is misnamed and natively matches ABGR4
444+
CASE(kARGB_4444_SkColorType, TextureFormat::kABGR4, TextureFormat::kARGB4)
445+
CASE(kRGBA_8888_SkColorType, TextureFormat::kRGBA8, TextureFormat::kBGRA8)
446+
CASE(kRGB_888x_SkColorType, TextureFormat::kRGB8,
447+
TextureFormat::kRGBA8,
448+
TextureFormat::kBGRA8)
449+
CASE(kBGRA_8888_SkColorType, TextureFormat::kBGRA8, TextureFormat::kRGBA8)
450+
CASE(kRGBA_1010102_SkColorType, TextureFormat::kRGB10_A2, TextureFormat::kBGR10_A2)
451+
CASE(kBGRA_1010102_SkColorType, TextureFormat::kBGR10_A2, TextureFormat::kRGB10_A2)
452+
CASE(kRGB_101010x_SkColorType, TextureFormat::kRGB10_A2, TextureFormat::kBGR10_A2)
453+
CASE(kBGR_101010x_SkColorType, TextureFormat::kBGR10_A2, TextureFormat::kRGB10_A2)
454+
CASE(kBGR_101010x_XR_SkColorType, TextureFormat::kBGR10_XR)
455+
CASE(kBGRA_10101010_XR_SkColorType, TextureFormat::kBGRA10x6_XR)
456+
CASE(kRGBA_10x6_SkColorType, TextureFormat::kRGBA10x6)
457+
CASE(kGray_8_SkColorType, TextureFormat::kR8)
458+
CASE(kRGBA_F16Norm_SkColorType, TextureFormat::kRGBA16F)
459+
CASE(kRGBA_F16_SkColorType, TextureFormat::kRGBA16F)
460+
CASE(kRGB_F16F16F16x_SkColorType, TextureFormat::kRGBA16F)
461+
CASE(kRGBA_F32_SkColorType, TextureFormat::kRGBA32F)
462+
CASE(kR8G8_unorm_SkColorType, TextureFormat::kRG8)
463+
CASE(kA16_float_SkColorType, TextureFormat::kR16F)
464+
CASE(kR16G16_float_SkColorType, TextureFormat::kRG16F)
465+
CASE(kA16_unorm_SkColorType, TextureFormat::kR16)
466+
CASE(kR16_unorm_SkColorType, TextureFormat::kR16)
467+
CASE(kR16G16_unorm_SkColorType, TextureFormat::kRG16)
468+
CASE(kR16G16B16A16_unorm_SkColorType, TextureFormat::kRGBA16)
469+
CASE(kSRGBA_8888_SkColorType, TextureFormat::kRGBA8_sRGB,
470+
TextureFormat::kBGRA8_sRGB)
471+
CASE(kR8_unorm_SkColorType, TextureFormat::kR8)
472+
}
473+
474+
SkUNREACHABLE;
475+
#undef CASE
476+
#undef N
477+
}
478+
426479
} // namespace skgpu::graphite

src/gpu/graphite/TextureFormat.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef skgpu_graphite_TextureFormat_DEFINED
99
#define skgpu_graphite_TextureFormat_DEFINED
1010

11+
#include "include/core/SkSpan.h"
1112
#include "include/core/SkTextureCompressionType.h"
1213
#include "src/gpu/Swizzle.h"
1314

@@ -17,6 +18,8 @@
1718

1819
enum SkColorType : int;
1920

21+
enum SkColorType : int;
22+
2023
namespace skgpu::graphite {
2124

2225
/**
@@ -172,6 +175,12 @@ Swizzle ReadSwizzleForColorType(SkColorType, TextureFormat);
172175
// and TextureInfo. If the returned optional is empty, it means the color type cannot be rendered to
173176
std::optional<Swizzle> WriteSwizzleForColorType(SkColorType, TextureFormat);
174177

178+
// Formats are ordered from most preferred to least based on the policies described above in
179+
// TextureFormat. These must still be filtered by support for a given Caps. A TextureFormat that
180+
// can used with the provided SkColorType is not necessarily included in this list, e.g. we often
181+
// allow BGR vs RGB mismatches between CPU and GPU layouts if that's what the client provides.
182+
SkSpan<const TextureFormat> PreferredTextureFormats(SkColorType);
183+
175184
} // namespace skgpu::graphite
176185

177186
#endif // skgpu_graphite_TextureFormat_DEFINED

0 commit comments

Comments
 (0)