• 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 <cmath>
16 
17 #include "tests/DawnTest.h"
18 
19 #include "common/Assert.h"
20 #include "common/Constants.h"
21 #include "utils/ComboRenderPipelineDescriptor.h"
22 #include "utils/WGPUHelpers.h"
23 
24 constexpr static unsigned int kRTSize = 64;
25 
26 namespace {
27     struct AddressModeTestCase {
28         wgpu::AddressMode mMode;
29         uint8_t mExpected2;
30         uint8_t mExpected3;
31     };
32     AddressModeTestCase addressModes[] = {
33         {
34             wgpu::AddressMode::Repeat,
35             0,
36             255,
37         },
38         {
39             wgpu::AddressMode::MirrorRepeat,
40             255,
41             0,
42         },
43         {
44             wgpu::AddressMode::ClampToEdge,
45             255,
46             255,
47         },
48     };
49 }  // namespace
50 
51 class SamplerTest : public DawnTest {
52   protected:
SetUp()53     void SetUp() override {
54         DawnTest::SetUp();
55         mRenderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
56 
57         auto vsModule = utils::CreateShaderModule(device, R"(
58             [[stage(vertex)]]
59             fn main([[builtin(vertex_index)]] VertexIndex : u32) -> [[builtin(position)]] vec4<f32> {
60                 var pos = array<vec2<f32>, 6>(
61                     vec2<f32>(-2.0, -2.0),
62                     vec2<f32>(-2.0,  2.0),
63                     vec2<f32>( 2.0, -2.0),
64                     vec2<f32>(-2.0,  2.0),
65                     vec2<f32>( 2.0, -2.0),
66                     vec2<f32>( 2.0,  2.0));
67                 return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
68             }
69         )");
70         auto fsModule = utils::CreateShaderModule(device, R"(
71             [[group(0), binding(0)]] var sampler0 : sampler;
72             [[group(0), binding(1)]] var texture0 : texture_2d<f32>;
73 
74             [[stage(fragment)]]
75             fn main([[builtin(position)]] FragCoord : vec4<f32>) -> [[location(0)]] vec4<f32> {
76                 return textureSample(texture0, sampler0, FragCoord.xy / vec2<f32>(2.0, 2.0));
77             })");
78 
79         utils::ComboRenderPipelineDescriptor pipelineDescriptor;
80         pipelineDescriptor.vertex.module = vsModule;
81         pipelineDescriptor.cFragment.module = fsModule;
82         pipelineDescriptor.cTargets[0].format = mRenderPass.colorFormat;
83 
84         mPipeline = device.CreateRenderPipeline(&pipelineDescriptor);
85         mBindGroupLayout = mPipeline.GetBindGroupLayout(0);
86 
87         wgpu::TextureDescriptor descriptor;
88         descriptor.dimension = wgpu::TextureDimension::e2D;
89         descriptor.size.width = 2;
90         descriptor.size.height = 2;
91         descriptor.size.depthOrArrayLayers = 1;
92         descriptor.sampleCount = 1;
93         descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
94         descriptor.mipLevelCount = 1;
95         descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding;
96         wgpu::Texture texture = device.CreateTexture(&descriptor);
97 
98         // Create a 2x2 checkerboard texture, with black in the top left and bottom right corners.
99         const uint32_t rowPixels = kTextureBytesPerRowAlignment / sizeof(RGBA8);
100         RGBA8 data[rowPixels * 2];
101         data[0] = data[rowPixels + 1] = RGBA8::kBlack;
102         data[1] = data[rowPixels] = RGBA8::kWhite;
103 
104         wgpu::Buffer stagingBuffer =
105             utils::CreateBufferFromData(device, data, sizeof(data), wgpu::BufferUsage::CopySrc);
106         wgpu::ImageCopyBuffer imageCopyBuffer = utils::CreateImageCopyBuffer(stagingBuffer, 0, 256);
107         wgpu::ImageCopyTexture imageCopyTexture =
108             utils::CreateImageCopyTexture(texture, 0, {0, 0, 0});
109         wgpu::Extent3D copySize = {2, 2, 1};
110 
111         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
112         encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyTexture, &copySize);
113 
114         wgpu::CommandBuffer copy = encoder.Finish();
115         queue.Submit(1, &copy);
116 
117         mTextureView = texture.CreateView();
118     }
119 
TestAddressModes(AddressModeTestCase u,AddressModeTestCase v,AddressModeTestCase w)120     void TestAddressModes(AddressModeTestCase u, AddressModeTestCase v, AddressModeTestCase w) {
121         wgpu::Sampler sampler;
122         {
123             wgpu::SamplerDescriptor descriptor = {};
124             descriptor.minFilter = wgpu::FilterMode::Nearest;
125             descriptor.magFilter = wgpu::FilterMode::Nearest;
126             descriptor.mipmapFilter = wgpu::FilterMode::Nearest;
127             descriptor.addressModeU = u.mMode;
128             descriptor.addressModeV = v.mMode;
129             descriptor.addressModeW = w.mMode;
130             sampler = device.CreateSampler(&descriptor);
131         }
132 
133         wgpu::BindGroup bindGroup =
134             utils::MakeBindGroup(device, mBindGroupLayout, {{0, sampler}, {1, mTextureView}});
135 
136         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
137         {
138             wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&mRenderPass.renderPassInfo);
139             pass.SetPipeline(mPipeline);
140             pass.SetBindGroup(0, bindGroup);
141             pass.Draw(6);
142             pass.EndPass();
143         }
144 
145         wgpu::CommandBuffer commands = encoder.Finish();
146         queue.Submit(1, &commands);
147 
148         RGBA8 expectedU2(u.mExpected2, u.mExpected2, u.mExpected2, 255);
149         RGBA8 expectedU3(u.mExpected3, u.mExpected3, u.mExpected3, 255);
150         RGBA8 expectedV2(v.mExpected2, v.mExpected2, v.mExpected2, 255);
151         RGBA8 expectedV3(v.mExpected3, v.mExpected3, v.mExpected3, 255);
152         EXPECT_PIXEL_RGBA8_EQ(RGBA8::kBlack, mRenderPass.color, 0, 0);
153         EXPECT_PIXEL_RGBA8_EQ(RGBA8::kWhite, mRenderPass.color, 0, 1);
154         EXPECT_PIXEL_RGBA8_EQ(RGBA8::kWhite, mRenderPass.color, 1, 0);
155         EXPECT_PIXEL_RGBA8_EQ(RGBA8::kBlack, mRenderPass.color, 1, 1);
156         EXPECT_PIXEL_RGBA8_EQ(expectedU2, mRenderPass.color, 2, 0);
157         EXPECT_PIXEL_RGBA8_EQ(expectedU3, mRenderPass.color, 3, 0);
158         EXPECT_PIXEL_RGBA8_EQ(expectedV2, mRenderPass.color, 0, 2);
159         EXPECT_PIXEL_RGBA8_EQ(expectedV3, mRenderPass.color, 0, 3);
160         // TODO: add tests for W address mode, once Dawn supports 3D textures
161     }
162 
163     utils::BasicRenderPass mRenderPass;
164     wgpu::BindGroupLayout mBindGroupLayout;
165     wgpu::RenderPipeline mPipeline;
166     wgpu::TextureView mTextureView;
167 };
168 
169 // Test drawing a rect with a checkerboard texture with different address modes.
TEST_P(SamplerTest,AddressMode)170 TEST_P(SamplerTest, AddressMode) {
171     for (auto u : addressModes) {
172         for (auto v : addressModes) {
173             for (auto w : addressModes) {
174                 TestAddressModes(u, v, w);
175             }
176         }
177     }
178 }
179 
180 DAWN_INSTANTIATE_TEST(SamplerTest,
181                       D3D12Backend(),
182                       MetalBackend(),
183                       OpenGLBackend(),
184                       OpenGLESBackend(),
185                       VulkanBackend());
186