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