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 "GrVkCommandBuffer.h" 9 10 #include "GrVkGpu.h" 11 #include "GrVkFramebuffer.h" 12 #include "GrVkImage.h" 13 #include "GrVkImageView.h" 14 #include "GrVkIndexBuffer.h" 15 #include "GrVkPipeline.h" 16 #include "GrVkPipelineState.h" 17 #include "GrVkRenderPass.h" 18 #include "GrVkRenderTarget.h" 19 #include "GrVkPipelineState.h" 20 #include "GrVkTransferBuffer.h" 21 #include "GrVkUtil.h" 22 #include "GrVkVertexBuffer.h" 23 #include "SkRect.h" 24 25 void GrVkCommandBuffer::invalidateState() { 26 for (auto& boundInputBuffer : fBoundInputBuffers) { 27 boundInputBuffer = VK_NULL_HANDLE; 28 } 29 fBoundIndexBuffer = VK_NULL_HANDLE; 30 31 memset(&fCachedViewport, 0, sizeof(VkViewport)); 32 fCachedViewport.width = - 1.0f; // Viewport must have a width greater than 0 33 34 memset(&fCachedScissor, 0, sizeof(VkRect2D)); 35 fCachedScissor.offset.x = -1; // Scissor offset must be greater that 0 to be valid 36 37 for (int i = 0; i < 4; ++i) { 38 fCachedBlendConstant[i] = -1.0; 39 } 40 } 41 42 void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const { 43 SkASSERT(!fIsActive); 44 for (int i = 0; i < fTrackedResources.count(); ++i) { 45 fTrackedResources[i]->unref(gpu); 46 } 47 48 for (int i = 0; i < fTrackedRecycledResources.count(); ++i) { 49 fTrackedRecycledResources[i]->recycle(const_cast<GrVkGpu*>(gpu)); 50 } 51 52 GR_VK_CALL(gpu->vkInterface(), FreeCommandBuffers(gpu->device(), gpu->cmdPool(), 53 1, &fCmdBuffer)); 54 55 this->onFreeGPUData(gpu); 56 } 57 58 void GrVkCommandBuffer::abandonGPUData() const { 59 for (int i = 0; i < fTrackedResources.count(); ++i) { 60 fTrackedResources[i]->unrefAndAbandon(); 61 } 62 63 for (int i = 0; i < fTrackedRecycledResources.count(); ++i) { 64 // We don't recycle resources when abandoning them. 65 fTrackedRecycledResources[i]->unrefAndAbandon(); 66 } 67 } 68 69 void GrVkCommandBuffer::reset(GrVkGpu* gpu) { 70 SkASSERT(!fIsActive); 71 for (int i = 0; i < fTrackedResources.count(); ++i) { 72 fTrackedResources[i]->unref(gpu); 73 } 74 for (int i = 0; i < fTrackedRecycledResources.count(); ++i) { 75 fTrackedRecycledResources[i]->recycle(const_cast<GrVkGpu*>(gpu)); 76 } 77 78 if (++fNumResets > kNumRewindResetsBeforeFullReset) { 79 fTrackedResources.reset(); 80 fTrackedRecycledResources.reset(); 81 fTrackedResources.setReserve(kInitialTrackedResourcesCount); 82 fTrackedRecycledResources.setReserve(kInitialTrackedResourcesCount); 83 fNumResets = 0; 84 } else { 85 fTrackedResources.rewind(); 86 fTrackedRecycledResources.rewind(); 87 } 88 89 90 this->invalidateState(); 91 92 // we will retain resources for later use 93 VkCommandBufferResetFlags flags = 0; 94 GR_VK_CALL(gpu->vkInterface(), ResetCommandBuffer(fCmdBuffer, flags)); 95 96 this->onReset(gpu); 97 } 98 99 //////////////////////////////////////////////////////////////////////////////// 100 // CommandBuffer commands 101 //////////////////////////////////////////////////////////////////////////////// 102 103 void GrVkCommandBuffer::pipelineBarrier(const GrVkGpu* gpu, 104 VkPipelineStageFlags srcStageMask, 105 VkPipelineStageFlags dstStageMask, 106 bool byRegion, 107 BarrierType barrierType, 108 void* barrier) const { 109 SkASSERT(fIsActive); 110 // For images we can have barriers inside of render passes but they require us to add more 111 // support in subpasses which need self dependencies to have barriers inside them. Also, we can 112 // never have buffer barriers inside of a render pass. For now we will just assert that we are 113 // not in a render pass. 114 SkASSERT(!fActiveRenderPass); 115 VkDependencyFlags dependencyFlags = byRegion ? VK_DEPENDENCY_BY_REGION_BIT : 0; 116 117 switch (barrierType) { 118 case kMemory_BarrierType: { 119 const VkMemoryBarrier* barrierPtr = reinterpret_cast<VkMemoryBarrier*>(barrier); 120 GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, 121 dstStageMask, dependencyFlags, 122 1, barrierPtr, 123 0, nullptr, 124 0, nullptr)); 125 break; 126 } 127 128 case kBufferMemory_BarrierType: { 129 const VkBufferMemoryBarrier* barrierPtr = 130 reinterpret_cast<VkBufferMemoryBarrier*>(barrier); 131 GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, 132 dstStageMask, dependencyFlags, 133 0, nullptr, 134 1, barrierPtr, 135 0, nullptr)); 136 break; 137 } 138 139 case kImageMemory_BarrierType: { 140 const VkImageMemoryBarrier* barrierPtr = 141 reinterpret_cast<VkImageMemoryBarrier*>(barrier); 142 GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier(fCmdBuffer, srcStageMask, 143 dstStageMask, dependencyFlags, 144 0, nullptr, 145 0, nullptr, 146 1, barrierPtr)); 147 break; 148 } 149 } 150 151 } 152 153 void GrVkCommandBuffer::bindInputBuffer(GrVkGpu* gpu, uint32_t binding, 154 const GrVkVertexBuffer* vbuffer) { 155 VkBuffer vkBuffer = vbuffer->buffer(); 156 SkASSERT(VK_NULL_HANDLE != vkBuffer); 157 SkASSERT(binding < kMaxInputBuffers); 158 // TODO: once vbuffer->offset() no longer always returns 0, we will need to track the offset 159 // to know if we can skip binding or not. 160 if (vkBuffer != fBoundInputBuffers[binding]) { 161 VkDeviceSize offset = vbuffer->offset(); 162 GR_VK_CALL(gpu->vkInterface(), CmdBindVertexBuffers(fCmdBuffer, 163 binding, 164 1, 165 &vkBuffer, 166 &offset)); 167 fBoundInputBuffers[binding] = vkBuffer; 168 addResource(vbuffer->resource()); 169 } 170 } 171 172 void GrVkCommandBuffer::bindIndexBuffer(GrVkGpu* gpu, const GrVkIndexBuffer* ibuffer) { 173 VkBuffer vkBuffer = ibuffer->buffer(); 174 SkASSERT(VK_NULL_HANDLE != vkBuffer); 175 // TODO: once ibuffer->offset() no longer always returns 0, we will need to track the offset 176 // to know if we can skip binding or not. 177 if (vkBuffer != fBoundIndexBuffer) { 178 GR_VK_CALL(gpu->vkInterface(), CmdBindIndexBuffer(fCmdBuffer, 179 vkBuffer, 180 ibuffer->offset(), 181 VK_INDEX_TYPE_UINT16)); 182 fBoundIndexBuffer = vkBuffer; 183 addResource(ibuffer->resource()); 184 } 185 } 186 187 void GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu, 188 int numAttachments, 189 const VkClearAttachment* attachments, 190 int numRects, 191 const VkClearRect* clearRects) const { 192 SkASSERT(fIsActive); 193 SkASSERT(fActiveRenderPass); 194 SkASSERT(numAttachments > 0); 195 SkASSERT(numRects > 0); 196 #ifdef SK_DEBUG 197 for (int i = 0; i < numAttachments; ++i) { 198 if (attachments[i].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { 199 uint32_t testIndex; 200 SkAssertResult(fActiveRenderPass->colorAttachmentIndex(&testIndex)); 201 SkASSERT(testIndex == attachments[i].colorAttachment); 202 } 203 } 204 #endif 205 GR_VK_CALL(gpu->vkInterface(), CmdClearAttachments(fCmdBuffer, 206 numAttachments, 207 attachments, 208 numRects, 209 clearRects)); 210 } 211 212 void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu, 213 GrVkPipelineState* pipelineState, 214 VkPipelineLayout layout, 215 uint32_t firstSet, 216 uint32_t setCount, 217 const VkDescriptorSet* descriptorSets, 218 uint32_t dynamicOffsetCount, 219 const uint32_t* dynamicOffsets) { 220 SkASSERT(fIsActive); 221 GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer, 222 VK_PIPELINE_BIND_POINT_GRAPHICS, 223 layout, 224 firstSet, 225 setCount, 226 descriptorSets, 227 dynamicOffsetCount, 228 dynamicOffsets)); 229 pipelineState->addUniformResources(*this); 230 } 231 232 void GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu, 233 const SkTArray<const GrVkRecycledResource*>& recycled, 234 const SkTArray<const GrVkResource*>& resources, 235 VkPipelineLayout layout, 236 uint32_t firstSet, 237 uint32_t setCount, 238 const VkDescriptorSet* descriptorSets, 239 uint32_t dynamicOffsetCount, 240 const uint32_t* dynamicOffsets) { 241 SkASSERT(fIsActive); 242 GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer, 243 VK_PIPELINE_BIND_POINT_GRAPHICS, 244 layout, 245 firstSet, 246 setCount, 247 descriptorSets, 248 dynamicOffsetCount, 249 dynamicOffsets)); 250 for (int i = 0; i < recycled.count(); ++i) { 251 this->addRecycledResource(recycled[i]); 252 } 253 for (int i = 0; i < resources.count(); ++i) { 254 this->addResource(resources[i]); 255 } 256 } 257 258 void GrVkCommandBuffer::bindPipeline(const GrVkGpu* gpu, const GrVkPipeline* pipeline) { 259 SkASSERT(fIsActive); 260 GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer, 261 VK_PIPELINE_BIND_POINT_GRAPHICS, 262 pipeline->pipeline())); 263 this->addResource(pipeline); 264 } 265 266 void GrVkCommandBuffer::drawIndexed(const GrVkGpu* gpu, 267 uint32_t indexCount, 268 uint32_t instanceCount, 269 uint32_t firstIndex, 270 int32_t vertexOffset, 271 uint32_t firstInstance) const { 272 SkASSERT(fIsActive); 273 SkASSERT(fActiveRenderPass); 274 GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexed(fCmdBuffer, 275 indexCount, 276 instanceCount, 277 firstIndex, 278 vertexOffset, 279 firstInstance)); 280 } 281 282 void GrVkCommandBuffer::draw(const GrVkGpu* gpu, 283 uint32_t vertexCount, 284 uint32_t instanceCount, 285 uint32_t firstVertex, 286 uint32_t firstInstance) const { 287 SkASSERT(fIsActive); 288 SkASSERT(fActiveRenderPass); 289 GR_VK_CALL(gpu->vkInterface(), CmdDraw(fCmdBuffer, 290 vertexCount, 291 instanceCount, 292 firstVertex, 293 firstInstance)); 294 } 295 296 void GrVkCommandBuffer::setViewport(const GrVkGpu* gpu, 297 uint32_t firstViewport, 298 uint32_t viewportCount, 299 const VkViewport* viewports) { 300 SkASSERT(fIsActive); 301 SkASSERT(1 == viewportCount); 302 if (memcmp(viewports, &fCachedViewport, sizeof(VkViewport))) { 303 GR_VK_CALL(gpu->vkInterface(), CmdSetViewport(fCmdBuffer, 304 firstViewport, 305 viewportCount, 306 viewports)); 307 fCachedViewport = viewports[0]; 308 } 309 } 310 311 void GrVkCommandBuffer::setScissor(const GrVkGpu* gpu, 312 uint32_t firstScissor, 313 uint32_t scissorCount, 314 const VkRect2D* scissors) { 315 SkASSERT(fIsActive); 316 SkASSERT(1 == scissorCount); 317 if (memcmp(scissors, &fCachedScissor, sizeof(VkRect2D))) { 318 GR_VK_CALL(gpu->vkInterface(), CmdSetScissor(fCmdBuffer, 319 firstScissor, 320 scissorCount, 321 scissors)); 322 fCachedScissor = scissors[0]; 323 } 324 } 325 326 void GrVkCommandBuffer::setBlendConstants(const GrVkGpu* gpu, 327 const float blendConstants[4]) { 328 SkASSERT(fIsActive); 329 if (memcmp(blendConstants, fCachedBlendConstant, 4 * sizeof(float))) { 330 GR_VK_CALL(gpu->vkInterface(), CmdSetBlendConstants(fCmdBuffer, blendConstants)); 331 memcpy(fCachedBlendConstant, blendConstants, 4 * sizeof(float)); 332 } 333 } 334 335 /////////////////////////////////////////////////////////////////////////////// 336 // PrimaryCommandBuffer 337 //////////////////////////////////////////////////////////////////////////////// 338 GrVkPrimaryCommandBuffer::~GrVkPrimaryCommandBuffer() { 339 // Should have ended any render pass we're in the middle of 340 SkASSERT(!fActiveRenderPass); 341 } 342 343 GrVkPrimaryCommandBuffer* GrVkPrimaryCommandBuffer::Create(const GrVkGpu* gpu, 344 VkCommandPool cmdPool) { 345 const VkCommandBufferAllocateInfo cmdInfo = { 346 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType 347 NULL, // pNext 348 cmdPool, // commandPool 349 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 350 1 // bufferCount 351 }; 352 353 VkCommandBuffer cmdBuffer; 354 VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateCommandBuffers(gpu->device(), 355 &cmdInfo, 356 &cmdBuffer)); 357 if (err) { 358 return nullptr; 359 } 360 return new GrVkPrimaryCommandBuffer(cmdBuffer); 361 } 362 363 void GrVkPrimaryCommandBuffer::begin(const GrVkGpu* gpu) { 364 SkASSERT(!fIsActive); 365 VkCommandBufferBeginInfo cmdBufferBeginInfo; 366 memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 367 cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 368 cmdBufferBeginInfo.pNext = nullptr; 369 cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 370 cmdBufferBeginInfo.pInheritanceInfo = nullptr; 371 372 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), BeginCommandBuffer(fCmdBuffer, 373 &cmdBufferBeginInfo)); 374 fIsActive = true; 375 } 376 377 void GrVkPrimaryCommandBuffer::end(const GrVkGpu* gpu) { 378 SkASSERT(fIsActive); 379 SkASSERT(!fActiveRenderPass); 380 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer)); 381 this->invalidateState(); 382 fIsActive = false; 383 } 384 385 void GrVkPrimaryCommandBuffer::beginRenderPass(const GrVkGpu* gpu, 386 const GrVkRenderPass* renderPass, 387 const VkClearValue* clearValues, 388 const GrVkRenderTarget& target, 389 const SkIRect& bounds, 390 bool forSecondaryCB) { 391 SkASSERT(fIsActive); 392 SkASSERT(!fActiveRenderPass); 393 SkASSERT(renderPass->isCompatible(target)); 394 395 VkRenderPassBeginInfo beginInfo; 396 VkRect2D renderArea; 397 renderArea.offset = { bounds.fLeft , bounds.fTop }; 398 renderArea.extent = { (uint32_t)bounds.width(), (uint32_t)bounds.height() }; 399 400 memset(&beginInfo, 0, sizeof(VkRenderPassBeginInfo)); 401 beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 402 beginInfo.pNext = nullptr; 403 beginInfo.renderPass = renderPass->vkRenderPass(); 404 beginInfo.framebuffer = target.framebuffer()->framebuffer(); 405 beginInfo.renderArea = renderArea; 406 beginInfo.clearValueCount = renderPass->clearValueCount(); 407 beginInfo.pClearValues = clearValues; 408 409 VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS 410 : VK_SUBPASS_CONTENTS_INLINE; 411 412 GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents)); 413 fActiveRenderPass = renderPass; 414 this->addResource(renderPass); 415 target.addResources(*this); 416 } 417 418 void GrVkPrimaryCommandBuffer::endRenderPass(const GrVkGpu* gpu) { 419 SkASSERT(fIsActive); 420 SkASSERT(fActiveRenderPass); 421 GR_VK_CALL(gpu->vkInterface(), CmdEndRenderPass(fCmdBuffer)); 422 fActiveRenderPass = nullptr; 423 } 424 425 void GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu, 426 GrVkSecondaryCommandBuffer* buffer) { 427 SkASSERT(fIsActive); 428 SkASSERT(!buffer->fIsActive); 429 SkASSERT(fActiveRenderPass); 430 SkASSERT(fActiveRenderPass->isCompatible(*buffer->fActiveRenderPass)); 431 432 GR_VK_CALL(gpu->vkInterface(), CmdExecuteCommands(fCmdBuffer, 1, &buffer->fCmdBuffer)); 433 buffer->ref(); 434 fSecondaryCommandBuffers.push_back(buffer); 435 // When executing a secondary command buffer all state (besides render pass state) becomes 436 // invalidated and must be reset. This includes bound buffers, pipelines, dynamic state, etc. 437 this->invalidateState(); 438 } 439 440 void GrVkPrimaryCommandBuffer::submitToQueue( 441 const GrVkGpu* gpu, 442 VkQueue queue, 443 GrVkGpu::SyncQueue sync, 444 SkTArray<const GrVkSemaphore::Resource*>& signalSemaphores, 445 SkTArray<const GrVkSemaphore::Resource*>& waitSemaphores) { 446 SkASSERT(!fIsActive); 447 448 VkResult err; 449 if (VK_NULL_HANDLE == fSubmitFence) { 450 VkFenceCreateInfo fenceInfo; 451 memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo)); 452 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 453 err = GR_VK_CALL(gpu->vkInterface(), CreateFence(gpu->device(), &fenceInfo, nullptr, 454 &fSubmitFence)); 455 SkASSERT(!err); 456 } else { 457 GR_VK_CALL(gpu->vkInterface(), ResetFences(gpu->device(), 1, &fSubmitFence)); 458 } 459 460 int signalCount = signalSemaphores.count(); 461 SkTArray<VkSemaphore> vkSignalSem(signalCount); 462 for (int i = 0; i < signalCount; ++i) { 463 this->addResource(signalSemaphores[i]); 464 vkSignalSem.push_back(signalSemaphores[i]->semaphore()); 465 } 466 467 int waitCount = waitSemaphores.count(); 468 SkTArray<VkSemaphore> vkWaitSems(waitCount); 469 SkTArray<VkPipelineStageFlags> vkWaitStages(waitCount); 470 for (int i = 0; i < waitCount; ++i) { 471 this->addResource(waitSemaphores[i]); 472 vkWaitSems.push_back(waitSemaphores[i]->semaphore()); 473 vkWaitStages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); 474 } 475 476 VkSubmitInfo submitInfo; 477 memset(&submitInfo, 0, sizeof(VkSubmitInfo)); 478 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 479 submitInfo.pNext = nullptr; 480 submitInfo.waitSemaphoreCount = waitCount; 481 submitInfo.pWaitSemaphores = vkWaitSems.begin(); 482 submitInfo.pWaitDstStageMask = vkWaitStages.begin(); 483 submitInfo.commandBufferCount = 1; 484 submitInfo.pCommandBuffers = &fCmdBuffer; 485 submitInfo.signalSemaphoreCount = vkSignalSem.count(); 486 submitInfo.pSignalSemaphores = vkSignalSem.begin(); 487 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), QueueSubmit(queue, 1, &submitInfo, fSubmitFence)); 488 489 if (GrVkGpu::kForce_SyncQueue == sync) { 490 err = GR_VK_CALL(gpu->vkInterface(), 491 WaitForFences(gpu->device(), 1, &fSubmitFence, true, UINT64_MAX)); 492 if (VK_TIMEOUT == err) { 493 SkDebugf("Fence failed to signal: %d\n", err); 494 SkFAIL("failing"); 495 } 496 SkASSERT(!err); 497 498 // Destroy the fence 499 GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr)); 500 fSubmitFence = VK_NULL_HANDLE; 501 } 502 } 503 504 bool GrVkPrimaryCommandBuffer::finished(const GrVkGpu* gpu) const { 505 if (VK_NULL_HANDLE == fSubmitFence) { 506 return true; 507 } 508 509 VkResult err = GR_VK_CALL(gpu->vkInterface(), GetFenceStatus(gpu->device(), fSubmitFence)); 510 switch (err) { 511 case VK_SUCCESS: 512 return true; 513 514 case VK_NOT_READY: 515 return false; 516 517 default: 518 SkDebugf("Error getting fence status: %d\n", err); 519 SkFAIL("failing"); 520 break; 521 } 522 523 return false; 524 } 525 526 void GrVkPrimaryCommandBuffer::onReset(GrVkGpu* gpu) { 527 for (int i = 0; i < fSecondaryCommandBuffers.count(); ++i) { 528 gpu->resourceProvider().recycleSecondaryCommandBuffer(fSecondaryCommandBuffers[i]); 529 } 530 fSecondaryCommandBuffers.reset(); 531 } 532 533 void GrVkPrimaryCommandBuffer::copyImage(const GrVkGpu* gpu, 534 GrVkImage* srcImage, 535 VkImageLayout srcLayout, 536 GrVkImage* dstImage, 537 VkImageLayout dstLayout, 538 uint32_t copyRegionCount, 539 const VkImageCopy* copyRegions) { 540 SkASSERT(fIsActive); 541 SkASSERT(!fActiveRenderPass); 542 this->addResource(srcImage->resource()); 543 this->addResource(dstImage->resource()); 544 GR_VK_CALL(gpu->vkInterface(), CmdCopyImage(fCmdBuffer, 545 srcImage->image(), 546 srcLayout, 547 dstImage->image(), 548 dstLayout, 549 copyRegionCount, 550 copyRegions)); 551 } 552 553 void GrVkPrimaryCommandBuffer::blitImage(const GrVkGpu* gpu, 554 const GrVkResource* srcResource, 555 VkImage srcImage, 556 VkImageLayout srcLayout, 557 const GrVkResource* dstResource, 558 VkImage dstImage, 559 VkImageLayout dstLayout, 560 uint32_t blitRegionCount, 561 const VkImageBlit* blitRegions, 562 VkFilter filter) { 563 SkASSERT(fIsActive); 564 SkASSERT(!fActiveRenderPass); 565 this->addResource(srcResource); 566 this->addResource(dstResource); 567 GR_VK_CALL(gpu->vkInterface(), CmdBlitImage(fCmdBuffer, 568 srcImage, 569 srcLayout, 570 dstImage, 571 dstLayout, 572 blitRegionCount, 573 blitRegions, 574 filter)); 575 } 576 577 void GrVkPrimaryCommandBuffer::blitImage(const GrVkGpu* gpu, 578 const GrVkImage& srcImage, 579 const GrVkImage& dstImage, 580 uint32_t blitRegionCount, 581 const VkImageBlit* blitRegions, 582 VkFilter filter) { 583 this->blitImage(gpu, 584 srcImage.resource(), 585 srcImage.image(), 586 srcImage.currentLayout(), 587 dstImage.resource(), 588 dstImage.image(), 589 dstImage.currentLayout(), 590 blitRegionCount, 591 blitRegions, 592 filter); 593 } 594 595 596 void GrVkPrimaryCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu, 597 GrVkImage* srcImage, 598 VkImageLayout srcLayout, 599 GrVkTransferBuffer* dstBuffer, 600 uint32_t copyRegionCount, 601 const VkBufferImageCopy* copyRegions) { 602 SkASSERT(fIsActive); 603 SkASSERT(!fActiveRenderPass); 604 this->addResource(srcImage->resource()); 605 this->addResource(dstBuffer->resource()); 606 GR_VK_CALL(gpu->vkInterface(), CmdCopyImageToBuffer(fCmdBuffer, 607 srcImage->image(), 608 srcLayout, 609 dstBuffer->buffer(), 610 copyRegionCount, 611 copyRegions)); 612 } 613 614 void GrVkPrimaryCommandBuffer::copyBufferToImage(const GrVkGpu* gpu, 615 GrVkTransferBuffer* srcBuffer, 616 GrVkImage* dstImage, 617 VkImageLayout dstLayout, 618 uint32_t copyRegionCount, 619 const VkBufferImageCopy* copyRegions) { 620 SkASSERT(fIsActive); 621 SkASSERT(!fActiveRenderPass); 622 this->addResource(srcBuffer->resource()); 623 this->addResource(dstImage->resource()); 624 GR_VK_CALL(gpu->vkInterface(), CmdCopyBufferToImage(fCmdBuffer, 625 srcBuffer->buffer(), 626 dstImage->image(), 627 dstLayout, 628 copyRegionCount, 629 copyRegions)); 630 } 631 632 void GrVkPrimaryCommandBuffer::updateBuffer(GrVkGpu* gpu, 633 GrVkBuffer* dstBuffer, 634 VkDeviceSize dstOffset, 635 VkDeviceSize dataSize, 636 const void* data) { 637 SkASSERT(fIsActive); 638 SkASSERT(!fActiveRenderPass); 639 SkASSERT(0 == (dstOffset & 0x03)); // four byte aligned 640 // TODO: handle larger transfer sizes 641 SkASSERT(dataSize <= 65536); 642 SkASSERT(0 == (dataSize & 0x03)); // four byte aligned 643 this->addResource(dstBuffer->resource()); 644 GR_VK_CALL(gpu->vkInterface(), CmdUpdateBuffer(fCmdBuffer, 645 dstBuffer->buffer(), 646 dstOffset, 647 dataSize, 648 (const uint32_t*) data)); 649 } 650 651 void GrVkPrimaryCommandBuffer::clearColorImage(const GrVkGpu* gpu, 652 GrVkImage* image, 653 const VkClearColorValue* color, 654 uint32_t subRangeCount, 655 const VkImageSubresourceRange* subRanges) { 656 SkASSERT(fIsActive); 657 SkASSERT(!fActiveRenderPass); 658 this->addResource(image->resource()); 659 GR_VK_CALL(gpu->vkInterface(), CmdClearColorImage(fCmdBuffer, 660 image->image(), 661 image->currentLayout(), 662 color, 663 subRangeCount, 664 subRanges)); 665 } 666 667 void GrVkPrimaryCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu, 668 GrVkImage* image, 669 const VkClearDepthStencilValue* color, 670 uint32_t subRangeCount, 671 const VkImageSubresourceRange* subRanges) { 672 SkASSERT(fIsActive); 673 SkASSERT(!fActiveRenderPass); 674 this->addResource(image->resource()); 675 GR_VK_CALL(gpu->vkInterface(), CmdClearDepthStencilImage(fCmdBuffer, 676 image->image(), 677 image->currentLayout(), 678 color, 679 subRangeCount, 680 subRanges)); 681 } 682 683 void GrVkPrimaryCommandBuffer::resolveImage(GrVkGpu* gpu, 684 const GrVkImage& srcImage, 685 const GrVkImage& dstImage, 686 uint32_t regionCount, 687 const VkImageResolve* regions) { 688 SkASSERT(fIsActive); 689 SkASSERT(!fActiveRenderPass); 690 691 this->addResource(srcImage.resource()); 692 this->addResource(dstImage.resource()); 693 694 GR_VK_CALL(gpu->vkInterface(), CmdResolveImage(fCmdBuffer, 695 srcImage.image(), 696 srcImage.currentLayout(), 697 dstImage.image(), 698 dstImage.currentLayout(), 699 regionCount, 700 regions)); 701 } 702 703 void GrVkPrimaryCommandBuffer::onFreeGPUData(const GrVkGpu* gpu) const { 704 SkASSERT(!fActiveRenderPass); 705 // Destroy the fence, if any 706 if (VK_NULL_HANDLE != fSubmitFence) { 707 GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr)); 708 } 709 } 710 711 /////////////////////////////////////////////////////////////////////////////// 712 // SecondaryCommandBuffer 713 //////////////////////////////////////////////////////////////////////////////// 714 715 GrVkSecondaryCommandBuffer* GrVkSecondaryCommandBuffer::Create(const GrVkGpu* gpu, 716 VkCommandPool cmdPool) { 717 const VkCommandBufferAllocateInfo cmdInfo = { 718 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType 719 NULL, // pNext 720 cmdPool, // commandPool 721 VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level 722 1 // bufferCount 723 }; 724 725 VkCommandBuffer cmdBuffer; 726 VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateCommandBuffers(gpu->device(), 727 &cmdInfo, 728 &cmdBuffer)); 729 if (err) { 730 return nullptr; 731 } 732 return new GrVkSecondaryCommandBuffer(cmdBuffer); 733 } 734 735 736 void GrVkSecondaryCommandBuffer::begin(const GrVkGpu* gpu, const GrVkFramebuffer* framebuffer, 737 const GrVkRenderPass* compatibleRenderPass) { 738 SkASSERT(!fIsActive); 739 SkASSERT(compatibleRenderPass); 740 fActiveRenderPass = compatibleRenderPass; 741 742 VkCommandBufferInheritanceInfo inheritanceInfo; 743 memset(&inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); 744 inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; 745 inheritanceInfo.pNext = nullptr; 746 inheritanceInfo.renderPass = fActiveRenderPass->vkRenderPass(); 747 inheritanceInfo.subpass = 0; // Currently only using 1 subpass for each render pass 748 inheritanceInfo.framebuffer = framebuffer ? framebuffer->framebuffer() : VK_NULL_HANDLE; 749 inheritanceInfo.occlusionQueryEnable = false; 750 inheritanceInfo.queryFlags = 0; 751 inheritanceInfo.pipelineStatistics = 0; 752 753 VkCommandBufferBeginInfo cmdBufferBeginInfo; 754 memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 755 cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 756 cmdBufferBeginInfo.pNext = nullptr; 757 cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | 758 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 759 cmdBufferBeginInfo.pInheritanceInfo = &inheritanceInfo; 760 761 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), BeginCommandBuffer(fCmdBuffer, 762 &cmdBufferBeginInfo)); 763 fIsActive = true; 764 } 765 766 void GrVkSecondaryCommandBuffer::end(const GrVkGpu* gpu) { 767 SkASSERT(fIsActive); 768 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), EndCommandBuffer(fCmdBuffer)); 769 this->invalidateState(); 770 fIsActive = false; 771 } 772 773