[graphite] Add ExtractRenderStepData

This doesn't reuse memory w/in the gatherer but sets us up to do so.

Bug: skia:12701
Change-Id: If5ed962e73609b113581ed2bd681e872fe3214c0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/526029
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2022-03-31 09:45:53 -04:00 committed by SkCQ
parent ee9ecfa478
commit 0ec0c38e2e
14 changed files with 75 additions and 40 deletions

View File

@ -122,7 +122,9 @@ generated_cc_atom(
":ContextUtils_hdr", ":ContextUtils_hdr",
":PaintParams_hdr", ":PaintParams_hdr",
":RecorderPriv_hdr", ":RecorderPriv_hdr",
":Renderer_hdr",
":ResourceProvider_hdr", ":ResourceProvider_hdr",
":UniformManager_hdr",
"//include/private:SkUniquePaintParamsID_hdr", "//include/private:SkUniquePaintParamsID_hdr",
"//src/core:SkBlenderBase_hdr", "//src/core:SkBlenderBase_hdr",
"//src/core:SkKeyContext_hdr", "//src/core:SkKeyContext_hdr",

View File

@ -10,7 +10,9 @@
#include <string> #include <string>
#include "experimental/graphite/src/PaintParams.h" #include "experimental/graphite/src/PaintParams.h"
#include "experimental/graphite/src/RecorderPriv.h" #include "experimental/graphite/src/RecorderPriv.h"
#include "experimental/graphite/src/Renderer.h"
#include "experimental/graphite/src/ResourceProvider.h" #include "experimental/graphite/src/ResourceProvider.h"
#include "experimental/graphite/src/UniformManager.h"
#include "include/private/SkUniquePaintParamsID.h" #include "include/private/SkUniquePaintParamsID.h"
#include "src/core/SkBlenderBase.h" #include "src/core/SkBlenderBase.h"
#include "src/core/SkKeyContext.h" #include "src/core/SkKeyContext.h"
@ -47,4 +49,20 @@ ExtractPaintData(Recorder* recorder,
return { entry->uniqueID(), uniformIndex, textureIndex }; return { entry->uniqueID(), uniformIndex, textureIndex };
} }
UniformDataCache::Index ExtractRenderStepData(UniformDataCache* geometryUniformDataCache,
SkPipelineDataGatherer* gatherer,
const RenderStep* step,
const DrawGeometry& geometry) {
SkDEBUGCODE(gatherer->checkReset());
// TODO: Get layout from the GPU
step->writeUniforms(Layout::kMetal, geometry, gatherer);
UniformDataCache::Index uIndex = geometryUniformDataCache->insert(gatherer->uniformDataBlock());
gatherer->reset();
return uIndex;
}
} // namespace skgpu } // namespace skgpu

View File

