• 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 "tests/unittests/validation/ValidationTest.h"
16 
17 #include "utils/WGPUHelpers.h"
18 
19 namespace {
20 
21     class VideoViewsValidation : public ValidationTest {
22       protected:
CreateTestDevice()23         WGPUDevice CreateTestDevice() override {
24             dawn_native::DawnDeviceDescriptor descriptor;
25             descriptor.requiredFeatures = {"multiplanar-formats"};
26             return adapter.CreateDevice(&descriptor);
27         }
28 
CreateVideoTextureForTest(wgpu::TextureFormat format,wgpu::TextureUsage usage)29         wgpu::Texture CreateVideoTextureForTest(wgpu::TextureFormat format,
30                                                 wgpu::TextureUsage usage) {
31             wgpu::TextureDescriptor descriptor;
32             descriptor.dimension = wgpu::TextureDimension::e2D;
33             descriptor.size.width = 1;
34             descriptor.size.height = 1;
35             descriptor.format = format;
36             descriptor.usage = usage;
37             return device.CreateTexture(&descriptor);
38         }
39     };
40 
41     // Test texture views compatibility rules.
TEST_F(VideoViewsValidation,CreateViewFails)42     TEST_F(VideoViewsValidation, CreateViewFails) {
43         wgpu::Texture videoTexture = CreateVideoTextureForTest(
44             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::None);
45 
46         wgpu::TextureViewDescriptor viewDesc = {};
47 
48         // Correct plane index but incompatible view format.
49         viewDesc.format = wgpu::TextureFormat::R8Uint;
50         viewDesc.aspect = wgpu::TextureAspect::Plane0Only;
51         ASSERT_DEVICE_ERROR(videoTexture.CreateView(&viewDesc));
52 
53         // Compatible view format but wrong plane index.
54         viewDesc.format = wgpu::TextureFormat::R8Unorm;
55         viewDesc.aspect = wgpu::TextureAspect::Plane1Only;
56         ASSERT_DEVICE_ERROR(videoTexture.CreateView(&viewDesc));
57 
58         // Compatible view format but wrong aspect.
59         viewDesc.format = wgpu::TextureFormat::R8Unorm;
60         viewDesc.aspect = wgpu::TextureAspect::All;
61         ASSERT_DEVICE_ERROR(videoTexture.CreateView(&viewDesc));
62 
63         // Create a single plane texture.
64         wgpu::TextureDescriptor desc;
65         desc.format = wgpu::TextureFormat::RGBA8Unorm;
66         desc.dimension = wgpu::TextureDimension::e2D;
67         desc.usage = wgpu::TextureUsage::None;
68         desc.size = {1, 1, 1};
69 
70         wgpu::Texture texture = device.CreateTexture(&desc);
71 
72         // Plane aspect specified with non-planar texture.
73         viewDesc.aspect = wgpu::TextureAspect::Plane0Only;
74         ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
75 
76         viewDesc.aspect = wgpu::TextureAspect::Plane1Only;
77         ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
78 
79         // Planar views with non-planar texture.
80         viewDesc.aspect = wgpu::TextureAspect::Plane0Only;
81         viewDesc.format = wgpu::TextureFormat::R8Unorm;
82         ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
83 
84         viewDesc.aspect = wgpu::TextureAspect::Plane1Only;
85         viewDesc.format = wgpu::TextureFormat::RG8Unorm;
86         ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc));
87     }
88 
89     // Test texture views compatibility rules.
TEST_F(VideoViewsValidation,CreateViewSucceeds)90     TEST_F(VideoViewsValidation, CreateViewSucceeds) {
91         wgpu::Texture yuvTexture = CreateVideoTextureForTest(
92             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::None);
93 
94         // Per plane view formats unspecified.
95         wgpu::TextureViewDescriptor planeViewDesc = {};
96         planeViewDesc.aspect = wgpu::TextureAspect::Plane0Only;
97         wgpu::TextureView plane0View = yuvTexture.CreateView(&planeViewDesc);
98 
99         planeViewDesc.aspect = wgpu::TextureAspect::Plane1Only;
100         wgpu::TextureView plane1View = yuvTexture.CreateView(&planeViewDesc);
101 
102         ASSERT_NE(plane0View.Get(), nullptr);
103         ASSERT_NE(plane1View.Get(), nullptr);
104 
105         // Per plane view formats specified.
106         planeViewDesc.aspect = wgpu::TextureAspect::Plane0Only;
107         planeViewDesc.format = wgpu::TextureFormat::R8Unorm;
108         plane0View = yuvTexture.CreateView(&planeViewDesc);
109 
110         planeViewDesc.aspect = wgpu::TextureAspect::Plane1Only;
111         planeViewDesc.format = wgpu::TextureFormat::RG8Unorm;
112         plane1View = yuvTexture.CreateView(&planeViewDesc);
113 
114         ASSERT_NE(plane0View.Get(), nullptr);
115         ASSERT_NE(plane1View.Get(), nullptr);
116     }
117 
118     // Test copying from one multi-planar format into another fails.
TEST_F(VideoViewsValidation,T2TCopyAllAspectsFails)119     TEST_F(VideoViewsValidation, T2TCopyAllAspectsFails) {
120         wgpu::Texture srcTexture = CreateVideoTextureForTest(
121             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
122 
123         wgpu::Texture dstTexture = CreateVideoTextureForTest(
124             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
125 
126         wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0});
127 
128         wgpu::ImageCopyTexture copyDst = utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0});
129 
130         wgpu::Extent3D copySize = {1, 1, 1};
131 
132         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
133         encoder.CopyTextureToTexture(&copySrc, &copyDst, &copySize);
134         ASSERT_DEVICE_ERROR(encoder.Finish());
135     }
136 
137     // Test copying from one multi-planar format into another per plane fails.
TEST_F(VideoViewsValidation,T2TCopyPlaneAspectFails)138     TEST_F(VideoViewsValidation, T2TCopyPlaneAspectFails) {
139         wgpu::Texture srcTexture = CreateVideoTextureForTest(
140             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
141 
142         wgpu::Texture dstTexture = CreateVideoTextureForTest(
143             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
144 
145         wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(
146             srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only);
147 
148         wgpu::ImageCopyTexture copyDst = utils::CreateImageCopyTexture(
149             dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane1Only);
150 
151         wgpu::Extent3D copySize = {1, 1, 1};
152 
153         {
154             wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
155             encoder.CopyTextureToTexture(&copySrc, &copyDst, &copySize);
156             ASSERT_DEVICE_ERROR(encoder.Finish());
157         }
158 
159         copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0},
160                                                 wgpu::TextureAspect::Plane1Only);
161 
162         {
163             wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
164             encoder.CopyTextureToTexture(&copySrc, &copyDst, &copySize);
165             ASSERT_DEVICE_ERROR(encoder.Finish());
166         }
167     }
168 
169     // Test copying from a multi-planar format to a buffer fails.
TEST_F(VideoViewsValidation,T2BCopyAllAspectsFails)170     TEST_F(VideoViewsValidation, T2BCopyAllAspectsFails) {
171         wgpu::Texture srcTexture = CreateVideoTextureForTest(
172             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
173 
174         wgpu::BufferDescriptor bufferDescriptor;
175         bufferDescriptor.size = 1;
176         bufferDescriptor.usage = wgpu::BufferUsage::CopyDst;
177         wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor);
178 
179         wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0});
180 
181         wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 4);
182 
183         wgpu::Extent3D copySize = {1, 1, 1};
184 
185         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
186         encoder.CopyTextureToBuffer(&copySrc, &copyDst, &copySize);
187         ASSERT_DEVICE_ERROR(encoder.Finish());
188     }
189 
190     // Test copying from multi-planar format per plane to a buffer fails.
TEST_F(VideoViewsValidation,T2BCopyPlaneAspectsFails)191     TEST_F(VideoViewsValidation, T2BCopyPlaneAspectsFails) {
192         wgpu::Texture srcTexture = CreateVideoTextureForTest(
193             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
194 
195         wgpu::BufferDescriptor bufferDescriptor;
196         bufferDescriptor.size = 1;
197         bufferDescriptor.usage = wgpu::BufferUsage::CopyDst;
198         wgpu::Buffer dstBuffer = device.CreateBuffer(&bufferDescriptor);
199 
200         wgpu::ImageCopyTexture copySrc = utils::CreateImageCopyTexture(
201             srcTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only);
202 
203         wgpu::ImageCopyBuffer copyDst = utils::CreateImageCopyBuffer(dstBuffer, 0, 4);
204 
205         wgpu::Extent3D copySize = {1, 1, 1};
206 
207         {
208             wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
209             encoder.CopyTextureToBuffer(&copySrc, &copyDst, &copySize);
210             ASSERT_DEVICE_ERROR(encoder.Finish());
211         }
212 
213         copySrc = utils::CreateImageCopyTexture(srcTexture, 0, {0, 0, 0},
214                                                 wgpu::TextureAspect::Plane1Only);
215 
216         {
217             wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
218             encoder.CopyTextureToBuffer(&copySrc, &copyDst, &copySize);
219             ASSERT_DEVICE_ERROR(encoder.Finish());
220         }
221     }
222 
223     // Test copying from a buffer to a multi-planar format fails.
TEST_F(VideoViewsValidation,B2TCopyAllAspectsFails)224     TEST_F(VideoViewsValidation, B2TCopyAllAspectsFails) {
225         std::vector<uint8_t> dummyData(4, 0);
226 
227         wgpu::Buffer srcBuffer = utils::CreateBufferFromData(
228             device, dummyData.data(), dummyData.size(), wgpu::BufferUsage::CopySrc);
229 
230         wgpu::Texture dstTexture = CreateVideoTextureForTest(
231             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
232 
233         wgpu::ImageCopyBuffer copySrc = utils::CreateImageCopyBuffer(srcBuffer, 0, 12, 4);
234 
235         wgpu::ImageCopyTexture copyDst = utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0});
236 
237         wgpu::Extent3D copySize = {1, 1, 1};
238 
239         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
240         encoder.CopyBufferToTexture(&copySrc, &copyDst, &copySize);
241         ASSERT_DEVICE_ERROR(encoder.Finish());
242     }
243 
244     // Test copying from a buffer to a multi-planar format per plane fails.
TEST_F(VideoViewsValidation,B2TCopyPlaneAspectsFails)245     TEST_F(VideoViewsValidation, B2TCopyPlaneAspectsFails) {
246         std::vector<uint8_t> dummyData(4, 0);
247 
248         wgpu::Buffer srcBuffer = utils::CreateBufferFromData(
249             device, dummyData.data(), dummyData.size(), wgpu::BufferUsage::CopySrc);
250 
251         wgpu::Texture dstTexture = CreateVideoTextureForTest(
252             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
253 
254         wgpu::ImageCopyBuffer copySrc = utils::CreateImageCopyBuffer(srcBuffer, 0, 12, 4);
255 
256         wgpu::ImageCopyTexture copyDst = utils::CreateImageCopyTexture(
257             dstTexture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only);
258 
259         wgpu::Extent3D copySize = {1, 1, 1};
260 
261         {
262             wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
263             encoder.CopyBufferToTexture(&copySrc, &copyDst, &copySize);
264             ASSERT_DEVICE_ERROR(encoder.Finish());
265         }
266 
267         copyDst = utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0},
268                                                 wgpu::TextureAspect::Plane1Only);
269 
270         {
271             wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
272             encoder.CopyBufferToTexture(&copySrc, &copyDst, &copySize);
273             ASSERT_DEVICE_ERROR(encoder.Finish());
274         }
275     }
276 
277     // Tests which multi-planar formats are allowed to be sampled.
TEST_F(VideoViewsValidation,SamplingMultiPlanarTexture)278     TEST_F(VideoViewsValidation, SamplingMultiPlanarTexture) {
279         wgpu::BindGroupLayout layout = utils::MakeBindGroupLayout(
280             device, {{0, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Float}});
281 
282         // R8BG8Biplanar420Unorm is allowed to be sampled, if plane 0 or plane 1 is selected.
283         wgpu::Texture texture = CreateVideoTextureForTest(
284             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
285 
286         wgpu::TextureViewDescriptor desc = {};
287 
288         desc.aspect = wgpu::TextureAspect::Plane0Only;
289         utils::MakeBindGroup(device, layout, {{0, texture.CreateView(&desc)}});
290 
291         desc.aspect = wgpu::TextureAspect::Plane1Only;
292         utils::MakeBindGroup(device, layout, {{0, texture.CreateView(&desc)}});
293     }
294 
295     // Tests creating a texture with a multi-plane format.
TEST_F(VideoViewsValidation,CreateTextureFails)296     TEST_F(VideoViewsValidation, CreateTextureFails) {
297         // multi-planar formats are NOT allowed to be renderable.
298         ASSERT_DEVICE_ERROR(CreateVideoTextureForTest(wgpu::TextureFormat::R8BG8Biplanar420Unorm,
299                                                       wgpu::TextureUsage::RenderAttachment));
300     }
301 
302     // Tests writing into a multi-planar format fails.
TEST_F(VideoViewsValidation,WriteTextureAllAspectsFails)303     TEST_F(VideoViewsValidation, WriteTextureAllAspectsFails) {
304         wgpu::Texture texture = CreateVideoTextureForTest(
305             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
306 
307         wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout(0, 4, 4);
308 
309         wgpu::ImageCopyTexture imageCopyTexture =
310             utils::CreateImageCopyTexture(texture, 0, {0, 0, 0});
311 
312         std::vector<uint8_t> dummyData(4, 0);
313         wgpu::Extent3D writeSize = {1, 1, 1};
314 
315         wgpu::Queue queue = device.GetQueue();
316 
317         ASSERT_DEVICE_ERROR(queue.WriteTexture(&imageCopyTexture, dummyData.data(),
318                                                dummyData.size(), &textureDataLayout, &writeSize));
319     }
320 
321     // Tests writing into a multi-planar format per plane fails.
TEST_F(VideoViewsValidation,WriteTexturePlaneAspectsFails)322     TEST_F(VideoViewsValidation, WriteTexturePlaneAspectsFails) {
323         wgpu::Texture texture = CreateVideoTextureForTest(
324             wgpu::TextureFormat::R8BG8Biplanar420Unorm, wgpu::TextureUsage::TextureBinding);
325 
326         wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout(0, 12, 4);
327         wgpu::ImageCopyTexture imageCopyTexture =
328             utils::CreateImageCopyTexture(texture, 0, {0, 0, 0}, wgpu::TextureAspect::Plane0Only);
329 
330         std::vector<uint8_t> dummmyData(4, 0);
331         wgpu::Extent3D writeSize = {1, 1, 1};
332 
333         wgpu::Queue queue = device.GetQueue();
334 
335         ASSERT_DEVICE_ERROR(queue.WriteTexture(&imageCopyTexture, dummmyData.data(),
336                                                dummmyData.size(), &textureDataLayout, &writeSize));
337     }
338 
339 }  // anonymous namespace
340