1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci// This is a GPU-backend specific test. It relies on static initializers to work 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include <memory> 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 13cb93a386Sopenharmony_ci#include "tests/Test.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include "include/core/SkString.h" 16cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 17cb93a386Sopenharmony_ci#include "src/core/SkPointPriv.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h" 20cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 21cb93a386Sopenharmony_ci#include "src/gpu/GrMemoryPool.h" 22cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h" 23cb93a386Sopenharmony_ci#include "src/gpu/GrProgramInfo.h" 24cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 25cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVarying.h" 26cb93a386Sopenharmony_ci#include "src/gpu/ops/GrMeshDrawOp.h" 27cb93a386Sopenharmony_ci#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h" 28cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h" 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_cinamespace { 31cb93a386Sopenharmony_ciclass Op : public GrMeshDrawOp { 32cb93a386Sopenharmony_cipublic: 33cb93a386Sopenharmony_ci DEFINE_OP_CLASS_ID 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci const char* name() const override { return "Test Op"; } 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci static GrOp::Owner Make(GrRecordingContext* rContext, int numAttribs) { 38cb93a386Sopenharmony_ci return GrOp::Make<Op>(rContext, numAttribs); 39cb93a386Sopenharmony_ci } 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci FixedFunctionFlags fixedFunctionFlags() const override { 42cb93a386Sopenharmony_ci return FixedFunctionFlags::kNone; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override { 46cb93a386Sopenharmony_ci return GrProcessorSet::EmptySetAnalysis(); 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ciprivate: 50cb93a386Sopenharmony_ci friend class ::GrOp; 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci Op(int numAttribs) : INHERITED(ClassID()), fNumAttribs(numAttribs) { 53cb93a386Sopenharmony_ci this->setBounds(SkRect::MakeWH(1.f, 1.f), HasAABloat::kNo, IsHairline::kNo); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci GrProgramInfo* programInfo() override { return fProgramInfo; } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci void onCreateProgramInfo(const GrCaps* caps, 59cb93a386Sopenharmony_ci SkArenaAlloc* arena, 60cb93a386Sopenharmony_ci const GrSurfaceProxyView& writeView, 61cb93a386Sopenharmony_ci bool usesMSAASurface, 62cb93a386Sopenharmony_ci GrAppliedClip&& appliedClip, 63cb93a386Sopenharmony_ci const GrDstProxyView& dstProxyView, 64cb93a386Sopenharmony_ci GrXferBarrierFlags renderPassXferBarriers, 65cb93a386Sopenharmony_ci GrLoadOp colorLoadOp) override { 66cb93a386Sopenharmony_ci class GP : public GrGeometryProcessor { 67cb93a386Sopenharmony_ci public: 68cb93a386Sopenharmony_ci static GrGeometryProcessor* Make(SkArenaAlloc* arena, int numAttribs) { 69cb93a386Sopenharmony_ci return arena->make([&](void* ptr) { 70cb93a386Sopenharmony_ci return new (ptr) GP(numAttribs); 71cb93a386Sopenharmony_ci }); 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci const char* name() const override { return "Test GP"; } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override { 77cb93a386Sopenharmony_ci class Impl : public ProgramImpl { 78cb93a386Sopenharmony_ci public: 79cb93a386Sopenharmony_ci void setData(const GrGLSLProgramDataManager&, 80cb93a386Sopenharmony_ci const GrShaderCaps&, 81cb93a386Sopenharmony_ci const GrGeometryProcessor&) override {} 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci private: 84cb93a386Sopenharmony_ci void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 85cb93a386Sopenharmony_ci const GP& gp = args.fGeomProc.cast<GP>(); 86cb93a386Sopenharmony_ci args.fVaryingHandler->emitAttributes(gp); 87cb93a386Sopenharmony_ci WriteOutputPosition(args.fVertBuilder, gpArgs, gp.fAttributes[0].name()); 88cb93a386Sopenharmony_ci GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 89cb93a386Sopenharmony_ci fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputColor); 90cb93a386Sopenharmony_ci fragBuilder->codeAppendf("const half4 %s = half4(1);", 91cb93a386Sopenharmony_ci args.fOutputCoverage); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci }; 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci return std::make_unique<Impl>(); 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder* builder) const override { 98cb93a386Sopenharmony_ci builder->add32(fNumAttribs); 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci private: 102cb93a386Sopenharmony_ci GP(int numAttribs) : INHERITED(kGP_ClassID), fNumAttribs(numAttribs) { 103cb93a386Sopenharmony_ci SkASSERT(numAttribs > 1); 104cb93a386Sopenharmony_ci fAttribNames = std::make_unique<SkString[]>(numAttribs); 105cb93a386Sopenharmony_ci fAttributes = std::make_unique<Attribute[]>(numAttribs); 106cb93a386Sopenharmony_ci for (auto i = 0; i < numAttribs; ++i) { 107cb93a386Sopenharmony_ci fAttribNames[i].printf("attr%d", i); 108cb93a386Sopenharmony_ci // This gives us more of a mix of attribute types, and allows the 109cb93a386Sopenharmony_ci // component count to fit within the limits for iOS Metal. 110cb93a386Sopenharmony_ci if (i & 0x1) { 111cb93a386Sopenharmony_ci fAttributes[i] = {fAttribNames[i].c_str(), kFloat_GrVertexAttribType, 112cb93a386Sopenharmony_ci kFloat_GrSLType}; 113cb93a386Sopenharmony_ci } else { 114cb93a386Sopenharmony_ci fAttributes[i] = {fAttribNames[i].c_str(), kFloat2_GrVertexAttribType, 115cb93a386Sopenharmony_ci kFloat2_GrSLType}; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci this->setVertexAttributes(fAttributes.get(), numAttribs); 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci int fNumAttribs; 122cb93a386Sopenharmony_ci std::unique_ptr<SkString[]> fAttribNames; 123cb93a386Sopenharmony_ci std::unique_ptr<Attribute[]> fAttributes; 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci using INHERITED = GrGeometryProcessor; 126cb93a386Sopenharmony_ci }; 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci GrGeometryProcessor* gp = GP::Make(arena, fNumAttribs); 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps, 131cb93a386Sopenharmony_ci arena, 132cb93a386Sopenharmony_ci writeView, 133cb93a386Sopenharmony_ci usesMSAASurface, 134cb93a386Sopenharmony_ci std::move(appliedClip), 135cb93a386Sopenharmony_ci dstProxyView, 136cb93a386Sopenharmony_ci gp, 137cb93a386Sopenharmony_ci GrProcessorSet::MakeEmptySet(), 138cb93a386Sopenharmony_ci GrPrimitiveType::kTriangles, 139cb93a386Sopenharmony_ci renderPassXferBarriers, 140cb93a386Sopenharmony_ci colorLoadOp, 141cb93a386Sopenharmony_ci GrPipeline::InputFlags::kNone); 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci void onPrepareDraws(GrMeshDrawTarget* target) override { 145cb93a386Sopenharmony_ci if (!fProgramInfo) { 146cb93a386Sopenharmony_ci this->createProgramInfo(target); 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_ci size_t vertexStride = fProgramInfo->geomProc().vertexStride(); 150cb93a386Sopenharmony_ci QuadHelper helper(target, vertexStride, 1); 151cb93a386Sopenharmony_ci SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.vertices()); 152cb93a386Sopenharmony_ci SkPointPriv::SetRectTriStrip(vertices, 0.f, 0.f, 1.f, 1.f, vertexStride); 153cb93a386Sopenharmony_ci fMesh = helper.mesh(); 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override { 157cb93a386Sopenharmony_ci if (!fProgramInfo || !fMesh) { 158cb93a386Sopenharmony_ci return; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds); 162cb93a386Sopenharmony_ci flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline()); 163cb93a386Sopenharmony_ci flushState->drawMesh(*fMesh); 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci int fNumAttribs; 167cb93a386Sopenharmony_ci GrSimpleMesh* fMesh = nullptr; 168cb93a386Sopenharmony_ci GrProgramInfo* fProgramInfo = nullptr; 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci using INHERITED = GrMeshDrawOp; 171cb93a386Sopenharmony_ci}; 172cb93a386Sopenharmony_ci} // namespace 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_ALL_CONTEXTS(VertexAttributeCount, reporter, ctxInfo) { 175cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 176cb93a386Sopenharmony_ci#if GR_GPU_STATS 177cb93a386Sopenharmony_ci GrGpu* gpu = dContext->priv().getGpu(); 178cb93a386Sopenharmony_ci#endif 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci auto sdc = skgpu::v1::SurfaceDrawContext::Make(dContext, 181cb93a386Sopenharmony_ci GrColorType::kRGBA_8888, 182cb93a386Sopenharmony_ci nullptr, 183cb93a386Sopenharmony_ci SkBackingFit::kApprox, 184cb93a386Sopenharmony_ci {1, 1}, 185cb93a386Sopenharmony_ci SkSurfaceProps()); 186cb93a386Sopenharmony_ci if (!sdc) { 187cb93a386Sopenharmony_ci ERRORF(reporter, "Could not create render target context."); 188cb93a386Sopenharmony_ci return; 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci int attribCnt = dContext->priv().caps()->maxVertexAttributes(); 191cb93a386Sopenharmony_ci if (!attribCnt) { 192cb93a386Sopenharmony_ci ERRORF(reporter, "No attributes allowed?!"); 193cb93a386Sopenharmony_ci return; 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci dContext->flushAndSubmit(); 196cb93a386Sopenharmony_ci dContext->priv().resetGpuStats(); 197cb93a386Sopenharmony_ci#if GR_GPU_STATS 198cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 0); 199cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 0); 200cb93a386Sopenharmony_ci#endif 201cb93a386Sopenharmony_ci // Adding discard to appease vulkan validation warning about loading uninitialized data on draw 202cb93a386Sopenharmony_ci sdc->discard(); 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci GrPaint grPaint; 205cb93a386Sopenharmony_ci // This one should succeed. 206cb93a386Sopenharmony_ci sdc->addDrawOp(Op::Make(dContext, attribCnt)); 207cb93a386Sopenharmony_ci dContext->flushAndSubmit(); 208cb93a386Sopenharmony_ci#if GR_GPU_STATS 209cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 1); 210cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 0); 211cb93a386Sopenharmony_ci#endif 212cb93a386Sopenharmony_ci dContext->priv().resetGpuStats(); 213cb93a386Sopenharmony_ci sdc->addDrawOp(Op::Make(dContext, attribCnt + 1)); 214cb93a386Sopenharmony_ci dContext->flushAndSubmit(); 215cb93a386Sopenharmony_ci#if GR_GPU_STATS 216cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gpu->stats()->numDraws() == 0); 217cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gpu->stats()->numFailedDraws() == 1); 218cb93a386Sopenharmony_ci#endif 219cb93a386Sopenharmony_ci} 220