| Index: src/gpu/vk/GrVkPipeline.cpp | 
| diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp | 
| index c0197cd7352352018227b5e21875b811d010badb..aef4875ae4715187339c67b836db8974c5ab6fc0 100644 | 
| --- a/src/gpu/vk/GrVkPipeline.cpp | 
| +++ b/src/gpu/vk/GrVkPipeline.cpp | 
| @@ -9,7 +9,7 @@ | 
|  | 
| #include "GrGeometryProcessor.h" | 
| #include "GrPipeline.h" | 
| - | 
| +#include "GrVkCommandBuffer.h" | 
| #include "GrVkGpu.h" | 
| #include "GrVkProgramDesc.h" | 
| #include "GrVkRenderTarget.h" | 
| @@ -188,52 +188,18 @@ void setup_depth_stencil_state(const GrVkGpu* gpu, | 
| void setup_viewport_scissor_state(const GrVkGpu* gpu, | 
| const GrPipeline& pipeline, | 
| const GrVkRenderTarget* vkRT, | 
| -                                  VkPipelineViewportStateCreateInfo* viewportInfo, | 
| -                                  VkViewport* viewport, | 
| -                                  VkRect2D* scissor) { | 
| +                                  VkPipelineViewportStateCreateInfo* viewportInfo) { | 
| memset(viewportInfo, 0, sizeof(VkPipelineViewportStateCreateInfo)); | 
| viewportInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; | 
| viewportInfo->pNext = nullptr; | 
| viewportInfo->flags = 0; | 
|  | 
| -    viewport->x = 0.0f; | 
| -    viewport->y = 0.0f; | 
| -    viewport->width = SkIntToScalar(vkRT->width()); | 
| -    viewport->height = SkIntToScalar(vkRT->height()); | 
| -    viewport->minDepth = 0.0f; | 
| -    viewport->maxDepth = 1.0f; | 
| viewportInfo->viewportCount = 1; | 
| -    viewportInfo->pViewports = viewport; | 
| - | 
| -    const GrScissorState& scissorState = pipeline.getScissorState(); | 
| -    if (scissorState.enabled() && | 
| -        !scissorState.rect().contains(0, 0, vkRT->width(), vkRT->height())) { | 
| -        // This all assumes the scissorState has previously been clipped to the device space render | 
| -        // target. | 
| -        scissor->offset.x = scissorState.rect().fLeft; | 
| -        scissor->extent.width = scissorState.rect().width(); | 
| -        if (kTopLeft_GrSurfaceOrigin == vkRT->origin()) { | 
| -            scissor->offset.y = scissorState.rect().fTop; | 
| -        } else { | 
| -            SkASSERT(kBottomLeft_GrSurfaceOrigin == vkRT->origin()); | 
| -            scissor->offset.y = vkRT->height() - scissorState.rect().fBottom; | 
| -        } | 
| -        scissor->extent.height = scissorState.rect().height(); | 
| - | 
| -        viewportInfo->scissorCount = 1; | 
| -        viewportInfo->pScissors = scissor; | 
| -        SkASSERT(scissor->offset.x >= 0); | 
| -        SkASSERT(scissor->offset.x + scissor->extent.width <= (uint32_t)vkRT->width()); | 
| -        SkASSERT(scissor->offset.y >= 0); | 
| -        SkASSERT(scissor->offset.y + scissor->extent.height <= (uint32_t)vkRT->height()); | 
| -    } else { | 
| -        scissor->extent.width = vkRT->width(); | 
| -        scissor->extent.height = vkRT->height(); | 
| -        scissor->offset.x = 0; | 
| -        scissor->offset.y = 0; | 
| -        viewportInfo->scissorCount = 1; | 
| -        viewportInfo->pScissors = scissor; | 
| -    } | 
| +    viewportInfo->pViewports = nullptr; // This is set dynamically | 
| + | 
| +    viewportInfo->scissorCount = 1; | 
| +    viewportInfo->pScissors = nullptr; // This is set dynamically | 
| + | 
| SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount); | 
| } | 
|  | 
| @@ -381,9 +347,7 @@ void setup_color_blend_state(const GrVkGpu* gpu, | 
| colorBlendInfo->logicOpEnable = VK_FALSE; | 
| colorBlendInfo->attachmentCount = 1; | 
| colorBlendInfo->pAttachments = attachmentState; | 
| -    if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) { | 
| -        GrColorToRGBAFloat(blendInfo.fBlendConstant, colorBlendInfo->blendConstants); | 
| -    } | 
| +    // colorBlendInfo->blendConstants is set dynamically | 
| } | 
|  | 
| VkCullModeFlags draw_face_to_vk_cull_mode(GrPipelineBuilder::DrawFace drawFace) { | 
| @@ -422,11 +386,17 @@ void setup_raster_state(const GrVkGpu* gpu, | 
|  | 
| void setup_dynamic_state(const GrVkGpu* gpu, | 
| const GrPipeline& pipeline, | 
| -                         VkPipelineDynamicStateCreateInfo* dynamicInfo) { | 
| +                         VkPipelineDynamicStateCreateInfo* dynamicInfo, | 
| +                         VkDynamicState* dynamicStates) { | 
| memset(dynamicInfo, 0, sizeof(VkPipelineDynamicStateCreateInfo)); | 
| dynamicInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; | 
| -    // TODO: mask out any state we might want to set dynamically | 
| -    dynamicInfo->dynamicStateCount = 0; | 
| +    dynamicInfo->pNext = VK_NULL_HANDLE; | 
| +    dynamicInfo->flags = 0; | 
| +    dynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT; | 
| +    dynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR; | 
| +    dynamicStates[2] = VK_DYNAMIC_STATE_BLEND_CONSTANTS; | 
| +    dynamicInfo->dynamicStateCount = 3; | 
| +    dynamicInfo->pDynamicStates = dynamicStates; | 
| } | 
|  | 
| GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline, | 
| @@ -454,9 +424,7 @@ GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline, | 
| GrRenderTarget* rt = pipeline.getRenderTarget(); | 
| GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); | 
| VkPipelineViewportStateCreateInfo viewportInfo; | 
| -    VkViewport viewport; | 
| -    VkRect2D scissor; | 
| -    setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo, &viewport, &scissor); | 
| +    setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo); | 
|  | 
| VkPipelineMultisampleStateCreateInfo multisampleInfo; | 
| setup_multisample_state(pipeline, &multisampleInfo); | 
| @@ -469,8 +437,9 @@ GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, const GrPipeline& pipeline, | 
| VkPipelineRasterizationStateCreateInfo rasterInfo; | 
| setup_raster_state(gpu, pipeline, &rasterInfo); | 
|  | 
| +    VkDynamicState dynamicStates[3]; | 
| VkPipelineDynamicStateCreateInfo dynamicInfo; | 
| -    setup_dynamic_state(gpu, pipeline, &dynamicInfo); | 
| +    setup_dynamic_state(gpu, pipeline, &dynamicInfo, dynamicStates); | 
|  | 
| VkGraphicsPipelineCreateInfo pipelineCreateInfo; | 
| memset(&pipelineCreateInfo, 0, sizeof(VkGraphicsPipelineCreateInfo)); | 
| @@ -511,3 +480,77 @@ void GrVkPipeline::freeGPUData(const GrVkGpu* gpu) const { | 
| } | 
|  | 
|  | 
| +void set_dynamic_scissor_state(GrVkGpu* gpu, | 
| +                               GrVkCommandBuffer* cmdBuffer, | 
| +                               const GrPipeline& pipeline, | 
| +                               const GrRenderTarget& target) { | 
| +    // We always use one scissor and if it is disabled we just make it the size of the RT | 
| +    const GrScissorState& scissorState = pipeline.getScissorState(); | 
| +    VkRect2D scissor; | 
| +    if (scissorState.enabled() && | 
| +        !scissorState.rect().contains(0, 0, target.width(), target.height())) { | 
| +        // This all assumes the scissorState has previously been clipped to the device space render | 
| +        // target. | 
| +        scissor.offset.x = scissorState.rect().fLeft; | 
| +        scissor.extent.width = scissorState.rect().width(); | 
| +        if (kTopLeft_GrSurfaceOrigin == target.origin()) { | 
| +            scissor.offset.y = scissorState.rect().fTop; | 
| +        } else { | 
| +            SkASSERT(kBottomLeft_GrSurfaceOrigin == target.origin()); | 
| +            scissor.offset.y = target.height() - scissorState.rect().fBottom; | 
| +        } | 
| +        scissor.extent.height = scissorState.rect().height(); | 
| + | 
| +        SkASSERT(scissor.offset.x >= 0); | 
| +        SkASSERT(scissor.offset.x + scissor.extent.width <= (uint32_t)target.width()); | 
| +        SkASSERT(scissor.offset.y >= 0); | 
| +        SkASSERT(scissor.offset.y + scissor.extent.height <= (uint32_t)target.height()); | 
| +    } else { | 
| +        scissor.extent.width = target.width(); | 
| +        scissor.extent.height = target.height(); | 
| +        scissor.offset.x = 0; | 
| +        scissor.offset.y = 0; | 
| +    } | 
| +    cmdBuffer->setScissor(gpu, 0, 1, &scissor); | 
| +} | 
| + | 
| +void set_dynamic_viewport_state(GrVkGpu* gpu, | 
| +                                GrVkCommandBuffer* cmdBuffer, | 
| +                                const GrRenderTarget& target) { | 
| +    // We always use one viewport the size of the RT | 
| +    VkViewport viewport; | 
| +    viewport.x = 0.0f; | 
| +    viewport.y = 0.0f; | 
| +    viewport.width = SkIntToScalar(target.width()); | 
| +    viewport.height = SkIntToScalar(target.height()); | 
| +    viewport.minDepth = 0.0f; | 
| +    viewport.maxDepth = 1.0f; | 
| +    cmdBuffer->setViewport(gpu, 0, 1, &viewport); | 
| +} | 
| + | 
| +void set_dynamic_blend_constant_state(GrVkGpu* gpu, | 
| +                                     GrVkCommandBuffer* cmdBuffer, | 
| +                                     const GrPipeline& pipeline) { | 
| +    GrXferProcessor::BlendInfo blendInfo; | 
| +    pipeline.getXferProcessor().getBlendInfo(&blendInfo); | 
| +    GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; | 
| +    GrBlendCoeff dstCoeff = blendInfo.fDstBlend; | 
| +    float floatColors[4]; | 
| +    if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) { | 
| +        GrColorToRGBAFloat(blendInfo.fBlendConstant, floatColors); | 
| +    } else { | 
| +        memset(floatColors, 0, 4 * sizeof(float)); | 
| +    } | 
| +    cmdBuffer->setBlendConstants(gpu, floatColors); | 
| +} | 
| + | 
| + | 
| + | 
| +void GrVkPipeline::SetDynamicState(GrVkGpu* gpu, | 
| +                                   GrVkCommandBuffer* cmdBuffer, | 
| +                                   const GrPipeline& pipeline) { | 
| +    const GrRenderTarget& target = *pipeline.getRenderTarget(); | 
| +    set_dynamic_scissor_state(gpu, cmdBuffer, pipeline, target); | 
| +    set_dynamic_viewport_state(gpu, cmdBuffer, target); | 
| +    set_dynamic_blend_constant_state(gpu, cmdBuffer, pipeline); | 
| +} | 
|  |