1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTDArray.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/AtlasTypes.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkBackingFit.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Swizzle.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpFlushState.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProxyProvider.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTargetProxy.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxy.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxyView.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTextureProxy.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTextureResolveManager.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrOp.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/OpsTask.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
38*c8dee2aaSAndroid Build Coastguard Worker #include <array>
39*c8dee2aaSAndroid Build Coastguard Worker #include <cassert>
40*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
41*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
42*c8dee2aaSAndroid Build Coastguard Worker #include <iterator>
43*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
44*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker class GrAppliedClip;
47*c8dee2aaSAndroid Build Coastguard Worker class GrDrawingManager;
48*c8dee2aaSAndroid Build Coastguard Worker class GrDstProxyView;
49*c8dee2aaSAndroid Build Coastguard Worker class GrRecordingContext;
50*c8dee2aaSAndroid Build Coastguard Worker class SkArenaAlloc;
51*c8dee2aaSAndroid Build Coastguard Worker enum class GrXferBarrierFlags;
52*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard Worker // We create Ops that write a value into a range of a buffer. We create ranges from
55*c8dee2aaSAndroid Build Coastguard Worker // kNumOpPositions starting positions x kRanges canonical ranges. We repeat each range kNumRepeats
56*c8dee2aaSAndroid Build Coastguard Worker // times (with a different value written by each of the repeats).
57*c8dee2aaSAndroid Build Coastguard Worker namespace {
58*c8dee2aaSAndroid Build Coastguard Worker struct Range {
59*c8dee2aaSAndroid Build Coastguard Worker unsigned fOffset;
60*c8dee2aaSAndroid Build Coastguard Worker unsigned fLength;
61*c8dee2aaSAndroid Build Coastguard Worker };
62*c8dee2aaSAndroid Build Coastguard Worker
63*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumOpPositions = 4;
64*c8dee2aaSAndroid Build Coastguard Worker static constexpr Range kRanges[] = {{0, 4,}, {1, 2}};
65*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumRanges = (int)std::size(kRanges);
66*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumRepeats = 2;
67*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumOps = kNumRepeats * kNumOpPositions * kNumRanges;
68*c8dee2aaSAndroid Build Coastguard Worker
fact(int n)69*c8dee2aaSAndroid Build Coastguard Worker static constexpr uint64_t fact(int n) {
70*c8dee2aaSAndroid Build Coastguard Worker assert(n > 0);
71*c8dee2aaSAndroid Build Coastguard Worker return n > 1 ? n * fact(n - 1) : 1;
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker // How wide should our result buffer be to hold values written by the ranges of the ops.
result_width()75*c8dee2aaSAndroid Build Coastguard Worker static constexpr unsigned result_width() {
76*c8dee2aaSAndroid Build Coastguard Worker unsigned maxLength = 0;
77*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumRanges; ++i) {
78*c8dee2aaSAndroid Build Coastguard Worker maxLength = maxLength > kRanges[i].fLength ? maxLength : kRanges[i].fLength;
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker return kNumOpPositions + maxLength - 1;
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker
83*c8dee2aaSAndroid Build Coastguard Worker // Number of possible allowable binary chainings among the kNumOps ops.
84*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumCombinableValues = fact(kNumOps) / fact(kNumOps - 2);
85*c8dee2aaSAndroid Build Coastguard Worker using Combinable = std::array<GrOp::CombineResult, kNumCombinableValues>;
86*c8dee2aaSAndroid Build Coastguard Worker
87*c8dee2aaSAndroid Build Coastguard Worker /**
88*c8dee2aaSAndroid Build Coastguard Worker * The index in Combinable for the result for combining op 'b' into op 'a', i.e. the result of
89*c8dee2aaSAndroid Build Coastguard Worker * op[a]->combineIfPossible(op[b]).
90*c8dee2aaSAndroid Build Coastguard Worker */
combinable_index(int a,int b)91*c8dee2aaSAndroid Build Coastguard Worker int64_t combinable_index(int a, int b) {
92*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(b != a);
93*c8dee2aaSAndroid Build Coastguard Worker // Each index gets kNumOps - 1 contiguous bools
94*c8dee2aaSAndroid Build Coastguard Worker int64_t aOffset = a * (kNumOps - 1);
95*c8dee2aaSAndroid Build Coastguard Worker // Within a's range we have one value each other op, but not one for a itself.
96*c8dee2aaSAndroid Build Coastguard Worker int64_t bIdxInA = b < a ? b : b - 1;
97*c8dee2aaSAndroid Build Coastguard Worker return aOffset + bIdxInA;
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker
100*c8dee2aaSAndroid Build Coastguard Worker /**
101*c8dee2aaSAndroid Build Coastguard Worker * Creates a legal set of combinability results for the ops. The likelihood that any two ops
102*c8dee2aaSAndroid Build Coastguard Worker * in a group can merge is randomly chosen.
103*c8dee2aaSAndroid Build Coastguard Worker */
init_combinable(int numGroups,Combinable * combinable,SkRandom * random)104*c8dee2aaSAndroid Build Coastguard Worker static void init_combinable(int numGroups, Combinable* combinable, SkRandom* random) {
105*c8dee2aaSAndroid Build Coastguard Worker SkScalar mergeProbability = random->nextUScalar1();
106*c8dee2aaSAndroid Build Coastguard Worker std::fill_n(combinable->begin(), kNumCombinableValues, GrOp::CombineResult::kCannotCombine);
107*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<int> groups[kNumOps];
108*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumOps; ++i) {
109*c8dee2aaSAndroid Build Coastguard Worker auto& group = groups[random->nextULessThan(numGroups)];
110*c8dee2aaSAndroid Build Coastguard Worker for (int g = 0; g < group.size(); ++g) {
111*c8dee2aaSAndroid Build Coastguard Worker int j = group[g];
112*c8dee2aaSAndroid Build Coastguard Worker if (random->nextUScalar1() < mergeProbability) {
113*c8dee2aaSAndroid Build Coastguard Worker (*combinable)[combinable_index(i, j)] = GrOp::CombineResult::kMerged;
114*c8dee2aaSAndroid Build Coastguard Worker } else {
115*c8dee2aaSAndroid Build Coastguard Worker (*combinable)[combinable_index(i, j)] = GrOp::CombineResult::kMayChain;
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker if (random->nextUScalar1() < mergeProbability) {
118*c8dee2aaSAndroid Build Coastguard Worker (*combinable)[combinable_index(j, i)] = GrOp::CombineResult::kMerged;
119*c8dee2aaSAndroid Build Coastguard Worker } else {
120*c8dee2aaSAndroid Build Coastguard Worker (*combinable)[combinable_index(j, i)] = GrOp::CombineResult::kMayChain;
121*c8dee2aaSAndroid Build Coastguard Worker }
122*c8dee2aaSAndroid Build Coastguard Worker }
123*c8dee2aaSAndroid Build Coastguard Worker group.push_back(i);
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker }
126*c8dee2aaSAndroid Build Coastguard Worker
127*c8dee2aaSAndroid Build Coastguard Worker /**
128*c8dee2aaSAndroid Build Coastguard Worker * A simple test op. It has an integer position, p. When it executes it writes p into an array
129*c8dee2aaSAndroid Build Coastguard Worker * of ints at index p and p+1. It takes a bitfield that indicates allowed pair-wise chainings.
130*c8dee2aaSAndroid Build Coastguard Worker */
131*c8dee2aaSAndroid Build Coastguard Worker class TestOp : public GrOp {
132*c8dee2aaSAndroid Build Coastguard Worker public:
133*c8dee2aaSAndroid Build Coastguard Worker DEFINE_OP_CLASS_ID
134*c8dee2aaSAndroid Build Coastguard Worker
Make(GrRecordingContext * context,int value,const Range & range,int result[],const Combinable * combinable)135*c8dee2aaSAndroid Build Coastguard Worker static GrOp::Owner Make(GrRecordingContext* context, int value, const Range& range,
136*c8dee2aaSAndroid Build Coastguard Worker int result[], const Combinable* combinable) {
137*c8dee2aaSAndroid Build Coastguard Worker return GrOp::Make<TestOp>(context, value, range, result, combinable);
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker
name() const140*c8dee2aaSAndroid Build Coastguard Worker const char* name() const override { return "TestOp"; }
141*c8dee2aaSAndroid Build Coastguard Worker
writeResult(int result[]) const142*c8dee2aaSAndroid Build Coastguard Worker void writeResult(int result[]) const {
143*c8dee2aaSAndroid Build Coastguard Worker for (const auto& op : ChainRange<TestOp>(this)) {
144*c8dee2aaSAndroid Build Coastguard Worker for (const auto& vr : op.fValueRanges) {
145*c8dee2aaSAndroid Build Coastguard Worker for (unsigned i = 0; i < vr.fRange.fLength; ++i) {
146*c8dee2aaSAndroid Build Coastguard Worker result[vr.fRange.fOffset + i] = vr.fValue;
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker }
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker private:
153*c8dee2aaSAndroid Build Coastguard Worker friend class ::GrOp; // for ctor
154*c8dee2aaSAndroid Build Coastguard Worker
TestOp(int value,const Range & range,int result[],const Combinable * combinable)155*c8dee2aaSAndroid Build Coastguard Worker TestOp(int value, const Range& range, int result[], const Combinable* combinable)
156*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(ClassID()), fResult(result), fCombinable(combinable) {
157*c8dee2aaSAndroid Build Coastguard Worker fValueRanges.push_back({value, range});
158*c8dee2aaSAndroid Build Coastguard Worker this->setBounds(SkRect::MakeXYWH(range.fOffset, 0, range.fOffset + range.fLength, 1),
159*c8dee2aaSAndroid Build Coastguard Worker HasAABloat::kNo, IsHairline::kNo);
160*c8dee2aaSAndroid Build Coastguard Worker }
161*c8dee2aaSAndroid Build Coastguard Worker
onPrePrepare(GrRecordingContext *,const GrSurfaceProxyView & writeView,GrAppliedClip *,const GrDstProxyView &,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)162*c8dee2aaSAndroid Build Coastguard Worker void onPrePrepare(GrRecordingContext*,
163*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView& writeView,
164*c8dee2aaSAndroid Build Coastguard Worker GrAppliedClip*,
165*c8dee2aaSAndroid Build Coastguard Worker const GrDstProxyView&,
166*c8dee2aaSAndroid Build Coastguard Worker GrXferBarrierFlags renderPassXferBarriers,
167*c8dee2aaSAndroid Build Coastguard Worker GrLoadOp colorLoadOp) override {}
168*c8dee2aaSAndroid Build Coastguard Worker
onPrepare(GrOpFlushState *)169*c8dee2aaSAndroid Build Coastguard Worker void onPrepare(GrOpFlushState*) override {}
170*c8dee2aaSAndroid Build Coastguard Worker
onExecute(GrOpFlushState *,const SkRect & chainBounds)171*c8dee2aaSAndroid Build Coastguard Worker void onExecute(GrOpFlushState*, const SkRect& chainBounds) override {
172*c8dee2aaSAndroid Build Coastguard Worker for (auto& op : ChainRange<TestOp>(this)) {
173*c8dee2aaSAndroid Build Coastguard Worker op.writeResult(fResult);
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker }
176*c8dee2aaSAndroid Build Coastguard Worker
onCombineIfPossible(GrOp * t,SkArenaAlloc * arenas,const GrCaps &)177*c8dee2aaSAndroid Build Coastguard Worker CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc* arenas, const GrCaps&) override {
178*c8dee2aaSAndroid Build Coastguard Worker // This op doesn't use the arenas, but make sure the OpsTask is sending it
179*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(arenas);
180*c8dee2aaSAndroid Build Coastguard Worker (void) arenas;
181*c8dee2aaSAndroid Build Coastguard Worker auto that = t->cast<TestOp>();
182*c8dee2aaSAndroid Build Coastguard Worker int v0 = fValueRanges[0].fValue;
183*c8dee2aaSAndroid Build Coastguard Worker int v1 = that->fValueRanges[0].fValue;
184*c8dee2aaSAndroid Build Coastguard Worker auto result = (*fCombinable)[combinable_index(v0, v1)];
185*c8dee2aaSAndroid Build Coastguard Worker if (result == GrOp::CombineResult::kMerged) {
186*c8dee2aaSAndroid Build Coastguard Worker std::move(that->fValueRanges.begin(), that->fValueRanges.end(),
187*c8dee2aaSAndroid Build Coastguard Worker std::back_inserter(fValueRanges));
188*c8dee2aaSAndroid Build Coastguard Worker }
189*c8dee2aaSAndroid Build Coastguard Worker return result;
190*c8dee2aaSAndroid Build Coastguard Worker }
191*c8dee2aaSAndroid Build Coastguard Worker
192*c8dee2aaSAndroid Build Coastguard Worker struct ValueRange {
193*c8dee2aaSAndroid Build Coastguard Worker int fValue;
194*c8dee2aaSAndroid Build Coastguard Worker Range fRange;
195*c8dee2aaSAndroid Build Coastguard Worker };
196*c8dee2aaSAndroid Build Coastguard Worker std::vector<ValueRange> fValueRanges;
197*c8dee2aaSAndroid Build Coastguard Worker int* fResult;
198*c8dee2aaSAndroid Build Coastguard Worker const Combinable* fCombinable;
199*c8dee2aaSAndroid Build Coastguard Worker
200*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrOp;
201*c8dee2aaSAndroid Build Coastguard Worker };
202*c8dee2aaSAndroid Build Coastguard Worker } // namespace
203*c8dee2aaSAndroid Build Coastguard Worker
204*c8dee2aaSAndroid Build Coastguard Worker /**
205*c8dee2aaSAndroid Build Coastguard Worker * Tests adding kNumOps to an op list with all possible allowed chaining configurations. Tests
206*c8dee2aaSAndroid Build Coastguard Worker * adding the ops in all possible orders and verifies that the chained executions don't violate
207*c8dee2aaSAndroid Build Coastguard Worker * painter's order.
208*c8dee2aaSAndroid Build Coastguard Worker */
209*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST(OpChainTest, reporter, /*ctxInfo*/, CtsEnforcement::kApiLevel_T) {
210*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrDirectContext> dContext = GrDirectContext::MakeMock(nullptr);
211*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dContext);
212*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = dContext->priv().caps();
213*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkISize kDims = {kNumOps + 1, 1};
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
216*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kYes);
217*c8dee2aaSAndroid Build Coastguard Worker
218*c8dee2aaSAndroid Build Coastguard Worker static const GrSurfaceOrigin kOrigin = kTopLeft_GrSurfaceOrigin;
219*c8dee2aaSAndroid Build Coastguard Worker auto proxy = dContext->priv().proxyProvider()->createProxy(format,
220*c8dee2aaSAndroid Build Coastguard Worker kDims,
221*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kYes,
222*c8dee2aaSAndroid Build Coastguard Worker 1,
223*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
224*c8dee2aaSAndroid Build Coastguard Worker SkBackingFit::kExact,
225*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kNo,
226*c8dee2aaSAndroid Build Coastguard Worker GrProtected::kNo,
227*c8dee2aaSAndroid Build Coastguard Worker /*label=*/"OpChainTest",
228*c8dee2aaSAndroid Build Coastguard Worker GrInternalSurfaceFlags::kNone);
229*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(proxy);
230*c8dee2aaSAndroid Build Coastguard Worker proxy->instantiate(dContext->priv().resourceProvider());
231*c8dee2aaSAndroid Build Coastguard Worker
232*c8dee2aaSAndroid Build Coastguard Worker skgpu::Swizzle writeSwizzle = caps->getWriteSwizzle(format, GrColorType::kRGBA_8888);
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker int result[result_width()];
235*c8dee2aaSAndroid Build Coastguard Worker int validResult[result_width()];
236*c8dee2aaSAndroid Build Coastguard Worker
237*c8dee2aaSAndroid Build Coastguard Worker int permutation[kNumOps];
238*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumOps; ++i) {
239*c8dee2aaSAndroid Build Coastguard Worker permutation[i] = i;
240*c8dee2aaSAndroid Build Coastguard Worker }
241*c8dee2aaSAndroid Build Coastguard Worker // Op order permutations.
242*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumPermutations = 100;
243*c8dee2aaSAndroid Build Coastguard Worker // For a given number of chainability groups, this is the number of random combinability reuslts
244*c8dee2aaSAndroid Build Coastguard Worker // we will test.
245*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumCombinabilitiesPerGrouping = 20;
246*c8dee2aaSAndroid Build Coastguard Worker SkRandom random;
247*c8dee2aaSAndroid Build Coastguard Worker bool repeat = false;
248*c8dee2aaSAndroid Build Coastguard Worker Combinable combinable;
249*c8dee2aaSAndroid Build Coastguard Worker GrDrawingManager* drawingMgr = dContext->priv().drawingManager();
250*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrArenas> arenas = sk_make_sp<GrArenas>();
251*c8dee2aaSAndroid Build Coastguard Worker for (int p = 0; p < kNumPermutations; ++p) {
252*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumOps - 2 && !repeat; ++i) {
253*c8dee2aaSAndroid Build Coastguard Worker // The current implementation of nextULessThan() is biased. :(
254*c8dee2aaSAndroid Build Coastguard Worker unsigned j = i + random.nextULessThan(kNumOps - i);
255*c8dee2aaSAndroid Build Coastguard Worker std::swap(permutation[i], permutation[j]);
256*c8dee2aaSAndroid Build Coastguard Worker }
257*c8dee2aaSAndroid Build Coastguard Worker // g is the number of chainable groups that we partition the ops into.
258*c8dee2aaSAndroid Build Coastguard Worker for (int g = 1; g < kNumOps; ++g) {
259*c8dee2aaSAndroid Build Coastguard Worker for (int c = 0; c < kNumCombinabilitiesPerGrouping; ++c) {
260*c8dee2aaSAndroid Build Coastguard Worker init_combinable(g, &combinable, &random);
261*c8dee2aaSAndroid Build Coastguard Worker skgpu::TokenTracker tracker;
262*c8dee2aaSAndroid Build Coastguard Worker GrOpFlushState flushState(dContext->priv().getGpu(),
263*c8dee2aaSAndroid Build Coastguard Worker dContext->priv().resourceProvider(),
264*c8dee2aaSAndroid Build Coastguard Worker &tracker);
265*c8dee2aaSAndroid Build Coastguard Worker skgpu::ganesh::OpsTask opsTask(drawingMgr,
266*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxyView(proxy, kOrigin, writeSwizzle),
267*c8dee2aaSAndroid Build Coastguard Worker dContext->priv().auditTrail(),
268*c8dee2aaSAndroid Build Coastguard Worker arenas);
269*c8dee2aaSAndroid Build Coastguard Worker // This assumes the particular values of kRanges.
270*c8dee2aaSAndroid Build Coastguard Worker std::fill_n(result, result_width(), -1);
271*c8dee2aaSAndroid Build Coastguard Worker std::fill_n(validResult, result_width(), -1);
272*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumOps; ++i) {
273*c8dee2aaSAndroid Build Coastguard Worker int value = permutation[i];
274*c8dee2aaSAndroid Build Coastguard Worker // factor out the repeats and then use the canonical starting position and range
275*c8dee2aaSAndroid Build Coastguard Worker // to determine an actual range.
276*c8dee2aaSAndroid Build Coastguard Worker int j = value % (kNumRanges * kNumOpPositions);
277*c8dee2aaSAndroid Build Coastguard Worker int pos = j % kNumOpPositions;
278*c8dee2aaSAndroid Build Coastguard Worker Range range = kRanges[j / kNumOpPositions];
279*c8dee2aaSAndroid Build Coastguard Worker range.fOffset += pos;
280*c8dee2aaSAndroid Build Coastguard Worker auto op = TestOp::Make(dContext.get(), value, range, result, &combinable);
281*c8dee2aaSAndroid Build Coastguard Worker TestOp* testOp = (TestOp*)op.get();
282*c8dee2aaSAndroid Build Coastguard Worker testOp->writeResult(validResult);
283*c8dee2aaSAndroid Build Coastguard Worker opsTask.addOp(drawingMgr, std::move(op),
284*c8dee2aaSAndroid Build Coastguard Worker GrTextureResolveManager(dContext->priv().drawingManager()),
285*c8dee2aaSAndroid Build Coastguard Worker *caps);
286*c8dee2aaSAndroid Build Coastguard Worker }
287*c8dee2aaSAndroid Build Coastguard Worker opsTask.makeClosed(dContext.get());
288*c8dee2aaSAndroid Build Coastguard Worker opsTask.prepare(&flushState);
289*c8dee2aaSAndroid Build Coastguard Worker opsTask.execute(&flushState);
290*c8dee2aaSAndroid Build Coastguard Worker opsTask.endFlush(drawingMgr);
291*c8dee2aaSAndroid Build Coastguard Worker opsTask.disown(drawingMgr);
292*c8dee2aaSAndroid Build Coastguard Worker #if 0 // Useful to repeat a random configuration that fails the test while debugger attached.
293*c8dee2aaSAndroid Build Coastguard Worker if (!std::equal(result, result + result_width(), validResult)) {
294*c8dee2aaSAndroid Build Coastguard Worker repeat = true;
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker #endif
297*c8dee2aaSAndroid Build Coastguard Worker (void)repeat;
298*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, std::equal(result, result + result_width(), validResult));
299*c8dee2aaSAndroid Build Coastguard Worker }
300*c8dee2aaSAndroid Build Coastguard Worker }
301*c8dee2aaSAndroid Build Coastguard Worker }
302*c8dee2aaSAndroid Build Coastguard Worker }
303