| Index: src/gpu/vk/GrVkGpu.cpp | 
| diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp | 
| index 05aa1de152f160518d01fc7e3dc87115c8180e33..33437415a9146f9d373883428d1e8d4fb114043c 100644 | 
| --- a/src/gpu/vk/GrVkGpu.cpp | 
| +++ b/src/gpu/vk/GrVkGpu.cpp | 
| @@ -174,13 +174,12 @@ GrVkGpu::~GrVkGpu() { | 
|  | 
| /////////////////////////////////////////////////////////////////////////////// | 
|  | 
| -GrGpuCommandBuffer* GrVkGpu::createCommandBuffer(const GrRenderTarget& target, | 
| -                                                 GrGpuCommandBuffer::LoadAndStoreOp colorOp, | 
| -                                                 GrColor colorClear, | 
| -                                                 GrGpuCommandBuffer::LoadAndStoreOp stencilOp, | 
| -                                                 GrColor stencilClear) { | 
| -    const GrVkRenderTarget& vkRT = static_cast<const GrVkRenderTarget&>(target); | 
| -    return new GrVkGpuCommandBuffer(this, vkRT, colorOp, colorClear, stencilOp, stencilClear); | 
| +GrGpuCommandBuffer* GrVkGpu::createCommandBuffer( | 
| +            GrRenderTarget* target, | 
| +            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo, | 
| +            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) { | 
| +    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); | 
| +    return new GrVkGpuCommandBuffer(this, vkRT, colorInfo, stencilInfo); | 
| } | 
|  | 
| void GrVkGpu::submitCommandBuffer(SyncQueue sync) { | 
| @@ -819,31 +818,6 @@ void GrVkGpu::generateMipmap(GrVkTexture* tex) const { | 
| oldResource->unref(this); | 
| } | 
|  | 
| - | 
| -//////////////////////////////////////////////////////////////////////////////// | 
| - | 
| -void GrVkGpu::bindGeometry(const GrPrimitiveProcessor& primProc, | 
| -                           const GrNonInstancedMesh& mesh) { | 
| -    // There is no need to put any memory barriers to make sure host writes have finished here. | 
| -    // When a command buffer is submitted to a queue, there is an implicit memory barrier that | 
| -    // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of | 
| -    // an active RenderPass. | 
| -    GrVkVertexBuffer* vbuf; | 
| -    vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer(); | 
| -    SkASSERT(vbuf); | 
| -    SkASSERT(!vbuf->isMapped()); | 
| - | 
| -    fCurrentCmdBuffer->bindVertexBuffer(this, vbuf); | 
| - | 
| -    if (mesh.isIndexed()) { | 
| -        GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer(); | 
| -        SkASSERT(ibuf); | 
| -        SkASSERT(!ibuf->isMapped()); | 
| - | 
| -        fCurrentCmdBuffer->bindIndexBuffer(this, ibuf); | 
| -    } | 
| -} | 
| - | 
| //////////////////////////////////////////////////////////////////////////////// | 
|  | 
| GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt, | 
| @@ -1087,157 +1061,6 @@ void GrVkGpu::clearStencil(GrRenderTarget* target) { | 
| fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange); | 
| } | 
|  | 
| -void GrVkGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) { | 
| -    SkASSERT(target); | 
| - | 
| -    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); | 
| -    GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment(); | 
| -    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)sb; | 
| - | 
| -    // this should only be called internally when we know we have a | 
| -    // stencil buffer. | 
| -    SkASSERT(sb); | 
| -    int stencilBitCount = sb->bits(); | 
| - | 
| -    // The contract with the callers does not guarantee that we preserve all bits in the stencil | 
| -    // during this clear. Thus we will clear the entire stencil to the desired value. | 
| - | 
| -    VkClearDepthStencilValue vkStencilColor; | 
| -    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); | 
| -    if (insideClip) { | 
| -        vkStencilColor.stencil = (1 << (stencilBitCount - 1)); | 
| -    } else { | 
| -        vkStencilColor.stencil = 0; | 
| -    } | 
| - | 
| -    vkStencil->setImageLayout(this, | 
| -                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, | 
| -                              VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, | 
| -                              VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | 
| -                              false); | 
| - | 
| -    // Change layout of our render target so it can be used as the color attachment. This is what | 
| -    // the render pass expects when it begins. | 
| -    vkRT->setImageLayout(this, | 
| -                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, | 
| -                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | 
| -                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | 
| -                         false); | 
| - | 
| -    VkClearRect clearRect; | 
| -    // Flip rect if necessary | 
| -    SkIRect vkRect = rect; | 
| - | 
| -    if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) { | 
| -        vkRect.fTop = vkRT->height() - rect.fBottom; | 
| -        vkRect.fBottom = vkRT->height() - rect.fTop; | 
| -    } | 
| - | 
| -    clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; | 
| -    clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() }; | 
| - | 
| -    clearRect.baseArrayLayer = 0; | 
| -    clearRect.layerCount = 1; | 
| - | 
| -    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); | 
| -    SkASSERT(renderPass); | 
| -    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); | 
| - | 
| -    uint32_t stencilIndex; | 
| -    SkAssertResult(renderPass->stencilAttachmentIndex(&stencilIndex)); | 
| - | 
| -    VkClearAttachment attachment; | 
| -    attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; | 
| -    attachment.colorAttachment = 0; // this value shouldn't matter | 
| -    attachment.clearValue.depthStencil = vkStencilColor; | 
| - | 
| -    fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect); | 
| -    fCurrentCmdBuffer->endRenderPass(this); | 
| - | 
| -    return; | 
| -} | 
| - | 
| -void GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) { | 
| -    // parent class should never let us get here with no RT | 
| -    SkASSERT(target); | 
| - | 
| -    VkClearColorValue vkColor; | 
| -    GrColorToRGBAFloat(color, vkColor.float32); | 
| - | 
| -    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); | 
| - | 
| -    if (rect.width() != target->width() || rect.height() != target->height()) { | 
| -        vkRT->setImageLayout(this, | 
| -                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, | 
| -                             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | 
| -                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | 
| -                             false); | 
| - | 
| -        // If we are using a stencil attachment we also need to change its layout to what the render | 
| -        // pass is expecting. | 
| -        if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment()) { | 
| -            GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; | 
| -            vkStencil->setImageLayout(this, | 
| -                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, | 
| -                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | 
| -                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, | 
| -                                      VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | 
| -                                      false); | 
| -        } | 
| - | 
| -        VkClearRect clearRect; | 
| -        // Flip rect if necessary | 
| -        SkIRect vkRect = rect; | 
| -        if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) { | 
| -            vkRect.fTop = vkRT->height() - rect.fBottom; | 
| -            vkRect.fBottom = vkRT->height() - rect.fTop; | 
| -        } | 
| -        clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; | 
| -        clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() }; | 
| -        clearRect.baseArrayLayer = 0; | 
| -        clearRect.layerCount = 1; | 
| - | 
| -        const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); | 
| -        SkASSERT(renderPass); | 
| -        fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); | 
| - | 
| -        uint32_t colorIndex; | 
| -        SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex)); | 
| - | 
| -        VkClearAttachment attachment; | 
| -        attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | 
| -        attachment.colorAttachment = colorIndex; | 
| -        attachment.clearValue.color = vkColor; | 
| - | 
| -        fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect); | 
| -        fCurrentCmdBuffer->endRenderPass(this); | 
| -        return; | 
| -    } | 
| - | 
| -    vkRT->setImageLayout(this, | 
| -                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | 
| -                         VK_ACCESS_TRANSFER_WRITE_BIT, | 
| -                         VK_PIPELINE_STAGE_TRANSFER_BIT, | 
| -                         false); | 
| - | 
| -    VkImageSubresourceRange subRange; | 
| -    memset(&subRange, 0, sizeof(VkImageSubresourceRange)); | 
| -    subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | 
| -    subRange.baseMipLevel = 0; | 
| -    subRange.levelCount = 1; | 
| -    subRange.baseArrayLayer = 0; | 
| -    subRange.layerCount = 1; | 
| - | 
| -    // In the future we may not actually be doing this type of clear at all. If we are inside a | 
| -    // render pass or doing a non full clear then we will use CmdClearColorAttachment. The more | 
| -    // common use case will be clearing an attachment at the start of a render pass, in which case | 
| -    // we will use the clear load ops. | 
| -    fCurrentCmdBuffer->clearColorImage(this, | 
| -                                       vkRT, | 
| -                                       &vkColor, | 
| -                                       1, &subRange); | 
| -} | 
| - | 
| inline bool can_copy_image(const GrSurface* dst, | 
| const GrSurface* src, | 
| const GrVkGpu* gpu) { | 
| @@ -1587,132 +1410,16 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, | 
| return true; | 
| } | 
|  | 
| -void GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buffer) { | 
| +void GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buffer, | 
| +                                           const GrVkRenderPass* renderPass, | 
| +                                           const VkClearValue* colorClear, | 
| +                                           GrVkRenderTarget* target, | 
| +                                           const SkIRect& bounds) { | 
| +    // Currently it is fine for us to always pass in 1 for the clear count even if no attachment | 
| +    // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the color attachment | 
| +    // which is always at the first attachment. | 
| +    fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target, bounds, true); | 
| fCurrentCmdBuffer->executeCommands(this, buffer); | 
| -} | 
| - | 
| -sk_sp<GrVkPipelineState> GrVkGpu::prepareDrawState(const GrPipeline& pipeline, | 
| -                                                   const GrPrimitiveProcessor& primProc, | 
| -                                                   GrPrimitiveType primitiveType, | 
| -                                                   const GrVkRenderPass& renderPass) { | 
| -    sk_sp<GrVkPipelineState> pipelineState = | 
| -        fResourceProvider.findOrCreateCompatiblePipelineState(pipeline, | 
| -                                                              primProc, | 
| -                                                              primitiveType, | 
| -                                                              renderPass); | 
| -    if (!pipelineState) { | 
| -        return pipelineState; | 
| -    } | 
| - | 
| -    pipelineState->setData(this, primProc, pipeline); | 
| - | 
| -    pipelineState->bind(this, fCurrentCmdBuffer); | 
| - | 
| -    GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline); | 
| - | 
| -    return pipelineState; | 
| -} | 
| - | 
| -void GrVkGpu::onDraw(const GrPipeline& pipeline, | 
| -                     const GrPrimitiveProcessor& primProc, | 
| -                     const GrMesh* meshes, | 
| -                     int meshCount) { | 
| -    if (!meshCount) { | 
| -        return; | 
| -    } | 
| -    GrRenderTarget* rt = pipeline.getRenderTarget(); | 
| -    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); | 
| -    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); | 
| -    SkASSERT(renderPass); | 
| - | 
| -    GrPrimitiveType primitiveType = meshes[0].primitiveType(); | 
| -    sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline, | 
| -                                                                    primProc, | 
| -                                                                    primitiveType, | 
| -                                                                    *renderPass); | 
| -    if (!pipelineState) { | 
| -        return; | 
| -    } | 
| - | 
| -    // Change layout of our render target so it can be used as the color attachment | 
| -    vkRT->setImageLayout(this, | 
| -                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, | 
| -                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | 
| -                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | 
| -                         false); | 
| - | 
| -    // If we are using a stencil attachment we also need to update its layout | 
| -    if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment()) { | 
| -        GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; | 
| -        vkStencil->setImageLayout(this, | 
| -                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, | 
| -                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | 
| -                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, | 
| -                                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | 
| -                                  false); | 
| -    } | 
| - | 
| -    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); | 
| - | 
| -    for (int i = 0; i < meshCount; ++i) { | 
| -        const GrMesh& mesh = meshes[i]; | 
| -        GrMesh::Iterator iter; | 
| -        const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh); | 
| -        do { | 
| -            if (nonIdxMesh->primitiveType() != primitiveType) { | 
| -                // Technically we don't have to call this here (since there is a safety check in | 
| -                // pipelineState:setData but this will allow for quicker freeing of resources if the | 
| -                // pipelineState sits in a cache for a while. | 
| -                pipelineState->freeTempResources(this); | 
| -                SkDEBUGCODE(pipelineState = nullptr); | 
| -                primitiveType = nonIdxMesh->primitiveType(); | 
| -                pipelineState = this->prepareDrawState(pipeline, | 
| -                                                       primProc, | 
| -                                                       primitiveType, | 
| -                                                       *renderPass); | 
| -                if (!pipelineState) { | 
| -                    return; | 
| -                } | 
| -            } | 
| -            SkASSERT(pipelineState); | 
| -            this->bindGeometry(primProc, *nonIdxMesh); | 
| - | 
| -            if (nonIdxMesh->isIndexed()) { | 
| -                fCurrentCmdBuffer->drawIndexed(this, | 
| -                                               nonIdxMesh->indexCount(), | 
| -                                               1, | 
| -                                               nonIdxMesh->startIndex(), | 
| -                                               nonIdxMesh->startVertex(), | 
| -                                               0); | 
| -            } else { | 
| -                fCurrentCmdBuffer->draw(this, | 
| -                                        nonIdxMesh->vertexCount(), | 
| -                                        1, | 
| -                                        nonIdxMesh->startVertex(), | 
| -                                        0); | 
| -            } | 
| - | 
| -            fStats.incNumDraws(); | 
| -        } while ((nonIdxMesh = iter.next())); | 
| -    } | 
| - | 
| fCurrentCmdBuffer->endRenderPass(this); | 
| - | 
| -    // Technically we don't have to call this here (since there is a safety check in | 
| -    // pipelineState:setData but this will allow for quicker freeing of resources if the | 
| -    // pipelineState sits in a cache for a while. | 
| -    pipelineState->freeTempResources(this); | 
| - | 
| -#if SWAP_PER_DRAW | 
| -    glFlush(); | 
| -#if defined(SK_BUILD_FOR_MAC) | 
| -    aglSwapBuffers(aglGetCurrentContext()); | 
| -    int set_a_break_pt_here = 9; | 
| -    aglSwapBuffers(aglGetCurrentContext()); | 
| -#elif defined(SK_BUILD_FOR_WIN32) | 
| -    SwapBuf(); | 
| -    int set_a_break_pt_here = 9; | 
| -    SwapBuf(); | 
| -#endif | 
| -#endif | 
| } | 
| + | 
|  |