1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2022 Google LLC
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 "tests/Test.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Context.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recorder.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recording.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Buffer.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RecorderPriv.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/UploadBufferManager.h"
16*c8dee2aaSAndroid Build Coastguard Worker
17*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
18*c8dee2aaSAndroid Build Coastguard Worker
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(UploadBufferManagerTest,reporter,context,CtsEnforcement::kApiLevel_V)19*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(UploadBufferManagerTest, reporter, context,
20*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
21*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recorder> recorder = context->makeRecorder();
22*c8dee2aaSAndroid Build Coastguard Worker UploadBufferManager* bufferManager = recorder->priv().uploadBufferManager();
23*c8dee2aaSAndroid Build Coastguard Worker
24*c8dee2aaSAndroid Build Coastguard Worker // The test source data.
25*c8dee2aaSAndroid Build Coastguard Worker char src[8] = {
26*c8dee2aaSAndroid Build Coastguard Worker 1, 2, 3, 4,
27*c8dee2aaSAndroid Build Coastguard Worker 5, 6, 7, 8,
28*c8dee2aaSAndroid Build Coastguard Worker };
29*c8dee2aaSAndroid Build Coastguard Worker
30*c8dee2aaSAndroid Build Coastguard Worker // Test multiple small writes to a reused buffer.
31*c8dee2aaSAndroid Build Coastguard Worker auto [smWriter0, smBufferInfo0] = bufferManager->getTextureUploadWriter(10, 1);
32*c8dee2aaSAndroid Build Coastguard Worker smWriter0.write(/*offset=*/0, src, /*srcRowBytes=*/4, /*dstRowBytes=*/3, /*trimRowBytes=*/3,
33*c8dee2aaSAndroid Build Coastguard Worker /*rowCount=*/2);
34*c8dee2aaSAndroid Build Coastguard Worker smWriter0.write(/*offset=*/6, src, /*srcRowBytes=*/4, /*dstRowBytes=*/2, /*trimRowBytes=*/2,
35*c8dee2aaSAndroid Build Coastguard Worker /*rowCount=*/2);
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker auto [smWriter1, smBufferInfo1] = bufferManager->getTextureUploadWriter(4, 1);
38*c8dee2aaSAndroid Build Coastguard Worker smWriter1.write(/*offset=*/0, src, /*srcRowBytes=*/4, /*dstRowBytes=*/2, /*trimRowBytes=*/2,
39*c8dee2aaSAndroid Build Coastguard Worker /*rowCount=*/2);
40*c8dee2aaSAndroid Build Coastguard Worker
41*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smBufferInfo0.fBuffer == smBufferInfo1.fBuffer);
42*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smBufferInfo0.fOffset == 0);
43*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smBufferInfo1.fOffset >= 10);
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Worker // Test a large write, which should get its own dedicated buffer.
46*c8dee2aaSAndroid Build Coastguard Worker auto [lgWriter, lgBufferInfo] = bufferManager->getTextureUploadWriter((64 << 10) + 1, 1);
47*c8dee2aaSAndroid Build Coastguard Worker lgWriter.write(/*offset=*/0, src, /*srcRowBytes=*/4, /*dstRowBytes=*/2, /*trimRowBytes=*/2,
48*c8dee2aaSAndroid Build Coastguard Worker /*rowCount=*/2);
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, lgBufferInfo.fBuffer != smBufferInfo0.fBuffer);
51*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, lgBufferInfo.fOffset == 0);
52*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, lgBufferInfo.fBuffer->isMapped());
53*c8dee2aaSAndroid Build Coastguard Worker const void* lgBufferMap = const_cast<Buffer*>(lgBufferInfo.fBuffer)->map();
54*c8dee2aaSAndroid Build Coastguard Worker const char expectedLgBufferMap[4] = {
55*c8dee2aaSAndroid Build Coastguard Worker 1, 2,
56*c8dee2aaSAndroid Build Coastguard Worker 5, 6,
57*c8dee2aaSAndroid Build Coastguard Worker };
58*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
59*c8dee2aaSAndroid Build Coastguard Worker memcmp(lgBufferMap, expectedLgBufferMap, sizeof(expectedLgBufferMap)) == 0);
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker // Test another small write after the large write.
62*c8dee2aaSAndroid Build Coastguard Worker auto [smWriter2, smBufferInfo2] = bufferManager->getTextureUploadWriter(2, 1);
63*c8dee2aaSAndroid Build Coastguard Worker smWriter2.write(/*offset=*/0, src, /*srcRowBytes=*/4, /*dstRowBytes=*/2, /*trimRowBytes=*/2,
64*c8dee2aaSAndroid Build Coastguard Worker /*rowCount=*/1);
65*c8dee2aaSAndroid Build Coastguard Worker
66*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smBufferInfo2.fBuffer == smBufferInfo0.fBuffer);
67*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smBufferInfo2.fOffset >= 4 + smBufferInfo1.fOffset);
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smBufferInfo0.fBuffer->isMapped());
70*c8dee2aaSAndroid Build Coastguard Worker const char* smBufferMap =
71*c8dee2aaSAndroid Build Coastguard Worker reinterpret_cast<const char*>(const_cast<Buffer*>(smBufferInfo0.fBuffer)->map());
72*c8dee2aaSAndroid Build Coastguard Worker // Each section of written data could be offset and aligned by GPU-required rules, so we can't
73*c8dee2aaSAndroid Build Coastguard Worker // easily validate the contents of the buffer in one go, and instead test at each of the three
74*c8dee2aaSAndroid Build Coastguard Worker // reported offsets.
75*c8dee2aaSAndroid Build Coastguard Worker const char expectedSmBuffer0[10] = { 1, 2, 3, 5, 6, 7, 1, 2, 5, 6 };
76*c8dee2aaSAndroid Build Coastguard Worker const char expectedSmBuffer1[4] = { 1, 2, 5, 6 };
77*c8dee2aaSAndroid Build Coastguard Worker const char expectedSmBuffer2[2] = { 1, 2};
78*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, memcmp(smBufferMap + smBufferInfo0.fOffset,
79*c8dee2aaSAndroid Build Coastguard Worker expectedSmBuffer0,
80*c8dee2aaSAndroid Build Coastguard Worker sizeof(expectedSmBuffer0)) == 0);
81*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, memcmp(smBufferMap + smBufferInfo1.fOffset,
82*c8dee2aaSAndroid Build Coastguard Worker expectedSmBuffer1,
83*c8dee2aaSAndroid Build Coastguard Worker sizeof(expectedSmBuffer1)) == 0);
84*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, memcmp(smBufferMap + smBufferInfo2.fOffset,
85*c8dee2aaSAndroid Build Coastguard Worker expectedSmBuffer1,
86*c8dee2aaSAndroid Build Coastguard Worker sizeof(expectedSmBuffer2)) == 0);
87*c8dee2aaSAndroid Build Coastguard Worker
88*c8dee2aaSAndroid Build Coastguard Worker // Snap a Recording from the Recorder. This will transfer resources from the UploadBufferManager
89*c8dee2aaSAndroid Build Coastguard Worker // to the Recording.
90*c8dee2aaSAndroid Build Coastguard Worker auto recording = recorder->snap();
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker // Test writes with a required alignment.
93*c8dee2aaSAndroid Build Coastguard Worker auto [alWriter0, alBufferInfo0] = bufferManager->getTextureUploadWriter(6, 4);
94*c8dee2aaSAndroid Build Coastguard Worker alWriter0.write(/*offset=*/0, src, /*srcRowBytes=*/4, /*dstRowBytes=*/3, /*trimRowBytes=*/3,
95*c8dee2aaSAndroid Build Coastguard Worker /*rowCount=*/2);
96*c8dee2aaSAndroid Build Coastguard Worker
97*c8dee2aaSAndroid Build Coastguard Worker auto [alWriter1, alBufferInfo1] = bufferManager->getTextureUploadWriter(2, 4);
98*c8dee2aaSAndroid Build Coastguard Worker alWriter1.write(/*offset=*/0, src, /*srcRowBytes=*/4, /*dstRowBytes=*/2, /*trimRowBytes=*/2,
99*c8dee2aaSAndroid Build Coastguard Worker /*rowCount=*/1);
100*c8dee2aaSAndroid Build Coastguard Worker
101*c8dee2aaSAndroid Build Coastguard Worker // Should not share a buffer with earlier small writes, since we've transferred previously-
102*c8dee2aaSAndroid Build Coastguard Worker // allocated resources to the command buffer.
103*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, alBufferInfo0.fBuffer != smBufferInfo0.fBuffer);
104*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, alBufferInfo0.fBuffer == alBufferInfo1.fBuffer);
105*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, alBufferInfo0.fOffset == 0);
106*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, alBufferInfo1.fOffset == 8);
107*c8dee2aaSAndroid Build Coastguard Worker
108*c8dee2aaSAndroid Build Coastguard Worker // From alWriter0.
109*c8dee2aaSAndroid Build Coastguard Worker const char expectedAlBufferMap0[6] = {
110*c8dee2aaSAndroid Build Coastguard Worker 1, 2, 3,
111*c8dee2aaSAndroid Build Coastguard Worker 5, 6, 7,
112*c8dee2aaSAndroid Build Coastguard Worker };
113*c8dee2aaSAndroid Build Coastguard Worker // From alWriter1.
114*c8dee2aaSAndroid Build Coastguard Worker const char expectedAlBufferMap1[2] = {
115*c8dee2aaSAndroid Build Coastguard Worker 1, 2,
116*c8dee2aaSAndroid Build Coastguard Worker };
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, alBufferInfo0.fBuffer->isMapped());
119*c8dee2aaSAndroid Build Coastguard Worker const void* alBufferMap = const_cast<Buffer*>(alBufferInfo0.fBuffer)->map();
120*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
121*c8dee2aaSAndroid Build Coastguard Worker memcmp(alBufferMap, expectedAlBufferMap0, sizeof(expectedAlBufferMap0)) == 0);
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker alBufferMap = SkTAddOffset<const void>(alBufferMap, 8);
124*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
125*c8dee2aaSAndroid Build Coastguard Worker memcmp(alBufferMap, expectedAlBufferMap1, sizeof(expectedAlBufferMap1)) == 0);
126*c8dee2aaSAndroid Build Coastguard Worker }
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
129