• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 // This is a GPU-backend specific test. It relies on static intializers to work
9 
10 #include "include/core/SkTypes.h"
11 #include "tests/Test.h"
12 
13 #include "include/core/SkString.h"
14 #include "include/gpu/GrContext.h"
15 #include "src/core/SkPointPriv.h"
16 #include "src/gpu/GrContextPriv.h"
17 #include "src/gpu/GrGeometryProcessor.h"
18 #include "src/gpu/GrGpu.h"
19 #include "src/gpu/GrMemoryPool.h"
20 #include "src/gpu/GrOpFlushState.h"
21 #include "src/gpu/GrRenderTargetContext.h"
22 #include "src/gpu/GrRenderTargetContextPriv.h"
23 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
24 #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
25 #include "src/gpu/glsl/GrGLSLVarying.h"
26 #include "src/gpu/ops/GrMeshDrawOp.h"
27 
28 namespace {
29 class Op : public GrMeshDrawOp {
30 public:
31     DEFINE_OP_CLASS_ID
32 
name() const33     const char* name() const override { return "Dummy Op"; }
34 
Make(GrContext * context,int numAttribs)35     static std::unique_ptr<GrDrawOp> Make(GrContext* context, int numAttribs) {
36         GrOpMemoryPool* pool = context->priv().opMemoryPool();
37 
38         return pool->allocate<Op>(numAttribs);
39     }
40 
fixedFunctionFlags() const41     FixedFunctionFlags fixedFunctionFlags() const override {
42         return FixedFunctionFlags::kNone;
43     }
44 
finalize(const GrCaps &,const GrAppliedClip *,bool hasMixedSampledCoverage,GrClampType)45     GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
46                                       bool hasMixedSampledCoverage, GrClampType) override {
47         return GrProcessorSet::EmptySetAnalysis();
48     }
49 
50 private:
51     friend class ::GrOpMemoryPool;
52 
Op(int numAttribs)53     Op(int numAttribs) : INHERITED(ClassID()), fNumAttribs(numAttribs) {
54         this->setBounds(SkRect::MakeWH(1.f, 1.f), HasAABloat::kNo, IsZeroArea::kNo);
55     }
56 
onPrepareDraws(Target * target)57     void onPrepareDraws(Target* target) override {
58         class GP : public GrGeometryProcessor {
59         public:
60             GP(int numAttribs) : INHERITED(kGP_ClassID), fNumAttribs(numAttribs) {
61                 SkASSERT(numAttribs > 1);
62                 fAttribNames.reset(new SkString[numAttribs]);
63                 fAttributes.reset(new Attribute[numAttribs]);
64                 for (auto i = 0; i < numAttribs; ++i) {
65                     fAttribNames[i].printf("attr%d", i);
66                     // This gives us more of a mix of attribute types, and allows the
67                     // component count to fit within the limits for iOS Metal.
68                     if (i & 0x1) {
69                         fAttributes[i] = {fAttribNames[i].c_str(), kFloat_GrVertexAttribType,
70                                                                    kFloat_GrSLType};
71                     } else {
72                         fAttributes[i] = {fAttribNames[i].c_str(), kFloat2_GrVertexAttribType,
73                                                                    kFloat2_GrSLType};
74                     }
75                 }
76                 this->setVertexAttributes(fAttributes.get(), numAttribs);
77             }
78             const char* name() const override { return "Dummy GP"; }
79 
80             GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
81                 class GLSLGP : public GrGLSLGeometryProcessor {
82                 public:
83                     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
84                         const GP& gp = args.fGP.cast<GP>();
85                         args.fVaryingHandler->emitAttributes(gp);
86                         this->writeOutputPosition(args.fVertBuilder, gpArgs,
87                                                   gp.fAttributes[0].name());
88                         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
89                         fragBuilder->codeAppendf("%s = half4(1);", args.fOutputColor);
90                         fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
91                     }
92                     void setData(const GrGLSLProgramDataManager& pdman,
93                                  const GrPrimitiveProcessor& primProc,
94                                  FPCoordTransformIter&&) override {}
95                 };
96                 return new GLSLGP();
97             }
98             void getGLSLProcessorKey(const GrShaderCaps&,
99                                      GrProcessorKeyBuilder* builder) const override {
100                 builder->add32(fNumAttribs);
101             }
102 
103         private:
104             int fNumAttribs;
105             std::unique_ptr<SkString[]> fAttribNames;
106             std::unique_ptr<Attribute[]> fAttributes;
107 
108             typedef GrGeometryProcessor INHERITED;
109         };
110         sk_sp<GrGeometryProcessor> gp(new GP(fNumAttribs));
111         size_t vertexStride = gp->vertexStride();
112         QuadHelper helper(target, vertexStride, 1);
113         SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.vertices());
114         SkPointPriv::SetRectTriStrip(vertices, 0.f, 0.f, 1.f, 1.f, vertexStride);
115         helper.recordDraw(target, std::move(gp));
116     }
117 
onExecute(GrOpFlushState * flushState,const SkRect & chainBounds)118     void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
119         flushState->executeDrawsAndUploadsForMeshDrawOp(
120                 this, chainBounds, GrProcessorSet::MakeEmptySet());
121     }
122 
123     int fNumAttribs;
124 
125     typedef GrMeshDrawOp INHERITED;
126 };
127 }
128 
DEF_GPUTEST_FOR_ALL_CONTEXTS(VertexAttributeCount,reporter,ctxInfo)129 DEF_GPUTEST_FOR_ALL_CONTEXTS(VertexAttributeCount, reporter, ctxInfo) {
130     GrContext* context = ctxInfo.grContext();
131 #if GR_GPU_STATS
132     GrGpu* gpu = context->priv().getGpu();
133 #endif
134 
135     sk_sp<GrRenderTargetContext> renderTargetContext(
136             context->priv().makeDeferredRenderTargetContext(SkBackingFit::kApprox, 1, 1,
137                                                             GrColorType::kRGBA_8888, nullptr));
138     if (!renderTargetContext) {
139         ERRORF(reporter, "Could not create render target context.");
140         return;
141     }
142     int attribCnt = context->priv().caps()->maxVertexAttributes();
143     if (!attribCnt) {
144         ERRORF(reporter, "No attributes allowed?!");
145         return;
146     }
147     context->flush();
148     context->priv().resetGpuStats();
149 #if GR_GPU_STATS
150     REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 0);
151     REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 0);
152 #endif
153     // Adding discard to appease vulkan validation warning about loading uninitialized data on draw
154     renderTargetContext->discard();
155 
156     GrPaint grPaint;
157     // This one should succeed.
158     renderTargetContext->priv().testingOnly_addDrawOp(Op::Make(context, attribCnt));
159     context->flush();
160 #if GR_GPU_STATS
161     REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 1);
162     REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 0);
163 #endif
164     context->priv().resetGpuStats();
165     renderTargetContext->priv().testingOnly_addDrawOp(Op::Make(context, attribCnt + 1));
166     context->flush();
167 #if GR_GPU_STATS
168     REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 0);
169     REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 1);
170 #endif
171 }
172