blob: 74041d9779a4f4d0996b9bedd18dc269a413baf4 [file] [log] [blame]
Yan47652562021-05-07 01:48:14 +00001// Copyright 2021 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 "common/Assert.h"
16#include "common/Constants.h"
17#include "common/Math.h"
18#include "tests/unittests/validation/ValidationTest.h"
19#include "utils/TestUtils.h"
Yunchao He9749f5a2021-07-09 02:47:49 +000020#include "utils/TextureUtils.h"
Yan47652562021-05-07 01:48:14 +000021#include "utils/WGPUHelpers.h"
22
23class CopyTextureForBrowserTest : public ValidationTest {
24 protected:
25 wgpu::Texture Create2DTexture(uint32_t width,
26 uint32_t height,
27 uint32_t mipLevelCount,
28 uint32_t arrayLayerCount,
29 wgpu::TextureFormat format,
30 wgpu::TextureUsage usage,
31 uint32_t sampleCount = 1) {
32 wgpu::TextureDescriptor descriptor;
33 descriptor.dimension = wgpu::TextureDimension::e2D;
34 descriptor.size.width = width;
35 descriptor.size.height = height;
36 descriptor.size.depthOrArrayLayers = arrayLayerCount;
37 descriptor.sampleCount = sampleCount;
38 descriptor.format = format;
39 descriptor.mipLevelCount = mipLevelCount;
40 descriptor.usage = usage;
41 wgpu::Texture tex = device.CreateTexture(&descriptor);
42 return tex;
43 }
44
45 void TestCopyTextureForBrowser(utils::Expectation expectation,
46 wgpu::Texture srcTexture,
47 uint32_t srcLevel,
48 wgpu::Origin3D srcOrigin,
49 wgpu::Texture dstTexture,
50 uint32_t dstLevel,
51 wgpu::Origin3D dstOrigin,
52 wgpu::Extent3D extent3D,
Yan483bead2021-12-14 04:51:45 +000053 wgpu::TextureAspect aspect = wgpu::TextureAspect::All,
54 wgpu::CopyTextureForBrowserOptions options = {}) {
Yan47652562021-05-07 01:48:14 +000055 wgpu::ImageCopyTexture srcImageCopyTexture =
56 utils::CreateImageCopyTexture(srcTexture, srcLevel, srcOrigin, aspect);
57 wgpu::ImageCopyTexture dstImageCopyTexture =
58 utils::CreateImageCopyTexture(dstTexture, dstLevel, dstOrigin, aspect);
Yan47652562021-05-07 01:48:14 +000059
60 if (expectation == utils::Expectation::Success) {
61 device.GetQueue().CopyTextureForBrowser(&srcImageCopyTexture, &dstImageCopyTexture,
62 &extent3D, &options);
63 } else {
64 ASSERT_DEVICE_ERROR(device.GetQueue().CopyTextureForBrowser(
65 &srcImageCopyTexture, &dstImageCopyTexture, &extent3D, &options));
66 }
67 }
68};
69
70// Tests should be Success
71TEST_F(CopyTextureForBrowserTest, Success) {
72 wgpu::Texture source =
73 Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
Brandon Jones27e17a62021-08-10 04:07:37 +000074 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
Yan47652562021-05-07 01:48:14 +000075 wgpu::Texture destination =
76 Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
77 wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
78
79 // Different copies, including some that touch the OOB condition
80 {
81 // Copy a region along top left boundary
82 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
83 {0, 0, 0}, {4, 4, 1});
84
85 // Copy entire texture
86 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
87 {0, 0, 0}, {16, 16, 1});
88
89 // Copy a region along bottom right boundary
90 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {8, 8, 0}, destination, 0,
91 {8, 8, 0}, {8, 8, 1});
92
93 // Copy region into mip
94 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 2,
95 {0, 0, 0}, {4, 4, 1});
96
97 // Copy mip into region
98 TestCopyTextureForBrowser(utils::Expectation::Success, source, 2, {0, 0, 0}, destination, 0,
99 {0, 0, 0}, {4, 4, 1});
100
101 // Copy between slices
102 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
103 {0, 0, 1}, {16, 16, 1});
104 }
105
106 // Empty copies are valid
107 {
108 // An empty copy
109 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
110 {0, 0, 0}, {0, 0, 1});
111
112 // An empty copy with depth = 0
113 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
114 {0, 0, 0}, {0, 0, 0});
115
116 // An empty copy touching the side of the source texture
117 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
118 {16, 16, 0}, {0, 0, 1});
119
120 // An empty copy touching the side of the destination texture
121 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
122 {16, 16, 0}, {0, 0, 1});
123 }
124}
125
126// Test source or destination texture has wrong usages
127TEST_F(CopyTextureForBrowserTest, IncorrectUsage) {
128 wgpu::Texture validSource =
129 Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
Brandon Jones27e17a62021-08-10 04:07:37 +0000130 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
Yan47652562021-05-07 01:48:14 +0000131 wgpu::Texture validDestination =
132 Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
133 wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
134 wgpu::Texture noSampledUsageSource =
135 Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopySrc);
136 wgpu::Texture noRenderAttachmentUsageDestination =
137 Create2DTexture(16, 16, 5, 2, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopyDst);
Brandon Jones27e17a62021-08-10 04:07:37 +0000138 wgpu::Texture noCopySrcUsageSource = Create2DTexture(
139 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::TextureBinding);
Yan47652562021-05-07 01:48:14 +0000140 wgpu::Texture noCopyDstUsageSource = Create2DTexture(
141 16, 16, 5, 2, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::RenderAttachment);
142
143 // Incorrect source usage causes failure : lack |Sampled| usage
144 TestCopyTextureForBrowser(utils::Expectation::Failure, noSampledUsageSource, 0, {0, 0, 0},
145 validDestination, 0, {0, 0, 0}, {16, 16, 1});
146
147 // Incorrect destination usage causes failure: lack |RenderAttachement| usage.
148 TestCopyTextureForBrowser(utils::Expectation::Failure, validSource, 0, {0, 0, 0},
149 noRenderAttachmentUsageDestination, 0, {0, 0, 0}, {16, 16, 1});
150
151 // Incorrect source usage causes failure : lack |CopySrc| usage
152 TestCopyTextureForBrowser(utils::Expectation::Failure, noCopySrcUsageSource, 0, {0, 0, 0},
153 validDestination, 0, {0, 0, 0}, {16, 16, 1});
154
155 // Incorrect destination usage causes failure: lack |CopyDst| usage.
156 TestCopyTextureForBrowser(utils::Expectation::Failure, validSource, 0, {0, 0, 0},
157 noCopyDstUsageSource, 0, {0, 0, 0}, {16, 16, 1});
158}
159
160// Test non-zero value origin in source and OOB copy rects.
161TEST_F(CopyTextureForBrowserTest, OutOfBounds) {
162 wgpu::Texture source =
163 Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
Brandon Jones27e17a62021-08-10 04:07:37 +0000164 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
Yan47652562021-05-07 01:48:14 +0000165 wgpu::Texture destination =
166 Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
167 wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
168
169 // OOB on source
170 {
171 // x + width overflows
172 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {1, 0, 0}, destination, 0,
173 {0, 0, 0}, {16, 16, 1});
174
175 // y + height overflows
176 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 1, 0}, destination, 0,
177 {0, 0, 0}, {16, 16, 1});
178
179 // non-zero mip overflows
180 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 1, {0, 0, 0}, destination, 0,
181 {0, 0, 0}, {9, 9, 1});
182
183 // copy to multiple slices
184 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
185 {0, 0, 2}, {16, 16, 2});
186
187 // copy origin z value is non-zero.
188 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 1}, destination, 0,
189 {0, 0, 2}, {16, 16, 1});
190 }
191
192 // OOB on destination
193 {
194 // x + width overflows
195 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
196 {1, 0, 0}, {16, 16, 1});
197
198 // y + height overflows
199 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
200 {0, 1, 0}, {16, 16, 1});
201
202 // non-zero mip overflows
203 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 1,
204 {0, 0, 0}, {9, 9, 1});
205
206 // arrayLayer + depth OOB
207 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
208 {0, 0, 4}, {16, 16, 1});
209
210 // empty copy on non-existent mip fails
211 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 6,
212 {0, 0, 0}, {0, 0, 1});
213
214 // empty copy on non-existent slice fails
215 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
216 {0, 0, 4}, {0, 0, 1});
217 }
218}
219
220// Test destination texture has format that not supported by CopyTextureForBrowser().
221TEST_F(CopyTextureForBrowserTest, InvalidDstFormat) {
222 wgpu::Texture source =
223 Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
Brandon Jones27e17a62021-08-10 04:07:37 +0000224 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
Yan47652562021-05-07 01:48:14 +0000225 wgpu::Texture destination =
226 Create2DTexture(16, 16, 5, 2, wgpu::TextureFormat::RG8Uint,
227 wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
228
229 // Not supported dst texture format.
230 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
231 {0, 0, 0}, {0, 0, 1});
232}
233
234// Test source or destination texture are multisampled.
235TEST_F(CopyTextureForBrowserTest, InvalidSampleCount) {
236 wgpu::Texture sourceMultiSampled1x =
237 Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
Brandon Jones27e17a62021-08-10 04:07:37 +0000238 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding, 1);
Yan47652562021-05-07 01:48:14 +0000239 wgpu::Texture destinationMultiSampled1x =
240 Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
241 wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 1);
242 wgpu::Texture sourceMultiSampled4x =
243 Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
Brandon Jones27e17a62021-08-10 04:07:37 +0000244 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding, 4);
Yan47652562021-05-07 01:48:14 +0000245 wgpu::Texture destinationMultiSampled4x =
246 Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
247 wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 4);
248
249 // An empty copy with dst texture sample count > 1 failure.
250 TestCopyTextureForBrowser(utils::Expectation::Failure, sourceMultiSampled1x, 0, {0, 0, 0},
251 destinationMultiSampled4x, 0, {0, 0, 0}, {0, 0, 1});
252
253 // A empty copy with source texture sample count > 1 failure
254 TestCopyTextureForBrowser(utils::Expectation::Failure, sourceMultiSampled4x, 0, {0, 0, 0},
255 destinationMultiSampled1x, 0, {0, 0, 0}, {0, 0, 1});
256}
Yan483bead2021-12-14 04:51:45 +0000257
258// Test color space conversion related attributes in CopyTextureForBrowserOptions.
259TEST_F(CopyTextureForBrowserTest, ColorSpaceConversion_ColorSpace) {
260 wgpu::Texture source =
261 Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
262 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
263 wgpu::Texture destination =
264 Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
265 wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
266
267 wgpu::CopyTextureForBrowserOptions options = {};
Yan483bead2021-12-14 04:51:45 +0000268 options.needsColorSpaceConversion = true;
Yan483bead2021-12-14 04:51:45 +0000269
270 // Valid cases
271 {
272 wgpu::CopyTextureForBrowserOptions validOptions = options;
Yan52040532021-12-15 04:08:56 +0000273 std::array<float, 7> srcTransferFunctionParameters = {};
274 std::array<float, 7> dstTransferFunctionParameters = {};
275 std::array<float, 9> conversionMatrix = {};
276 validOptions.srcTransferFunctionParameters = srcTransferFunctionParameters.data();
277 validOptions.dstTransferFunctionParameters = dstTransferFunctionParameters.data();
278 validOptions.conversionMatrix = conversionMatrix.data();
Yan483bead2021-12-14 04:51:45 +0000279 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
280 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, validOptions);
281
282 // if no color space conversion, no need to validate related attributes
283 wgpu::CopyTextureForBrowserOptions noColorSpaceConversion = options;
284 noColorSpaceConversion.needsColorSpaceConversion = false;
285 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
286 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All,
287 noColorSpaceConversion);
288 }
289
Yan483bead2021-12-14 04:51:45 +0000290 // Invalid cases: srcTransferFunctionParameters, dstTransferFunctionParameters or
Yan52040532021-12-15 04:08:56 +0000291 // conversionMatrix is nullptr or not set
Yan483bead2021-12-14 04:51:45 +0000292 {
Yan52040532021-12-15 04:08:56 +0000293 // not set srcTransferFunctionParameters
Yan483bead2021-12-14 04:51:45 +0000294 wgpu::CopyTextureForBrowserOptions invalidOptions = options;
Yan52040532021-12-15 04:08:56 +0000295 std::array<float, 7> dstTransferFunctionParameters = {};
296 std::array<float, 9> conversionMatrix = {};
297 invalidOptions.dstTransferFunctionParameters = dstTransferFunctionParameters.data();
298 invalidOptions.conversionMatrix = conversionMatrix.data();
299 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
300 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, invalidOptions);
301
302 // set to nullptr
Yan483bead2021-12-14 04:51:45 +0000303 invalidOptions.srcTransferFunctionParameters = nullptr;
304 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
305 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, invalidOptions);
306 }
307
308 {
Yan52040532021-12-15 04:08:56 +0000309 // not set dstTransferFunctionParameters
Yan483bead2021-12-14 04:51:45 +0000310 wgpu::CopyTextureForBrowserOptions invalidOptions = options;
Yan52040532021-12-15 04:08:56 +0000311 std::array<float, 7> srcTransferFunctionParameters = {};
312 std::array<float, 9> conversionMatrix = {};
313 invalidOptions.srcTransferFunctionParameters = srcTransferFunctionParameters.data();
314 invalidOptions.conversionMatrix = conversionMatrix.data();
315 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
316 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, invalidOptions);
317
318 // set to nullptr
Yan483bead2021-12-14 04:51:45 +0000319 invalidOptions.dstTransferFunctionParameters = nullptr;
320 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
321 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, invalidOptions);
322 }
323
324 {
Yan52040532021-12-15 04:08:56 +0000325 // not set conversionMatrix
Yan483bead2021-12-14 04:51:45 +0000326 wgpu::CopyTextureForBrowserOptions invalidOptions = options;
Yan52040532021-12-15 04:08:56 +0000327 std::array<float, 7> srcTransferFunctionParameters = {};
328 std::array<float, 7> dstTransferFunctionParameters = {};
329 invalidOptions.srcTransferFunctionParameters = srcTransferFunctionParameters.data();
330 invalidOptions.dstTransferFunctionParameters = dstTransferFunctionParameters.data();
331 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
332 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, invalidOptions);
333
334 // set to nullptr
Yan483bead2021-12-14 04:51:45 +0000335 invalidOptions.conversionMatrix = nullptr;
336 TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
337 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, invalidOptions);
338 }
339}
340
341// Test option.srcAlphaMode/dstAlphaMode
342TEST_F(CopyTextureForBrowserTest, ColorSpaceConversion_TextureAlphaState) {
343 wgpu::Texture source =
344 Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
345 wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
346 wgpu::Texture destination =
347 Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
348 wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
349
350 wgpu::CopyTextureForBrowserOptions options = {};
351
352 // Valid src texture alpha state and valid dst texture alpha state
353 {
354 options.srcAlphaMode = wgpu::AlphaMode::Premultiplied;
355 options.dstAlphaMode = wgpu::AlphaMode::Premultiplied;
356
357 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
358 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, options);
359
360 options.srcAlphaMode = wgpu::AlphaMode::Premultiplied;
361 options.dstAlphaMode = wgpu::AlphaMode::Unpremultiplied;
362
363 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
364 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, options);
365
366 options.srcAlphaMode = wgpu::AlphaMode::Unpremultiplied;
367 options.dstAlphaMode = wgpu::AlphaMode::Premultiplied;
368
369 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
370 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, options);
371
372 options.srcAlphaMode = wgpu::AlphaMode::Unpremultiplied;
373 options.dstAlphaMode = wgpu::AlphaMode::Unpremultiplied;
374
375 TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
376 {0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, options);
377 }
378}