[graphite] Add Caps::toString virtual
This will be used to pretty print YCbCr information in the Pipeline labels.
As an example, this will replace the substring:
HardwareImage(3: kAwAEPcAAAAAAAAA)
with:
HardwareImage(x247 2020+narrow cos cos nearest F rgba cf1lf0)
Unfortunately, wgpu::YCbCrVkDescriptor and skgpu::VulkanYcbcrConversionInfo have diverged (in their handling of the ChromaFilter and member variable ordering) so we can't share code between native Vulkan and Dawn Vulkan.
Bug: b/456438502
Change-Id: I3b78af7a546e30c0104cd988bb43b5f08e9886ef
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1087937
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/gpu/vk/VulkanTypes.h b/include/gpu/vk/VulkanTypes.h
index b9d0017..b3f4d5a 100644
--- a/include/gpu/vk/VulkanTypes.h
+++ b/include/gpu/vk/VulkanTypes.h
@@ -157,6 +157,7 @@
VkBool32 forceExplicitReconstruction() const { return fForceExplicitReconstruction; }
VkComponentMapping components() const { return fComponents; }
+ bool samplerFilterMustMatchChromaFilter() const { return fSamplerFilterMustMatchChromaFilter; }
bool supportsLinearFilter() const { return fSupportsLinearFilter; }
// Returns a populated VkSamplerYcbcrConversionCreateInfo object based on
@@ -225,7 +226,7 @@
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY};
- // Default these values to the most restrictive. These defaults only really matter while until
+ // Default these values to the most restrictive. These defaults only really matter until
// we force all clients to go through our constructors. At that point these will be set to the
// correct values.
bool fSamplerFilterMustMatchChromaFilter = true;
diff --git a/src/gpu/graphite/Caps.h b/src/gpu/graphite/Caps.h
index 905fb3e..5c34b01 100644
--- a/src/gpu/graphite/Caps.h
+++ b/src/gpu/graphite/Caps.h
@@ -189,7 +189,7 @@
*/
size_t requiredTransferBufferAlignment() const { return fRequiredTransferBufferAlignment; }
- /* Returns the aligned rowBytes when transfering to or from a Texture */
+ /* Returns the aligned rowBytes when transferring to or from a Texture */
size_t getAlignedTextureDataRowBytes(size_t rowBytes) const {
return SkAlignTo(rowBytes, fTextureDataRowBytesAlignment);
}
@@ -202,10 +202,13 @@
return {};
}
+ /* Returns a compressed label describing the immutable sampler for the Pipeline label */
+ virtual std::string toString(const ImmutableSamplerInfo&) const { return ""; }
+
/**
* Backends may have restrictions on what types of textures support Device::writePixels().
* If this returns false then the caller should implement a fallback where a temporary texture
- * is created, pixels are written to it, and then that is copied or drawn into the the surface.
+ * is created, pixels are written to it, and then that is copied or drawn into the surface.
*/
virtual bool supportsWritePixels(const TextureInfo&) const = 0;
diff --git a/src/gpu/graphite/dawn/DawnCaps.cpp b/src/gpu/graphite/dawn/DawnCaps.cpp
index 6d01941..b8ce276 100644
--- a/src/gpu/graphite/dawn/DawnCaps.cpp
+++ b/src/gpu/graphite/dawn/DawnCaps.cpp
@@ -1163,6 +1163,87 @@
return {};
}
+#if !defined(__EMSCRIPTEN__)
+static constexpr const char* filter_mode_to_str(wgpu::FilterMode mode) {
+ switch (mode) {
+ case wgpu::FilterMode::Undefined: return "undefined";
+ case wgpu::FilterMode::Nearest: return "nearest";
+ case wgpu::FilterMode::Linear: return "linear";
+ }
+ SkUNREACHABLE;
+}
+
+static constexpr const char* model_to_str(uint32_t c) {
+ switch (c) {
+ case 0 /* VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY */: return "RGB-I";
+ case 1 /* VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY */: return "YCbCr-I";
+ case 2 /* VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 */: return "709";
+ case 3 /* VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 */: return "601";
+ case 4 /* VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 */: return "2020";
+ default: return "unknown";
+ }
+ SkUNREACHABLE;
+}
+
+static constexpr const char* range_to_str(uint32_t r) {
+ switch (r) {
+ case 0 /* VK_SAMPLER_YCBCR_RANGE_ITU_FULL */: return "full";
+ case 1 /* VK_SAMPLER_YCBCR_RANGE_ITU_NARROW */: return "narrow";
+ default: return "unknown";
+ }
+ SkUNREACHABLE;
+}
+
+static constexpr char swizzle_to_str(uint32_t c, char identityAnswer) {
+ switch (c) {
+ case 0 /* VK_COMPONENT_SWIZZLE_IDENTITY */: return identityAnswer;
+ case 1 /* VK_COMPONENT_SWIZZLE_ZERO */: return '0';
+ case 2 /* VK_COMPONENT_SWIZZLE_ONE */: return '1';
+ case 3 /* VK_COMPONENT_SWIZZLE_R */: return 'r';
+ case 4 /* VK_COMPONENT_SWIZZLE_G */: return 'g';
+ case 5 /* VK_COMPONENT_SWIZZLE_B */: return 'b';
+ case 6 /* VK_COMPONENT_SWIZZLE_A */: return 'a';
+ default: return '?';
+ }
+ SkUNREACHABLE;
+}
+#endif
+
+std::string DawnCaps::toString(const ImmutableSamplerInfo& immutableSamplerInfo) const {
+#if defined(__EMSCRIPTEN__)
+ return "";
+#else
+ const wgpu::YCbCrVkDescriptor info =
+ DawnDescriptorFromImmutableSamplerInfo(immutableSamplerInfo);
+ if (!DawnDescriptorIsValid(info)) {
+ return "";
+ }
+
+ std::string result;
+
+ if (info.vkFormat == 0) {
+ result += 'x';
+ result += std::to_string(info.externalFormat);
+ } else {
+ result += info.vkFormat;
+ }
+
+ result += " ";
+ result += model_to_str(info.vkYCbCrModel);
+ result += "+";
+ result += range_to_str(info.vkYCbCrRange);
+ result += info.vkXChromaOffset ? " mid" : " cos"; // midpoint or cosited-even
+ result += info.vkYChromaOffset ? " mid " : " cos "; // midpoint or cosited-even
+ result += filter_mode_to_str(info.vkChromaFilter);
+ result += info.forceExplicitReconstruction ? " T " : " F ";
+ result += swizzle_to_str(info.vkComponentSwizzleRed, 'r');
+ result += swizzle_to_str(info.vkComponentSwizzleGreen, 'g');
+ result += swizzle_to_str(info.vkComponentSwizzleBlue, 'b');
+ result += swizzle_to_str(info.vkComponentSwizzleAlpha, 'a');
+ return result;
+#endif
+}
+
void DawnCaps::buildKeyForTexture(SkISize dimensions,
const TextureInfo& info,
ResourceType type,
diff --git a/src/gpu/graphite/dawn/DawnCaps.h b/src/gpu/graphite/dawn/DawnCaps.h
index 79ae7b1..bee374d 100644
--- a/src/gpu/graphite/dawn/DawnCaps.h
+++ b/src/gpu/graphite/dawn/DawnCaps.h
@@ -58,6 +58,8 @@
const RendererProvider*) const override;
UniqueKey makeComputePipelineKey(const ComputePipelineDesc&) const override;
ImmutableSamplerInfo getImmutableSamplerInfo(const TextureInfo&) const override;
+ std::string toString(const ImmutableSamplerInfo&) const override;
+
bool isRenderable(const TextureInfo&) const override;
bool isStorage(const TextureInfo&) const override;
diff --git a/src/gpu/graphite/vk/VulkanCaps.cpp b/src/gpu/graphite/vk/VulkanCaps.cpp
index 5a7ad43..67b9ac2 100644
--- a/src/gpu/graphite/vk/VulkanCaps.cpp
+++ b/src/gpu/graphite/vk/VulkanCaps.cpp
@@ -2239,4 +2239,49 @@
return {};
}
+static constexpr const char* vk_chromafilter_to_str(VkFilter f) {
+ switch (f) {
+ case VK_FILTER_NEAREST: return "nearest";
+ case VK_FILTER_LINEAR: return "linear";
+ case VK_FILTER_CUBIC_EXT: return "cubic";
+ default: return "unknown";
+ }
+ SkUNREACHABLE;
+}
+
+std::string VulkanCaps::toString(const ImmutableSamplerInfo& immutableSamplerInfo) const {
+ const skgpu::VulkanYcbcrConversionInfo info =
+ VulkanYcbcrConversion::FromImmutableSamplerInfo(immutableSamplerInfo);
+ if (!info.isValid()) {
+ return "";
+ }
+
+ std::string result;
+
+ if (info.hasExternalFormat()) {
+ result += 'x';
+ result += std::to_string(info.externalFormat());
+ } else {
+ result += info.format();
+ }
+
+ result += " ";
+ result += VkModelToStr(info.model());
+ result += "+";
+ result += VkRangeToStr(info.range());
+ result += info.xChromaOffset() ? " mid" : " cos"; // midpoint or cosited-even
+ result += info.yChromaOffset() ? " mid " : " cos "; // midpoint or cosited-even
+ result += vk_chromafilter_to_str(info.chromaFilter());
+ result += info.forceExplicitReconstruction() ? " T " : " F ";
+ result += VkSwizzleToStr(info.components().r, 'r');
+ result += VkSwizzleToStr(info.components().g, 'g');
+ result += VkSwizzleToStr(info.components().b, 'b');
+ result += VkSwizzleToStr(info.components().a, 'a');
+ result += " cf";
+ result += info.samplerFilterMustMatchChromaFilter() ? '1' : '0';
+ result += "lf";
+ result += info.supportsLinearFilter() ? '1' : '0';
+ return result;
+}
+
} // namespace skgpu::graphite
diff --git a/src/gpu/graphite/vk/VulkanCaps.h b/src/gpu/graphite/vk/VulkanCaps.h
index 5dfaa76..b67c4cd 100644
--- a/src/gpu/graphite/vk/VulkanCaps.h
+++ b/src/gpu/graphite/vk/VulkanCaps.h
@@ -52,6 +52,7 @@
DstReadStrategy getDstReadStrategy() const override;
ImmutableSamplerInfo getImmutableSamplerInfo(const TextureInfo&) const override;
+ std::string toString(const ImmutableSamplerInfo&) const override;
UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc&,
const RenderPassDesc&) const override;
diff --git a/src/gpu/vk/VulkanUtilsPriv.cpp b/src/gpu/vk/VulkanUtilsPriv.cpp
index 25b76e0..b95db22 100644
--- a/src/gpu/vk/VulkanUtilsPriv.cpp
+++ b/src/gpu/vk/VulkanUtilsPriv.cpp
@@ -397,7 +397,7 @@
fSupportsLinearFilter = SkToBool(formatFeatures &
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
if (fSamplerFilterMustMatchChromaFilter && !fSupportsLinearFilter) {
- // Because we don't have have separate reconstruction filter, the min, mag and filter must
+ // Because we don't have separate reconstruction filter, the min, mag and filter must
// all match. However, we also don't support linear sampling so the min/mag filter have to
// be nearest. Therefore, we force the chroma filter to be nearest regardless of support for
// the feature VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.
diff --git a/src/gpu/vk/VulkanUtilsPriv.h b/src/gpu/vk/VulkanUtilsPriv.h
index 3b495d3..1e40948 100644
--- a/src/gpu/vk/VulkanUtilsPriv.h
+++ b/src/gpu/vk/VulkanUtilsPriv.h
@@ -300,6 +300,41 @@
}
}
+static constexpr const char* VkModelToStr(VkSamplerYcbcrModelConversion c) {
+ switch (c) {
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY: return "RGB-I";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY: return "YCbCr-I";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709: return "709";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601: return "601";
+ case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020: return "2020";
+ default: return "unknown";
+ }
+ SkUNREACHABLE;
+}
+
+static constexpr const char* VkRangeToStr(VkSamplerYcbcrRange r) {
+ switch (r) {
+ case VK_SAMPLER_YCBCR_RANGE_ITU_FULL: return "full";
+ case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW: return "narrow";
+ default: return "unknown";
+ }
+ SkUNREACHABLE;
+}
+
+static constexpr char VkSwizzleToStr(VkComponentSwizzle c, char identityAnswer) {
+ switch (c) {
+ case VK_COMPONENT_SWIZZLE_IDENTITY: return identityAnswer;
+ case VK_COMPONENT_SWIZZLE_ZERO: return '0';
+ case VK_COMPONENT_SWIZZLE_ONE: return '1';
+ case VK_COMPONENT_SWIZZLE_R: return 'r';
+ case VK_COMPONENT_SWIZZLE_G: return 'g';
+ case VK_COMPONENT_SWIZZLE_B: return 'b';
+ case VK_COMPONENT_SWIZZLE_A: return 'a';
+ default: return '?';
+ }
+ SkUNREACHABLE;
+}
+
#ifdef SK_BUILD_FOR_ANDROID
/**
* Vulkan AHardwareBuffer utility functions shared between graphite and ganesh