Support inline uploads in Vulkan

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3586

Change-Id: I5913c336aa33851d6d2e80d9638df2efa8ac0400
Reviewed-on: https://skia-review.googlesource.com/3586
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2016-10-18 11:48:51 -04:00 committed by Skia Commit-Bot
parent 560285d93a
commit 77b53f66ba
11 changed files with 113 additions and 37 deletions

View File

@ -9,6 +9,7 @@
#define GrBatchBuffer_DEFINED
#include "GrBufferAllocPool.h"
#include "GrGpu.h"
#include "batches/GrVertexBatch.h"
class GrGpuCommandBuffer;

View File

@ -9,7 +9,9 @@
#define GrGpuCommandBuffer_DEFINED
#include "GrColor.h"
#include "batches/GrDrawBatch.h"
class GrBatchFlushState;
class GrFixedClip;
class GrGpu;
class GrMesh;
@ -64,17 +66,20 @@ public:
int meshCount,
const SkRect& bounds);
// Performs an upload of vertex data in the middle of a set of a set of draws
virtual void inlineUpload(GrBatchFlushState* state, GrDrawBatch::DeferredUploadFn& upload) = 0;
/**
* Clear the passed in render target. Ignores the draw state and clip.
*/
* Clear the passed in render target. Ignores the draw state and clip.
*/
void clear(const GrFixedClip&, GrColor);
void clearStencilClip(const GrFixedClip&, bool insideStencilMask);
/**
* Discards the contents render target. nullptr indicates that the current render target should
* be discarded.
**/
* Discards the contents render target. nullptr indicates that the current render target should
* be discarded.
*/
// TODO: This should be removed in the future to favor using the load and store ops for discard
virtual void discard() = 0;

View File

@ -10,7 +10,6 @@
#include "GrColor.h"
#include "GrFragmentProcessor.h"
#include "GrGpu.h"
#include "GrNonAtomicRef.h"
#include "GrPendingProgramElement.h"
#include "GrPrimitiveProcessor.h"

View File

@ -10,6 +10,7 @@
#include "GrBatchAtlas.h"
#include "GrBuffer.h"
#include "GrGpu.h"
#include "GrTextureProvider.h"
#include "GrPathRange.h"

View File

