Skip to content

Commit 6e8d0bd

Browse files
committed
add tests for adapter_allowed
1 parent 0ff42e7 commit 6e8d0bd

1 file changed

Lines changed: 174 additions & 57 deletions

File tree

wgpu-core/src/instance.rs

Lines changed: 174 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use alloc::{borrow::ToOwned as _, boxed::Box, string::String, sync::Arc, vec, vec::Vec};
2+
use core::fmt;
23

34
use hashbrown::HashMap;
45
use thiserror::Error;
@@ -414,64 +415,13 @@ impl Instance {
414415
})
415416
}
416417

417-
/// This function checks that the adapter obeys WebGPU's adapter capability
418-
/// guarantees. Most of the limits are adjusted in wgpu-hal's
419-
/// `adjust_raw_limits` fn. So we only check the remaining properties here.
420-
/// See <https://gpuweb.github.io/gpuweb/#adapter-capability-guarantees>.
421418
fn adapter_allowed(&self, raw: &hal::DynExposedAdapter) -> bool {
422-
// Check "All alignment-class limits must be powers of 2."
423-
//
424-
// Even if the application has not requested strict WebGPU compliance,
425-
// non-power-of-two alignment limits are nonsensical, so don't attempt
426-
// to use such a device.
427-
let min_uniform_buffer_offset_alignment =
428-
raw.capabilities.limits.min_uniform_buffer_offset_alignment;
429-
if !min_uniform_buffer_offset_alignment.is_power_of_two() {
430-
log::error!(
431-
"Adapter {:?} min_uniform_buffer_offset_alignment limit is not a power of 2: {:?}",
432-
raw.info,
433-
min_uniform_buffer_offset_alignment
434-
);
435-
return false;
436-
}
437-
let min_storage_buffer_offset_alignment =
438-
raw.capabilities.limits.min_storage_buffer_offset_alignment;
439-
if !min_storage_buffer_offset_alignment.is_power_of_two() {
440-
log::error!(
441-
"Adapter {:?} min_storage_buffer_offset_alignment limit is not a power of 2: {:?}",
442-
raw.info,
443-
min_storage_buffer_offset_alignment
444-
);
445-
return false;
446-
}
447-
448-
// Following checks are only enabled if `STRICT_WEBGPU_COMPLIANCE` is set.
449-
if !self.flags.contains(InstanceFlags::STRICT_WEBGPU_COMPLIANCE) {
450-
return true;
451-
}
452-
453-
// Check "All supported limits must be either the default value or better."
454-
let failed_limits = check_limits(&wgt::Limits::defaults(), &raw.capabilities.limits);
455-
if !failed_limits.is_empty() {
456-
log::debug!(
457-
"Adapter {:?} is not WebGPU compliant due to limits: {:?}",
458-
raw.info,
459-
failed_limits
460-
);
461-
return false;
462-
}
463-
464-
if !raw.capabilities.downlevel.is_webgpu_compliant() {
465-
let missing_flags = wgt::DownlevelFlags::compliant() - raw.capabilities.downlevel.flags;
466-
log::debug!(
467-
"Adapter {:?} is not WebGPU compliant due to missing downlevel flags: {:?}",
468-
raw.info,
469-
missing_flags
470-
);
471-
return false;
472-
}
473-
474-
true
419+
adapter_allowed(
420+
self.flags,
421+
&raw.info,
422+
&raw.capabilities.limits,
423+
&raw.capabilities.downlevel,
424+
)
475425
}
476426

