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