GrPipelineDynamicStateTest.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Copyright 2017 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. #include "include/core/SkTypes.h"
  8. #include "tests/Test.h"
  9. #include "include/gpu/GrContext.h"
  10. #include "include/private/GrRecordingContext.h"
  11. #include "src/core/SkMakeUnique.h"
  12. #include "src/gpu/GrColor.h"
  13. #include "src/gpu/GrContextPriv.h"
  14. #include "src/gpu/GrGeometryProcessor.h"
  15. #include "src/gpu/GrGpuCommandBuffer.h"
  16. #include "src/gpu/GrMemoryPool.h"
  17. #include "src/gpu/GrOpFlushState.h"
  18. #include "src/gpu/GrRecordingContextPriv.h"
  19. #include "src/gpu/GrRenderTargetContext.h"
  20. #include "src/gpu/GrRenderTargetContextPriv.h"
  21. #include "src/gpu/GrResourceProvider.h"
  22. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  23. #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
  24. #include "src/gpu/glsl/GrGLSLVarying.h"
  25. #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
  26. /**
  27. * This is a GPU-backend specific test for dynamic pipeline state. It draws boxes using dynamic
  28. * scissor rectangles then reads back the result to verify a successful test.
  29. */
  30. static constexpr int kScreenSize = 6;
  31. static constexpr int kNumMeshes = 4;
  32. static constexpr int kScreenSplitX = kScreenSize/2;
  33. static constexpr int kScreenSplitY = kScreenSize/2;
  34. static const SkIRect kDynamicScissors[kNumMeshes] = {
  35. SkIRect::MakeLTRB(0, 0, kScreenSplitX, kScreenSplitY),
  36. SkIRect::MakeLTRB(0, kScreenSplitY, kScreenSplitX, kScreenSize),
  37. SkIRect::MakeLTRB(kScreenSplitX, 0, kScreenSize, kScreenSplitY),
  38. SkIRect::MakeLTRB(kScreenSplitX, kScreenSplitY, kScreenSize, kScreenSize),
  39. };
  40. static const GrColor kMeshColors[kNumMeshes] {
  41. GrColorPackRGBA(255, 0, 0, 255),
  42. GrColorPackRGBA(0, 255, 0, 255),
  43. GrColorPackRGBA(0, 0, 255, 255),
  44. GrColorPackRGBA(0, 0, 0, 255)
  45. };
  46. struct Vertex {
  47. float fX;
  48. float fY;
  49. GrColor fColor;
  50. };
  51. class GrPipelineDynamicStateTestProcessor : public GrGeometryProcessor {
  52. public:
  53. GrPipelineDynamicStateTestProcessor()
  54. : INHERITED(kGrPipelineDynamicStateTestProcessor_ClassID) {
  55. this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
  56. }
  57. const char* name() const override { return "GrPipelineDynamicStateTest Processor"; }
  58. void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const final {}
  59. GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
  60. const Attribute& inVertex() const { return kAttributes[0]; }
  61. const Attribute& inColor() const { return kAttributes[1]; }
  62. private:
  63. static constexpr Attribute kAttributes[] = {
  64. {"vertex", kFloat2_GrVertexAttribType, kHalf2_GrSLType},
  65. {"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType},
  66. };
  67. friend class GLSLPipelineDynamicStateTestProcessor;
  68. typedef GrGeometryProcessor INHERITED;
  69. };
  70. constexpr GrPrimitiveProcessor::Attribute GrPipelineDynamicStateTestProcessor::kAttributes[];
  71. class GLSLPipelineDynamicStateTestProcessor : public GrGLSLGeometryProcessor {
  72. void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
  73. FPCoordTransformIter&& transformIter) final {}
  74. void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
  75. const GrPipelineDynamicStateTestProcessor& mp =
  76. args.fGP.cast<GrPipelineDynamicStateTestProcessor>();
  77. GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
  78. varyingHandler->emitAttributes(mp);
  79. varyingHandler->addPassThroughAttribute(mp.inColor(), args.fOutputColor);
  80. GrGLSLVertexBuilder* v = args.fVertBuilder;
  81. v->codeAppendf("float2 vertex = %s;", mp.inVertex().name());
  82. gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
  83. GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
  84. f->codeAppendf("%s = half4(1);", args.fOutputCoverage);
  85. }
  86. };
  87. GrGLSLPrimitiveProcessor*
  88. GrPipelineDynamicStateTestProcessor::createGLSLInstance(const GrShaderCaps&) const {
  89. return new GLSLPipelineDynamicStateTestProcessor;
  90. }
  91. class GrPipelineDynamicStateTestOp : public GrDrawOp {
  92. public:
  93. DEFINE_OP_CLASS_ID
  94. static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
  95. GrScissorTest scissorTest,
  96. sk_sp<const GrBuffer> vbuff) {
  97. GrOpMemoryPool* pool = context->priv().opMemoryPool();
  98. return pool->allocate<GrPipelineDynamicStateTestOp>(scissorTest, std::move(vbuff));
  99. }
  100. private:
  101. friend class GrOpMemoryPool;
  102. GrPipelineDynamicStateTestOp(GrScissorTest scissorTest, sk_sp<const GrBuffer> vbuff)
  103. : INHERITED(ClassID())
  104. , fScissorTest(scissorTest)
  105. , fVertexBuffer(std::move(vbuff)) {
  106. this->setBounds(SkRect::MakeIWH(kScreenSize, kScreenSize),
  107. HasAABloat::kNo, IsZeroArea::kNo);
  108. }
  109. const char* name() const override { return "GrPipelineDynamicStateTestOp"; }
  110. FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
  111. GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*,
  112. bool hasMixedSampledCoverage, GrClampType) override {
  113. return GrProcessorSet::EmptySetAnalysis();
  114. }
  115. void onPrepare(GrOpFlushState*) override {}
  116. void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override {
  117. GrPipeline pipeline(fScissorTest, SkBlendMode::kSrc, state->drawOpArgs().fOutputSwizzle);
  118. SkSTArray<kNumMeshes, GrMesh> meshes;
  119. for (int i = 0; i < kNumMeshes; ++i) {
  120. GrMesh& mesh = meshes.emplace_back(GrPrimitiveType::kTriangleStrip);
  121. mesh.setNonIndexedNonInstanced(4);
  122. mesh.setVertexData(fVertexBuffer, 4 * i);
  123. }
  124. GrPipeline::DynamicStateArrays dynamicState;
  125. dynamicState.fScissorRects = kDynamicScissors;
  126. state->rtCommandBuffer()->draw(GrPipelineDynamicStateTestProcessor(), pipeline, nullptr,
  127. &dynamicState, meshes.begin(), 4,
  128. SkRect::MakeIWH(kScreenSize, kScreenSize));
  129. }
  130. GrScissorTest fScissorTest;
  131. const sk_sp<const GrBuffer> fVertexBuffer;
  132. typedef GrDrawOp INHERITED;
  133. };
  134. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrPipelineDynamicStateTest, reporter, ctxInfo) {
  135. GrContext* context = ctxInfo.grContext();
  136. GrResourceProvider* rp = context->priv().resourceProvider();
  137. sk_sp<GrRenderTargetContext> rtc(context->priv().makeDeferredRenderTargetContext(
  138. SkBackingFit::kExact, kScreenSize, kScreenSize, GrColorType::kRGBA_8888, nullptr));
  139. if (!rtc) {
  140. ERRORF(reporter, "could not create render target context.");
  141. return;
  142. }
  143. constexpr float d = (float) kScreenSize;
  144. Vertex vdata[kNumMeshes * 4] = {
  145. {0, 0, kMeshColors[0]},
  146. {0, d, kMeshColors[0]},
  147. {d, 0, kMeshColors[0]},
  148. {d, d, kMeshColors[0]},
  149. {0, 0, kMeshColors[1]},
  150. {0, d, kMeshColors[1]},
  151. {d, 0, kMeshColors[1]},
  152. {d, d, kMeshColors[1]},
  153. {0, 0, kMeshColors[2]},
  154. {0, d, kMeshColors[2]},
  155. {d, 0, kMeshColors[2]},
  156. {d, d, kMeshColors[2]},
  157. {0, 0, kMeshColors[3]},
  158. {0, d, kMeshColors[3]},
  159. {d, 0, kMeshColors[3]},
  160. {d, d, kMeshColors[3]}
  161. };
  162. sk_sp<const GrBuffer> vbuff(rp->createBuffer(sizeof(vdata), GrGpuBufferType::kVertex,
  163. kDynamic_GrAccessPattern, vdata));
  164. if (!vbuff) {
  165. ERRORF(reporter, "vbuff is null.");
  166. return;
  167. }
  168. uint32_t resultPx[kScreenSize * kScreenSize];
  169. for (GrScissorTest scissorTest : {GrScissorTest::kEnabled, GrScissorTest::kDisabled}) {
  170. rtc->clear(nullptr, SkPMColor4f::FromBytes_RGBA(0xbaaaaaad),
  171. GrRenderTargetContext::CanClearFullscreen::kYes);
  172. rtc->priv().testingOnly_addDrawOp(
  173. GrPipelineDynamicStateTestOp::Make(context, scissorTest, vbuff));
  174. rtc->readPixels(SkImageInfo::Make(kScreenSize, kScreenSize,
  175. kRGBA_8888_SkColorType, kPremul_SkAlphaType),
  176. resultPx, 4 * kScreenSize, {0, 0});
  177. for (int y = 0; y < kScreenSize; ++y) {
  178. for (int x = 0; x < kScreenSize; ++x) {
  179. int expectedColorIdx;
  180. if (GrScissorTest::kEnabled == scissorTest) {
  181. expectedColorIdx = (x < kScreenSplitX ? 0 : 2) + (y < kScreenSplitY ? 0 : 1);
  182. } else {
  183. expectedColorIdx = kNumMeshes - 1;
  184. }
  185. uint32_t expected = kMeshColors[expectedColorIdx];
  186. uint32_t actual = resultPx[y * kScreenSize + x];
  187. if (expected != actual) {
  188. ERRORF(reporter, "[scissor=%s] pixel (%i,%i): got 0x%x expected 0x%x",
  189. GrScissorTest::kEnabled == scissorTest ? "enabled" : "disabled", x, y,
  190. actual, expected);
  191. return;
  192. }
  193. }
  194. }
  195. }
  196. }