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
This commit is contained in:
egdaniel 2016-06-08 14:02:27 -07:00 committed by Commit bot
parent 28215d44b3
commit 066df7ca91
14 changed files with 277 additions and 2 deletions

View File

@ -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',

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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,

View File

@ -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<const GrVkRenderTarget&>(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<GrVkPipelineState> GrVkGpu::prepareDrawState(const GrPipeline& pipeline,
const GrPrimitiveProcessor& primProc,
GrPrimitiveType primitiveType,

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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 {

View File

@ -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*

View File

@ -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: