From 066df7ca911b65d416783f3bec6f4f1662948ad5 Mon Sep 17 00:00:00 2001 From: egdaniel Date: Wed, 8 Jun 2016 14:02:27 -0700 Subject: [PATCH] Add GpuCommandBuffer support. Currently this is not actually hooked into the system. To give some context, in a follow up CL I'll add this to GrDrawTarget. For this I will move the gpu onDraw command to the GpuCommandBuffer as well. For GL this will end up just being a pass through to a non virtual draw(...) on GrGLGpu, and for vulkan it will mostly do what it currently does but adding commands to the secondary command buffer instead. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2038583002 Review-Url: https://codereview.chromium.org/2038583002 --- gyp/gpu.gypi | 4 ++ src/gpu/GrGpu.h | 9 +++ src/gpu/GrGpuCommandBuffer.h | 37 ++++++++++++ src/gpu/gl/GrGLGpu.cpp | 9 +++ src/gpu/gl/GrGLGpu.h | 6 ++ src/gpu/gl/GrGLGpuCommandBuffer.h | 33 +++++++++++ src/gpu/vk/GrVkCommandBuffer.cpp | 3 + src/gpu/vk/GrVkGpu.cpp | 15 +++++ src/gpu/vk/GrVkGpu.h | 11 +++- src/gpu/vk/GrVkGpuCommandBuffer.cpp | 92 +++++++++++++++++++++++++++++ src/gpu/vk/GrVkGpuCommandBuffer.h | 41 +++++++++++++ src/gpu/vk/GrVkRenderTarget.h | 3 + src/gpu/vk/GrVkResourceProvider.cpp | 8 ++- tools/gpu/GrTest.cpp | 8 +++ 14 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 src/gpu/GrGpuCommandBuffer.h create mode 100644 src/gpu/gl/GrGLGpuCommandBuffer.h create mode 100644 src/gpu/vk/GrVkGpuCommandBuffer.cpp create mode 100644 src/gpu/vk/GrVkGpuCommandBuffer.h diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index 5c55aec33f..0fbfea16ce 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -101,6 +101,7 @@ '<(skia_src_path)/gpu/GrGpu.cpp', '<(skia_src_path)/gpu/GrGpu.h', '<(skia_src_path)/gpu/GrGpuResourceCacheAccess.h', + '<(skia_src_path)/gpu/GrGpuCommandBuffer.h', '<(skia_src_path)/gpu/GrGpuResourcePriv.h', '<(skia_src_path)/gpu/GrGpuResource.cpp', '<(skia_src_path)/gpu/GrGpuFactory.cpp', @@ -338,6 +339,7 @@ '<(skia_src_path)/gpu/gl/GrGLGLSL.h', '<(skia_src_path)/gpu/gl/GrGLGpu.cpp', '<(skia_src_path)/gpu/gl/GrGLGpu.h', + '<(skia_src_path)/gpu/gl/GrGLGpuCommandBuffer.h', '<(skia_src_path)/gpu/gl/GrGLGpuProgramCache.cpp', '<(skia_src_path)/gpu/gl/GrGLExtensions.cpp', '<(skia_src_path)/gpu/gl/GrGLInterface.cpp', @@ -457,6 +459,8 @@ '<(skia_src_path)/gpu/vk/GrVkGLSLSampler.h', '<(skia_src_path)/gpu/vk/GrVkGpu.cpp', '<(skia_src_path)/gpu/vk/GrVkGpu.h', + '<(skia_src_path)/gpu/vk/GrVkGpuCommandBuffer.cpp', + '<(skia_src_path)/gpu/vk/GrVkGpuCommandBuffer.h', '<(skia_src_path)/gpu/vk/GrVkImage.cpp', '<(skia_src_path)/gpu/vk/GrVkImage.h', '<(skia_src_path)/gpu/vk/GrVkImageView.cpp', diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 63a56ddd2d..a99ce8f45e 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -8,6 +8,7 @@ #ifndef GrGpu_DEFINED #define GrGpu_DEFINED +#include "GrGpuCommandBuffer.h" #include "GrPipelineBuilder.h" #include "GrProgramDesc.h" #include "GrSwizzle.h" @@ -360,6 +361,14 @@ public: // multisample information itself. const MultisampleSpecs& getMultisampleSpecs(GrRenderTarget*, const GrStencilSettings&); + // Creates a GrGpuCommandBuffer in which the GrDrawTarget can send draw commands to instead of + // directly to the Gpu object. + virtual GrGpuCommandBuffer* createCommandBuffer(const GrRenderTarget& target, + GrGpuCommandBuffer::LoadAndStoreOp colorOp, + GrColor colorClear, + GrGpuCommandBuffer::LoadAndStoreOp stencilOp, + GrColor stencilClear) = 0; + // We pass in an array of meshCount GrMesh to the draw. The backend should loop over each // GrMesh object and emit a draw for it. Each draw will use the same GrPipeline and // GrPrimitiveProcessor. This may fail if the draw would exceed any resource limits (e.g. diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h new file mode 100644 index 0000000000..3c6e6116fb --- /dev/null +++ b/src/gpu/GrGpuCommandBuffer.h @@ -0,0 +1,37 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#ifndef GrGpuCommandBuffer_DEFINED +#define GrGpuCommandBuffer_DEFINED + +#include "GrColor.h" + +class GrRenderTarget; + +class GrGpuCommandBuffer { +public: + enum LoadAndStoreOp { + kLoadAndStore_LoadAndStoreOp, + kLoadAndDiscard_LoadAndStoreOp, + kClearAndStore_LoadAndStoreOp, + kClearAndDiscard_LoadAndStoreOp, + kDiscardAndStore_LoadAndStoreOp, + kDiscardAndDiscard_LoadAndStoreOp, + }; + + GrGpuCommandBuffer() {} + virtual ~GrGpuCommandBuffer() {} + + // Signals the end of recording to the command buffer and that it can now be submitted. + virtual void end() = 0; + + // Sends the command buffer off to the GPU object to execute the commands built up in the + // buffer. The gpu object is allowed to defer execution of the commands until it is flushed. + virtual void submit() = 0; +}; + +#endif diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index dcad9ce5a4..5d6b7ac2e7 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -8,6 +8,7 @@ #include "GrGLGpu.h" #include "GrGLBuffer.h" #include "GrGLGLSL.h" +#include "GrGLGpuCommandBuffer.h" #include "GrGLStencilAttachment.h" #include "GrGLTextureRenderTarget.h" #include "GrGpuResourcePriv.h" @@ -2623,6 +2624,14 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, return true; } +GrGpuCommandBuffer* GrGLGpu::createCommandBuffer(const GrRenderTarget& target, + GrGpuCommandBuffer::LoadAndStoreOp colorOp, + GrColor colorClear, + GrGpuCommandBuffer::LoadAndStoreOp stencilOp, + GrColor stencilClear) { + return new GrGLGpuCommandBuffer(this); +} + void GrGLGpu::finishDrawTarget() { if (fPLSHasBeenUsed) { /* There is an ARM driver bug where if we use PLS, and then draw a frame which does not diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index e2e27d586a..9cce41c76d 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -101,6 +101,12 @@ public: void clearStencil(GrRenderTarget*) override; + GrGpuCommandBuffer* createCommandBuffer(const GrRenderTarget& target, + GrGpuCommandBuffer::LoadAndStoreOp colorOp, + GrColor colorClear, + GrGpuCommandBuffer::LoadAndStoreOp stencilOp, + GrColor stencilClear) override; + void invalidateBoundRenderTarget() { fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID; } diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h new file mode 100644 index 0000000000..8925322d4a --- /dev/null +++ b/src/gpu/gl/GrGLGpuCommandBuffer.h @@ -0,0 +1,33 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#ifndef GrGLGpuCommandBuffer_DEFINED +#define GrGLGpuCommandBuffer_DEFINED + +#include "GrGpuCommandBuffer.h" + +class GrGLGpu; + +class GrGLGpuCommandBuffer : public GrGpuCommandBuffer { +public: + GrGLGpuCommandBuffer(GrGLGpu* gpu) /*: fGpu(gpu)*/ {} + + virtual ~GrGLGpuCommandBuffer() {} + + void end() override {} + + void submit() override {} + +private: + // commented out to appease clang compiler warning about unused private field + // GrGLGpu* fGpu; + + typedef GrGpuCommandBuffer INHERITED; +}; + +#endif + diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp index 9604355aad..2b636edf20 100644 --- a/src/gpu/vk/GrVkCommandBuffer.cpp +++ b/src/gpu/vk/GrVkCommandBuffer.cpp @@ -311,6 +311,9 @@ void GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu, GR_VK_CALL(gpu->vkInterface(), CmdExecuteCommands(fCmdBuffer, 1, &buffer->fCmdBuffer)); this->addResource(buffer); + // When executing a secondary command buffer all state (besides render pass state) becomes + // invalidated and must be reset. This includes bound buffers, pipelines, dynamic state, etc. + this->invalidateState(); } void GrVkPrimaryCommandBuffer::submitToQueue(const GrVkGpu* gpu, diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index bc0b98ea8b..6f953653e4 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -17,6 +17,7 @@ #include "GrTexturePriv.h" #include "GrVkCommandBuffer.h" +#include "GrVkGpuCommandBuffer.h" #include "GrVkImage.h" #include "GrVkIndexBuffer.h" #include "GrVkMemory.h" @@ -160,6 +161,15 @@ GrVkGpu::~GrVkGpu() { /////////////////////////////////////////////////////////////////////////////// +GrGpuCommandBuffer* GrVkGpu::createCommandBuffer(const GrRenderTarget& target, + GrGpuCommandBuffer::LoadAndStoreOp colorOp, + GrColor colorClear, + GrGpuCommandBuffer::LoadAndStoreOp stencilOp, + GrColor stencilClear) { + const GrVkRenderTarget& vkRT = static_cast(target); + return new GrVkGpuCommandBuffer(this, vkRT, colorOp, colorClear, stencilOp, stencilClear); +} + void GrVkGpu::submitCommandBuffer(SyncQueue sync) { SkASSERT(fCurrentCmdBuffer); fCurrentCmdBuffer->end(this); @@ -1569,6 +1579,11 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, return true; } + +void GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buffer) { + fCurrentCmdBuffer->executeCommands(this, buffer); +} + sk_sp GrVkGpu::prepareDrawState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, GrPrimitiveType primitiveType, diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index 00055ad87c..cd72c69bd4 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -24,10 +24,11 @@ class GrPipeline; class GrNonInstancedMesh; class GrVkBufferImpl; -class GrVkCommandBuffer; class GrVkPipeline; class GrVkPipelineState; +class GrVkPrimaryCommandBuffer; class GrVkRenderPass; +class GrVkSecondaryCommandBuffer; class GrVkTexture; struct GrVkInterface; @@ -90,6 +91,12 @@ public: void clearStencil(GrRenderTarget* target) override; + GrGpuCommandBuffer* createCommandBuffer(const GrRenderTarget& target, + GrGpuCommandBuffer::LoadAndStoreOp colorOp, + GrColor colorClear, + GrGpuCommandBuffer::LoadAndStoreOp stencilOp, + GrColor stencilClear) override; + void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {} void addMemoryBarrier(VkPipelineStageFlags srcStageMask, @@ -109,6 +116,8 @@ public: return fCompiler; } + void submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer*); + void finishDrawTarget() override; void generateMipmap(GrVkTexture* tex) const; diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp new file mode 100644 index 0000000000..e9a13d4517 --- /dev/null +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -0,0 +1,92 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#include "GrVkGpuCommandBuffer.h" + +#include "GrVkCommandBuffer.h" +#include "GrVkGpu.h" +#include "GrVkRenderPass.h" +#include "GrVkRenderTarget.h" +#include "GrVkResourceProvider.h" + +void get_vk_load_store_ops(GrGpuCommandBuffer::LoadAndStoreOp op, + VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* storeOp) { + switch (op) { + case GrGpuCommandBuffer::kLoadAndStore_LoadAndStoreOp: + *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + *storeOp = VK_ATTACHMENT_STORE_OP_STORE; + break; + case GrGpuCommandBuffer::kLoadAndDiscard_LoadAndStoreOp: + *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + break; + case GrGpuCommandBuffer::kClearAndStore_LoadAndStoreOp: + *loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + *storeOp = VK_ATTACHMENT_STORE_OP_STORE; + break; + case GrGpuCommandBuffer::kClearAndDiscard_LoadAndStoreOp: + *loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + break; + case GrGpuCommandBuffer::kDiscardAndStore_LoadAndStoreOp: + *loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + *storeOp = VK_ATTACHMENT_STORE_OP_STORE; + break; + case GrGpuCommandBuffer::kDiscardAndDiscard_LoadAndStoreOp: + *loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + break; + } +} + +GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu, + const GrVkRenderTarget& target, + LoadAndStoreOp colorOp, GrColor colorClear, + LoadAndStoreOp stencilOp, GrColor stencilClear) + : fGpu(gpu) { + VkAttachmentLoadOp vkLoadOp; + VkAttachmentStoreOp vkStoreOp; + + get_vk_load_store_ops(colorOp, &vkLoadOp, &vkStoreOp); + GrVkRenderPass::LoadStoreOps vkColorOps(vkLoadOp, vkStoreOp); + + get_vk_load_store_ops(stencilOp, &vkLoadOp, &vkStoreOp); + GrVkRenderPass::LoadStoreOps vkStencilOps(vkLoadOp, vkStoreOp); + + GrVkRenderPass::LoadStoreOps vkResolveOps(VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_STORE_OP_STORE); + + const GrVkResourceProvider::CompatibleRPHandle& rpHandle = target.compatibleRenderPassHandle(); + if (rpHandle.isValid()) { + fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle, + vkColorOps, + vkResolveOps, + vkStencilOps); + } else { + fRenderPass = fGpu->resourceProvider().findRenderPass(target, + vkColorOps, + vkResolveOps, + vkStencilOps); + } + + fCommandBuffer = GrVkSecondaryCommandBuffer::Create(gpu, gpu->cmdPool(), fRenderPass); + fCommandBuffer->begin(gpu, target.framebuffer()); +} + +GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() { + fCommandBuffer->unref(fGpu); + fRenderPass->unref(fGpu); +} + +void GrVkGpuCommandBuffer::end() { + fCommandBuffer->end(fGpu); +} + +void GrVkGpuCommandBuffer::submit() { + fGpu->submitSecondaryCommandBuffer(fCommandBuffer); +} + diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h new file mode 100644 index 0000000000..b68aa0334c --- /dev/null +++ b/src/gpu/vk/GrVkGpuCommandBuffer.h @@ -0,0 +1,41 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#ifndef GrVkGpuCommandBuffer_DEFINED +#define GrVkGpuCommandBuffer_DEFINED + +#include "GrGpuCommandBuffer.h" + +#include "GrColor.h" + +class GrVkGpu; +class GrVkRenderPass; +class GrVkRenderTarget; +class GrVkSecondaryCommandBuffer; + +class GrVkGpuCommandBuffer : public GrGpuCommandBuffer { +public: + GrVkGpuCommandBuffer(GrVkGpu* gpu, + const GrVkRenderTarget&, + LoadAndStoreOp colorOp, GrColor colorClear, + LoadAndStoreOp stencilOp, GrColor stencilClear); + + virtual ~GrVkGpuCommandBuffer(); + + void end() override; + + void submit() override; + +private: + const GrVkRenderPass* fRenderPass; + GrVkSecondaryCommandBuffer* fCommandBuffer; + GrVkGpu* fGpu; + + typedef GrGpuCommandBuffer INHERITED; +}; + +#endif diff --git a/src/gpu/vk/GrVkRenderTarget.h b/src/gpu/vk/GrVkRenderTarget.h index 735f5cdf7c..01ebf269df 100644 --- a/src/gpu/vk/GrVkRenderTarget.h +++ b/src/gpu/vk/GrVkRenderTarget.h @@ -53,6 +53,9 @@ public: const GrVkImageView* stencilAttachmentView() const; const GrVkRenderPass* simpleRenderPass() const { return fCachedSimpleRenderPass; } + GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle() const { + return fCompatibleRPHandle; + } // override of GrRenderTarget ResolveType getResolveType() const override { diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp index ae333bc69e..a632be44e2 100644 --- a/src/gpu/vk/GrVkResourceProvider.cpp +++ b/src/gpu/vk/GrVkResourceProvider.cpp @@ -10,6 +10,7 @@ #include "GrTextureParams.h" #include "GrVkCommandBuffer.h" #include "GrVkPipeline.h" +#include "GrVkRenderTarget.h" #include "GrVkSampler.h" #include "GrVkUtil.h" @@ -139,10 +140,15 @@ const GrVkRenderPass* GrVkResourceProvider::findRenderPass( const GrVkRenderPass::LoadStoreOps& resolveOps, const GrVkRenderPass::LoadStoreOps& stencilOps, CompatibleRPHandle* compatibleHandle) { + GrVkResourceProvider::CompatibleRPHandle tempRPHandle; + GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle + : &tempRPHandle; + *pRPHandle = target.compatibleRenderPassHandle(); + // This will get us the handle to (and possible create) the compatible set for the specific // GrVkRenderPass we are looking for. this->findCompatibleRenderPass(target, compatibleHandle); - return this->findRenderPass(*compatibleHandle, colorOps, resolveOps, stencilOps); + return this->findRenderPass(*pRPHandle, colorOps, resolveOps, stencilOps); } const GrVkRenderPass* diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp index c797dc011a..e380b34010 100644 --- a/tools/gpu/GrTest.cpp +++ b/tools/gpu/GrTest.cpp @@ -302,6 +302,14 @@ public: return false; } + GrGpuCommandBuffer* createCommandBuffer(const GrRenderTarget& target, + GrGpuCommandBuffer::LoadAndStoreOp colorOp, + GrColor colorClear, + GrGpuCommandBuffer::LoadAndStoreOp stencilOp, + GrColor stencilClear) override { + return nullptr; + } + void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {}; private: