Add testing-only backend render target support to GrVkGpu.
Update unit tests to use backend render targets on non-GL contexts
Add named DM configs for rendering to Vulkan backend render targets and textures.
Make src data ptr param to createTestingOnlyBackendTexture be const.
Change-Id: I17f5375ed9bb08422006698956469d3151c4954c
Reviewed-on: https://skia-review.googlesource.com/113276
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 40d7664..2aacc49 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -452,14 +452,13 @@
/** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is
only to be used for testing (particularly for testing the methods that import an externally
created texture into Skia. Must be matched with a call to deleteTestingOnlyTexture(). */
- GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, SkColorType,
+ GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h, SkColorType,
bool isRenderTarget, GrMipMapped);
/** Older version based on GrPixelConfig. Currently the preferred one above devolves to this. */
- virtual GrBackendTexture createTestingOnlyBackendTexture(
- void* pixels, int w, int h,
- GrPixelConfig config,
- bool isRenderTarget,
- GrMipMapped mipMapped) = 0;
+ virtual GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
+ GrPixelConfig config,
+ bool isRenderTarget,
+ GrMipMapped mipMapped) = 0;
/** Check a handle represents an actual texture in the backend API that has not been freed. */
virtual bool isTestingOnlyBackendTexture(const GrBackendTexture&) const = 0;
/**
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 7e69fbe..9023554 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -4345,7 +4345,7 @@
}
#if GR_TEST_UTILS
-GrBackendTexture GrGLGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
+GrBackendTexture GrGLGpu::createTestingOnlyBackendTexture(const void* pixels, int w, int h,
GrPixelConfig config, bool /*isRT*/,
GrMipMapped mipMapped) {
if (!this->caps()->isConfigTexturable(config)) {
@@ -4395,7 +4395,7 @@
if (!pixels) {
// Fill in the texture with all zeros so we don't have random garbage
pixels = defaultStorage.get();
- memset(pixels, 0, baseLayerSize);
+ memset(defaultStorage.get(), 0, baseLayerSize);
}
int width = w;
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 79d74d2..7ddd4e7 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -145,9 +145,8 @@
int width,
int height) override;
#if GR_TEST_UTILS
- GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h,
- GrPixelConfig config,
- bool isRenderTarget,
+ GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
+ GrPixelConfig config, bool isRenderTarget,
GrMipMapped mipMapped) override;
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
void deleteTestingOnlyBackendTexture(const GrBackendTexture&) override;
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index b1c3e7d..4b786ab 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -181,7 +181,7 @@
}
#if GR_TEST_UTILS
-GrBackendTexture GrMockGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
+GrBackendTexture GrMockGpu::createTestingOnlyBackendTexture(const void* pixels, int w, int h,
GrPixelConfig config, bool isRT,
GrMipMapped mipMapped) {
GrMockTextureInfo info;
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index f0d7c07..8a3dc30 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -114,8 +114,9 @@
void clearStencil(GrRenderTarget*, int clearValue) override {}
#if GR_TEST_UTILS
- GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig,
- bool isRT, GrMipMapped) override;
+ GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
+ GrPixelConfig, bool isRT,
+ GrMipMapped) override;
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
void deleteTestingOnlyBackendTexture(const GrBackendTexture&) override;
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 1babc82..4729e6e 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -138,7 +138,7 @@
void clearStencil(GrRenderTarget* target, int clearValue) override {}
#if GR_TEST_UTILS
- GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h,
+ GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
GrPixelConfig config, bool isRT,
GrMipMapped) override {
return GrBackendTexture();
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 73787bf..5e6473e 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1131,8 +1131,8 @@
////////////////////////////////////////////////////////////////////////////////
-bool copy_testing_data(GrVkGpu* gpu, void* srcData, const GrVkAlloc& alloc, size_t bufferOffset,
- size_t srcRowBytes, size_t dstRowBytes, int h) {
+bool copy_testing_data(GrVkGpu* gpu, const void* srcData, const GrVkAlloc& alloc,
+ size_t bufferOffset, size_t srcRowBytes, size_t dstRowBytes, int h) {
// For Noncoherent buffers we want to make sure the range that we map, both offset and size,
// are aligned to the nonCoherentAtomSize limit. We may have to move the initial offset back to
// meet the alignment requirements. So we track how far we move back and then adjust the mapped
@@ -1184,33 +1184,39 @@
}
#if GR_TEST_UTILS
-GrBackendTexture GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
- GrPixelConfig config,
- bool isRenderTarget,
- GrMipMapped mipMapped) {
-
+bool GrVkGpu::createTestingOnlyVkImage(GrPixelConfig config, int w, int h, bool texturable,
+ bool renderable, GrMipMapped mipMapped, const void* srcData,
+ GrVkImageInfo* info) {
+ SkASSERT(texturable || renderable);
+ if (!texturable) {
+ SkASSERT(GrMipMapped::kNo == mipMapped);
+ SkASSERT(!srcData);
+ }
VkFormat pixelFormat;
if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
- return GrBackendTexture(); // invalid
+ return false;
}
- if (!fVkCaps->isConfigTexturable(config)) {
- return GrBackendTexture(); // invalid
+ if (texturable && !fVkCaps->isConfigTexturable(config)) {
+ return false;
}
- if (isRenderTarget && !fVkCaps->isConfigRenderable(config)) {
- return GrBackendTexture(); // invalid
+ if (renderable && !fVkCaps->isConfigRenderable(config)) {
+ return false;
}
// Currently we don't support uploading pixel data when mipped.
if (srcData && GrMipMapped::kYes == mipMapped) {
- return GrBackendTexture(); // invalid
+ return false;
}
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
+ VkImageUsageFlags usageFlags = 0;
usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- if (isRenderTarget) {
+ if (texturable) {
+ usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
+ }
+ if (renderable) {
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
@@ -1221,7 +1227,7 @@
// Create Image
VkSampleCountFlagBits vkSamples;
if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
- return GrBackendTexture(); // invalid
+ return false;
}
// Figure out the number of mip levels.
@@ -1248,11 +1254,12 @@
initialLayout // initialLayout
};
- GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
+ GR_VK_CALL_ERRCHECK(this->vkInterface(),
+ CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
if (!GrVkMemory::AllocAndBindImageMemory(this, image, false, &alloc)) {
VK_CALL(DestroyImage(this->device(), image, nullptr));
- return GrBackendTexture(); // invalid
+ return false;
}
// We need to declare these early so that we can delete them at the end outside of the if block.
@@ -1273,7 +1280,7 @@
if (err) {
GrVkMemory::FreeImageMemory(this, false, alloc);
VK_CALL(DestroyImage(fDevice, image, nullptr));
- return GrBackendTexture(); // invalid
+ return false;
}
VkCommandBufferBeginInfo cmdBufferBeginInfo;
@@ -1328,7 +1335,7 @@
VK_CALL(DestroyImage(fDevice, image, nullptr));
VK_CALL(EndCommandBuffer(cmdBuffer));
VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- return GrBackendTexture(); // invalid
+ return false;
}
if (!GrVkMemory::AllocAndBindBufferMemory(this, buffer, GrVkBuffer::kCopyRead_Type, true,
@@ -1338,7 +1345,7 @@
VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
VK_CALL(EndCommandBuffer(cmdBuffer));
VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- return GrBackendTexture(); // invalid
+ return false;
}
currentWidth = w;
@@ -1355,7 +1362,7 @@
VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
VK_CALL(EndCommandBuffer(cmdBuffer));
VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- return GrBackendTexture(); // invalid
+ return false;
}
currentWidth = SkTMax(1, currentWidth / 2);
currentHeight = SkTMax(1, currentHeight / 2);
@@ -1401,27 +1408,29 @@
VK_CALL(CmdCopyBufferToImage(cmdBuffer, buffer, image, initialLayout, regions.count(),
regions.begin()));
- // Change Image layout to shader read since if we use this texture as a borrowed textures within
- // Ganesh we require that its layout be set to that
- memset(&barrier, 0, sizeof(VkImageMemoryBarrier));
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.pNext = nullptr;
- barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLayout);
- barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- barrier.oldLayout = initialLayout;
- barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.image = image;
- barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, mipLevels, 0 , 1};
-
- VK_CALL(CmdPipelineBarrier(cmdBuffer,
- GrVkMemory::LayoutToPipelineStageFlags(initialLayout),
- VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
- 0,
- 0, nullptr,
- 0, nullptr,
- 1, &barrier));
+ if (texturable) {
+ // Change Image layout to shader read since if we use this texture as a borrowed textures
+ // within Ganesh we require that its layout be set to that
+ memset(&barrier, 0, sizeof(VkImageMemoryBarrier));
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.pNext = nullptr;
+ barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLayout);
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ barrier.oldLayout = initialLayout;
+ barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = image;
+ barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, mipLevels, 0, 1};
+ initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ VK_CALL(CmdPipelineBarrier(cmdBuffer,
+ GrVkMemory::LayoutToPipelineStageFlags(initialLayout),
+ VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ 0,
+ 0, nullptr,
+ 0, nullptr,
+ 1, &barrier));
+ }
// End CommandBuffer
err = VK_CALL(EndCommandBuffer(cmdBuffer));
@@ -1471,15 +1480,24 @@
VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
VK_CALL(DestroyFence(fDevice, fence, nullptr));
+ info->fImage = image;
+ info->fAlloc = alloc;
+ info->fImageTiling = VK_IMAGE_TILING_OPTIMAL;
+ info->fImageLayout = initialLayout;
+ info->fFormat = pixelFormat;
+ info->fLevelCount = mipLevels;
+ return true;
+}
+
+GrBackendTexture GrVkGpu::createTestingOnlyBackendTexture(const void* srcData, int w, int h,
+ GrPixelConfig config, bool isRenderTarget,
+ GrMipMapped mipMapped) {
GrVkImageInfo info;
- info.fImage = image;
- info.fAlloc = alloc;
- info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
- info.fImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- info.fFormat = pixelFormat;
- info.fLevelCount = mipLevels;
-
+ if (!this->createTestingOnlyVkImage(config, w, h, true, isRenderTarget, mipMapped, srcData,
+ &info)) {
+ return {};
+ }
return GrBackendTexture(w, h, info);
}
@@ -1512,13 +1530,29 @@
}
}
-GrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType,
- GrSRGBEncoded) {
- return GrBackendRenderTarget();
+GrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType ct,
+ GrSRGBEncoded srgbEncoded) {
+ GrVkImageInfo info;
+ auto config = GrColorTypeToPixelConfig(ct, srgbEncoded);
+ if (kUnknown_GrPixelConfig == config) {
+ return {};
+ }
+ if (!this->createTestingOnlyVkImage(config, w, h, false, true, GrMipMapped::kNo, nullptr,
+ &info)) {
+ return {};
+ }
+ return {w, h, 1, 0, info};
}
-void GrVkGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {}
+void GrVkGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
+ SkASSERT(kVulkan_GrBackend == rt.fBackend);
+ if (const auto* info = rt.getVkImageInfo()) {
+ // something in the command buffer may still be using this, so force submit
+ this->submitCommandBuffer(kForce_SyncQueue);
+ GrVkImage::DestroyImageInfo(this, const_cast<GrVkImageInfo*>(info));
+ }
+}
void GrVkGpu::testingOnly_flushGpuAndSync() {
this->submitCommandBuffer(kForce_SyncQueue);
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index b5ddcb8..6eac5c8 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -70,9 +70,8 @@
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
#if GR_TEST_UTILS
- GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h,
- GrPixelConfig config,
- bool isRenderTarget,
+ GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
+ GrPixelConfig config, bool isRenderTarget,
GrMipMapped) override;
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
void deleteTestingOnlyBackendTexture(const GrBackendTexture&) override;
@@ -247,6 +246,12 @@
void resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
const SkIPoint& dstPoint);
+#if GR_TEST_UTILS
+ bool createTestingOnlyVkImage(GrPixelConfig config, int w, int h, bool texturable,
+ bool renderable, GrMipMapped mipMapped, const void* srcData,
+ GrVkImageInfo* info);
+#endif
+
sk_sp<const GrVkBackendContext> fBackendContext;
sk_sp<GrVkCaps> fVkCaps;