Add a bindBuffers() call to GrOpsRenderPass

Adds a bindBuffers() call and removes the GrBuffer arguments from the
draw calls.

Change-Id: I43c2dd8afe80c41e48c1d9d5210affcfe6f095fc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/273840
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Chris Dalton 2020-03-02 11:45:27 -07:00 committed by Skia Commit-Bot
parent 4c0ffe7820
commit ded437003d
10 changed files with 282 additions and 285 deletions

View File

@ -200,30 +200,33 @@ inline void GrMesh::setVertexData(sk_sp<const GrBuffer> vertexBuffer, int baseVe
inline void GrMesh::draw(GrOpsRenderPass* opsRenderPass) const {
if (this->isInstanced()) {
if (!this->isIndexed()) {
opsRenderPass->drawInstanced(fInstanceBuffer.get(), fInstanceData.fInstanceCount,
fInstanceData.fBaseInstance, fVertexBuffer.get(),
opsRenderPass->bindBuffers(nullptr, fInstanceBuffer.get(), fVertexBuffer.get());
opsRenderPass->drawInstanced(fInstanceData.fInstanceCount, fInstanceData.fBaseInstance,
fInstanceNonIndexData.fVertexCount, fBaseVertex);
} else {
opsRenderPass->bindBuffers(fIndexBuffer.get(), fInstanceBuffer.get(),
fVertexBuffer.get(), this->primitiveRestart());
opsRenderPass->drawIndexedInstanced(
fIndexBuffer.get(), fInstanceIndexData.fIndexCount, 0, this->primitiveRestart(),
fInstanceBuffer.get(), fInstanceData.fInstanceCount,
fInstanceData.fBaseInstance, fVertexBuffer.get(), fBaseVertex);
fInstanceIndexData.fIndexCount, 0, fInstanceData.fInstanceCount,
fInstanceData.fBaseInstance, fBaseVertex);
}
return;
}
if (!this->isIndexed()) {
SkASSERT(fNonIndexNonInstanceData.fVertexCount > 0);
opsRenderPass->draw(fVertexBuffer.get(), fNonIndexNonInstanceData.fVertexCount,
fBaseVertex);
opsRenderPass->bindBuffers(nullptr, nullptr, fVertexBuffer.get());
opsRenderPass->draw(fNonIndexNonInstanceData.fVertexCount, fBaseVertex);
return;
}
opsRenderPass->bindBuffers(fIndexBuffer.get(), nullptr, fVertexBuffer.get(),
this->primitiveRestart());
if (0 == fIndexData.fPatternRepeatCount) {
opsRenderPass->drawIndexed(
fIndexBuffer.get(), fIndexData.fIndexCount, fNonPatternIndexData.fBaseIndex,
this->primitiveRestart(), fNonPatternIndexData.fMinIndexValue,
fNonPatternIndexData.fMaxIndexValue, fVertexBuffer.get(), fBaseVertex);
opsRenderPass->drawIndexed(fIndexData.fIndexCount, fNonPatternIndexData.fBaseIndex,
fNonPatternIndexData.fMinIndexValue,
fNonPatternIndexData.fMaxIndexValue, fBaseVertex);
return;
}
@ -237,8 +240,7 @@ inline void GrMesh::draw(GrOpsRenderPass* opsRenderPass) const {
int minIndexValue = 0;
int maxIndexValue = fPatternData.fVertexCount * repeatCount - 1;
SkASSERT(!(fFlags & Flags::kUsePrimitiveRestart));
opsRenderPass->drawIndexed(fIndexBuffer.get(), indexCount, 0, this->primitiveRestart(),
minIndexValue, maxIndexValue, fVertexBuffer.get(),
opsRenderPass->drawIndexed(indexCount, 0, minIndexValue, maxIndexValue,
fBaseVertex + fPatternData.fVertexCount * baseRepetition);
baseRepetition += repeatCount;
} while (baseRepetition < fIndexData.fPatternRepeatCount);

View File

@ -91,8 +91,11 @@ void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRec
}
fTextureBindingStatus = (hasTextures) ?
DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
fHasVertexAttributes = programInfo.primProc().hasVertexAttributes();
fHasInstanceAttributes = programInfo.primProc().hasInstanceAttributes();
fHasIndexBuffer = false;
fInstanceBufferStatus = (programInfo.primProc().hasInstanceAttributes()) ?
DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
fVertexBufferStatus = (programInfo.primProc().hasVertexAttributes()) ?
DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
#endif
fDrawPipelineStatus = DrawPipelineStatus::kOk;
@ -149,6 +152,36 @@ void GrOpsRenderPass::drawMeshes(const GrProgramInfo& programInfo, const GrMesh
}
}
void GrOpsRenderPass::bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrPrimitiveRestart primRestart) {
if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
return;
}
#ifdef SK_DEBUG
if (indexBuffer) {
fHasIndexBuffer = true;
}
SkASSERT((DynamicStateStatus::kDisabled == fInstanceBufferStatus) != SkToBool(instanceBuffer));
if (instanceBuffer) {
fInstanceBufferStatus = DynamicStateStatus::kConfigured;
}
SkASSERT((DynamicStateStatus::kDisabled == fVertexBufferStatus) != SkToBool(vertexBuffer));
if (vertexBuffer) {
fVertexBufferStatus = DynamicStateStatus::kConfigured;
}
if (GrPrimitiveRestart::kYes == primRestart) {
SkASSERT(this->gpu()->caps()->usePrimitiveRestart());
}
#endif
this->onBindBuffers(indexBuffer, instanceBuffer, vertexBuffer, primRestart);
}
bool GrOpsRenderPass::prepareToDraw() {
if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
@ -164,52 +197,45 @@ bool GrOpsRenderPass::prepareToDraw() {
return true;
}
void GrOpsRenderPass::draw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) {
void GrOpsRenderPass::draw(int vertexCount, int baseVertex) {
if (!this->prepareToDraw()) {
return;
}
SkASSERT(SkToBool(vertexBuffer) == fHasVertexAttributes);
this->onDraw(vertexBuffer, vertexCount, baseVertex);
SkASSERT(!fHasIndexBuffer);
SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
this->onDraw(vertexCount, baseVertex);
}
void GrOpsRenderPass::drawIndexed(const GrBuffer* indexBuffer, int indexCount,
int baseIndex, GrPrimitiveRestart primitiveRestart,
uint16_t minIndexValue, uint16_t maxIndexValue,
const GrBuffer* vertexBuffer, int baseVertex) {
void GrOpsRenderPass::drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
uint16_t maxIndexValue, int baseVertex) {
if (!this->prepareToDraw()) {
return;
}
SkASSERT(GrPrimitiveRestart::kNo == primitiveRestart ||
this->gpu()->caps()->usePrimitiveRestart());
SkASSERT(SkToBool(vertexBuffer) == fHasVertexAttributes);
this->onDrawIndexed(indexBuffer, indexCount, baseIndex, primitiveRestart, minIndexValue,
maxIndexValue, vertexBuffer, baseVertex);
SkASSERT(fHasIndexBuffer);
SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
this->onDrawIndexed(indexCount, baseIndex, minIndexValue, maxIndexValue, baseVertex);
}
void GrOpsRenderPass::drawInstanced(const GrBuffer* instanceBuffer, int instanceCount, int
baseInstance, const GrBuffer* vertexBuffer, int vertexCount,
void GrOpsRenderPass::drawInstanced(int instanceCount, int baseInstance, int vertexCount,
int baseVertex) {
if (!this->prepareToDraw()) {
return;
}
SkASSERT(SkToBool(vertexBuffer) == fHasVertexAttributes);
SkASSERT(SkToBool(instanceBuffer) == fHasInstanceAttributes);
this->onDrawInstanced(instanceBuffer, instanceCount, baseInstance, vertexBuffer, vertexCount,
baseVertex);
SkASSERT(!fHasIndexBuffer);
SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex);
}
void GrOpsRenderPass::drawIndexedInstanced(
const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart primitiveRestart, const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer, int baseVertex) {
void GrOpsRenderPass::drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
int baseInstance, int baseVertex) {
if (!this->prepareToDraw()) {
return;
}
SkASSERT(GrPrimitiveRestart::kNo == primitiveRestart ||
this->gpu()->caps()->usePrimitiveRestart());
SkASSERT(SkToBool(vertexBuffer) == fHasVertexAttributes);
SkASSERT(SkToBool(instanceBuffer) == fHasInstanceAttributes);
this->onDrawIndexedInstanced(indexBuffer, indexCount, baseIndex, primitiveRestart,
instanceBuffer, instanceCount, baseInstance, vertexBuffer,
baseVertex);
SkASSERT(fHasIndexBuffer);
SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance, baseVertex);
}