@ -10,6 +10,8 @@
#include "GrPathRenderer.h"
#include "GrGpu.h"
class GrDashLinePathRenderer : public GrPathRenderer {
private:
bool onCanDrawPath(const CanDrawPathArgs&) const override;

View File

@ -72,7 +72,7 @@ void GrVertexBatch::onDraw(GrBatchFlushState* state, const SkRect& bounds) {
GrBatchDrawToken drawToken = state->nextTokenToFlush();
while (currUploadIdx < fInlineUploads.count() &&
fInlineUploads[currUploadIdx].fUploadBeforeToken == drawToken) {
state->doUpload(fInlineUploads[currUploadIdx++].fUpload);
state->commandBuffer()->inlineUpload(state, fInlineUploads[currUploadIdx++].fUpload);
}
const QueuedDraw &draw = fQueuedDraws[currDrawIdx];
state->commandBuffer()->draw(*this->pipeline(), *draw.fGeometryProcessor.get(),

View File

@ -10,6 +10,7 @@
#include "GrGpuCommandBuffer.h"
#include "GrBatchFlushState.h"
#include "GrGLGpu.h"
class GrGLRenderTarget;
@ -29,6 +30,10 @@ public:
void discard() override {}
void inlineUpload(GrBatchFlushState* state, GrDrawBatch::DeferredUploadFn& upload) override {
state->doUpload(upload);
}
private:
GrGpu* gpu() override { return fGpu; }
GrRenderTarget* renderTarget() override { return fRenderTarget; }

View File

@ -8,6 +8,7 @@
#ifndef gr_instanced_InstancedRendering_DEFINED
#define gr_instanced_InstancedRendering_DEFINED
#include "GrGpu.h"
#include "GrMemoryPool.h"
#include "SkTInternalLList.h"
#include "batches/GrDrawBatch.h"

View File

@ -387,6 +387,7 @@ void GrVkPrimaryCommandBuffer::endRenderPass(const GrVkGpu* gpu) {
void GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu,
GrVkSecondaryCommandBuffer* buffer) {
SkASSERT(fIsActive);
SkASSERT(!buffer->fIsActive);
SkASSERT(fActiveRenderPass);
SkASSERT(fActiveRenderPass->isCompatible(*buffer->fActiveRenderPass));

View File

@ -7,6 +7,7 @@
#include "GrVkGpuCommandBuffer.h"
#include "GrBatchFlushState.h"
#include "GrFixedClip.h"
#include "GrMesh.h"
#include "GrPipeline.h"
@ -57,9 +58,7 @@ GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu,
const LoadAndStoreInfo& colorInfo,
const LoadAndStoreInfo& stencilInfo)
: fGpu(gpu)
, fRenderTarget(target)
, fIsEmpty(true)
, fStartsWithClear(false) {
, fRenderTarget(target) {
VkAttachmentLoadOp vkLoadOp;
VkAttachmentStoreOp vkStoreOp;
@ -86,6 +85,8 @@ GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu,
GrColorToRGBAFloat(colorInfo.fClearColor, cbInfo.fColorClearValue.color.float32);
cbInfo.fBounds.setEmpty();
cbInfo.fIsEmpty = true;
cbInfo.fStartsWithClear = false;
cbInfo.fCommandBuffer = gpu->resourceProvider().findOrCreateSecondaryCommandBuffer();
cbInfo.fCommandBuffer->begin(gpu, target->framebuffer(), cbInfo.fRenderPass);
@ -107,18 +108,6 @@ void GrVkGpuCommandBuffer::end() {
}
void GrVkGpuCommandBuffer::onSubmit() {
// TODO: We can't add this optimization yet since many things create a scratch texture which
// adds the discard immediately, but then don't draw to it right away. This causes the discard
// to be ignored and we get yelled at for loading uninitialized data. However, once MDP lands,
// the discard will get reordered with the rest of the draw commands and we can re-enable this.
#if 0
if (fIsEmpty && !fStartsWithClear) {
// We have sumbitted no actual draw commands to the command buffer and we are not using
// the render pass to do a clear so there is no need to submit anything.
return;
}
#endif
// Change layout of our render target so it can be used as the color attachment. Currently
// we don't attach the resolve to the framebuffer so no need to change its layout.
GrVkImage* targetImage = fRenderTarget->msaaImage() ? fRenderTarget->msaaImage()
@ -145,6 +134,23 @@ void GrVkGpuCommandBuffer::onSubmit() {
for (int i = 0; i < fCommandBufferInfos.count(); ++i) {
CommandBufferInfo& cbInfo = fCommandBufferInfos[i];
for (int j = 0; j < cbInfo.fPreDrawUploads.count(); ++j) {
InlineUploadInfo& iuInfo = cbInfo.fPreDrawUploads[j];
iuInfo.fFlushState->doUpload(iuInfo.fUpload);
}
// TODO: We can't add this optimization yet since many things create a scratch texture which
// adds the discard immediately, but then don't draw to it right away. This causes the
// discard to be ignored and we get yelled at for loading uninitialized data. However, once
// MDP lands, the discard will get reordered with the rest of the draw commands and we can
// re-enable this.
#if 0
if (cbInfo.fIsEmpty && !cbInfo.fStartsWithClear) {
// We have sumbitted no actual draw commands to the command buffer and we are not using
// the render pass to do a clear so there is no need to submit anything.
continue;
}
#endif
if (cbInfo.fBounds.intersect(0, 0,
SkIntToScalar(fRenderTarget->width()),
SkIntToScalar(fRenderTarget->height()))) {
@ -158,8 +164,8 @@ void GrVkGpuCommandBuffer::onSubmit() {
}
void GrVkGpuCommandBuffer::discard() {
if (fIsEmpty) {
CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdBuffer];
CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdBuffer];
if (cbInfo.fIsEmpty) {
// We will change the render pass to do a clear load instead
GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE);
@ -182,7 +188,7 @@ void GrVkGpuCommandBuffer::discard() {
SkASSERT(cbInfo.fRenderPass->isCompatible(*oldRP));
oldRP->unref(fGpu);
fStartsWithClear = false;
cbInfo.fStartsWithClear = false;
}
}
@ -237,7 +243,7 @@ void GrVkGpuCommandBuffer::onClearStencilClip(const GrFixedClip& clip,
attachment.clearValue.depthStencil = vkStencilColor;
cbInfo.fCommandBuffer->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
fIsEmpty = false;
cbInfo.fIsEmpty = false;
// Update command buffer bounds
if (!clip.scissorEnabled()) {
@ -256,7 +262,7 @@ void GrVkGpuCommandBuffer::onClear(const GrFixedClip& clip, GrColor color) {
VkClearColorValue vkColor;
GrColorToRGBAFloat(color, vkColor.float32);
if (fIsEmpty && !clip.scissorEnabled()) {
if (cbInfo.fIsEmpty && !clip.scissorEnabled()) {
// We will change the render pass to do a clear load instead
GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE);
@ -281,7 +287,7 @@ void GrVkGpuCommandBuffer::onClear(const GrFixedClip& clip, GrColor color) {
oldRP->unref(fGpu);
GrColorToRGBAFloat(color, cbInfo.fColorClearValue.color.float32);
fStartsWithClear = true;
cbInfo.fStartsWithClear = true;
// Update command buffer bounds
cbInfo.fBounds.join(fRenderTarget->getBoundsRect());
@ -315,7 +321,7 @@ void GrVkGpuCommandBuffer::onClear(const GrFixedClip& clip, GrColor color) {
attachment.clearValue.color = vkColor;
cbInfo.fCommandBuffer->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
fIsEmpty = false;
cbInfo.fIsEmpty = false;
// Update command buffer bounds
if (!clip.scissorEnabled()) {
@ -326,6 +332,48 @@ void GrVkGpuCommandBuffer::onClear(const GrFixedClip& clip, GrColor color) {
return;
}
void GrVkGpuCommandBuffer::addAdditionalCommandBuffer() {
fCommandBufferInfos[fCurrentCmdBuffer].fCommandBuffer->end(fGpu);
CommandBufferInfo& cbInfo = fCommandBufferInfos.push_back();
fCurrentCmdBuffer++;
GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE);
GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE);
const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
fRenderTarget->compatibleRenderPassHandle();
if (rpHandle.isValid()) {
cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
vkColorOps,
vkStencilOps);
} else {
cbInfo.fRenderPass = fGpu->resourceProvider().findRenderPass(*fRenderTarget,
vkColorOps,
vkStencilOps);
}
cbInfo.fCommandBuffer = fGpu->resourceProvider().findOrCreateSecondaryCommandBuffer();
// It shouldn't matter what we set the clear color to here since we will assume loading of the
// attachment.
memset(&cbInfo.fColorClearValue, 0, sizeof(VkClearValue));
cbInfo.fBounds.setEmpty();
cbInfo.fIsEmpty = true;
cbInfo.fStartsWithClear = false;
cbInfo.fCommandBuffer->begin(fGpu, fRenderTarget->framebuffer(), cbInfo.fRenderPass);
}
void GrVkGpuCommandBuffer::inlineUpload(GrBatchFlushState* state,
GrDrawBatch::DeferredUploadFn& upload) {
if (!fCommandBufferInfos[fCurrentCmdBuffer].fIsEmpty) {
this->addAdditionalCommandBuffer();
}
fCommandBufferInfos[fCurrentCmdBuffer].fPreDrawUploads.emplace_back(state, upload);
}
////////////////////////////////////////////////////////////////////////////////
void GrVkGpuCommandBuffer::bindGeometry(const GrPrimitiveProcessor& primProc,
@ -471,7 +519,7 @@ void GrVkGpuCommandBuffer::onDraw(const GrPipeline& pipeline,
nonIdxMesh->startVertex(),
0);
}
fIsEmpty = false;
cbInfo.fIsEmpty = false;
fGpu->stats()->incNumDraws();
} while ((nonIdxMesh = iter.next()));

View File

@ -34,6 +34,8 @@ public:
void discard() override;
void inlineUpload(GrBatchFlushState* state, GrDrawBatch::DeferredUploadFn& upload) override;
private:
GrGpu* gpu() override;
GrRenderTarget* renderTarget() override;
@ -57,11 +59,25 @@ private:
void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override;
void addAdditionalCommandBuffer();
struct InlineUploadInfo {
InlineUploadInfo(GrBatchFlushState* state, const GrDrawBatch::DeferredUploadFn& upload)
: fFlushState(state)
, fUpload(upload) {}
GrBatchFlushState* fFlushState;
GrDrawBatch::DeferredUploadFn fUpload;
};
struct CommandBufferInfo {
const GrVkRenderPass* fRenderPass;
GrVkSecondaryCommandBuffer* fCommandBuffer;
VkClearValue fColorClearValue;
SkRect fBounds;
const GrVkRenderPass* fRenderPass;
GrVkSecondaryCommandBuffer* fCommandBuffer;
VkClearValue fColorClearValue;
SkRect fBounds;
bool fIsEmpty;
bool fStartsWithClear;
SkTArray<InlineUploadInfo> fPreDrawUploads;
};
SkTArray<CommandBufferInfo> fCommandBufferInfos;
@ -70,9 +86,6 @@ private:
GrVkGpu* fGpu;
GrVkRenderTarget* fRenderTarget;
bool fIsEmpty;
bool fStartsWithClear;
typedef GrGpuCommandBuffer INHERITED;
};