• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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/unittests/validation/ValidationTest.h"
16 
17 #include "common/Constants.h"
18 #include "common/Math.h"
19 #include "utils/ComboRenderPipelineDescriptor.h"
20 #include "utils/TextureUtils.h"
21 #include "utils/WGPUHelpers.h"
22 
23 namespace {
24 
25     constexpr wgpu::TextureFormat kNonRenderableColorFormats[] = {
26         wgpu::TextureFormat::RG11B10Ufloat, wgpu::TextureFormat::RGB9E5Ufloat,
27         wgpu::TextureFormat::R8Snorm,       wgpu::TextureFormat::RG8Snorm,
28         wgpu::TextureFormat::RGBA8Snorm,
29     };
30 
31     wgpu::TextureDimension kDimensions[] = {
32         wgpu::TextureDimension::e1D,
33         wgpu::TextureDimension::e3D,
34     };
35 
36     class TextureValidationTest : public ValidationTest {
37       protected:
SetUp()38         void SetUp() override {
39             ValidationTest::SetUp();
40 
41             queue = device.GetQueue();
42         }
43 
CreateDefaultTextureDescriptor()44         wgpu::TextureDescriptor CreateDefaultTextureDescriptor() {
45             wgpu::TextureDescriptor descriptor;
46             descriptor.size.width = kWidth;
47             descriptor.size.height = kHeight;
48             descriptor.size.depthOrArrayLayers = kDefaultDepth;
49             descriptor.mipLevelCount = kDefaultMipLevels;
50             descriptor.sampleCount = kDefaultSampleCount;
51             descriptor.dimension = wgpu::TextureDimension::e2D;
52             descriptor.format = kDefaultTextureFormat;
53             descriptor.usage =
54                 wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
55             return descriptor;
56         }
57 
58         wgpu::Queue queue;
59 
60       private:
61         // Choose the LCM of all current compressed texture format texel dimensions as the
62         // dimensions of the default texture.
63         static constexpr uint32_t kWidth = 120;
64         static constexpr uint32_t kHeight = 120;
65         static constexpr uint32_t kDefaultDepth = 1;
66         static constexpr uint32_t kDefaultMipLevels = 1;
67         static constexpr uint32_t kDefaultSampleCount = 1;
68 
69         static constexpr wgpu::TextureFormat kDefaultTextureFormat =
70             wgpu::TextureFormat::RGBA8Unorm;
71     };
72 
73     // Test the validation of sample count
TEST_F(TextureValidationTest,SampleCount)74     TEST_F(TextureValidationTest, SampleCount) {
75         wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
76 
77         // sampleCount == 1 is allowed.
78         {
79             wgpu::TextureDescriptor descriptor = defaultDescriptor;
80             descriptor.sampleCount = 1;
81 
82             device.CreateTexture(&descriptor);
83         }
84 
85         // sampleCount == 4 is allowed.
86         {
87             wgpu::TextureDescriptor descriptor = defaultDescriptor;
88             descriptor.sampleCount = 4;
89 
90             device.CreateTexture(&descriptor);
91         }
92 
93         // It is an error to create a texture with an invalid sampleCount.
94         {
95             wgpu::TextureDescriptor descriptor = defaultDescriptor;
96             descriptor.sampleCount = 3;
97 
98             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
99         }
100 
101         // It is an error to create a multisampled texture with mipLevelCount > 1.
102         {
103             wgpu::TextureDescriptor descriptor = defaultDescriptor;
104             descriptor.sampleCount = 4;
105             descriptor.mipLevelCount = 2;
106 
107             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
108         }
109 
110         // It is an error to create a multisampled 1D or 3D texture.
111         {
112             wgpu::TextureDescriptor descriptor = defaultDescriptor;
113             descriptor.sampleCount = 4;
114 
115             descriptor.size.height = 1;
116             descriptor.dimension = wgpu::TextureDimension::e1D;
117             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
118 
119             descriptor.dimension = wgpu::TextureDimension::e3D;
120             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
121         }
122 
123         // It is an error to create a multisample texture when the format cannot support
124         // multisample.
125         {
126             wgpu::TextureDescriptor descriptor = defaultDescriptor;
127             descriptor.sampleCount = 4;
128 
129             for (wgpu::TextureFormat format : kNonRenderableColorFormats) {
130                 // If a format can support multisample, it must be renderable.
131                 descriptor.format = format;
132                 ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
133             }
134         }
135 
136         // Currently we do not support multisampled 2D textures with depth>1.
137         {
138             wgpu::TextureDescriptor descriptor = defaultDescriptor;
139             descriptor.sampleCount = 4;
140             descriptor.size.depthOrArrayLayers = 2;
141 
142             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
143         }
144 
145         // It is an error to set TextureUsage::StorageBinding when sampleCount > 1.
146         {
147             wgpu::TextureDescriptor descriptor = defaultDescriptor;
148             descriptor.sampleCount = 4;
149             descriptor.usage |= wgpu::TextureUsage::StorageBinding;
150 
151             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
152         }
153     }
154 
155     // Test the validation of the mip level count
TEST_F(TextureValidationTest,MipLevelCount)156     TEST_F(TextureValidationTest, MipLevelCount) {
157         wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
158 
159         // mipLevelCount == 1 is allowed
160         {
161             wgpu::TextureDescriptor descriptor = defaultDescriptor;
162             descriptor.size.width = 32;
163             descriptor.size.height = 32;
164             descriptor.mipLevelCount = 1;
165 
166             device.CreateTexture(&descriptor);
167         }
168 
169         // mipLevelCount == 0 is an error
170         {
171             wgpu::TextureDescriptor descriptor = defaultDescriptor;
172             descriptor.size.width = 32;
173             descriptor.size.height = 32;
174             descriptor.mipLevelCount = 0;
175 
176             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
177         }
178 
179         // Full mip chains are allowed
180         {
181             wgpu::TextureDescriptor descriptor = defaultDescriptor;
182             descriptor.size.width = 32;
183             descriptor.size.height = 32;
184             // Mip level sizes: 32, 16, 8, 4, 2, 1
185             descriptor.mipLevelCount = 6;
186 
187             device.CreateTexture(&descriptor);
188         }
189 
190         // Test non-power-of-two width
191         {
192             wgpu::TextureDescriptor descriptor = defaultDescriptor;
193             // Mip level width: 31, 15, 7, 3, 1
194             descriptor.size.width = 31;
195             descriptor.size.height = 4;
196 
197             // Full mip chains on non-power-of-two width are allowed
198             descriptor.mipLevelCount = 5;
199             device.CreateTexture(&descriptor);
200 
201             // Too big mip chains on non-power-of-two width are disallowed
202             descriptor.mipLevelCount = 6;
203             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
204         }
205 
206         // Test non-power-of-two height
207         {
208             wgpu::TextureDescriptor descriptor = defaultDescriptor;
209             descriptor.size.width = 4;
210             // Mip level height: 31, 15, 7, 3, 1
211             descriptor.size.height = 31;
212 
213             // Full mip chains on non-power-of-two height are allowed
214             descriptor.mipLevelCount = 5;
215             device.CreateTexture(&descriptor);
216 
217             // Too big mip chains on non-power-of-two height are disallowed
218             descriptor.mipLevelCount = 6;
219             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
220         }
221 
222         // Undefined shift check if miplevel is bigger than the integer bit width.
223         {
224             wgpu::TextureDescriptor descriptor = defaultDescriptor;
225             descriptor.size.width = 32;
226             descriptor.size.height = 32;
227             descriptor.mipLevelCount = 100;
228 
229             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
230         }
231 
232         // Non square mip map halves the resolution until a 1x1 dimension
233         {
234             wgpu::TextureDescriptor descriptor = defaultDescriptor;
235             descriptor.size.width = 32;
236             descriptor.size.height = 8;
237             // Mip maps: 32 * 8, 16 * 4, 8 * 2, 4 * 1, 2 * 1, 1 * 1
238             descriptor.mipLevelCount = 6;
239 
240             device.CreateTexture(&descriptor);
241         }
242 
243         // Non square mip map for a 3D textures
244         {
245             wgpu::TextureDescriptor descriptor = defaultDescriptor;
246             descriptor.size.width = 32;
247             descriptor.size.height = 8;
248             descriptor.size.depthOrArrayLayers = 64;
249             descriptor.dimension = wgpu::TextureDimension::e3D;
250             // Non square mip map halves width, height and depth until a 1x1x1 dimension for a 3D
251             // texture. So there are 7 mipmaps at most: 32 * 8 * 64, 16 * 4 * 32, 8 * 2 * 16,
252             // 4 * 1 * 8, 2 * 1 * 4, 1 * 1 * 2, 1 * 1 * 1.
253             descriptor.mipLevelCount = 7;
254             device.CreateTexture(&descriptor);
255         }
256 
257         // Non square mip map for 2D textures with depth > 1
258         {
259             wgpu::TextureDescriptor descriptor = defaultDescriptor;
260             descriptor.size.width = 32;
261             descriptor.size.height = 8;
262             descriptor.size.depthOrArrayLayers = 64;
263             // Non square mip map halves width and height until a 1x1 dimension for a 2D texture,
264             // even its depth > 1. So there are 6 mipmaps at most: 32 * 8, 16 * 4, 8 * 2, 4 * 1, 2 *
265             // 1, 1 * 1.
266             descriptor.dimension = wgpu::TextureDimension::e2D;
267             descriptor.mipLevelCount = 7;
268             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
269             descriptor.mipLevelCount = 6;
270             device.CreateTexture(&descriptor);
271         }
272 
273         // Mip level equal to the maximum for a 2D texture is allowed
274         {
275             uint32_t maxTextureDimension2D = GetSupportedLimits().limits.maxTextureDimension2D;
276             wgpu::TextureDescriptor descriptor = defaultDescriptor;
277             descriptor.size.width = maxTextureDimension2D;
278             descriptor.size.height = maxTextureDimension2D;
279             descriptor.mipLevelCount = Log2(maxTextureDimension2D) + 1u;
280 
281             device.CreateTexture(&descriptor);
282         }
283 
284         // Mip level exceeding the maximum for a 2D texture not allowed
285         {
286             uint32_t maxTextureDimension2D = GetSupportedLimits().limits.maxTextureDimension2D;
287             wgpu::TextureDescriptor descriptor = defaultDescriptor;
288             descriptor.size.width = maxTextureDimension2D;
289             descriptor.size.height = maxTextureDimension2D;
290             descriptor.mipLevelCount = Log2(maxTextureDimension2D) + 2u;
291 
292             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
293         }
294     }
295 
296     // Test the validation of array layer count
TEST_F(TextureValidationTest,ArrayLayerCount)297     TEST_F(TextureValidationTest, ArrayLayerCount) {
298         wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
299         wgpu::Limits supportedLimits = GetSupportedLimits().limits;
300 
301         // Array layer count exceeding maxTextureArrayLayers is not allowed for 2D texture
302         {
303             wgpu::TextureDescriptor descriptor = defaultDescriptor;
304 
305             descriptor.size.depthOrArrayLayers = supportedLimits.maxTextureArrayLayers + 1u;
306             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
307         }
308 
309         // Array layer count less than maxTextureArrayLayers is allowed
310         {
311             wgpu::TextureDescriptor descriptor = defaultDescriptor;
312             descriptor.size.depthOrArrayLayers = supportedLimits.maxTextureArrayLayers >> 1;
313             device.CreateTexture(&descriptor);
314         }
315 
316         // Array layer count equal to maxTextureArrayLayers is allowed
317         {
318             wgpu::TextureDescriptor descriptor = defaultDescriptor;
319             descriptor.size.depthOrArrayLayers = supportedLimits.maxTextureArrayLayers;
320             device.CreateTexture(&descriptor);
321         }
322     }
323 
324     // Test the validation of 2D texture size
325     TEST_F(TextureValidationTest, 2DTextureSize) {
326         wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
327         wgpu::Limits supportedLimits = GetSupportedLimits().limits;
328 
329         // Out-of-bound texture dimension is not allowed
330         {
331             wgpu::TextureDescriptor descriptor = defaultDescriptor;
332             descriptor.size.width = supportedLimits.maxTextureDimension2D + 1u;
333             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
334 
335             descriptor.size.width = 1;
336             descriptor.size.height = supportedLimits.maxTextureDimension2D + 1u;
337             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
338         }
339 
340         // Zero-sized texture is not allowed
341         {
342             wgpu::TextureDescriptor descriptor = defaultDescriptor;
343             descriptor.size = {0, 1, 1};
344             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
345 
346             descriptor.size = {1, 0, 1};
347             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
348 
349             descriptor.size = {1, 1, 0};
350             // 2D texture with depth=0 is not allowed
351             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
352         }
353 
354         // Texture size less than max dimension is allowed
355         {
356             wgpu::TextureDescriptor descriptor = defaultDescriptor;
357             descriptor.size.width = supportedLimits.maxTextureDimension2D >> 1;
358             descriptor.size.height = supportedLimits.maxTextureDimension2D >> 1;
359             device.CreateTexture(&descriptor);
360         }
361 
362         // Texture size equal to max dimension is allowed
363         {
364             wgpu::TextureDescriptor descriptor = defaultDescriptor;
365             descriptor.size.width = supportedLimits.maxTextureDimension2D;
366             descriptor.size.height = supportedLimits.maxTextureDimension2D;
367             descriptor.dimension = wgpu::TextureDimension::e2D;
368             device.CreateTexture(&descriptor);
369         }
370     }
371 
372     // Test the validation of 3D texture size
373     TEST_F(TextureValidationTest, 3DTextureSize) {
374         wgpu::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor();
375         wgpu::Limits supportedLimits = GetSupportedLimits().limits;
376 
377         // Out-of-bound texture dimension is not allowed
378         {
379             wgpu::TextureDescriptor descriptor = defaultDescriptor;
380             descriptor.dimension = wgpu::TextureDimension::e3D;
381 
382             descriptor.size = {supportedLimits.maxTextureDimension3D + 1u, 1, 1};
383             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
384 
385             descriptor.size = {1, supportedLimits.maxTextureDimension3D + 1u, 1};
386             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
387 
388             descriptor.size = {1, 1, supportedLimits.maxTextureDimension3D + 1u};
389             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
390         }
391 
392         // Zero-sized texture is not allowed
393         {
394             wgpu::TextureDescriptor descriptor = defaultDescriptor;
395             descriptor.dimension = wgpu::TextureDimension::e3D;
396 
397             descriptor.size = {0, 1, 1};
398             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
399 
400             descriptor.size = {1, 0, 1};
401             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
402 
403             descriptor.size = {1, 1, 0};
404             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
405         }
406 
407         // Texture size less than max dimension is allowed
408         {
409             wgpu::TextureDescriptor descriptor = defaultDescriptor;
410             descriptor.dimension = wgpu::TextureDimension::e3D;
411 
412             descriptor.size = {supportedLimits.maxTextureDimension3D >> 1,
413                                supportedLimits.maxTextureDimension3D >> 1,
414                                supportedLimits.maxTextureDimension3D >> 1};
415             device.CreateTexture(&descriptor);
416         }
417 
418         // Texture size equal to max dimension is allowed
419         {
420             wgpu::TextureDescriptor descriptor = defaultDescriptor;
421             descriptor.dimension = wgpu::TextureDimension::e3D;
422 
423             descriptor.size = {supportedLimits.maxTextureDimension3D,
424                                supportedLimits.maxTextureDimension3D,
425                                supportedLimits.maxTextureDimension3D};
426             device.CreateTexture(&descriptor);
427         }
428     }
429 
430     // Test that depth/stencil formats are invalid for 3D texture
TEST_F(TextureValidationTest,DepthStencilFormatsFor3D)431     TEST_F(TextureValidationTest, DepthStencilFormatsFor3D) {
432         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
433 
434         wgpu::TextureFormat depthStencilFormats[] = {
435             wgpu::TextureFormat::Stencil8,     wgpu::TextureFormat::Depth16Unorm,
436             wgpu::TextureFormat::Depth24Plus,  wgpu::TextureFormat::Depth24PlusStencil8,
437             wgpu::TextureFormat::Depth32Float,
438         };
439 
440         for (wgpu::TextureDimension dimension : kDimensions) {
441             for (wgpu::TextureFormat format : depthStencilFormats) {
442                 descriptor.format = format;
443                 descriptor.dimension = dimension;
444                 ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
445             }
446         }
447     }
448 
449     // Test that it is valid to destroy a texture
TEST_F(TextureValidationTest,DestroyTexture)450     TEST_F(TextureValidationTest, DestroyTexture) {
451         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
452         wgpu::Texture texture = device.CreateTexture(&descriptor);
453         texture.Destroy();
454     }
455 
456     // Test that it's valid to destroy a destroyed texture
TEST_F(TextureValidationTest,DestroyDestroyedTexture)457     TEST_F(TextureValidationTest, DestroyDestroyedTexture) {
458         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
459         wgpu::Texture texture = device.CreateTexture(&descriptor);
460         texture.Destroy();
461         texture.Destroy();
462     }
463 
464     // Test that it's invalid to submit a destroyed texture in a queue
465     // in the case of destroy, encode, submit
TEST_F(TextureValidationTest,DestroyEncodeSubmit)466     TEST_F(TextureValidationTest, DestroyEncodeSubmit) {
467         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
468         wgpu::Texture texture = device.CreateTexture(&descriptor);
469         wgpu::TextureView textureView = texture.CreateView();
470 
471         utils::ComboRenderPassDescriptor renderPass({textureView});
472 
473         // Destroy the texture
474         texture.Destroy();
475 
476         wgpu::CommandEncoder encoder_post_destroy = device.CreateCommandEncoder();
477         {
478             wgpu::RenderPassEncoder pass = encoder_post_destroy.BeginRenderPass(&renderPass);
479             pass.EndPass();
480         }
481         wgpu::CommandBuffer commands = encoder_post_destroy.Finish();
482 
483         // Submit should fail due to destroyed texture
484         ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
485     }
486 
487     // Test that it's invalid to submit a destroyed texture in a queue
488     // in the case of encode, destroy, submit
TEST_F(TextureValidationTest,EncodeDestroySubmit)489     TEST_F(TextureValidationTest, EncodeDestroySubmit) {
490         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
491         wgpu::Texture texture = device.CreateTexture(&descriptor);
492         wgpu::TextureView textureView = texture.CreateView();
493 
494         utils::ComboRenderPassDescriptor renderPass({textureView});
495 
496         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
497         {
498             wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
499             pass.EndPass();
500         }
501         wgpu::CommandBuffer commands = encoder.Finish();
502 
503         // Destroy the texture
504         texture.Destroy();
505 
506         // Submit should fail due to destroyed texture
507         ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
508     }
509 
510     // Test it is an error to create an RenderAttachment texture with a non-renderable format.
TEST_F(TextureValidationTest,NonRenderableAndRenderAttachment)511     TEST_F(TextureValidationTest, NonRenderableAndRenderAttachment) {
512         wgpu::TextureDescriptor descriptor;
513         descriptor.size = {1, 1, 1};
514         descriptor.usage = wgpu::TextureUsage::RenderAttachment;
515 
516         // Succeeds because RGBA8Unorm is renderable
517         descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
518         device.CreateTexture(&descriptor);
519 
520         for (wgpu::TextureFormat format : kNonRenderableColorFormats) {
521             // Fails because `format` is non-renderable
522             descriptor.format = format;
523             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
524         }
525     }
526 
527     // Test it is an error to create a Storage texture with any format that doesn't support
528     // TextureUsage::StorageBinding texture usages.
TEST_F(TextureValidationTest,TextureFormatNotSupportTextureUsageStorage)529     TEST_F(TextureValidationTest, TextureFormatNotSupportTextureUsageStorage) {
530         wgpu::TextureDescriptor descriptor;
531         descriptor.size = {1, 1, 1};
532         descriptor.usage = wgpu::TextureUsage::StorageBinding;
533 
534         for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
535             descriptor.format = format;
536             if (utils::TextureFormatSupportsStorageTexture(format)) {
537                 device.CreateTexture(&descriptor);
538             } else {
539                 ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
540             }
541         }
542     }
543 
544     // Test it is an error to create a texture with format "Undefined".
TEST_F(TextureValidationTest,TextureFormatUndefined)545     TEST_F(TextureValidationTest, TextureFormatUndefined) {
546         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
547         descriptor.format = wgpu::TextureFormat::Undefined;
548         ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
549     }
550 
551     // Test that the creation of a texture with depth24unorm-stencil8 will fail when the feature
552     // Depth24UnormStencil8 is not enabled.
TEST_F(TextureValidationTest,UseD24S8FormatWithoutEnablingFeature)553     TEST_F(TextureValidationTest, UseD24S8FormatWithoutEnablingFeature) {
554         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
555         descriptor.format = wgpu::TextureFormat::Depth24UnormStencil8;
556         ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
557     }
558 
559     // Test that the creation of a texture with depth32float-stencil8 will fail when the feature
560     // Depth32FloatStencil8 is not enabled.
TEST_F(TextureValidationTest,UseD32S8FormatWithoutEnablingFeature)561     TEST_F(TextureValidationTest, UseD32S8FormatWithoutEnablingFeature) {
562         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
563         descriptor.format = wgpu::TextureFormat::Depth32FloatStencil8;
564         ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
565     }
566 
567     // Test that the creation of a texture with BC format will fail when the feature
568     // textureCompressionBC is not enabled.
TEST_F(TextureValidationTest,UseBCFormatWithoutEnablingFeature)569     TEST_F(TextureValidationTest, UseBCFormatWithoutEnablingFeature) {
570         for (wgpu::TextureFormat format : utils::kBCFormats) {
571             wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
572             descriptor.format = format;
573             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
574         }
575     }
576 
577     // Test that the creation of a texture with ETC2 format will fail when the feature
578     // textureCompressionETC2 is not enabled.
TEST_F(TextureValidationTest,UseETC2FormatWithoutEnablingFeature)579     TEST_F(TextureValidationTest, UseETC2FormatWithoutEnablingFeature) {
580         for (wgpu::TextureFormat format : utils::kETC2Formats) {
581             wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
582             descriptor.format = format;
583             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
584         }
585     }
586 
587     // Test that the creation of a texture with ASTC format will fail when the feature
588     // textureCompressionASTC is not enabled.
TEST_F(TextureValidationTest,UseASTCFormatWithoutEnablingFeature)589     TEST_F(TextureValidationTest, UseASTCFormatWithoutEnablingFeature) {
590         for (wgpu::TextureFormat format : utils::kASTCFormats) {
591             wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
592             descriptor.format = format;
593             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
594         }
595     }
596 
597     class D24S8TextureFormatsValidationTests : public TextureValidationTest {
598       protected:
CreateTestDevice()599         WGPUDevice CreateTestDevice() override {
600             dawn_native::DeviceDescriptor descriptor;
601             descriptor.requiredFeatures = {"depth24unorm-stencil8"};
602             return adapter.CreateDevice(&descriptor);
603         }
604     };
605 
606     // Test that depth24unorm-stencil8 format is invalid for 3D texture
TEST_F(D24S8TextureFormatsValidationTests,DepthStencilFormatsFor3D)607     TEST_F(D24S8TextureFormatsValidationTests, DepthStencilFormatsFor3D) {
608         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
609 
610         for (wgpu::TextureDimension dimension : kDimensions) {
611             descriptor.format = wgpu::TextureFormat::Depth24UnormStencil8;
612             descriptor.dimension = dimension;
613             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
614         }
615     }
616 
617     class D32S8TextureFormatsValidationTests : public TextureValidationTest {
618       protected:
CreateTestDevice()619         WGPUDevice CreateTestDevice() override {
620             dawn_native::DeviceDescriptor descriptor;
621             descriptor.requiredFeatures = {"depth32float-stencil8"};
622             return adapter.CreateDevice(&descriptor);
623         }
624     };
625 
626     // Test that depth32float-stencil8 format is invalid for 3D texture
TEST_F(D32S8TextureFormatsValidationTests,DepthStencilFormatsFor3D)627     TEST_F(D32S8TextureFormatsValidationTests, DepthStencilFormatsFor3D) {
628         wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
629 
630         for (wgpu::TextureDimension dimension : kDimensions) {
631             descriptor.format = wgpu::TextureFormat::Depth32FloatStencil8;
632             descriptor.dimension = dimension;
633             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
634         }
635     }
636 
637     // TODO(jiawei.shao@intel.com): add tests to verify we cannot create 1D or 3D textures with
638     // compressed texture formats.
639     class CompressedTextureFormatsValidationTests : public TextureValidationTest {
640       protected:
CreateTestDevice()641         WGPUDevice CreateTestDevice() override {
642             dawn_native::DawnDeviceDescriptor descriptor;
643             descriptor.requiredFeatures = {"texture-compression-bc", "texture-compression-etc2",
644                                            "texture-compression-astc"};
645             return adapter.CreateDevice(&descriptor);
646         }
647 
CreateDefaultTextureDescriptor()648         wgpu::TextureDescriptor CreateDefaultTextureDescriptor() {
649             wgpu::TextureDescriptor descriptor =
650                 TextureValidationTest::CreateDefaultTextureDescriptor();
651             descriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
652                                wgpu::TextureUsage::TextureBinding;
653             descriptor.size.width = kWidth;
654             descriptor.size.height = kHeight;
655             return descriptor;
656         }
657 
658       private:
659         // Choose the LCM of all current compressed texture format texel dimensions as the
660         // dimensions of the default texture.
661         static constexpr uint32_t kWidth = 120;
662         static constexpr uint32_t kHeight = 120;
663     };
664 
665     // Test that only CopySrc, CopyDst and Sampled are accepted as usage in compressed formats.
TEST_F(CompressedTextureFormatsValidationTests,TextureUsage)666     TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) {
667         wgpu::TextureUsage invalidUsages[] = {
668             wgpu::TextureUsage::RenderAttachment,
669             wgpu::TextureUsage::StorageBinding,
670             wgpu::TextureUsage::Present,
671         };
672         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
673             for (wgpu::TextureUsage usage : invalidUsages) {
674                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
675                 descriptor.format = format;
676                 descriptor.usage = usage;
677                 ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
678             }
679         }
680     }
681 
682     // Test that using various MipLevelCount is allowed for compressed formats.
TEST_F(CompressedTextureFormatsValidationTests,MipLevelCount)683     TEST_F(CompressedTextureFormatsValidationTests, MipLevelCount) {
684         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
685             for (uint32_t mipLevels : {1, 3, 6}) {
686                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
687                 descriptor.format = format;
688                 descriptor.mipLevelCount = mipLevels;
689                 device.CreateTexture(&descriptor);
690             }
691         }
692     }
693 
694     // Test that it is invalid to specify SampleCount>1 in compressed formats.
TEST_F(CompressedTextureFormatsValidationTests,SampleCount)695     TEST_F(CompressedTextureFormatsValidationTests, SampleCount) {
696         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
697             wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
698             descriptor.format = format;
699             descriptor.sampleCount = 4;
700             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
701         }
702     }
703 
704     // Test that it is allowed to create a 2D texture with depth>1 in compressed formats.
705     TEST_F(CompressedTextureFormatsValidationTests, 2DArrayTexture) {
706         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
707             wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
708             descriptor.format = format;
709             descriptor.size.depthOrArrayLayers = 6;
710             device.CreateTexture(&descriptor);
711         }
712     }
713 
714     // Test that it is not allowed to create a 3D texture in compressed formats.
715     TEST_F(CompressedTextureFormatsValidationTests, 3DTexture) {
716         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
717             wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
718             descriptor.format = format;
719             descriptor.size.depthOrArrayLayers = 4;
720             descriptor.dimension = wgpu::TextureDimension::e3D;
721             ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
722         }
723     }
724 
725     // Test that it is invalid to use numbers for a texture's width/height that are not multiples
726     // of the compressed block sizes.
TEST_F(CompressedTextureFormatsValidationTests,TextureSize)727     TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
728         for (wgpu::TextureFormat format : utils::kCompressedFormats) {
729             uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
730             uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
731 
732             // Test that the default size (120 x 120) is valid for all formats.
733             {
734                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
735                 descriptor.format = format;
736                 ASSERT_TRUE(descriptor.size.width % blockWidth == 0 &&
737                             descriptor.size.height % blockHeight == 0);
738                 device.CreateTexture(&descriptor);
739             }
740 
741             // Test that invalid width should cause an error. Note that if the block width of the
742             // compression type is even, we test that alignment to half the width is not sufficient.
743             {
744                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
745                 descriptor.format = format;
746                 descriptor.size.width =
747                     blockWidth % 2 == 0 ? blockWidth - (blockWidth / 2) : blockWidth - 1;
748                 ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
749             }
750 
751             // Test that invalid width should cause an error. Note that if the block height of the
752             // compression type is even, we test that alignment to half the height is not
753             // sufficient.
754             {
755                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
756                 descriptor.format = format;
757                 descriptor.size.height =
758                     blockHeight % 2 == 0 ? blockHeight - (blockHeight / 2) : blockHeight - 1;
759                 ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
760             }
761 
762             // Test a working dimension based on some constant multipliers to the dimensions.
763             {
764                 constexpr uint32_t kWidthMultiplier = 3;
765                 constexpr uint32_t kHeightMultiplier = 8;
766                 wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
767                 descriptor.format = format;
768                 descriptor.size.width = kWidthMultiplier * blockWidth;
769                 descriptor.size.height = kHeightMultiplier * blockHeight;
770                 device.CreateTexture(&descriptor);
771             }
772         }
773     }
774 
775 }  // namespace
776