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, ©Size);
113
114 wgpu::CommandBuffer copy = encoder.Finish();
115 queue.Submit(1, ©);
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