Add sample count to GrVkImageInfo.
Pre-req for allowing rendering to an externally created MSSA VkImage.
Bug: skia:9832
Cq-Include-Trybots: luci.skia.skia.primary:Test-Debian10-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-Vulkan,Test-Win10-Clang-NUC8i5BEK-GPU-IntelIris655-x86_64-Release-All-Vulkan,Test-Win10-Clang-ShuttleA-GPU-RadeonHD7770-x86_64-Release-All-Vulkan,Test-Android-Clang-GalaxyS9-GPU-MaliG72-arm64-Release-All-Android_Vulkan,Test-Android-Clang-GalaxyS7_G930FD-GPU-MaliT880-arm64-Release-All-Android_Vulkan,Test-Android-Clang-GalaxyS20-GPU-MaliG77-arm64-Release-All-Android_Vulkan,Test-Android-Clang-Pixel4XL-GPU-Adreno640-arm64-Release-All-Android_Vulkan,Test-Android-Clang-P30-GPU-MaliG76-arm64-Release-All-Android_Vulkan
Change-Id: Ibf41944c6946dda7e27bdcd509ecd04976fc9ade
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/320262
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
index 2ec3c34..54e50a2 100644
--- a/RELEASE_NOTES.txt
+++ b/RELEASE_NOTES.txt
@@ -9,9 +9,17 @@
* <insert new release notes here>
+ * GrVkImageInfo now has a field for sample count. GrBackendRenderTarget constructor
+ that took both a GrVkImageInfo and separate sample count is deprecated. Use the
+ version without sample count instead.
+
* Added deprecation warning for Metal support on MacOS 10.13, iOS 8.3, and older.
https://review.skia.org/320260
+ * GrVkImageInfo now has a field for sample count. GrBackendRenderTarget constructor
+ that took both a GrVkImageInfo and separate sample count is deprecated. Use the
+ version without sample count instead.
+
* Update SkClipOp::kMax_EnumValue to include only intersect and difference when
SK_SUPPORT_DEPRECATED_CLIPOPS is not defined.
https://review.skia.org/320064
diff --git a/include/gpu/GrBackendSurface.h b/include/gpu/GrBackendSurface.h
index fa5141a..9fe6fc0 100644
--- a/include/gpu/GrBackendSurface.h
+++ b/include/gpu/GrBackendSurface.h
@@ -428,7 +428,10 @@
#endif
#ifdef SK_VULKAN
+ /** Deprecated. Sample count is now part of GrVkImageInfo. */
GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo);
+
+ GrBackendRenderTarget(int width, int height, const GrVkImageInfo& vkInfo);
#endif
#ifdef SK_METAL
@@ -530,7 +533,9 @@
#ifdef SK_VULKAN
friend class GrVkRenderTarget;
- GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo,
+ GrBackendRenderTarget(int width,
+ int height,
+ const GrVkImageInfo& vkInfo,
sk_sp<GrBackendSurfaceMutableStateImpl> mutableState);
#endif
diff --git a/include/gpu/vk/GrVkTypes.h b/include/gpu/vk/GrVkTypes.h
index 300ff4d..954753b 100644
--- a/include/gpu/vk/GrVkTypes.h
+++ b/include/gpu/vk/GrVkTypes.h
@@ -102,6 +102,7 @@
VkImageLayout fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkFormat fFormat = VK_FORMAT_UNDEFINED;
VkImageUsageFlags fImageUsageFlags = 0;
+ uint32_t fSampleCount = 1;
uint32_t fLevelCount = 0;
uint32_t fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
GrProtected fProtected = GrProtected::kNo;
@@ -113,8 +114,9 @@
return fImage == that.fImage && fAlloc == that.fAlloc &&
fImageTiling == that.fImageTiling && fImageLayout == that.fImageLayout &&
fFormat == that.fFormat && fImageUsageFlags == that.fImageUsageFlags &&
- fLevelCount == that.fLevelCount && fCurrentQueueFamily == that.fCurrentQueueFamily &&
- fProtected == that.fProtected && fYcbcrConversionInfo == that.fYcbcrConversionInfo &&
+ fSampleCount == that.fSampleCount && fLevelCount == that.fLevelCount &&
+ fCurrentQueueFamily == that.fCurrentQueueFamily && fProtected == that.fProtected &&
+ fYcbcrConversionInfo == that.fYcbcrConversionInfo &&
fSharingMode == that.fSharingMode;
}
#endif
diff --git a/src/gpu/GrBackendSurface.cpp b/src/gpu/GrBackendSurface.cpp
index 28bcdd8..22d2f23 100644
--- a/src/gpu/GrBackendSurface.cpp
+++ b/src/gpu/GrBackendSurface.cpp
@@ -852,32 +852,43 @@
#endif
#ifdef SK_VULKAN
+static GrVkImageInfo resolve_vkii_sample_count(const GrVkImageInfo& vkII, int sidebandSampleCnt) {
+ auto result = vkII;
+ result.fSampleCount = std::max({vkII.fSampleCount,
+ static_cast<uint32_t>(sidebandSampleCnt),
+ 1U});
+ return result;
+}
+
GrBackendRenderTarget::GrBackendRenderTarget(int width,
int height,
int sampleCnt,
const GrVkImageInfo& vkInfo)
- : GrBackendRenderTarget(width, height, sampleCnt, vkInfo,
+ : GrBackendRenderTarget(width, height, resolve_vkii_sample_count(vkInfo, sampleCnt)) {}
+
+GrBackendRenderTarget::GrBackendRenderTarget(int width,
+ int height,
+ const GrVkImageInfo& vkInfo)
+ : GrBackendRenderTarget(width, height, vkInfo,
sk_sp<GrBackendSurfaceMutableStateImpl>(
new GrBackendSurfaceMutableStateImpl(
- vkInfo.fImageLayout, vkInfo.fCurrentQueueFamily))) {}
+ vkInfo.fImageLayout, vkInfo.fCurrentQueueFamily))) {}
static const VkImageUsageFlags kDefaultRTUsageFlags =
kDefaultUsageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
GrBackendRenderTarget::GrBackendRenderTarget(int width,
int height,
- int sampleCnt,
const GrVkImageInfo& vkInfo,
sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)
: fIsValid(true)
, fWidth(width)
, fHeight(height)
- , fSampleCnt(std::max(1, sampleCnt))
+ , fSampleCnt(std::max(1U, vkInfo.fSampleCount))
, fStencilBits(0) // We always create stencil buffers internally for vulkan
, fBackend(GrBackendApi::kVulkan)
, fVkInfo(apply_default_usage_flags(vkInfo, kDefaultRTUsageFlags))
- , fMutableState(mutableState) {
-}
+ , fMutableState(mutableState) {}
#endif
#ifdef SK_METAL
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 642acad..a5ec36a 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1246,6 +1246,11 @@
}
static bool check_tex_image_info(const GrVkCaps& caps, const GrVkImageInfo& info) {
+ // We don't support directly importing multisampled textures for sampling from shaders.
+ if (info.fSampleCount != 1) {
+ return false;
+ }
+
if (info.fYcbcrConversionInfo.isValid() && info.fYcbcrConversionInfo.fExternalFormat != 0) {
return true;
}
@@ -1268,12 +1273,11 @@
return true;
}
-static bool check_rt_image_info(const GrVkCaps& caps, const GrVkImageInfo& info, int sampleCnt) {
- if (!caps.isFormatRenderable(info.fFormat, sampleCnt)) {
+static bool check_rt_image_info(const GrVkCaps& caps, const GrVkImageInfo& info, bool resolveOnly) {
+ if (!caps.isFormatRenderable(info.fFormat, info.fSampleCount)) {
return false;
}
- // We currently require all render targets to be made with color attachment support
- if (!SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
+ if (!resolveOnly && !SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
return false;
}
return true;
@@ -1330,7 +1334,10 @@
if (!check_tex_image_info(this->vkCaps(), imageInfo)) {
return nullptr;
}
- if (!check_rt_image_info(this->vkCaps(), imageInfo, sampleCnt)) {
+ // If sampleCnt is > 1 we will create an intermediate MSAA VkImage and then resolve into
+ // the wrapped VkImage.
+ bool resolveOnly = sampleCnt > 1;
+ if (!check_rt_image_info(this->vkCaps(), imageInfo, resolveOnly)) {
return nullptr;
}
@@ -1367,7 +1374,9 @@
return nullptr;
}
- if (!check_rt_image_info(this->vkCaps(), info, backendRT.sampleCnt())) {
+ // We will always render directly to this VkImage.
+ static bool kResolveOnly = false;
+ if (!check_rt_image_info(this->vkCaps(), info, kResolveOnly)) {
return nullptr;
}
@@ -1379,7 +1388,7 @@
SkASSERT(mutableState);
sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(
- this, backendRT.dimensions(), 1, info, std::move(mutableState));
+ this, backendRT.dimensions(), backendRT.sampleCnt(), info, std::move(mutableState));
// We don't allow the client to supply a premade stencil buffer. We always create one if needed.
SkASSERT(!backendRT.stencilBits());
@@ -1399,8 +1408,15 @@
if (!check_image_info(this->vkCaps(), imageInfo, false, this->queueIndex())) {
return nullptr;
}
+ // See comment below about intermediate MSAA buffer.
+ if (imageInfo.fSampleCount > 1) {
+ return nullptr;
+ }
- if (!check_rt_image_info(this->vkCaps(), imageInfo, sampleCnt)) {
+ // If sampleCnt is > 1 we will create an intermediate MSAA VkImage and then resolve into
+ // the wrapped VkImage.
+ bool resolveOnly = sampleCnt > 1;
+ if (!check_rt_image_info(this->vkCaps(), imageInfo, resolveOnly)) {
return nullptr;
}
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp
index c2c396b..ea23573 100644
--- a/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/src/gpu/vk/GrVkRenderTarget.cpp
@@ -528,8 +528,7 @@
GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
- return GrBackendRenderTarget(this->width(), this->height(), this->numSamples(), fInfo,
- this->getMutableState());
+ return GrBackendRenderTarget(this->width(), this->height(), fInfo, this->getMutableState());
}
const GrManagedResource* GrVkRenderTarget::stencilImageResource() const {
diff --git a/tests/VkWrapTests.cpp b/tests/VkWrapTests.cpp
index 98353ef..24085a4 100644
--- a/tests/VkWrapTests.cpp
+++ b/tests/VkWrapTests.cpp
@@ -83,6 +83,19 @@
REPORTER_ASSERT(reporter, tex);
}
+
+ // image has MSAA
+ {
+ GrVkImageInfo backendCopy = imageInfo;
+ backendCopy.fSampleCount = 4;
+ GrBackendTexture backendTex = GrBackendTexture(kW, kH, backendCopy);
+ tex = gpu->wrapBackendTexture(backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
+ kRead_GrIOType);
+ REPORTER_ASSERT(reporter, !tex);
+ tex = gpu->wrapBackendTexture(backendTex, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo,
+ kRead_GrIOType);
+ REPORTER_ASSERT(reporter, !tex);
+ }
}
void wrap_rt_test(skiatest::Reporter* reporter, GrDirectContext* dContext) {
@@ -119,6 +132,15 @@
REPORTER_ASSERT(reporter, rt);
}
+ // Image has MSAA
+ {
+ GrVkImageInfo backendCopy = imageInfo;
+ backendCopy.fSampleCount = 4;
+ GrBackendRenderTarget backendRT(kW, kH, backendCopy);
+ rt = gpu->wrapBackendRenderTarget(backendRT);
+ REPORTER_ASSERT(reporter, !rt);
+ }
+
// When we wrapBackendRenderTarget it is always borrowed, so we must make sure to free the
// resource when we're done.
dContext->deleteBackendTexture(origBackendTex);
@@ -172,6 +194,26 @@
GrWrapCacheable::kNo);
REPORTER_ASSERT(reporter, tex);
}
+
+ // check rendering with MSAA
+ {
+ int maxSamples = dContext->priv().caps()->maxRenderTargetSampleCount(
+ origBackendTex.getBackendFormat());
+ bool shouldSucceed = maxSamples > 1;
+ tex = gpu->wrapRenderableBackendTexture(origBackendTex, 2, kBorrow_GrWrapOwnership,
+ GrWrapCacheable::kNo);
+ REPORTER_ASSERT(reporter, SkToBool(tex) == shouldSucceed);
+ }
+
+ // Image has MSAA
+ {
+ GrVkImageInfo backendCopy = imageInfo;
+ backendCopy.fSampleCount = 4;
+ GrBackendTexture backendTex = GrBackendTexture(kW, kH, backendCopy);
+ tex = gpu->wrapRenderableBackendTexture(backendTex, 1, kAdopt_GrWrapOwnership,
+ GrWrapCacheable::kNo);
+ REPORTER_ASSERT(reporter, !tex);
+ }
}
DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkWrapTests, reporter, ctxInfo) {
diff --git a/tools/gpu/vk/VkYcbcrSamplerHelper.cpp b/tools/gpu/vk/VkYcbcrSamplerHelper.cpp
index de8d0d1..f083245 100644
--- a/tools/gpu/vk/VkYcbcrSamplerHelper.cpp
+++ b/tools/gpu/vk/VkYcbcrSamplerHelper.cpp
@@ -196,6 +196,7 @@
VK_IMAGE_LAYOUT_UNDEFINED,
vkImageInfo.format,
vkImageInfo.usage,
+ 1 /* sample count */,
1 /* levelCount */,
VK_QUEUE_FAMILY_IGNORED,
GrProtected::kNo,