View File

@ -66,9 +66,14 @@ public:
// again with a different array for primProcTextures. (On subsequent calls, if the backend is
// capable of updating the primitive processor textures independently, then it will
// automatically skip binding textures from GrPipeline.)
//
// If the current program does not use textures, this is a no-op.
void bindTextures(const GrPrimitiveProcessor&, const GrPipeline&,
const GrSurfaceProxy* const primProcTextures[]);
void bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrPrimitiveRestart = GrPrimitiveRestart::kNo);
// Draws the given array of meshes using the current pipeline state. The client must call
// bindPipeline() before using this method.
//
@ -76,18 +81,19 @@ public:
// setScissor() and bindTextures() on the client's behalf.
void drawMeshes(const GrProgramInfo&, const GrMesh[], int meshCount);
// These methods issue draws using the current pipeline state. The client must call
// bindPipeline(), followed by setScissor() and/or bindTextures() if applicable, before using
// these methods.
void draw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex);
void drawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex, GrPrimitiveRestart,
uint16_t minIndexValue, uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
// These methods issue draws using the current pipeline state. Before drawing, the caller must
// configure the pipeline and dynamic state:
//
// - Call bindPipeline()
// - If the scissor test is enabled, call setScissorRect()
// - If the current program uses textures, call bindTextures()
// - Call bindBuffers() (even if all buffers are null)
void draw(int vertexCount, int baseVertex);
void drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue,
int baseVertex);
void drawInstanced(const GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
const GrBuffer* vertexBuffer, int vertexCount, int baseVertex);
void drawIndexedInstanced(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer, int baseVertex);
void drawInstanced(int instanceCount, int baseInstance, int vertexCount, int baseVertex);
void drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
int baseVertex);
// Performs an upload of vertex data in the middle of a set of a set of draws
virtual void inlineUpload(GrOpFlushState*, GrDeferredTextureUploadFn&) = 0;
@ -132,17 +138,15 @@ private:
virtual void onSetScissorRect(const SkIRect&) = 0;
virtual bool onBindTextures(const GrPrimitiveProcessor&, const GrPipeline&,
const GrSurfaceProxy* const primProcTextures[]) = 0;
virtual void onDraw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) = 0;
virtual void onDrawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, uint16_t minIndexValue, uint16_t maxIndexValue,
const GrBuffer* vertexBuffer, int baseVertex) = 0;
virtual void onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer, int vertexCount,
virtual void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrPrimitiveRestart) = 0;
virtual void onDraw(int vertexCount, int baseVertex) = 0;
virtual void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
uint16_t maxIndexValue, int baseVertex) = 0;
virtual void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
int baseVertex) = 0;
virtual void onDrawIndexedInstanced(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, const GrBuffer* instanceBuffer,
int instanceCount, int baseInstance,
const GrBuffer* vertexBuffer, int baseVertex) = 0;
virtual void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
int baseInstance, int baseVertex) = 0;
virtual void onClear(const GrFixedClip&, const SkPMColor4f&) = 0;
virtual void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) = 0;
virtual void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) {}
@ -165,8 +169,9 @@ private:
DynamicStateStatus fScissorStatus = DynamicStateStatus::kDisabled;
DynamicStateStatus fTextureBindingStatus = DynamicStateStatus::kDisabled;
bool fHasVertexAttributes = false;
bool fHasInstanceAttributes = false;
bool fHasIndexBuffer = false;
DynamicStateStatus fInstanceBufferStatus = DynamicStateStatus::kDisabled;
DynamicStateStatus fVertexBufferStatus = DynamicStateStatus::kDisabled;
#endif
typedef GrOpsRenderPass INHERITED;