477427
pub fn enumerate_adapters(
@@ -1315,3 +1265,170 @@ impl Global {
13151265
Ok((device_id, queue_id))
13161266
}
13171267
}
1268+
1269+
/// This function checks that the adapter obeys WebGPU's adapter capability
1270+
/// guarantees. Most of the limits are adjusted in wgpu-hal's
1271+
/// `adjust_raw_limits` fn. So we only check the remaining properties here.
1272+
/// See <https://gpuweb.github.io/gpuweb/#adapter-capability-guarantees>.
1273+
fn adapter_allowed(
1274+
flags: InstanceFlags,
1275+
info: &impl fmt::Debug,
1276+
limits: &wgt::Limits,
1277+
downlevel: &wgt::DownlevelCapabilities,
1278+
) -> bool {
1279+
// Check "All alignment-class limits must be powers of 2."
1280+
//
1281+
// Even if the application has not requested strict WebGPU compliance,
1282+
// non-power-of-two alignment limits are nonsensical, so don't attempt
1283+
// to use such a device.
1284+
let min_uniform_buffer_offset_alignment = limits.min_uniform_buffer_offset_alignment;
1285+
if !min_uniform_buffer_offset_alignment.is_power_of_two() {
1286+
log::error!(
1287+
"Adapter {:?} min_uniform_buffer_offset_alignment limit is not a power of 2: {:?}",
1288+
info,
1289+
min_uniform_buffer_offset_alignment
1290+
);
1291+
return false;
1292+
}
1293+
let min_storage_buffer_offset_alignment = limits.min_storage_buffer_offset_alignment;
1294+
if !min_storage_buffer_offset_alignment.is_power_of_two() {
1295+
log::error!(
1296+
"Adapter {:?} min_storage_buffer_offset_alignment limit is not a power of 2: {:?}",
1297+
info,
1298+
min_storage_buffer_offset_alignment
1299+
);
1300+
return false;
1301+
}
1302+
1303+
// Following checks are only enabled if `STRICT_WEBGPU_COMPLIANCE` is set.
1304+
if !flags.contains(InstanceFlags::STRICT_WEBGPU_COMPLIANCE) {
1305+
return true;
1306+
}
1307+
1308+
// Check "All supported limits must be either the default value or better."
1309+
let failed_limits = check_limits(&wgt::Limits::defaults(), limits);
1310+
if !failed_limits.is_empty() {
1311+
log::debug!(
1312+
"Adapter {:?} is not WebGPU compliant due to limits: {:?}",
1313+
info,
1314+
failed_limits
1315+
);
1316+
return false;
1317+
}
1318+
1319+
if !downlevel.is_webgpu_compliant() {
1320+
let missing_flags = wgt::DownlevelFlags::compliant() - downlevel.flags;
1321+
log::debug!(
1322+
"Adapter {:?} is not WebGPU compliant due to missing downlevel flags: {:?}",
1323+
info,
1324+
missing_flags
1325+
);
1326+
return false;
1327+
}
1328+
1329+
true
1330+
}
1331+
1332+
#[cfg(test)]
1333+
mod tests {
1334+
use super::*;
1335+
1336+
fn compliant_downlevel() -> wgt::DownlevelCapabilities {
1337+
wgt::DownlevelCapabilities {
1338+
flags: wgt::DownlevelFlags::compliant(),
1339+
..Default::default()
1340+
}
1341+
}
1342+
1343+
#[test]
1344+
fn non_power_of_two_uniform_alignment_always_rejected() {
1345+
let limits = wgt::Limits {
1346+
min_uniform_buffer_offset_alignment: 3,
1347+
..wgt::Limits::defaults()
1348+
};
1349+
assert!(!adapter_allowed(
1350+
InstanceFlags::empty(),
1351+
&"",
1352+
&limits,
1353+
&compliant_downlevel()
1354+
));
1355+
assert!(!adapter_allowed(
1356+
InstanceFlags::STRICT_WEBGPU_COMPLIANCE,
1357+
&"",
1358+
&limits,
1359+
&compliant_downlevel()
1360+
));
1361+
}
1362+
1363+
#[test]
1364+
fn non_power_of_two_storage_alignment_always_rejected() {
1365+
let limits = wgt::Limits {
1366+
min_storage_buffer_offset_alignment: 96,
1367+
..wgt::Limits::defaults()
1368+
};
1369+
assert!(!adapter_allowed(
1370+
InstanceFlags::empty(),
1371+
&"",
1372+
&limits,
1373+
&compliant_downlevel()
1374+
));
1375+
assert!(!adapter_allowed(
1376+
InstanceFlags::STRICT_WEBGPU_COMPLIANCE,
1377+
&"",
1378+
&limits,
1379+
&compliant_downlevel()
1380+
));
1381+
}
1382+
1383+
#[test]
1384+
fn low_limits_allowed_without_strict_compliance() {
1385+
let limits = wgt::Limits {
1386+
max_texture_dimension_1d: 1,
1387+
..wgt::Limits::defaults()
1388+
};
1389+
assert!(adapter_allowed(
1390+
InstanceFlags::empty(),
1391+
&"",
1392+
&limits,
1393+
&wgt::DownlevelCapabilities::default()
1394+
));
1395+
}
1396+
1397+
#[test]
1398+
fn low_limits_rejected_with_strict_compliance() {
1399+
let limits = wgt::Limits {
1400+
max_texture_dimension_1d: 1,
1401+
..wgt::Limits::defaults()
1402+
};
1403+
assert!(!adapter_allowed(
1404+
InstanceFlags::STRICT_WEBGPU_COMPLIANCE,
1405+
&"",
1406+
&limits,
1407+
&compliant_downlevel()
1408+
));
1409+
}
1410+
1411+
#[test]
1412+
fn missing_downlevel_flags_rejected_with_strict_compliance() {
1413+
let downlevel = wgt::DownlevelCapabilities {
1414+
flags: wgt::DownlevelFlags::empty(),
1415+
..Default::default()
1416+
};
1417+
assert!(!adapter_allowed(
1418+
InstanceFlags::STRICT_WEBGPU_COMPLIANCE,
1419+
&"",
1420+
&wgt::Limits::defaults(),
1421+
&downlevel
1422+
));
1423+
}
1424+
1425+
#[test]
1426+
fn fully_compliant_adapter_always_allowed() {
1427+
assert!(adapter_allowed(
1428+
InstanceFlags::STRICT_WEBGPU_COMPLIANCE,
1429+
&"",
1430+
&wgt::Limits::defaults(),
1431+
&compliant_downlevel()
1432+
));
1433+
}
1434+
}

0 commit comments

Comments
 (0)