skia2/tests/PrimitiveProcessorTest.cpp
Chris Dalton 57ab06c14e Delete mixed samples
Mixed samples is no longer relevant for Ganesh. DMSAA and the new
Ganesh architecture both rely on full MSAA, and any platform where
mixed samples is supported will ultimately not use the old
architecture.

Change-Id: I5acc745010e090ef26310d92ec6240be2cd494cf
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/399837
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
2021-04-22 20:11:34 +00:00

214 lines
8.6 KiB
C++

/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// This is a GPU-backend specific test. It relies on static intializers to work
#include <memory>
#include "include/core/SkTypes.h"
#include "tests/Test.h"
#include "include/core/SkString.h"
#include "include/gpu/GrDirectContext.h"
#include "src/core/SkPointPriv.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/ops/GrMeshDrawOp.h"
#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
namespace {
class Op : public GrMeshDrawOp {
public:
DEFINE_OP_CLASS_ID
const char* name() const override { return "Dummy Op"; }
static GrOp::Owner Make(GrRecordingContext* rContext, int numAttribs) {
return GrOp::Make<Op>(rContext, numAttribs);
}
FixedFunctionFlags fixedFunctionFlags() const override {
return FixedFunctionFlags::kNone;
}
GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override {
return GrProcessorSet::EmptySetAnalysis();
}
private:
friend class ::GrOp;
Op(int numAttribs) : INHERITED(ClassID()), fNumAttribs(numAttribs) {
this->setBounds(SkRect::MakeWH(1.f, 1.f), HasAABloat::kNo, IsHairline::kNo);
}
GrProgramInfo* programInfo() override { return fProgramInfo; }
void onCreateProgramInfo(const GrCaps* caps,
SkArenaAlloc* arena,
const GrSurfaceProxyView& writeView,
GrAppliedClip&& appliedClip,
const GrXferProcessor::DstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) override {
class GP : public GrGeometryProcessor {
public:
static GrGeometryProcessor* Make(SkArenaAlloc* arena, int numAttribs) {
return arena->make([&](void* ptr) {
return new (ptr) GP(numAttribs);
});
}
const char* name() const override { return "Dummy GP"; }
GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override {
class GLSLGP : public GrGLSLGeometryProcessor {
public:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const GP& gp = args.fGeomProc.cast<GP>();
args.fVaryingHandler->emitAttributes(gp);
WriteOutputPosition(args.fVertBuilder, gpArgs, gp.fAttributes[0].name());
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputColor);
fragBuilder->codeAppendf("const half4 %s = half4(1);",
args.fOutputCoverage);
}
void setData(const GrGLSLProgramDataManager&,
const GrShaderCaps&,
const GrGeometryProcessor&) override {}
};
return new GLSLGP();
}
void getGLSLProcessorKey(const GrShaderCaps&,
GrProcessorKeyBuilder* builder) const override {
builder->add32(fNumAttribs);
}
private:
GP(int numAttribs) : INHERITED(kGP_ClassID), fNumAttribs(numAttribs) {
SkASSERT(numAttribs > 1);
fAttribNames = std::make_unique<SkString[]>(numAttribs);
fAttributes = std::make_unique<Attribute[]>(numAttribs);
for (auto i = 0; i < numAttribs; ++i) {
fAttribNames[i].printf("attr%d", i);
// This gives us more of a mix of attribute types, and allows the
// component count to fit within the limits for iOS Metal.
if (i & 0x1) {
fAttributes[i] = {fAttribNames[i].c_str(), kFloat_GrVertexAttribType,
kFloat_GrSLType};
} else {
fAttributes[i] = {fAttribNames[i].c_str(), kFloat2_GrVertexAttribType,
kFloat2_GrSLType};
}
}
this->setVertexAttributes(fAttributes.get(), numAttribs);
}
int fNumAttribs;
std::unique_ptr<SkString[]> fAttribNames;
std::unique_ptr<Attribute[]> fAttributes;
using INHERITED = GrGeometryProcessor;
};
GrGeometryProcessor* gp = GP::Make(arena, fNumAttribs);
fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps,
arena,
writeView,
std::move(appliedClip),
dstProxyView,
gp,
GrProcessorSet::MakeEmptySet(),
GrPrimitiveType::kTriangles,
renderPassXferBarriers,
colorLoadOp,
GrPipeline::InputFlags::kNone);
}
void onPrepareDraws(Target* target) override {
if (!fProgramInfo) {
this->createProgramInfo(target);
}
size_t vertexStride = fProgramInfo->geomProc().vertexStride();
QuadHelper helper(target, vertexStride, 1);
SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.vertices());
SkPointPriv::SetRectTriStrip(vertices, 0.f, 0.f, 1.f, 1.f, vertexStride);
fMesh = helper.mesh();
}
void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
if (!fProgramInfo || !fMesh) {
return;
}
flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
flushState->drawMesh(*fMesh);
}
int fNumAttribs;
GrSimpleMesh* fMesh = nullptr;
GrProgramInfo* fProgramInfo = nullptr;
using INHERITED = GrMeshDrawOp;
};
} // namespace
DEF_GPUTEST_FOR_ALL_CONTEXTS(VertexAttributeCount, reporter, ctxInfo) {
auto context = ctxInfo.directContext();
#if GR_GPU_STATS
GrGpu* gpu = context->priv().getGpu();
#endif
auto surfaceDrawContext = GrSurfaceDrawContext::Make(context, GrColorType::kRGBA_8888, nullptr,
SkBackingFit::kApprox, {1, 1},
SkSurfaceProps());
if (!surfaceDrawContext) {
ERRORF(reporter, "Could not create render target context.");
return;
}
int attribCnt = context->priv().caps()->maxVertexAttributes();
if (!attribCnt) {
ERRORF(reporter, "No attributes allowed?!");
return;
}
context->flushAndSubmit();
context->priv().resetGpuStats();
#if GR_GPU_STATS
REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 0);
REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 0);
#endif
// Adding discard to appease vulkan validation warning about loading uninitialized data on draw
surfaceDrawContext->discard();
GrPaint grPaint;
// This one should succeed.
surfaceDrawContext->addDrawOp(Op::Make(context, attribCnt));
context->flushAndSubmit();
#if GR_GPU_STATS
REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 1);
REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 0);
#endif
context->priv().resetGpuStats();
surfaceDrawContext->addDrawOp(Op::Make(context, attribCnt + 1));
context->flushAndSubmit();
#if GR_GPU_STATS
REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 0);
REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 1);
#endif
}