View File

@ -46,9 +46,9 @@ bool GrGLOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc,
return true;
}
void GrGLOpsRenderPass::setupGeometry(const GrBuffer* indexBuffer, const GrBuffer* vertexBuffer,
int baseVertex, const GrBuffer* instanceBuffer,
int baseInstance, GrPrimitiveRestart primitiveRestart) {
void GrGLOpsRenderPass::onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer,
GrPrimitiveRestart primitiveRestart) {
SkASSERT((primitiveRestart == GrPrimitiveRestart::kNo) || indexBuffer);
GrGLProgram* program = fGpu->currentProgram();
if (!program) {
@ -56,7 +56,29 @@ void GrGLOpsRenderPass::setupGeometry(const GrBuffer* indexBuffer, const GrBuffe
}
int numAttribs = program->numVertexAttributes() + program->numInstanceAttributes();
auto* attribState = fGpu->bindInternalVertexArray(indexBuffer, numAttribs, primitiveRestart);
fAttribArrayState = fGpu->bindInternalVertexArray(indexBuffer, numAttribs, primitiveRestart);
if (indexBuffer) {
if (indexBuffer->isCpuBuffer()) {
auto* cpuIndexBuffer = static_cast<const GrCpuBuffer*>(indexBuffer);
fIndexPointer = reinterpret_cast<const uint16_t*>(cpuIndexBuffer->data());
} else {
fIndexPointer = nullptr;
}
}
// We defer binding of instance and vertex buffers because GL does not (always) support base
// instance and/or base vertex.
fDeferredInstanceBuffer = sk_ref_sp(instanceBuffer);
fDeferredVertexBuffer = sk_ref_sp(vertexBuffer);
}
void GrGLOpsRenderPass::setupGeometry(const GrBuffer* vertexBuffer, int baseVertex,
const GrBuffer* instanceBuffer, int baseInstance) {
GrGLProgram* program = fGpu->currentProgram();
if (!program) {
return;
}
if (int vertexStride = program->vertexStride()) {
SkASSERT(vertexBuffer);
@ -66,8 +88,9 @@ void GrGLOpsRenderPass::setupGeometry(const GrBuffer* indexBuffer, const GrBuffe
for (int i = 0; i < program->numVertexAttributes(); ++i) {
const auto& attrib = program->vertexAttribute(i);
static constexpr int kDivisor = 0;
attribState->set(fGpu, attrib.fLocation, vertexBuffer, attrib.fCPUType, attrib.fGPUType,
vertexStride, bufferOffset + attrib.fOffset, kDivisor);
fAttribArrayState->set(fGpu, attrib.fLocation, vertexBuffer, attrib.fCPUType,
attrib.fGPUType, vertexStride, bufferOffset + attrib.fOffset,
kDivisor);
}
}
if (int instanceStride = program->instanceStride()) {
@ -79,69 +102,55 @@ void GrGLOpsRenderPass::setupGeometry(const GrBuffer* indexBuffer, const GrBuffe
for (int i = 0; i < program->numInstanceAttributes(); ++i, ++attribIdx) {
const auto& attrib = program->instanceAttribute(i);
static constexpr int kDivisor = 1;
attribState->set(fGpu, attrib.fLocation, instanceBuffer, attrib.fCPUType,
attrib.fGPUType, instanceStride, bufferOffset + attrib.fOffset,
kDivisor);
fAttribArrayState->set(fGpu, attrib.fLocation, instanceBuffer, attrib.fCPUType,
attrib.fGPUType, instanceStride, bufferOffset + attrib.fOffset,
kDivisor);
}
}
}
static const GrGLvoid* get_gl_index_ptr(const GrBuffer* indexBuffer, int baseIndex) {
size_t baseOffset = baseIndex * sizeof(uint16_t);
if (indexBuffer->isCpuBuffer()) {
return static_cast<const GrCpuBuffer*>(indexBuffer)->data() + baseOffset;
} else {
return reinterpret_cast<const GrGLvoid*>(baseOffset);
}
}
void GrGLOpsRenderPass::onDraw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) {
void GrGLOpsRenderPass::onDraw(int vertexCount, int baseVertex) {
if (fGpu->glCaps().drawArraysBaseVertexIsBroken()) {
this->setupGeometry(nullptr, vertexBuffer, baseVertex, nullptr, 0, GrPrimitiveRestart::kNo);
this->setupGeometry(fDeferredVertexBuffer.get(), baseVertex, nullptr, 0);
fGpu->drawArrays(fPrimitiveType, 0, vertexCount);
return;
}
this->setupGeometry(nullptr, vertexBuffer, 0, nullptr, 0, GrPrimitiveRestart::kNo);
this->setupGeometry(fDeferredVertexBuffer.get(), 0, nullptr, 0);
fGpu->drawArrays(fPrimitiveType, baseVertex, vertexCount);
}
void GrGLOpsRenderPass::onDrawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart primitiveRestart, uint16_t minIndexValue,
uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
int baseVertex) {
const GrGLvoid* indexPtr = get_gl_index_ptr(indexBuffer, baseIndex);
this->setupGeometry(indexBuffer, vertexBuffer, baseVertex, nullptr, 0, primitiveRestart);
void GrGLOpsRenderPass::onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
uint16_t maxIndexValue, int baseVertex) {
this->setupGeometry(fDeferredVertexBuffer.get(), baseVertex, nullptr, 0);
if (fGpu->glCaps().drawRangeElementsSupport()) {
fGpu->drawRangeElements(fPrimitiveType, minIndexValue, maxIndexValue, indexCount,
GR_GL_UNSIGNED_SHORT, indexPtr);
GR_GL_UNSIGNED_SHORT, fIndexPointer + baseIndex);
} else {
fGpu->drawElements(fPrimitiveType, indexCount, GR_GL_UNSIGNED_SHORT, indexPtr);
fGpu->drawElements(fPrimitiveType, indexCount, GR_GL_UNSIGNED_SHORT,
fIndexPointer + baseIndex);
}
}
void GrGLOpsRenderPass::onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer,
int vertexCount, int baseVertex) {
void GrGLOpsRenderPass::onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
int baseVertex) {
int maxInstances = fGpu->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
for (int i = 0; i < instanceCount; i += maxInstances) {
this->setupGeometry(nullptr, vertexBuffer, 0, instanceBuffer, baseInstance + i,
GrPrimitiveRestart::kNo);
this->setupGeometry(fDeferredVertexBuffer.get(), 0, fDeferredInstanceBuffer.get(),
baseInstance + i);
fGpu->drawArraysInstanced(fPrimitiveType, baseVertex, vertexCount,
std::min(instanceCount - i, maxInstances));
}
}
void GrGLOpsRenderPass::onDrawIndexedInstanced(
const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart primitiveRestart, const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer, int baseVertex) {
const GrGLvoid* indexPtr = get_gl_index_ptr(indexBuffer, baseIndex);
void GrGLOpsRenderPass::onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
int baseInstance, int baseVertex) {
int maxInstances = fGpu->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
for (int i = 0; i < instanceCount; i += maxInstances) {
this->setupGeometry(indexBuffer, vertexBuffer, baseVertex,
instanceBuffer, baseInstance + i, primitiveRestart);
fGpu->drawElementsInstanced(fPrimitiveType, indexCount, GR_GL_UNSIGNED_SHORT, indexPtr,
this->setupGeometry(fDeferredVertexBuffer.get(), baseVertex, fDeferredInstanceBuffer.get(),
baseInstance + i);
fGpu->drawElementsInstanced(fPrimitiveType, indexCount, GR_GL_UNSIGNED_SHORT,
fIndexPointer + baseIndex,
std::min(instanceCount - i, maxInstances));
}
}

View File

@ -49,23 +49,21 @@ public:
private:
GrGpu* gpu() override { return fGpu; }
void setupGeometry(const GrBuffer* indexBuffer, const GrBuffer* vertexBuffer, int baseVertex,
const GrBuffer* instanceBuffer, int baseInstance,
GrPrimitiveRestart enablePrimitiveRestart);
void setupGeometry(const GrBuffer* vertexBuffer, int baseVertex, const GrBuffer* instanceBuffer,
int baseInstance);
bool onBindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) override;
void onSetScissorRect(const SkIRect& scissor) override;
bool onBindTextures(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline,
const GrSurfaceProxy* const primProcTextures[]) override;
void onDraw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) override;
void onDrawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, uint16_t minIndexValue, uint16_t maxIndexValue,
const GrBuffer* vertexBuffer, int baseVertex) override;
void onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) override;
void onDrawIndexedInstanced(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, const GrBuffer* instanceBuffer,
int instanceCount, int baseInstance, const GrBuffer* vertexBuffer,
void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrPrimitiveRestart) override;
void onDraw(int vertexCount, int baseVertex) override;
void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
uint16_t maxIndexValue, int baseVertex) override;
void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
int baseVertex) override;
void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
int baseVertex) override;
void onClear(const GrFixedClip& clip, const SkPMColor4f& color) override;
void onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) override;
@ -77,6 +75,16 @@ private:
// Per-pipeline state.
GrPrimitiveType fPrimitiveType;
GrGLAttribArrayState* fAttribArrayState = nullptr;
// If using an index buffer, this gets set during onBindBuffers. It is either the CPU address of
// the indices, or nullptr if they reside physically in GPU memory.
const uint16_t* fIndexPointer;
// We may defer binding of instance and vertex buffers because GL does not always support a base
// instance and/or vertex.
sk_sp<const GrBuffer> fDeferredInstanceBuffer;
sk_sp<const GrBuffer> fDeferredVertexBuffer;
typedef GrOpsRenderPass INHERITED;
};

