Index: src/gpu/vk/GrVkGpu.cpp |
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp |
index ef2d0be615d0734a3e03f1469d08b9f81219179d..9528efc8e0333cb99d0251b5f646d9e4f19da400 100644 |
--- a/src/gpu/vk/GrVkGpu.cpp |
+++ b/src/gpu/vk/GrVkGpu.cpp |
@@ -520,6 +520,12 @@ GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::Li |
if (renderTarget) { |
tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, desc, lifeCycle, |
imageDesc); |
+#if 0 |
+ // This clear can be included to fix warning described in htttps://bugs.skia.org/5045 |
+ // Obviously we do not want to be clearling needlessly every time we create a render target. |
+ SkIRect rect = SkIRect::MakeWH(tex->width(), tex->height()); |
+ this->clear(rect, GrColor_TRANSPARENT_BLACK, tex->asRenderTarget()); |
+#endif |
} else { |
tex = GrVkTexture::CreateNewTexture(this, desc, lifeCycle, imageDesc); |
} |
@@ -882,6 +888,118 @@ void GrVkGpu::finishDrawTarget() { |
this->submitCommandBuffer(kSkip_SyncQueue); |
} |
+void GrVkGpu::clearStencil(GrRenderTarget* target) { |
+ if (nullptr == target) { |
+ return; |
+ } |
+ GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment(); |
+ GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; |
+ |
+ |
+ VkClearDepthStencilValue vkStencilColor; |
+ memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); |
+ |
+ VkImageLayout origDstLayout = vkStencil->currentLayout(); |
+ |
+ VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); |
+ VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; |
+ |
+ VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);; |
+ VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
+ |
+ vkStencil->setImageLayout(this, |
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
+ srcAccessMask, |
+ dstAccessMask, |
+ srcStageMask, |
+ dstStageMask, |
+ false); |
+ |
+ |
+ VkImageSubresourceRange subRange; |
+ memset(&subRange, 0, sizeof(VkImageSubresourceRange)); |
+ subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; |
+ subRange.baseMipLevel = 0; |
+ subRange.levelCount = 1; |
+ subRange.baseArrayLayer = 0; |
+ subRange.layerCount = 1; |
+ |
+ // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a |
+ // draw. Thus we should look into using the load op functions on the render pass to clear out |
+ // the stencil there. |
+ 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; |
+ } |
+ |
+ VkImageLayout origDstLayout = vkStencil->currentLayout(); |
+ VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout); |
+ VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; |
+ VkPipelineStageFlags srcStageMask = |
+ GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); |
+ VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; |
+ vkStencil->setImageLayout(this, |
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
+ srcAccessMask, |
+ dstAccessMask, |
+ srcStageMask, |
+ dstStageMask, |
+ 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); |
@@ -896,7 +1014,7 @@ void GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color |
VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout); |
VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; |
VkPipelineStageFlags srcStageMask = |
- GrVkMemory::LayoutToPipelineStageFlags(vkRT->currentLayout()); |
+ GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); |
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; |
vkRT->setImageLayout(this, |
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
@@ -907,12 +1025,14 @@ void GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color |
false); |
VkClearRect clearRect; |
- clearRect.rect.offset = { rect.fLeft, rect.fTop }; |
- clearRect.rect.extent = { (uint32_t)rect.width(), (uint32_t)rect.height() }; |
- clearRect.baseArrayLayer = 0; |
- clearRect.layerCount = 1; |
- |
- |
+ // 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() }; |
const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); |
SkASSERT(renderPass); |
@@ -1201,7 +1321,6 @@ void GrVkGpu::onDraw(const DrawArgs& args, const GrNonInstancedVertices& vertice |
const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); |
SkASSERT(renderPass); |
- |
GrVkProgram* program = GrVkProgramBuilder::CreateProgram(this, args, |
vertices.primitiveType(), |
*renderPass); |
@@ -1234,6 +1353,26 @@ void GrVkGpu::onDraw(const DrawArgs& args, const GrNonInstancedVertices& vertice |
dstStageMask, |
false); |
+ // If we are using a stencil attachment we also need to update its layout |
+ if (!args.fPipeline->getStencil().isDisabled()) { |
+ GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment(); |
+ GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; |
+ VkImageLayout origDstLayout = vkStencil->currentLayout(); |
+ VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout); |
+ VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | |
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; |
+ VkPipelineStageFlags srcStageMask = |
+ GrVkMemory::LayoutToPipelineStageFlags(origDstLayout); |
+ VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; |
+ vkStencil->setImageLayout(this, |
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
+ srcAccessMask, |
+ dstAccessMask, |
+ srcStageMask, |
+ dstStageMask, |
+ false); |
+ } |
+ |
if (vertices.isIndexed()) { |
fCurrentCmdBuffer->drawIndexed(this, |
vertices.indexCount(), |