1 // Copyright 2019 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "tests/perf_tests/DawnPerfTest.h"
16
17 #include "utils/WGPUHelpers.h"
18
19 namespace {
20
21 constexpr unsigned int kNumIterations = 50;
22
23 enum class UploadMethod {
24 WriteBuffer,
25 MappedAtCreation,
26 };
27
28 // Perf delta exists between ranges [0, 1MB] vs [1MB, MAX_SIZE).
29 // These are sample buffer sizes within each range.
30 enum class UploadSize {
31 BufferSize_1KB = 1 * 1024,
32 BufferSize_64KB = 64 * 1024,
33 BufferSize_1MB = 1 * 1024 * 1024,
34
35 BufferSize_4MB = 4 * 1024 * 1024,
36 BufferSize_16MB = 16 * 1024 * 1024,
37 };
38
39 struct BufferUploadParams : AdapterTestParam {
BufferUploadParams__anonc4205b350111::BufferUploadParams40 BufferUploadParams(const AdapterTestParam& param,
41 UploadMethod uploadMethod,
42 UploadSize uploadSize)
43 : AdapterTestParam(param), uploadMethod(uploadMethod), uploadSize(uploadSize) {
44 }
45
46 UploadMethod uploadMethod;
47 UploadSize uploadSize;
48 };
49
operator <<(std::ostream & ostream,const BufferUploadParams & param)50 std::ostream& operator<<(std::ostream& ostream, const BufferUploadParams& param) {
51 ostream << static_cast<const AdapterTestParam&>(param);
52
53 switch (param.uploadMethod) {
54 case UploadMethod::WriteBuffer:
55 ostream << "_WriteBuffer";
56 break;
57 case UploadMethod::MappedAtCreation:
58 ostream << "_MappedAtCreation";
59 break;
60 }
61
62 switch (param.uploadSize) {
63 case UploadSize::BufferSize_1KB:
64 ostream << "_BufferSize_1KB";
65 break;
66 case UploadSize::BufferSize_64KB:
67 ostream << "_BufferSize_64KB";
68 break;
69 case UploadSize::BufferSize_1MB:
70 ostream << "_BufferSize_1MB";
71 break;
72 case UploadSize::BufferSize_4MB:
73 ostream << "_BufferSize_4MB";
74 break;
75 case UploadSize::BufferSize_16MB:
76 ostream << "_BufferSize_16MB";
77 break;
78 }
79
80 return ostream;
81 }
82
83 } // namespace
84
85 // Test uploading |kBufferSize| bytes of data |kNumIterations| times.
86 class BufferUploadPerf : public DawnPerfTestWithParams<BufferUploadParams> {
87 public:
BufferUploadPerf()88 BufferUploadPerf()
89 : DawnPerfTestWithParams(kNumIterations, 1),
90 data(static_cast<size_t>(GetParam().uploadSize)) {
91 }
92 ~BufferUploadPerf() override = default;
93
94 void SetUp() override;
95
96 private:
97 void Step() override;
98
99 wgpu::Buffer dst;
100 std::vector<uint8_t> data;
101 };
102
SetUp()103 void BufferUploadPerf::SetUp() {
104 DawnPerfTestWithParams<BufferUploadParams>::SetUp();
105
106 wgpu::BufferDescriptor desc = {};
107 desc.size = data.size();
108 desc.usage = wgpu::BufferUsage::CopyDst;
109
110 dst = device.CreateBuffer(&desc);
111 }
112
Step()113 void BufferUploadPerf::Step() {
114 switch (GetParam().uploadMethod) {
115 case UploadMethod::WriteBuffer: {
116 for (unsigned int i = 0; i < kNumIterations; ++i) {
117 queue.WriteBuffer(dst, 0, data.data(), data.size());
118 }
119 // Make sure all WriteBuffer's are flushed.
120 queue.Submit(0, nullptr);
121 break;
122 }
123
124 case UploadMethod::MappedAtCreation: {
125 wgpu::BufferDescriptor desc = {};
126 desc.size = data.size();
127 desc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
128 desc.mappedAtCreation = true;
129
130 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
131
132 for (unsigned int i = 0; i < kNumIterations; ++i) {
133 wgpu::Buffer buffer = device.CreateBuffer(&desc);
134 memcpy(buffer.GetMappedRange(0, data.size()), data.data(), data.size());
135 buffer.Unmap();
136 encoder.CopyBufferToBuffer(buffer, 0, dst, 0, data.size());
137 }
138
139 wgpu::CommandBuffer commands = encoder.Finish();
140 queue.Submit(1, &commands);
141 break;
142 }
143 }
144 }
145
TEST_P(BufferUploadPerf,Run)146 TEST_P(BufferUploadPerf, Run) {
147 RunTest();
148 }
149
150 DAWN_INSTANTIATE_TEST_P(BufferUploadPerf,
151 {D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend()},
152 {UploadMethod::WriteBuffer, UploadMethod::MappedAtCreation},
153 {UploadSize::BufferSize_1KB, UploadSize::BufferSize_64KB,
154 UploadSize::BufferSize_1MB, UploadSize::BufferSize_4MB,
155 UploadSize::BufferSize_16MB});
156