aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/vk/GrVkCaps.cpp5
-rw-r--r--src/gpu/vk/GrVkCaps.h12
-rw-r--r--src/gpu/vk/GrVkGpu.cpp54
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(&region, 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;
}