aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2016-05-02 10:58:12 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-05-02 10:58:12 -0700
commitc578b06319f271ac46ac78e3b86f74fbceed360e (patch)
tree545d29b587b4750dcfb4d43920db3dc3019a67ab
parentb917e04d513fc5bc9ceb101f45a0d66a945a3017 (diff)
Fix VK WritePixels with offset rect
VkUploadPixelsTest was failing because it was reallocating the image when it didn't need to, because it was not resetting the rowBytes when it did need to, and because the origin was incorrect when using bottom-up images. GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1940963002 Review-Url: https://codereview.chromium.org/1940963002
-rw-r--r--src/gpu/vk/GrVkGpu.cpp83
1 files changed, 48 insertions, 35 deletions
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 33b53b1bcd..71782777a5 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -283,9 +283,10 @@ bool GrVkGpu::onWritePixels(GrSurface* surface,
success = this->uploadTexDataLinear(vkTex, left, top, width, height, config,
texels.begin()->fPixels, texels.begin()->fRowBytes);
} else {
- int mipLevels = texels.count();
- if (vkTex->texturePriv().maxMipMapLevel() != mipLevels) {
- if (!vkTex->reallocForMipmap(this, mipLevels)) {
+ int newMipLevels = texels.count();
+ int currentMipLevels = vkTex->texturePriv().maxMipMapLevel();
+ if ((currentMipLevels || newMipLevels != 1) && newMipLevels != currentMipLevels) {
+ if (!vkTex->reallocForMipmap(this, newMipLevels)) {
return false;
}
}
@@ -389,36 +390,45 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
size_t bpp = GrBytesPerPixel(dataConfig);
// texels is const.
- // But we may need to adjust the fPixels ptr based on the copyRect.
- // In this case we need to make a non-const shallow copy of texels.
- const SkTArray<GrMipLevel>* texelsPtr = &texels;
- SkTArray<GrMipLevel> texelsCopy;
- if (0 != left || 0 != top || width != tex->width() || height != tex->height()) {
- texelsCopy = texels;
+ // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
+ // Because of this we need to make a non-const shallow copy of texels.
+ SkTArray<GrMipLevel> texelsShallowCopy(texels);
- SkASSERT(1 == texels.count());
- SkASSERT(texelsCopy[0].fPixels);
-
- if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
- &width, &height, &texelsCopy[0].fPixels,
- &texelsCopy[0].fRowBytes)) {
- return false;
- }
-
- texelsPtr = &texelsCopy;
+ for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
+ currentMipLevel--) {
+ SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
}
// Determine whether we need to flip when we copy into the buffer
- bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsPtr->empty());
+ bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty());
+ // adjust any params (left, top, currentWidth, currentHeight
// find the combined size of all the mip levels and the relative offset of
// each into the collective buffer
- size_t combinedBufferSize = 0;
- SkTArray<size_t> individualMipOffsets(texelsPtr->count());
- for (int currentMipLevel = 0; currentMipLevel < texelsPtr->count(); currentMipLevel++) {
- int twoToTheMipLevel = 1 << currentMipLevel;
- int currentWidth = SkTMax(1, width / twoToTheMipLevel);
- int currentHeight = SkTMax(1, height / twoToTheMipLevel);
+ // Do the first level separately because we may need to adjust width and height
+ // (for the non-mipped case).
+ if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
+ &width,
+ &height,
+ &texelsShallowCopy[0].fPixels,
+ &texelsShallowCopy[0].fRowBytes)) {
+ return false;
+ }
+ SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count());
+ individualMipOffsets.push_back(0);
+ size_t combinedBufferSize = width * bpp * height;
+ int currentWidth = width;
+ int currentHeight = height;
+ for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
+ currentWidth = SkTMax(1, currentWidth/2);
+ currentHeight = SkTMax(1, currentHeight/2);
+ if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
+ &currentWidth,
+ &currentHeight,
+ &texelsShallowCopy[currentMipLevel].fPixels,
+ &texelsShallowCopy[currentMipLevel].fRowBytes)) {
+ return false;
+ }
const size_t trimmedSize = currentWidth * bpp * currentHeight;
individualMipOffsets.push_back(combinedBufferSize);
combinedBufferSize += trimmedSize;
@@ -429,18 +439,17 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
char* buffer = (char*) transferBuffer->map();
- SkTArray<VkBufferImageCopy> regions(texelsPtr->count());
+ SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count());
- for (int currentMipLevel = 0; currentMipLevel < texelsPtr->count(); currentMipLevel++) {
- int twoToTheMipLevel = 1 << currentMipLevel;
- int currentWidth = SkTMax(1, width / twoToTheMipLevel);
- int currentHeight = SkTMax(1, height / twoToTheMipLevel);
+ currentWidth = width;
+ currentHeight = height;
+ for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
const size_t trimRowBytes = currentWidth * bpp;
- const size_t rowBytes = (*texelsPtr)[currentMipLevel].fRowBytes;
+ const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
// copy data into the buffer, skipping the trailing bytes
char* dst = buffer + individualMipOffsets[currentMipLevel];
- const char* src = (const char*)(*texelsPtr)[currentMipLevel].fPixels;
+ const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
if (flipY) {
src += (currentHeight - 1) * rowBytes;
for (int y = 0; y < currentHeight; y++) {
@@ -460,8 +469,11 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
region.bufferRowLength = currentWidth;
region.bufferImageHeight = currentHeight;
region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
- region.imageOffset = { left, top, 0 };
+ region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 };
region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
+
+ currentWidth = SkTMax(1, currentWidth/2);
+ currentHeight = SkTMax(1, currentHeight/2);
}
transferBuffer->unmap();
@@ -553,12 +565,13 @@ GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budget
// This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
// requested, this ImageDesc describes the resolved texture. Therefore we always have samples set
// to 1.
+ int mipLevels = texels.empty() ? 1 : texels.count();
GrVkImage::ImageDesc imageDesc;
imageDesc.fImageType = VK_IMAGE_TYPE_2D;
imageDesc.fFormat = pixelFormat;
imageDesc.fWidth = desc.fWidth;
imageDesc.fHeight = desc.fHeight;
- imageDesc.fLevels = linearTiling ? 1 : texels.count();
+ imageDesc.fLevels = linearTiling ? 1 : mipLevels;
imageDesc.fSamples = 1;
imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
imageDesc.fUsageFlags = usageFlags;