Add GrSimpleMeshDrawOpHelper::CreateProgramInfo

This helper method can be used by the MeshDrawOps to (pre-)create their GrProgramInfos.

Bug: skia:9455
Change-Id: I41b7c2aefc0f633a1d32996c7f0cce3d11f8fcb1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/273815
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2020-02-28 11:56:44 -05:00 committed by Skia Commit-Bot
parent b62cee315e
commit ce97857f5b
7 changed files with 166 additions and 65 deletions

View File

@ -1647,6 +1647,8 @@ Result GPUDDLSink::ddlDraw(const Src& src,
Result result = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
SkIntToScalar(size.height())));
if (!result.isOk()) {
gpuTaskGroup->add([gpuTestCtx] { gpuTestCtx->makeNotCurrent(); });
gpuTaskGroup->wait();
return result;
}
sk_sp<SkPicture> inputPicture(recorder.finishRecordingAsPicture());
@ -1657,6 +1659,8 @@ Result GPUDDLSink::ddlDraw(const Src& src,
DDLPromiseImageHelper promiseImageHelper;
sk_sp<SkData> compressedPictureData = promiseImageHelper.deflateSKP(inputPicture.get());
if (!compressedPictureData) {
gpuTaskGroup->add([gpuTestCtx] { gpuTestCtx->makeNotCurrent(); });
gpuTaskGroup->wait();
return Result::Fatal("GPUDDLSink: Couldn't deflate SkPicture");
}

View File

@ -33,9 +33,11 @@
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrOpsRenderPass.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrProcessorAnalysis.h"
#include "src/gpu/GrProcessorSet.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
@ -81,12 +83,60 @@ protected:
this->setBounds(rect, HasAABloat::kYes, IsHairline::kNo);
}
void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState,
std::move(fProcessorSet),
GrPipeline::InputFlags::kNone);
virtual GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) = 0;
flushState->executeDrawsAndUploadsForMeshDrawOp(this, chainBounds, pipeline);
GrProgramInfo* createProgramInfo(const GrCaps* caps,
SkArenaAlloc* arena,
const GrSurfaceProxyView* outputView,
GrAppliedClip&& appliedClip,
const GrXferProcessor::DstProxyView& dstProxyView) {
auto gp = this->makeGP(*caps, arena);
if (!gp) {
return nullptr;
}
GrPipeline::InputFlags flags = GrPipeline::InputFlags::kNone;
return GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps, arena, outputView,
std::move(appliedClip), dstProxyView,
gp, std::move(fProcessorSet), flags);
}
GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) {
return this->createProgramInfo(&flushState->caps(),
flushState->allocator(),
flushState->view(),
flushState->detachAppliedClip(),
flushState->dstProxyView());
}
void onPrePrepareDraws(GrRecordingContext* context,
const GrSurfaceProxyView* outputView,
GrAppliedClip* clip,
const GrXferProcessor::DstProxyView& dstProxyView) final {
SkArenaAlloc* arena = context->priv().recordTimeAllocator();
// This is equivalent to a GrOpFlushState::detachAppliedClip
GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, outputView,
std::move(appliedClip), dstProxyView);
context->priv().recordProgramInfo(fProgramInfo);
}
void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) final {
if (!fProgramInfo) {
fProgramInfo = this->createProgramInfo(flushState);
}
if (!fProgramInfo) {
return;
}
static constexpr int kOneMesh = 1;
flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMesh, kOneMesh);
}
GrClipEdgeType edgeType() const { return fEdgeType; }
@ -94,11 +144,15 @@ protected:
const SkRect& rect() const { return fRect; }
const SkPMColor4f& color() const { return fColor; }
protected:
GrMesh* fMesh = nullptr; // filled in by the derived classes
private:
SkRect fRect;
SkPMColor4f fColor;
GrClipEdgeType fEdgeType;
GrProcessorSet fProcessorSet;
SkRect fRect;
SkPMColor4f fColor;
GrClipEdgeType fEdgeType;
GrProcessorSet fProcessorSet;
GrProgramInfo* fProgramInfo = nullptr;
typedef GrMeshDrawOp INHERITED;
};
@ -110,7 +164,7 @@ class BezierConicTestOp : public BezierTestOp {
public:
DEFINE_OP_CLASS_ID
const char* name() const override { return "BezierConicTestOp"; }
const char* name() const final { return "BezierConicTestOp"; }
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
GrClipEdgeType et,
@ -134,29 +188,30 @@ private:
float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
};
void onPrepareDraws(Target* target) override {
GrGeometryProcessor* gp = GrConicEffect::Make(target->allocator(), this->color(),
SkMatrix::I(), this->edgeType(),
target->caps(), SkMatrix::I(), false);
if (!gp) {
return;
GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final {
auto tmp = GrConicEffect::Make(arena, this->color(), SkMatrix::I(), this->edgeType(),
caps, SkMatrix::I(), false);
if (!tmp) {
return nullptr;
}
SkASSERT(tmp->vertexStride() == sizeof(Vertex));
return tmp;
}
SkASSERT(gp->vertexStride() == sizeof(Vertex));
void onPrepareDraws(Target* target) final {
QuadHelper helper(target, sizeof(Vertex), 1);
Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
if (!verts) {
return;
}
SkRect rect = this->rect();
SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
rect.fBottom, sizeof(Vertex));
SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
for (int v = 0; v < 4; ++v) {
SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
}
helper.recordDraw(target, gp);
fMesh = helper.mesh();
}
SkMatrix fKLM;
@ -343,15 +398,17 @@ private:
float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
};
void onPrepareDraws(Target* target) override {
GrGeometryProcessor* gp = GrQuadEffect::Make(target->allocator(), this->color(),
SkMatrix::I(), this->edgeType(),
target->caps(), SkMatrix::I(), false);
if (!gp) {
return;
GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final {
auto tmp = GrQuadEffect::Make(arena, this->color(), SkMatrix::I(), this->edgeType(),
caps, SkMatrix::I(), false);
if (!tmp) {
return nullptr;
}
SkASSERT(tmp->vertexStride() == sizeof(Vertex));
return tmp;
}
SkASSERT(gp->vertexStride() == sizeof(Vertex));
void onPrepareDraws(Target* target) final {
QuadHelper helper(target, sizeof(Vertex), 1);
Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
if (!verts) {
@ -360,7 +417,8 @@ private:
SkRect rect = this->rect();
SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
fDevToUV.apply(verts, 4, sizeof(Vertex), sizeof(SkPoint));
helper.recordDraw(target, gp);
fMesh = helper.mesh();
}
GrPathUtils::QuadUVMatrix fDevToUV;

View File

@ -20,6 +20,7 @@
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
#include "src/gpu/ops/GrDrawOp.h"
#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
namespace {
@ -98,6 +99,13 @@ private:
const GrSurfaceProxyView* outputView,
GrAppliedClip&&,
const GrXferProcessor::DstProxyView&);
GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) {
return this->createProgramInfo(&flushState->caps(),
flushState->allocator(),
flushState->view(),
flushState->detachAppliedClip(),
flushState->dstProxyView());
}
const GrAAType fAAType;
const SkPMColor4f fOriginalColor;
@ -568,7 +576,8 @@ void FillRRectOp::onPrePrepare(GrRecordingContext* context,
// TODO: it would be cool if, right here, we created both the program info and desc
// in the record-time arena. Then, if the program info had already been seen, we could
// get pointers back to the prior versions and be able to return the allocated space
// back to the arena.
// back to the arena. Note that this would require separating the portions of the
// ProgramInfo that represent state from those that are just definitional.
fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, outputView,
std::move(appliedClip), dstProxyView);
@ -868,38 +877,17 @@ GrProgramInfo* FillRRectOp::createProgramInfo(const GrCaps* caps,
const GrSurfaceProxyView* outputView,
GrAppliedClip&& appliedClip,
const GrXferProcessor::DstProxyView& dstProxyView) {
GrGeometryProcessor* geomProc = Processor::Make(arena, fAAType, fFlags);
SkASSERT(geomProc->instanceStride() == (size_t)fInstanceStride);
GrGeometryProcessor* gp = Processor::Make(arena, fAAType, fFlags);
SkASSERT(gp->instanceStride() == (size_t)fInstanceStride);
GrPipeline::InitArgs initArgs;
GrPipeline::InputFlags flags = GrPipeline::InputFlags::kNone;
if (GrAAType::kMSAA == fAAType) {
initArgs.fInputFlags = GrPipeline::InputFlags::kHWAntialias;
}
initArgs.fCaps = caps;
initArgs.fDstProxyView = dstProxyView;
initArgs.fOutputSwizzle = outputView->swizzle();
GrPipeline::FixedDynamicState* fixedDynamicState = nullptr;
if (appliedClip.scissorState().enabled()) {
fixedDynamicState = arena->make<GrPipeline::FixedDynamicState>(
appliedClip.scissorState().rect());
flags = GrPipeline::InputFlags::kHWAntialias;
}
GrPipeline* pipeline = arena->make<GrPipeline>(initArgs,
std::move(fProcessors),
std::move(appliedClip));
GrRenderTargetProxy* outputProxy = outputView->asRenderTargetProxy();
return arena->make<GrProgramInfo>(outputProxy->numSamples(),
outputProxy->numStencilSamples(),
outputProxy->backendFormat(),
outputView->origin(),
pipeline,
geomProc,
fixedDynamicState,
nullptr, 0,
GrPrimitiveType::kTriangles);
return GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps, arena, outputView,
std::move(appliedClip), dstProxyView,
gp, std::move(fProcessors), flags);
}
void FillRRectOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
@ -908,11 +896,7 @@ void FillRRectOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBound
}
if (!fProgramInfo) {
fProgramInfo = this->createProgramInfo(&flushState->caps(),
flushState->allocator(),
flushState->view(),
flushState->detachAppliedClip(),
flushState->dstProxyView());
fProgramInfo = this->createProgramInfo(flushState);
}
GrMesh* mesh = flushState->allocator()->make<GrMesh>();

