• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 "utils/WGPUHelpers.h"
16 
17 #include "tests/unittests/validation/ValidationTest.h"
18 
19 namespace {
20 
21     class TextureSubresourceTest : public ValidationTest {
22       public:
23         static constexpr uint32_t kSize = 32u;
24         static constexpr wgpu::TextureFormat kFormat = wgpu::TextureFormat::RGBA8Unorm;
25 
CreateTexture(uint32_t mipLevelCount,uint32_t arrayLayerCount,wgpu::TextureUsage usage)26         wgpu::Texture CreateTexture(uint32_t mipLevelCount,
27                                     uint32_t arrayLayerCount,
28                                     wgpu::TextureUsage usage) {
29             wgpu::TextureDescriptor texDesc;
30             texDesc.dimension = wgpu::TextureDimension::e2D;
31             texDesc.size = {kSize, kSize, arrayLayerCount};
32             texDesc.sampleCount = 1;
33             texDesc.mipLevelCount = mipLevelCount;
34             texDesc.usage = usage;
35             texDesc.format = kFormat;
36             return device.CreateTexture(&texDesc);
37         }
38 
CreateTextureView(wgpu::Texture texture,uint32_t baseMipLevel,uint32_t baseArrayLayer)39         wgpu::TextureView CreateTextureView(wgpu::Texture texture,
40                                             uint32_t baseMipLevel,
41                                             uint32_t baseArrayLayer) {
42             wgpu::TextureViewDescriptor viewDesc;
43             viewDesc.format = kFormat;
44             viewDesc.baseArrayLayer = baseArrayLayer;
45             viewDesc.arrayLayerCount = 1;
46             viewDesc.baseMipLevel = baseMipLevel;
47             viewDesc.mipLevelCount = 1;
48             viewDesc.dimension = wgpu::TextureViewDimension::e2D;
49             return texture.CreateView(&viewDesc);
50         }
51 
TestRenderPass(const wgpu::TextureView & renderView,const wgpu::TextureView & samplerView)52         void TestRenderPass(const wgpu::TextureView& renderView,
53                             const wgpu::TextureView& samplerView) {
54             // Create bind group
55             wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
56                 device, {{0, wgpu::ShaderStage::Vertex, wgpu::TextureSampleType::Float}});
57 
58             utils::ComboRenderPassDescriptor renderPassDesc({renderView});
59 
60             // It is valid to read from and write into different subresources of the same texture
61             {
62                 wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, samplerView}});
63                 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
64                 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDesc);
65                 pass.SetBindGroup(0, bindGroup);
66                 pass.EndPass();
67                 encoder.Finish();
68             }
69 
70             // It is not currently possible to test that it is valid to have multiple reads from a
71             // subresource while there is a single write in another subresource.
72 
73             // It is invalid to read and write into the same subresources
74             {
75                 wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, renderView}});
76                 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
77                 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDesc);
78                 pass.SetBindGroup(0, bindGroup);
79                 pass.EndPass();
80                 ASSERT_DEVICE_ERROR(encoder.Finish());
81             }
82 
83             // It is valid to write into and then read from the same level of a texture in different
84             // render passes
85             {
86                 wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, bgl, {{0, samplerView}});
87 
88                 wgpu::BindGroupLayout bgl1 = utils::MakeBindGroupLayout(
89                     device, {{0, wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::WriteOnly,
90                               kFormat}});
91                 wgpu::BindGroup bindGroup1 = utils::MakeBindGroup(device, bgl1, {{0, samplerView}});
92 
93                 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
94                 wgpu::RenderPassEncoder pass1 = encoder.BeginRenderPass(&renderPassDesc);
95                 pass1.SetBindGroup(0, bindGroup1);
96                 pass1.EndPass();
97 
98                 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDesc);
99                 pass.SetBindGroup(0, bindGroup);
100                 pass.EndPass();
101 
102                 encoder.Finish();
103             }
104         }
105     };
106 
107     // Test different mipmap levels
TEST_F(TextureSubresourceTest,MipmapLevelsTest)108     TEST_F(TextureSubresourceTest, MipmapLevelsTest) {
109         // Create texture with 2 mipmap levels and 1 layer
110         wgpu::Texture texture = CreateTexture(2, 1,
111                                               wgpu::TextureUsage::TextureBinding |
112                                                   wgpu::TextureUsage::RenderAttachment |
113                                                   wgpu::TextureUsage::StorageBinding);
114 
115         // Create two views on different mipmap levels.
116         wgpu::TextureView samplerView = CreateTextureView(texture, 0, 0);
117         wgpu::TextureView renderView = CreateTextureView(texture, 1, 0);
118         TestRenderPass(samplerView, renderView);
119     }
120 
121     // Test different array layers
TEST_F(TextureSubresourceTest,ArrayLayersTest)122     TEST_F(TextureSubresourceTest, ArrayLayersTest) {
123         // Create texture with 1 mipmap level and 2 layers
124         wgpu::Texture texture = CreateTexture(1, 2,
125                                               wgpu::TextureUsage::TextureBinding |
126                                                   wgpu::TextureUsage::RenderAttachment |
127                                                   wgpu::TextureUsage::StorageBinding);
128 
129         // Create two views on different layers.
130         wgpu::TextureView samplerView = CreateTextureView(texture, 0, 0);
131         wgpu::TextureView renderView = CreateTextureView(texture, 0, 1);
132 
133         TestRenderPass(samplerView, renderView);
134     }
135 
136     // TODO (yunchao.he@intel.com):
137     //	* Add tests for compute, in which texture subresource is traced per dispatch.
138     //
139     //	* Add tests for multiple encoders upon the same resource simultaneously. This situation fits
140     //	some cases like VR, multi-threading, etc.
141     //
142     //	* Add tests for conflicts between usages in two render bundles used in the same pass.
143 
144 }  // anonymous namespace
145