Home | History | Annotate | Download | only in vk
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrVkGpu.h"
      9 
     10 #include "GrContextOptions.h"
     11 #include "GrGeometryProcessor.h"
     12 #include "GrGpuResourceCacheAccess.h"
     13 #include "GrMesh.h"
     14 #include "GrPipeline.h"
     15 #include "GrRenderTargetPriv.h"
     16 #include "GrSurfacePriv.h"
     17 #include "GrTexturePriv.h"
     18 
     19 #include "GrVkCommandBuffer.h"
     20 #include "GrVkGpuCommandBuffer.h"
     21 #include "GrVkImage.h"
     22 #include "GrVkIndexBuffer.h"
     23 #include "GrVkMemory.h"
     24 #include "GrVkPipeline.h"
     25 #include "GrVkPipelineState.h"
     26 #include "GrVkRenderPass.h"
     27 #include "GrVkResourceProvider.h"
     28 #include "GrVkSemaphore.h"
     29 #include "GrVkTexture.h"
     30 #include "GrVkTextureRenderTarget.h"
     31 #include "GrVkTransferBuffer.h"
     32 #include "GrVkVertexBuffer.h"
     33 
     34 #include "SkConvertPixels.h"
     35 #include "SkMipMap.h"
     36 
     37 #include "vk/GrVkInterface.h"
     38 #include "vk/GrVkTypes.h"
     39 
     40 #include "SkSLCompiler.h"
     41 
     42 #define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
     43 #define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
     44 #define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
     45 
     46 #ifdef SK_ENABLE_VK_LAYERS
     47 VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
     48     VkDebugReportFlagsEXT       flags,
     49     VkDebugReportObjectTypeEXT  objectType,
     50     uint64_t                    object,
     51     size_t                      location,
     52     int32_t                     messageCode,
     53     const char*                 pLayerPrefix,
     54     const char*                 pMessage,
     55     void*                       pUserData) {
     56     if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
     57         SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
     58         return VK_TRUE; // skip further layers
     59     } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
     60         SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
     61     } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
     62         SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
     63     } else {
     64         SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
     65     }
     66     return VK_FALSE;
     67 }
     68 #endif
     69 
     70 GrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
     71                        GrContext* context) {
     72     const GrVkBackendContext* vkBackendContext =
     73         reinterpret_cast<const GrVkBackendContext*>(backendContext);
     74     if (!vkBackendContext) {
     75         vkBackendContext = GrVkBackendContext::Create();
     76         if (!vkBackendContext) {
     77             return nullptr;
     78         }
     79     } else {
     80         vkBackendContext->ref();
     81     }
     82 
     83     if (!vkBackendContext->fInterface->validate(vkBackendContext->fExtensions)) {
     84         return nullptr;
     85     }
     86 
     87     return new GrVkGpu(context, options, vkBackendContext);
     88 }
     89 
     90 ////////////////////////////////////////////////////////////////////////////////
     91 
     92 GrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
     93                  const GrVkBackendContext* backendCtx)
     94     : INHERITED(context)
     95     , fDevice(backendCtx->fDevice)
     96     , fQueue(backendCtx->fQueue)
     97     , fResourceProvider(this) {
     98     fBackendContext.reset(backendCtx);
     99 
    100 #ifdef SK_ENABLE_VK_LAYERS
    101     fCallback = VK_NULL_HANDLE;
    102     if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) {
    103         // Setup callback creation information
    104         VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
    105         callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
    106         callbackCreateInfo.pNext = nullptr;
    107         callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
    108                                    VK_DEBUG_REPORT_WARNING_BIT_EXT |
    109                                    //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
    110                                    //VK_DEBUG_REPORT_DEBUG_BIT_EXT |
    111                                    VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
    112         callbackCreateInfo.pfnCallback = &DebugReportCallback;
    113         callbackCreateInfo.pUserData = nullptr;
    114 
    115         // Register the callback
    116         GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT(
    117                             backendCtx->fInstance, &callbackCreateInfo, nullptr, &fCallback));
    118     }
    119 #endif
    120 
    121     fCompiler = new SkSL::Compiler();
    122 
    123     fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice,
    124                                backendCtx->fFeatures, backendCtx->fExtensions));
    125     fCaps.reset(SkRef(fVkCaps.get()));
    126 
    127     VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps));
    128 
    129     const VkCommandPoolCreateInfo cmdPoolInfo = {
    130         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
    131         nullptr,                                         // pNext
    132         VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
    133         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // CmdPoolCreateFlags
    134         backendCtx->fGraphicsQueueIndex,                 // queueFamilyIndex
    135     };
    136     GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr,
    137                                                                &fCmdPool));
    138 
    139     // must call this after creating the CommandPool
    140     fResourceProvider.init();
    141     fCurrentCmdBuffer = fResourceProvider.findOrCreatePrimaryCommandBuffer();
    142     SkASSERT(fCurrentCmdBuffer);
    143     fCurrentCmdBuffer->begin(this);
    144 
    145     // set up our heaps
    146     fHeaps[kLinearImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
    147     // We want the OptimalImage_Heap to use a SubAlloc_strategy but it occasionally causes the
    148     // device to run out of memory. Most likely this is caused by fragmentation in the device heap
    149     // and we can't allocate more. Until we get a fix moving this to SingleAlloc.
    150     fHeaps[kOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 64*1024*1024));
    151     fHeaps[kSmallOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 2*1024*1024));
    152     fHeaps[kVertexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
    153     fHeaps[kIndexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
    154     fHeaps[kUniformBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 256*1024));
    155     fHeaps[kCopyReadBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
    156     fHeaps[kCopyWriteBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
    157 }
    158 
    159 GrVkGpu::~GrVkGpu() {
    160     fCurrentCmdBuffer->end(this);
    161     fCurrentCmdBuffer->unref(this);
    162 
    163     // wait for all commands to finish
    164     fResourceProvider.checkCommandBuffers();
    165     VkResult res = VK_CALL(QueueWaitIdle(fQueue));
    166 
    167     // On windows, sometimes calls to QueueWaitIdle return before actually signalling the fences
    168     // on the command buffers even though they have completed. This causes an assert to fire when
    169     // destroying the command buffers. Currently this ony seems to happen on windows, so we add a
    170     // sleep to make sure the fence signals.
    171 #ifdef SK_DEBUG
    172     if (this->vkCaps().mustSleepOnTearDown()) {
    173 #if defined(SK_BUILD_FOR_WIN)
    174         Sleep(10); // In milliseconds
    175 #else
    176         sleep(1);  // In seconds
    177 #endif
    178     }
    179 #endif
    180 
    181 #ifdef SK_DEBUG
    182     SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res);
    183 #endif
    184 
    185     for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) {
    186         fSemaphoresToWaitOn[i]->unref(this);
    187     }
    188     fSemaphoresToWaitOn.reset();
    189 
    190     fCopyManager.destroyResources(this);
    191 
    192     // must call this just before we destroy the command pool and VkDevice
    193     fResourceProvider.destroyResources(VK_ERROR_DEVICE_LOST == res);
    194 
    195     VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
    196 
    197     delete fCompiler;
    198 
    199 #ifdef SK_ENABLE_VK_LAYERS
    200     if (fCallback) {
    201         VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallback, nullptr));
    202         fCallback = VK_NULL_HANDLE;
    203     }
    204 #endif
    205 }
    206 
    207 ///////////////////////////////////////////////////////////////////////////////
    208 
    209 GrGpuCommandBuffer* GrVkGpu::createCommandBuffer(
    210             const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
    211             const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
    212     return new GrVkGpuCommandBuffer(this, colorInfo, stencilInfo);
    213 }
    214 
    215 void GrVkGpu::submitCommandBuffer(SyncQueue sync,
    216                                   const GrVkSemaphore::Resource* signalSemaphore) {
    217     SkASSERT(fCurrentCmdBuffer);
    218     fCurrentCmdBuffer->end(this);
    219 
    220     fCurrentCmdBuffer->submitToQueue(this, fQueue, sync, signalSemaphore, fSemaphoresToWaitOn);
    221 
    222     for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) {
    223         fSemaphoresToWaitOn[i]->unref(this);
    224     }
    225     fSemaphoresToWaitOn.reset();
    226 
    227     fResourceProvider.checkCommandBuffers();
    228 
    229     // Release old command buffer and create a new one
    230     fCurrentCmdBuffer->unref(this);
    231     fCurrentCmdBuffer = fResourceProvider.findOrCreatePrimaryCommandBuffer();
    232     SkASSERT(fCurrentCmdBuffer);
    233 
    234     fCurrentCmdBuffer->begin(this);
    235 }
    236 
    237 ///////////////////////////////////////////////////////////////////////////////
    238 GrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern accessPattern,
    239                                   const void* data) {
    240     GrBuffer* buff;
    241     switch (type) {
    242         case kVertex_GrBufferType:
    243             SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
    244                      kStatic_GrAccessPattern == accessPattern);
    245             buff = GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
    246             break;
    247         case kIndex_GrBufferType:
    248             SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
    249                      kStatic_GrAccessPattern == accessPattern);
    250             buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
    251             break;
    252         case kXferCpuToGpu_GrBufferType:
    253             SkASSERT(kStream_GrAccessPattern == accessPattern);
    254             buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type);
    255             break;
    256         case kXferGpuToCpu_GrBufferType:
    257             SkASSERT(kStream_GrAccessPattern == accessPattern);
    258             buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
    259             break;
    260         default:
    261             SkFAIL("Unknown buffer type.");
    262             return nullptr;
    263     }
    264     if (data && buff) {
    265         buff->updateData(data, size);
    266     }
    267     return buff;
    268 }
    269 
    270 ////////////////////////////////////////////////////////////////////////////////
    271 bool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
    272                                    GrPixelConfig srcConfig, DrawPreference* drawPreference,
    273                                    WritePixelTempDrawInfo* tempDrawInfo) {
    274     if (GrPixelConfigIsCompressed(dstSurface->config())) {
    275         return false;
    276     }
    277 
    278     GrRenderTarget* renderTarget = dstSurface->asRenderTarget();
    279 
    280     // Start off assuming no swizzling
    281     tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
    282     tempDrawInfo->fWriteConfig = srcConfig;
    283 
    284     // These settings we will always want if a temp draw is performed. Initially set the config
    285     // to srcConfig, though that may be modified if we decide to do a R/B swap
    286     tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
    287     tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
    288     tempDrawInfo->fTempSurfaceDesc.fWidth = width;
    289     tempDrawInfo->fTempSurfaceDesc.fHeight = height;
    290     tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
    291     tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
    292 
    293     if (dstSurface->config() == srcConfig) {
    294         return true;
    295     }
    296 
    297     if (renderTarget && this->vkCaps().isConfigRenderable(renderTarget->config(),
    298                                                           renderTarget->numColorSamples() > 1)) {
    299         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
    300 
    301         bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
    302 
    303         if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) {
    304             if (!this->vkCaps().isConfigTexturable(dstSurface->config())) {
    305                 return false;
    306             }
    307             tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
    308             tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
    309             tempDrawInfo->fWriteConfig = dstSurface->config();
    310         }
    311         return true;
    312     }
    313 
    314     return false;
    315 }
    316 
    317 bool GrVkGpu::onWritePixels(GrSurface* surface,
    318                             int left, int top, int width, int height,
    319                             GrPixelConfig config,
    320                             const SkTArray<GrMipLevel>& texels) {
    321     GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
    322     if (!vkTex) {
    323         return false;
    324     }
    325 
    326     // Make sure we have at least the base level
    327     if (texels.empty() || !texels.begin()->fPixels) {
    328         return false;
    329     }
    330 
    331     // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
    332     if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
    333         return false;
    334     }
    335 
    336     bool success = false;
    337     if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) {
    338         // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo()
    339         SkASSERT(config == vkTex->desc().fConfig);
    340         // TODO: add compressed texture support
    341         // delete the following two lines and uncomment the two after that when ready
    342         vkTex->unref();
    343         return false;
    344         //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width,
    345         //                                       height);
    346     } else {
    347         bool linearTiling = vkTex->isLinearTiled();
    348         if (linearTiling) {
    349             if (texels.count() > 1) {
    350                 SkDebugf("Can't upload mipmap data to linear tiled texture");
    351                 return false;
    352             }
    353             if (VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) {
    354                 // Need to change the layout to general in order to perform a host write
    355                 vkTex->setImageLayout(this,
    356                                       VK_IMAGE_LAYOUT_GENERAL,
    357                                       VK_ACCESS_HOST_WRITE_BIT,
    358                                       VK_PIPELINE_STAGE_HOST_BIT,
    359                                       false);
    360                 this->submitCommandBuffer(kForce_SyncQueue);
    361             }
    362             success = this->uploadTexDataLinear(vkTex, left, top, width, height, config,
    363                                                 texels.begin()->fPixels, texels.begin()->fRowBytes);
    364         } else {
    365             int newMipLevels = texels.count();
    366             int currentMipLevels = vkTex->texturePriv().maxMipMapLevel() + 1;
    367             if (newMipLevels != currentMipLevels) {
    368                 if (!vkTex->reallocForMipmap(this, newMipLevels)) {
    369                     return false;
    370                 }
    371             }
    372             success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config, texels);
    373         }
    374     }
    375 
    376     return success;
    377 }
    378 
    379 void GrVkGpu::resolveImage(GrVkRenderTarget* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
    380                            const SkIPoint& dstPoint) {
    381     SkASSERT(dst);
    382     SkASSERT(src && src->numColorSamples() > 1 && src->msaaImage());
    383 
    384     if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
    385         this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
    386     }
    387 
    388     // Flip rect if necessary
    389     SkIRect srcVkRect = srcRect;
    390     int32_t dstY = dstPoint.fY;
    391 
    392     if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
    393         SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
    394         srcVkRect.fTop = src->height() - srcRect.fBottom;
    395         srcVkRect.fBottom = src->height() - srcRect.fTop;
    396         dstY = dst->height() - dstPoint.fY - srcVkRect.height();
    397     }
    398 
    399     VkImageResolve resolveInfo;
    400     resolveInfo.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
    401     resolveInfo.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
    402     resolveInfo.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
    403     resolveInfo.dstOffset = { dstPoint.fX, dstY, 0 };
    404     resolveInfo.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
    405 
    406     dst->setImageLayout(this,
    407                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    408                         VK_ACCESS_TRANSFER_WRITE_BIT,
    409                         VK_PIPELINE_STAGE_TRANSFER_BIT,
    410                         false);
    411 
    412     src->msaaImage()->setImageLayout(this,
    413                                      VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
    414                                      VK_ACCESS_TRANSFER_READ_BIT,
    415                                      VK_PIPELINE_STAGE_TRANSFER_BIT,
    416                                      false);
    417 
    418     fCurrentCmdBuffer->resolveImage(this, *src->msaaImage(), *dst, 1, &resolveInfo);
    419 }
    420 
    421 void GrVkGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
    422     if (target->needsResolve()) {
    423         SkASSERT(target->numColorSamples() > 1);
    424         GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
    425         SkASSERT(rt->msaaImage());
    426 
    427         const SkIRect& srcRect = rt->getResolveRect();
    428 
    429         this->resolveImage(rt, rt, srcRect, SkIPoint::Make(srcRect.fLeft, srcRect.fTop));
    430 
    431         rt->flagAsResolved();
    432 
    433         if (requiresSubmit) {
    434             this->submitCommandBuffer(kSkip_SyncQueue);
    435         }
    436     }
    437 }
    438 
    439 bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex,
    440                                   int left, int top, int width, int height,
    441                                   GrPixelConfig dataConfig,
    442                                   const void* data,
    443                                   size_t rowBytes) {
    444     SkASSERT(data);
    445     SkASSERT(tex->isLinearTiled());
    446 
    447     // If we're uploading compressed data then we should be using uploadCompressedTexData
    448     SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
    449 
    450     size_t bpp = GrBytesPerPixel(dataConfig);
    451 
    452     const GrSurfaceDesc& desc = tex->desc();
    453 
    454     if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
    455                                                &width, &height, &data, &rowBytes)) {
    456         return false;
    457     }
    458     size_t trimRowBytes = width * bpp;
    459 
    460     SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
    461              VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
    462     const VkImageSubresource subres = {
    463         VK_IMAGE_ASPECT_COLOR_BIT,
    464         0,  // mipLevel
    465         0,  // arraySlice
    466     };
    467     VkSubresourceLayout layout;
    468     VkResult err;
    469 
    470     const GrVkInterface* interface = this->vkInterface();
    471 
    472     GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
    473                                                     tex->image(),
    474                                                     &subres,
    475                                                     &layout));
    476 
    477     int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height : top;
    478     const GrVkAlloc& alloc = tex->alloc();
    479     VkDeviceSize offset = alloc.fOffset + texTop*layout.rowPitch + left*bpp;
    480     VkDeviceSize size = height*layout.rowPitch;
    481     void* mapPtr;
    482     err = GR_VK_CALL(interface, MapMemory(fDevice, alloc.fMemory, offset, size, 0, &mapPtr));
    483     if (err) {
    484         return false;
    485     }
    486 
    487     if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
    488         // copy into buffer by rows
    489         const char* srcRow = reinterpret_cast<const char*>(data);
    490         char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
    491         for (int y = 0; y < height; y++) {
    492             memcpy(dstRow, srcRow, trimRowBytes);
    493             srcRow += rowBytes;
    494             dstRow -= layout.rowPitch;
    495         }
    496     } else {
    497         SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes,
    498                      height);
    499     }
    500 
    501     GrVkMemory::FlushMappedAlloc(this, alloc);
    502     GR_VK_CALL(interface, UnmapMemory(fDevice, alloc.fMemory));
    503 
    504     return true;
    505 }
    506 
    507 bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
    508                                    int left, int top, int width, int height,
    509                                    GrPixelConfig dataConfig,
    510                                    const SkTArray<GrMipLevel>& texels) {
    511     SkASSERT(!tex->isLinearTiled());
    512     // The assumption is either that we have no mipmaps, or that our rect is the entire texture
    513     SkASSERT(1 == texels.count() ||
    514              (0 == left && 0 == top && width == tex->width() && height == tex->height()));
    515 
    516     // If we're uploading compressed data then we should be using uploadCompressedTexData
    517     SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
    518 
    519     if (width == 0 || height == 0) {
    520         return false;
    521     }
    522 
    523     const GrSurfaceDesc& desc = tex->desc();
    524     SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
    525     size_t bpp = GrBytesPerPixel(dataConfig);
    526 
    527     // texels is const.
    528     // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
    529     // Because of this we need to make a non-const shallow copy of texels.
    530     SkTArray<GrMipLevel> texelsShallowCopy(texels);
    531 
    532     for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
    533          currentMipLevel--) {
    534         SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
    535     }
    536 
    537     // Determine whether we need to flip when we copy into the buffer
    538     bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty());
    539 
    540     // adjust any params (left, top, currentWidth, currentHeight
    541     // find the combined size of all the mip levels and the relative offset of
    542     // each into the collective buffer
    543     // Do the first level separately because we may need to adjust width and height
    544     // (for the non-mipped case).
    545     if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
    546                                                &width,
    547                                                &height,
    548                                                &texelsShallowCopy[0].fPixels,
    549                                                &texelsShallowCopy[0].fRowBytes)) {
    550         return false;
    551     }
    552     SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count());
    553     individualMipOffsets.push_back(0);
    554     size_t combinedBufferSize = width * bpp * height;
    555     int currentWidth = width;
    556     int currentHeight = height;
    557     // The alignment must be at least 4 bytes and a multiple of the bytes per pixel of the image
    558     // config. This works with the assumption that the bytes in pixel config is always a power of 2.
    559     SkASSERT((bpp & (bpp - 1)) == 0);
    560     const size_t alignmentMask = 0x3 | (bpp - 1);
    561     for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
    562         currentWidth = SkTMax(1, currentWidth/2);
    563         currentHeight = SkTMax(1, currentHeight/2);
    564         if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
    565                                                    &currentWidth,
    566                                                    &currentHeight,
    567                                                    &texelsShallowCopy[currentMipLevel].fPixels,
    568                                                    &texelsShallowCopy[currentMipLevel].fRowBytes)) {
    569             return false;
    570         }
    571         const size_t trimmedSize = currentWidth * bpp * currentHeight;
    572         const size_t alignmentDiff = combinedBufferSize & alignmentMask;
    573         if (alignmentDiff != 0) {
    574            combinedBufferSize += alignmentMask - alignmentDiff + 1;
    575         }
    576         individualMipOffsets.push_back(combinedBufferSize);
    577         combinedBufferSize += trimmedSize;
    578     }
    579 
    580     // allocate buffer to hold our mip data
    581     GrVkTransferBuffer* transferBuffer =
    582                    GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
    583 
    584     char* buffer = (char*) transferBuffer->map();
    585     SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count());
    586 
    587     currentWidth = width;
    588     currentHeight = height;
    589     for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
    590         const size_t trimRowBytes = currentWidth * bpp;
    591         const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
    592 
    593         // copy data into the buffer, skipping the trailing bytes
    594         char* dst = buffer + individualMipOffsets[currentMipLevel];
    595         const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
    596         if (flipY) {
    597             src += (currentHeight - 1) * rowBytes;
    598             for (int y = 0; y < currentHeight; y++) {
    599                 memcpy(dst, src, trimRowBytes);
    600                 src -= rowBytes;
    601                 dst += trimRowBytes;
    602             }
    603         } else {
    604             SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight);
    605         }
    606 
    607         VkBufferImageCopy& region = regions.push_back();
    608         memset(&region, 0, sizeof(VkBufferImageCopy));
    609         region.bufferOffset = transferBuffer->offset() + individualMipOffsets[currentMipLevel];
    610         region.bufferRowLength = currentWidth;
    611         region.bufferImageHeight = currentHeight;
    612         region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
    613         region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 };
    614         region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
    615 
    616         currentWidth = SkTMax(1, currentWidth/2);
    617         currentHeight = SkTMax(1, currentHeight/2);
    618     }
    619 
    620     // no need to flush non-coherent memory, unmap will do that for us
    621     transferBuffer->unmap();
    622 
    623     // Change layout of our target so it can be copied to
    624     tex->setImageLayout(this,
    625                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    626                         VK_ACCESS_TRANSFER_WRITE_BIT,
    627                         VK_PIPELINE_STAGE_TRANSFER_BIT,
    628                         false);
    629 
    630     // Copy the buffer to the image
    631     fCurrentCmdBuffer->copyBufferToImage(this,
    632                                          transferBuffer,
    633                                          tex,
    634                                          VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    635                                          regions.count(),
    636                                          regions.begin());
    637     transferBuffer->unref();
    638 
    639     return true;
    640 }
    641 
    642 ////////////////////////////////////////////////////////////////////////////////
    643 GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
    644                                     const SkTArray<GrMipLevel>& texels) {
    645     bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
    646 
    647     VkFormat pixelFormat;
    648     if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
    649         return nullptr;
    650     }
    651 
    652     if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
    653         return nullptr;
    654     }
    655 
    656     if (renderTarget && !fVkCaps->isConfigRenderable(desc.fConfig, false)) {
    657         return nullptr;
    658     }
    659 
    660     bool linearTiling = false;
    661     if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) {
    662         // we can't have a linear texture with a mipmap
    663         if (texels.count() > 1) {
    664             SkDebugf("Trying to create linear tiled texture with mipmap");
    665             return nullptr;
    666         }
    667         if (fVkCaps->isConfigTexturableLinearly(desc.fConfig) &&
    668             (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) {
    669             linearTiling = true;
    670         } else {
    671             return nullptr;
    672         }
    673     }
    674 
    675     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
    676     if (renderTarget) {
    677         usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    678     }
    679 
    680     // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
    681     // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
    682     // will be using this texture in some copy or not. Also this assumes, as is the current case,
    683     // that all render targets in vulkan are also textures. If we change this practice of setting
    684     // both bits, we must make sure to set the destination bit if we are uploading srcData to the
    685     // texture.
    686     usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    687 
    688     VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
    689                                                            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
    690 
    691     // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
    692     // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set
    693     // to 1.
    694     int mipLevels = texels.empty() ? 1 : texels.count();
    695     GrVkImage::ImageDesc imageDesc;
    696     imageDesc.fImageType = VK_IMAGE_TYPE_2D;
    697     imageDesc.fFormat = pixelFormat;
    698     imageDesc.fWidth = desc.fWidth;
    699     imageDesc.fHeight = desc.fHeight;
    700     imageDesc.fLevels = linearTiling ? 1 : mipLevels;
    701     imageDesc.fSamples = 1;
    702     imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
    703     imageDesc.fUsageFlags = usageFlags;
    704     imageDesc.fMemProps = memProps;
    705 
    706     GrVkTexture* tex;
    707     if (renderTarget) {
    708         tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc,
    709                                                                     imageDesc);
    710     } else {
    711         tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc);
    712     }
    713 
    714     if (!tex) {
    715         return nullptr;
    716     }
    717 
    718     if (!texels.empty()) {
    719         SkASSERT(texels.begin()->fPixels);
    720         bool success;
    721         if (linearTiling) {
    722             success = this->uploadTexDataLinear(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
    723                                                 texels.begin()->fPixels, texels.begin()->fRowBytes);
    724         } else {
    725             success = this->uploadTexDataOptimal(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
    726                                                  texels);
    727         }
    728         if (!success) {
    729             tex->unref();
    730             return nullptr;
    731         }
    732     }
    733 
    734     return tex;
    735 }
    736 
    737 ////////////////////////////////////////////////////////////////////////////////
    738 
    739 bool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src,
    740                            VkDeviceSize offset, VkDeviceSize size) {
    741 
    742     // Update the buffer
    743     fCurrentCmdBuffer->updateBuffer(this, buffer, offset, size, src);
    744 
    745     return true;
    746 }
    747 
    748 ////////////////////////////////////////////////////////////////////////////////
    749 
    750 static GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
    751     // By default, all textures in Vk use TopLeft
    752     if (kDefault_GrSurfaceOrigin == origin) {
    753         return kTopLeft_GrSurfaceOrigin;
    754     } else {
    755         return origin;
    756     }
    757 }
    758 
    759 sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
    760                                                GrWrapOwnership ownership) {
    761     if (0 == desc.fTextureHandle) {
    762         return nullptr;
    763     }
    764 
    765     int maxSize = this->caps()->maxTextureSize();
    766     if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
    767         return nullptr;
    768     }
    769 
    770     const GrVkImageInfo* info = reinterpret_cast<const GrVkImageInfo*>(desc.fTextureHandle);
    771     if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc.fMemory) {
    772         return nullptr;
    773     }
    774 #ifdef SK_DEBUG
    775     VkFormat format;
    776     if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) {
    777         return nullptr;
    778     }
    779     SkASSERT(format == info->fFormat);
    780 #endif
    781 
    782     GrSurfaceDesc surfDesc;
    783     // next line relies on GrBackendTextureDesc's flags matching GrTexture's
    784     surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
    785     surfDesc.fWidth = desc.fWidth;
    786     surfDesc.fHeight = desc.fHeight;
    787     surfDesc.fConfig = desc.fConfig;
    788     surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
    789     bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
    790     SkASSERT(!renderTarget || kAdoptAndCache_GrWrapOwnership != ownership);  // Not supported
    791     // In GL, Chrome assumes all textures are BottomLeft
    792     // In VK, we don't have this restriction
    793     surfDesc.fOrigin = resolve_origin(desc.fOrigin);
    794 
    795     if (!renderTarget) {
    796         return GrVkTexture::MakeWrappedTexture(this, surfDesc, ownership, info);
    797     }
    798     return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, surfDesc, ownership, info);
    799 }
    800 
    801 sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc){
    802 
    803     const GrVkImageInfo* info =
    804         reinterpret_cast<const GrVkImageInfo*>(wrapDesc.fRenderTargetHandle);
    805     if (VK_NULL_HANDLE == info->fImage) {
    806         return nullptr;
    807     }
    808 
    809     GrSurfaceDesc desc;
    810     desc.fConfig = wrapDesc.fConfig;
    811     desc.fFlags = kCheckAllocation_GrSurfaceFlag | kRenderTarget_GrSurfaceFlag;
    812     desc.fWidth = wrapDesc.fWidth;
    813     desc.fHeight = wrapDesc.fHeight;
    814     desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
    815 
    816     desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
    817 
    818     sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(this, desc, info);
    819     if (tgt && wrapDesc.fStencilBits) {
    820         if (!createStencilAttachmentForRenderTarget(tgt.get(), desc.fWidth, desc.fHeight)) {
    821             return nullptr;
    822         }
    823     }
    824     return tgt;
    825 }
    826 
    827 void GrVkGpu::generateMipmap(GrVkTexture* tex) {
    828     // don't do anything for linearly tiled textures (can't have mipmaps)
    829     if (tex->isLinearTiled()) {
    830         SkDebugf("Trying to create mipmap for linear tiled texture");
    831         return;
    832     }
    833 
    834     // determine if we can blit to and from this format
    835     const GrVkCaps& caps = this->vkCaps();
    836     if (!caps.configCanBeDstofBlit(tex->config(), false) ||
    837         !caps.configCanBeSrcofBlit(tex->config(), false) ||
    838         !caps.mipMapSupport()) {
    839         return;
    840     }
    841 
    842     if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
    843         this->submitCommandBuffer(kSkip_SyncQueue);
    844     }
    845 
    846     // We may need to resolve the texture first if it is also a render target
    847     GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(tex->asRenderTarget());
    848     if (texRT) {
    849         this->internalResolveRenderTarget(texRT, false);
    850     }
    851 
    852     int width = tex->width();
    853     int height = tex->height();
    854     VkImageBlit blitRegion;
    855     memset(&blitRegion, 0, sizeof(VkImageBlit));
    856 
    857     // SkMipMap doesn't include the base level in the level count so we have to add 1
    858     uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height()) + 1;
    859     if (levelCount != tex->mipLevels()) {
    860         const GrVkResource* oldResource = tex->resource();
    861         oldResource->ref();
    862         // grab handle to the original image resource
    863         VkImage oldImage = tex->image();
    864 
    865         // change the original image's layout so we can copy from it
    866         tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
    867                             VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
    868 
    869         if (!tex->reallocForMipmap(this, levelCount)) {
    870             oldResource->unref(this);
    871             return;
    872         }
    873         // change the new image's layout so we can blit to it
    874         tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
    875                             VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
    876 
    877         // Blit original image to top level of new image
    878         blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
    879         blitRegion.srcOffsets[0] = { 0, 0, 0 };
    880         blitRegion.srcOffsets[1] = { width, height, 1 };
    881         blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
    882         blitRegion.dstOffsets[0] = { 0, 0, 0 };
    883         blitRegion.dstOffsets[1] = { width, height, 1 };
    884 
    885         fCurrentCmdBuffer->blitImage(this,
    886                                      oldResource,
    887                                      oldImage,
    888                                      VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
    889                                      tex->resource(),
    890                                      tex->image(),
    891                                      VK_IMAGE_LAYOUT_GENERAL,
    892                                      1,
    893                                      &blitRegion,
    894                                      VK_FILTER_LINEAR);
    895 
    896         oldResource->unref(this);
    897     } else {
    898         // change layout of the layers so we can write to them.
    899         tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
    900                             VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
    901     }
    902 
    903     // setup memory barrier
    904     SkASSERT(GrVkFormatToPixelConfig(tex->imageFormat(), nullptr));
    905     VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
    906     VkImageMemoryBarrier imageMemoryBarrier = {
    907         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,          // sType
    908         NULL,                                            // pNext
    909         VK_ACCESS_TRANSFER_WRITE_BIT,                    // srcAccessMask
    910         VK_ACCESS_TRANSFER_READ_BIT,                     // dstAccessMask
    911         VK_IMAGE_LAYOUT_GENERAL,                         // oldLayout
    912         VK_IMAGE_LAYOUT_GENERAL,                         // newLayout
    913         VK_QUEUE_FAMILY_IGNORED,                         // srcQueueFamilyIndex
    914         VK_QUEUE_FAMILY_IGNORED,                         // dstQueueFamilyIndex
    915         tex->image(),                                    // image
    916         { aspectFlags, 0, 1, 0, 1 }                      // subresourceRange
    917     };
    918 
    919     // Blit the miplevels
    920     uint32_t mipLevel = 1;
    921     while (mipLevel < levelCount) {
    922         int prevWidth = width;
    923         int prevHeight = height;
    924         width = SkTMax(1, width / 2);
    925         height = SkTMax(1, height / 2);
    926 
    927         imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1;
    928         this->addImageMemoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
    929                                     false, &imageMemoryBarrier);
    930 
    931         blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel - 1, 0, 1 };
    932         blitRegion.srcOffsets[0] = { 0, 0, 0 };
    933         blitRegion.srcOffsets[1] = { prevWidth, prevHeight, 1 };
    934         blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 };
    935         blitRegion.dstOffsets[0] = { 0, 0, 0 };
    936         blitRegion.dstOffsets[1] = { width, height, 1 };
    937         fCurrentCmdBuffer->blitImage(this,
    938                                      *tex,
    939                                      *tex,
    940                                      1,
    941                                      &blitRegion,
    942                                      VK_FILTER_LINEAR);
    943         ++mipLevel;
    944     }
    945 }
    946 
    947 ////////////////////////////////////////////////////////////////////////////////
    948 
    949 GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
    950                                                                      int width,
    951                                                                      int height) {
    952     SkASSERT(width >= rt->width());
    953     SkASSERT(height >= rt->height());
    954 
    955     int samples = rt->numStencilSamples();
    956 
    957     const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
    958 
    959     GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
    960                                                                  width,
    961                                                                  height,
    962                                                                  samples,
    963                                                                  sFmt));
    964     fStats.incStencilAttachmentCreates();
    965     return stencil;
    966 }
    967 
    968 ////////////////////////////////////////////////////////////////////////////////
    969 
    970 bool copy_testing_data(GrVkGpu* gpu, void* srcData, const GrVkAlloc& alloc,
    971                        size_t srcRowBytes, size_t dstRowBytes, int h) {
    972     void* mapPtr;
    973     VkResult err = GR_VK_CALL(gpu->vkInterface(), MapMemory(gpu->device(),
    974                                                             alloc.fMemory,
    975                                                             alloc.fOffset,
    976                                                             dstRowBytes * h,
    977                                                             0,
    978                                                             &mapPtr));
    979     if (err) {
    980         return false;
    981     }
    982 
    983     // If there is no padding on dst we can do a single memcopy.
    984     // This assumes the srcData comes in with no padding.
    985     SkRectMemcpy(mapPtr, static_cast<size_t>(dstRowBytes), srcData, srcRowBytes, srcRowBytes, h);
    986     GrVkMemory::FlushMappedAlloc(gpu, alloc);
    987     GR_VK_CALL(gpu->vkInterface(), UnmapMemory(gpu->device(), alloc.fMemory));
    988     return true;
    989 }
    990 
    991 GrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
    992                                                          GrPixelConfig config,
    993                                                          bool isRenderTarget) {
    994 
    995     VkFormat pixelFormat;
    996     if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
    997         return 0;
    998     }
    999 
   1000     bool linearTiling = false;
   1001     if (!fVkCaps->isConfigTexturable(config)) {
   1002         return 0;
   1003     }
   1004 
   1005     if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) {
   1006         return 0;
   1007     }
   1008 
   1009     if (fVkCaps->isConfigTexturableLinearly(config) &&
   1010         (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false))) {
   1011         linearTiling = true;
   1012     }
   1013 
   1014     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
   1015     usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
   1016     usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
   1017     if (isRenderTarget) {
   1018         usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
   1019     }
   1020 
   1021     VkImage image = VK_NULL_HANDLE;
   1022     GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0, 0 };
   1023 
   1024     VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
   1025     VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
   1026                                 ? VK_IMAGE_LAYOUT_PREINITIALIZED
   1027                                 : VK_IMAGE_LAYOUT_UNDEFINED;
   1028 
   1029     // Create Image
   1030     VkSampleCountFlagBits vkSamples;
   1031     if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
   1032         return 0;
   1033     }
   1034 
   1035     const VkImageCreateInfo imageCreateInfo = {
   1036         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
   1037         NULL,                                        // pNext
   1038         0,                                           // VkImageCreateFlags
   1039         VK_IMAGE_TYPE_2D,                            // VkImageType
   1040         pixelFormat,                                 // VkFormat
   1041         { (uint32_t) w, (uint32_t) h, 1 },           // VkExtent3D
   1042         1,                                           // mipLevels
   1043         1,                                           // arrayLayers
   1044         vkSamples,                                   // samples
   1045         imageTiling,                                 // VkImageTiling
   1046         usageFlags,                                  // VkImageUsageFlags
   1047         VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
   1048         0,                                           // queueFamilyCount
   1049         0,                                           // pQueueFamilyIndices
   1050         initialLayout                                // initialLayout
   1051     };
   1052 
   1053     GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
   1054 
   1055     if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc)) {
   1056         VK_CALL(DestroyImage(this->device(), image, nullptr));
   1057         return 0;
   1058     }
   1059 
   1060     if (srcData) {
   1061         size_t bpp = GrBytesPerPixel(config);
   1062         size_t rowCopyBytes = bpp * w;
   1063         if (linearTiling) {
   1064             const VkImageSubresource subres = {
   1065                 VK_IMAGE_ASPECT_COLOR_BIT,
   1066                 0,  // mipLevel
   1067                 0,  // arraySlice
   1068             };
   1069             VkSubresourceLayout layout;
   1070 
   1071             VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
   1072 
   1073             if (!copy_testing_data(this, srcData, alloc, rowCopyBytes,
   1074                                    static_cast<size_t>(layout.rowPitch), h)) {
   1075                 GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
   1076                 VK_CALL(DestroyImage(fDevice, image, nullptr));
   1077                 return 0;
   1078             }
   1079         } else {
   1080             SkASSERT(w && h);
   1081 
   1082             VkBuffer buffer;
   1083             VkBufferCreateInfo bufInfo;
   1084             memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
   1085             bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
   1086             bufInfo.flags = 0;
   1087             bufInfo.size = rowCopyBytes * h;
   1088             bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
   1089             bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
   1090             bufInfo.queueFamilyIndexCount = 0;
   1091             bufInfo.pQueueFamilyIndices = nullptr;
   1092             VkResult err;
   1093             err = VK_CALL(CreateBuffer(fDevice, &bufInfo, nullptr, &buffer));
   1094 
   1095             if (err) {
   1096                 GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
   1097                 VK_CALL(DestroyImage(fDevice, image, nullptr));
   1098                 return 0;
   1099             }
   1100 
   1101             GrVkAlloc bufferAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
   1102             if (!GrVkMemory::AllocAndBindBufferMemory(this, buffer, GrVkBuffer::kCopyRead_Type,
   1103                                                       true, &bufferAlloc)) {
   1104                 GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
   1105                 VK_CALL(DestroyImage(fDevice, image, nullptr));
   1106                 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
   1107                 return 0;
   1108             }
   1109 
   1110             if (!copy_testing_data(this, srcData, bufferAlloc, rowCopyBytes, rowCopyBytes, h)) {
   1111                 GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
   1112                 VK_CALL(DestroyImage(fDevice, image, nullptr));
   1113                 GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
   1114                 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
   1115                 return 0;
   1116             }
   1117 
   1118             const VkCommandBufferAllocateInfo cmdInfo = {
   1119                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
   1120                 NULL,                                             // pNext
   1121                 fCmdPool,                                         // commandPool
   1122                 VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
   1123                 1                                                 // bufferCount
   1124             };
   1125 
   1126             VkCommandBuffer cmdBuffer;
   1127             err = VK_CALL(AllocateCommandBuffers(fDevice, &cmdInfo, &cmdBuffer));
   1128             if (err) {
   1129                 GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
   1130                 VK_CALL(DestroyImage(fDevice, image, nullptr));
   1131                 GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
   1132                 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
   1133                 return 0;
   1134             }
   1135 
   1136             VkCommandBufferBeginInfo cmdBufferBeginInfo;
   1137             memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
   1138             cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
   1139             cmdBufferBeginInfo.pNext = nullptr;
   1140             cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
   1141             cmdBufferBeginInfo.pInheritanceInfo = nullptr;
   1142 
   1143             err = VK_CALL(BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
   1144             SkASSERT(!err);
   1145 
   1146             // Set image layout and add barrier
   1147             VkImageMemoryBarrier barrier;
   1148             memset(&barrier, 0, sizeof(VkImageMemoryBarrier));
   1149             barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
   1150             barrier.pNext = nullptr;
   1151             barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLayout);
   1152             barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
   1153             barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
   1154             barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
   1155             barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
   1156             barrier.image = image;
   1157             barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0 , 1};
   1158 
   1159             VK_CALL(CmdPipelineBarrier(cmdBuffer,
   1160                                        GrVkMemory::LayoutToPipelineStageFlags(initialLayout),
   1161                                        VK_PIPELINE_STAGE_TRANSFER_BIT,
   1162                                        0,
   1163                                        0, nullptr,
   1164                                        0, nullptr,
   1165                                        1, &barrier));
   1166             initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
   1167 
   1168             // Submit copy command
   1169             VkBufferImageCopy region;
   1170             memset(&region, 0, sizeof(VkBufferImageCopy));
   1171             region.bufferOffset = 0;
   1172             region.bufferRowLength = w;
   1173             region.bufferImageHeight = h;
   1174             region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
   1175             region.imageOffset = { 0, 0, 0 };
   1176             region.imageExtent = { (uint32_t)w, (uint32_t)h, 1 };
   1177 
   1178             VK_CALL(CmdCopyBufferToImage(cmdBuffer, buffer, image, initialLayout, 1, &region));
   1179 
   1180             // End CommandBuffer
   1181             err = VK_CALL(EndCommandBuffer(cmdBuffer));
   1182             SkASSERT(!err);
   1183 
   1184             // Create Fence for queue
   1185             VkFence fence;
   1186             VkFenceCreateInfo fenceInfo;
   1187             memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
   1188             fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
   1189 
   1190             err = VK_CALL(CreateFence(fDevice, &fenceInfo, nullptr, &fence));
   1191             SkASSERT(!err);
   1192 
   1193             VkSubmitInfo submitInfo;
   1194             memset(&submitInfo, 0, sizeof(VkSubmitInfo));
   1195             submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
   1196             submitInfo.pNext = nullptr;
   1197             submitInfo.waitSemaphoreCount = 0;
   1198             submitInfo.pWaitSemaphores = nullptr;
   1199             submitInfo.pWaitDstStageMask = 0;
   1200             submitInfo.commandBufferCount = 1;
   1201             submitInfo.pCommandBuffers = &cmdBuffer;
   1202             submitInfo.signalSemaphoreCount = 0;
   1203             submitInfo.pSignalSemaphores = nullptr;
   1204             err = VK_CALL(QueueSubmit(this->queue(), 1, &submitInfo, fence));
   1205             SkASSERT(!err);
   1206 
   1207             err = VK_CALL(WaitForFences(fDevice, 1, &fence, true, UINT64_MAX));
   1208             if (VK_TIMEOUT == err) {
   1209                 GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
   1210                 VK_CALL(DestroyImage(fDevice, image, nullptr));
   1211                 GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
   1212                 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
   1213                 VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
   1214                 VK_CALL(DestroyFence(fDevice, fence, nullptr));
   1215                 SkDebugf("Fence failed to signal: %d\n", err);
   1216                 SkFAIL("failing");
   1217             }
   1218             SkASSERT(!err);
   1219 
   1220             // Clean up transfer resources
   1221             GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
   1222             VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
   1223             VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
   1224             VK_CALL(DestroyFence(fDevice, fence, nullptr));
   1225         }
   1226     }
   1227 
   1228     GrVkImageInfo* info = new GrVkImageInfo;
   1229     info->fImage = image;
   1230     info->fAlloc = alloc;
   1231     info->fImageTiling = imageTiling;
   1232     info->fImageLayout = initialLayout;
   1233     info->fFormat = pixelFormat;
   1234     info->fLevelCount = 1;
   1235 
   1236     return (GrBackendObject)info;
   1237 }
   1238 
   1239 bool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
   1240     const GrVkImageInfo* backend = reinterpret_cast<const GrVkImageInfo*>(id);
   1241 
   1242     if (backend && backend->fImage && backend->fAlloc.fMemory) {
   1243         VkMemoryRequirements req;
   1244         memset(&req, 0, sizeof(req));
   1245         GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
   1246                                                                    backend->fImage,
   1247                                                                    &req));
   1248         // TODO: find a better check
   1249         // This will probably fail with a different driver
   1250         return (req.size > 0) && (req.size <= 8192 * 8192);
   1251     }
   1252 
   1253     return false;
   1254 }
   1255 
   1256 void GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
   1257     GrVkImageInfo* backend = reinterpret_cast<GrVkImageInfo*>(id);
   1258     if (backend) {
   1259         if (!abandon) {
   1260             // something in the command buffer may still be using this, so force submit
   1261             this->submitCommandBuffer(kForce_SyncQueue);
   1262             GrVkImage::DestroyImageInfo(this, backend);
   1263         }
   1264         delete backend;
   1265     }
   1266 }
   1267 
   1268 ////////////////////////////////////////////////////////////////////////////////
   1269 
   1270 void GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
   1271                                VkPipelineStageFlags dstStageMask,
   1272                                bool byRegion,
   1273                                VkMemoryBarrier* barrier) const {
   1274     SkASSERT(fCurrentCmdBuffer);
   1275     fCurrentCmdBuffer->pipelineBarrier(this,
   1276                                        srcStageMask,
   1277                                        dstStageMask,
   1278                                        byRegion,
   1279                                        GrVkCommandBuffer::kMemory_BarrierType,
   1280                                        barrier);
   1281 }
   1282 
   1283 void GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
   1284                                      VkPipelineStageFlags dstStageMask,
   1285                                      bool byRegion,
   1286                                      VkBufferMemoryBarrier* barrier) const {
   1287     SkASSERT(fCurrentCmdBuffer);
   1288     fCurrentCmdBuffer->pipelineBarrier(this,
   1289                                        srcStageMask,
   1290                                        dstStageMask,
   1291                                        byRegion,
   1292                                        GrVkCommandBuffer::kBufferMemory_BarrierType,
   1293                                        barrier);
   1294 }
   1295 
   1296 void GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
   1297                                     VkPipelineStageFlags dstStageMask,
   1298                                     bool byRegion,
   1299                                     VkImageMemoryBarrier* barrier) const {
   1300     SkASSERT(fCurrentCmdBuffer);
   1301     fCurrentCmdBuffer->pipelineBarrier(this,
   1302                                        srcStageMask,
   1303                                        dstStageMask,
   1304                                        byRegion,
   1305                                        GrVkCommandBuffer::kImageMemory_BarrierType,
   1306                                        barrier);
   1307 }
   1308 
   1309 void GrVkGpu::finishOpList() {
   1310     // Submit the current command buffer to the Queue
   1311     this->submitCommandBuffer(kSkip_SyncQueue);
   1312 }
   1313 
   1314 void GrVkGpu::clearStencil(GrRenderTarget* target) {
   1315     if (nullptr == target) {
   1316         return;
   1317     }
   1318     GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
   1319     GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
   1320 
   1321 
   1322     VkClearDepthStencilValue vkStencilColor;
   1323     memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
   1324 
   1325     vkStencil->setImageLayout(this,
   1326                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
   1327                               VK_ACCESS_TRANSFER_WRITE_BIT,
   1328                               VK_PIPELINE_STAGE_TRANSFER_BIT,
   1329                               false);
   1330 
   1331     VkImageSubresourceRange subRange;
   1332     memset(&subRange, 0, sizeof(VkImageSubresourceRange));
   1333     subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
   1334     subRange.baseMipLevel = 0;
   1335     subRange.levelCount = 1;
   1336     subRange.baseArrayLayer = 0;
   1337     subRange.layerCount = 1;
   1338 
   1339     // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
   1340     // draw. Thus we should look into using the load op functions on the render pass to clear out
   1341     // the stencil there.
   1342     fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
   1343 }
   1344 
   1345 inline bool can_copy_image(const GrSurface* dst,
   1346                            const GrSurface* src,
   1347                            const GrVkGpu* gpu) {
   1348     const GrRenderTarget* dstRT = dst->asRenderTarget();
   1349     const GrRenderTarget* srcRT = src->asRenderTarget();
   1350     if (dstRT && srcRT) {
   1351         if (srcRT->numColorSamples() != dstRT->numColorSamples()) {
   1352             return false;
   1353         }
   1354     } else if (dstRT) {
   1355         if (dstRT->numColorSamples() > 1) {
   1356             return false;
   1357         }
   1358     } else if (srcRT) {
   1359         if (srcRT->numColorSamples() > 1) {
   1360             return false;
   1361         }
   1362     }
   1363 
   1364     // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
   1365     // as image usage flags.
   1366     if (src->origin() == dst->origin() &&
   1367         GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) {
   1368         return true;
   1369     }
   1370 
   1371     return false;
   1372 }
   1373 
   1374 void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
   1375                                      GrSurface* src,
   1376                                      GrVkImage* dstImage,
   1377                                      GrVkImage* srcImage,
   1378                                      const SkIRect& srcRect,
   1379                                      const SkIPoint& dstPoint) {
   1380     SkASSERT(can_copy_image(dst, src, this));
   1381 
   1382     // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
   1383     // the cache is flushed since it is only being written to.
   1384     dstImage->setImageLayout(this,
   1385                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
   1386                              VK_ACCESS_TRANSFER_WRITE_BIT,
   1387                              VK_PIPELINE_STAGE_TRANSFER_BIT,
   1388                              false);
   1389 
   1390     srcImage->setImageLayout(this,
   1391                              VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1392                              VK_ACCESS_TRANSFER_READ_BIT,
   1393                              VK_PIPELINE_STAGE_TRANSFER_BIT,
   1394                              false);
   1395 
   1396     // Flip rect if necessary
   1397     SkIRect srcVkRect = srcRect;
   1398     int32_t dstY = dstPoint.fY;
   1399 
   1400     if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
   1401         SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
   1402         srcVkRect.fTop = src->height() - srcRect.fBottom;
   1403         srcVkRect.fBottom =  src->height() - srcRect.fTop;
   1404         dstY = dst->height() - dstPoint.fY - srcVkRect.height();
   1405     }
   1406 
   1407     VkImageCopy copyRegion;
   1408     memset(&copyRegion, 0, sizeof(VkImageCopy));
   1409     copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
   1410     copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
   1411     copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
   1412     copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
   1413     copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
   1414 
   1415     fCurrentCmdBuffer->copyImage(this,
   1416                                  srcImage,
   1417                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1418                                  dstImage,
   1419                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
   1420                                  1,
   1421                                  &copyRegion);
   1422 
   1423     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
   1424                                         srcRect.width(), srcRect.height());
   1425     this->didWriteToSurface(dst, &dstRect);
   1426 }
   1427 
   1428 inline bool can_copy_as_blit(const GrSurface* dst,
   1429                              const GrSurface* src,
   1430                              const GrVkImage* dstImage,
   1431                              const GrVkImage* srcImage,
   1432                              const GrVkGpu* gpu) {
   1433     // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
   1434     // as image usage flags.
   1435     const GrVkCaps& caps = gpu->vkCaps();
   1436     if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) ||
   1437         !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) {
   1438         return false;
   1439     }
   1440 
   1441     // We cannot blit images that are multisampled. Will need to figure out if we can blit the
   1442     // resolved msaa though.
   1443     if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
   1444         (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
   1445         return false;
   1446     }
   1447 
   1448     return true;
   1449 }
   1450 
   1451 void GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
   1452                                 GrSurface* src,
   1453                                 GrVkImage* dstImage,
   1454                                 GrVkImage* srcImage,
   1455                                 const SkIRect& srcRect,
   1456                                 const SkIPoint& dstPoint) {
   1457     SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this));
   1458 
   1459     dstImage->setImageLayout(this,
   1460                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
   1461                              VK_ACCESS_TRANSFER_WRITE_BIT,
   1462                              VK_PIPELINE_STAGE_TRANSFER_BIT,
   1463                              false);
   1464 
   1465     srcImage->setImageLayout(this,
   1466                              VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1467                              VK_ACCESS_TRANSFER_READ_BIT,
   1468                              VK_PIPELINE_STAGE_TRANSFER_BIT,
   1469                              false);
   1470 
   1471     // Flip rect if necessary
   1472     SkIRect srcVkRect;
   1473     srcVkRect.fLeft = srcRect.fLeft;
   1474     srcVkRect.fRight = srcRect.fRight;
   1475     SkIRect dstRect;
   1476     dstRect.fLeft = dstPoint.fX;
   1477     dstRect.fRight = dstPoint.fX + srcRect.width();
   1478 
   1479     if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
   1480         srcVkRect.fTop = src->height() - srcRect.fBottom;
   1481         srcVkRect.fBottom = src->height() - srcRect.fTop;
   1482     } else {
   1483         srcVkRect.fTop = srcRect.fTop;
   1484         srcVkRect.fBottom = srcRect.fBottom;
   1485     }
   1486 
   1487     if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
   1488         dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
   1489     } else {
   1490         dstRect.fTop = dstPoint.fY;
   1491     }
   1492     dstRect.fBottom = dstRect.fTop + srcVkRect.height();
   1493 
   1494     // If we have different origins, we need to flip the top and bottom of the dst rect so that we
   1495     // get the correct origintation of the copied data.
   1496     if (src->origin() != dst->origin()) {
   1497         SkTSwap(dstRect.fTop, dstRect.fBottom);
   1498     }
   1499 
   1500     VkImageBlit blitRegion;
   1501     memset(&blitRegion, 0, sizeof(VkImageBlit));
   1502     blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
   1503     blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
   1504     blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 1 };
   1505     blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
   1506     blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
   1507     blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 1 };
   1508 
   1509     fCurrentCmdBuffer->blitImage(this,
   1510                                  *srcImage,
   1511                                  *dstImage,
   1512                                  1,
   1513                                  &blitRegion,
   1514                                  VK_FILTER_NEAREST); // We never scale so any filter works here
   1515 
   1516     this->didWriteToSurface(dst, &dstRect);
   1517 }
   1518 
   1519 inline bool can_copy_as_resolve(const GrSurface* dst,
   1520                                 const GrSurface* src,
   1521                                 const GrVkGpu* gpu) {
   1522     // Our src must be a multisampled render target
   1523     if (!src->asRenderTarget() || src->asRenderTarget()->numColorSamples() <= 1) {
   1524         return false;
   1525     }
   1526 
   1527     // The dst must be a render target but not multisampled
   1528     if (!dst->asRenderTarget() || dst->asRenderTarget()->numColorSamples() > 1) {
   1529         return false;
   1530     }
   1531 
   1532     // Surfaces must have the same origin.
   1533     if (src->origin() != dst->origin()) {
   1534         return false;
   1535     }
   1536 
   1537     return true;
   1538 }
   1539 
   1540 void GrVkGpu::copySurfaceAsResolve(GrSurface* dst,
   1541                                    GrSurface* src,
   1542                                    const SkIRect& srcRect,
   1543                                    const SkIPoint& dstPoint) {
   1544     GrVkRenderTarget* dstRT = static_cast<GrVkRenderTarget*>(dst->asRenderTarget());
   1545     GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
   1546     SkASSERT(dstRT && dstRT->numColorSamples() <= 1);
   1547     this->resolveImage(dstRT, srcRT, srcRect, dstPoint);
   1548 }
   1549 
   1550 bool GrVkGpu::onCopySurface(GrSurface* dst,
   1551                             GrSurface* src,
   1552                             const SkIRect& srcRect,
   1553                             const SkIPoint& dstPoint) {
   1554     if (can_copy_as_resolve(dst, src, this)) {
   1555         this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
   1556         return true;
   1557     }
   1558 
   1559     if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
   1560         this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
   1561     }
   1562 
   1563     if (fCopyManager.copySurfaceAsDraw(this, dst, src, srcRect, dstPoint)) {
   1564         return true;
   1565     }
   1566 
   1567     GrVkImage* dstImage;
   1568     GrVkImage* srcImage;
   1569     GrRenderTarget* dstRT = dst->asRenderTarget();
   1570     if (dstRT) {
   1571         GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
   1572         dstImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
   1573     } else {
   1574         SkASSERT(dst->asTexture());
   1575         dstImage = static_cast<GrVkTexture*>(dst->asTexture());
   1576     }
   1577     GrRenderTarget* srcRT = src->asRenderTarget();
   1578     if (srcRT) {
   1579         GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(srcRT);
   1580         srcImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
   1581     } else {
   1582         SkASSERT(src->asTexture());
   1583         srcImage = static_cast<GrVkTexture*>(src->asTexture());
   1584     }
   1585 
   1586     if (can_copy_image(dst, src, this)) {
   1587         this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
   1588         return true;
   1589     }
   1590 
   1591     if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) {
   1592         this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
   1593         return true;
   1594     }
   1595 
   1596     return false;
   1597 }
   1598 
   1599 void GrVkGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
   1600                                       int* effectiveSampleCnt, SamplePattern*) {
   1601     // TODO: stub.
   1602     SkASSERT(!this->caps()->sampleLocationsSupport());
   1603     *effectiveSampleCnt = rt->desc().fSampleCnt;
   1604 }
   1605 
   1606 bool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
   1607                                   GrPixelConfig readConfig, DrawPreference* drawPreference,
   1608                                   ReadPixelTempDrawInfo* tempDrawInfo) {
   1609     // These settings we will always want if a temp draw is performed.
   1610     tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
   1611     tempDrawInfo->fTempSurfaceDesc.fWidth = width;
   1612     tempDrawInfo->fTempSurfaceDesc.fHeight = height;
   1613     tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
   1614     tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
   1615     tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox;
   1616 
   1617     // For now assume no swizzling, we may change that below.
   1618     tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
   1619 
   1620     // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read
   1621     // from will be srcConfig and we will read readConfig pixels from it.
   1622     // Not that if we require a draw and return a non-renderable format for the temp surface the
   1623     // base class will fail for us.
   1624     tempDrawInfo->fTempSurfaceDesc.fConfig = srcSurface->config();
   1625     tempDrawInfo->fReadConfig = readConfig;
   1626 
   1627     if (srcSurface->config() == readConfig) {
   1628         return true;
   1629     }
   1630 
   1631     if (this->vkCaps().isConfigRenderable(readConfig, srcSurface->desc().fSampleCnt > 1)) {
   1632         ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
   1633         tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
   1634         tempDrawInfo->fReadConfig = readConfig;
   1635         return true;
   1636     }
   1637 
   1638     return false;
   1639 }
   1640 
   1641 bool GrVkGpu::onReadPixels(GrSurface* surface,
   1642                            int left, int top, int width, int height,
   1643                            GrPixelConfig config,
   1644                            void* buffer,
   1645                            size_t rowBytes) {
   1646     VkFormat pixelFormat;
   1647     if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
   1648         return false;
   1649     }
   1650 
   1651     GrVkImage* image = nullptr;
   1652     GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
   1653     if (rt) {
   1654         // resolve the render target if necessary
   1655         switch (rt->getResolveType()) {
   1656             case GrVkRenderTarget::kCantResolve_ResolveType:
   1657                 return false;
   1658             case GrVkRenderTarget::kAutoResolves_ResolveType:
   1659                 break;
   1660             case GrVkRenderTarget::kCanResolve_ResolveType:
   1661                 this->internalResolveRenderTarget(rt, false);
   1662                 break;
   1663             default:
   1664                 SkFAIL("Unknown resolve type");
   1665         }
   1666         image = rt;
   1667     } else {
   1668         image = static_cast<GrVkTexture*>(surface->asTexture());
   1669     }
   1670 
   1671     if (!image) {
   1672         return false;
   1673     }
   1674 
   1675     // Change layout of our target so it can be used as copy
   1676     image->setImageLayout(this,
   1677                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1678                           VK_ACCESS_TRANSFER_READ_BIT,
   1679                           VK_PIPELINE_STAGE_TRANSFER_BIT,
   1680                           false);
   1681 
   1682     size_t bpp = GrBytesPerPixel(config);
   1683     size_t tightRowBytes = bpp * width;
   1684     bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
   1685 
   1686     VkBufferImageCopy region;
   1687     memset(&region, 0, sizeof(VkBufferImageCopy));
   1688 
   1689     bool copyFromOrigin = this->vkCaps().mustDoCopiesFromOrigin();
   1690     if (copyFromOrigin) {
   1691         region.imageOffset = { 0, 0, 0 };
   1692         region.imageExtent = { (uint32_t)(left + width),
   1693                                (uint32_t)(flipY ? surface->height() - top : top + height),
   1694                                1
   1695                              };
   1696     } else {
   1697         VkOffset3D offset = {
   1698             left,
   1699             flipY ? surface->height() - top - height : top,
   1700             0
   1701         };
   1702         region.imageOffset = offset;
   1703         region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
   1704     }
   1705 
   1706     size_t transBufferRowBytes = bpp * region.imageExtent.width;
   1707     GrVkTransferBuffer* transferBuffer =
   1708             static_cast<GrVkTransferBuffer*>(this->createBuffer(transBufferRowBytes * height,
   1709                                                                 kXferGpuToCpu_GrBufferType,
   1710                                                                 kStream_GrAccessPattern));
   1711 
   1712     // Copy the image to a buffer so we can map it to cpu memory
   1713     region.bufferOffset = transferBuffer->offset();
   1714     region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below.
   1715     region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
   1716     region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
   1717 
   1718     fCurrentCmdBuffer->copyImageToBuffer(this,
   1719                                          image,
   1720                                          VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
   1721                                          transferBuffer,
   1722                                          1,
   1723                                          &region);
   1724 
   1725     // make sure the copy to buffer has finished
   1726     transferBuffer->addMemoryBarrier(this,
   1727                                      VK_ACCESS_TRANSFER_WRITE_BIT,
   1728                                      VK_ACCESS_HOST_READ_BIT,
   1729                                      VK_PIPELINE_STAGE_TRANSFER_BIT,
   1730                                      VK_PIPELINE_STAGE_HOST_BIT,
   1731                                      false);
   1732 
   1733     // We need to submit the current command buffer to the Queue and make sure it finishes before
   1734     // we can copy the data out of the buffer.
   1735     this->submitCommandBuffer(kForce_SyncQueue);
   1736     GrVkMemory::InvalidateMappedAlloc(this, transferBuffer->alloc());
   1737     void* mappedMemory = transferBuffer->map();
   1738 
   1739     if (copyFromOrigin) {
   1740         uint32_t skipRows = region.imageExtent.height - height;
   1741         mappedMemory = (char*)mappedMemory + transBufferRowBytes * skipRows + bpp * left;
   1742     }
   1743 
   1744     if (flipY) {
   1745         const char* srcRow = reinterpret_cast<const char*>(mappedMemory);
   1746         char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes;
   1747         for (int y = 0; y < height; y++) {
   1748             memcpy(dstRow, srcRow, tightRowBytes);
   1749             srcRow += transBufferRowBytes;
   1750             dstRow -= rowBytes;
   1751         }
   1752     } else {
   1753         SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, height);
   1754     }
   1755 
   1756     transferBuffer->unmap();
   1757     transferBuffer->unref();
   1758     return true;
   1759 }
   1760 
   1761 // The RenderArea bounds we pass into BeginRenderPass must have a start x value that is a multiple
   1762 // of the granularity. The width must also be a multiple of the granularity or eaqual to the width
   1763 // the the entire attachment. Similar requirements for the y and height components.
   1764 void adjust_bounds_to_granularity(SkIRect* dstBounds, const SkIRect& srcBounds,
   1765                                   const VkExtent2D& granularity, int maxWidth, int maxHeight) {
   1766     // Adjust Width
   1767     if ((0 != granularity.width && 1 != granularity.width)) {
   1768         // Start with the right side of rect so we know if we end up going pass the maxWidth.
   1769         int rightAdj = srcBounds.fRight % granularity.width;
   1770         if (rightAdj != 0) {
   1771             rightAdj = granularity.width - rightAdj;
   1772         }
   1773         dstBounds->fRight = srcBounds.fRight + rightAdj;
   1774         if (dstBounds->fRight > maxWidth) {
   1775             dstBounds->fRight = maxWidth;
   1776             dstBounds->fLeft = 0;
   1777         } else {
   1778             dstBounds->fLeft = srcBounds.fLeft - srcBounds.fLeft % granularity.width;
   1779         }
   1780     } else {
   1781         dstBounds->fLeft = srcBounds.fLeft;
   1782         dstBounds->fRight = srcBounds.fRight;
   1783     }
   1784 
   1785     // Adjust height
   1786     if ((0 != granularity.height && 1 != granularity.height)) {
   1787         // Start with the bottom side of rect so we know if we end up going pass the maxHeight.
   1788         int bottomAdj = srcBounds.fBottom % granularity.height;
   1789         if (bottomAdj != 0) {
   1790             bottomAdj = granularity.height - bottomAdj;
   1791         }
   1792         dstBounds->fBottom = srcBounds.fBottom + bottomAdj;
   1793         if (dstBounds->fBottom > maxHeight) {
   1794             dstBounds->fBottom = maxHeight;
   1795             dstBounds->fTop = 0;
   1796         } else {
   1797             dstBounds->fTop = srcBounds.fTop - srcBounds.fTop % granularity.height;
   1798         }
   1799     } else {
   1800         dstBounds->fTop = srcBounds.fTop;
   1801         dstBounds->fBottom = srcBounds.fBottom;
   1802     }
   1803 }
   1804 
   1805 void GrVkGpu::submitSecondaryCommandBuffer(const SkTArray<GrVkSecondaryCommandBuffer*>& buffers,
   1806                                            const GrVkRenderPass* renderPass,
   1807                                            const VkClearValue* colorClear,
   1808                                            GrVkRenderTarget* target,
   1809                                            const SkIRect& bounds) {
   1810     const SkIRect* pBounds = &bounds;
   1811     SkIRect flippedBounds;
   1812     if (kBottomLeft_GrSurfaceOrigin == target->origin()) {
   1813         flippedBounds = bounds;
   1814         flippedBounds.fTop = target->height() - bounds.fBottom;
   1815         flippedBounds.fBottom = target->height() - bounds.fTop;
   1816         pBounds = &flippedBounds;
   1817     }
   1818 
   1819     // The bounds we use for the render pass should be of the granularity supported
   1820     // by the device.
   1821     const VkExtent2D& granularity = renderPass->granularity();
   1822     SkIRect adjustedBounds;
   1823     if ((0 != granularity.width && 1 != granularity.width) ||
   1824         (0 != granularity.height && 1 != granularity.height)) {
   1825         adjust_bounds_to_granularity(&adjustedBounds, *pBounds, granularity,
   1826                                      target->width(), target->height());
   1827         pBounds = &adjustedBounds;
   1828     }
   1829 
   1830     fCurrentCmdBuffer->beginRenderPass(this, renderPass, colorClear, *target, *pBounds, true);
   1831     for (int i = 0; i < buffers.count(); ++i) {
   1832         fCurrentCmdBuffer->executeCommands(this, buffers[i]);
   1833     }
   1834     fCurrentCmdBuffer->endRenderPass(this);
   1835 
   1836     this->didWriteToSurface(target, &bounds);
   1837 }
   1838 
   1839 GrFence SK_WARN_UNUSED_RESULT GrVkGpu::insertFence() {
   1840     VkFenceCreateInfo createInfo;
   1841     memset(&createInfo, 0, sizeof(VkFenceCreateInfo));
   1842     createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
   1843     createInfo.pNext = nullptr;
   1844     createInfo.flags = 0;
   1845     VkFence fence = VK_NULL_HANDLE;
   1846 
   1847     VK_CALL_ERRCHECK(CreateFence(this->device(), &createInfo, nullptr, &fence));
   1848     VK_CALL(QueueSubmit(this->queue(), 0, nullptr, fence));
   1849 
   1850     GR_STATIC_ASSERT(sizeof(GrFence) >= sizeof(VkFence));
   1851     return (GrFence)fence;
   1852 }
   1853 
   1854 bool GrVkGpu::waitFence(GrFence fence, uint64_t timeout) {
   1855     SkASSERT(VK_NULL_HANDLE != (VkFence)fence);
   1856 
   1857     VkResult result = VK_CALL(WaitForFences(this->device(), 1, (VkFence*)&fence, VK_TRUE, timeout));
   1858     return (VK_SUCCESS == result);
   1859 }
   1860 
   1861 void GrVkGpu::deleteFence(GrFence fence) const {
   1862     VK_CALL(DestroyFence(this->device(), (VkFence)fence, nullptr));
   1863 }
   1864 
   1865 sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrVkGpu::makeSemaphore() {
   1866     return GrVkSemaphore::Make(this);
   1867 }
   1868 
   1869 void GrVkGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore) {
   1870     GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get());
   1871 
   1872     this->submitCommandBuffer(kSkip_SyncQueue, vkSem->getResource());
   1873 }
   1874 
   1875 void GrVkGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
   1876     GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get());
   1877 
   1878     const GrVkSemaphore::Resource* resource = vkSem->getResource();
   1879     resource->ref();
   1880     fSemaphoresToWaitOn.push_back(resource);
   1881 }
   1882 
   1883 void GrVkGpu::flush() {
   1884     // We submit the command buffer to the queue whenever Ganesh is flushed, so nothing is needed
   1885 }
   1886