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