@ -16,8 +16,10 @@ class SkUniquePaintParamsID;
namespace skgpu { namespace skgpu {
class DrawGeometry;
class PaintParams; class PaintParams;
class Recorder; class Recorder;
class RenderStep;
std::tuple<SkUniquePaintParamsID, UniformDataCache::Index, TextureDataCache::Index> std::tuple<SkUniquePaintParamsID, UniformDataCache::Index, TextureDataCache::Index>
ExtractPaintData(Recorder*, ExtractPaintData(Recorder*,
@ -25,6 +27,11 @@ ExtractPaintData(Recorder*,
SkPaintParamsKeyBuilder* builder, SkPaintParamsKeyBuilder* builder,
const PaintParams&); const PaintParams&);
UniformDataCache::Index ExtractRenderStepData(UniformDataCache* geometryUniformDataCache,
SkPipelineDataGatherer* gatherer,
const RenderStep* step,
const DrawGeometry& geometry);
} // namespace skgpu } // namespace skgpu
#endif // skgpu_ContextUtils_DEFINED #endif // skgpu_ContextUtils_DEFINED

View File

@ -195,15 +195,6 @@ public:
, fUniformDataCache(uniformDataCache) { , fUniformDataCache(uniformDataCache) {
} }
UniformDataCache::Index addUniforms(const SkUniformDataBlock& uniformDataBlock) {
if (uniformDataBlock.empty()) {
return {};
}
UniformDataCache::Index uIndex = fUniformDataCache->insert(uniformDataBlock);
return this->addUniforms(uIndex);
}
UniformDataCache::Index addUniforms(UniformDataCache::Index uIndex) { UniformDataCache::Index addUniforms(UniformDataCache::Index uIndex) {
if (!uIndex.isValid()) { if (!uIndex.isValid()) {
return {}; return {};
@ -354,11 +345,12 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
UniformDataCache::Index geometryUniformIndex; UniformDataCache::Index geometryUniformIndex;
if (step->numUniforms() > 0) { if (step->numUniforms() > 0) {
// TODO: Get layout from the GPU UniformDataCache::Index uniformDataIndex;
auto uniforms = step->writeUniforms(Layout::kMetal, draw.fGeometry); uniformDataIndex = ExtractRenderStepData(&geometryUniformDataCache,
&gatherer,
geometryUniformIndex = geometryUniformBindings.addUniforms( step,
SkUniformDataBlock(std::move(uniforms))); draw.fGeometry);
geometryUniformIndex = geometryUniformBindings.addUniforms(uniformDataIndex);
} }
GraphicsPipelineDesc desc; GraphicsPipelineDesc desc;

View File

@ -25,6 +25,7 @@
#include <vector> #include <vector>
enum class SkPathFillType; enum class SkPathFillType;
class SkPipelineDataGatherer;
class SkUniformData; class SkUniformData;
namespace skgpu { namespace skgpu {
@ -53,7 +54,9 @@ public:
// nice if we could remember the offsets for the layout/gpu and reuse them across draws. // nice if we could remember the offsets for the layout/gpu and reuse them across draws.
// Similarly, it would be nice if this could write into reusable storage and then DrawPass or // Similarly, it would be nice if this could write into reusable storage and then DrawPass or
// UniformCache handles making an sk_sp if we need to assign a new unique ID to the uniform data // UniformCache handles making an sk_sp if we need to assign a new unique ID to the uniform data
virtual sk_sp<SkUniformData> writeUniforms(Layout layout, const DrawGeometry&) const = 0; virtual void writeUniforms(Layout layout,
const DrawGeometry&,
SkPipelineDataGatherer*) const = 0;
// Returns a name formatted as "Subclass[variant]", where "Subclass" matches the C++ class name // Returns a name formatted as "Subclass[variant]", where "Subclass" matches the C++ class name
// and variant is a unique term describing instance's specific configuration. // and variant is a unique term describing instance's specific configuration.

View File

@ -56,9 +56,10 @@ void CoverBoundsRenderStep::writeVertices(DrawWriter* writer, const DrawGeometry
<< devPoints[2].x << devPoints[2].y << depth << devPoints[2].w;// BR << devPoints[2].x << devPoints[2].y << depth << devPoints[2].w;// BR
} }
sk_sp<SkUniformData> CoverBoundsRenderStep::writeUniforms(Layout, const DrawGeometry&) const { void CoverBoundsRenderStep::writeUniforms(Layout,
const DrawGeometry&,
SkPipelineDataGatherer*) const {
// Control points are pre-transformed to device space on the CPU, so no uniforms needed. // Control points are pre-transformed to device space on the CPU, so no uniforms needed.
return nullptr;
} }
} // namespace skgpu } // namespace skgpu

View File

@ -20,7 +20,7 @@ public:
const char* vertexSkSL() const override; const char* vertexSkSL() const override;
void writeVertices(DrawWriter*, const DrawGeometry&) const override; void writeVertices(DrawWriter*, const DrawGeometry&) const override;
sk_sp<SkUniformData> writeUniforms(Layout, const DrawGeometry&) const override; void writeUniforms(Layout, const DrawGeometry&, SkPipelineDataGatherer*) const override;
private: private:
const bool fInverseFill; const bool fInverseFill;

View File

@ -60,9 +60,10 @@ void MiddleOutFanRenderStep::writeVertices(DrawWriter* writer, const DrawGeometr
} }
} }
sk_sp<SkUniformData> MiddleOutFanRenderStep::writeUniforms(Layout, const DrawGeometry&) const { void MiddleOutFanRenderStep::writeUniforms(Layout,
const DrawGeometry&,
SkPipelineDataGatherer*) const {
// Control points are pre-transformed to device space on the CPU, so no uniforms needed. // Control points are pre-transformed to device space on the CPU, so no uniforms needed.
return nullptr;
} }
} // namespace skgpu } // namespace skgpu

View File

@ -23,7 +23,7 @@ public:
const char* vertexSkSL() const override; const char* vertexSkSL() const override;
void writeVertices(DrawWriter*, const DrawGeometry&) const override; void writeVertices(DrawWriter*, const DrawGeometry&) const override;
sk_sp<SkUniformData> writeUniforms(Layout, const DrawGeometry&) const override; void writeUniforms(Layout, const DrawGeometry&, SkPipelineDataGatherer*) const override;
}; };
} // namespace skgpu } // namespace skgpu