View File

@ -34,35 +34,17 @@ public:
int numDraws() const { return fNumDraws; }
private:
bool onBindPipeline(const GrProgramInfo&, const SkRect&) override {
return true;
}
bool onBindPipeline(const GrProgramInfo&, const SkRect&) override { return true; }
void onSetScissorRect(const SkIRect&) override {}
bool onBindTextures(const GrPrimitiveProcessor&, const GrPipeline&,
const GrSurfaceProxy* const primProcTextures[]) override {
return true;
}
void onDraw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) override {
this->dummyDraw();
}
void onDrawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, uint16_t minIndexValue, uint16_t maxIndexValue,
const GrBuffer* vertexBuffer, int baseVertex) override {
this->dummyDraw();
}
void onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) override {
this->dummyDraw();
}
void onDrawIndexedInstanced(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, const GrBuffer* instanceBuffer,
int instanceCount, int baseInstance, const GrBuffer* vertexBuffer,
int baseVertex) override {
this->dummyDraw();
}
void onClear(const GrFixedClip&, const SkPMColor4f&) override {
this->markRenderTargetDirty();
}
const GrSurfaceProxy* const primProcTextures[]) override { return true; }
void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrPrimitiveRestart) override {}
void onDraw(int, int) override { this->dummyDraw(); }
void onDrawIndexed(int, int, uint16_t, uint16_t, int) override { this->dummyDraw(); }
void onDrawInstanced(int, int, int, int) override { this->dummyDraw(); }
void onDrawIndexedInstanced(int, int, int, int, int) override { this->dummyDraw(); }
void onClear(const GrFixedClip&, const SkPMColor4f&) override { this->markRenderTargetDirty(); }
void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override {}
void dummyDraw() {
this->markRenderTargetDirty();

View File

@ -43,15 +43,14 @@ private:
void onSetScissorRect(const SkIRect&) override;
bool onBindTextures(const GrPrimitiveProcessor&, const GrPipeline&,
const GrSurfaceProxy* const primProcTextures[]) override;
void onDraw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) override;
void onDrawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, uint16_t minIndexValue, uint16_t maxIndexValue,
const GrBuffer* vertexBuffer, int baseVertex) override;
void onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) override;
void onDrawIndexedInstanced(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, const GrBuffer* instanceBuffer,
int instanceCount, int baseInstance, const GrBuffer* vertexBuffer,
void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrPrimitiveRestart) override;
void onDraw(int vertexCount, int baseVertex) override;
void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
uint16_t maxIndexValue, int baseVertex) override;
void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
int baseVertex) override;
void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
int baseVertex) override;
void onClear(const GrFixedClip& clip, const SkPMColor4f& color) override;
@ -61,11 +60,8 @@ private:
void setupRenderPass(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo);
void bindGeometry(const GrBuffer* vertexBuffer, size_t vertexOffset,
const GrBuffer* instanceBuffer);
void setVertexBuffer(id<MTLRenderCommandEncoder>, const GrMtlBuffer*, size_t offset,
size_t index);
size_t inputBufferIndex);
void resetBufferBindings();
void precreateCmdEncoder();
@ -76,6 +72,12 @@ private:
MTLPrimitiveType fActivePrimitiveType;
MTLRenderPassDescriptor* fRenderPassDesc;
SkRect fBounds;
// The index buffer in metal is an argument to the draw call, rather than a stateful binding.
sk_sp<const GrMtlBuffer> fIndexBuffer;
// We defer binding of the vertex buffer because Metal doesn't have baseVertex for drawIndexed.
sk_sp<const GrMtlBuffer> fDeferredVertexBuffer;
size_t fCurrentVertexStride;
static constexpr size_t kNumBindings = GrMtlUniformHandler::kLastUniformBinding + 3;

