diff options
-rw-r--r-- | src/gpu/vk/GrVkCaps.cpp | 5 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.h | 12 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 54 |
3 files changed, 53 insertions, 18 deletions
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp index 9027f68815..3348916d25 100644 --- a/src/gpu/vk/GrVkCaps.cpp +++ b/src/gpu/vk/GrVkCaps.cpp @@ -16,6 +16,7 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* VkPhysicalDevice physDev, uint32_t featureFlags, uint32_t extensionFlags) : INHERITED(contextOptions) { fCanUseGLSLForShaderModule = false; + fMustDoCopiesFromOrigin = false; /************************************************************************** * GrDrawTargetCaps fields @@ -66,6 +67,10 @@ void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* // fCanUseGLSLForShaderModule = true; } + if (kQualcomm_VkVendor == properties.vendorID) { + fMustDoCopiesFromOrigin = true; + } + this->applyOptionsOverrides(contextOptions); GrGLSLCaps* glslCaps = static_cast<GrGLSLCaps*>(fShaderCaps.get()); glslCaps->applyOptionsOverrides(contextOptions); diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h index 3733f2c1d6..f1ab8d050a 100644 --- a/src/gpu/vk/GrVkCaps.h +++ b/src/gpu/vk/GrVkCaps.h @@ -62,6 +62,10 @@ public: return fCanUseGLSLForShaderModule; } + bool mustDoCopiesFromOrigin() const { + return fMustDoCopiesFromOrigin; + } + /** * Returns both a supported and most prefered stencil format to use in draws. */ @@ -72,6 +76,10 @@ public: GrGLSLCaps* glslCaps() const { return reinterpret_cast<GrGLSLCaps*>(fShaderCaps.get()); } private: + enum VkVendor { + kQualcomm_VkVendor = 20803, + }; + void init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface, VkPhysicalDevice device, uint32_t featureFlags, uint32_t extensionFlags); void initGrCaps(const VkPhysicalDeviceProperties&, @@ -107,6 +115,10 @@ private: // Tells of if we can pass in straight GLSL string into vkCreateShaderModule bool fCanUseGLSLForShaderModule; + // On Adreno vulkan, they do not respect the imageOffset parameter at least in + // copyImageToBuffer. This flag says that we must do the copy starting from the origin always. + bool fMustDoCopiesFromOrigin; + typedef GrCaps INHERITED; }; diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 9a8a6e4e8c..ed165c52a1 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -1702,27 +1702,41 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, VK_PIPELINE_STAGE_TRANSFER_BIT, false); - GrVkTransferBuffer* transferBuffer = - static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height, - kXferGpuToCpu_GrBufferType, - kStream_GrAccessPattern)); - + size_t bpp = GrBytesPerPixel(config); + size_t tightRowBytes = bpp * width; bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); - VkOffset3D offset = { - left, - flipY ? surface->height() - top - height : top, - 0 - }; - // Copy the image to a buffer so we can map it to cpu memory VkBufferImageCopy region; memset(®ion, 0, sizeof(VkBufferImageCopy)); + + bool copyFromOrigin = this->vkCaps().mustDoCopiesFromOrigin(); + if (copyFromOrigin) { + region.imageOffset = { 0, 0, 0 }; + region.imageExtent = { (uint32_t)(left + width), + (uint32_t)(flipY ? surface->height() - top : top + height), + 1 + }; + } else { + VkOffset3D offset = { + left, + flipY ? surface->height() - top - height : top, + 0 + }; + region.imageOffset = offset; + region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; + } + + size_t transBufferRowBytes = bpp * region.imageExtent.width; + GrVkTransferBuffer* transferBuffer = + static_cast<GrVkTransferBuffer*>(this->createBuffer(transBufferRowBytes * height, + kXferGpuToCpu_GrBufferType, + kStream_GrAccessPattern)); + + // Copy the image to a buffer so we can map it to cpu memory region.bufferOffset = transferBuffer->offset(); region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below. region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images. region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; - region.imageOffset = offset; - region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; fCurrentCmdBuffer->copyImageToBuffer(this, image, @@ -1745,26 +1759,30 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, void* mappedMemory = transferBuffer->map(); - size_t tightRowBytes = GrBytesPerPixel(config) * width; + if (copyFromOrigin) { + uint32_t skipRows = region.imageExtent.height - height; + mappedMemory = (char*)mappedMemory + transBufferRowBytes * skipRows + bpp * left; + } + if (flipY) { const char* srcRow = reinterpret_cast<const char*>(mappedMemory); char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes; for (int y = 0; y < height; y++) { memcpy(dstRow, srcRow, tightRowBytes); - srcRow += tightRowBytes; + srcRow += transBufferRowBytes; dstRow -= rowBytes; } } else { - if (tightRowBytes == rowBytes) { + if (transBufferRowBytes == rowBytes) { memcpy(buffer, mappedMemory, rowBytes*height); } else { - SkRectMemcpy(buffer, rowBytes, mappedMemory, tightRowBytes, tightRowBytes, height); + SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, + height); } } transferBuffer->unmap(); transferBuffer->unref(); - return true; } |