blob: 5e6fb1295152161f6ab8af5693953bde29a67e60 [file] [log] [blame]
/*
* 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/DrawWriter.h"
#include "src/gpu/BufferWriter.h"
#include "src/gpu/graphite/DrawCommands.h"
namespace skgpu::graphite {
DrawWriter::DrawWriter(DrawPassCommands::List* commandList, DrawBufferManager* bufferManager)
: fCommandList(commandList)
, fManager(bufferManager)
, fPrimitiveType(PrimitiveType::kTriangles)
, fVertexStride(0)
, fInstanceStride(0)
, fVertices()
, fIndices()
, fInstances()
, fTemplateCount(0)
, fPendingCount(0)
, fPendingBase(0)
, fPendingBufferBinds(true) {
SkASSERT(commandList && bufferManager);
}
void DrawWriter::setTemplate(BindBufferInfo vertices,
BindBufferInfo indices,
BindBufferInfo instances,
int templateCount) {
if (vertices != fVertices || instances != fInstances || fIndices != indices) {
if (fPendingCount > 0) {
this->flush();
}
bool willAppendVertices = templateCount == 0;
bool isAppendingVertices = fTemplateCount == 0;
if (willAppendVertices != isAppendingVertices ||
(isAppendingVertices && fVertices != vertices) ||
(!isAppendingVertices && fInstances != instances)) {
// The buffer binding target for appended data is changing, so reset the base offset
fPendingBase = 0;
}
fVertices = vertices;
fInstances = instances;
fIndices = indices;
fTemplateCount = templateCount;
fPendingBufferBinds = true;
} else if ((templateCount >= 0 && templateCount != fTemplateCount) || // vtx or reg. instances
(templateCount < 0 && fTemplateCount >= 0)) { // dynamic index instances
if (fPendingCount > 0) {
this->flush();
}
if ((templateCount == 0) != (fTemplateCount == 0)) {
// Switching from appending vertices to instances, or vice versa, so the pending
// base vertex for appended data is invalid
fPendingBase = 0;
}
fTemplateCount = templateCount;
}
SkASSERT(fVertices == vertices);
SkASSERT(fInstances == instances);
SkASSERT(fIndices == indices);
// NOTE: This allows 'fTemplateCount' to update across multiple DynamicInstances as long
// as they have the same vertex and index buffers.
SkASSERT((fTemplateCount < 0) == (templateCount < 0));
SkASSERT(fTemplateCount < 0 || fTemplateCount == templateCount);
}
void DrawWriter::flush() {
// If nothing was appended, or the only appended data was through dynamic instances and the
// final vertex count per instance is 0 (-1 in the sign encoded field), nothing should be drawn.
if (fPendingCount == 0 || fTemplateCount == -1) {
return;
}
if (fPendingBufferBinds) {
fCommandList->bindDrawBuffers(fVertices, fInstances, fIndices);
fPendingBufferBinds = false;
}
if (fTemplateCount) {
// Instanced drawing
unsigned int realVertexCount;
if (fTemplateCount < 0) {
realVertexCount = -fTemplateCount - 1;
fTemplateCount = -1; // reset to re-accumulate max index account for next flush
} else {
realVertexCount = fTemplateCount;
}
if (fIndices) {
fCommandList->drawIndexedInstanced(fPrimitiveType, 0, realVertexCount, 0,
fPendingBase, fPendingCount);
} else {
fCommandList->drawInstanced(fPrimitiveType, 0, realVertexCount,
fPendingBase, fPendingCount);
}
} else {
SkASSERT(!fInstances);
if (fIndices) {
fCommandList->drawIndexed(fPrimitiveType, 0, fPendingCount, fPendingBase);
} else {
fCommandList->draw(fPrimitiveType, fPendingBase, fPendingCount);
}
}
fPendingBase += fPendingCount;
fPendingCount = 0;
}
} // namespace skgpu::graphite