| // Copyright 2021 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 <gtest/gtest.h> | 
 |  | 
 | #include "dawn_native/Limits.h" | 
 |  | 
 | // Test |GetDefaultLimits| returns the default. | 
 | TEST(Limits, GetDefaultLimits) { | 
 |     dawn::native::Limits limits = {}; | 
 |     EXPECT_NE(limits.maxBindGroups, 4u); | 
 |  | 
 |     dawn::native::GetDefaultLimits(&limits); | 
 |  | 
 |     EXPECT_EQ(limits.maxBindGroups, 4u); | 
 | } | 
 |  | 
 | // Test |ReifyDefaultLimits| populates the default if | 
 | // values are undefined. | 
 | TEST(Limits, ReifyDefaultLimits_PopulatesDefault) { | 
 |     dawn::native::Limits limits; | 
 |     limits.maxComputeWorkgroupStorageSize = wgpu::kLimitU32Undefined; | 
 |     limits.maxStorageBufferBindingSize = wgpu::kLimitU64Undefined; | 
 |  | 
 |     dawn::native::Limits reified = dawn::native::ReifyDefaultLimits(limits); | 
 |     EXPECT_EQ(reified.maxComputeWorkgroupStorageSize, 16352u); | 
 |     EXPECT_EQ(reified.maxStorageBufferBindingSize, 134217728ul); | 
 | } | 
 |  | 
 | // Test |ReifyDefaultLimits| clamps to the default if | 
 | // values are worse than the default. | 
 | TEST(Limits, ReifyDefaultLimits_Clamps) { | 
 |     dawn::native::Limits limits; | 
 |     limits.maxStorageBuffersPerShaderStage = 4; | 
 |     limits.minUniformBufferOffsetAlignment = 512; | 
 |  | 
 |     dawn::native::Limits reified = dawn::native::ReifyDefaultLimits(limits); | 
 |     EXPECT_EQ(reified.maxStorageBuffersPerShaderStage, 8u); | 
 |     EXPECT_EQ(reified.minUniformBufferOffsetAlignment, 256u); | 
 | } | 
 |  | 
 | // Test |ValidateLimits| works to validate limits are not better | 
 | // than supported. | 
 | TEST(Limits, ValidateLimits) { | 
 |     // Start with the default for supported. | 
 |     dawn::native::Limits defaults; | 
 |     dawn::native::GetDefaultLimits(&defaults); | 
 |  | 
 |     // Test supported == required is valid. | 
 |     { | 
 |         dawn::native::Limits required = defaults; | 
 |         EXPECT_TRUE(ValidateLimits(defaults, required).IsSuccess()); | 
 |     } | 
 |  | 
 |     // Test supported == required is valid, when they are not default. | 
 |     { | 
 |         dawn::native::Limits supported = defaults; | 
 |         dawn::native::Limits required = defaults; | 
 |         supported.maxBindGroups += 1; | 
 |         required.maxBindGroups += 1; | 
 |         EXPECT_TRUE(ValidateLimits(supported, required).IsSuccess()); | 
 |     } | 
 |  | 
 |     // Test that default-initialized (all undefined) is valid. | 
 |     { | 
 |         dawn::native::Limits required = {}; | 
 |         EXPECT_TRUE(ValidateLimits(defaults, required).IsSuccess()); | 
 |     } | 
 |  | 
 |     // Test that better than max is invalid. | 
 |     { | 
 |         dawn::native::Limits required = {}; | 
 |         required.maxTextureDimension3D = defaults.maxTextureDimension3D + 1; | 
 |         dawn::native::MaybeError err = ValidateLimits(defaults, required); | 
 |         EXPECT_TRUE(err.IsError()); | 
 |         err.AcquireError(); | 
 |     } | 
 |  | 
 |     // Test that worse than max is valid. | 
 |     { | 
 |         dawn::native::Limits required = {}; | 
 |         required.maxComputeWorkgroupSizeX = defaults.maxComputeWorkgroupSizeX - 1; | 
 |         EXPECT_TRUE(ValidateLimits(defaults, required).IsSuccess()); | 
 |     } | 
 |  | 
 |     // Test that better than min is invalid. | 
 |     { | 
 |         dawn::native::Limits required = {}; | 
 |         required.minUniformBufferOffsetAlignment = defaults.minUniformBufferOffsetAlignment / 2; | 
 |         dawn::native::MaybeError err = ValidateLimits(defaults, required); | 
 |         EXPECT_TRUE(err.IsError()); | 
 |         err.AcquireError(); | 
 |     } | 
 |  | 
 |     // Test that worse than min is valid. | 
 |     { | 
 |         dawn::native::Limits required = {}; | 
 |         required.minStorageBufferOffsetAlignment = defaults.minStorageBufferOffsetAlignment * 2; | 
 |         EXPECT_TRUE(ValidateLimits(defaults, required).IsSuccess()); | 
 |     } | 
 | } | 
 |  | 
 | // Test that |ApplyLimitTiers| degrades limits to the next best tier. | 
 | TEST(Limits, ApplyLimitTiers) { | 
 |     auto SetLimitsStorageBufferBindingSizeTier2 = [](dawn::native::Limits* limits) { | 
 |         limits->maxStorageBufferBindingSize = 1073741824; | 
 |     }; | 
 |     dawn::native::Limits limitsStorageBufferBindingSizeTier2; | 
 |     dawn::native::GetDefaultLimits(&limitsStorageBufferBindingSizeTier2); | 
 |     SetLimitsStorageBufferBindingSizeTier2(&limitsStorageBufferBindingSizeTier2); | 
 |  | 
 |     auto SetLimitsStorageBufferBindingSizeTier3 = [](dawn::native::Limits* limits) { | 
 |         limits->maxStorageBufferBindingSize = 2147483647; | 
 |     }; | 
 |     dawn::native::Limits limitsStorageBufferBindingSizeTier3; | 
 |     dawn::native::GetDefaultLimits(&limitsStorageBufferBindingSizeTier3); | 
 |     SetLimitsStorageBufferBindingSizeTier3(&limitsStorageBufferBindingSizeTier3); | 
 |  | 
 |     auto SetLimitsComputeWorkgroupStorageSizeTier1 = [](dawn::native::Limits* limits) { | 
 |         limits->maxComputeWorkgroupStorageSize = 16352; | 
 |     }; | 
 |     dawn::native::Limits limitsComputeWorkgroupStorageSizeTier1; | 
 |     dawn::native::GetDefaultLimits(&limitsComputeWorkgroupStorageSizeTier1); | 
 |     SetLimitsComputeWorkgroupStorageSizeTier1(&limitsComputeWorkgroupStorageSizeTier1); | 
 |  | 
 |     auto SetLimitsComputeWorkgroupStorageSizeTier3 = [](dawn::native::Limits* limits) { | 
 |         limits->maxComputeWorkgroupStorageSize = 65536; | 
 |     }; | 
 |     dawn::native::Limits limitsComputeWorkgroupStorageSizeTier3; | 
 |     dawn::native::GetDefaultLimits(&limitsComputeWorkgroupStorageSizeTier3); | 
 |     SetLimitsComputeWorkgroupStorageSizeTier3(&limitsComputeWorkgroupStorageSizeTier3); | 
 |  | 
 |     // Test that applying tiers to limits that are exactly | 
 |     // equal to a tier returns the same values. | 
 |     { | 
 |         dawn::native::Limits limits = limitsStorageBufferBindingSizeTier2; | 
 |         EXPECT_EQ(ApplyLimitTiers(limits), limits); | 
 |  | 
 |         limits = limitsStorageBufferBindingSizeTier3; | 
 |         EXPECT_EQ(ApplyLimitTiers(limits), limits); | 
 |     } | 
 |  | 
 |     // Test all limits slightly worse than tier 3. | 
 |     { | 
 |         dawn::native::Limits limits = limitsStorageBufferBindingSizeTier3; | 
 |         limits.maxStorageBufferBindingSize -= 1; | 
 |         EXPECT_EQ(ApplyLimitTiers(limits), limitsStorageBufferBindingSizeTier2); | 
 |     } | 
 |  | 
 |     // Test that limits may match one tier exactly and be degraded in another tier. | 
 |     // Degrading to one tier does not affect the other tier. | 
 |     { | 
 |         dawn::native::Limits limits = limitsComputeWorkgroupStorageSizeTier3; | 
 |         // Set tier 3 and change one limit to be insufficent. | 
 |         SetLimitsStorageBufferBindingSizeTier3(&limits); | 
 |         limits.maxStorageBufferBindingSize -= 1; | 
 |  | 
 |         dawn::native::Limits tiered = ApplyLimitTiers(limits); | 
 |  | 
 |         // Check that |tiered| has the limits of memorySize tier 2 | 
 |         dawn::native::Limits tieredWithMemorySizeTier2 = tiered; | 
 |         SetLimitsStorageBufferBindingSizeTier2(&tieredWithMemorySizeTier2); | 
 |         EXPECT_EQ(tiered, tieredWithMemorySizeTier2); | 
 |  | 
 |         // Check that |tiered| has the limits of bindingSpace tier 3 | 
 |         dawn::native::Limits tieredWithBindingSpaceTier3 = tiered; | 
 |         SetLimitsComputeWorkgroupStorageSizeTier3(&tieredWithBindingSpaceTier3); | 
 |         EXPECT_EQ(tiered, tieredWithBindingSpaceTier3); | 
 |     } | 
 |  | 
 |     // Test that limits may be simultaneously degraded in two tiers independently. | 
 |     { | 
 |         dawn::native::Limits limits; | 
 |         dawn::native::GetDefaultLimits(&limits); | 
 |         SetLimitsComputeWorkgroupStorageSizeTier3(&limits); | 
 |         SetLimitsStorageBufferBindingSizeTier3(&limits); | 
 |         limits.maxComputeWorkgroupStorageSize = | 
 |             limitsComputeWorkgroupStorageSizeTier1.maxComputeWorkgroupStorageSize + 1; | 
 |         limits.maxStorageBufferBindingSize = | 
 |             limitsStorageBufferBindingSizeTier2.maxStorageBufferBindingSize + 1; | 
 |  | 
 |         dawn::native::Limits tiered = ApplyLimitTiers(limits); | 
 |  | 
 |         dawn::native::Limits expected = tiered; | 
 |         SetLimitsComputeWorkgroupStorageSizeTier1(&expected); | 
 |         SetLimitsStorageBufferBindingSizeTier2(&expected); | 
 |         EXPECT_EQ(tiered, expected); | 
 |     } | 
 | } |