1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandBuffer.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 11cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 12cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkBuffer.h" 13cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandPool.h" 14cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkFramebuffer.h" 15cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkGpu.h" 16cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkImage.h" 17cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkImageView.h" 18cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipeline.h" 19cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipelineState.h" 20cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipelineState.h" 21cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkRenderPass.h" 22cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkRenderTarget.h" 23cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkUtil.h" 24cb93a386Sopenharmony_ci#ifdef SK_VK_PARTIALRENDER 25cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkDrawAreaManager.h" 26cb93a386Sopenharmony_ci#include "src/gpu/vk/vulkan_header_ext_huawei.h" 27cb93a386Sopenharmony_ci#endif 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_civoid GrVkCommandBuffer::invalidateState() { 30cb93a386Sopenharmony_ci for (auto& boundInputBuffer : fBoundInputBuffers) { 31cb93a386Sopenharmony_ci boundInputBuffer = VK_NULL_HANDLE; 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci fBoundIndexBuffer = VK_NULL_HANDLE; 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci memset(&fCachedViewport, 0, sizeof(VkViewport)); 36cb93a386Sopenharmony_ci fCachedViewport.width = - 1.0f; // Viewport must have a width greater than 0 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci memset(&fCachedScissor, 0, sizeof(VkRect2D)); 39cb93a386Sopenharmony_ci fCachedScissor.offset.x = -1; // Scissor offset must be greater that 0 to be valid 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci for (int i = 0; i < 4; ++i) { 42cb93a386Sopenharmony_ci fCachedBlendConstant[i] = -1.0; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci} 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_civoid GrVkCommandBuffer::freeGPUData(const GrGpu* gpu, VkCommandPool cmdPool) const { 47cb93a386Sopenharmony_ci TRACE_EVENT0("skia.gpu", TRACE_FUNC); 48cb93a386Sopenharmony_ci SkASSERT(!fIsActive); 49cb93a386Sopenharmony_ci SkASSERT(!fTrackedResources.count()); 50cb93a386Sopenharmony_ci SkASSERT(!fTrackedRecycledResources.count()); 51cb93a386Sopenharmony_ci SkASSERT(!fTrackedGpuBuffers.count()); 52cb93a386Sopenharmony_ci SkASSERT(!fTrackedGpuSurfaces.count()); 53cb93a386Sopenharmony_ci SkASSERT(cmdPool != VK_NULL_HANDLE); 54cb93a386Sopenharmony_ci SkASSERT(!this->isWrapped()); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci GrVkGpu* vkGpu = (GrVkGpu*)gpu; 57cb93a386Sopenharmony_ci GR_VK_CALL(vkGpu->vkInterface(), FreeCommandBuffers(vkGpu->device(), cmdPool, 1, &fCmdBuffer)); 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci this->onFreeGPUData(vkGpu); 60cb93a386Sopenharmony_ci} 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_civoid GrVkCommandBuffer::releaseResources() { 63cb93a386Sopenharmony_ci TRACE_EVENT0("skia.gpu", TRACE_FUNC); 64cb93a386Sopenharmony_ci SkASSERT(!fIsActive || this->isWrapped()); 65cb93a386Sopenharmony_ci fTrackedResources.reset(); 66cb93a386Sopenharmony_ci fTrackedRecycledResources.reset(); 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci fTrackedGpuBuffers.reset(); 69cb93a386Sopenharmony_ci fTrackedGpuSurfaces.reset(); 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci this->invalidateState(); 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci this->onReleaseResources(); 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 77cb93a386Sopenharmony_ci// CommandBuffer commands 78cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_civoid GrVkCommandBuffer::pipelineBarrier(const GrVkGpu* gpu, 81cb93a386Sopenharmony_ci const GrManagedResource* resource, 82cb93a386Sopenharmony_ci VkPipelineStageFlags srcStageMask, 83cb93a386Sopenharmony_ci VkPipelineStageFlags dstStageMask, 84cb93a386Sopenharmony_ci bool byRegion, 85cb93a386Sopenharmony_ci BarrierType barrierType, 86cb93a386Sopenharmony_ci void* barrier) { 87cb93a386Sopenharmony_ci SkASSERT(!this->isWrapped()); 88cb93a386Sopenharmony_ci SkASSERT(fIsActive); 89cb93a386Sopenharmony_ci#ifdef SK_DEBUG 90cb93a386Sopenharmony_ci // For images we can have barriers inside of render passes but they require us to add more 91cb93a386Sopenharmony_ci // support in subpasses which need self dependencies to have barriers inside them. Also, we can 92cb93a386Sopenharmony_ci // never have buffer barriers inside of a render pass. For now we will just assert that we are 93cb93a386Sopenharmony_ci // not in a render pass. 94cb93a386Sopenharmony_ci bool isValidSubpassBarrier = false; 95cb93a386Sopenharmony_ci if (barrierType == kImageMemory_BarrierType) { 96cb93a386Sopenharmony_ci VkImageMemoryBarrier* imgBarrier = static_cast<VkImageMemoryBarrier*>(barrier); 97cb93a386Sopenharmony_ci isValidSubpassBarrier = (imgBarrier->newLayout == imgBarrier->oldLayout) && 98cb93a386Sopenharmony_ci (imgBarrier->srcQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) && 99cb93a386Sopenharmony_ci (imgBarrier->dstQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) && 100cb93a386Sopenharmony_ci byRegion; 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass || isValidSubpassBarrier); 103cb93a386Sopenharmony_ci#endif 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci if (barrierType == kBufferMemory_BarrierType) { 106cb93a386Sopenharmony_ci const VkBufferMemoryBarrier* barrierPtr = static_cast<VkBufferMemoryBarrier*>(barrier); 107cb93a386Sopenharmony_ci fBufferBarriers.push_back(*barrierPtr); 108cb93a386Sopenharmony_ci } else { 109cb93a386Sopenharmony_ci SkASSERT(barrierType == kImageMemory_BarrierType); 110cb93a386Sopenharmony_ci const VkImageMemoryBarrier* barrierPtr = static_cast<VkImageMemoryBarrier*>(barrier); 111cb93a386Sopenharmony_ci // We need to check if we are adding a pipeline barrier that covers part of the same 112cb93a386Sopenharmony_ci // subresource range as a barrier that is already in current batch. If it does, then we must 113cb93a386Sopenharmony_ci // submit the first batch because the vulkan spec does not define a specific ordering for 114cb93a386Sopenharmony_ci // barriers submitted in the same batch. 115cb93a386Sopenharmony_ci // TODO: Look if we can gain anything by merging barriers together instead of submitting 116cb93a386Sopenharmony_ci // the old ones. 117cb93a386Sopenharmony_ci for (int i = 0; i < fImageBarriers.count(); ++i) { 118cb93a386Sopenharmony_ci VkImageMemoryBarrier& currentBarrier = fImageBarriers[i]; 119cb93a386Sopenharmony_ci if (barrierPtr->image == currentBarrier.image) { 120cb93a386Sopenharmony_ci const VkImageSubresourceRange newRange = barrierPtr->subresourceRange; 121cb93a386Sopenharmony_ci const VkImageSubresourceRange oldRange = currentBarrier.subresourceRange; 122cb93a386Sopenharmony_ci SkASSERT(newRange.aspectMask == oldRange.aspectMask); 123cb93a386Sopenharmony_ci SkASSERT(newRange.baseArrayLayer == oldRange.baseArrayLayer); 124cb93a386Sopenharmony_ci SkASSERT(newRange.layerCount == oldRange.layerCount); 125cb93a386Sopenharmony_ci uint32_t newStart = newRange.baseMipLevel; 126cb93a386Sopenharmony_ci uint32_t newEnd = newRange.baseMipLevel + newRange.levelCount - 1; 127cb93a386Sopenharmony_ci uint32_t oldStart = oldRange.baseMipLevel; 128cb93a386Sopenharmony_ci uint32_t oldEnd = oldRange.baseMipLevel + oldRange.levelCount - 1; 129cb93a386Sopenharmony_ci if (std::max(newStart, oldStart) <= std::min(newEnd, oldEnd)) { 130cb93a386Sopenharmony_ci this->submitPipelineBarriers(gpu); 131cb93a386Sopenharmony_ci break; 132cb93a386Sopenharmony_ci } 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci fImageBarriers.push_back(*barrierPtr); 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci fBarriersByRegion |= byRegion; 138cb93a386Sopenharmony_ci fSrcStageMask = fSrcStageMask | srcStageMask; 139cb93a386Sopenharmony_ci fDstStageMask = fDstStageMask | dstStageMask; 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci fHasWork = true; 142cb93a386Sopenharmony_ci if (resource) { 143cb93a386Sopenharmony_ci this->addResource(resource); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci if (fActiveRenderPass) { 146cb93a386Sopenharmony_ci this->submitPipelineBarriers(gpu, true); 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci} 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_civoid GrVkCommandBuffer::submitPipelineBarriers(const GrVkGpu* gpu, bool forSelfDependency) { 151cb93a386Sopenharmony_ci SkASSERT(fIsActive); 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci // Currently we never submit a pipeline barrier without at least one memory barrier. 154cb93a386Sopenharmony_ci if (fBufferBarriers.count() || fImageBarriers.count()) { 155cb93a386Sopenharmony_ci // For images we can have barriers inside of render passes but they require us to add more 156cb93a386Sopenharmony_ci // support in subpasses which need self dependencies to have barriers inside them. Also, we 157cb93a386Sopenharmony_ci // can never have buffer barriers inside of a render pass. For now we will just assert that 158cb93a386Sopenharmony_ci // we are not in a render pass. 159cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass || forSelfDependency); 160cb93a386Sopenharmony_ci SkASSERT(!this->isWrapped()); 161cb93a386Sopenharmony_ci SkASSERT(fSrcStageMask && fDstStageMask); 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci VkDependencyFlags dependencyFlags = fBarriersByRegion ? VK_DEPENDENCY_BY_REGION_BIT : 0; 164cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdPipelineBarrier( 165cb93a386Sopenharmony_ci fCmdBuffer, fSrcStageMask, fDstStageMask, dependencyFlags, 0, nullptr, 166cb93a386Sopenharmony_ci fBufferBarriers.count(), fBufferBarriers.begin(), 167cb93a386Sopenharmony_ci fImageBarriers.count(), fImageBarriers.begin())); 168cb93a386Sopenharmony_ci fBufferBarriers.reset(); 169cb93a386Sopenharmony_ci fImageBarriers.reset(); 170cb93a386Sopenharmony_ci fBarriersByRegion = false; 171cb93a386Sopenharmony_ci fSrcStageMask = 0; 172cb93a386Sopenharmony_ci fDstStageMask = 0; 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci SkASSERT(!fBufferBarriers.count()); 175cb93a386Sopenharmony_ci SkASSERT(!fImageBarriers.count()); 176cb93a386Sopenharmony_ci SkASSERT(!fBarriersByRegion); 177cb93a386Sopenharmony_ci SkASSERT(!fSrcStageMask); 178cb93a386Sopenharmony_ci SkASSERT(!fDstStageMask); 179cb93a386Sopenharmony_ci} 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_civoid GrVkCommandBuffer::bindInputBuffer(GrVkGpu* gpu, uint32_t binding, 182cb93a386Sopenharmony_ci sk_sp<const GrBuffer> buffer) { 183cb93a386Sopenharmony_ci VkBuffer vkBuffer = static_cast<const GrVkBuffer*>(buffer.get())->vkBuffer(); 184cb93a386Sopenharmony_ci SkASSERT(VK_NULL_HANDLE != vkBuffer); 185cb93a386Sopenharmony_ci SkASSERT(binding < kMaxInputBuffers); 186cb93a386Sopenharmony_ci // TODO: once vbuffer->offset() no longer always returns 0, we will need to track the offset 187cb93a386Sopenharmony_ci // to know if we can skip binding or not. 188cb93a386Sopenharmony_ci if (vkBuffer != fBoundInputBuffers[binding]) { 189cb93a386Sopenharmony_ci VkDeviceSize offset = 0; 190cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdBindVertexBuffers(fCmdBuffer, 191cb93a386Sopenharmony_ci binding, 192cb93a386Sopenharmony_ci 1, 193cb93a386Sopenharmony_ci &vkBuffer, 194cb93a386Sopenharmony_ci &offset)); 195cb93a386Sopenharmony_ci fBoundInputBuffers[binding] = vkBuffer; 196cb93a386Sopenharmony_ci this->addGrBuffer(std::move(buffer)); 197cb93a386Sopenharmony_ci } 198cb93a386Sopenharmony_ci} 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_civoid GrVkCommandBuffer::bindIndexBuffer(GrVkGpu* gpu, sk_sp<const GrBuffer> buffer) { 201cb93a386Sopenharmony_ci VkBuffer vkBuffer = static_cast<const GrVkBuffer*>(buffer.get())->vkBuffer(); 202cb93a386Sopenharmony_ci SkASSERT(VK_NULL_HANDLE != vkBuffer); 203cb93a386Sopenharmony_ci // TODO: once ibuffer->offset() no longer always returns 0, we will need to track the offset 204cb93a386Sopenharmony_ci // to know if we can skip binding or not. 205cb93a386Sopenharmony_ci if (vkBuffer != fBoundIndexBuffer) { 206cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdBindIndexBuffer(fCmdBuffer, 207cb93a386Sopenharmony_ci vkBuffer, /*offset=*/0, 208cb93a386Sopenharmony_ci VK_INDEX_TYPE_UINT16)); 209cb93a386Sopenharmony_ci fBoundIndexBuffer = vkBuffer; 210cb93a386Sopenharmony_ci this->addGrBuffer(std::move(buffer)); 211cb93a386Sopenharmony_ci } 212cb93a386Sopenharmony_ci} 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_civoid GrVkCommandBuffer::clearAttachments(const GrVkGpu* gpu, 215cb93a386Sopenharmony_ci int numAttachments, 216cb93a386Sopenharmony_ci const VkClearAttachment* attachments, 217cb93a386Sopenharmony_ci int numRects, 218cb93a386Sopenharmony_ci const VkClearRect* clearRects) { 219cb93a386Sopenharmony_ci SkASSERT(fIsActive); 220cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass); 221cb93a386Sopenharmony_ci SkASSERT(numAttachments > 0); 222cb93a386Sopenharmony_ci SkASSERT(numRects > 0); 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci this->addingWork(gpu); 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci#ifdef SK_DEBUG 227cb93a386Sopenharmony_ci for (int i = 0; i < numAttachments; ++i) { 228cb93a386Sopenharmony_ci if (attachments[i].aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { 229cb93a386Sopenharmony_ci uint32_t testIndex; 230cb93a386Sopenharmony_ci SkAssertResult(fActiveRenderPass->colorAttachmentIndex(&testIndex)); 231cb93a386Sopenharmony_ci SkASSERT(testIndex == attachments[i].colorAttachment); 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci } 234cb93a386Sopenharmony_ci#endif 235cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdClearAttachments(fCmdBuffer, 236cb93a386Sopenharmony_ci numAttachments, 237cb93a386Sopenharmony_ci attachments, 238cb93a386Sopenharmony_ci numRects, 239cb93a386Sopenharmony_ci clearRects)); 240cb93a386Sopenharmony_ci if (gpu->vkCaps().mustInvalidatePrimaryCmdBufferStateAfterClearAttachments()) { 241cb93a386Sopenharmony_ci this->invalidateState(); 242cb93a386Sopenharmony_ci } 243cb93a386Sopenharmony_ci} 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_civoid GrVkCommandBuffer::bindDescriptorSets(const GrVkGpu* gpu, 246cb93a386Sopenharmony_ci VkPipelineLayout layout, 247cb93a386Sopenharmony_ci uint32_t firstSet, 248cb93a386Sopenharmony_ci uint32_t setCount, 249cb93a386Sopenharmony_ci const VkDescriptorSet* descriptorSets, 250cb93a386Sopenharmony_ci uint32_t dynamicOffsetCount, 251cb93a386Sopenharmony_ci const uint32_t* dynamicOffsets) { 252cb93a386Sopenharmony_ci SkASSERT(fIsActive); 253cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdBindDescriptorSets(fCmdBuffer, 254cb93a386Sopenharmony_ci VK_PIPELINE_BIND_POINT_GRAPHICS, 255cb93a386Sopenharmony_ci layout, 256cb93a386Sopenharmony_ci firstSet, 257cb93a386Sopenharmony_ci setCount, 258cb93a386Sopenharmony_ci descriptorSets, 259cb93a386Sopenharmony_ci dynamicOffsetCount, 260cb93a386Sopenharmony_ci dynamicOffsets)); 261cb93a386Sopenharmony_ci} 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_civoid GrVkCommandBuffer::bindPipeline(const GrVkGpu* gpu, sk_sp<const GrVkPipeline> pipeline) { 264cb93a386Sopenharmony_ci SkASSERT(fIsActive); 265cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdBindPipeline(fCmdBuffer, 266cb93a386Sopenharmony_ci VK_PIPELINE_BIND_POINT_GRAPHICS, 267cb93a386Sopenharmony_ci pipeline->pipeline())); 268cb93a386Sopenharmony_ci this->addResource(std::move(pipeline)); 269cb93a386Sopenharmony_ci} 270cb93a386Sopenharmony_ci 271cb93a386Sopenharmony_civoid GrVkCommandBuffer::pushConstants(const GrVkGpu* gpu, VkPipelineLayout layout, 272cb93a386Sopenharmony_ci VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, 273cb93a386Sopenharmony_ci const void* values) { 274cb93a386Sopenharmony_ci SkASSERT(fIsActive); 275cb93a386Sopenharmony_ci // offset and size must be a multiple of 4 276cb93a386Sopenharmony_ci SkASSERT(!SkToBool(offset & 0x3)); 277cb93a386Sopenharmony_ci SkASSERT(!SkToBool(size & 0x3)); 278cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdPushConstants(fCmdBuffer, 279cb93a386Sopenharmony_ci layout, 280cb93a386Sopenharmony_ci stageFlags, 281cb93a386Sopenharmony_ci offset, 282cb93a386Sopenharmony_ci size, 283cb93a386Sopenharmony_ci values)); 284cb93a386Sopenharmony_ci} 285cb93a386Sopenharmony_ci 286cb93a386Sopenharmony_civoid GrVkCommandBuffer::drawIndexed(const GrVkGpu* gpu, 287cb93a386Sopenharmony_ci uint32_t indexCount, 288cb93a386Sopenharmony_ci uint32_t instanceCount, 289cb93a386Sopenharmony_ci uint32_t firstIndex, 290cb93a386Sopenharmony_ci int32_t vertexOffset, 291cb93a386Sopenharmony_ci uint32_t firstInstance) { 292cb93a386Sopenharmony_ci SkASSERT(fIsActive); 293cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass); 294cb93a386Sopenharmony_ci this->addingWork(gpu); 295cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexed(fCmdBuffer, 296cb93a386Sopenharmony_ci indexCount, 297cb93a386Sopenharmony_ci instanceCount, 298cb93a386Sopenharmony_ci firstIndex, 299cb93a386Sopenharmony_ci vertexOffset, 300cb93a386Sopenharmony_ci firstInstance)); 301cb93a386Sopenharmony_ci} 302cb93a386Sopenharmony_ci 303cb93a386Sopenharmony_civoid GrVkCommandBuffer::draw(const GrVkGpu* gpu, 304cb93a386Sopenharmony_ci uint32_t vertexCount, 305cb93a386Sopenharmony_ci uint32_t instanceCount, 306cb93a386Sopenharmony_ci uint32_t firstVertex, 307cb93a386Sopenharmony_ci uint32_t firstInstance) { 308cb93a386Sopenharmony_ci SkASSERT(fIsActive); 309cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass); 310cb93a386Sopenharmony_ci this->addingWork(gpu); 311cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdDraw(fCmdBuffer, 312cb93a386Sopenharmony_ci vertexCount, 313cb93a386Sopenharmony_ci instanceCount, 314cb93a386Sopenharmony_ci firstVertex, 315cb93a386Sopenharmony_ci firstInstance)); 316cb93a386Sopenharmony_ci} 317cb93a386Sopenharmony_ci 318cb93a386Sopenharmony_civoid GrVkCommandBuffer::drawIndirect(const GrVkGpu* gpu, 319cb93a386Sopenharmony_ci sk_sp<const GrBuffer> indirectBuffer, 320cb93a386Sopenharmony_ci VkDeviceSize offset, 321cb93a386Sopenharmony_ci uint32_t drawCount, 322cb93a386Sopenharmony_ci uint32_t stride) { 323cb93a386Sopenharmony_ci SkASSERT(fIsActive); 324cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass); 325cb93a386Sopenharmony_ci SkASSERT(!indirectBuffer->isCpuBuffer()); 326cb93a386Sopenharmony_ci this->addingWork(gpu); 327cb93a386Sopenharmony_ci VkBuffer vkBuffer = static_cast<const GrVkBuffer*>(indirectBuffer.get())->vkBuffer(); 328cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdDrawIndirect(fCmdBuffer, 329cb93a386Sopenharmony_ci vkBuffer, 330cb93a386Sopenharmony_ci offset, 331cb93a386Sopenharmony_ci drawCount, 332cb93a386Sopenharmony_ci stride)); 333cb93a386Sopenharmony_ci this->addGrBuffer(std::move(indirectBuffer)); 334cb93a386Sopenharmony_ci} 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_civoid GrVkCommandBuffer::drawIndexedIndirect(const GrVkGpu* gpu, 337cb93a386Sopenharmony_ci sk_sp<const GrBuffer> indirectBuffer, 338cb93a386Sopenharmony_ci VkDeviceSize offset, 339cb93a386Sopenharmony_ci uint32_t drawCount, 340cb93a386Sopenharmony_ci uint32_t stride) { 341cb93a386Sopenharmony_ci SkASSERT(fIsActive); 342cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass); 343cb93a386Sopenharmony_ci SkASSERT(!indirectBuffer->isCpuBuffer()); 344cb93a386Sopenharmony_ci this->addingWork(gpu); 345cb93a386Sopenharmony_ci VkBuffer vkBuffer = static_cast<const GrVkBuffer*>(indirectBuffer.get())->vkBuffer(); 346cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexedIndirect(fCmdBuffer, 347cb93a386Sopenharmony_ci vkBuffer, 348cb93a386Sopenharmony_ci offset, 349cb93a386Sopenharmony_ci drawCount, 350cb93a386Sopenharmony_ci stride)); 351cb93a386Sopenharmony_ci this->addGrBuffer(std::move(indirectBuffer)); 352cb93a386Sopenharmony_ci} 353cb93a386Sopenharmony_ci 354cb93a386Sopenharmony_civoid GrVkCommandBuffer::setViewport(const GrVkGpu* gpu, 355cb93a386Sopenharmony_ci uint32_t firstViewport, 356cb93a386Sopenharmony_ci uint32_t viewportCount, 357cb93a386Sopenharmony_ci const VkViewport* viewports) { 358cb93a386Sopenharmony_ci SkASSERT(fIsActive); 359cb93a386Sopenharmony_ci SkASSERT(1 == viewportCount); 360cb93a386Sopenharmony_ci if (0 != memcmp(viewports, &fCachedViewport, sizeof(VkViewport))) { 361cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdSetViewport(fCmdBuffer, 362cb93a386Sopenharmony_ci firstViewport, 363cb93a386Sopenharmony_ci viewportCount, 364cb93a386Sopenharmony_ci viewports)); 365cb93a386Sopenharmony_ci fCachedViewport = viewports[0]; 366cb93a386Sopenharmony_ci } 367cb93a386Sopenharmony_ci} 368cb93a386Sopenharmony_ci 369cb93a386Sopenharmony_civoid GrVkCommandBuffer::setScissor(const GrVkGpu* gpu, 370cb93a386Sopenharmony_ci uint32_t firstScissor, 371cb93a386Sopenharmony_ci uint32_t scissorCount, 372cb93a386Sopenharmony_ci const VkRect2D* scissors) { 373cb93a386Sopenharmony_ci SkASSERT(fIsActive); 374cb93a386Sopenharmony_ci SkASSERT(1 == scissorCount); 375cb93a386Sopenharmony_ci if (0 != memcmp(scissors, &fCachedScissor, sizeof(VkRect2D))) { 376cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdSetScissor(fCmdBuffer, 377cb93a386Sopenharmony_ci firstScissor, 378cb93a386Sopenharmony_ci scissorCount, 379cb93a386Sopenharmony_ci scissors)); 380cb93a386Sopenharmony_ci fCachedScissor = scissors[0]; 381cb93a386Sopenharmony_ci } 382cb93a386Sopenharmony_ci} 383cb93a386Sopenharmony_ci 384cb93a386Sopenharmony_civoid GrVkCommandBuffer::setBlendConstants(const GrVkGpu* gpu, 385cb93a386Sopenharmony_ci const float blendConstants[4]) { 386cb93a386Sopenharmony_ci SkASSERT(fIsActive); 387cb93a386Sopenharmony_ci if (0 != memcmp(blendConstants, fCachedBlendConstant, 4 * sizeof(float))) { 388cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdSetBlendConstants(fCmdBuffer, blendConstants)); 389cb93a386Sopenharmony_ci memcpy(fCachedBlendConstant, blendConstants, 4 * sizeof(float)); 390cb93a386Sopenharmony_ci } 391cb93a386Sopenharmony_ci} 392cb93a386Sopenharmony_ci 393cb93a386Sopenharmony_civoid GrVkCommandBuffer::addingWork(const GrVkGpu* gpu) { 394cb93a386Sopenharmony_ci this->submitPipelineBarriers(gpu); 395cb93a386Sopenharmony_ci fHasWork = true; 396cb93a386Sopenharmony_ci} 397cb93a386Sopenharmony_ci 398cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 399cb93a386Sopenharmony_ci// PrimaryCommandBuffer 400cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 401cb93a386Sopenharmony_ciGrVkPrimaryCommandBuffer::~GrVkPrimaryCommandBuffer() { 402cb93a386Sopenharmony_ci // Should have ended any render pass we're in the middle of 403cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 404cb93a386Sopenharmony_ci} 405cb93a386Sopenharmony_ci 406cb93a386Sopenharmony_ciGrVkPrimaryCommandBuffer* GrVkPrimaryCommandBuffer::Create(GrVkGpu* gpu, 407cb93a386Sopenharmony_ci VkCommandPool cmdPool) { 408cb93a386Sopenharmony_ci const VkCommandBufferAllocateInfo cmdInfo = { 409cb93a386Sopenharmony_ci VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType 410cb93a386Sopenharmony_ci nullptr, // pNext 411cb93a386Sopenharmony_ci cmdPool, // commandPool 412cb93a386Sopenharmony_ci VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 413cb93a386Sopenharmony_ci 1 // bufferCount 414cb93a386Sopenharmony_ci }; 415cb93a386Sopenharmony_ci 416cb93a386Sopenharmony_ci VkCommandBuffer cmdBuffer; 417cb93a386Sopenharmony_ci VkResult err; 418cb93a386Sopenharmony_ci GR_VK_CALL_RESULT(gpu, err, AllocateCommandBuffers(gpu->device(), &cmdInfo, &cmdBuffer)); 419cb93a386Sopenharmony_ci if (err) { 420cb93a386Sopenharmony_ci return nullptr; 421cb93a386Sopenharmony_ci } 422cb93a386Sopenharmony_ci return new GrVkPrimaryCommandBuffer(cmdBuffer); 423cb93a386Sopenharmony_ci} 424cb93a386Sopenharmony_ci 425cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::begin(GrVkGpu* gpu) { 426cb93a386Sopenharmony_ci SkASSERT(!fIsActive); 427cb93a386Sopenharmony_ci VkCommandBufferBeginInfo cmdBufferBeginInfo; 428cb93a386Sopenharmony_ci memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 429cb93a386Sopenharmony_ci cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 430cb93a386Sopenharmony_ci cmdBufferBeginInfo.pNext = nullptr; 431cb93a386Sopenharmony_ci cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 432cb93a386Sopenharmony_ci cmdBufferBeginInfo.pInheritanceInfo = nullptr; 433cb93a386Sopenharmony_ci 434cb93a386Sopenharmony_ci GR_VK_CALL_ERRCHECK(gpu, BeginCommandBuffer(fCmdBuffer, &cmdBufferBeginInfo)); 435cb93a386Sopenharmony_ci fIsActive = true; 436cb93a386Sopenharmony_ci} 437cb93a386Sopenharmony_ci 438cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::end(GrVkGpu* gpu, bool abandoningBuffer) { 439cb93a386Sopenharmony_ci SkASSERT(fIsActive); 440cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 441cb93a386Sopenharmony_ci 442cb93a386Sopenharmony_ci // If we are in the process of abandoning the context then the GrResourceCache will have freed 443cb93a386Sopenharmony_ci // all resources before destroying the GrVkGpu. When we destroy the GrVkGpu we call end on the 444cb93a386Sopenharmony_ci // command buffer to keep all our state tracking consistent. However, the vulkan validation 445cb93a386Sopenharmony_ci // layers complain about calling end on a command buffer that contains resources that have 446cb93a386Sopenharmony_ci // already been deleted. From the vulkan API it isn't required to end the command buffer to 447cb93a386Sopenharmony_ci // delete it, so we just skip the vulkan API calls and update our own state tracking. 448cb93a386Sopenharmony_ci if (!abandoningBuffer) { 449cb93a386Sopenharmony_ci this->submitPipelineBarriers(gpu); 450cb93a386Sopenharmony_ci 451cb93a386Sopenharmony_ci GR_VK_CALL_ERRCHECK(gpu, EndCommandBuffer(fCmdBuffer)); 452cb93a386Sopenharmony_ci } 453cb93a386Sopenharmony_ci this->invalidateState(); 454cb93a386Sopenharmony_ci fIsActive = false; 455cb93a386Sopenharmony_ci fHasWork = false; 456cb93a386Sopenharmony_ci} 457cb93a386Sopenharmony_ci 458cb93a386Sopenharmony_cibool GrVkPrimaryCommandBuffer::beginRenderPass(GrVkGpu* gpu, 459cb93a386Sopenharmony_ci const GrVkRenderPass* renderPass, 460cb93a386Sopenharmony_ci sk_sp<const GrVkFramebuffer> framebuffer, 461cb93a386Sopenharmony_ci const VkClearValue clearValues[], 462cb93a386Sopenharmony_ci const GrSurface* target, 463cb93a386Sopenharmony_ci const SkIRect& bounds, 464cb93a386Sopenharmony_ci bool forSecondaryCB) { 465cb93a386Sopenharmony_ci SkASSERT(fIsActive); 466cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 467cb93a386Sopenharmony_ci 468cb93a386Sopenharmony_ci SkASSERT(framebuffer); 469cb93a386Sopenharmony_ci 470cb93a386Sopenharmony_ci this->addingWork(gpu); 471cb93a386Sopenharmony_ci 472cb93a386Sopenharmony_ci VkRenderPassBeginInfo beginInfo; 473cb93a386Sopenharmony_ci VkRect2D renderArea; 474cb93a386Sopenharmony_ci renderArea.offset = { bounds.fLeft , bounds.fTop }; 475cb93a386Sopenharmony_ci renderArea.extent = { (uint32_t)bounds.width(), (uint32_t)bounds.height() }; 476cb93a386Sopenharmony_ci 477cb93a386Sopenharmony_ci memset(&beginInfo, 0, sizeof(VkRenderPassBeginInfo)); 478cb93a386Sopenharmony_ci beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 479cb93a386Sopenharmony_ci beginInfo.pNext = nullptr; 480cb93a386Sopenharmony_ci beginInfo.renderPass = renderPass->vkRenderPass(); 481cb93a386Sopenharmony_ci beginInfo.framebuffer = framebuffer->framebuffer(); 482cb93a386Sopenharmony_ci beginInfo.renderArea = renderArea; 483cb93a386Sopenharmony_ci beginInfo.clearValueCount = renderPass->clearValueCount(); 484cb93a386Sopenharmony_ci beginInfo.pClearValues = clearValues; 485cb93a386Sopenharmony_ci 486cb93a386Sopenharmony_ci VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS 487cb93a386Sopenharmony_ci : VK_SUBPASS_CONTENTS_INLINE; 488cb93a386Sopenharmony_ci 489cb93a386Sopenharmony_ci#ifdef SK_VK_PARTIALRENDER 490cb93a386Sopenharmony_ci VkRenderPassDamageRegionBeginInfo renderPassDamageRegionBeginInfo {}; 491cb93a386Sopenharmony_ci std::vector<VkRect2D> regions; 492cb93a386Sopenharmony_ci 493cb93a386Sopenharmony_ci if (target) { 494cb93a386Sopenharmony_ci GrRenderTarget* renderTarget = const_cast<GrRenderTarget*>(target->asRenderTarget()); 495cb93a386Sopenharmony_ci std::vector<SkIRect>& renderAreas = GrVkDrawAreaManager::getInstance().getDrawingArea(renderTarget); 496cb93a386Sopenharmony_ci if (!renderAreas.empty()) { 497cb93a386Sopenharmony_ci renderPassDamageRegionBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_DAMAGE_REGION_BEGIN_INFO_TYPE; 498cb93a386Sopenharmony_ci renderPassDamageRegionBeginInfo.pNext = nullptr; 499cb93a386Sopenharmony_ci 500cb93a386Sopenharmony_ci for (auto &rect : renderAreas) { 501cb93a386Sopenharmony_ci VkRect2D vkRect = {{rect.fLeft, rect.fTop}, {rect.width(), rect.height()}}; 502cb93a386Sopenharmony_ci regions.push_back(vkRect); 503cb93a386Sopenharmony_ci } 504cb93a386Sopenharmony_ci 505cb93a386Sopenharmony_ci renderPassDamageRegionBeginInfo.regionCount = static_cast<uint32_t>(regions.size()); 506cb93a386Sopenharmony_ci renderPassDamageRegionBeginInfo.regions = regions.data(); 507cb93a386Sopenharmony_ci beginInfo.pNext = &renderPassDamageRegionBeginInfo; 508cb93a386Sopenharmony_ci } 509cb93a386Sopenharmony_ci } 510cb93a386Sopenharmony_ci#endif 511cb93a386Sopenharmony_ci 512cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents)); 513cb93a386Sopenharmony_ci fActiveRenderPass = renderPass; 514cb93a386Sopenharmony_ci this->addResource(renderPass); 515cb93a386Sopenharmony_ci this->addResource(std::move(framebuffer)); 516cb93a386Sopenharmony_ci this->addGrSurface(sk_ref_sp(target)); 517cb93a386Sopenharmony_ci return true; 518cb93a386Sopenharmony_ci} 519cb93a386Sopenharmony_ci 520cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::endRenderPass(const GrVkGpu* gpu) { 521cb93a386Sopenharmony_ci SkASSERT(fIsActive); 522cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass); 523cb93a386Sopenharmony_ci this->addingWork(gpu); 524cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdEndRenderPass(fCmdBuffer)); 525cb93a386Sopenharmony_ci fActiveRenderPass = nullptr; 526cb93a386Sopenharmony_ci} 527cb93a386Sopenharmony_ci 528cb93a386Sopenharmony_ci 529cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::nexSubpass(GrVkGpu* gpu, bool forSecondaryCB) { 530cb93a386Sopenharmony_ci SkASSERT(fIsActive); 531cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass); 532cb93a386Sopenharmony_ci VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS 533cb93a386Sopenharmony_ci : VK_SUBPASS_CONTENTS_INLINE; 534cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdNextSubpass(fCmdBuffer, contents)); 535cb93a386Sopenharmony_ci} 536cb93a386Sopenharmony_ci 537cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu, 538cb93a386Sopenharmony_ci std::unique_ptr<GrVkSecondaryCommandBuffer> buffer) { 539cb93a386Sopenharmony_ci // The Vulkan spec allows secondary command buffers to be executed on a primary command buffer 540cb93a386Sopenharmony_ci // if the command pools both were created from were created with the same queue family. However, 541cb93a386Sopenharmony_ci // we currently always create them from the same pool. 542cb93a386Sopenharmony_ci SkASSERT(fIsActive); 543cb93a386Sopenharmony_ci SkASSERT(!buffer->fIsActive); 544cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass); 545cb93a386Sopenharmony_ci SkASSERT(fActiveRenderPass->isCompatible(*buffer->fActiveRenderPass)); 546cb93a386Sopenharmony_ci 547cb93a386Sopenharmony_ci this->addingWork(gpu); 548cb93a386Sopenharmony_ci 549cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdExecuteCommands(fCmdBuffer, 1, &buffer->fCmdBuffer)); 550cb93a386Sopenharmony_ci fSecondaryCommandBuffers.push_back(std::move(buffer)); 551cb93a386Sopenharmony_ci // When executing a secondary command buffer all state (besides render pass state) becomes 552cb93a386Sopenharmony_ci // invalidated and must be reset. This includes bound buffers, pipelines, dynamic state, etc. 553cb93a386Sopenharmony_ci this->invalidateState(); 554cb93a386Sopenharmony_ci} 555cb93a386Sopenharmony_ci 556cb93a386Sopenharmony_ci#ifdef SKIA_USE_XEG 557cb93a386Sopenharmony_cistatic std::atomic<uint64_t> g_totalFrameLoad(0); 558cb93a386Sopenharmony_ci 559cb93a386Sopenharmony_ciextern "C" __attribute__((visibility("default"))) void get_frame_load(uint64_t* frame_load) 560cb93a386Sopenharmony_ci{ 561cb93a386Sopenharmony_ci *frame_load = g_totalFrameLoad; 562cb93a386Sopenharmony_ci g_totalFrameLoad.store(0); 563cb93a386Sopenharmony_ci} 564cb93a386Sopenharmony_ci#endif 565cb93a386Sopenharmony_ci 566cb93a386Sopenharmony_cistatic bool submit_to_queue(GrVkGpu* gpu, 567cb93a386Sopenharmony_ci VkQueue queue, 568cb93a386Sopenharmony_ci VkFence fence, 569cb93a386Sopenharmony_ci uint32_t waitCount, 570cb93a386Sopenharmony_ci const VkSemaphore* waitSemaphores, 571cb93a386Sopenharmony_ci const VkPipelineStageFlags* waitStages, 572cb93a386Sopenharmony_ci uint32_t commandBufferCount, 573cb93a386Sopenharmony_ci const VkCommandBuffer* commandBuffers, 574cb93a386Sopenharmony_ci uint32_t signalCount, 575cb93a386Sopenharmony_ci const VkSemaphore* signalSemaphores, 576cb93a386Sopenharmony_ci GrProtected protectedContext) { 577cb93a386Sopenharmony_ci VkProtectedSubmitInfo protectedSubmitInfo; 578cb93a386Sopenharmony_ci if (protectedContext == GrProtected::kYes) { 579cb93a386Sopenharmony_ci memset(&protectedSubmitInfo, 0, sizeof(VkProtectedSubmitInfo)); 580cb93a386Sopenharmony_ci protectedSubmitInfo.sType = VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO; 581cb93a386Sopenharmony_ci protectedSubmitInfo.pNext = nullptr; 582cb93a386Sopenharmony_ci protectedSubmitInfo.protectedSubmit = VK_TRUE; 583cb93a386Sopenharmony_ci } 584cb93a386Sopenharmony_ci 585cb93a386Sopenharmony_ci VkSubmitInfo submitInfo; 586cb93a386Sopenharmony_ci memset(&submitInfo, 0, sizeof(VkSubmitInfo)); 587cb93a386Sopenharmony_ci submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 588cb93a386Sopenharmony_ci submitInfo.pNext = protectedContext == GrProtected::kYes ? &protectedSubmitInfo : nullptr; 589cb93a386Sopenharmony_ci submitInfo.waitSemaphoreCount = waitCount; 590cb93a386Sopenharmony_ci submitInfo.pWaitSemaphores = waitSemaphores; 591cb93a386Sopenharmony_ci submitInfo.pWaitDstStageMask = waitStages; 592cb93a386Sopenharmony_ci submitInfo.commandBufferCount = commandBufferCount; 593cb93a386Sopenharmony_ci submitInfo.pCommandBuffers = commandBuffers; 594cb93a386Sopenharmony_ci submitInfo.signalSemaphoreCount = signalCount; 595cb93a386Sopenharmony_ci submitInfo.pSignalSemaphores = signalSemaphores; 596cb93a386Sopenharmony_ci VkResult result; 597cb93a386Sopenharmony_ci GR_VK_CALL_RESULT(gpu, result, QueueSubmit(queue, 1, &submitInfo, fence)); 598cb93a386Sopenharmony_ci 599cb93a386Sopenharmony_ci#ifdef SKIA_USE_XEG 600cb93a386Sopenharmony_ci if (nullptr != gpu->vkInterface()->fFunctions.fGetPerFrameLoad) { 601cb93a386Sopenharmony_ci uint64_t frameLoad = 0; 602cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), GetPerFrameLoad(commandBufferCount, commandBuffers, &frameLoad)); 603cb93a386Sopenharmony_ci SkDebugf("frameLoad %{public}u\n", frameLoad); 604cb93a386Sopenharmony_ci g_totalFrameLoad += frameLoad; 605cb93a386Sopenharmony_ci } 606cb93a386Sopenharmony_ci#endif 607cb93a386Sopenharmony_ci 608cb93a386Sopenharmony_ci return result == VK_SUCCESS; 609cb93a386Sopenharmony_ci} 610cb93a386Sopenharmony_ci 611cb93a386Sopenharmony_cibool GrVkPrimaryCommandBuffer::submitToQueue( 612cb93a386Sopenharmony_ci GrVkGpu* gpu, 613cb93a386Sopenharmony_ci VkQueue queue, 614cb93a386Sopenharmony_ci SkTArray<GrVkSemaphore::Resource*>& signalSemaphores, 615cb93a386Sopenharmony_ci SkTArray<GrVkSemaphore::Resource*>& waitSemaphores) { 616cb93a386Sopenharmony_ci SkASSERT(!fIsActive); 617cb93a386Sopenharmony_ci 618cb93a386Sopenharmony_ci VkResult err; 619cb93a386Sopenharmony_ci if (VK_NULL_HANDLE == fSubmitFence) { 620cb93a386Sopenharmony_ci VkFenceCreateInfo fenceInfo; 621cb93a386Sopenharmony_ci memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo)); 622cb93a386Sopenharmony_ci fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 623cb93a386Sopenharmony_ci GR_VK_CALL_RESULT(gpu, err, CreateFence(gpu->device(), &fenceInfo, nullptr, 624cb93a386Sopenharmony_ci &fSubmitFence)); 625cb93a386Sopenharmony_ci if (err) { 626cb93a386Sopenharmony_ci fSubmitFence = VK_NULL_HANDLE; 627cb93a386Sopenharmony_ci return false; 628cb93a386Sopenharmony_ci } 629cb93a386Sopenharmony_ci } else { 630cb93a386Sopenharmony_ci // This cannot return DEVICE_LOST so we assert we succeeded. 631cb93a386Sopenharmony_ci GR_VK_CALL_RESULT(gpu, err, ResetFences(gpu->device(), 1, &fSubmitFence)); 632cb93a386Sopenharmony_ci SkASSERT(err == VK_SUCCESS); 633cb93a386Sopenharmony_ci } 634cb93a386Sopenharmony_ci 635cb93a386Sopenharmony_ci int signalCount = signalSemaphores.count(); 636cb93a386Sopenharmony_ci int waitCount = waitSemaphores.count(); 637cb93a386Sopenharmony_ci 638cb93a386Sopenharmony_ci bool submitted = false; 639cb93a386Sopenharmony_ci 640cb93a386Sopenharmony_ci if (0 == signalCount && 0 == waitCount) { 641cb93a386Sopenharmony_ci // This command buffer has no dependent semaphores so we can simply just submit it to the 642cb93a386Sopenharmony_ci // queue with no worries. 643cb93a386Sopenharmony_ci submitted = submit_to_queue( 644cb93a386Sopenharmony_ci gpu, queue, fSubmitFence, 0, nullptr, nullptr, 1, &fCmdBuffer, 0, nullptr, 645cb93a386Sopenharmony_ci gpu->protectedContext() ? GrProtected::kYes : GrProtected::kNo); 646cb93a386Sopenharmony_ci } else { 647cb93a386Sopenharmony_ci SkTArray<VkSemaphore> vkSignalSems(signalCount); 648cb93a386Sopenharmony_ci for (int i = 0; i < signalCount; ++i) { 649cb93a386Sopenharmony_ci if (signalSemaphores[i]->shouldSignal()) { 650cb93a386Sopenharmony_ci this->addResource(signalSemaphores[i]); 651cb93a386Sopenharmony_ci vkSignalSems.push_back(signalSemaphores[i]->semaphore()); 652cb93a386Sopenharmony_ci } 653cb93a386Sopenharmony_ci } 654cb93a386Sopenharmony_ci 655cb93a386Sopenharmony_ci SkTArray<VkSemaphore> vkWaitSems(waitCount); 656cb93a386Sopenharmony_ci SkTArray<VkPipelineStageFlags> vkWaitStages(waitCount); 657cb93a386Sopenharmony_ci for (int i = 0; i < waitCount; ++i) { 658cb93a386Sopenharmony_ci if (waitSemaphores[i]->shouldWait()) { 659cb93a386Sopenharmony_ci this->addResource(waitSemaphores[i]); 660cb93a386Sopenharmony_ci vkWaitSems.push_back(waitSemaphores[i]->semaphore()); 661cb93a386Sopenharmony_ci vkWaitStages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); 662cb93a386Sopenharmony_ci } 663cb93a386Sopenharmony_ci } 664cb93a386Sopenharmony_ci submitted = submit_to_queue(gpu, queue, fSubmitFence, vkWaitSems.count(), 665cb93a386Sopenharmony_ci vkWaitSems.begin(), vkWaitStages.begin(), 1, &fCmdBuffer, 666cb93a386Sopenharmony_ci vkSignalSems.count(), vkSignalSems.begin(), 667cb93a386Sopenharmony_ci gpu->protectedContext() ? GrProtected::kYes : GrProtected::kNo); 668cb93a386Sopenharmony_ci if (submitted) { 669cb93a386Sopenharmony_ci for (int i = 0; i < signalCount; ++i) { 670cb93a386Sopenharmony_ci signalSemaphores[i]->markAsSignaled(); 671cb93a386Sopenharmony_ci } 672cb93a386Sopenharmony_ci for (int i = 0; i < waitCount; ++i) { 673cb93a386Sopenharmony_ci waitSemaphores[i]->markAsWaited(); 674cb93a386Sopenharmony_ci } 675cb93a386Sopenharmony_ci } 676cb93a386Sopenharmony_ci } 677cb93a386Sopenharmony_ci 678cb93a386Sopenharmony_ci if (!submitted) { 679cb93a386Sopenharmony_ci // Destroy the fence or else we will try to wait forever for it to finish. 680cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr)); 681cb93a386Sopenharmony_ci fSubmitFence = VK_NULL_HANDLE; 682cb93a386Sopenharmony_ci return false; 683cb93a386Sopenharmony_ci } 684cb93a386Sopenharmony_ci return true; 685cb93a386Sopenharmony_ci} 686cb93a386Sopenharmony_ci 687cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::forceSync(GrVkGpu* gpu) { 688cb93a386Sopenharmony_ci if (fSubmitFence == VK_NULL_HANDLE) { 689cb93a386Sopenharmony_ci return; 690cb93a386Sopenharmony_ci } 691cb93a386Sopenharmony_ci GR_VK_CALL_ERRCHECK(gpu, WaitForFences(gpu->device(), 1, &fSubmitFence, true, UINT64_MAX)); 692cb93a386Sopenharmony_ci} 693cb93a386Sopenharmony_ci 694cb93a386Sopenharmony_cibool GrVkPrimaryCommandBuffer::finished(GrVkGpu* gpu) { 695cb93a386Sopenharmony_ci SkASSERT(!fIsActive); 696cb93a386Sopenharmony_ci if (VK_NULL_HANDLE == fSubmitFence) { 697cb93a386Sopenharmony_ci return true; 698cb93a386Sopenharmony_ci } 699cb93a386Sopenharmony_ci 700cb93a386Sopenharmony_ci VkResult err; 701cb93a386Sopenharmony_ci GR_VK_CALL_RESULT_NOCHECK(gpu, err, GetFenceStatus(gpu->device(), fSubmitFence)); 702cb93a386Sopenharmony_ci switch (err) { 703cb93a386Sopenharmony_ci case VK_SUCCESS: 704cb93a386Sopenharmony_ci case VK_ERROR_DEVICE_LOST: 705cb93a386Sopenharmony_ci return true; 706cb93a386Sopenharmony_ci 707cb93a386Sopenharmony_ci case VK_NOT_READY: 708cb93a386Sopenharmony_ci return false; 709cb93a386Sopenharmony_ci 710cb93a386Sopenharmony_ci default: 711cb93a386Sopenharmony_ci SkDebugf("Error getting fence status: %d\n", err); 712cb93a386Sopenharmony_ci SK_ABORT("Got an invalid fence status"); 713cb93a386Sopenharmony_ci return false; 714cb93a386Sopenharmony_ci } 715cb93a386Sopenharmony_ci} 716cb93a386Sopenharmony_ci 717cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::addFinishedProc(sk_sp<GrRefCntedCallback> finishedProc) { 718cb93a386Sopenharmony_ci fFinishedProcs.push_back(std::move(finishedProc)); 719cb93a386Sopenharmony_ci} 720cb93a386Sopenharmony_ci 721cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::onReleaseResources() { 722cb93a386Sopenharmony_ci for (int i = 0; i < fSecondaryCommandBuffers.count(); ++i) { 723cb93a386Sopenharmony_ci fSecondaryCommandBuffers[i]->releaseResources(); 724cb93a386Sopenharmony_ci } 725cb93a386Sopenharmony_ci this->callFinishedProcs(); 726cb93a386Sopenharmony_ci} 727cb93a386Sopenharmony_ci 728cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::recycleSecondaryCommandBuffers(GrVkCommandPool* cmdPool) { 729cb93a386Sopenharmony_ci for (int i = 0; i < fSecondaryCommandBuffers.count(); ++i) { 730cb93a386Sopenharmony_ci fSecondaryCommandBuffers[i].release()->recycle(cmdPool); 731cb93a386Sopenharmony_ci } 732cb93a386Sopenharmony_ci fSecondaryCommandBuffers.reset(); 733cb93a386Sopenharmony_ci} 734cb93a386Sopenharmony_ci 735cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::copyImage(const GrVkGpu* gpu, 736cb93a386Sopenharmony_ci GrVkImage* srcImage, 737cb93a386Sopenharmony_ci VkImageLayout srcLayout, 738cb93a386Sopenharmony_ci GrVkImage* dstImage, 739cb93a386Sopenharmony_ci VkImageLayout dstLayout, 740cb93a386Sopenharmony_ci uint32_t copyRegionCount, 741cb93a386Sopenharmony_ci const VkImageCopy* copyRegions) { 742cb93a386Sopenharmony_ci SkASSERT(fIsActive); 743cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 744cb93a386Sopenharmony_ci this->addingWork(gpu); 745cb93a386Sopenharmony_ci this->addResource(srcImage->resource()); 746cb93a386Sopenharmony_ci this->addResource(dstImage->resource()); 747cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdCopyImage(fCmdBuffer, 748cb93a386Sopenharmony_ci srcImage->image(), 749cb93a386Sopenharmony_ci srcLayout, 750cb93a386Sopenharmony_ci dstImage->image(), 751cb93a386Sopenharmony_ci dstLayout, 752cb93a386Sopenharmony_ci copyRegionCount, 753cb93a386Sopenharmony_ci copyRegions)); 754cb93a386Sopenharmony_ci} 755cb93a386Sopenharmony_ci 756cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::blitImage(const GrVkGpu* gpu, 757cb93a386Sopenharmony_ci const GrManagedResource* srcResource, 758cb93a386Sopenharmony_ci VkImage srcImage, 759cb93a386Sopenharmony_ci VkImageLayout srcLayout, 760cb93a386Sopenharmony_ci const GrManagedResource* dstResource, 761cb93a386Sopenharmony_ci VkImage dstImage, 762cb93a386Sopenharmony_ci VkImageLayout dstLayout, 763cb93a386Sopenharmony_ci uint32_t blitRegionCount, 764cb93a386Sopenharmony_ci const VkImageBlit* blitRegions, 765cb93a386Sopenharmony_ci VkFilter filter) { 766cb93a386Sopenharmony_ci SkASSERT(fIsActive); 767cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 768cb93a386Sopenharmony_ci this->addingWork(gpu); 769cb93a386Sopenharmony_ci this->addResource(srcResource); 770cb93a386Sopenharmony_ci this->addResource(dstResource); 771cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdBlitImage(fCmdBuffer, 772cb93a386Sopenharmony_ci srcImage, 773cb93a386Sopenharmony_ci srcLayout, 774cb93a386Sopenharmony_ci dstImage, 775cb93a386Sopenharmony_ci dstLayout, 776cb93a386Sopenharmony_ci blitRegionCount, 777cb93a386Sopenharmony_ci blitRegions, 778cb93a386Sopenharmony_ci filter)); 779cb93a386Sopenharmony_ci} 780cb93a386Sopenharmony_ci 781cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::blitImage(const GrVkGpu* gpu, 782cb93a386Sopenharmony_ci const GrVkImage& srcImage, 783cb93a386Sopenharmony_ci const GrVkImage& dstImage, 784cb93a386Sopenharmony_ci uint32_t blitRegionCount, 785cb93a386Sopenharmony_ci const VkImageBlit* blitRegions, 786cb93a386Sopenharmony_ci VkFilter filter) { 787cb93a386Sopenharmony_ci this->blitImage(gpu, 788cb93a386Sopenharmony_ci srcImage.resource(), 789cb93a386Sopenharmony_ci srcImage.image(), 790cb93a386Sopenharmony_ci srcImage.currentLayout(), 791cb93a386Sopenharmony_ci dstImage.resource(), 792cb93a386Sopenharmony_ci dstImage.image(), 793cb93a386Sopenharmony_ci dstImage.currentLayout(), 794cb93a386Sopenharmony_ci blitRegionCount, 795cb93a386Sopenharmony_ci blitRegions, 796cb93a386Sopenharmony_ci filter); 797cb93a386Sopenharmony_ci} 798cb93a386Sopenharmony_ci 799cb93a386Sopenharmony_ci 800cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::copyImageToBuffer(const GrVkGpu* gpu, 801cb93a386Sopenharmony_ci GrVkImage* srcImage, 802cb93a386Sopenharmony_ci VkImageLayout srcLayout, 803cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> dstBuffer, 804cb93a386Sopenharmony_ci uint32_t copyRegionCount, 805cb93a386Sopenharmony_ci const VkBufferImageCopy* copyRegions) { 806cb93a386Sopenharmony_ci SkASSERT(fIsActive); 807cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 808cb93a386Sopenharmony_ci this->addingWork(gpu); 809cb93a386Sopenharmony_ci GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(dstBuffer.get()); 810cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdCopyImageToBuffer(fCmdBuffer, 811cb93a386Sopenharmony_ci srcImage->image(), 812cb93a386Sopenharmony_ci srcLayout, 813cb93a386Sopenharmony_ci vkBuffer->vkBuffer(), 814cb93a386Sopenharmony_ci copyRegionCount, 815cb93a386Sopenharmony_ci copyRegions)); 816cb93a386Sopenharmony_ci this->addResource(srcImage->resource()); 817cb93a386Sopenharmony_ci this->addGrBuffer(std::move(dstBuffer)); 818cb93a386Sopenharmony_ci} 819cb93a386Sopenharmony_ci 820cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::copyBufferToImage(const GrVkGpu* gpu, 821cb93a386Sopenharmony_ci VkBuffer srcBuffer, 822cb93a386Sopenharmony_ci GrVkImage* dstImage, 823cb93a386Sopenharmony_ci VkImageLayout dstLayout, 824cb93a386Sopenharmony_ci uint32_t copyRegionCount, 825cb93a386Sopenharmony_ci const VkBufferImageCopy* copyRegions) { 826cb93a386Sopenharmony_ci SkASSERT(fIsActive); 827cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 828cb93a386Sopenharmony_ci this->addingWork(gpu); 829cb93a386Sopenharmony_ci 830cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdCopyBufferToImage(fCmdBuffer, 831cb93a386Sopenharmony_ci srcBuffer, 832cb93a386Sopenharmony_ci dstImage->image(), 833cb93a386Sopenharmony_ci dstLayout, 834cb93a386Sopenharmony_ci copyRegionCount, 835cb93a386Sopenharmony_ci copyRegions)); 836cb93a386Sopenharmony_ci this->addResource(dstImage->resource()); 837cb93a386Sopenharmony_ci} 838cb93a386Sopenharmony_ci 839cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::copyBuffer(GrVkGpu* gpu, 840cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> srcBuffer, 841cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> dstBuffer, 842cb93a386Sopenharmony_ci uint32_t regionCount, 843cb93a386Sopenharmony_ci const VkBufferCopy* regions) { 844cb93a386Sopenharmony_ci SkASSERT(fIsActive); 845cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 846cb93a386Sopenharmony_ci this->addingWork(gpu); 847cb93a386Sopenharmony_ci#ifdef SK_DEBUG 848cb93a386Sopenharmony_ci for (uint32_t i = 0; i < regionCount; ++i) { 849cb93a386Sopenharmony_ci const VkBufferCopy& region = regions[i]; 850cb93a386Sopenharmony_ci SkASSERT(region.size > 0); 851cb93a386Sopenharmony_ci SkASSERT(region.srcOffset < srcBuffer->size()); 852cb93a386Sopenharmony_ci SkASSERT(region.dstOffset < dstBuffer->size()); 853cb93a386Sopenharmony_ci SkASSERT(region.srcOffset + region.size <= srcBuffer->size()); 854cb93a386Sopenharmony_ci SkASSERT(region.dstOffset + region.size <= dstBuffer->size()); 855cb93a386Sopenharmony_ci } 856cb93a386Sopenharmony_ci#endif 857cb93a386Sopenharmony_ci 858cb93a386Sopenharmony_ci const GrVkBuffer* srcVk = static_cast<GrVkBuffer*>(srcBuffer.get()); 859cb93a386Sopenharmony_ci const GrVkBuffer* dstVk = static_cast<GrVkBuffer*>(dstBuffer.get()); 860cb93a386Sopenharmony_ci 861cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdCopyBuffer(fCmdBuffer, 862cb93a386Sopenharmony_ci srcVk->vkBuffer(), 863cb93a386Sopenharmony_ci dstVk->vkBuffer(), 864cb93a386Sopenharmony_ci regionCount, 865cb93a386Sopenharmony_ci regions)); 866cb93a386Sopenharmony_ci this->addGrBuffer(std::move(srcBuffer)); 867cb93a386Sopenharmony_ci this->addGrBuffer(std::move(dstBuffer)); 868cb93a386Sopenharmony_ci} 869cb93a386Sopenharmony_ci 870cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::updateBuffer(GrVkGpu* gpu, 871cb93a386Sopenharmony_ci sk_sp<GrVkBuffer> dstBuffer, 872cb93a386Sopenharmony_ci VkDeviceSize dstOffset, 873cb93a386Sopenharmony_ci VkDeviceSize dataSize, 874cb93a386Sopenharmony_ci const void* data) { 875cb93a386Sopenharmony_ci SkASSERT(fIsActive); 876cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 877cb93a386Sopenharmony_ci SkASSERT(0 == (dstOffset & 0x03)); // four byte aligned 878cb93a386Sopenharmony_ci // TODO: handle larger transfer sizes 879cb93a386Sopenharmony_ci SkASSERT(dataSize <= 65536); 880cb93a386Sopenharmony_ci SkASSERT(0 == (dataSize & 0x03)); // four byte aligned 881cb93a386Sopenharmony_ci this->addingWork(gpu); 882cb93a386Sopenharmony_ci GR_VK_CALL( 883cb93a386Sopenharmony_ci gpu->vkInterface(), 884cb93a386Sopenharmony_ci CmdUpdateBuffer( 885cb93a386Sopenharmony_ci fCmdBuffer, dstBuffer->vkBuffer(), dstOffset, dataSize, (const uint32_t*)data)); 886cb93a386Sopenharmony_ci this->addGrBuffer(std::move(dstBuffer)); 887cb93a386Sopenharmony_ci} 888cb93a386Sopenharmony_ci 889cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::clearColorImage(const GrVkGpu* gpu, 890cb93a386Sopenharmony_ci GrVkImage* image, 891cb93a386Sopenharmony_ci const VkClearColorValue* color, 892cb93a386Sopenharmony_ci uint32_t subRangeCount, 893cb93a386Sopenharmony_ci const VkImageSubresourceRange* subRanges) { 894cb93a386Sopenharmony_ci SkASSERT(fIsActive); 895cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 896cb93a386Sopenharmony_ci this->addingWork(gpu); 897cb93a386Sopenharmony_ci this->addResource(image->resource()); 898cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdClearColorImage(fCmdBuffer, 899cb93a386Sopenharmony_ci image->image(), 900cb93a386Sopenharmony_ci image->currentLayout(), 901cb93a386Sopenharmony_ci color, 902cb93a386Sopenharmony_ci subRangeCount, 903cb93a386Sopenharmony_ci subRanges)); 904cb93a386Sopenharmony_ci} 905cb93a386Sopenharmony_ci 906cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu, 907cb93a386Sopenharmony_ci GrVkImage* image, 908cb93a386Sopenharmony_ci const VkClearDepthStencilValue* color, 909cb93a386Sopenharmony_ci uint32_t subRangeCount, 910cb93a386Sopenharmony_ci const VkImageSubresourceRange* subRanges) { 911cb93a386Sopenharmony_ci SkASSERT(fIsActive); 912cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 913cb93a386Sopenharmony_ci this->addingWork(gpu); 914cb93a386Sopenharmony_ci this->addResource(image->resource()); 915cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdClearDepthStencilImage(fCmdBuffer, 916cb93a386Sopenharmony_ci image->image(), 917cb93a386Sopenharmony_ci image->currentLayout(), 918cb93a386Sopenharmony_ci color, 919cb93a386Sopenharmony_ci subRangeCount, 920cb93a386Sopenharmony_ci subRanges)); 921cb93a386Sopenharmony_ci} 922cb93a386Sopenharmony_ci 923cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::resolveImage(GrVkGpu* gpu, 924cb93a386Sopenharmony_ci const GrVkImage& srcImage, 925cb93a386Sopenharmony_ci const GrVkImage& dstImage, 926cb93a386Sopenharmony_ci uint32_t regionCount, 927cb93a386Sopenharmony_ci const VkImageResolve* regions) { 928cb93a386Sopenharmony_ci SkASSERT(fIsActive); 929cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 930cb93a386Sopenharmony_ci 931cb93a386Sopenharmony_ci this->addingWork(gpu); 932cb93a386Sopenharmony_ci this->addResource(srcImage.resource()); 933cb93a386Sopenharmony_ci this->addResource(dstImage.resource()); 934cb93a386Sopenharmony_ci 935cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdResolveImage(fCmdBuffer, 936cb93a386Sopenharmony_ci srcImage.image(), 937cb93a386Sopenharmony_ci srcImage.currentLayout(), 938cb93a386Sopenharmony_ci dstImage.image(), 939cb93a386Sopenharmony_ci dstImage.currentLayout(), 940cb93a386Sopenharmony_ci regionCount, 941cb93a386Sopenharmony_ci regions)); 942cb93a386Sopenharmony_ci} 943cb93a386Sopenharmony_ci 944cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::onFreeGPUData(const GrVkGpu* gpu) const { 945cb93a386Sopenharmony_ci SkASSERT(!fActiveRenderPass); 946cb93a386Sopenharmony_ci // Destroy the fence, if any 947cb93a386Sopenharmony_ci if (VK_NULL_HANDLE != fSubmitFence) { 948cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr)); 949cb93a386Sopenharmony_ci } 950cb93a386Sopenharmony_ci SkASSERT(!fSecondaryCommandBuffers.count()); 951cb93a386Sopenharmony_ci} 952cb93a386Sopenharmony_ci 953cb93a386Sopenharmony_civoid GrVkPrimaryCommandBuffer::drawBlurImage(const GrVkGpu* gpu, 954cb93a386Sopenharmony_ci const GrVkImage* image, 955cb93a386Sopenharmony_ci SkISize colorAttachmentDimensions, 956cb93a386Sopenharmony_ci const SkOriginInfo& originInfo, 957cb93a386Sopenharmony_ci const SkBlurArg& blurArg) 958cb93a386Sopenharmony_ci{ 959cb93a386Sopenharmony_ci if ((gpu == nullptr) || (image == nullptr)) { 960cb93a386Sopenharmony_ci return; 961cb93a386Sopenharmony_ci } 962cb93a386Sopenharmony_ci this->addingWork(gpu); 963cb93a386Sopenharmony_ci 964cb93a386Sopenharmony_ci VkRect2D srcRegion; 965cb93a386Sopenharmony_ci srcRegion.offset = { blurArg.srcRect.fLeft , blurArg.srcRect.fTop }; 966cb93a386Sopenharmony_ci srcRegion.extent = { (uint32_t)blurArg.srcRect.width(), (uint32_t)blurArg.srcRect.height() }; 967cb93a386Sopenharmony_ci 968cb93a386Sopenharmony_ci VkRect2D dstRegion; 969cb93a386Sopenharmony_ci dstRegion.offset = { blurArg.dstRect.fLeft , blurArg.dstRect.fTop }; 970cb93a386Sopenharmony_ci dstRegion.extent = { (uint32_t)blurArg.dstRect.width(), (uint32_t)blurArg.dstRect.height() }; 971cb93a386Sopenharmony_ci 972cb93a386Sopenharmony_ci if (originInfo.rtOrigin == kBottomLeft_GrSurfaceOrigin) { 973cb93a386Sopenharmony_ci dstRegion.offset.y = colorAttachmentDimensions.height() - blurArg.dstRect.fBottom; 974cb93a386Sopenharmony_ci } 975cb93a386Sopenharmony_ci 976cb93a386Sopenharmony_ci VkBlurColorFilterInfoHUAWEI colorFilterInfo {}; 977cb93a386Sopenharmony_ci colorFilterInfo.sType = VkStructureTypeHUAWEI::VK_STRUCTURE_TYPE_BLUR_COLOR_FILTER_INFO_HUAWEI; 978cb93a386Sopenharmony_ci colorFilterInfo.pNext = nullptr; 979cb93a386Sopenharmony_ci colorFilterInfo.saturation = blurArg.saturation; 980cb93a386Sopenharmony_ci colorFilterInfo.brightness = blurArg.brightness; 981cb93a386Sopenharmony_ci 982cb93a386Sopenharmony_ci VkDrawBlurImageInfoHUAWEI drawBlurImageInfo {}; 983cb93a386Sopenharmony_ci drawBlurImageInfo.sType = VkStructureTypeHUAWEI::VK_STRUCTURE_TYPE_DRAW_BLUR_IMAGE_INFO_HUAWEI; 984cb93a386Sopenharmony_ci drawBlurImageInfo.pNext = &colorFilterInfo; 985cb93a386Sopenharmony_ci drawBlurImageInfo.sigma = blurArg.sigma; 986cb93a386Sopenharmony_ci drawBlurImageInfo.origin = (originInfo.rtOrigin != originInfo.imageOrigin) 987cb93a386Sopenharmony_ci ? BLUR_ORIGIN_Y_AXIS_FLIP_HUAWEI 988cb93a386Sopenharmony_ci : BLUR_ORIGIN_NONE_FLIP_HUAWEI; 989cb93a386Sopenharmony_ci drawBlurImageInfo.srcRegion = srcRegion; 990cb93a386Sopenharmony_ci drawBlurImageInfo.dstRegion = dstRegion; 991cb93a386Sopenharmony_ci drawBlurImageInfo.srcImageView = image->textureView()->imageView(); 992cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), CmdDrawBlurImageHUAWEI(fCmdBuffer, &drawBlurImageInfo)); 993cb93a386Sopenharmony_ci} 994cb93a386Sopenharmony_ci 995cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 996cb93a386Sopenharmony_ci// SecondaryCommandBuffer 997cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 998cb93a386Sopenharmony_ci 999cb93a386Sopenharmony_ciGrVkSecondaryCommandBuffer* GrVkSecondaryCommandBuffer::Create(GrVkGpu* gpu, 1000cb93a386Sopenharmony_ci GrVkCommandPool* cmdPool) { 1001cb93a386Sopenharmony_ci SkASSERT(cmdPool); 1002cb93a386Sopenharmony_ci const VkCommandBufferAllocateInfo cmdInfo = { 1003cb93a386Sopenharmony_ci VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType 1004cb93a386Sopenharmony_ci nullptr, // pNext 1005cb93a386Sopenharmony_ci cmdPool->vkCommandPool(), // commandPool 1006cb93a386Sopenharmony_ci VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level 1007cb93a386Sopenharmony_ci 1 // bufferCount 1008cb93a386Sopenharmony_ci }; 1009cb93a386Sopenharmony_ci 1010cb93a386Sopenharmony_ci VkCommandBuffer cmdBuffer; 1011cb93a386Sopenharmony_ci VkResult err; 1012cb93a386Sopenharmony_ci GR_VK_CALL_RESULT(gpu, err, AllocateCommandBuffers(gpu->device(), &cmdInfo, &cmdBuffer)); 1013cb93a386Sopenharmony_ci if (err) { 1014cb93a386Sopenharmony_ci return nullptr; 1015cb93a386Sopenharmony_ci } 1016cb93a386Sopenharmony_ci return new GrVkSecondaryCommandBuffer(cmdBuffer, /*externalRenderPass=*/nullptr); 1017cb93a386Sopenharmony_ci} 1018cb93a386Sopenharmony_ci 1019cb93a386Sopenharmony_ciGrVkSecondaryCommandBuffer* GrVkSecondaryCommandBuffer::Create( 1020cb93a386Sopenharmony_ci VkCommandBuffer cmdBuffer, const GrVkRenderPass* externalRenderPass) { 1021cb93a386Sopenharmony_ci return new GrVkSecondaryCommandBuffer(cmdBuffer, externalRenderPass); 1022cb93a386Sopenharmony_ci} 1023cb93a386Sopenharmony_ci 1024cb93a386Sopenharmony_civoid GrVkSecondaryCommandBuffer::begin(GrVkGpu* gpu, const GrVkFramebuffer* framebuffer, 1025cb93a386Sopenharmony_ci const GrVkRenderPass* compatibleRenderPass) { 1026cb93a386Sopenharmony_ci SkASSERT(!fIsActive); 1027cb93a386Sopenharmony_ci SkASSERT(!this->isWrapped()); 1028cb93a386Sopenharmony_ci SkASSERT(compatibleRenderPass); 1029cb93a386Sopenharmony_ci fActiveRenderPass = compatibleRenderPass; 1030cb93a386Sopenharmony_ci 1031cb93a386Sopenharmony_ci VkCommandBufferInheritanceInfo inheritanceInfo; 1032cb93a386Sopenharmony_ci memset(&inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); 1033cb93a386Sopenharmony_ci inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; 1034cb93a386Sopenharmony_ci inheritanceInfo.pNext = nullptr; 1035cb93a386Sopenharmony_ci inheritanceInfo.renderPass = fActiveRenderPass->vkRenderPass(); 1036cb93a386Sopenharmony_ci inheritanceInfo.subpass = 0; // Currently only using 1 subpass for each render pass 1037cb93a386Sopenharmony_ci inheritanceInfo.framebuffer = framebuffer ? framebuffer->framebuffer() : VK_NULL_HANDLE; 1038cb93a386Sopenharmony_ci inheritanceInfo.occlusionQueryEnable = false; 1039cb93a386Sopenharmony_ci inheritanceInfo.queryFlags = 0; 1040cb93a386Sopenharmony_ci inheritanceInfo.pipelineStatistics = 0; 1041cb93a386Sopenharmony_ci 1042cb93a386Sopenharmony_ci VkCommandBufferBeginInfo cmdBufferBeginInfo; 1043cb93a386Sopenharmony_ci memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 1044cb93a386Sopenharmony_ci cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 1045cb93a386Sopenharmony_ci cmdBufferBeginInfo.pNext = nullptr; 1046cb93a386Sopenharmony_ci cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | 1047cb93a386Sopenharmony_ci VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 1048cb93a386Sopenharmony_ci cmdBufferBeginInfo.pInheritanceInfo = &inheritanceInfo; 1049cb93a386Sopenharmony_ci 1050cb93a386Sopenharmony_ci GR_VK_CALL_ERRCHECK(gpu, BeginCommandBuffer(fCmdBuffer, &cmdBufferBeginInfo)); 1051cb93a386Sopenharmony_ci 1052cb93a386Sopenharmony_ci fIsActive = true; 1053cb93a386Sopenharmony_ci} 1054cb93a386Sopenharmony_ci 1055cb93a386Sopenharmony_civoid GrVkSecondaryCommandBuffer::end(GrVkGpu* gpu) { 1056cb93a386Sopenharmony_ci SkASSERT(fIsActive); 1057cb93a386Sopenharmony_ci SkASSERT(!this->isWrapped()); 1058cb93a386Sopenharmony_ci GR_VK_CALL_ERRCHECK(gpu, EndCommandBuffer(fCmdBuffer)); 1059cb93a386Sopenharmony_ci this->invalidateState(); 1060cb93a386Sopenharmony_ci fHasWork = false; 1061cb93a386Sopenharmony_ci fIsActive = false; 1062cb93a386Sopenharmony_ci} 1063cb93a386Sopenharmony_ci 1064cb93a386Sopenharmony_civoid GrVkSecondaryCommandBuffer::recycle(GrVkCommandPool* cmdPool) { 1065cb93a386Sopenharmony_ci if (this->isWrapped()) { 1066cb93a386Sopenharmony_ci delete this; 1067cb93a386Sopenharmony_ci } else { 1068cb93a386Sopenharmony_ci cmdPool->recycleSecondaryCommandBuffer(this); 1069cb93a386Sopenharmony_ci } 1070cb93a386Sopenharmony_ci} 1071cb93a386Sopenharmony_ci 1072