OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrVkGpu.h" | 8 #include "GrVkGpu.h" |
9 | 9 |
10 #include "GrContextOptions.h" | 10 #include "GrContextOptions.h" |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 #ifdef ENABLE_VK_LAYERS | 167 #ifdef ENABLE_VK_LAYERS |
168 if (fCallback) { | 168 if (fCallback) { |
169 VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallb
ack, nullptr)); | 169 VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallb
ack, nullptr)); |
170 fCallback = VK_NULL_HANDLE; | 170 fCallback = VK_NULL_HANDLE; |
171 } | 171 } |
172 #endif | 172 #endif |
173 } | 173 } |
174 | 174 |
175 /////////////////////////////////////////////////////////////////////////////// | 175 /////////////////////////////////////////////////////////////////////////////// |
176 | 176 |
177 GrGpuCommandBuffer* GrVkGpu::createCommandBuffer(const GrRenderTarget& target, | 177 GrGpuCommandBuffer* GrVkGpu::createCommandBuffer( |
178 GrGpuCommandBuffer::LoadAndStor
eOp colorOp, | 178 GrRenderTarget* target, |
179 GrColor colorClear, | 179 const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo, |
180 GrGpuCommandBuffer::LoadAndStor
eOp stencilOp, | 180 const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) { |
181 GrColor stencilClear) { | 181 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); |
182 const GrVkRenderTarget& vkRT = static_cast<const GrVkRenderTarget&>(target); | 182 return new GrVkGpuCommandBuffer(this, vkRT, colorInfo, stencilInfo); |
183 return new GrVkGpuCommandBuffer(this, vkRT, colorOp, colorClear, stencilOp,
stencilClear); | |
184 } | 183 } |
185 | 184 |
186 void GrVkGpu::submitCommandBuffer(SyncQueue sync) { | 185 void GrVkGpu::submitCommandBuffer(SyncQueue sync) { |
187 SkASSERT(fCurrentCmdBuffer); | 186 SkASSERT(fCurrentCmdBuffer); |
188 fCurrentCmdBuffer->end(this); | 187 fCurrentCmdBuffer->end(this); |
189 | 188 |
190 fCurrentCmdBuffer->submitToQueue(this, fQueue, sync); | 189 fCurrentCmdBuffer->submitToQueue(this, fQueue, sync); |
191 fResourceProvider.checkCommandBuffers(); | 190 fResourceProvider.checkCommandBuffers(); |
192 | 191 |
193 // Release old command buffer and create a new one | 192 // Release old command buffer and create a new one |
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 *tex, | 811 *tex, |
813 1, | 812 1, |
814 &blitRegion, | 813 &blitRegion, |
815 VK_FILTER_LINEAR); | 814 VK_FILTER_LINEAR); |
816 ++mipLevel; | 815 ++mipLevel; |
817 } | 816 } |
818 | 817 |
819 oldResource->unref(this); | 818 oldResource->unref(this); |
820 } | 819 } |
821 | 820 |
822 | |
823 //////////////////////////////////////////////////////////////////////////////// | |
824 | |
825 void GrVkGpu::bindGeometry(const GrPrimitiveProcessor& primProc, | |
826 const GrNonInstancedMesh& mesh) { | |
827 // There is no need to put any memory barriers to make sure host writes have
finished here. | |
828 // When a command buffer is submitted to a queue, there is an implicit memor
y barrier that | |
829 // occurs for all host writes. Additionally, BufferMemoryBarriers are not al
lowed inside of | |
830 // an active RenderPass. | |
831 GrVkVertexBuffer* vbuf; | |
832 vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer(); | |
833 SkASSERT(vbuf); | |
834 SkASSERT(!vbuf->isMapped()); | |
835 | |
836 fCurrentCmdBuffer->bindVertexBuffer(this, vbuf); | |
837 | |
838 if (mesh.isIndexed()) { | |
839 GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer(); | |
840 SkASSERT(ibuf); | |
841 SkASSERT(!ibuf->isMapped()); | |
842 | |
843 fCurrentCmdBuffer->bindIndexBuffer(this, ibuf); | |
844 } | |
845 } | |
846 | |
847 //////////////////////////////////////////////////////////////////////////////// | 821 //////////////////////////////////////////////////////////////////////////////// |
848 | 822 |
849 GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRen
derTarget* rt, | 823 GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRen
derTarget* rt, |
850 int width, | 824 int width, |
851 int height)
{ | 825 int height)
{ |
852 SkASSERT(width >= rt->width()); | 826 SkASSERT(width >= rt->width()); |
853 SkASSERT(height >= rt->height()); | 827 SkASSERT(height >= rt->height()); |
854 | 828 |
855 int samples = rt->numStencilSamples(); | 829 int samples = rt->numStencilSamples(); |
856 | 830 |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1080 subRange.levelCount = 1; | 1054 subRange.levelCount = 1; |
1081 subRange.baseArrayLayer = 0; | 1055 subRange.baseArrayLayer = 0; |
1082 subRange.layerCount = 1; | 1056 subRange.layerCount = 1; |
1083 | 1057 |
1084 // TODO: I imagine that most times we want to clear a stencil it will be at
the beginning of a | 1058 // TODO: I imagine that most times we want to clear a stencil it will be at
the beginning of a |
1085 // draw. Thus we should look into using the load op functions on the render
pass to clear out | 1059 // draw. Thus we should look into using the load op functions on the render
pass to clear out |
1086 // the stencil there. | 1060 // the stencil there. |
1087 fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor,
1, &subRange); | 1061 fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor,
1, &subRange); |
1088 } | 1062 } |
1089 | 1063 |
1090 void GrVkGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bo
ol insideClip) { | |
1091 SkASSERT(target); | |
1092 | |
1093 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); | |
1094 GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment(); | |
1095 GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)sb; | |
1096 | |
1097 // this should only be called internally when we know we have a | |
1098 // stencil buffer. | |
1099 SkASSERT(sb); | |
1100 int stencilBitCount = sb->bits(); | |
1101 | |
1102 // The contract with the callers does not guarantee that we preserve all bit
s in the stencil | |
1103 // during this clear. Thus we will clear the entire stencil to the desired v
alue. | |
1104 | |
1105 VkClearDepthStencilValue vkStencilColor; | |
1106 memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); | |
1107 if (insideClip) { | |
1108 vkStencilColor.stencil = (1 << (stencilBitCount - 1)); | |
1109 } else { | |
1110 vkStencilColor.stencil = 0; | |
1111 } | |
1112 | |
1113 vkStencil->setImageLayout(this, | |
1114 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, | |
1115 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, | |
1116 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | |
1117 false); | |
1118 | |
1119 // Change layout of our render target so it can be used as the color attachm
ent. This is what | |
1120 // the render pass expects when it begins. | |
1121 vkRT->setImageLayout(this, | |
1122 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, | |
1123 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | |
1124 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | |
1125 false); | |
1126 | |
1127 VkClearRect clearRect; | |
1128 // Flip rect if necessary | |
1129 SkIRect vkRect = rect; | |
1130 | |
1131 if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) { | |
1132 vkRect.fTop = vkRT->height() - rect.fBottom; | |
1133 vkRect.fBottom = vkRT->height() - rect.fTop; | |
1134 } | |
1135 | |
1136 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; | |
1137 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height(
) }; | |
1138 | |
1139 clearRect.baseArrayLayer = 0; | |
1140 clearRect.layerCount = 1; | |
1141 | |
1142 const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); | |
1143 SkASSERT(renderPass); | |
1144 fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); | |
1145 | |
1146 uint32_t stencilIndex; | |
1147 SkAssertResult(renderPass->stencilAttachmentIndex(&stencilIndex)); | |
1148 | |
1149 VkClearAttachment attachment; | |
1150 attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; | |
1151 attachment.colorAttachment = 0; // this value shouldn't matter | |
1152 attachment.clearValue.depthStencil = vkStencilColor; | |
1153 | |
1154 fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect); | |
1155 fCurrentCmdBuffer->endRenderPass(this); | |
1156 | |
1157 return; | |
1158 } | |
1159 | |
1160 void GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color
) { | |
1161 // parent class should never let us get here with no RT | |
1162 SkASSERT(target); | |
1163 | |
1164 VkClearColorValue vkColor; | |
1165 GrColorToRGBAFloat(color, vkColor.float32); | |
1166 | |
1167 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target); | |
1168 | |
1169 if (rect.width() != target->width() || rect.height() != target->height()) { | |
1170 vkRT->setImageLayout(this, | |
1171 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, | |
1172 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | |
1173 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | |
1174 false); | |
1175 | |
1176 // If we are using a stencil attachment we also need to change its layou
t to what the render | |
1177 // pass is expecting. | |
1178 if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAt
tachment()) { | |
1179 GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; | |
1180 vkStencil->setImageLayout(this, | |
1181 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_O
PTIMAL, | |
1182 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_B
IT | | |
1183 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BI
T, | |
1184 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | |
1185 false); | |
1186 } | |
1187 | |
1188 VkClearRect clearRect; | |
1189 // Flip rect if necessary | |
1190 SkIRect vkRect = rect; | |
1191 if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) { | |
1192 vkRect.fTop = vkRT->height() - rect.fBottom; | |
1193 vkRect.fBottom = vkRT->height() - rect.fTop; | |
1194 } | |
1195 clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop }; | |
1196 clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.hei
ght() }; | |
1197 clearRect.baseArrayLayer = 0; | |
1198 clearRect.layerCount = 1; | |
1199 | |
1200 const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); | |
1201 SkASSERT(renderPass); | |
1202 fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); | |
1203 | |
1204 uint32_t colorIndex; | |
1205 SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex)); | |
1206 | |
1207 VkClearAttachment attachment; | |
1208 attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | |
1209 attachment.colorAttachment = colorIndex; | |
1210 attachment.clearValue.color = vkColor; | |
1211 | |
1212 fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect)
; | |
1213 fCurrentCmdBuffer->endRenderPass(this); | |
1214 return; | |
1215 } | |
1216 | |
1217 vkRT->setImageLayout(this, | |
1218 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | |
1219 VK_ACCESS_TRANSFER_WRITE_BIT, | |
1220 VK_PIPELINE_STAGE_TRANSFER_BIT, | |
1221 false); | |
1222 | |
1223 VkImageSubresourceRange subRange; | |
1224 memset(&subRange, 0, sizeof(VkImageSubresourceRange)); | |
1225 subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | |
1226 subRange.baseMipLevel = 0; | |
1227 subRange.levelCount = 1; | |
1228 subRange.baseArrayLayer = 0; | |
1229 subRange.layerCount = 1; | |
1230 | |
1231 // In the future we may not actually be doing this type of clear at all. If
we are inside a | |
1232 // render pass or doing a non full clear then we will use CmdClearColorAttac
hment. The more | |
1233 // common use case will be clearing an attachment at the start of a render p
ass, in which case | |
1234 // we will use the clear load ops. | |
1235 fCurrentCmdBuffer->clearColorImage(this, | |
1236 vkRT, | |
1237 &vkColor, | |
1238 1, &subRange); | |
1239 } | |
1240 | |
1241 inline bool can_copy_image(const GrSurface* dst, | 1064 inline bool can_copy_image(const GrSurface* dst, |
1242 const GrSurface* src, | 1065 const GrSurface* src, |
1243 const GrVkGpu* gpu) { | 1066 const GrVkGpu* gpu) { |
1244 // Currently we don't support msaa | 1067 // Currently we don't support msaa |
1245 if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1)
|| | 1068 if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1)
|| |
1246 (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1))
{ | 1069 (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1))
{ |
1247 return false; | 1070 return false; |
1248 } | 1071 } |
1249 | 1072 |
1250 // We require that all vulkan GrSurfaces have been created with transfer_dst
and transfer_src | 1073 // We require that all vulkan GrSurfaces have been created with transfer_dst
and transfer_src |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1580 memcpy(top, bottom, tightRowBytes); | 1403 memcpy(top, bottom, tightRowBytes); |
1581 memcpy(bottom, tmpRow, tightRowBytes); | 1404 memcpy(bottom, tmpRow, tightRowBytes); |
1582 top += rowBytes; | 1405 top += rowBytes; |
1583 bottom -= rowBytes; | 1406 bottom -= rowBytes; |
1584 } | 1407 } |
1585 } | 1408 } |
1586 | 1409 |
1587 return true; | 1410 return true; |
1588 } | 1411 } |
1589 | 1412 |
1590 void GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buf
fer) { | 1413 void GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buf
fer, |
| 1414 const GrVkRenderPass* renderPass, |
| 1415 const VkClearValue* colorClear, |
| 1416 GrVkRenderTarget* target, |
| 1417 const SkIRect& bounds) { |
| 1418 // Currently it is fine for us to always pass in 1 for the clear count even
if no attachment |
| 1419 // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the
color attachment |
| 1420 // which is always at the first attachment. |
| 1421 fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target,
bounds, true); |
1591 fCurrentCmdBuffer->executeCommands(this, buffer); | 1422 fCurrentCmdBuffer->executeCommands(this, buffer); |
| 1423 fCurrentCmdBuffer->endRenderPass(this); |
1592 } | 1424 } |
1593 | 1425 |
1594 sk_sp<GrVkPipelineState> GrVkGpu::prepareDrawState(const GrPipeline& pipeline, | |
1595 const GrPrimitiveProcessor& p
rimProc, | |
1596 GrPrimitiveType primitiveType
, | |
1597 const GrVkRenderPass& renderP
ass) { | |
1598 sk_sp<GrVkPipelineState> pipelineState = | |
1599 fResourceProvider.findOrCreateCompatiblePipelineState(pipeline, | |
1600 primProc, | |
1601 primitiveType, | |
1602 renderPass); | |
1603 if (!pipelineState) { | |
1604 return pipelineState; | |
1605 } | |
1606 | |
1607 pipelineState->setData(this, primProc, pipeline); | |
1608 | |
1609 pipelineState->bind(this, fCurrentCmdBuffer); | |
1610 | |
1611 GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline); | |
1612 | |
1613 return pipelineState; | |
1614 } | |
1615 | |
1616 void GrVkGpu::onDraw(const GrPipeline& pipeline, | |
1617 const GrPrimitiveProcessor& primProc, | |
1618 const GrMesh* meshes, | |
1619 int meshCount) { | |
1620 if (!meshCount) { | |
1621 return; | |
1622 } | |
1623 GrRenderTarget* rt = pipeline.getRenderTarget(); | |
1624 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); | |
1625 const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); | |
1626 SkASSERT(renderPass); | |
1627 | |
1628 GrPrimitiveType primitiveType = meshes[0].primitiveType(); | |
1629 sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline, | |
1630 primProc, | |
1631 primitiveTyp
e, | |
1632 *renderPass)
; | |
1633 if (!pipelineState) { | |
1634 return; | |
1635 } | |
1636 | |
1637 // Change layout of our render target so it can be used as the color attachm
ent | |
1638 vkRT->setImageLayout(this, | |
1639 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, | |
1640 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | |
1641 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | |
1642 false); | |
1643 | |
1644 // If we are using a stencil attachment we also need to update its layout | |
1645 if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttach
ment()) { | |
1646 GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil; | |
1647 vkStencil->setImageLayout(this, | |
1648 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIM
AL, | |
1649 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | | |
1650 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, | |
1651 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | |
1652 false); | |
1653 } | |
1654 | |
1655 fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT); | |
1656 | |
1657 for (int i = 0; i < meshCount; ++i) { | |
1658 const GrMesh& mesh = meshes[i]; | |
1659 GrMesh::Iterator iter; | |
1660 const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh); | |
1661 do { | |
1662 if (nonIdxMesh->primitiveType() != primitiveType) { | |
1663 // Technically we don't have to call this here (since there is a
safety check in | |
1664 // pipelineState:setData but this will allow for quicker freeing
of resources if the | |
1665 // pipelineState sits in a cache for a while. | |
1666 pipelineState->freeTempResources(this); | |
1667 SkDEBUGCODE(pipelineState = nullptr); | |
1668 primitiveType = nonIdxMesh->primitiveType(); | |
1669 pipelineState = this->prepareDrawState(pipeline, | |
1670 primProc, | |
1671 primitiveType, | |
1672 *renderPass); | |
1673 if (!pipelineState) { | |
1674 return; | |
1675 } | |
1676 } | |
1677 SkASSERT(pipelineState); | |
1678 this->bindGeometry(primProc, *nonIdxMesh); | |
1679 | |
1680 if (nonIdxMesh->isIndexed()) { | |
1681 fCurrentCmdBuffer->drawIndexed(this, | |
1682 nonIdxMesh->indexCount(), | |
1683 1, | |
1684 nonIdxMesh->startIndex(), | |
1685 nonIdxMesh->startVertex(), | |
1686 0); | |
1687 } else { | |
1688 fCurrentCmdBuffer->draw(this, | |
1689 nonIdxMesh->vertexCount(), | |
1690 1, | |
1691 nonIdxMesh->startVertex(), | |
1692 0); | |
1693 } | |
1694 | |
1695 fStats.incNumDraws(); | |
1696 } while ((nonIdxMesh = iter.next())); | |
1697 } | |
1698 | |
1699 fCurrentCmdBuffer->endRenderPass(this); | |
1700 | |
1701 // Technically we don't have to call this here (since there is a safety chec
k in | |
1702 // pipelineState:setData but this will allow for quicker freeing of resource
s if the | |
1703 // pipelineState sits in a cache for a while. | |
1704 pipelineState->freeTempResources(this); | |
1705 | |
1706 #if SWAP_PER_DRAW | |
1707 glFlush(); | |
1708 #if defined(SK_BUILD_FOR_MAC) | |
1709 aglSwapBuffers(aglGetCurrentContext()); | |
1710 int set_a_break_pt_here = 9; | |
1711 aglSwapBuffers(aglGetCurrentContext()); | |
1712 #elif defined(SK_BUILD_FOR_WIN32) | |
1713 SwapBuf(); | |
1714 int set_a_break_pt_here = 9; | |
1715 SwapBuf(); | |
1716 #endif | |
1717 #endif | |
1718 } | |
OLD | NEW |