Chromium Code Reviews| Index: src/gpu/vk/GrVkGpu.cpp |
| diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp |
| index 28dce344be37659f0e18b4fbd768dc0b7164461f..88b9542a032c51753083d7c2b935e0959b30df5e 100644 |
| --- a/src/gpu/vk/GrVkGpu.cpp |
| +++ b/src/gpu/vk/GrVkGpu.cpp |
| @@ -183,10 +183,12 @@ GrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPatter |
| kStatic_GrAccessPattern == accessPattern); |
| return GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern); |
| case kXferCpuToGpu_GrBufferType: |
| - SkASSERT(kStream_GrAccessPattern == accessPattern); |
| + SkASSERT(kDynamic_GrAccessPattern == accessPattern || |
| + kStream_GrAccessPattern == accessPattern); |
| return GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type); |
| case kXferGpuToCpu_GrBufferType: |
| - SkASSERT(kStream_GrAccessPattern == accessPattern); |
| + SkASSERT(kDynamic_GrAccessPattern == accessPattern || |
| + kStream_GrAccessPattern == accessPattern); |
| return GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type); |
| default: |
| SkFAIL("Unknown buffer type."); |
| @@ -274,6 +276,100 @@ bool GrVkGpu::onWritePixels(GrSurface* surface, |
| return false; |
| } |
| + |
| +bool GrVkGpu::onTransferPixels(GrSurface* surface, |
| + int left, int top, int width, int height, |
| + GrPixelConfig config, GrBuffer* transferBuffer, |
| + size_t bufferOffset, size_t rowBytes) { |
| + GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture()); |
| + if (!vkTex) { |
|
egdaniel
2016/04/18 16:46:34
why do you require that this is a texture for vulk
jvanverth1
2016/04/19 17:14:27
The expected use case for this is to transfer CPU-
egdaniel
2016/04/19 17:22:18
Well if we don't want to OpenGL and Vulkan be diff
bsalomon
2016/04/19 18:19:26
If we are only planning to use it with textures an
|
| + return false; |
| + } |
| + GrVkTransferBuffer* vkBuffer = static_cast<GrVkTransferBuffer*>(transferBuffer); |
| + if (!vkBuffer) { |
| + return false; |
| + } |
| + |
| + // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels. |
| + if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { |
| + return false; |
| + } |
| + |
| + // TODO: Not clear how to handle y axis flip |
|
egdaniel
2016/04/18 16:46:34
well I guess there are two options here. First wou
jvanverth1
2016/04/19 17:14:27
The temp image seems like the best bet -- I'm goin
|
| + if (kBottomLeft_GrSurfaceOrigin == vkTex->origin()) { |
| + return false; |
| + } |
| + |
| + bool success = false; |
| + if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) { |
| + // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo() |
| + SkASSERT(config == vkTex->desc().fConfig); |
| + // TODO: add compressed texture support |
| + // delete the following two lines and uncomment the two after that when ready |
| + vkTex->unref(); |
| + return false; |
| + //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width, |
| + // height); |
| + } else { |
| + // make sure the unmap has finished |
| + vkBuffer->addMemoryBarrier(this, |
| + VK_ACCESS_HOST_WRITE_BIT, |
| + VK_ACCESS_TRANSFER_READ_BIT, |
| + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, |
| + VK_PIPELINE_STAGE_TRANSFER_BIT, |
| + false); |
| + |
| + // Set up copy region |
| + VkOffset3D offset = { |
|
egdaniel
2016/04/18 16:46:34
why not just inline this like subresource or exten
jvanverth1
2016/04/19 17:14:27
Done.
|
| + left, |
| + top, |
| + 0 |
| + }; |
| + size_t bpp = GrBytesPerPixel(config); |
| + |
| + VkBufferImageCopy region; |
| + memset(®ion, 0, sizeof(VkBufferImageCopy)); |
| + region.bufferOffset = bufferOffset; |
| + region.bufferRowLength = (uint32_t)(rowBytes/bpp); |
| + region.bufferImageHeight = 0; |
| + region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; |
| + region.imageOffset = offset; |
| + region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; |
| + |
| + // Change layout of our target so it can be copied to |
| + VkImageLayout layout = vkTex->currentLayout(); |
| + VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout); |
| + VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; |
| + VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout); |
| + VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| + vkTex->setImageLayout(this, |
| + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| + srcAccessMask, |
| + dstAccessMask, |
| + srcStageMask, |
| + dstStageMask, |
| + false); |
| + |
| + // Copy the buffer to the image |
| + fCurrentCmdBuffer->copyBufferToImage(this, |
|
egdaniel
2016/04/18 16:46:34
if the surface is linearly tiled should we not jus
jvanverth1
2016/04/19 17:14:27
That would copy the data from the GPU to the CPU,
egdaniel
2016/04/19 17:22:18
unless it is cached :), but we can punt on this fo
|
| + vkBuffer, |
| + vkTex, |
| + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| + 1, |
| + ®ion); |
| + |
| + // Submit the current command buffer to the Queue |
| + this->submitCommandBuffer(kSkip_SyncQueue); |
| + } |
| + |
| + if (success) { |
| + vkTex->texturePriv().dirtyMipMaps(true); |
| + return true; |
| + } |
| + |
| + return false; |
| +} |
| + |
| bool GrVkGpu::uploadTexData(GrVkTexture* tex, |
| int left, int top, int width, int height, |
| GrPixelConfig dataConfig, |