mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Make wgpu-info into a proper CLI Tool (#3856)
This commit is contained in:
parent
acb7712c5a
commit
e6be20f72e
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -1883,6 +1883,12 @@ dependencies = [
|
|||||||
"indexmap",
|
"indexmap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pico-args"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -3188,9 +3194,14 @@ dependencies = [
|
|||||||
name = "wgpu-info"
|
name = "wgpu-info"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"bitflags 2.3.2",
|
"bitflags 2.3.2",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"pico-args",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
|
"wgpu-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@ -55,6 +55,7 @@ rev = "76003dc0035d53a474d366dcdf49d2e4d12e921f"
|
|||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
arrayvec = "0.7"
|
arrayvec = "0.7"
|
||||||
async-executor = "1"
|
async-executor = "1"
|
||||||
bitflags = "2"
|
bitflags = "2"
|
||||||
@ -82,6 +83,7 @@ noise = { version = "0.7", default-features = false }
|
|||||||
obj = "0.10"
|
obj = "0.10"
|
||||||
# parking_lot 0.12 switches from `winapi` to `windows`; permit either
|
# parking_lot 0.12 switches from `winapi` to `windows`; permit either
|
||||||
parking_lot = ">=0.11,<0.13"
|
parking_lot = ">=0.11,<0.13"
|
||||||
|
pico-args = { version = "0.5.0", features = ["eq-separator", "short-space-opt", "combined-flags"] }
|
||||||
png = "0.17.9"
|
png = "0.17.9"
|
||||||
pollster = "0.2"
|
pollster = "0.2"
|
||||||
profiling = { version = "1", default-features = false }
|
profiling = { version = "1", default-features = false }
|
||||||
|
|||||||
@ -3,14 +3,18 @@ name = "wgpu-info"
|
|||||||
version.workspace = true
|
version.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
description = "Adapter information and per-adapter test program"
|
description = "A tool to print and process information about available wgpu adapters."
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
publish = false
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
bitflags.workspace = true
|
bitflags.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
|
pico-args.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
wgpu.workspace = true
|
wgpu.workspace = true
|
||||||
|
wgpu-types = { workspace = true, features = ["trace", "replay"] }
|
||||||
|
|||||||
90
wgpu-info/src/cli.rs
Normal file
90
wgpu-info/src/cli.rs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
use std::{io, process::exit};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
|
const HELP: &str = "\
|
||||||
|
Usage: wgpu-info [--input <PATH>] [--output <PATH>] [--json]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Print this help message.
|
||||||
|
-i, --input <PATH> Source to read JSON report from. (\"-\" reads from stdin)
|
||||||
|
-o, --output <PATH> Destination to write output to. (\"-\" writes to stdout)
|
||||||
|
-j, --json Output JSON information instead of human-readable text.
|
||||||
|
";
|
||||||
|
|
||||||
|
fn exit_with_help() {
|
||||||
|
eprintln!("{HELP}");
|
||||||
|
exit(101);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() -> anyhow::Result<()> {
|
||||||
|
let mut args = pico_args::Arguments::from_env();
|
||||||
|
// Check for help flag before parsing arguments
|
||||||
|
let help = args.contains(["-h", "--help"]);
|
||||||
|
|
||||||
|
if help {
|
||||||
|
exit_with_help();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Argument parsing
|
||||||
|
let input_path: Option<String> = args.opt_value_from_str(["-i", "--input"]).unwrap();
|
||||||
|
let output_path: Option<String> = args.opt_value_from_str(["-o", "--output"]).unwrap();
|
||||||
|
let json = args.contains(["-j", "--json"]);
|
||||||
|
|
||||||
|
let remaining = args.finish();
|
||||||
|
if !remaining.is_empty() {
|
||||||
|
eprint!("Unknown argument(s): ");
|
||||||
|
for arg in remaining {
|
||||||
|
eprint!("\"{}\" ", arg.to_string_lossy());
|
||||||
|
}
|
||||||
|
eprint!("\n\n");
|
||||||
|
exit_with_help();
|
||||||
|
}
|
||||||
|
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
|
// Generate or load report
|
||||||
|
let report = match input_path.as_deref() {
|
||||||
|
// Pull report from stdin or file
|
||||||
|
Some(path) => {
|
||||||
|
let json = if "-" == path {
|
||||||
|
std::io::read_to_string(std::io::stdin()).context("Could not read from stdin")?
|
||||||
|
} else {
|
||||||
|
std::fs::read_to_string(path)
|
||||||
|
.with_context(|| format!("Could not read from file \"{path}\""))?
|
||||||
|
};
|
||||||
|
crate::report::GpuReport::from_json(&json).context("Could not parse JSON")?
|
||||||
|
}
|
||||||
|
// Generate the report natively
|
||||||
|
None => crate::report::GpuReport::generate(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup output writer
|
||||||
|
let mut file_handle;
|
||||||
|
let mut std_handle;
|
||||||
|
let output: &mut dyn io::Write = match output_path.as_deref() {
|
||||||
|
None | Some("-") => {
|
||||||
|
std_handle = io::stdout();
|
||||||
|
&mut std_handle
|
||||||
|
}
|
||||||
|
Some(path) => {
|
||||||
|
file_handle = std::fs::File::create(path)
|
||||||
|
.with_context(|| format!("Could not create file \"{path}\""))?;
|
||||||
|
&mut file_handle
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut output = io::BufWriter::new(output);
|
||||||
|
|
||||||
|
let output_name = output_path.as_deref().unwrap_or("stdout");
|
||||||
|
|
||||||
|
if json {
|
||||||
|
report
|
||||||
|
.into_json(output)
|
||||||
|
.with_context(|| format!("Failed to write to output: {output_name}"))?;
|
||||||
|
} else {
|
||||||
|
crate::human::print_adapters(&mut output, &report)
|
||||||
|
.with_context(|| format!("Failed to write to output: {output_name}"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
240
wgpu-info/src/human.rs
Normal file
240
wgpu-info/src/human.rs
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
use std::io;
|
||||||
|
|
||||||
|
use bitflags::Flags;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
report::{AdapterReport, GpuReport},
|
||||||
|
texture::{self, TEXTURE_FORMAT_LIST},
|
||||||
|
};
|
||||||
|
|
||||||
|
trait FlagsExt: Flags {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
self.iter_names().next().unwrap().0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn valid_bits() -> std::iter::Enumerate<bitflags::iter::Iter<Self>> {
|
||||||
|
Self::all().iter().enumerate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_debug_print_width() -> usize {
|
||||||
|
let mut width = 0;
|
||||||
|
for bit in Self::all().iter() {
|
||||||
|
width = width.max(bit.name().len());
|
||||||
|
}
|
||||||
|
width
|
||||||
|
}
|
||||||
|
|
||||||
|
fn println_table_header(output: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
write!(output, "┌─")?;
|
||||||
|
for (i, bit) in Self::valid_bits() {
|
||||||
|
if i != 0 {
|
||||||
|
write!(output, "─┬─")?;
|
||||||
|
}
|
||||||
|
let length = bit.name().len();
|
||||||
|
write!(output, "{}", "─".repeat(length))?;
|
||||||
|
}
|
||||||
|
writeln!(output, "─┐")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn println_table_footer(output: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
write!(output, "└─")?;
|
||||||
|
for (i, bit) in Self::valid_bits() {
|
||||||
|
if i != 0 {
|
||||||
|
write!(output, "─┴─")?;
|
||||||
|
}
|
||||||
|
let length = bit.name().len();
|
||||||
|
write!(output, "{}", "─".repeat(length))?;
|
||||||
|
}
|
||||||
|
writeln!(output, "─┘")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> FlagsExt for T where T: Flags {}
|
||||||
|
|
||||||
|
// Lets keep these print statements on one line
|
||||||
|
#[rustfmt::skip]
|
||||||
|
fn print_adapter(output: &mut impl io::Write, report: &AdapterReport, idx: usize) -> io::Result<()> {
|
||||||
|
let AdapterReport {
|
||||||
|
info,
|
||||||
|
features,
|
||||||
|
limits,
|
||||||
|
downlevel_caps:
|
||||||
|
downlevel,
|
||||||
|
texture_format_features
|
||||||
|
} = &report;
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// Adapter Info //
|
||||||
|
//////////////////
|
||||||
|
|
||||||
|
writeln!(output, "Adapter {idx}:")?;
|
||||||
|
writeln!(output, "\t Backend: {:?}", info.backend)?;
|
||||||
|
writeln!(output, "\t Name: {:?}", info.name)?;
|
||||||
|
writeln!(output, "\t VendorID: {:?}", info.vendor)?;
|
||||||
|
writeln!(output, "\t DeviceID: {:?}", info.device)?;
|
||||||
|
writeln!(output, "\t Type: {:?}", info.device_type)?;
|
||||||
|
writeln!(output, "\t Driver: {:?}", info.driver)?;
|
||||||
|
writeln!(output, "\tDriverInfo: {:?}", info.driver_info)?;
|
||||||
|
writeln!(output, "\t Compliant: {:?}", downlevel.is_webgpu_compliant())?;
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// Features //
|
||||||
|
//////////////
|
||||||
|
|
||||||
|
writeln!(output, "\tFeatures:")?;
|
||||||
|
let max_feature_flag_width = wgpu::Features::max_debug_print_width();
|
||||||
|
for bit in wgpu::Features::all().iter() {
|
||||||
|
writeln!(output, "\t\t{:>width$}: {}", bit.name(), features.contains(bit), width = max_feature_flag_width)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////
|
||||||
|
// Limits //
|
||||||
|
////////////
|
||||||
|
|
||||||
|
writeln!(output, "\tLimits:")?;
|
||||||
|
let wgpu::Limits {
|
||||||
|
max_texture_dimension_1d,
|
||||||
|
max_texture_dimension_2d,
|
||||||
|
max_texture_dimension_3d,
|
||||||
|
max_texture_array_layers,
|
||||||
|
max_bind_groups,
|
||||||
|
max_bindings_per_bind_group,
|
||||||
|
max_dynamic_uniform_buffers_per_pipeline_layout,
|
||||||
|
max_dynamic_storage_buffers_per_pipeline_layout,
|
||||||
|
max_sampled_textures_per_shader_stage,
|
||||||
|
max_samplers_per_shader_stage,
|
||||||
|
max_storage_buffers_per_shader_stage,
|
||||||
|
max_storage_textures_per_shader_stage,
|
||||||
|
max_uniform_buffers_per_shader_stage,
|
||||||
|
max_uniform_buffer_binding_size,
|
||||||
|
max_storage_buffer_binding_size,
|
||||||
|
max_buffer_size,
|
||||||
|
max_vertex_buffers,
|
||||||
|
max_vertex_attributes,
|
||||||
|
max_vertex_buffer_array_stride,
|
||||||
|
max_push_constant_size,
|
||||||
|
min_uniform_buffer_offset_alignment,
|
||||||
|
min_storage_buffer_offset_alignment,
|
||||||
|
max_inter_stage_shader_components,
|
||||||
|
max_compute_workgroup_storage_size,
|
||||||
|
max_compute_invocations_per_workgroup,
|
||||||
|
max_compute_workgroup_size_x,
|
||||||
|
max_compute_workgroup_size_y,
|
||||||
|
max_compute_workgroup_size_z,
|
||||||
|
max_compute_workgroups_per_dimension,
|
||||||
|
} = limits;
|
||||||
|
writeln!(output, "\t\t Max Texture Dimension 1d: {max_texture_dimension_1d}")?;
|
||||||
|
writeln!(output, "\t\t Max Texture Dimension 2d: {max_texture_dimension_2d}")?;
|
||||||
|
writeln!(output, "\t\t Max Texture Dimension 3d: {max_texture_dimension_3d}")?;
|
||||||
|
writeln!(output, "\t\t Max Texture Array Layers: {max_texture_array_layers}")?;
|
||||||
|
writeln!(output, "\t\t Max Bind Groups: {max_bind_groups}")?;
|
||||||
|
writeln!(output, "\t\t Max Bindings Per Bind Group: {max_bindings_per_bind_group}")?;
|
||||||
|
writeln!(output, "\t\t Max Dynamic Uniform Buffers Per Pipeline Layout: {max_dynamic_uniform_buffers_per_pipeline_layout}")?;
|
||||||
|
writeln!(output, "\t\t Max Dynamic Storage Buffers Per Pipeline Layout: {max_dynamic_storage_buffers_per_pipeline_layout}")?;
|
||||||
|
writeln!(output, "\t\t Max Sampled Textures Per Shader Stage: {max_sampled_textures_per_shader_stage}")?;
|
||||||
|
writeln!(output, "\t\t Max Samplers Per Shader Stage: {max_samplers_per_shader_stage}")?;
|
||||||
|
writeln!(output, "\t\t Max Storage Buffers Per Shader Stage: {max_storage_buffers_per_shader_stage}")?;
|
||||||
|
writeln!(output, "\t\t Max Storage Textures Per Shader Stage: {max_storage_textures_per_shader_stage}")?;
|
||||||
|
writeln!(output, "\t\t Max Uniform Buffers Per Shader Stage: {max_uniform_buffers_per_shader_stage}")?;
|
||||||
|
writeln!(output, "\t\t Max Uniform Buffer Binding Size: {max_uniform_buffer_binding_size}")?;
|
||||||
|
writeln!(output, "\t\t Max Storage Buffer Binding Size: {max_storage_buffer_binding_size}")?;
|
||||||
|
writeln!(output, "\t\t Max Buffer Size: {max_buffer_size}")?;
|
||||||
|
writeln!(output, "\t\t Max Vertex Buffers: {max_vertex_buffers}")?;
|
||||||
|
writeln!(output, "\t\t Max Vertex Attributes: {max_vertex_attributes}")?;
|
||||||
|
writeln!(output, "\t\t Max Vertex Buffer Array Stride: {max_vertex_buffer_array_stride}")?;
|
||||||
|
writeln!(output, "\t\t Max Push Constant Size: {max_push_constant_size}")?;
|
||||||
|
writeln!(output, "\t\t Min Uniform Buffer Offset Alignment: {min_uniform_buffer_offset_alignment}")?;
|
||||||
|
writeln!(output, "\t\t Min Storage Buffer Offset Alignment: {min_storage_buffer_offset_alignment}")?;
|
||||||
|
writeln!(output, "\t\t Max Inter-Stage Shader Component: {max_inter_stage_shader_components}")?;
|
||||||
|
writeln!(output, "\t\t Max Compute Workgroup Storage Size: {max_compute_workgroup_storage_size}")?;
|
||||||
|
writeln!(output, "\t\t Max Compute Invocations Per Workgroup: {max_compute_invocations_per_workgroup}")?;
|
||||||
|
writeln!(output, "\t\t Max Compute Workgroup Size X: {max_compute_workgroup_size_x}")?;
|
||||||
|
writeln!(output, "\t\t Max Compute Workgroup Size Y: {max_compute_workgroup_size_y}")?;
|
||||||
|
writeln!(output, "\t\t Max Compute Workgroup Size Z: {max_compute_workgroup_size_z}")?;
|
||||||
|
writeln!(output, "\t\t Max Compute Workgroups Per Dimension: {max_compute_workgroups_per_dimension}")?;
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// Downlevel Properties //
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
writeln!(output, "\tDownlevel Properties:")?;
|
||||||
|
let wgpu::DownlevelCapabilities {
|
||||||
|
shader_model,
|
||||||
|
limits: _,
|
||||||
|
flags,
|
||||||
|
} = downlevel;
|
||||||
|
writeln!(output, "\t\t Shader Model: {shader_model:?}")?;
|
||||||
|
let max_downlevel_flag_width = wgpu::DownlevelFlags::max_debug_print_width();
|
||||||
|
for bit in wgpu::DownlevelFlags::all().iter() {
|
||||||
|
writeln!(output, "\t\t{:>width$}: {}", bit.name(), flags.contains(bit), width = max_downlevel_flag_width)?;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
// Texture Usages //
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
let max_format_name_size = texture::max_texture_format_string_size();
|
||||||
|
let texture_format_whitespace = " ".repeat(max_format_name_size);
|
||||||
|
|
||||||
|
writeln!(output, "\n\t Texture Format Allowed Usages:")?;
|
||||||
|
|
||||||
|
write!(output, "\t\t {texture_format_whitespace}")?;
|
||||||
|
wgpu::TextureUsages::println_table_header(output)?;
|
||||||
|
for format in TEXTURE_FORMAT_LIST {
|
||||||
|
let features = texture_format_features[&format];
|
||||||
|
let format_name = texture::texture_format_name(format);
|
||||||
|
write!(output, "\t\t{format_name:>0$}", max_format_name_size)?;
|
||||||
|
for bit in wgpu::TextureUsages::all().iter() {
|
||||||
|
write!(output, " │ ")?;
|
||||||
|
if features.allowed_usages.contains(bit) {
|
||||||
|
write!(output, "{}", bit.name())?;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let length = bit.name().len();
|
||||||
|
write!(output, "{}", " ".repeat(length))?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
writeln!(output, " │")?;
|
||||||
|
}
|
||||||
|
write!(output, "\t\t {texture_format_whitespace}")?;
|
||||||
|
wgpu::TextureUsages::println_table_footer(output)?;
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// Texture Format Flags //
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
writeln!(output, "\n\t Texture Format Flags:")?;
|
||||||
|
|
||||||
|
write!(output, "\t\t {texture_format_whitespace}")?;
|
||||||
|
wgpu::TextureFormatFeatureFlags::println_table_header(output)?;
|
||||||
|
|
||||||
|
for format in TEXTURE_FORMAT_LIST {
|
||||||
|
let features = texture_format_features[&format];
|
||||||
|
let format_name = texture::texture_format_name(format);
|
||||||
|
|
||||||
|
write!(output, "\t\t{format_name:>0$}", max_format_name_size)?;
|
||||||
|
for bit in wgpu::TextureFormatFeatureFlags::all().iter() {
|
||||||
|
write!(output, " │ ")?;
|
||||||
|
if features.flags.contains(bit) {
|
||||||
|
write!(output, "{}", bit.name())?;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let length = bit.name().len();
|
||||||
|
write!(output, "{}", " ".repeat(length))?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
writeln!(output, " │")?;
|
||||||
|
}
|
||||||
|
write!(output, "\t\t {texture_format_whitespace}")?;
|
||||||
|
wgpu::TextureFormatFeatureFlags::println_table_footer(output)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_adapters(output: &mut impl io::Write, report: &GpuReport) -> io::Result<()> {
|
||||||
|
for (idx, adapter) in report.devices.iter().enumerate() {
|
||||||
|
print_adapter(output, adapter, idx)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -1,435 +1,16 @@
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
mod inner {
|
mod cli;
|
||||||
use std::{
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
process::{exit, Command},
|
mod human;
|
||||||
time::Instant,
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
};
|
mod report;
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
mod texture;
|
||||||
|
|
||||||
use bitflags::Flags;
|
fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
// Lets keep these on one line
|
|
||||||
#[rustfmt::skip]
|
|
||||||
const TEXTURE_FORMAT_LIST: [wgpu::TextureFormat; 114] = [
|
|
||||||
wgpu::TextureFormat::R8Unorm,
|
|
||||||
wgpu::TextureFormat::R8Snorm,
|
|
||||||
wgpu::TextureFormat::R8Uint,
|
|
||||||
wgpu::TextureFormat::R8Sint,
|
|
||||||
wgpu::TextureFormat::R16Uint,
|
|
||||||
wgpu::TextureFormat::R16Sint,
|
|
||||||
wgpu::TextureFormat::R16Unorm,
|
|
||||||
wgpu::TextureFormat::R16Snorm,
|
|
||||||
wgpu::TextureFormat::R16Float,
|
|
||||||
wgpu::TextureFormat::Rg8Unorm,
|
|
||||||
wgpu::TextureFormat::Rg8Snorm,
|
|
||||||
wgpu::TextureFormat::Rg8Uint,
|
|
||||||
wgpu::TextureFormat::Rg8Sint,
|
|
||||||
wgpu::TextureFormat::R32Uint,
|
|
||||||
wgpu::TextureFormat::R32Sint,
|
|
||||||
wgpu::TextureFormat::R32Float,
|
|
||||||
wgpu::TextureFormat::Rg16Uint,
|
|
||||||
wgpu::TextureFormat::Rg16Sint,
|
|
||||||
wgpu::TextureFormat::Rg16Unorm,
|
|
||||||
wgpu::TextureFormat::Rg16Snorm,
|
|
||||||
wgpu::TextureFormat::Rg16Float,
|
|
||||||
wgpu::TextureFormat::Rgba8Unorm,
|
|
||||||
wgpu::TextureFormat::Rgba8UnormSrgb,
|
|
||||||
wgpu::TextureFormat::Rgba8Snorm,
|
|
||||||
wgpu::TextureFormat::Rgba8Uint,
|
|
||||||
wgpu::TextureFormat::Rgba8Sint,
|
|
||||||
wgpu::TextureFormat::Bgra8Unorm,
|
|
||||||
wgpu::TextureFormat::Bgra8UnormSrgb,
|
|
||||||
wgpu::TextureFormat::Rgb10a2Unorm,
|
|
||||||
wgpu::TextureFormat::Rg11b10Float,
|
|
||||||
wgpu::TextureFormat::Rg32Uint,
|
|
||||||
wgpu::TextureFormat::Rg32Sint,
|
|
||||||
wgpu::TextureFormat::Rg32Float,
|
|
||||||
wgpu::TextureFormat::Rgba16Uint,
|
|
||||||
wgpu::TextureFormat::Rgba16Sint,
|
|
||||||
wgpu::TextureFormat::Rgba16Unorm,
|
|
||||||
wgpu::TextureFormat::Rgba16Snorm,
|
|
||||||
wgpu::TextureFormat::Rgba16Float,
|
|
||||||
wgpu::TextureFormat::Rgba32Uint,
|
|
||||||
wgpu::TextureFormat::Rgba32Sint,
|
|
||||||
wgpu::TextureFormat::Rgba32Float,
|
|
||||||
wgpu::TextureFormat::Stencil8,
|
|
||||||
wgpu::TextureFormat::Depth16Unorm,
|
|
||||||
wgpu::TextureFormat::Depth32Float,
|
|
||||||
wgpu::TextureFormat::Depth32FloatStencil8,
|
|
||||||
wgpu::TextureFormat::Depth24Plus,
|
|
||||||
wgpu::TextureFormat::Depth24PlusStencil8,
|
|
||||||
wgpu::TextureFormat::Rgb9e5Ufloat,
|
|
||||||
wgpu::TextureFormat::Bc1RgbaUnorm,
|
|
||||||
wgpu::TextureFormat::Bc1RgbaUnormSrgb,
|
|
||||||
wgpu::TextureFormat::Bc2RgbaUnorm,
|
|
||||||
wgpu::TextureFormat::Bc2RgbaUnormSrgb,
|
|
||||||
wgpu::TextureFormat::Bc3RgbaUnorm,
|
|
||||||
wgpu::TextureFormat::Bc3RgbaUnormSrgb,
|
|
||||||
wgpu::TextureFormat::Bc4RUnorm,
|
|
||||||
wgpu::TextureFormat::Bc4RSnorm,
|
|
||||||
wgpu::TextureFormat::Bc5RgUnorm,
|
|
||||||
wgpu::TextureFormat::Bc5RgSnorm,
|
|
||||||
wgpu::TextureFormat::Bc6hRgbUfloat,
|
|
||||||
wgpu::TextureFormat::Bc6hRgbFloat,
|
|
||||||
wgpu::TextureFormat::Bc7RgbaUnorm,
|
|
||||||
wgpu::TextureFormat::Bc7RgbaUnormSrgb,
|
|
||||||
wgpu::TextureFormat::Etc2Rgb8Unorm,
|
|
||||||
wgpu::TextureFormat::Etc2Rgb8UnormSrgb,
|
|
||||||
wgpu::TextureFormat::Etc2Rgb8A1Unorm,
|
|
||||||
wgpu::TextureFormat::Etc2Rgb8A1UnormSrgb,
|
|
||||||
wgpu::TextureFormat::Etc2Rgba8Unorm,
|
|
||||||
wgpu::TextureFormat::Etc2Rgba8UnormSrgb,
|
|
||||||
wgpu::TextureFormat::EacR11Unorm,
|
|
||||||
wgpu::TextureFormat::EacR11Snorm,
|
|
||||||
wgpu::TextureFormat::EacRg11Unorm,
|
|
||||||
wgpu::TextureFormat::EacRg11Snorm,
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::Unorm },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::UnormSrgb },
|
|
||||||
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::Hdr },
|
|
||||||
];
|
|
||||||
|
|
||||||
// Lets keep these on one line
|
|
||||||
#[rustfmt::skip]
|
|
||||||
fn print_info_from_adapter(adapter: &wgpu::Adapter, idx: usize) {
|
|
||||||
let info = adapter.get_info();
|
|
||||||
let downlevel = adapter.get_downlevel_capabilities();
|
|
||||||
let features = adapter.features();
|
|
||||||
let limits = adapter.limits();
|
|
||||||
|
|
||||||
//////////////////
|
|
||||||
// Adapter Info //
|
|
||||||
//////////////////
|
|
||||||
|
|
||||||
println!("Adapter {idx}:");
|
|
||||||
println!("\t Backend: {:?}", info.backend);
|
|
||||||
println!("\t Name: {:?}", info.name);
|
|
||||||
println!("\t VendorID: {:?}", info.vendor);
|
|
||||||
println!("\t DeviceID: {:?}", info.device);
|
|
||||||
println!("\t Type: {:?}", info.device_type);
|
|
||||||
println!("\t Driver: {:?}", info.driver);
|
|
||||||
println!("\tDriverInfo: {:?}", info.driver_info);
|
|
||||||
println!("\t Compliant: {:?}", downlevel.is_webgpu_compliant());
|
|
||||||
|
|
||||||
//////////////
|
|
||||||
// Features //
|
|
||||||
//////////////
|
|
||||||
|
|
||||||
println!("\tFeatures:");
|
|
||||||
let max_feature_flag_width = wgpu::Features::max_debug_print_width();
|
|
||||||
for bit in wgpu::Features::all().iter() {
|
|
||||||
println!("\t\t{:>width$}: {}", bit.name(), features.contains(bit), width = max_feature_flag_width);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////
|
|
||||||
// Limits //
|
|
||||||
////////////
|
|
||||||
|
|
||||||
println!("\tLimits:");
|
|
||||||
let wgpu::Limits {
|
|
||||||
max_texture_dimension_1d,
|
|
||||||
max_texture_dimension_2d,
|
|
||||||
max_texture_dimension_3d,
|
|
||||||
max_texture_array_layers,
|
|
||||||
max_bind_groups,
|
|
||||||
max_bindings_per_bind_group,
|
|
||||||
max_dynamic_uniform_buffers_per_pipeline_layout,
|
|
||||||
max_dynamic_storage_buffers_per_pipeline_layout,
|
|
||||||
max_sampled_textures_per_shader_stage,
|
|
||||||
max_samplers_per_shader_stage,
|
|
||||||
max_storage_buffers_per_shader_stage,
|
|
||||||
max_storage_textures_per_shader_stage,
|
|
||||||
max_uniform_buffers_per_shader_stage,
|
|
||||||
max_uniform_buffer_binding_size,
|
|
||||||
max_storage_buffer_binding_size,
|
|
||||||
max_buffer_size,
|
|
||||||
max_vertex_buffers,
|
|
||||||
max_vertex_attributes,
|
|
||||||
max_vertex_buffer_array_stride,
|
|
||||||
max_push_constant_size,
|
|
||||||
min_uniform_buffer_offset_alignment,
|
|
||||||
min_storage_buffer_offset_alignment,
|
|
||||||
max_inter_stage_shader_components,
|
|
||||||
max_compute_workgroup_storage_size,
|
|
||||||
max_compute_invocations_per_workgroup,
|
|
||||||
max_compute_workgroup_size_x,
|
|
||||||
max_compute_workgroup_size_y,
|
|
||||||
max_compute_workgroup_size_z,
|
|
||||||
max_compute_workgroups_per_dimension,
|
|
||||||
} = limits;
|
|
||||||
println!("\t\t Max Texture Dimension 1d: {max_texture_dimension_1d}");
|
|
||||||
println!("\t\t Max Texture Dimension 2d: {max_texture_dimension_2d}");
|
|
||||||
println!("\t\t Max Texture Dimension 3d: {max_texture_dimension_3d}");
|
|
||||||
println!("\t\t Max Texture Array Layers: {max_texture_array_layers}");
|
|
||||||
println!("\t\t Max Bind Groups: {max_bind_groups}");
|
|
||||||
println!("\t\t Max Bindings Per Bind Group: {max_bindings_per_bind_group}");
|
|
||||||
println!("\t\t Max Dynamic Uniform Buffers Per Pipeline Layout: {max_dynamic_uniform_buffers_per_pipeline_layout}");
|
|
||||||
println!("\t\t Max Dynamic Storage Buffers Per Pipeline Layout: {max_dynamic_storage_buffers_per_pipeline_layout}");
|
|
||||||
println!("\t\t Max Sampled Textures Per Shader Stage: {max_sampled_textures_per_shader_stage}");
|
|
||||||
println!("\t\t Max Samplers Per Shader Stage: {max_samplers_per_shader_stage}");
|
|
||||||
println!("\t\t Max Storage Buffers Per Shader Stage: {max_storage_buffers_per_shader_stage}");
|
|
||||||
println!("\t\t Max Storage Textures Per Shader Stage: {max_storage_textures_per_shader_stage}");
|
|
||||||
println!("\t\t Max Uniform Buffers Per Shader Stage: {max_uniform_buffers_per_shader_stage}");
|
|
||||||
println!("\t\t Max Uniform Buffer Binding Size: {max_uniform_buffer_binding_size}");
|
|
||||||
println!("\t\t Max Storage Buffer Binding Size: {max_storage_buffer_binding_size}");
|
|
||||||
println!("\t\t Max Buffer Size: {max_buffer_size}");
|
|
||||||
println!("\t\t Max Vertex Buffers: {max_vertex_buffers}");
|
|
||||||
println!("\t\t Max Vertex Attributes: {max_vertex_attributes}");
|
|
||||||
println!("\t\t Max Vertex Buffer Array Stride: {max_vertex_buffer_array_stride}");
|
|
||||||
println!("\t\t Max Push Constant Size: {max_push_constant_size}");
|
|
||||||
println!("\t\t Min Uniform Buffer Offset Alignment: {min_uniform_buffer_offset_alignment}");
|
|
||||||
println!("\t\t Min Storage Buffer Offset Alignment: {min_storage_buffer_offset_alignment}");
|
|
||||||
println!("\t\t Max Inter-Stage Shader Component: {max_inter_stage_shader_components}");
|
|
||||||
println!("\t\t Max Compute Workgroup Storage Size: {max_compute_workgroup_storage_size}");
|
|
||||||
println!("\t\t Max Compute Invocations Per Workgroup: {max_compute_invocations_per_workgroup}");
|
|
||||||
println!("\t\t Max Compute Workgroup Size X: {max_compute_workgroup_size_x}");
|
|
||||||
println!("\t\t Max Compute Workgroup Size Y: {max_compute_workgroup_size_y}");
|
|
||||||
println!("\t\t Max Compute Workgroup Size Z: {max_compute_workgroup_size_z}");
|
|
||||||
println!("\t\t Max Compute Workgroups Per Dimension: {max_compute_workgroups_per_dimension}");
|
|
||||||
|
|
||||||
//////////////////////////
|
|
||||||
// Downlevel Properties //
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
println!("\tDownlevel Properties:");
|
|
||||||
let wgpu::DownlevelCapabilities {
|
|
||||||
shader_model,
|
|
||||||
limits: _,
|
|
||||||
flags,
|
|
||||||
} = downlevel;
|
|
||||||
println!("\t\t Shader Model: {shader_model:?}");
|
|
||||||
let max_downlevel_flag_width = wgpu::DownlevelFlags::max_debug_print_width();
|
|
||||||
for bit in wgpu::DownlevelFlags::all().iter() {
|
|
||||||
println!("\t\t{:>width$}: {}", bit.name(), flags.contains(bit), width = max_downlevel_flag_width);
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////
|
|
||||||
// Texture Usages //
|
|
||||||
////////////////////
|
|
||||||
|
|
||||||
let max_format_name_size = max_texture_format_name_size();
|
|
||||||
let texture_format_whitespace = " ".repeat(max_format_name_size);
|
|
||||||
|
|
||||||
println!("\n\t Texture Format Allowed Usages:");
|
|
||||||
|
|
||||||
print!("\t\t {texture_format_whitespace}");
|
|
||||||
wgpu::TextureUsages::println_table_header();
|
|
||||||
for format in TEXTURE_FORMAT_LIST {
|
|
||||||
let features = adapter.get_texture_format_features(format);
|
|
||||||
let format_name = texture_format_name(format);
|
|
||||||
print!("\t\t{format_name:>0$}", max_format_name_size);
|
|
||||||
for bit in wgpu::TextureUsages::all().iter() {
|
|
||||||
print!(" │ ");
|
|
||||||
if features.allowed_usages.contains(bit) {
|
|
||||||
print!("{}", bit.name());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let length = bit.name().len();
|
|
||||||
print!("{}", " ".repeat(length))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!(" │");
|
|
||||||
}
|
|
||||||
print!("\t\t {texture_format_whitespace}");
|
|
||||||
wgpu::TextureUsages::println_table_footer();
|
|
||||||
|
|
||||||
//////////////////////////
|
|
||||||
// Texture Format Flags //
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
println!("\n\t Texture Format Flags:");
|
|
||||||
|
|
||||||
print!("\t\t {texture_format_whitespace}");
|
|
||||||
wgpu::TextureFormatFeatureFlags::println_table_header();
|
|
||||||
|
|
||||||
for format in TEXTURE_FORMAT_LIST {
|
|
||||||
let features = adapter.get_texture_format_features(format);
|
|
||||||
let format_name = texture_format_name(format);
|
|
||||||
|
|
||||||
print!("\t\t{format_name:>0$}", max_format_name_size);
|
|
||||||
for bit in wgpu::TextureFormatFeatureFlags::all().iter() {
|
|
||||||
print!(" │ ");
|
|
||||||
if features.flags.contains(bit) {
|
|
||||||
print!("{}", bit.name());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let length = bit.name().len();
|
|
||||||
print!("{}", " ".repeat(length))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!(" │");
|
|
||||||
}
|
|
||||||
print!("\t\t {texture_format_whitespace}");
|
|
||||||
wgpu::TextureFormatFeatureFlags::println_table_footer();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
env_logger::init();
|
|
||||||
let args: Vec<_> = std::env::args().skip(1).collect();
|
|
||||||
|
|
||||||
let instance = wgpu::Instance::default();
|
|
||||||
let adapters: Vec<_> = instance.enumerate_adapters(wgpu::Backends::all()).collect();
|
|
||||||
let adapter_count = adapters.len();
|
|
||||||
|
|
||||||
if args.is_empty() {
|
|
||||||
for (idx, adapter) in adapters.into_iter().enumerate() {
|
|
||||||
print_info_from_adapter(&adapter, idx)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let all_start = Instant::now();
|
|
||||||
|
|
||||||
for (idx, adapter) in adapters.into_iter().enumerate() {
|
|
||||||
let adapter_start_time = Instant::now();
|
|
||||||
let idx = idx + 1;
|
|
||||||
let info = adapter.get_info();
|
|
||||||
println!(
|
|
||||||
"=========== TESTING {} on {:?} ({} of {}) ===========",
|
|
||||||
info.name, info.backend, idx, adapter_count
|
|
||||||
);
|
|
||||||
let exit_status = Command::new(&args[0])
|
|
||||||
.args(&args[1..])
|
|
||||||
.env("WGPU_ADAPTER_NAME", &info.name)
|
|
||||||
.env(
|
|
||||||
"WGPU_BACKEND",
|
|
||||||
match info.backend {
|
|
||||||
wgpu::Backend::Empty => unreachable!(),
|
|
||||||
wgpu::Backend::Vulkan => "vulkan",
|
|
||||||
wgpu::Backend::Metal => "metal",
|
|
||||||
wgpu::Backend::Dx12 => "dx12",
|
|
||||||
wgpu::Backend::Dx11 => "dx11",
|
|
||||||
wgpu::Backend::Gl => "gl",
|
|
||||||
wgpu::Backend::BrowserWebGpu => "webgpu",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.spawn()
|
|
||||||
.unwrap()
|
|
||||||
.wait()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let adapter_time = adapter_start_time.elapsed().as_secs_f32();
|
|
||||||
|
|
||||||
if exit_status.success() {
|
|
||||||
println!(
|
|
||||||
"=========== PASSED! {} on {:?} ({} of {}) in {:.3}s ===========",
|
|
||||||
info.name, info.backend, idx, adapter_count, adapter_time
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
println!(
|
|
||||||
"=========== FAILED! {} on {:?} ({} of {}) in {:.3}s ===========",
|
|
||||||
info.name, info.backend, idx, adapter_count, adapter_time
|
|
||||||
);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let all_time = all_start.elapsed().as_secs_f32();
|
|
||||||
|
|
||||||
println!("=========== {adapter_count} adapters PASSED in {all_time:.3}s ===========");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait FlagsExt: Flags {
|
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
self.iter_names().next().unwrap().0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn valid_bits() -> std::iter::Enumerate<bitflags::iter::Iter<Self>> {
|
|
||||||
Self::all().iter().enumerate()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn max_debug_print_width() -> usize {
|
|
||||||
let mut width = 0;
|
|
||||||
for bit in Self::all().iter() {
|
|
||||||
width = width.max(bit.name().len());
|
|
||||||
}
|
|
||||||
width
|
|
||||||
}
|
|
||||||
|
|
||||||
fn println_table_header() {
|
|
||||||
print!("┌─");
|
|
||||||
for (i, bit) in Self::valid_bits() {
|
|
||||||
if i != 0 {
|
|
||||||
print!("─┬─");
|
|
||||||
}
|
|
||||||
let length = bit.name().len();
|
|
||||||
print!("{}", "─".repeat(length));
|
|
||||||
}
|
|
||||||
println!("─┐");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn println_table_footer() {
|
|
||||||
print!("└─");
|
|
||||||
for (i, bit) in Self::valid_bits() {
|
|
||||||
if i != 0 {
|
|
||||||
print!("─┴─");
|
|
||||||
}
|
|
||||||
let length = bit.name().len();
|
|
||||||
print!("{}", "─".repeat(length));
|
|
||||||
}
|
|
||||||
println!("─┘")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> FlagsExt for T where T: Flags {}
|
|
||||||
|
|
||||||
fn max_texture_format_name_size() -> usize {
|
|
||||||
TEXTURE_FORMAT_LIST
|
|
||||||
.into_iter()
|
|
||||||
.map(|f| texture_format_name(f).len())
|
|
||||||
.max()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn texture_format_name(format: wgpu::TextureFormat) -> String {
|
|
||||||
match format {
|
|
||||||
wgpu::TextureFormat::Astc { block, channel } => {
|
|
||||||
format!("Astc{block:?}{channel:?}:")
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
format!("{format:?}:")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
inner::main();
|
{
|
||||||
|
cli::main()?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
58
wgpu-info/src/report.rs
Normal file
58
wgpu-info/src/report.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use std::{collections::HashMap, io};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use wgpu::{
|
||||||
|
AdapterInfo, DownlevelCapabilities, Features, Limits, TextureFormat, TextureFormatFeatures,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::texture;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct GpuReport {
|
||||||
|
pub devices: Vec<AdapterReport>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GpuReport {
|
||||||
|
pub fn generate() -> Self {
|
||||||
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::default());
|
||||||
|
let adapters = instance.enumerate_adapters(wgpu::Backends::all());
|
||||||
|
|
||||||
|
let mut devices = Vec::with_capacity(adapters.len());
|
||||||
|
for adapter in adapters {
|
||||||
|
let features = adapter.features();
|
||||||
|
let limits = adapter.limits();
|
||||||
|
let downlevel_caps = adapter.get_downlevel_capabilities();
|
||||||
|
let texture_format_features = texture::TEXTURE_FORMAT_LIST
|
||||||
|
.into_iter()
|
||||||
|
.map(|format| (format, adapter.get_texture_format_features(format)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
devices.push(AdapterReport {
|
||||||
|
info: adapter.get_info(),
|
||||||
|
features,
|
||||||
|
limits,
|
||||||
|
downlevel_caps,
|
||||||
|
texture_format_features,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { devices }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_json(file: &str) -> serde_json::Result<Self> {
|
||||||
|
serde_json::from_str(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_json(self, output: impl io::Write) -> serde_json::Result<()> {
|
||||||
|
serde_json::to_writer_pretty(output, &self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct AdapterReport {
|
||||||
|
pub info: AdapterInfo,
|
||||||
|
pub features: Features,
|
||||||
|
pub limits: Limits,
|
||||||
|
pub downlevel_caps: DownlevelCapabilities,
|
||||||
|
pub texture_format_features: HashMap<TextureFormat, TextureFormatFeatures>,
|
||||||
|
}
|
||||||
137
wgpu-info/src/texture.rs
Normal file
137
wgpu-info/src/texture.rs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// Lets keep these on one line
|
||||||
|
#[rustfmt::skip]
|
||||||
|
pub const TEXTURE_FORMAT_LIST: [wgpu::TextureFormat; 114] = [
|
||||||
|
wgpu::TextureFormat::R8Unorm,
|
||||||
|
wgpu::TextureFormat::R8Snorm,
|
||||||
|
wgpu::TextureFormat::R8Uint,
|
||||||
|
wgpu::TextureFormat::R8Sint,
|
||||||
|
wgpu::TextureFormat::R16Uint,
|
||||||
|
wgpu::TextureFormat::R16Sint,
|
||||||
|
wgpu::TextureFormat::R16Unorm,
|
||||||
|
wgpu::TextureFormat::R16Snorm,
|
||||||
|
wgpu::TextureFormat::R16Float,
|
||||||
|
wgpu::TextureFormat::Rg8Unorm,
|
||||||
|
wgpu::TextureFormat::Rg8Snorm,
|
||||||
|
wgpu::TextureFormat::Rg8Uint,
|
||||||
|
wgpu::TextureFormat::Rg8Sint,
|
||||||
|
wgpu::TextureFormat::R32Uint,
|
||||||
|
wgpu::TextureFormat::R32Sint,
|
||||||
|
wgpu::TextureFormat::R32Float,
|
||||||
|
wgpu::TextureFormat::Rg16Uint,
|
||||||
|
wgpu::TextureFormat::Rg16Sint,
|
||||||
|
wgpu::TextureFormat::Rg16Unorm,
|
||||||
|
wgpu::TextureFormat::Rg16Snorm,
|
||||||
|
wgpu::TextureFormat::Rg16Float,
|
||||||
|
wgpu::TextureFormat::Rgba8Unorm,
|
||||||
|
wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||||
|
wgpu::TextureFormat::Rgba8Snorm,
|
||||||
|
wgpu::TextureFormat::Rgba8Uint,
|
||||||
|
wgpu::TextureFormat::Rgba8Sint,
|
||||||
|
wgpu::TextureFormat::Bgra8Unorm,
|
||||||
|
wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
|
wgpu::TextureFormat::Rgb10a2Unorm,
|
||||||
|
wgpu::TextureFormat::Rg11b10Float,
|
||||||
|
wgpu::TextureFormat::Rg32Uint,
|
||||||
|
wgpu::TextureFormat::Rg32Sint,
|
||||||
|
wgpu::TextureFormat::Rg32Float,
|
||||||
|
wgpu::TextureFormat::Rgba16Uint,
|
||||||
|
wgpu::TextureFormat::Rgba16Sint,
|
||||||
|
wgpu::TextureFormat::Rgba16Unorm,
|
||||||
|
wgpu::TextureFormat::Rgba16Snorm,
|
||||||
|
wgpu::TextureFormat::Rgba16Float,
|
||||||
|
wgpu::TextureFormat::Rgba32Uint,
|
||||||
|
wgpu::TextureFormat::Rgba32Sint,
|
||||||
|
wgpu::TextureFormat::Rgba32Float,
|
||||||
|
wgpu::TextureFormat::Stencil8,
|
||||||
|
wgpu::TextureFormat::Depth16Unorm,
|
||||||
|
wgpu::TextureFormat::Depth32Float,
|
||||||
|
wgpu::TextureFormat::Depth32FloatStencil8,
|
||||||
|
wgpu::TextureFormat::Depth24Plus,
|
||||||
|
wgpu::TextureFormat::Depth24PlusStencil8,
|
||||||
|
wgpu::TextureFormat::Rgb9e5Ufloat,
|
||||||
|
wgpu::TextureFormat::Bc1RgbaUnorm,
|
||||||
|
wgpu::TextureFormat::Bc1RgbaUnormSrgb,
|
||||||
|
wgpu::TextureFormat::Bc2RgbaUnorm,
|
||||||
|
wgpu::TextureFormat::Bc2RgbaUnormSrgb,
|
||||||
|
wgpu::TextureFormat::Bc3RgbaUnorm,
|
||||||
|
wgpu::TextureFormat::Bc3RgbaUnormSrgb,
|
||||||
|
wgpu::TextureFormat::Bc4RUnorm,
|
||||||
|
wgpu::TextureFormat::Bc4RSnorm,
|
||||||
|
wgpu::TextureFormat::Bc5RgUnorm,
|
||||||
|
wgpu::TextureFormat::Bc5RgSnorm,
|
||||||
|
wgpu::TextureFormat::Bc6hRgbUfloat,
|
||||||
|
wgpu::TextureFormat::Bc6hRgbFloat,
|
||||||
|
wgpu::TextureFormat::Bc7RgbaUnorm,
|
||||||
|
wgpu::TextureFormat::Bc7RgbaUnormSrgb,
|
||||||
|
wgpu::TextureFormat::Etc2Rgb8Unorm,
|
||||||
|
wgpu::TextureFormat::Etc2Rgb8UnormSrgb,
|
||||||
|
wgpu::TextureFormat::Etc2Rgb8A1Unorm,
|
||||||
|
wgpu::TextureFormat::Etc2Rgb8A1UnormSrgb,
|
||||||
|
wgpu::TextureFormat::Etc2Rgba8Unorm,
|
||||||
|
wgpu::TextureFormat::Etc2Rgba8UnormSrgb,
|
||||||
|
wgpu::TextureFormat::EacR11Unorm,
|
||||||
|
wgpu::TextureFormat::EacR11Snorm,
|
||||||
|
wgpu::TextureFormat::EacRg11Unorm,
|
||||||
|
wgpu::TextureFormat::EacRg11Snorm,
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B4x4, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x4, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B5x5, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x5, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B6x6, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x5, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x6, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B8x8, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x5, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x6, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x8, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B10x10, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x10, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::Unorm },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::UnormSrgb },
|
||||||
|
wgpu::TextureFormat::Astc { block: wgpu::AstcBlock::B12x12, channel: wgpu::AstcChannel::Hdr },
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn max_texture_format_string_size() -> usize {
|
||||||
|
TEXTURE_FORMAT_LIST
|
||||||
|
.into_iter()
|
||||||
|
.map(|f| texture_format_name(f).len())
|
||||||
|
.max()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn texture_format_name(format: wgpu::TextureFormat) -> String {
|
||||||
|
match format {
|
||||||
|
wgpu::TextureFormat::Astc { block, channel } => {
|
||||||
|
format!("Astc{block:?}{channel:?}:")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
format!("{format:?}:")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -26,7 +26,7 @@ pub mod math;
|
|||||||
// behavior to this macro (unspecified bit do not produce an error).
|
// behavior to this macro (unspecified bit do not produce an error).
|
||||||
macro_rules! impl_bitflags {
|
macro_rules! impl_bitflags {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "serde")]
|
||||||
impl serde::Serialize for $name {
|
impl serde::Serialize for $name {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@ -36,7 +36,7 @@ macro_rules! impl_bitflags {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "replay")]
|
#[cfg(feature = "serde")]
|
||||||
impl<'de> serde::Deserialize<'de> for $name {
|
impl<'de> serde::Deserialize<'de> for $name {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
|
||||||
where
|
where
|
||||||
@ -92,8 +92,7 @@ pub const QUERY_SIZE: u32 = 8;
|
|||||||
/// Backends supported by wgpu.
|
/// Backends supported by wgpu.
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
|
||||||
pub enum Backend {
|
pub enum Backend {
|
||||||
/// Dummy backend, used for testing.
|
/// Dummy backend, used for testing.
|
||||||
Empty = 0,
|
Empty = 0,
|
||||||
@ -825,8 +824,7 @@ impl Features {
|
|||||||
/// [`downlevel_defaults()`]: Limits::downlevel_defaults
|
/// [`downlevel_defaults()`]: Limits::downlevel_defaults
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
|
||||||
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase", default))]
|
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase", default))]
|
||||||
pub struct Limits {
|
pub struct Limits {
|
||||||
/// Maximum allowed value for the `size.width` of a texture created with `TextureDimension::D1`.
|
/// Maximum allowed value for the `size.width` of a texture created with `TextureDimension::D1`.
|
||||||
@ -1116,6 +1114,7 @@ impl Limits {
|
|||||||
/// Represents the sets of additional limits on an adapter,
|
/// Represents the sets of additional limits on an adapter,
|
||||||
/// which take place when running on downlevel backends.
|
/// which take place when running on downlevel backends.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct DownlevelLimits {}
|
pub struct DownlevelLimits {}
|
||||||
|
|
||||||
#[allow(unknown_lints)] // derivable_impls is nightly only currently
|
#[allow(unknown_lints)] // derivable_impls is nightly only currently
|
||||||
@ -1128,6 +1127,7 @@ impl Default for DownlevelLimits {
|
|||||||
|
|
||||||
/// Lists various ways the underlying platform does not conform to the WebGPU standard.
|
/// Lists various ways the underlying platform does not conform to the WebGPU standard.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct DownlevelCapabilities {
|
pub struct DownlevelCapabilities {
|
||||||
/// Combined boolean flags.
|
/// Combined boolean flags.
|
||||||
pub flags: DownlevelFlags,
|
pub flags: DownlevelFlags,
|
||||||
@ -1282,6 +1282,7 @@ impl DownlevelFlags {
|
|||||||
/// Collections of shader features a device supports if they support less than WebGPU normally allows.
|
/// Collections of shader features a device supports if they support less than WebGPU normally allows.
|
||||||
// TODO: Fill out the differences between shader models more completely
|
// TODO: Fill out the differences between shader models more completely
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub enum ShaderModel {
|
pub enum ShaderModel {
|
||||||
/// Extremely limited shaders, including a total instruction limit.
|
/// Extremely limited shaders, including a total instruction limit.
|
||||||
Sm2,
|
Sm2,
|
||||||
@ -1294,8 +1295,7 @@ pub enum ShaderModel {
|
|||||||
/// Supported physical device types.
|
/// Supported physical device types.
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
|
||||||
pub enum DeviceType {
|
pub enum DeviceType {
|
||||||
/// Other or Unknown.
|
/// Other or Unknown.
|
||||||
Other,
|
Other,
|
||||||
@ -1313,8 +1313,7 @@ pub enum DeviceType {
|
|||||||
|
|
||||||
/// Information about an adapter.
|
/// Information about an adapter.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
|
||||||
pub struct AdapterInfo {
|
pub struct AdapterInfo {
|
||||||
/// Adapter name
|
/// Adapter name
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -1865,6 +1864,7 @@ impl_bitflags!(TextureFormatFeatureFlags);
|
|||||||
///
|
///
|
||||||
/// Features are defined by WebGPU specification unless `Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled.
|
/// Features are defined by WebGPU specification unless `Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled.
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct TextureFormatFeatures {
|
pub struct TextureFormatFeatures {
|
||||||
/// Valid bits for `TextureDescriptor::Usage` provided for format creation.
|
/// Valid bits for `TextureDescriptor::Usage` provided for format creation.
|
||||||
pub allowed_usages: TextureUsages,
|
pub allowed_usages: TextureUsages,
|
||||||
|
|||||||
@ -1440,7 +1440,7 @@ impl Instance {
|
|||||||
target_os = "emscripten",
|
target_os = "emscripten",
|
||||||
feature = "webgl"
|
feature = "webgl"
|
||||||
))]
|
))]
|
||||||
pub fn enumerate_adapters(&self, backends: Backends) -> impl Iterator<Item = Adapter> {
|
pub fn enumerate_adapters(&self, backends: Backends) -> impl ExactSizeIterator<Item = Adapter> {
|
||||||
let context = Arc::clone(&self.context);
|
let context = Arc::clone(&self.context);
|
||||||
self.context
|
self.context
|
||||||
.as_any()
|
.as_any()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user