1 // Copyright 2019 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/DawnTest.h"
16
17 #include "utils/ComboRenderPipelineDescriptor.h"
18 #include "utils/DawnHelpers.h"
19
20 class ObjectCachingTest : public DawnTest {};
21
22 // Test that BindGroupLayouts are correctly deduplicated.
TEST_P(ObjectCachingTest,BindGroupLayoutDeduplication)23 TEST_P(ObjectCachingTest, BindGroupLayoutDeduplication) {
24 dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
25 device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer}});
26 dawn::BindGroupLayout sameBgl = utils::MakeBindGroupLayout(
27 device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer}});
28 dawn::BindGroupLayout otherBgl = utils::MakeBindGroupLayout(
29 device, {{1, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer}});
30
31 EXPECT_NE(bgl.Get(), otherBgl.Get());
32 EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire());
33 }
34
35 // Test that two similar bind group layouts won't refer to the same one.
TEST_P(ObjectCachingTest,BindGroupLayoutDynamic)36 TEST_P(ObjectCachingTest, BindGroupLayoutDynamic) {
37 dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
38 device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer, true}});
39 dawn::BindGroupLayout sameBgl = utils::MakeBindGroupLayout(
40 device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer, true}});
41 dawn::BindGroupLayout otherBgl = utils::MakeBindGroupLayout(
42 device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer, false}});
43
44 EXPECT_NE(bgl.Get(), otherBgl.Get());
45 EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire());
46 }
47
48 // Test that an error object doesn't try to uncache itself
TEST_P(ObjectCachingTest,ErrorObjectDoesntUncache)49 TEST_P(ObjectCachingTest, ErrorObjectDoesntUncache) {
50 ASSERT_DEVICE_ERROR(
51 dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
52 device, {{0, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer},
53 {0, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer}}));
54 }
55
56 // Test that PipelineLayouts are correctly deduplicated.
TEST_P(ObjectCachingTest,PipelineLayoutDeduplication)57 TEST_P(ObjectCachingTest, PipelineLayoutDeduplication) {
58 dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
59 device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer}});
60 dawn::BindGroupLayout otherBgl = utils::MakeBindGroupLayout(
61 device, {{1, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer}});
62
63 dawn::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
64 dawn::PipelineLayout samePl = utils::MakeBasicPipelineLayout(device, &bgl);
65 dawn::PipelineLayout otherPl1 = utils::MakeBasicPipelineLayout(device, nullptr);
66 dawn::PipelineLayout otherPl2 = utils::MakeBasicPipelineLayout(device, &otherBgl);
67
68 EXPECT_NE(pl.Get(), otherPl1.Get());
69 EXPECT_NE(pl.Get(), otherPl2.Get());
70 EXPECT_EQ(pl.Get() == samePl.Get(), !UsesWire());
71 }
72
73 // Test that ShaderModules are correctly deduplicated.
TEST_P(ObjectCachingTest,ShaderModuleDeduplication)74 TEST_P(ObjectCachingTest, ShaderModuleDeduplication) {
75 dawn::ShaderModule module = utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
76 #version 450
77 layout(location = 0) out vec4 fragColor;
78 void main() {
79 fragColor = vec4(0.0, 1.0, 0.0, 1.0);
80 })");
81 dawn::ShaderModule sameModule =
82 utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
83 #version 450
84 layout(location = 0) out vec4 fragColor;
85 void main() {
86 fragColor = vec4(0.0, 1.0, 0.0, 1.0);
87 })");
88 dawn::ShaderModule otherModule =
89 utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
90 #version 450
91 layout(location = 0) out vec4 fragColor;
92 void main() {
93 fragColor = vec4(0.0);
94 })");
95
96 EXPECT_NE(module.Get(), otherModule.Get());
97 EXPECT_EQ(module.Get() == sameModule.Get(), !UsesWire());
98 }
99
100 // Test that ComputePipeline are correctly deduplicated wrt. their ShaderModule
TEST_P(ObjectCachingTest,ComputePipelineDeduplicationOnShaderModule)101 TEST_P(ObjectCachingTest, ComputePipelineDeduplicationOnShaderModule) {
102 dawn::ShaderModule module = utils::CreateShaderModule(device, utils::ShaderStage::Compute, R"(
103 #version 450
104 void main() {
105 int i = 0;
106 })");
107 dawn::ShaderModule sameModule =
108 utils::CreateShaderModule(device, utils::ShaderStage::Compute, R"(
109 #version 450
110 void main() {
111 int i = 0;
112 })");
113 dawn::ShaderModule otherModule =
114 utils::CreateShaderModule(device, utils::ShaderStage::Compute, R"(
115 #version 450
116 void main() {
117 })");
118
119 EXPECT_NE(module.Get(), otherModule.Get());
120 EXPECT_EQ(module.Get() == sameModule.Get(), !UsesWire());
121
122 dawn::PipelineLayout layout = utils::MakeBasicPipelineLayout(device, nullptr);
123
124 dawn::PipelineStageDescriptor stageDesc;
125 stageDesc.entryPoint = "main";
126 stageDesc.module = module;
127
128 dawn::ComputePipelineDescriptor desc;
129 desc.computeStage = &stageDesc;
130 desc.layout = layout;
131
132 dawn::ComputePipeline pipeline = device.CreateComputePipeline(&desc);
133
134 stageDesc.module = sameModule;
135 dawn::ComputePipeline samePipeline = device.CreateComputePipeline(&desc);
136
137 stageDesc.module = otherModule;
138 dawn::ComputePipeline otherPipeline = device.CreateComputePipeline(&desc);
139
140 EXPECT_NE(pipeline.Get(), otherPipeline.Get());
141 EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire());
142 }
143
144 // Test that ComputePipeline are correctly deduplicated wrt. their layout
TEST_P(ObjectCachingTest,ComputePipelineDeduplicationOnLayout)145 TEST_P(ObjectCachingTest, ComputePipelineDeduplicationOnLayout) {
146 dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
147 device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer}});
148 dawn::BindGroupLayout otherBgl = utils::MakeBindGroupLayout(
149 device, {{1, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer}});
150
151 dawn::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
152 dawn::PipelineLayout samePl = utils::MakeBasicPipelineLayout(device, &bgl);
153 dawn::PipelineLayout otherPl = utils::MakeBasicPipelineLayout(device, nullptr);
154
155 EXPECT_NE(pl.Get(), otherPl.Get());
156 EXPECT_EQ(pl.Get() == samePl.Get(), !UsesWire());
157
158 dawn::PipelineStageDescriptor stageDesc;
159 stageDesc.entryPoint = "main";
160 stageDesc.module = utils::CreateShaderModule(device, utils::ShaderStage::Compute, R"(
161 #version 450
162 void main() {
163 int i = 0;
164 })");
165
166 dawn::ComputePipelineDescriptor desc;
167 desc.computeStage = &stageDesc;
168
169 desc.layout = pl;
170 dawn::ComputePipeline pipeline = device.CreateComputePipeline(&desc);
171
172 desc.layout = samePl;
173 dawn::ComputePipeline samePipeline = device.CreateComputePipeline(&desc);
174
175 desc.layout = otherPl;
176 dawn::ComputePipeline otherPipeline = device.CreateComputePipeline(&desc);
177
178 EXPECT_NE(pipeline.Get(), otherPipeline.Get());
179 EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire());
180 }
181
182 // Test that RenderPipelines are correctly deduplicated wrt. their layout
TEST_P(ObjectCachingTest,RenderPipelineDeduplicationOnLayout)183 TEST_P(ObjectCachingTest, RenderPipelineDeduplicationOnLayout) {
184 dawn::BindGroupLayout bgl = utils::MakeBindGroupLayout(
185 device, {{1, dawn::ShaderStageBit::Fragment, dawn::BindingType::UniformBuffer}});
186 dawn::BindGroupLayout otherBgl = utils::MakeBindGroupLayout(
187 device, {{1, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer}});
188
189 dawn::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
190 dawn::PipelineLayout samePl = utils::MakeBasicPipelineLayout(device, &bgl);
191 dawn::PipelineLayout otherPl = utils::MakeBasicPipelineLayout(device, nullptr);
192
193 EXPECT_NE(pl.Get(), otherPl.Get());
194 EXPECT_EQ(pl.Get() == samePl.Get(), !UsesWire());
195
196 utils::ComboRenderPipelineDescriptor desc(device);
197 desc.cVertexStage.module = utils::CreateShaderModule(device, utils::ShaderStage::Vertex, R"(
198 #version 450
199 void main() {
200 gl_Position = vec4(0.0);
201 })");
202 desc.cFragmentStage.module = utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
203 #version 450
204 void main() {
205 })");
206
207 desc.layout = pl;
208 dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
209
210 desc.layout = samePl;
211 dawn::RenderPipeline samePipeline = device.CreateRenderPipeline(&desc);
212
213 desc.layout = otherPl;
214 dawn::RenderPipeline otherPipeline = device.CreateRenderPipeline(&desc);
215
216 EXPECT_NE(pipeline.Get(), otherPipeline.Get());
217 EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire());
218 }
219
220 // Test that RenderPipelines are correctly deduplicated wrt. their vertex module
TEST_P(ObjectCachingTest,RenderPipelineDeduplicationOnVertexModule)221 TEST_P(ObjectCachingTest, RenderPipelineDeduplicationOnVertexModule) {
222 dawn::ShaderModule module = utils::CreateShaderModule(device, utils::ShaderStage::Vertex, R"(
223 #version 450
224 void main() {
225 gl_Position = vec4(0.0);
226 })");
227 dawn::ShaderModule sameModule =
228 utils::CreateShaderModule(device, utils::ShaderStage::Vertex, R"(
229 #version 450
230 void main() {
231 gl_Position = vec4(0.0);
232 })");
233 dawn::ShaderModule otherModule =
234 utils::CreateShaderModule(device, utils::ShaderStage::Vertex, R"(
235 #version 450
236 void main() {
237 gl_Position = vec4(1.0);
238 })");
239
240 EXPECT_NE(module.Get(), otherModule.Get());
241 EXPECT_EQ(module.Get() == sameModule.Get(), !UsesWire());
242
243 utils::ComboRenderPipelineDescriptor desc(device);
244 desc.cFragmentStage.module = utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
245 #version 450
246 void main() {
247 })");
248
249 desc.cVertexStage.module = module;
250 dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
251
252 desc.cVertexStage.module = sameModule;
253 dawn::RenderPipeline samePipeline = device.CreateRenderPipeline(&desc);
254
255 desc.cVertexStage.module = otherModule;
256 dawn::RenderPipeline otherPipeline = device.CreateRenderPipeline(&desc);
257
258 EXPECT_NE(pipeline.Get(), otherPipeline.Get());
259 EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire());
260 }
261
262 // Test that RenderPipelines are correctly deduplicated wrt. their fragment module
TEST_P(ObjectCachingTest,RenderPipelineDeduplicationOnFragmentModule)263 TEST_P(ObjectCachingTest, RenderPipelineDeduplicationOnFragmentModule) {
264 dawn::ShaderModule module = utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
265 #version 450
266 void main() {
267 })");
268 dawn::ShaderModule sameModule =
269 utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
270 #version 450
271 void main() {
272 })");
273 dawn::ShaderModule otherModule =
274 utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
275 #version 450
276 void main() {
277 int i = 0;
278 })");
279
280 EXPECT_NE(module.Get(), otherModule.Get());
281 EXPECT_EQ(module.Get() == sameModule.Get(), !UsesWire());
282
283 utils::ComboRenderPipelineDescriptor desc(device);
284 desc.cVertexStage.module = utils::CreateShaderModule(device, utils::ShaderStage::Vertex, R"(
285 #version 450
286 void main() {
287 gl_Position = vec4(0.0);
288 })");
289
290 desc.cFragmentStage.module = module;
291 dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
292
293 desc.cFragmentStage.module = sameModule;
294 dawn::RenderPipeline samePipeline = device.CreateRenderPipeline(&desc);
295
296 desc.cFragmentStage.module = otherModule;
297 dawn::RenderPipeline otherPipeline = device.CreateRenderPipeline(&desc);
298
299 EXPECT_NE(pipeline.Get(), otherPipeline.Get());
300 EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire());
301 }
302
303 // Test that Samplers are correctly deduplicated.
TEST_P(ObjectCachingTest,SamplerDeduplication)304 TEST_P(ObjectCachingTest, SamplerDeduplication) {
305 dawn::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor();
306 dawn::Sampler sampler = device.CreateSampler(&samplerDesc);
307
308 dawn::SamplerDescriptor sameSamplerDesc = utils::GetDefaultSamplerDescriptor();
309 dawn::Sampler sameSampler = device.CreateSampler(&sameSamplerDesc);
310
311 dawn::SamplerDescriptor otherSamplerDescAddressModeU = utils::GetDefaultSamplerDescriptor();
312 otherSamplerDescAddressModeU.addressModeU = dawn::AddressMode::ClampToEdge;
313 dawn::Sampler otherSamplerAddressModeU = device.CreateSampler(&otherSamplerDescAddressModeU);
314
315 dawn::SamplerDescriptor otherSamplerDescAddressModeV = utils::GetDefaultSamplerDescriptor();
316 otherSamplerDescAddressModeV.addressModeV = dawn::AddressMode::ClampToEdge;
317 dawn::Sampler otherSamplerAddressModeV = device.CreateSampler(&otherSamplerDescAddressModeV);
318
319 dawn::SamplerDescriptor otherSamplerDescAddressModeW = utils::GetDefaultSamplerDescriptor();
320 otherSamplerDescAddressModeW.addressModeW = dawn::AddressMode::ClampToEdge;
321 dawn::Sampler otherSamplerAddressModeW = device.CreateSampler(&otherSamplerDescAddressModeW);
322
323 dawn::SamplerDescriptor otherSamplerDescMagFilter = utils::GetDefaultSamplerDescriptor();
324 otherSamplerDescMagFilter.magFilter = dawn::FilterMode::Nearest;
325 dawn::Sampler otherSamplerMagFilter = device.CreateSampler(&otherSamplerDescMagFilter);
326
327 dawn::SamplerDescriptor otherSamplerDescMinFilter = utils::GetDefaultSamplerDescriptor();
328 otherSamplerDescMinFilter.minFilter = dawn::FilterMode::Nearest;
329 dawn::Sampler otherSamplerMinFilter = device.CreateSampler(&otherSamplerDescMinFilter);
330
331 dawn::SamplerDescriptor otherSamplerDescMipmapFilter = utils::GetDefaultSamplerDescriptor();
332 otherSamplerDescMipmapFilter.mipmapFilter = dawn::FilterMode::Nearest;
333 dawn::Sampler otherSamplerMipmapFilter = device.CreateSampler(&otherSamplerDescMipmapFilter);
334
335 dawn::SamplerDescriptor otherSamplerDescLodMinClamp = utils::GetDefaultSamplerDescriptor();
336 otherSamplerDescLodMinClamp.lodMinClamp += 1;
337 dawn::Sampler otherSamplerLodMinClamp = device.CreateSampler(&otherSamplerDescLodMinClamp);
338
339 dawn::SamplerDescriptor otherSamplerDescLodMaxClamp = utils::GetDefaultSamplerDescriptor();
340 otherSamplerDescLodMaxClamp.lodMaxClamp += 1;
341 dawn::Sampler otherSamplerLodMaxClamp = device.CreateSampler(&otherSamplerDescLodMaxClamp);
342
343 dawn::SamplerDescriptor otherSamplerDescCompareFunction = utils::GetDefaultSamplerDescriptor();
344 otherSamplerDescCompareFunction.compare = dawn::CompareFunction::Always;
345 dawn::Sampler otherSamplerCompareFunction =
346 device.CreateSampler(&otherSamplerDescCompareFunction);
347
348 EXPECT_NE(sampler.Get(), otherSamplerAddressModeU.Get());
349 EXPECT_NE(sampler.Get(), otherSamplerAddressModeV.Get());
350 EXPECT_NE(sampler.Get(), otherSamplerAddressModeW.Get());
351 EXPECT_NE(sampler.Get(), otherSamplerMagFilter.Get());
352 EXPECT_NE(sampler.Get(), otherSamplerMinFilter.Get());
353 EXPECT_NE(sampler.Get(), otherSamplerMipmapFilter.Get());
354 EXPECT_NE(sampler.Get(), otherSamplerLodMinClamp.Get());
355 EXPECT_NE(sampler.Get(), otherSamplerLodMaxClamp.Get());
356 EXPECT_NE(sampler.Get(), otherSamplerCompareFunction.Get());
357 EXPECT_EQ(sampler.Get() == sameSampler.Get(), !UsesWire());
358 }
359
360 DAWN_INSTANTIATE_TEST(ObjectCachingTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);
361