• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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"
20 #include "utils/TextureUtils.h"
21 #include "utils/WGPUHelpers.h"
22 
23 class CopyTextureForBrowserTest : public ValidationTest {
24   protected:
Create2DTexture(uint32_t width,uint32_t height,uint32_t mipLevelCount,uint32_t arrayLayerCount,wgpu::TextureFormat format,wgpu::TextureUsage usage,uint32_t sampleCount=1)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 
TestCopyTextureForBrowser(utils::Expectation expectation,wgpu::Texture srcTexture,uint32_t srcLevel,wgpu::Origin3D srcOrigin,wgpu::Texture dstTexture,uint32_t dstLevel,wgpu::Origin3D dstOrigin,wgpu::Extent3D extent3D,wgpu::TextureAspect aspect=wgpu::TextureAspect::All)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,
53                                    wgpu::TextureAspect aspect = wgpu::TextureAspect::All) {
54         wgpu::ImageCopyTexture srcImageCopyTexture =
55             utils::CreateImageCopyTexture(srcTexture, srcLevel, srcOrigin, aspect);
56         wgpu::ImageCopyTexture dstImageCopyTexture =
57             utils::CreateImageCopyTexture(dstTexture, dstLevel, dstOrigin, aspect);
58         wgpu::CopyTextureForBrowserOptions options = {};
59 
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
TEST_F(CopyTextureForBrowserTest,Success)71 TEST_F(CopyTextureForBrowserTest, Success) {
72     wgpu::Texture source =
73         Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
74                         wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
75     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
TEST_F(CopyTextureForBrowserTest,IncorrectUsage)127 TEST_F(CopyTextureForBrowserTest, IncorrectUsage) {
128     wgpu::Texture validSource =
129         Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
130                         wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
131     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);
138     wgpu::Texture noCopySrcUsageSource = Create2DTexture(
139         16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::TextureBinding);
140     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.
TEST_F(CopyTextureForBrowserTest,OutOfBounds)161 TEST_F(CopyTextureForBrowserTest, OutOfBounds) {
162     wgpu::Texture source =
163         Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
164                         wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
165     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().
TEST_F(CopyTextureForBrowserTest,InvalidDstFormat)221 TEST_F(CopyTextureForBrowserTest, InvalidDstFormat) {
222     wgpu::Texture source =
223         Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
224                         wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
225     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.
TEST_F(CopyTextureForBrowserTest,InvalidSampleCount)235 TEST_F(CopyTextureForBrowserTest, InvalidSampleCount) {
236     wgpu::Texture sourceMultiSampled1x =
237         Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
238                         wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding, 1);
239     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,
244                         wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding, 4);
245     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 }
257