Clamp limits to the defaults if they are worse than the defaults

Bug: dawn:685
Change-Id: Ibae70390fae1d9bde2b625edf7de17e6aafb9cda
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/64603
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Austin Eng 2021-09-20 20:58:46 +00:00 committed by Dawn LUCI CQ
parent 44d729fc8c
commit 1c85de6888
3 changed files with 73 additions and 33 deletions

View File

@ -57,8 +57,13 @@ namespace dawn_native {
template <>
struct CheckLimit<LimitBetterDirection::Lower> {
template <typename T>
static MaybeError Invoke(T supported, T required) {
if (required < supported) {
static bool IsBetter(T lhs, T rhs) {
return lhs < rhs;
}
template <typename T>
static MaybeError Validate(T supported, T required) {
if (IsBetter(required, supported)) {
return DAWN_VALIDATION_ERROR("requiredLimit lower than supported limit");
}
return {};
@ -68,8 +73,13 @@ namespace dawn_native {
template <>
struct CheckLimit<LimitBetterDirection::Higher> {
template <typename T>
static MaybeError Invoke(T supported, T required) {
if (required > supported) {
static bool IsBetter(T lhs, T rhs) {
return lhs > rhs;
}
template <typename T>
static MaybeError Validate(T supported, T required) {
if (IsBetter(required, supported)) {
return DAWN_VALIDATION_ERROR("requiredLimit greater than supported limit");
}
return {};
@ -103,11 +113,14 @@ namespace dawn_native {
Limits ReifyDefaultLimits(const Limits& limits) {
Limits out;
#define X(Better, limitName, defaultValue) \
if (!IsLimitUndefined(limits.limitName)) { \
out.limitName = limits.limitName; \
} else { \
out.limitName = defaultValue; \
#define X(Better, limitName, defaultValue) \
if (IsLimitUndefined(limits.limitName) || \
CheckLimit<LimitBetterDirection::Better>::IsBetter( \
static_cast<decltype(limits.limitName)>(defaultValue), limits.limitName)) { \
/* If the limit is undefined or the default is better, use the default */ \
out.limitName = defaultValue; \
} else { \
out.limitName = limits.limitName; \
}
LIMITS(X)
#undef X
@ -115,10 +128,10 @@ namespace dawn_native {
}
MaybeError ValidateLimits(const Limits& supportedLimits, const Limits& requiredLimits) {
#define X(Better, limitName, defaultValue) \
if (!IsLimitUndefined(requiredLimits.limitName)) { \
DAWN_TRY(CheckLimit<LimitBetterDirection::Better>::Invoke(supportedLimits.limitName, \
requiredLimits.limitName)); \
#define X(Better, limitName, defaultValue) \
if (!IsLimitUndefined(requiredLimits.limitName)) { \
DAWN_TRY(CheckLimit<LimitBetterDirection::Better>::Validate(supportedLimits.limitName, \
requiredLimits.limitName)); \
}
LIMITS(X)
#undef X

View File

@ -28,7 +28,8 @@ namespace dawn_native {
void GetDefaultLimits(Limits* limits);
// Returns a copy of |limits| where all undefined values are replaced
// with their defaults.
// with their defaults. Also clamps to the defaults if the provided limits
// are worse.
Limits ReifyDefaultLimits(const Limits& limits);
// Validate that |requiredLimits| are no better than |supportedLimits|.

View File

@ -91,18 +91,20 @@ TEST_F(RequestDeviceValidationTest, HigherIsBetter) {
wgpu::SupportedLimits supportedLimits;
EXPECT_TRUE(adapter.GetLimits(reinterpret_cast<WGPUSupportedLimits*>(&supportedLimits)));
// Test below the max.
limits.limits.maxBindGroups = supportedLimits.limits.maxBindGroups - 1;
adapter.RequestDevice(
&descriptor, ExpectRequestDeviceSuccess, CheckDevice([&](wgpu::Device device) {
wgpu::SupportedLimits limits;
device.GetLimits(&limits);
// If we can support better than the default, test below the max.
if (supportedLimits.limits.maxBindGroups > 4u) {
limits.limits.maxBindGroups = supportedLimits.limits.maxBindGroups - 1;
adapter.RequestDevice(
&descriptor, ExpectRequestDeviceSuccess, CheckDevice([&](wgpu::Device device) {
wgpu::SupportedLimits limits;
device.GetLimits(&limits);
// Check we got exactly the request.
EXPECT_EQ(limits.limits.maxBindGroups, supportedLimits.limits.maxBindGroups - 1);
// Check another default limit.
EXPECT_EQ(limits.limits.maxTextureArrayLayers, 256u);
}));
// Check we got exactly the request.
EXPECT_EQ(limits.limits.maxBindGroups, supportedLimits.limits.maxBindGroups - 1);
// Check another default limit.
EXPECT_EQ(limits.limits.maxTextureArrayLayers, 256u);
}));
}
// Test the max.
limits.limits.maxBindGroups = supportedLimits.limits.maxBindGroups;
@ -120,6 +122,17 @@ TEST_F(RequestDeviceValidationTest, HigherIsBetter) {
// Test above the max.
limits.limits.maxBindGroups = supportedLimits.limits.maxBindGroups + 1;
adapter.RequestDevice(&descriptor, ExpectRequestDeviceError, nullptr);
// Test worse than the default
limits.limits.maxBindGroups = 3u;
adapter.RequestDevice(&descriptor, ExpectRequestDeviceSuccess,
CheckDevice([&](wgpu::Device device) {
wgpu::SupportedLimits limits;
device.GetLimits(&limits);
// Check we got the default.
EXPECT_EQ(limits.limits.maxBindGroups, 4u);
}));
}
// Test that requesting a device where a required limit is below the minimum value.
@ -151,19 +164,32 @@ TEST_F(RequestDeviceValidationTest, LowerIsBetter) {
EXPECT_EQ(limits.limits.maxTextureArrayLayers, 256u);
}));
// Test above the min.
limits.limits.minUniformBufferOffsetAlignment =
supportedLimits.limits.minUniformBufferOffsetAlignment * 2;
// IF we can support better than the default, test above the min.
if (supportedLimits.limits.minUniformBufferOffsetAlignment > 256u) {
limits.limits.minUniformBufferOffsetAlignment =
supportedLimits.limits.minUniformBufferOffsetAlignment * 2;
adapter.RequestDevice(
&descriptor, ExpectRequestDeviceSuccess, CheckDevice([&](wgpu::Device device) {
wgpu::SupportedLimits limits;
device.GetLimits(&limits);
// Check we got exactly the request.
EXPECT_EQ(limits.limits.minUniformBufferOffsetAlignment,
supportedLimits.limits.minUniformBufferOffsetAlignment * 2);
// Check another default limit.
EXPECT_EQ(limits.limits.maxTextureArrayLayers, 256u);
}));
}
// Test worse than the default
limits.limits.minUniformBufferOffsetAlignment = 2u * 256u;
adapter.RequestDevice(&descriptor, ExpectRequestDeviceSuccess,
CheckDevice([&](wgpu::Device device) {
wgpu::SupportedLimits limits;
device.GetLimits(&limits);
// Check we got exactly the request.
EXPECT_EQ(limits.limits.minUniformBufferOffsetAlignment,
supportedLimits.limits.minUniformBufferOffsetAlignment * 2);
// Check another default limit.
EXPECT_EQ(limits.limits.maxTextureArrayLayers, 256u);
// Check we got the default.
EXPECT_EQ(limits.limits.minUniformBufferOffsetAlignment, 256u);
}));
}