View File

@ -246,70 +246,63 @@ void GrMtlOpsRenderPass::setupRenderPass(
fActiveRenderCmdEncoder = nil;
}
void GrMtlOpsRenderPass::bindGeometry(const GrBuffer* vertexBuffer,
size_t vertexOffset,
const GrBuffer* instanceBuffer) {
size_t bufferIndex = GrMtlUniformHandler::kLastUniformBinding + 1;
void GrMtlOpsRenderPass::onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer,
GrPrimitiveRestart primRestart) {
SkASSERT(GrPrimitiveRestart::kNo == primRestart);
int inputBufferIndex = 0;
if (vertexBuffer) {
SkASSERT(!vertexBuffer->isCpuBuffer());
SkASSERT(!static_cast<const GrGpuBuffer*>(vertexBuffer)->isMapped());
const GrMtlBuffer* grMtlBuffer = static_cast<const GrMtlBuffer*>(vertexBuffer);
this->setVertexBuffer(fActiveRenderCmdEncoder, grMtlBuffer, vertexOffset, bufferIndex++);
fDeferredVertexBuffer = sk_ref_sp(static_cast<const GrMtlBuffer*>(vertexBuffer));
++inputBufferIndex;
}
if (instanceBuffer) {
SkASSERT(!instanceBuffer->isCpuBuffer());
SkASSERT(!static_cast<const GrGpuBuffer*>(instanceBuffer)->isMapped());
const GrMtlBuffer* grMtlBuffer = static_cast<const GrMtlBuffer*>(instanceBuffer);
this->setVertexBuffer(fActiveRenderCmdEncoder, grMtlBuffer, 0, bufferIndex++);
this->setVertexBuffer(fActiveRenderCmdEncoder, grMtlBuffer, 0, inputBufferIndex++);
}
if (indexBuffer) {
SkASSERT(!indexBuffer->isCpuBuffer());
SkASSERT(!static_cast<const GrGpuBuffer*>(indexBuffer)->isMapped());
fIndexBuffer = sk_ref_sp(static_cast<const GrMtlBuffer*>(indexBuffer));
}
}
void GrMtlOpsRenderPass::onDraw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) {
void GrMtlOpsRenderPass::onDraw(int vertexCount, int baseVertex) {
SkASSERT(fActivePipelineState);
SkASSERT(nil != fActiveRenderCmdEncoder);
this->bindGeometry(vertexBuffer, 0, nullptr);
this->setVertexBuffer(fActiveRenderCmdEncoder, fDeferredVertexBuffer.get(), 0, 0);
[fActiveRenderCmdEncoder drawPrimitives:fActivePrimitiveType
vertexStart:baseVertex
vertexCount:vertexCount];
}
void GrMtlOpsRenderPass::onDrawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart primitiveRestart, uint16_t minIndexValue,
uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
int baseVertex) {
void GrMtlOpsRenderPass::onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
uint16_t maxIndexValue, int baseVertex) {
SkASSERT(fActivePipelineState);
SkASSERT(nil != fActiveRenderCmdEncoder);
this->bindGeometry(vertexBuffer, fCurrentVertexStride*baseVertex, nullptr);
SkASSERT(fIndexBuffer);
this->setVertexBuffer(fActiveRenderCmdEncoder, fDeferredVertexBuffer.get(),
fCurrentVertexStride * baseVertex, 0);
id<MTLBuffer> mtlIndexBuffer = nil;
if (indexBuffer) {
SkASSERT(!indexBuffer->isCpuBuffer());
SkASSERT(!static_cast<const GrGpuBuffer*>(indexBuffer)->isMapped());
mtlIndexBuffer = static_cast<const GrMtlBuffer*>(indexBuffer)->mtlBuffer();
SkASSERT(mtlIndexBuffer);
}
SkASSERT(primitiveRestart == GrPrimitiveRestart::kNo);
size_t indexOffset = static_cast<const GrMtlBuffer*>(indexBuffer)->offset() +
sizeof(uint16_t) * baseIndex;
size_t indexOffset = fIndexBuffer->offset() + sizeof(uint16_t) * baseIndex;
[fActiveRenderCmdEncoder drawIndexedPrimitives:fActivePrimitiveType
indexCount:indexCount
indexType:MTLIndexTypeUInt16
indexBuffer:mtlIndexBuffer
indexBuffer:fIndexBuffer->mtlBuffer()
indexBufferOffset:indexOffset];
fGpu->stats()->incNumDraws();
}
void GrMtlOpsRenderPass::onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer,
int vertexCount, int baseVertex) {
void GrMtlOpsRenderPass::onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
int baseVertex) {
SkASSERT(fActivePipelineState);
SkASSERT(nil != fActiveRenderCmdEncoder);
this->bindGeometry(vertexBuffer, 0, instanceBuffer);
this->setVertexBuffer(fActiveRenderCmdEncoder, fDeferredVertexBuffer.get(), 0, 0);
if (@available(macOS 10.11, iOS 9.0, *)) {
[fActiveRenderCmdEncoder drawPrimitives:fActivePrimitiveType
@ -323,31 +316,18 @@ void GrMtlOpsRenderPass::onDrawInstanced(const GrBuffer* instanceBuffer, int ins
}
void GrMtlOpsRenderPass::onDrawIndexedInstanced(
const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart primitiveRestart, const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer, int baseVertex) {
int indexCount, int baseIndex, int instanceCount, int baseInstance, int baseVertex) {
SkASSERT(fActivePipelineState);
SkASSERT(nil != fActiveRenderCmdEncoder);
this->bindGeometry(vertexBuffer, 0, instanceBuffer);
id<MTLBuffer> mtlIndexBuffer = nil;
if (indexBuffer) {
SkASSERT(!indexBuffer->isCpuBuffer());
SkASSERT(!static_cast<const GrGpuBuffer*>(indexBuffer)->isMapped());
mtlIndexBuffer = static_cast<const GrMtlBuffer*>(indexBuffer)->mtlBuffer();
SkASSERT(mtlIndexBuffer);
}
SkASSERT(primitiveRestart == GrPrimitiveRestart::kNo);
size_t indexOffset = static_cast<const GrMtlBuffer*>(indexBuffer)->offset() +
sizeof(uint16_t) * baseIndex;
SkASSERT(fIndexBuffer);
this->setVertexBuffer(fActiveRenderCmdEncoder, fDeferredVertexBuffer.get(), 0, 0);
size_t indexOffset = fIndexBuffer->offset() + sizeof(uint16_t) * baseIndex;
if (@available(macOS 10.11, iOS 9.0, *)) {
[fActiveRenderCmdEncoder drawIndexedPrimitives:fActivePrimitiveType
indexCount:indexCount
indexType:MTLIndexTypeUInt16
indexBuffer:mtlIndexBuffer
indexBuffer:fIndexBuffer->mtlBuffer()
indexBufferOffset:indexOffset
instanceCount:instanceCount
baseVertex:baseVertex
@ -361,7 +341,9 @@ void GrMtlOpsRenderPass::onDrawIndexedInstanced(
void GrMtlOpsRenderPass::setVertexBuffer(id<MTLRenderCommandEncoder> encoder,
const GrMtlBuffer* buffer,
size_t vertexOffset,
size_t index) {
size_t inputBufferIndex) {
constexpr static int kFirstBufferBindingIdx = GrMtlUniformHandler::kLastUniformBinding + 1;
int index = inputBufferIndex + kFirstBufferBindingIdx;
SkASSERT(index < 4);
id<MTLBuffer> mtlVertexBuffer = buffer->mtlBuffer();
SkASSERT(mtlVertexBuffer);

View File

@ -443,42 +443,6 @@ void GrVkOpsRenderPass::inlineUpload(GrOpFlushState* state, GrDeferredTextureUpl
////////////////////////////////////////////////////////////////////////////////
void GrVkOpsRenderPass::bindGeometry(const GrGpuBuffer* indexBuffer,
const GrGpuBuffer* vertexBuffer,
const GrGpuBuffer* instanceBuffer) {
GrVkCommandBuffer* currCmdBuf = this->currentCommandBuffer();
// There is no need to put any memory barriers to make sure host writes have finished here.
// When a command buffer is submitted to a queue, there is an implicit memory barrier that
// occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of
// an active RenderPass.
// Here our vertex and instance inputs need to match the same 0-based bindings they were
// assigned in GrVkPipeline. That is, vertex first (if any) followed by instance.
uint32_t binding = 0;
if (vertexBuffer) {
SkASSERT(vertexBuffer);
SkASSERT(!vertexBuffer->isMapped());
currCmdBuf->bindInputBuffer(fGpu, binding++,
static_cast<const GrVkVertexBuffer*>(vertexBuffer));
}
if (instanceBuffer) {
SkASSERT(instanceBuffer);
SkASSERT(!instanceBuffer->isMapped());
currCmdBuf->bindInputBuffer(fGpu, binding++,
static_cast<const GrVkVertexBuffer*>(instanceBuffer));
}
if (indexBuffer) {
SkASSERT(indexBuffer);
SkASSERT(!indexBuffer->isMapped());
currCmdBuf->bindIndexBuffer(fGpu, static_cast<const GrVkIndexBuffer*>(indexBuffer));
}
}
#ifdef SK_DEBUG
void check_sampled_texture(GrTexture* tex, GrRenderTarget* rt, GrVkGpu* gpu) {
SkASSERT(!tex->isProtected() || (rt->isProtected() && gpu->protectedContext()));
@ -582,45 +546,70 @@ void GrVkOpsRenderPass::onSetScissorRect(const SkIRect& scissor) {
bool GrVkOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
const GrSurfaceProxy* const primProcTextures[]) {
SkASSERT(fCurrentPipelineState);
return fCurrentPipelineState->setAndBindTextures(fGpu, primProc, pipeline, primProcTextures,
this->currentCommandBuffer());
}
void GrVkOpsRenderPass::onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer,
void GrVkOpsRenderPass::onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer,
GrPrimitiveRestart primRestart) {
SkASSERT(GrPrimitiveRestart::kNo == primRestart);
if (!fCurrentRenderPass) {
SkASSERT(fGpu->isDeviceLost());
return;
}
SkASSERT(fCurrentPipelineState);
SkASSERT(!fGpu->caps()->usePrimitiveRestart()); // Ignore primitiveRestart parameter.
GrVkCommandBuffer* currCmdBuf = this->currentCommandBuffer();
SkASSERT(currCmdBuf);
// There is no need to put any memory barriers to make sure host writes have finished here.
// When a command buffer is submitted to a queue, there is an implicit memory barrier that
// occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of
// an active RenderPass.
// Here our vertex and instance inputs need to match the same 0-based bindings they were
// assigned in GrVkPipeline. That is, vertex first (if any) followed by instance.
uint32_t binding = 0;
if (auto* vkVertexBuffer = static_cast<const GrVkVertexBuffer*>(vertexBuffer)) {
SkASSERT(!vkVertexBuffer->isCpuBuffer());
SkASSERT(!vkVertexBuffer->isMapped());
currCmdBuf->bindInputBuffer(fGpu, binding++, vkVertexBuffer);
}
if (auto* vkInstanceBuffer = static_cast<const GrVkVertexBuffer*>(instanceBuffer)) {
SkASSERT(!vkInstanceBuffer->isCpuBuffer());
SkASSERT(!vkInstanceBuffer->isMapped());
currCmdBuf->bindInputBuffer(fGpu, binding++, vkInstanceBuffer);
}
if (auto* vkIndexBuffer = static_cast<const GrVkIndexBuffer*>(indexBuffer)) {
SkASSERT(!vkIndexBuffer->isCpuBuffer());
SkASSERT(!vkIndexBuffer->isMapped());
currCmdBuf->bindIndexBuffer(fGpu, vkIndexBuffer);
}
}
void GrVkOpsRenderPass::onDrawInstanced(int instanceCount,
int baseInstance,
int vertexCount, int baseVertex) {
if (!fCurrentRenderPass) {
SkASSERT(fGpu->isDeviceLost());
return;
}
SkASSERT(fCurrentPipelineState);
SkASSERT(!vertexBuffer || !vertexBuffer->isCpuBuffer());
SkASSERT(!instanceBuffer || !instanceBuffer->isCpuBuffer());
auto gpuVertexBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer);
auto gpuInstanceBuffer = static_cast<const GrGpuBuffer*>(instanceBuffer);
this->bindGeometry(nullptr, gpuVertexBuffer, gpuInstanceBuffer);
this->currentCommandBuffer()->draw(fGpu, vertexCount, instanceCount, baseVertex, baseInstance);
fGpu->stats()->incNumDraws();
fCurrentCBIsEmpty = false;
}
void GrVkOpsRenderPass::onDrawIndexedInstanced(
const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart primitiveRestart, const GrBuffer* instanceBuffer, int instanceCount,
int baseInstance, const GrBuffer* vertexBuffer, int baseVertex) {
void GrVkOpsRenderPass::onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
int baseInstance, int baseVertex) {
if (!fCurrentRenderPass) {
SkASSERT(fGpu->isDeviceLost());
return;
}
SkASSERT(fCurrentPipelineState);
SkASSERT(primitiveRestart == GrPrimitiveRestart::kNo);
SkASSERT(!vertexBuffer || !vertexBuffer->isCpuBuffer());
SkASSERT(!instanceBuffer || !instanceBuffer->isCpuBuffer());
SkASSERT(!indexBuffer->isCpuBuffer());
auto gpuIndexxBuffer = static_cast<const GrGpuBuffer*>(indexBuffer);
auto gpuVertexBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer);
auto gpuInstanceBuffer = static_cast<const GrGpuBuffer*>(instanceBuffer);
this->bindGeometry(gpuIndexxBuffer, gpuVertexBuffer, gpuInstanceBuffer);
this->currentCommandBuffer()->drawIndexed(fGpu, indexCount, instanceCount,
baseIndex, baseVertex, baseInstance);
fGpu->stats()->incNumDraws();

View File

@ -63,30 +63,22 @@ private:
GrVkCommandBuffer* currentCommandBuffer();
// Bind vertex and index buffers
void bindGeometry(const GrGpuBuffer* indexBuffer,
const GrGpuBuffer* vertexBuffer,
const GrGpuBuffer* instanceBuffer);
bool onBindPipeline(const GrProgramInfo&, const SkRect& drawBounds) override;
void onSetScissorRect(const SkIRect&) override;
bool onBindTextures(const GrPrimitiveProcessor&, const GrPipeline&,
const GrSurfaceProxy* const primProcTextures[]) override;
void onDraw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) override {
this->onDrawInstanced(nullptr, 1, 0, vertexBuffer, vertexCount, baseVertex);
void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
const GrBuffer* vertexBuffer, GrPrimitiveRestart) override;
void onDraw(int vertexCount, int baseVertex) override {
this->onDrawInstanced(1, 0, vertexCount, baseVertex);
}
void onDrawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart primitiveRestart, uint16_t minIndexValue,
uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
int baseVertex) override {
this->onDrawIndexedInstanced(indexBuffer, indexCount, baseIndex, primitiveRestart, nullptr,
1, 0, vertexBuffer, baseVertex);
void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
uint16_t maxIndexValue, int baseVertex) override {
this->onDrawIndexedInstanced(indexCount, baseIndex, 1, 0, baseVertex);
}
void onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount, int baseInstance,
const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) override;
void onDrawIndexedInstanced(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
GrPrimitiveRestart, const GrBuffer* instanceBuffer,
int instanceCount, int baseInstance, const GrBuffer* vertexBuffer,
void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
int baseVertex) override;
void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
int baseVertex) override;
void onClear(const GrFixedClip&, const SkPMColor4f& color) override;