[graphite] Partially connect DrawPass, UniformCache and ProgramCache

Bug: skia:12466
Change-Id: Ib23a501664ebba581376fa0cb1ce5c6537e5d349
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/465136
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Robert Phillips 2021-10-29 11:25:24 -04:00 committed by SkCQ
parent 0dfb2d9679
commit 527d127719
7 changed files with 95 additions and 30 deletions

View File

@ -303,7 +303,7 @@ void Device::flushPendingWorkToRecorder() {
// TODO: iterate the clip stack and issue a depth-only draw for every clip element that has
// a non-empty usage bounds, using that bounds as the scissor.
auto drawTask = fDC->snapRenderPassTask(fColorDepthBoundsManager.get());
auto drawTask = fDC->snapRenderPassTask(fRecorder.get(), fColorDepthBoundsManager.get());
if (drawTask) {
fRecorder->add(std::move(drawTask));
}

View File

@ -75,18 +75,19 @@ void DrawContext::strokePath(const Transform& localToDevice,
fPendingDraws->strokePath(localToDevice, shape, stroke, clip, order, paint);
}
void DrawContext::snapDrawPass(const BoundsManager* occlusionCuller) {
void DrawContext::snapDrawPass(Recorder* recorder, const BoundsManager* occlusionCuller) {
if (fPendingDraws->drawCount() == 0) {
return;
}
auto pass = DrawPass::Make(std::move(fPendingDraws), fTarget, occlusionCuller);
auto pass = DrawPass::Make(recorder, std::move(fPendingDraws), fTarget, occlusionCuller);
fDrawPasses.push_back(std::move(pass));
fPendingDraws = std::make_unique<DrawList>();
}
sk_sp<Task> DrawContext::snapRenderPassTask(const BoundsManager* occlusionCuller) {
this->snapDrawPass(occlusionCuller);
sk_sp<Task> DrawContext::snapRenderPassTask(Recorder* recorder,
const BoundsManager* occlusionCuller) {
this->snapDrawPass(recorder, occlusionCuller);
if (fDrawPasses.empty()) {
return nullptr;
}

View File

@ -19,6 +19,7 @@
namespace skgpu {
class BoundsManager;
class Recorder;
class Shape;
class Transform;
@ -74,7 +75,7 @@ public:
// DrawPass.
// TBD - should this also return the task so the caller can point to it with its own
// dependencies? Or will that be mostly automatic based on draws and proxy refs?
void snapDrawPass(const BoundsManager* occlusionCuller);
void snapDrawPass(Recorder*, const BoundsManager* occlusionCuller);
// TBD: snapRenderPassTask() might not need to be public, and could be spec'ed to require that
// snapDrawPass() must have been called first. A lot of it will depend on how the task graph is
@ -85,7 +86,7 @@ public:
// caller is responsible for configuring the returned Tasks's dependencies.
//
// Returns null if there are no pending commands or draw passes to move into a task.
sk_sp<Task> snapRenderPassTask(const BoundsManager* occlusionCuller);
sk_sp<Task> snapRenderPassTask(Recorder*, const BoundsManager* occlusionCuller);
private:
DrawContext(sk_sp<TextureProxy>, const SkImageInfo&);

View File

@ -8,9 +8,33 @@
#include "experimental/graphite/src/DrawList.h"
#include "experimental/graphite/src/Renderer.h"
#include "include/core/SkShader.h"
namespace skgpu {
PaintParams::PaintParams(const SkColor4f& color,
SkBlendMode blendMode,
sk_sp<SkShader> shader)
: fColor(color)
, fBlendMode(blendMode)
, fShader(std::move(shader)) {
}
PaintParams::PaintParams(const PaintParams& other)
: fColor(other.fColor)
, fBlendMode(other.fBlendMode)
, fShader(other.fShader) {
}
PaintParams::~PaintParams() {}
PaintParams& PaintParams::operator=(const PaintParams& other) {
fColor = other.fColor;
fBlendMode = other.fBlendMode;
fShader = other.fShader;
return *this;
}
sk_sp<SkShader> PaintParams::refShader() const { return fShader; }
const Transform& DrawList::deduplicateTransform(const Transform& localToDevice) {
// TODO: This is a pretty simple deduplication strategy and doesn't take advantage of the stack
// knowledge that Device has.

View File

@ -10,7 +10,6 @@
#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "include/core/SkShader.h"
#include "include/private/SkTOptional.h"
#include "src/core/SkTBlockList.h"
@ -21,6 +20,7 @@
#include <limits>
class SkPath;
class SkShader;
struct SkIRect;
namespace skgpu {
@ -35,18 +35,16 @@ class Renderer;
// assumed to be anti-aliased.
class PaintParams {
public:
PaintParams(const SkColor4f& color,
SkBlendMode blendMode,
sk_sp<SkShader> shader)
: fColor(color)
, fBlendMode(blendMode)
, fShader(std::move(shader)) {}
PaintParams(const SkColor4f& color, SkBlendMode, sk_sp<SkShader>);
PaintParams(const PaintParams&);
~PaintParams();
PaintParams(const PaintParams&) = default;
PaintParams& operator=(const PaintParams&);
SkColor4f color() const { return fColor; }
SkBlendMode blendMode() const { return fBlendMode; }
SkShader* shader() const { return fShader.get(); }
SkColor4f color() const { return fColor; }
SkBlendMode blendMode() const { return fBlendMode; }
SkShader* shader() const { return fShader.get(); }
sk_sp<SkShader> refShader() const;
private:
SkColor4f fColor;
@ -71,6 +69,8 @@ public:
StrokeParams(const StrokeParams&) = default;
StrokeParams& operator=(const StrokeParams&) = default;
bool isMiterJoin() const { return fJoinLimit > 0.f; }
bool isBevelJoin() const { return fJoinLimit == 0.f; }
bool isRoundJoin() const { return fJoinLimit < 0.f; }

View File

@ -8,8 +8,11 @@
#include "experimental/graphite/src/DrawPass.h"
#include "experimental/graphite/include/GraphiteTypes.h"
#include "experimental/graphite/src/ContextUtils.h"
#include "experimental/graphite/src/DrawContext.h"
#include "experimental/graphite/src/DrawList.h"
#include "experimental/graphite/src/ProgramCache.h"
#include "experimental/graphite/src/Recorder.h"
#include "experimental/graphite/src/Renderer.h"
#include "experimental/graphite/src/TextureProxy.h"
#include "experimental/graphite/src/geom/BoundsManager.h"
@ -19,6 +22,27 @@
#include <algorithm>
namespace {
// Retrieve the program ID and uniformData ID
std::tuple<uint32_t, uint32_t> get_ids_from_paint(skgpu::Recorder* recorder,
skgpu::PaintParams params) {
// TODO: add an ExtractCombo that takes PaintParams directly?
SkPaint p;
p.setColor(params.color());
p.setBlendMode(params.blendMode());
p.setShader(params.refShader());
// TODO: perhaps just return the ids here rather than the sk_sps?
auto [ combo, uniformData] = ExtractCombo(recorder->uniformCache(), p);
auto programInfo = recorder->programCache()->findOrCreateProgram(combo);
return { programInfo->id(), uniformData->id() };
}
} // anonymous namespace
namespace skgpu {
/**
@ -108,7 +132,8 @@ DrawPass::DrawPass(sk_sp<TextureProxy> target, const SkIRect& bounds,
DrawPass::~DrawPass() = default;
std::unique_ptr<DrawPass> DrawPass::Make(std::unique_ptr<DrawList> draws,
std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
std::unique_ptr<DrawList> draws,
sk_sp<TextureProxy> target,
const BoundsManager* occlusionCuller) {
// NOTE: This assert is here to ensure SortKey is as tightly packed as possible. Any change to
@ -140,13 +165,15 @@ std::unique_ptr<DrawPass> DrawPass::Make(std::unique_ptr<DrawList> draws,
continue;
}
// TODO: Hand off to Rob/Jim for extracting shader and uniform data to CPU memory
// if draw.fPaintParams, analyze params and determine shader code and write out shading
// uniforms.
// If we have two different descriptors, such that the uniforms from the PaintParams can be
// bound independently of those used by the rest of the RenderStep, then we can upload now
// and remember 'shadingIndex' for re-use on any RenderStep that does shading.
int shadingIndex = 0;
// and remember the location for re-use on any RenderStep that does shading.
uint32_t programID = ProgramCache::kInvalidProgramID;
uint32_t shadingID = UniformData::kInvalidUniformID;
if (draw.fPaintParams.has_value()) {
std::tie(programID, shadingID) = get_ids_from_paint(recorder,
draw.fPaintParams.value());
}
for (int stepIndex = 0; stepIndex < draw.fRenderer.numRenderSteps(); ++stepIndex) {
const RenderStep* const step = draw.fRenderer.steps()[stepIndex];
@ -158,9 +185,19 @@ std::unique_ptr<DrawPass> DrawPass::Make(std::unique_ptr<DrawList> draws,
// providing shape, transform, scissor, and paint depth to RenderStep
int geometryIndex = 0;
int shadingIndex = -1;
const bool performsShading = draw.fPaintParams.has_value() && step->performsShading();
keys.push_back({&draw, stepIndex, pipelineIndex, geometryIndex,
performsShading ? shadingIndex : -1});
if (performsShading) {
// TODO: we need to combine the 'programID' with the RenderPass info and the
// geometric rendering method to get the true 'pipelineIndex'
pipelineIndex = programID;
shadingIndex = shadingID;
} else {
// TODO: fill in 'pipelineIndex' for Chris' stencil/depth draws
}
keys.push_back({&draw, stepIndex, pipelineIndex, geometryIndex, shadingIndex});
}
passBounds.join(draw.fClip.drawBounds());

View File

@ -16,10 +16,10 @@
namespace skgpu {
class BoundsManager;
class DrawList;
class TextureProxy;
class CommandBuffer;
class DrawList;
class Recorder;
class TextureProxy;
/**
* DrawPass is analogous to a subpass, storing the drawing operations in the order they are stored
@ -38,7 +38,9 @@ public:
~DrawPass();
// TODO: Replace SDC with the SDC's surface proxy view
static std::unique_ptr<DrawPass> Make(std::unique_ptr<DrawList>, sk_sp<TextureProxy>,
static std::unique_ptr<DrawPass> Make(Recorder*,
std::unique_ptr<DrawList>,
sk_sp<TextureProxy>,
const BoundsManager* occlusionCuller);
// Defined relative to the top-left corner of the surface the DrawPass renders to, and is