diff --git a/experimental/graphite/src/DrawBufferManager.cpp b/experimental/graphite/src/DrawBufferManager.cpp index fc6108621d..b94ef105a4 100644 --- a/experimental/graphite/src/DrawBufferManager.cpp +++ b/experimental/graphite/src/DrawBufferManager.cpp @@ -34,6 +34,12 @@ static bool can_fit(size_t requestedSize, } std::tuple DrawBufferManager::getVertexWriter(size_t requiredBytes) { + if (!requiredBytes) { + BindBufferInfo bindInfo; + bindInfo.fBuffer = nullptr; + bindInfo.fOffset = 0; + return {VertexWriter(nullptr), bindInfo}; + } if (fCurrentVertexBuffer && !can_fit(requiredBytes, fCurrentVertexBuffer.get(), fVertexOffset, /*alignment=*/1)) { fUsedBuffers.push_back(std::move(fCurrentVertexBuffer)); @@ -57,6 +63,12 @@ std::tuple DrawBufferManager::getVertexWriter(size } std::tuple DrawBufferManager::getIndexWriter(size_t requiredBytes) { + if (!requiredBytes) { + BindBufferInfo bindInfo; + bindInfo.fBuffer = nullptr; + bindInfo.fOffset = 0; + return {IndexWriter(nullptr), bindInfo}; + } if (fCurrentIndexBuffer && !can_fit(requiredBytes, fCurrentIndexBuffer.get(), fIndexOffset, /*alignment=*/1)) { fUsedBuffers.push_back(std::move(fCurrentIndexBuffer)); @@ -81,6 +93,12 @@ std::tuple DrawBufferManager::getIndexWriter(size_t std::tuple DrawBufferManager::getUniformWriter( size_t requiredBytes) { + if (!requiredBytes) { + BindBufferInfo bindInfo; + bindInfo.fBuffer = nullptr; + bindInfo.fOffset = 0; + return {UniformWriter(nullptr), bindInfo}; + } if (fCurrentUniformBuffer && !can_fit(requiredBytes, fCurrentUniformBuffer.get(), diff --git a/experimental/graphite/src/DrawList.cpp b/experimental/graphite/src/DrawList.cpp index 998754303d..0d0beea467 100644 --- a/experimental/graphite/src/DrawList.cpp +++ b/experimental/graphite/src/DrawList.cpp @@ -9,6 +9,7 @@ #include "experimental/graphite/src/Renderer.h" #include "include/core/SkShader.h" +#include "src/gpu/BufferWriter.h" namespace skgpu { @@ -88,4 +89,23 @@ void DrawList::strokePath(const Transform& localToDevice, // fRenderStepCount += Renderer::StrokePath().numRenderSteps(); } +size_t DrawList::Draw::requiredVertexSpace(int renderStep) const { + SkASSERT(renderStep < fRenderer.numRenderSteps()); + return fRenderer.steps()[renderStep]->requiredVertexSpace(fShape); +} + +size_t DrawList::Draw::requiredIndexSpace(int renderStep) const { + SkASSERT(renderStep < fRenderer.numRenderSteps()); + return fRenderer.steps()[renderStep]->requiredIndexSpace(fShape); +} + +void DrawList::Draw::writeVertices(VertexWriter vertexWriter, + IndexWriter indexWriter, + int renderStep) const { + SkASSERT(renderStep < fRenderer.numRenderSteps()); + fRenderer.steps()[renderStep]->writeVertices(std::move(vertexWriter), + std::move(indexWriter), + fShape); +} + } // namespace skgpu diff --git a/experimental/graphite/src/DrawList.h b/experimental/graphite/src/DrawList.h index 4aba8c7ebd..5c5b823855 100644 --- a/experimental/graphite/src/DrawList.h +++ b/experimental/graphite/src/DrawList.h @@ -25,7 +25,9 @@ struct SkIRect; namespace skgpu { +struct IndexWriter; class Renderer; +struct VertexWriter; // TBD: If occlusion culling is eliminated as a phase, we can easily move the paint conversion // back to Device when the command is recorded (similar to SkPaint -> GrPaint), and then @@ -212,6 +214,11 @@ private: , fOrder(order) , fPaintParams(paint ? skstd::optional(*paint) : skstd::nullopt) , fStrokeParams(stroke ? skstd::optional(*stroke) : skstd::nullopt) {} + + size_t requiredVertexSpace(int renderStep) const; + size_t requiredIndexSpace(int renderStep) const; + + void writeVertices(VertexWriter, IndexWriter, int renderStep) const; }; // The returned Transform reference remains valid for the lifetime of the DrawList. diff --git a/experimental/graphite/src/DrawPass.cpp b/experimental/graphite/src/DrawPass.cpp index b44602345c..1609b86046 100644 --- a/experimental/graphite/src/DrawPass.cpp +++ b/experimental/graphite/src/DrawPass.cpp @@ -8,6 +8,7 @@ #include "experimental/graphite/src/DrawPass.h" #include "experimental/graphite/include/GraphiteTypes.h" +#include "experimental/graphite/src/Buffer.h" #include "experimental/graphite/src/ContextUtils.h" #include "experimental/graphite/src/DrawBufferManager.h" #include "experimental/graphite/src/DrawContext.h" @@ -21,6 +22,7 @@ #include "src/core/SkMathPriv.h" #include "src/core/SkUtils.h" +#include "src/gpu/BufferWriter.h" #include @@ -234,8 +236,36 @@ std::unique_ptr DrawPass::Make(Recorder* recorder, uint32_t lastShadingUniforms = UniformData::kInvalidUniformID; uint32_t lastGeometryUniforms = 0; SkIRect lastScissor = SkIRect::MakeSize(target->dimensions()); + Buffer* lastBoundVertexBuffer = nullptr; + Buffer* lastBoundIndexBuffer = nullptr; + for (const SortKey& key : keys) { const DrawList::Draw& draw = *key.draw(); + int renderStep = key.renderStep(); + + size_t vertexSize = draw.requiredVertexSpace(renderStep); + size_t indexSize = draw.requiredIndexSpace(renderStep); + auto [vertexWriter, vertexInfo] = bufferMgr->getVertexWriter(vertexSize); + auto [indexWriter, indexInfo] = bufferMgr->getIndexWriter(indexSize); + draw.writeVertices(std::move(vertexWriter), std::move(indexWriter), renderStep); + + if (vertexSize) { + SkASSERT(vertexWriter); + if (lastBoundVertexBuffer != vertexInfo.fBuffer) { + // TODO: Record a vertex bind call that stores the vertexInfo.fBuffer. + } + // TODO: Store the vertexInfo.fOffset so the draw will know its vertex offset when it + // executes. + } + if (indexSize) { + SkASSERT(indexWriter); + if (lastBoundIndexBuffer != indexInfo.fBuffer) { + // TODO: Record a vertex bind call that stores the vertexInfo.fBuffer. + } + // TODO: Store the vertexInfo.fOffset so the draw will know its vertex offset when it + // executes. + } + // TODO: Have the render step write out vertices and figure out what draw call function and // primitive type it uses. The vertex buffer binding/offset and draw params will be examined // to determine if the active draw can be updated to include the new vertices, or if it has diff --git a/experimental/graphite/src/Renderer.h b/experimental/graphite/src/Renderer.h index b390a81371..7d067c7c0d 100644 --- a/experimental/graphite/src/Renderer.h +++ b/experimental/graphite/src/Renderer.h @@ -16,6 +16,10 @@ namespace skgpu { +struct IndexWriter; +class Shape; +struct VertexWriter; + class RenderStep { public: virtual ~RenderStep() {} @@ -25,6 +29,10 @@ public: virtual bool requiresMSAA() const = 0; virtual bool performsShading() const = 0; + virtual size_t requiredVertexSpace(const Shape&) const = 0; + virtual size_t requiredIndexSpace(const Shape&) const = 0; + virtual void writeVertices(VertexWriter, IndexWriter, const Shape&) const = 0; + // TODO: Actual API to do things // 1. Provide stencil settings // 2. Provide shader key or MSL(?) for the vertex stage diff --git a/experimental/graphite/src/render/StencilAndFillPathRenderer.cpp b/experimental/graphite/src/render/StencilAndFillPathRenderer.cpp index 48ca3d10f3..b4c55af7d6 100644 --- a/experimental/graphite/src/render/StencilAndFillPathRenderer.cpp +++ b/experimental/graphite/src/render/StencilAndFillPathRenderer.cpp @@ -7,6 +7,9 @@ #include "experimental/graphite/src/Renderer.h" +#include "experimental/graphite/src/geom/Shape.h" +#include "src/gpu/BufferWriter.h" + namespace skgpu { namespace { @@ -61,6 +64,21 @@ public: bool requiresMSAA() const override { return false; } bool performsShading() const override { return true; } + size_t requiredVertexSpace(const Shape&) const override { + return 8 * sizeof(float); + } + + size_t requiredIndexSpace(const Shape&) const override { + return 0; + } + + void writeVertices(VertexWriter vertexWriter, + IndexWriter indexWriter, + const Shape& shape) const override { + vertexWriter.writeQuad(VertexWriter::TriStripFromRect(shape.bounds().asSkRect())); + } + + private: };