View File

@ -206,9 +206,10 @@ void TessellateCurvesRenderStep::writeVertices(DrawWriter* dw, const DrawGeometr
} }
} }
sk_sp<SkUniformData> TessellateCurvesRenderStep::writeUniforms(Layout, const DrawGeometry&) const { void TessellateCurvesRenderStep::writeUniforms(Layout,
const DrawGeometry&,
SkPipelineDataGatherer*) const {
// Control points are pre-transformed to device space on the CPU, so no uniforms needed. // Control points are pre-transformed to device space on the CPU, so no uniforms needed.
return nullptr;
} }
} // namespace skgpu } // namespace skgpu

View File

@ -23,7 +23,7 @@ public:
const char* vertexSkSL() const override; const char* vertexSkSL() const override;
void writeVertices(DrawWriter*, const DrawGeometry&) const override; void writeVertices(DrawWriter*, const DrawGeometry&) const override;
sk_sp<SkUniformData> writeUniforms(Layout, const DrawGeometry&) const override; void writeUniforms(Layout, const DrawGeometry&, SkPipelineDataGatherer*) const override;
}; };
} // namespace skgpu } // namespace skgpu

View File

@ -241,9 +241,10 @@ void TessellateWedgesRenderStep::writeVertices(DrawWriter* dw, const DrawGeometr
} }
} }
sk_sp<SkUniformData> TessellateWedgesRenderStep::writeUniforms(Layout, const DrawGeometry&) const { void TessellateWedgesRenderStep::writeUniforms(Layout,
const DrawGeometry&,
SkPipelineDataGatherer*) const {
// Control points are pre-transformed to device space on the CPU, so no uniforms needed. // Control points are pre-transformed to device space on the CPU, so no uniforms needed.
return nullptr;
} }
} // namespace skgpu } // namespace skgpu

View File

@ -21,7 +21,7 @@ public:
const char* vertexSkSL() const override; const char* vertexSkSL() const override;
void writeVertices(DrawWriter*, const DrawGeometry&) const override; void writeVertices(DrawWriter*, const DrawGeometry&) const override;
sk_sp<SkUniformData> writeUniforms(Layout, const DrawGeometry&) const override; void writeUniforms(Layout, const DrawGeometry&, SkPipelineDataGatherer*) const override;
}; };

View File

