| // Copyright 2019 The Dawn Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "tests/DawnTest.h" |
| |
| #include "utils/ComboRenderPipelineDescriptor.h" |
| #include "utils/WGPUHelpers.h" |
| |
| class ObjectCachingTest : public DawnTest {}; |
| |
| // Test that BindGroupLayouts are correctly deduplicated. |
| TEST_P(ObjectCachingTest, BindGroupLayoutDeduplication) { |
| wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer}}); |
| wgpu::BindGroupLayout sameBgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer}}); |
| wgpu::BindGroupLayout otherBgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Vertex, wgpu::BindingType::UniformBuffer}}); |
| |
| EXPECT_NE(bgl.Get(), otherBgl.Get()); |
| EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire()); |
| } |
| |
| // Test that two similar bind group layouts won't refer to the same one if they differ by dynamic. |
| TEST_P(ObjectCachingTest, BindGroupLayoutDynamic) { |
| wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer, true}}); |
| wgpu::BindGroupLayout sameBgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer, true}}); |
| wgpu::BindGroupLayout otherBgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer, false}}); |
| |
| EXPECT_NE(bgl.Get(), otherBgl.Get()); |
| EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire()); |
| } |
| |
| // Test that two similar bind group layouts won't refer to the same one if they differ by |
| // textureComponentType |
| TEST_P(ObjectCachingTest, BindGroupLayoutTextureComponentType) { |
| wgpu::BindGroupLayout bgl = |
| utils::MakeBindGroupLayout(device, {{1, |
| wgpu::ShaderStage::Fragment, |
| wgpu::BindingType::SampledTexture, |
| false, |
| false, |
| {}, |
| wgpu::TextureViewDimension::e2D, |
| wgpu::TextureComponentType::Float}}); |
| wgpu::BindGroupLayout sameBgl = |
| utils::MakeBindGroupLayout(device, {{1, |
| wgpu::ShaderStage::Fragment, |
| wgpu::BindingType::SampledTexture, |
| false, |
| false, |
| {}, |
| wgpu::TextureViewDimension::e2D, |
| wgpu::TextureComponentType::Float}}); |
| wgpu::BindGroupLayout otherBgl = |
| utils::MakeBindGroupLayout(device, {{1, |
| wgpu::ShaderStage::Fragment, |
| wgpu::BindingType::SampledTexture, |
| false, |
| false, |
| {}, |
| wgpu::TextureViewDimension::e2D, |
| wgpu::TextureComponentType::Uint}}); |
| |
| EXPECT_NE(bgl.Get(), otherBgl.Get()); |
| EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire()); |
| } |
| |
| // Test that two similar bind group layouts won't refer to the same one if they differ by |
| // viewDimension |
| TEST_P(ObjectCachingTest, BindGroupLayoutViewDimension) { |
| wgpu::BindGroupLayout bgl = |
| utils::MakeBindGroupLayout(device, {{1, |
| wgpu::ShaderStage::Fragment, |
| wgpu::BindingType::SampledTexture, |
| false, |
| false, |
| {}, |
| wgpu::TextureViewDimension::e2D, |
| wgpu::TextureComponentType::Float}}); |
| wgpu::BindGroupLayout sameBgl = |
| utils::MakeBindGroupLayout(device, {{1, |
| wgpu::ShaderStage::Fragment, |
| wgpu::BindingType::SampledTexture, |
| false, |
| false, |
| {}, |
| wgpu::TextureViewDimension::e2D, |
| wgpu::TextureComponentType::Float}}); |
| wgpu::BindGroupLayout otherBgl = |
| utils::MakeBindGroupLayout(device, {{1, |
| wgpu::ShaderStage::Fragment, |
| wgpu::BindingType::SampledTexture, |
| false, |
| false, |
| {}, |
| wgpu::TextureViewDimension::e2DArray, |
| wgpu::TextureComponentType::Float}}); |
| |
| EXPECT_NE(bgl.Get(), otherBgl.Get()); |
| EXPECT_EQ(bgl.Get() == sameBgl.Get(), !UsesWire()); |
| } |
| |
| // Test that an error object doesn't try to uncache itself |
| TEST_P(ObjectCachingTest, ErrorObjectDoesntUncache) { |
| DAWN_SKIP_TEST_IF(IsDawnValidationSkipped()); |
| |
| ASSERT_DEVICE_ERROR( |
| wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout( |
| device, {{0, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer}, |
| {0, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer}})); |
| } |
| |
| // Test that PipelineLayouts are correctly deduplicated. |
| TEST_P(ObjectCachingTest, PipelineLayoutDeduplication) { |
| wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer}}); |
| wgpu::BindGroupLayout otherBgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Vertex, wgpu::BindingType::UniformBuffer}}); |
| |
| wgpu::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl); |
| wgpu::PipelineLayout samePl = utils::MakeBasicPipelineLayout(device, &bgl); |
| wgpu::PipelineLayout otherPl1 = utils::MakeBasicPipelineLayout(device, nullptr); |
| wgpu::PipelineLayout otherPl2 = utils::MakeBasicPipelineLayout(device, &otherBgl); |
| |
| EXPECT_NE(pl.Get(), otherPl1.Get()); |
| EXPECT_NE(pl.Get(), otherPl2.Get()); |
| EXPECT_EQ(pl.Get() == samePl.Get(), !UsesWire()); |
| } |
| |
| // Test that ShaderModules are correctly deduplicated. |
| TEST_P(ObjectCachingTest, ShaderModuleDeduplication) { |
| wgpu::ShaderModule module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( |
| #version 450 |
| layout(location = 0) out vec4 fragColor; |
| void main() { |
| fragColor = vec4(0.0, 1.0, 0.0, 1.0); |
| })"); |
| wgpu::ShaderModule sameModule = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( |
| #version 450 |
| layout(location = 0) out vec4 fragColor; |
| void main() { |
| fragColor = vec4(0.0, 1.0, 0.0, 1.0); |
| })"); |
| wgpu::ShaderModule otherModule = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( |
| #version 450 |
| layout(location = 0) out vec4 fragColor; |
| void main() { |
| fragColor = vec4(0.0); |
| })"); |
| |
| EXPECT_NE(module.Get(), otherModule.Get()); |
| EXPECT_EQ(module.Get() == sameModule.Get(), !UsesWire()); |
| } |
| |
| // Test that ComputePipeline are correctly deduplicated wrt. their ShaderModule |
| TEST_P(ObjectCachingTest, ComputePipelineDeduplicationOnShaderModule) { |
| wgpu::ShaderModule module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"( |
| #version 450 |
| shared uint i; |
| void main() { |
| i = 0; |
| })"); |
| wgpu::ShaderModule sameModule = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"( |
| #version 450 |
| shared uint i; |
| void main() { |
| i = 0; |
| })"); |
| wgpu::ShaderModule otherModule = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"( |
| #version 450 |
| void main() { |
| })"); |
| |
| EXPECT_NE(module.Get(), otherModule.Get()); |
| EXPECT_EQ(module.Get() == sameModule.Get(), !UsesWire()); |
| |
| wgpu::PipelineLayout layout = utils::MakeBasicPipelineLayout(device, nullptr); |
| |
| wgpu::ComputePipelineDescriptor desc; |
| desc.computeStage.entryPoint = "main"; |
| desc.layout = layout; |
| |
| desc.computeStage.module = module; |
| wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&desc); |
| |
| desc.computeStage.module = sameModule; |
| wgpu::ComputePipeline samePipeline = device.CreateComputePipeline(&desc); |
| |
| desc.computeStage.module = otherModule; |
| wgpu::ComputePipeline otherPipeline = device.CreateComputePipeline(&desc); |
| |
| EXPECT_NE(pipeline.Get(), otherPipeline.Get()); |
| EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire()); |
| } |
| |
| // Test that ComputePipeline are correctly deduplicated wrt. their layout |
| TEST_P(ObjectCachingTest, ComputePipelineDeduplicationOnLayout) { |
| wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer}}); |
| wgpu::BindGroupLayout otherBgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Vertex, wgpu::BindingType::UniformBuffer}}); |
| |
| wgpu::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl); |
| wgpu::PipelineLayout samePl = utils::MakeBasicPipelineLayout(device, &bgl); |
| wgpu::PipelineLayout otherPl = utils::MakeBasicPipelineLayout(device, nullptr); |
| |
| EXPECT_NE(pl.Get(), otherPl.Get()); |
| EXPECT_EQ(pl.Get() == samePl.Get(), !UsesWire()); |
| |
| wgpu::ComputePipelineDescriptor desc; |
| desc.computeStage.entryPoint = "main"; |
| desc.computeStage.module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Compute, R"( |
| #version 450 |
| shared uint i; |
| void main() { |
| i = 0; |
| })"); |
| |
| desc.layout = pl; |
| wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&desc); |
| |
| desc.layout = samePl; |
| wgpu::ComputePipeline samePipeline = device.CreateComputePipeline(&desc); |
| |
| desc.layout = otherPl; |
| wgpu::ComputePipeline otherPipeline = device.CreateComputePipeline(&desc); |
| |
| EXPECT_NE(pipeline.Get(), otherPipeline.Get()); |
| EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire()); |
| } |
| |
| // Test that RenderPipelines are correctly deduplicated wrt. their layout |
| TEST_P(ObjectCachingTest, RenderPipelineDeduplicationOnLayout) { |
| wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer}}); |
| wgpu::BindGroupLayout otherBgl = utils::MakeBindGroupLayout( |
| device, {{1, wgpu::ShaderStage::Vertex, wgpu::BindingType::UniformBuffer}}); |
| |
| wgpu::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl); |
| wgpu::PipelineLayout samePl = utils::MakeBasicPipelineLayout(device, &bgl); |
| wgpu::PipelineLayout otherPl = utils::MakeBasicPipelineLayout(device, nullptr); |
| |
| EXPECT_NE(pl.Get(), otherPl.Get()); |
| EXPECT_EQ(pl.Get() == samePl.Get(), !UsesWire()); |
| |
| utils::ComboRenderPipelineDescriptor desc(device); |
| desc.vertexStage.module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( |
| #version 450 |
| void main() { |
| gl_Position = vec4(0.0); |
| })"); |
| desc.cFragmentStage.module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( |
| #version 450 |
| void main() { |
| })"); |
| |
| desc.layout = pl; |
| wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc); |
| |
| desc.layout = samePl; |
| wgpu::RenderPipeline samePipeline = device.CreateRenderPipeline(&desc); |
| |
| desc.layout = otherPl; |
| wgpu::RenderPipeline otherPipeline = device.CreateRenderPipeline(&desc); |
| |
| EXPECT_NE(pipeline.Get(), otherPipeline.Get()); |
| EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire()); |
| } |
| |
| // Test that RenderPipelines are correctly deduplicated wrt. their vertex module |
| TEST_P(ObjectCachingTest, RenderPipelineDeduplicationOnVertexModule) { |
| wgpu::ShaderModule module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( |
| #version 450 |
| void main() { |
| gl_Position = vec4(0.0); |
| })"); |
| wgpu::ShaderModule sameModule = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( |
| #version 450 |
| void main() { |
| gl_Position = vec4(0.0); |
| })"); |
| wgpu::ShaderModule otherModule = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( |
| #version 450 |
| void main() { |
| gl_Position = vec4(1.0); |
| })"); |
| |
| EXPECT_NE(module.Get(), otherModule.Get()); |
| EXPECT_EQ(module.Get() == sameModule.Get(), !UsesWire()); |
| |
| utils::ComboRenderPipelineDescriptor desc(device); |
| desc.cFragmentStage.module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( |
| #version 450 |
| void main() { |
| })"); |
| |
| desc.vertexStage.module = module; |
| wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc); |
| |
| desc.vertexStage.module = sameModule; |
| wgpu::RenderPipeline samePipeline = device.CreateRenderPipeline(&desc); |
| |
| desc.vertexStage.module = otherModule; |
| wgpu::RenderPipeline otherPipeline = device.CreateRenderPipeline(&desc); |
| |
| EXPECT_NE(pipeline.Get(), otherPipeline.Get()); |
| EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire()); |
| } |
| |
| // Test that RenderPipelines are correctly deduplicated wrt. their fragment module |
| TEST_P(ObjectCachingTest, RenderPipelineDeduplicationOnFragmentModule) { |
| wgpu::ShaderModule module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( |
| #version 450 |
| void main() { |
| })"); |
| wgpu::ShaderModule sameModule = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( |
| #version 450 |
| void main() { |
| })"); |
| wgpu::ShaderModule otherModule = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"( |
| #version 450 |
| layout (location = 0) out vec4 color; |
| void main() { |
| color = vec4(0.0); |
| })"); |
| |
| EXPECT_NE(module.Get(), otherModule.Get()); |
| EXPECT_EQ(module.Get() == sameModule.Get(), !UsesWire()); |
| |
| utils::ComboRenderPipelineDescriptor desc(device); |
| desc.vertexStage.module = |
| utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, R"( |
| #version 450 |
| void main() { |
| gl_Position = vec4(0.0); |
| })"); |
| |
| desc.cFragmentStage.module = module; |
| wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc); |
| |
| desc.cFragmentStage.module = sameModule; |
| wgpu::RenderPipeline samePipeline = device.CreateRenderPipeline(&desc); |
| |
| desc.cFragmentStage.module = otherModule; |
| wgpu::RenderPipeline otherPipeline = device.CreateRenderPipeline(&desc); |
| |
| EXPECT_NE(pipeline.Get(), otherPipeline.Get()); |
| EXPECT_EQ(pipeline.Get() == samePipeline.Get(), !UsesWire()); |
| } |
| |
| // Test that Samplers are correctly deduplicated. |
| TEST_P(ObjectCachingTest, SamplerDeduplication) { |
| wgpu::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor(); |
| wgpu::Sampler sampler = device.CreateSampler(&samplerDesc); |
| |
| wgpu::SamplerDescriptor sameSamplerDesc = utils::GetDefaultSamplerDescriptor(); |
| wgpu::Sampler sameSampler = device.CreateSampler(&sameSamplerDesc); |
| |
| wgpu::SamplerDescriptor otherSamplerDescAddressModeU = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescAddressModeU.addressModeU = wgpu::AddressMode::ClampToEdge; |
| wgpu::Sampler otherSamplerAddressModeU = device.CreateSampler(&otherSamplerDescAddressModeU); |
| |
| wgpu::SamplerDescriptor otherSamplerDescAddressModeV = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescAddressModeV.addressModeV = wgpu::AddressMode::ClampToEdge; |
| wgpu::Sampler otherSamplerAddressModeV = device.CreateSampler(&otherSamplerDescAddressModeV); |
| |
| wgpu::SamplerDescriptor otherSamplerDescAddressModeW = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescAddressModeW.addressModeW = wgpu::AddressMode::ClampToEdge; |
| wgpu::Sampler otherSamplerAddressModeW = device.CreateSampler(&otherSamplerDescAddressModeW); |
| |
| wgpu::SamplerDescriptor otherSamplerDescMagFilter = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescMagFilter.magFilter = wgpu::FilterMode::Nearest; |
| wgpu::Sampler otherSamplerMagFilter = device.CreateSampler(&otherSamplerDescMagFilter); |
| |
| wgpu::SamplerDescriptor otherSamplerDescMinFilter = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescMinFilter.minFilter = wgpu::FilterMode::Nearest; |
| wgpu::Sampler otherSamplerMinFilter = device.CreateSampler(&otherSamplerDescMinFilter); |
| |
| wgpu::SamplerDescriptor otherSamplerDescMipmapFilter = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescMipmapFilter.mipmapFilter = wgpu::FilterMode::Nearest; |
| wgpu::Sampler otherSamplerMipmapFilter = device.CreateSampler(&otherSamplerDescMipmapFilter); |
| |
| wgpu::SamplerDescriptor otherSamplerDescLodMinClamp = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescLodMinClamp.lodMinClamp += 1; |
| wgpu::Sampler otherSamplerLodMinClamp = device.CreateSampler(&otherSamplerDescLodMinClamp); |
| |
| wgpu::SamplerDescriptor otherSamplerDescLodMaxClamp = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescLodMaxClamp.lodMaxClamp += 1; |
| wgpu::Sampler otherSamplerLodMaxClamp = device.CreateSampler(&otherSamplerDescLodMaxClamp); |
| |
| wgpu::SamplerDescriptor otherSamplerDescCompareFunction = utils::GetDefaultSamplerDescriptor(); |
| otherSamplerDescCompareFunction.compare = wgpu::CompareFunction::Always; |
| wgpu::Sampler otherSamplerCompareFunction = |
| device.CreateSampler(&otherSamplerDescCompareFunction); |
| |
| EXPECT_NE(sampler.Get(), otherSamplerAddressModeU.Get()); |
| EXPECT_NE(sampler.Get(), otherSamplerAddressModeV.Get()); |
| EXPECT_NE(sampler.Get(), otherSamplerAddressModeW.Get()); |
| EXPECT_NE(sampler.Get(), otherSamplerMagFilter.Get()); |
| EXPECT_NE(sampler.Get(), otherSamplerMinFilter.Get()); |
| EXPECT_NE(sampler.Get(), otherSamplerMipmapFilter.Get()); |
| EXPECT_NE(sampler.Get(), otherSamplerLodMinClamp.Get()); |
| EXPECT_NE(sampler.Get(), otherSamplerLodMaxClamp.Get()); |
| EXPECT_NE(sampler.Get(), otherSamplerCompareFunction.Get()); |
| EXPECT_EQ(sampler.Get() == sameSampler.Get(), !UsesWire()); |
| } |
| |
| DAWN_INSTANTIATE_TEST(ObjectCachingTest, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend()); |