View File

@ -50,6 +50,7 @@ protected:
const GrPipeline::FixedDynamicState*) const;
void* vertices() const { return fVertices; }
GrMesh* mesh() { return fMesh; }
protected:
PatternHelper() = default;
@ -71,6 +72,7 @@ protected:
QuadHelper() = delete;
QuadHelper(Target* target, size_t vertexStride, int quadsToDraw);
using PatternHelper::mesh;
using PatternHelper::recordDraw;
using PatternHelper::vertices;

View File

@ -7,6 +7,7 @@
#include "src/gpu/GrAppliedClip.h"
#include "src/gpu/GrProcessorSet.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrUserStencilSettings.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/geometry/GrRect.h"
@ -118,9 +119,9 @@ const GrPipeline* GrSimpleMeshDrawOpHelper::CreatePipeline(
GrPipeline::InitArgs pipelineArgs;
pipelineArgs.fInputFlags = pipelineFlags;
pipelineArgs.fDstProxyView = dstProxyView;
pipelineArgs.fCaps = caps;
pipelineArgs.fUserStencil = stencilSettings;
pipelineArgs.fCaps = caps;
pipelineArgs.fDstProxyView = dstProxyView;
pipelineArgs.fOutputSwizzle = outputView->swizzle();
return arena->make<GrPipeline>(pipelineArgs,
@ -153,6 +154,45 @@ const GrPipeline* GrSimpleMeshDrawOpHelper::createPipeline(GrOpFlushState* flush
this->pipelineFlags());
}
GrProgramInfo* GrSimpleMeshDrawOpHelper::CreateProgramInfo(
const GrCaps* caps,
SkArenaAlloc* arena,
const GrSurfaceProxyView* outputView,
GrAppliedClip&& appliedClip,
const GrXferProcessor::DstProxyView& dstProxyView,
GrGeometryProcessor* geometryProcessor,
GrProcessorSet&& processorSet,
GrPipeline::InputFlags pipelineFlags) {
static constexpr int kZeroPrimProcTextures = 0;
auto fixedDynamicState = GrMeshDrawOp::Target::MakeFixedDynamicState(arena,
&appliedClip,
kZeroPrimProcTextures);
auto pipeline = CreatePipeline(caps,
arena,
outputView,
std::move(appliedClip),
dstProxyView,
std::move(processorSet),
pipelineFlags);
GrRenderTargetProxy* outputProxy = outputView->asRenderTargetProxy();
static constexpr int kOneMesh = 1;
auto tmp = arena->make<GrProgramInfo>(outputProxy->numSamples(),
outputProxy->numStencilSamples(),
outputProxy->backendFormat(),
outputView->origin(),
pipeline,
geometryProcessor,
fixedDynamicState,
nullptr,
kOneMesh,
GrPrimitiveType::kTriangles);
SkASSERT(tmp->primProc().numTextureSamplers() <= 0);
return tmp;
}
#ifdef SK_DEBUG
static void dump_pipeline_flags(GrPipeline::InputFlags flags, SkString* result) {
if (GrPipeline::InputFlags::kNone != flags) {

View File

@ -140,6 +140,19 @@ public:
const GrPipeline* createPipeline(GrOpFlushState* flushState);
// Create a programInfo with the following properties:
// its primitive processor uses no textures
// it has no dynamic state besides the scissor clip
// it is only applied to a single kTriangles mesh
static GrProgramInfo* CreateProgramInfo(const GrCaps*,
SkArenaAlloc*,
const GrSurfaceProxyView* outputView,
GrAppliedClip&&,
const GrXferProcessor::DstProxyView&,
GrGeometryProcessor*,
GrProcessorSet&&,
GrPipeline::InputFlags pipelineFlags);
GrProcessorSet detachProcessorSet() {
return fProcessors ? std::move(*fProcessors) : GrProcessorSet::MakeEmptySet();
}

View File

@ -193,7 +193,7 @@ void WinGLTestContext::onPlatformMakeCurrent() const {
}
if (!wglMakeCurrent(dc, glrc)) {
SkDebugf("Could not create rendering context.\n");
SkDebugf("Could not make current.\n");
}
}