@ -74,16 +74,18 @@ public:
writer->draw({}, 4); writer->draw({}, 4);
} }
sk_sp<SkUniformData> writeUniforms(Layout layout, const DrawGeometry& geom) const override { void writeUniforms(Layout layout,
const DrawGeometry& geom,
SkPipelineDataGatherer* gatherer) const override {
SkASSERT(geom.shape().isRect()); SkASSERT(geom.shape().isRect());
// TODO: A << API for uniforms would be nice, particularly if it could take pre-computed // TODO: A << API for uniforms would be nice, particularly if it could take pre-computed
// offsets for each uniform. // offsets for each uniform.
auto uniforms = SkUniformData::Make(this->uniforms(), sizeof(float) * 4); sk_sp<SkUniformData> uniforms = SkUniformData::Make(this->uniforms(), sizeof(float) * 4);
float2 scale = geom.shape().rect().size(); float2 scale = geom.shape().rect().size();
float2 translate = geom.shape().rect().topLeft(); float2 translate = geom.shape().rect().topLeft();
memcpy(uniforms->data(), &scale, sizeof(float2)); memcpy(uniforms->data(), &scale, sizeof(float2));
memcpy(uniforms->data() + sizeof(float2), &translate, sizeof(float2)); memcpy(uniforms->data() + sizeof(float2), &translate, sizeof(float2));
return uniforms; gatherer->add(std::move(uniforms));
} }
private: private:
@ -133,11 +135,13 @@ public:
writer->drawIndexed(vertices, indices, 6); writer->drawIndexed(vertices, indices, 6);
} }
sk_sp<SkUniformData> writeUniforms(Layout layout, const DrawGeometry&) const override { void writeUniforms(Layout layout,
auto uniforms = SkUniformData::Make(this->uniforms(), sizeof(float) * 4); const DrawGeometry&,
SkPipelineDataGatherer* gatherer) const override {
sk_sp<SkUniformData> uniforms = SkUniformData::Make(this->uniforms(), sizeof(float) * 4);
float data[4] = {2.f, 2.f, -1.f, -1.f}; float data[4] = {2.f, 2.f, -1.f, -1.f};
memcpy(uniforms->data(), data, 4 * sizeof(float)); memcpy(uniforms->data(), data, 4 * sizeof(float));
return uniforms; gatherer->add(std::move(uniforms));
} }
private: private:
@ -183,9 +187,7 @@ public:
instances.append(1) << geom.shape().rect().topLeft() << geom.shape().rect().size(); instances.append(1) << geom.shape().rect().topLeft() << geom.shape().rect().size();
} }
sk_sp<SkUniformData> writeUniforms(Layout, const DrawGeometry&) const override { void writeUniforms(Layout, const DrawGeometry&, SkPipelineDataGatherer*) const override { }
return nullptr;
}
private: private:
InstanceRectDraw() InstanceRectDraw()
@ -288,6 +290,8 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
SkColor4f fColor; SkColor4f fColor;
}; };
SkPipelineDataGatherer gatherer;
auto draw = [&](const RenderStep* step, std::vector<RectAndColor> draws) { auto draw = [&](const RenderStep* step, std::vector<RectAndColor> draws) {
GraphicsPipelineDesc pipelineDesc; GraphicsPipelineDesc pipelineDesc;
pipelineDesc.setProgram(step, uniqueID); pipelineDesc.setProgram(step, uniqueID);
@ -312,15 +316,20 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
DrawOrder order(depth); DrawOrder order(depth);
DrawGeometry geom{kIdentity, shape, {shape.bounds(), kBounds}, order, nullptr}; DrawGeometry geom{kIdentity, shape, {shape.bounds(), kBounds}, order, nullptr};
auto renderStepUniforms = step->writeUniforms(Layout::kMetal, geom); SkDEBUGCODE(gatherer.checkReset());
if (renderStepUniforms) { step->writeUniforms(Layout::kMetal, geom, &gatherer);
if (gatherer.hasUniforms()) {
SkUniformDataBlock* renderStepUniforms = &gatherer.uniformDataBlock();
auto [writer, bindInfo] = auto [writer, bindInfo] =
bufferMgr.getUniformWriter(renderStepUniforms->dataSize()); bufferMgr.getUniformWriter(renderStepUniforms->totalUniformSize());
writer.write(renderStepUniforms->data(), renderStepUniforms->dataSize()); for (const auto &u : *renderStepUniforms) {
writer.write(u->data(), u->dataSize());
}
commandBuffer->bindUniformBuffer(UniformSlot::kRenderStep, commandBuffer->bindUniformBuffer(UniformSlot::kRenderStep,
sk_ref_sp(bindInfo.fBuffer), sk_ref_sp(bindInfo.fBuffer),
bindInfo.fOffset); bindInfo.fOffset);
} }
gatherer.reset();
// TODO: Rely on uniform writer and GetUniforms(kSolidColor). // TODO: Rely on uniform writer and GetUniforms(kSolidColor).
auto [writer, bindInfo] = bufferMgr.getUniformWriter(sizeof(SkColor4f)); auto [writer, bindInfo] = bufferMgr.getUniformWriter(sizeof(SkColor4f));