Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Many Steps Towards GL Testing Working #2504

Merged
merged 12 commits into from
Feb 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ wgpu/red.png

# Readme says to check out CTS here
cts/

# Readme says to put angle in working directory
*.dll
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Both [HLSL](https://github.com/Microsoft/DirectXShaderCompiler) and [GLSL](https
have compilers to target SPIR-V. All of these shader languages can be used with any backend, we
will handle all of the conversion. Additionally, support for these shader inputs is not going away.

While WebGPU does not support any shader language other than WGSL, we will automatically convert your
While WebGPU does not support any shading language other than WGSL, we will automatically convert your
non-WGSL shaders if you're running on WebGPU.

WGSL is always supported by default, but GLSL and SPIR-V need features enabled to compile in support.
Expand All @@ -99,7 +99,7 @@ We support running our GLES3 backend over it in order to reach platforms with GL
In order to run with Angle, "angle" feature has to be enabled, and Angle libraries placed in a location visible to the application.
These binaries can be downloaded from [gfbuild-angle](https://github.com/DileSoft/gfbuild-angle) artifacts.

On Windows, you generally need to copy them into the working directory, or in the same directory as the executable.
On Windows, you generally need to copy them into the working directory, in the same directory as the executable, or somewhere in your path.
On Linux, you can point to them using `LD_LIBRARY_PATH` environment.

## Environment Variables
Expand Down
9 changes: 6 additions & 3 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2735,10 +2735,13 @@ impl<A: HalApi> Device<A> {
let format_desc = format.describe();
self.require_features(format_desc.required_features)?;

if self
let using_device_features = self
.features
.contains(wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES)
{
.contains(wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES);
// If we're running downlevel, we need to manually ask the backend what we can use as we can't trust WebGPU.
kvark marked this conversation as resolved.
Show resolved Hide resolved
let downlevel = !self.downlevel.is_webgpu_compliant();

if using_device_features || downlevel {
Ok(adapter.get_texture_format_features(format))
} else {
Ok(format_desc.guaranteed_format_features)
Expand Down
49 changes: 8 additions & 41 deletions wgpu-core/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,49 +28,16 @@ pub struct FailedLimit {
}

fn check_limits(requested: &wgt::Limits, allowed: &wgt::Limits) -> Vec<FailedLimit> {
use std::cmp::Ordering;
let mut failed = Vec::new();

macro_rules! compare {
($name:ident, $ordering:ident) => {
match requested.$name.cmp(&allowed.$name) {
Ordering::$ordering | Ordering::Equal => (),
_ => failed.push(FailedLimit {
name: stringify!($name),
requested: requested.$name,
allowed: allowed.$name,
}),
}
};
}
requested.check_limits_with_fail_fn(allowed, false, |name, requested, allowed| {
kvark marked this conversation as resolved.
Show resolved Hide resolved
failed.push(FailedLimit {
name,
requested,
allowed,
})
});

compare!(max_texture_dimension_1d, Less);
compare!(max_texture_dimension_2d, Less);
compare!(max_texture_dimension_3d, Less);
compare!(max_texture_array_layers, Less);
compare!(max_bind_groups, Less);
compare!(max_dynamic_uniform_buffers_per_pipeline_layout, Less);
compare!(max_dynamic_storage_buffers_per_pipeline_layout, Less);
compare!(max_sampled_textures_per_shader_stage, Less);
compare!(max_samplers_per_shader_stage, Less);
compare!(max_storage_buffers_per_shader_stage, Less);
compare!(max_storage_textures_per_shader_stage, Less);
compare!(max_uniform_buffers_per_shader_stage, Less);
compare!(max_uniform_buffer_binding_size, Less);
compare!(max_storage_buffer_binding_size, Less);
compare!(max_vertex_buffers, Less);
compare!(max_vertex_attributes, Less);
compare!(max_vertex_buffer_array_stride, Less);
compare!(max_push_constant_size, Less);
compare!(min_uniform_buffer_offset_alignment, Greater);
compare!(min_storage_buffer_offset_alignment, Greater);
compare!(max_inter_stage_shader_components, Less);
compare!(max_compute_workgroup_storage_size, Less);
compare!(max_compute_invocations_per_workgroup, Less);
compare!(max_compute_workgroup_size_x, Less);
compare!(max_compute_workgroup_size_y, Less);
compare!(max_compute_workgroup_size_z, Less);
compare!(max_compute_workgroups_per_dimension, Less);
failed
}

Expand Down Expand Up @@ -878,7 +845,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.map_err(|_| InvalidAdapter)
}

pub fn adapter_downlevel_properties<A: HalApi>(
pub fn adapter_downlevel_capabilities<A: HalApi>(
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
&self,
adapter_id: AdapterId,
) -> Result<wgt::DownlevelCapabilities, InvalidAdapter> {
Expand Down
2 changes: 1 addition & 1 deletion wgpu-core/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ pub enum CreateTextureError {
InvalidFormatUsages(wgt::TextureUsages, wgt::TextureFormat),
#[error("Texture usages {0:?} are not allowed on a texture of dimensions {1:?}")]
InvalidDimensionUsages(wgt::TextureUsages, wgt::TextureDimension),
#[error("Texture format {0:?} can't be used")]
#[error("Texture format {0:?} can't be used due to missing features.")]
MissingFeatures(wgt::TextureFormat, #[source] MissingFeatures),
}

Expand Down
23 changes: 20 additions & 3 deletions wgpu-hal/src/gles/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,6 @@ impl super::Adapter {
};

let mut downlevel_flags = wgt::DownlevelFlags::empty()
| wgt::DownlevelFlags::DEVICE_LOCAL_IMAGE_COPIES
| wgt::DownlevelFlags::NON_POWER_OF_TWO_MIPMAPPED_TEXTURES
| wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES
| wgt::DownlevelFlags::COMPARISON_SAMPLERS;
Expand Down Expand Up @@ -303,13 +302,31 @@ impl super::Adapter {
downlevel_flags.contains(wgt::DownlevelFlags::VERTEX_STORAGE)
&& vertex_shader_storage_textures != 0,
);
let gles_bcn_exts = [
"GL_EXT_texture_compression_s3tc_srgb",
"GL_EXT_texture_compression_rgtc",
"GL_EXT_texture_compression_bptc",
];
let webgl_bcn_exts = [
"WEBGL_compressed_texture_s3tc",
"WEBGL_compressed_texture_s3tc_srgb",
"EXT_texture_compression_rgtc",
"EXT_texture_compression_bptc",
];
let bcn_exts = if cfg!(target_arch = "wasm32") {
&webgl_bcn_exts[..]
} else {
&gles_bcn_exts[..]
};
features.set(
wgt::Features::TEXTURE_COMPRESSION_BC,
bcn_exts.iter().all(|&ext| extensions.contains(ext)),
);
features.set(
wgt::Features::TEXTURE_COMPRESSION_ETC2,
// This is a part of GLES-3 but not WebGL2 core
!cfg!(target_arch = "wasm32") || extensions.contains("WEBGL_compressed_texture_etc"),
);
//Note: `wgt::Features::TEXTURE_COMPRESSION_BC` can't be fully supported, but there are
// "WEBGL_compressed_texture_s3tc" and "WEBGL_compressed_texture_s3tc_srgb" which could partially cover it
features.set(
wgt::Features::TEXTURE_COMPRESSION_ASTC_LDR,
extensions.contains("GL_KHR_texture_compression_astc_ldr")
Expand Down
24 changes: 12 additions & 12 deletions wgpu-hal/src/gles/conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ impl super::AdapterShared {

let (internal, external, data_type) = match texture_format {
Tf::R8Unorm => (glow::R8, glow::RED, glow::UNSIGNED_BYTE),
Tf::R8Snorm => (glow::R8, glow::RED, glow::BYTE),
Tf::R8Snorm => (glow::R8_SNORM, glow::RED, glow::BYTE),
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
Tf::R8Uint => (glow::R8UI, glow::RED_INTEGER, glow::UNSIGNED_BYTE),
Tf::R8Sint => (glow::R8I, glow::RED_INTEGER, glow::BYTE),
Tf::R16Uint => (glow::R16UI, glow::RED_INTEGER, glow::UNSIGNED_SHORT),
Expand All @@ -17,7 +17,7 @@ impl super::AdapterShared {
Tf::R16Snorm => (glow::R16_SNORM, glow::RED, glow::SHORT),
Tf::R16Float => (glow::R16F, glow::RED, glow::HALF_FLOAT),
Tf::Rg8Unorm => (glow::RG8, glow::RG, glow::UNSIGNED_BYTE),
Tf::Rg8Snorm => (glow::RG8, glow::RG, glow::BYTE),
Tf::Rg8Snorm => (glow::RG8_SNORM, glow::RG, glow::BYTE),
Tf::Rg8Uint => (glow::RG8UI, glow::RG_INTEGER, glow::UNSIGNED_BYTE),
Tf::Rg8Sint => (glow::RG8I, glow::RG_INTEGER, glow::BYTE),
Tf::R32Uint => (glow::R32UI, glow::RED_INTEGER, glow::UNSIGNED_INT),
Expand All @@ -31,8 +31,8 @@ impl super::AdapterShared {
Tf::Rgba8Unorm => (glow::RGBA8, glow::RGBA, glow::UNSIGNED_BYTE),
Tf::Rgba8UnormSrgb => (glow::SRGB8_ALPHA8, glow::RGBA, glow::UNSIGNED_BYTE),
Tf::Bgra8UnormSrgb => (glow::SRGB8_ALPHA8, glow::RGBA, glow::UNSIGNED_BYTE), //TODO?
Tf::Rgba8Snorm => (glow::RGBA8, glow::RGBA, glow::BYTE),
Tf::Bgra8Unorm => (glow::RGBA8, glow::BGRA, glow::UNSIGNED_BYTE),
Tf::Rgba8Snorm => (glow::RGBA8_SNORM, glow::RGBA, glow::BYTE),
Tf::Bgra8Unorm => (glow::RGBA8, glow::RGBA, glow::UNSIGNED_BYTE), //TODO?
Tf::Rgba8Uint => (glow::RGBA8UI, glow::RGBA_INTEGER, glow::UNSIGNED_BYTE),
Tf::Rgba8Sint => (glow::RGBA8I, glow::RGBA_INTEGER, glow::BYTE),
Tf::Rgb10a2Unorm => (
Expand Down Expand Up @@ -74,14 +74,14 @@ impl super::AdapterShared {
Tf::Bc2RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, glow::RGBA, 0),
Tf::Bc3RgbaUnorm => (glow::COMPRESSED_RGBA_S3TC_DXT5_EXT, glow::RGBA, 0),
Tf::Bc3RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, glow::RGBA, 0),
Tf::Bc4RUnorm
| Tf::Bc4RSnorm
| Tf::Bc5RgUnorm
| Tf::Bc5RgSnorm
| Tf::Bc6hRgbUfloat
| Tf::Bc6hRgbSfloat
| Tf::Bc7RgbaUnorm
| Tf::Bc7RgbaUnormSrgb => unimplemented!(),
Tf::Bc4RUnorm => (glow::COMPRESSED_RED_RGTC1, glow::RED, 0),
Tf::Bc4RSnorm => (glow::COMPRESSED_SIGNED_RED_RGTC1, glow::RED, 0),
Tf::Bc5RgUnorm => (glow::COMPRESSED_RG_RGTC2, glow::RG, 0),
Tf::Bc5RgSnorm => (glow::COMPRESSED_SIGNED_RG_RGTC2, glow::RG, 0),
Tf::Bc6hRgbUfloat => (glow::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, glow::RGB, 0),
Tf::Bc6hRgbSfloat => (glow::COMPRESSED_RGB_BPTC_SIGNED_FLOAT, glow::RGB, 0),
Tf::Bc7RgbaUnorm => (glow::COMPRESSED_RGBA_BPTC_UNORM, glow::RGBA, 0),
Tf::Bc7RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, glow::RGBA, 0),
Tf::Etc2Rgb8Unorm => (glow::COMPRESSED_RGB8_ETC2, glow::RGB, 0),
Tf::Etc2Rgb8UnormSrgb => (glow::COMPRESSED_SRGB8_ETC2, glow::RGB, 0),
Tf::Etc2Rgb8A1Unorm => (
Expand Down
15 changes: 12 additions & 3 deletions wgpu-hal/src/gles/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,18 @@ impl super::Queue {
_ => unreachable!(),
}
} else {
let bytes_per_image =
copy.buffer_layout.rows_per_image.map_or(1, |rpi| rpi.get())
* copy.buffer_layout.bytes_per_row.map_or(1, |bpr| bpr.get());
let bytes_per_row = copy
.buffer_layout
.bytes_per_row
.map_or(copy.size.width * format_info.block_size as u32, |bpr| {
bpr.get()
});
let rows_per_image = copy.buffer_layout.rows_per_image.map_or(
copy.size.height / format_info.block_dimensions.1 as u32,
|rpi| rpi.get(),
);

let bytes_per_image = bytes_per_row * rows_per_image;
let offset = copy.buffer_layout.offset as u32;

let buffer_data;
Expand Down
2 changes: 1 addition & 1 deletion wgpu-info/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ license = "MIT OR Apache-2.0"

[dependencies]
env_logger = "0.9"
wgpu = { version = "0.12", path = "../wgpu" }
wgpu = { version = "0.12", path = "../wgpu", features = ["angle", "vulkan-portability"] }
2 changes: 1 addition & 1 deletion wgpu-info/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
#[rustfmt::skip]
fn print_info_from_adapter(adapter: &wgpu::Adapter, idx: usize) {
let info = adapter.get_info();
let downlevel = adapter.get_downlevel_properties();
let downlevel = adapter.get_downlevel_capabilities();
let features = adapter.features();
let limits = adapter.limits();

Expand Down
103 changes: 89 additions & 14 deletions wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ impl Features {
///
/// See also: <https://gpuweb.github.io/gpuweb/#dictdef-gpulimits>
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
Expand Down Expand Up @@ -820,6 +820,76 @@ impl Limits {
..self
}
}

/// Compares every limits within self is within the limits given in `allowed`.
///
/// If you need detailed information on failures, look at [`Limits::check_limits_with_fail_fn`].
pub fn check_limits(&self, allowed: &Self) -> bool {
let mut within = true;
self.check_limits_with_fail_fn(allowed, true, |_, _, _| within = false);
within
}

/// Compares every limits within self is within the limits given in `allowed`.
/// For an easy to use binary choice, use [`Limits::check_limits`].
///
/// If a value is not within the allowed limit, this function calls the `fail_fn`
/// with the:
/// - limit name
/// - self's limit
/// - allowed's limit.
///
/// If fatal is true, a single failure bails out the comparison after a single failure.
pub fn check_limits_with_fail_fn(
&self,
allowed: &Self,
fatal: bool,
mut fail_fn: impl FnMut(&'static str, u32, u32),
) {
use std::cmp::Ordering;

macro_rules! compare {
($name:ident, $ordering:ident) => {
match self.$name.cmp(&allowed.$name) {
Ordering::$ordering | Ordering::Equal => (),
_ => {
fail_fn(stringify!($name), self.$name, allowed.$name);
if fatal {
return;
}
}
}
};
}

compare!(max_texture_dimension_1d, Less);
compare!(max_texture_dimension_2d, Less);
compare!(max_texture_dimension_3d, Less);
compare!(max_texture_array_layers, Less);
compare!(max_bind_groups, Less);
compare!(max_dynamic_uniform_buffers_per_pipeline_layout, Less);
compare!(max_dynamic_storage_buffers_per_pipeline_layout, Less);
compare!(max_sampled_textures_per_shader_stage, Less);
compare!(max_samplers_per_shader_stage, Less);
compare!(max_storage_buffers_per_shader_stage, Less);
compare!(max_storage_textures_per_shader_stage, Less);
compare!(max_uniform_buffers_per_shader_stage, Less);
compare!(max_uniform_buffer_binding_size, Less);
compare!(max_storage_buffer_binding_size, Less);
compare!(max_vertex_buffers, Less);
compare!(max_vertex_attributes, Less);
compare!(max_vertex_buffer_array_stride, Less);
compare!(max_push_constant_size, Less);
compare!(min_uniform_buffer_offset_alignment, Greater);
compare!(min_storage_buffer_offset_alignment, Greater);
compare!(max_inter_stage_shader_components, Less);
compare!(max_compute_workgroup_storage_size, Less);
compare!(max_compute_invocations_per_workgroup, Less);
compare!(max_compute_workgroup_size_x, Less);
compare!(max_compute_workgroup_size_y, Less);
compare!(max_compute_workgroup_size_z, Less);
compare!(max_compute_workgroups_per_dimension, Less);
}
}

/// Represents the sets of additional limits on an adapter,
Expand Down Expand Up @@ -881,41 +951,46 @@ bitflags::bitflags! {
/// [`DownlevelCapabilities::is_webgpu_compliant()`] function.
pub struct DownlevelFlags: u32 {
/// The device supports compiling and using compute shaders.
///
/// DX11 on FL10 level hardware, WebGL2, and GLES3.0 devices do not support compute.
const COMPUTE_SHADERS = 1 << 0;
/// Supports binding storage buffers and textures to fragment shaders.
const FRAGMENT_WRITABLE_STORAGE = 1 << 1;
/// Supports indirect drawing and dispatching.
///
/// DX11 on FL10 level hardware, WebGL2, and GLES 3.0 devices do not support indirect.
const INDIRECT_EXECUTION = 1 << 2;
/// Supports non-zero `base_vertex` parameter to indexed draw calls.
const BASE_VERTEX = 1 << 3;
/// Supports reading from a depth/stencil buffer while using as a read-only depth/stencil
/// attachment.
///
/// The WebGL2 and GLES backends do not support RODS.
const READ_ONLY_DEPTH_STENCIL = 1 << 4;
/// Supports:
/// - copy_image_to_image
/// - copy_buffer_to_image and copy_image_to_buffer with a buffer without a MAP_* usage
const DEVICE_LOCAL_IMAGE_COPIES = 1 << 5;
/// Supports textures with mipmaps which have a non power of two size.
const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 1 << 6;
const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 1 << 5;
/// Supports textures that are cube arrays.
const CUBE_ARRAY_TEXTURES = 1 << 7;
const CUBE_ARRAY_TEXTURES = 1 << 6;
/// Supports comparison samplers.
const COMPARISON_SAMPLERS = 1 << 8;
const COMPARISON_SAMPLERS = 1 << 7;
/// Supports different blend operations per color attachment.
const INDEPENDENT_BLEND = 1 << 9;
const INDEPENDENT_BLEND = 1 << 8;
/// Supports storage buffers in vertex shaders.
const VERTEX_STORAGE = 1 << 10;
const VERTEX_STORAGE = 1 << 9;

/// Supports samplers with anisotropic filtering. Note this isn't actually required by
/// WebGPU, the implementation is allowed to completely ignore aniso clamp. This flag is
/// here for native backends so they can comunicate to the user of aniso is enabled.
const ANISOTROPIC_FILTERING = 1 << 11;
///
/// All backends and all devices support anisotropic filtering.
const ANISOTROPIC_FILTERING = 1 << 10;

/// Supports storage buffers in fragment shaders.
const FRAGMENT_STORAGE = 1 << 12;
const FRAGMENT_STORAGE = 1 << 11;

/// Supports sample-rate shading.
const MULTISAMPLED_SHADING = 1 << 12;

/// Supports sample shading and multisample interpolation.
const MULTISAMPLED_SHADING = 1 << 13;
}
}

Expand Down
Loading