/* * Copyright 2021 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/gpu/graphite/CommandBuffer.h" #include "src/core/SkTraceEvent.h" #include "src/gpu/RefCntedCallback.h" #include "src/gpu/graphite/Buffer.h" #include "src/gpu/graphite/ComputePipeline.h" #include "src/gpu/graphite/GraphicsPipeline.h" #include "src/gpu/graphite/Log.h" #include "src/gpu/graphite/Sampler.h" #include "src/gpu/graphite/Texture.h" #include "src/gpu/graphite/TextureProxy.h" namespace skgpu::graphite { CommandBuffer::CommandBuffer() {} CommandBuffer::~CommandBuffer() { this->releaseResources(); } void CommandBuffer::releaseResources() { TRACE_EVENT0("skia.gpu", TRACE_FUNC); fTrackedUsageResources.clear(); fCommandBufferResources.clear(); } void CommandBuffer::resetCommandBuffer() { TRACE_EVENT0("skia.gpu", TRACE_FUNC); this->releaseResources(); this->onResetCommandBuffer(); fBuffersToAsyncMap.clear(); } void CommandBuffer::trackResource(sk_sp resource) { fTrackedUsageResources.push_back(std::move(resource)); } void CommandBuffer::trackCommandBufferResource(sk_sp resource) { fCommandBufferResources.push_back(std::move(resource)); } void CommandBuffer::addFinishedProc(sk_sp finishedProc) { fFinishedProcs.push_back(std::move(finishedProc)); } void CommandBuffer::callFinishedProcs(bool success) { if (!success) { for (int i = 0; i < fFinishedProcs.size(); ++i) { fFinishedProcs[i]->setFailureResult(); } } fFinishedProcs.clear(); } void CommandBuffer::addBuffersToAsyncMapOnSubmit(SkSpan> buffers) { for (size_t i = 0; i < buffers.size(); ++i) { SkASSERT(buffers[i]); fBuffersToAsyncMap.push_back(buffers[i]); } } SkSpan> CommandBuffer::buffersToAsyncMapOnSubmit() const { return fBuffersToAsyncMap; } bool CommandBuffer::addRenderPass(const RenderPassDesc& renderPassDesc, sk_sp colorTexture, sk_sp resolveTexture, sk_sp depthStencilTexture, SkRect viewport, const DrawPassList& drawPasses) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); fRenderPassSize = colorTexture->dimensions(); if (!this->onAddRenderPass(renderPassDesc, colorTexture.get(), resolveTexture.get(), depthStencilTexture.get(), viewport, drawPasses)) { return false; } if (colorTexture) { this->trackCommandBufferResource(std::move(colorTexture)); } if (resolveTexture) { this->trackCommandBufferResource(std::move(resolveTexture)); } if (depthStencilTexture) { this->trackCommandBufferResource(std::move(depthStencilTexture)); } // We just assume if you are adding a render pass that the render pass will actually do work. In // theory we could have a discard load that doesn't submit any draws, clears, etc. But hopefully // something so trivial would be caught before getting here. SkDEBUGCODE(fHasWork = true;) return true; } bool CommandBuffer::addComputePass(DispatchGroupSpan dispatchGroups) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); if (!this->onAddComputePass(dispatchGroups)) { return false; } SkDEBUGCODE(fHasWork = true;) return true; } bool CommandBuffer::copyBufferToBuffer(const Buffer* srcBuffer, size_t srcOffset, sk_sp dstBuffer, size_t dstOffset, size_t size) { SkASSERT(srcBuffer); SkASSERT(dstBuffer); if (!this->onCopyBufferToBuffer(srcBuffer, srcOffset, dstBuffer.get(), dstOffset, size)) { return false; } this->trackResource(std::move(dstBuffer)); SkDEBUGCODE(fHasWork = true;) return true; } bool CommandBuffer::copyTextureToBuffer(sk_sp texture, SkIRect srcRect, sk_sp buffer, size_t bufferOffset, size_t bufferRowBytes) { SkASSERT(texture); SkASSERT(buffer); if (!this->onCopyTextureToBuffer(texture.get(), srcRect, buffer.get(), bufferOffset, bufferRowBytes)) { return false; } this->trackCommandBufferResource(std::move(texture)); this->trackResource(std::move(buffer)); SkDEBUGCODE(fHasWork = true;) return true; } bool CommandBuffer::copyBufferToTexture(const Buffer* buffer, sk_sp texture, const BufferTextureCopyData* copyData, int count) { SkASSERT(buffer); SkASSERT(texture); SkASSERT(count > 0 && copyData); if (!this->onCopyBufferToTexture(buffer, texture.get(), copyData, count)) { return false; } this->trackCommandBufferResource(std::move(texture)); SkDEBUGCODE(fHasWork = true;) return true; } bool CommandBuffer::copyTextureToTexture(sk_sp src, SkIRect srcRect, sk_sp dst, SkIPoint dstPoint, int mipLevel) { SkASSERT(src); SkASSERT(dst); if (src->textureInfo().isProtected() == Protected::kYes && dst->textureInfo().isProtected() != Protected::kYes) { SKGPU_LOG_E("Can't copy from protected memory to non-protected"); return false; } if (!this->onCopyTextureToTexture(src.get(), srcRect, dst.get(), dstPoint, mipLevel)) { return false; } this->trackCommandBufferResource(std::move(src)); this->trackCommandBufferResource(std::move(dst)); SkDEBUGCODE(fHasWork = true;) return true; } bool CommandBuffer::synchronizeBufferToCpu(sk_sp buffer) { SkASSERT(buffer); bool didResultInWork = false; if (!this->onSynchronizeBufferToCpu(buffer.get(), &didResultInWork)) { return false; } if (didResultInWork) { this->trackResource(std::move(buffer)); SkDEBUGCODE(fHasWork = true;) } return true; } bool CommandBuffer::clearBuffer(const Buffer* buffer, size_t offset, size_t size) { SkASSERT(buffer); if (!this->onClearBuffer(buffer, offset, size)) { return false; } SkDEBUGCODE(fHasWork = true;) return true; } } // namespace skgpu::graphite