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

Re-enable GL testing in CI #2508

Merged
merged 13 commits into from
Mar 1, 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
15 changes: 11 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
target: x86_64-unknown-linux-gnu
tool: clippy
kind: local
backends: vulkan # gl
backends: vulkan gl
nextest_url: https://get.nexte.st/latest/linux

- name: Linux aarch64
Expand Down Expand Up @@ -139,7 +139,7 @@ jobs:
- name: caching
uses: Swatinem/rust-cache@v1
with:
key: ${{ matrix.target }}-a # suffix for cache busting
key: ${{ matrix.target }}-b # suffix for cache busting

- name: download nextest
if: matrix.kind == 'local'
Expand All @@ -152,13 +152,20 @@ jobs:
run: |
echo "$ANDROID_HOME/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin" >> $GITHUB_PATH

- name: install llvmpipe and lavapipe
- name: install llvmpipe, lavapipe, and vulkan sdk
if: matrix.os == 'ubuntu-20.04' && matrix.target != 'aarch64-linux-android' && matrix.kind == 'local'
run: |
sudo apt-get update -y -qq

# llvmpipe/lavapipe
sudo add-apt-repository ppa:oibaf/graphics-drivers -y

# vulkan sdk
wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-focal.list https://packages.lunarg.com/vulkan/lunarg-vulkan-focal.list

sudo apt-get update
sudo apt install -y libegl1-mesa libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers
sudo apt install -y libegl1-mesa libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers vulkan-sdk

# We enable line numbers for panics, but that's it
- name: disable debug
Expand Down
29 changes: 16 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,40 +116,43 @@ When running the CTS, use the variables `DENO_WEBGPU_ADAPTER_NAME`, `DENO_WEBGPU

We have multiple methods of testing, each of which tests different qualities about wgpu. We automatically run our tests on CI if possible. The current state of CI testing:

| Backend/Platform | Status |
| ---------------- | ---------------------------------------------------------------------- |
| DX12/Windows 10 | :heavy_check_mark: (over WARP) |
| DX11/Windows 10 | :construction: (over WARP) |
| Metal/MacOS | :x: (no CPU runner) |
| Vulkan/Linux | :ok: ([cts hangs](https://github.com/gfx-rs/wgpu/issues/1974)) |
| GLES/Linux | :x: ([egl fails init](https://github.com/gfx-rs/wgpu/issues/1551)) |
| Backend/Platform | Tests | CTS | Notes |
| ---------------- | -------------------|---------------------|-------------------------------------- |
| DX12/Windows 10 | :heavy_check_mark: | :heavy_check_mark: | using WARP |
| DX11/Windows 10 | :construction: | — | using WARP |
| Metal/MacOS | — | — | metal requires GPU |
| Vulkan/Linux | :heavy_check_mark: | :x: | using lavapipe, [cts hangs][cts-hang] |
| GLES/Linux | :heavy_check_mark: | — | using llvmpipe |

[cts-hang]: https://github.com/gfx-rs/wgpu/issues/1974

### Core Test Infrastructure

All framework based examples have image comparison tested against their screenshot.
We use a tool called [`cargo nextest`](https://github.com/nextest-rs/nextest) to run our tests.
To install it, run `cargo install cargo-nextest`.

To run the test suite on the default device:

```
cargo test --no-fail-fast
cargo nextest run --no-fail-fast
```

There's logic which can automatically run the tests once for each adapter on your system.
`wgpu-info` can run the tests once for each adapter on your system.

```
cargo run --bin wgpu-info -- cargo test --no-fail-fast
cargo run --bin wgpu-info -- cargo nextest run --no-fail-fast
```

Then to run an example's image comparison tests, run:

```
cargo test --example <example-name> --no-fail-fast
cargo nextest run --example <example-name> --no-fail-fast
```

Or run a part of the integration test suite:

```
cargo test -p wgpu -- <name-of-test>
cargo nextest run -p wgpu -- <name-of-test>
```

If you are a user and want a way to help contribute to wgpu, we always need more help writing test cases.
Expand Down
16 changes: 15 additions & 1 deletion wgpu-core/src/command/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::device::trace::Command as TraceCommand;
use crate::{
command::{CommandBuffer, CommandEncoderError},
conv,
device::Device,
device::{Device, MissingDownlevelFlags},
error::{ErrorFormatter, PrettyError},
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
id::{BufferId, CommandEncoderId, Id, TextureId, Valid},
Expand Down Expand Up @@ -108,6 +108,8 @@ pub enum TransferError {
},
#[error(transparent)]
MemoryInitFailure(#[from] super::ClearError),
#[error("Cannot encode this copy because of a missing downelevel flag")]
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
}

impl PrettyError for TransferError {
Expand Down Expand Up @@ -839,6 +841,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
);
}

if format_desc.sample_type == wgt::TextureSampleType::Depth
&& !device
.downlevel
.flags
.contains(wgt::DownlevelFlags::DEPTH_TEXTURE_AND_BUFFER_COPIES)
{
return Err(TransferError::MissingDownlevelFlags(MissingDownlevelFlags(
wgt::DownlevelFlags::DEPTH_TEXTURE_AND_BUFFER_COPIES,
))
.into());
}

cmd_buf
.buffer_memory_init_actions
.extend(dst_buffer.initialization_status.create_action(
Expand Down
10 changes: 9 additions & 1 deletion wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ impl<A: HalApi> Device<A> {
if desc.dimension != wgt::TextureDimension::D2 {
// Depth textures can only be 2D
if format_desc.sample_type == wgt::TextureSampleType::Depth {
return Err(resource::CreateTextureError::InvalidDepthKind(
return Err(resource::CreateTextureError::InvalidDepthDimension(
desc.dimension,
desc.format,
));
Expand All @@ -654,6 +654,14 @@ impl<A: HalApi> Device<A> {
desc.dimension,
));
}

// Compressed textures can only be 2D
if format_desc.is_compressed() {
return Err(resource::CreateTextureError::InvalidCompressedDimension(
desc.dimension,
desc.format,
));
}
}

let format_features = self
Expand Down
6 changes: 4 additions & 2 deletions wgpu-core/src/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,10 @@ pub enum CreateTextureError {
EmptyUsage,
#[error(transparent)]
InvalidDimension(#[from] TextureDimensionError),
#[error("Depth texture kind {0:?} of format {0:?} can't be created")]
InvalidDepthKind(wgt::TextureDimension, wgt::TextureFormat),
#[error("Depth texture ({1:?}) can't be created as {0:?}")]
InvalidDepthDimension(wgt::TextureDimension, wgt::TextureFormat),
#[error("Compressed texture ({1:?}) can't be created as {0:?}")]
InvalidCompressedDimension(wgt::TextureDimension, wgt::TextureFormat),
#[error(
"Texture descriptor mip level count {requested} is invalid, maximum allowed is {maximum}"
)]
Expand Down
4 changes: 2 additions & 2 deletions wgpu-hal/src/dx12/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ unsafe extern "system" fn output_debug_string_handler(
log::log!(level, "{}", message);

if cfg!(debug_assertions) && level == log::Level::Error {
// Panicking behind FFI is UB, so we just exit.
std::process::exit(1);
// Set canary and continue
crate::VALIDATION_CANARY.set();
}

excpt::EXCEPTION_CONTINUE_EXECUTION
Expand Down
120 changes: 85 additions & 35 deletions wgpu-hal/src/gles/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,10 @@ impl super::Adapter {
super::PrivateCapabilities::CAN_DISABLE_DRAW_BUFFER,
!cfg!(target_arch = "wasm32"),
);
private_caps.set(
super::PrivateCapabilities::GET_BUFFER_SUB_DATA,
cfg!(target_arch = "wasm32"),
);

let max_texture_size = gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) as u32;
let max_texture_3d_size = gl.get_parameter_i32(glow::MAX_3D_TEXTURE_SIZE) as u32;
Expand Down Expand Up @@ -597,35 +601,59 @@ impl crate::Adapter<super::Api> for super::Adapter {
use crate::TextureFormatCapabilities as Tfc;
use wgt::TextureFormat as Tf;

// The storage types are sprinkled based on section
// "TEXTURE IMAGE LOADS AND STORES" of GLES-3.2 spec.
let unfiltered_color =
Tfc::SAMPLED | Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE | Tfc::MULTISAMPLE_RESOLVE;
let filtered_color = unfiltered_color | Tfc::SAMPLED_LINEAR | Tfc::COLOR_ATTACHMENT_BLEND;
// Base types are pulled from the table in the OpenGLES 3.0 spec in section 3.8.
//
// The storage types are based on table 8.26, in section
// "TEXTURE IMAGE LOADS AND STORES" of OpenGLES-3.2 spec.
let empty = Tfc::empty();
let unfilterable = Tfc::SAMPLED;
let depth = Tfc::SAMPLED | Tfc::DEPTH_STENCIL_ATTACHMENT;
let filterable = unfilterable | Tfc::SAMPLED_LINEAR;
let renderable =
unfilterable | Tfc::COLOR_ATTACHMENT | Tfc::MULTISAMPLE | Tfc::MULTISAMPLE_RESOLVE;
let filterable_renderable = filterable | renderable | Tfc::COLOR_ATTACHMENT_BLEND;
let storage = Tfc::STORAGE | Tfc::STORAGE_READ_WRITE;
match format {
Tf::R8Unorm | Tf::R8Snorm => filtered_color,
Tf::R8Uint | Tf::R8Sint | Tf::R16Uint | Tf::R16Sint => unfiltered_color,
Tf::R16Float | Tf::Rg8Unorm | Tf::Rg8Snorm => filtered_color,
Tf::Rg8Uint | Tf::Rg8Sint | Tf::R32Uint | Tf::R32Sint => {
unfiltered_color | Tfc::STORAGE
}
Tf::R16Unorm | Tf::Rg16Unorm | Tf::Rgba16Unorm => filtered_color,
Tf::R16Snorm | Tf::Rg16Snorm | Tf::Rgba16Snorm => filtered_color,
Tf::R32Float => unfiltered_color,
Tf::Rg16Uint | Tf::Rg16Sint => unfiltered_color,
Tf::Rg16Float | Tf::Rgba8Unorm | Tf::Rgba8UnormSrgb => filtered_color | Tfc::STORAGE,
Tf::Bgra8UnormSrgb | Tf::Rgba8Snorm | Tf::Bgra8Unorm => filtered_color,
Tf::Rgba8Uint | Tf::Rgba8Sint => unfiltered_color | Tfc::STORAGE,
Tf::Rgb10a2Unorm | Tf::Rg11b10Float => filtered_color,
Tf::Rg32Uint | Tf::Rg32Sint => unfiltered_color,
Tf::Rg32Float => unfiltered_color | Tfc::STORAGE,
Tf::Rgba16Uint | Tf::Rgba16Sint => unfiltered_color | Tfc::STORAGE,
Tf::Rgba16Float => filtered_color | Tfc::STORAGE,
Tf::Rgba32Uint | Tf::Rgba32Sint => unfiltered_color | Tfc::STORAGE,
Tf::Rgba32Float => unfiltered_color | Tfc::STORAGE,
Tf::Depth32Float => Tfc::SAMPLED | Tfc::DEPTH_STENCIL_ATTACHMENT,
Tf::Depth24Plus => Tfc::SAMPLED | Tfc::DEPTH_STENCIL_ATTACHMENT,
Tf::Depth24PlusStencil8 => Tfc::SAMPLED | Tfc::DEPTH_STENCIL_ATTACHMENT,
Tf::R8Unorm => filterable_renderable,
Tf::R8Snorm => filterable,
Tf::R8Uint => renderable,
Tf::R8Sint => renderable,
Tf::R16Uint => renderable,
Tf::R16Sint => renderable,
Tf::R16Unorm => empty,
Tf::R16Snorm => empty,
Tf::R16Float => filterable,
Tf::Rg8Unorm => filterable_renderable,
Tf::Rg8Snorm => filterable,
Tf::Rg8Uint => renderable,
Tf::Rg8Sint => renderable,
Tf::R32Uint => renderable | storage,
Tf::R32Sint => renderable | storage,
Tf::R32Float => unfilterable | storage,
Tf::Rg16Uint => renderable,
Tf::Rg16Sint => renderable,
Tf::Rg16Unorm => empty,
Tf::Rg16Snorm => empty,
Tf::Rg16Float => filterable,
Tf::Rgba8Unorm | Tf::Rgba8UnormSrgb => filterable_renderable | storage,
Tf::Bgra8Unorm | Tf::Bgra8UnormSrgb => filterable_renderable,
Tf::Rgba8Snorm => filterable,
Tf::Rgba8Uint => renderable | storage,
Tf::Rgba8Sint => renderable | storage,
Tf::Rgb10a2Unorm => filterable_renderable,
Tf::Rg11b10Float => filterable,
Tf::Rg32Uint => renderable,
Tf::Rg32Sint => renderable,
Tf::Rg32Float => unfilterable,
Tf::Rgba16Uint => renderable | storage,
Tf::Rgba16Sint => renderable | storage,
Tf::Rgba16Unorm => empty,
Tf::Rgba16Snorm => empty,
Tf::Rgba16Float => filterable | storage,
Tf::Rgba32Uint => renderable | storage,
Tf::Rgba32Sint => renderable | storage,
Tf::Rgba32Float => unfilterable | storage,
Tf::Depth32Float | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => depth,
Tf::Rgb9e5Ufloat
| Tf::Bc1RgbaUnorm
| Tf::Bc1RgbaUnormSrgb
Expand Down Expand Up @@ -653,16 +681,12 @@ impl crate::Adapter<super::Api> for super::Adapter {
| Tf::EacRg11Snorm
| Tf::Astc {
block: _,
channel: AstcChannel::Unorm,
}
| Tf::Astc {
block: _,
channel: AstcChannel::UnormSrgb,
} => Tfc::SAMPLED | Tfc::SAMPLED_LINEAR,
channel: AstcChannel::Unorm | AstcChannel::UnormSrgb,
} => filterable,
Tf::Astc {
block: _,
channel: AstcChannel::Hdr,
} => unimplemented!(),
} => empty,
}
}

Expand Down Expand Up @@ -706,6 +730,32 @@ impl crate::Adapter<super::Api> for super::Adapter {
}
}

impl super::AdapterShared {
pub(super) unsafe fn get_buffer_sub_data(
&self,
gl: &glow::Context,
target: u32,
offset: i32,
dst_data: &mut [u8],
) {
if self
.private_caps
.contains(super::PrivateCapabilities::GET_BUFFER_SUB_DATA)
{
gl.get_buffer_sub_data(target, offset, dst_data);
} else {
log::error!("Fake map");
let length = dst_data.len();
let buffer_mapping =
gl.map_buffer_range(target, offset, length as _, glow::MAP_READ_BIT);

std::ptr::copy_nonoverlapping(buffer_mapping, dst_data.as_mut_ptr(), length);

gl.unmap_buffer(target);
}
}
}

// SAFE: WASM doesn't have threads
#[cfg(target_arch = "wasm32")]
unsafe impl Sync for super::Adapter {}
Expand Down
8 changes: 2 additions & 6 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ impl crate::Device<super::Api> for super::Device {
let ptr = if let Some(ref map_read_allocation) = buffer.data {
let mut guard = map_read_allocation.lock().unwrap();
let slice = guard.as_mut_slice();
gl.get_buffer_sub_data(buffer.target, 0, slice);
self.shared.get_buffer_sub_data(gl, buffer.target, 0, slice);
slice.as_mut_ptr()
} else {
gl.map_buffer_range(
Expand All @@ -478,11 +478,7 @@ impl crate::Device<super::Api> for super::Device {
}
unsafe fn unmap_buffer(&self, buffer: &super::Buffer) -> Result<(), crate::DeviceError> {
if let Some(raw) = buffer.raw {
if !self
.shared
.workarounds
.contains(super::Workarounds::EMULATE_BUFFER_MAP)
{
if buffer.data.is_none() {
let gl = &self.shared.context.lock();
gl.bind_buffer(buffer.target, Some(raw));
gl.unmap_buffer(buffer.target);
Expand Down
3 changes: 2 additions & 1 deletion wgpu-hal/src/gles/egl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, m
);

if cfg!(debug_assertions) && log_severity == log::Level::Error {
std::process::exit(1);
// Set canary and continue
crate::VALIDATION_CANARY.set();
}
}

Expand Down
2 changes: 2 additions & 0 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ bitflags::bitflags! {
const INDEX_BUFFER_ROLE_CHANGE = 1 << 5;
/// Indicates that the device supports disabling draw buffers
const CAN_DISABLE_DRAW_BUFFER = 1 << 6;
/// Supports `glGetBufferSubData`
const GET_BUFFER_SUB_DATA = 1 << 7;
}
}

Expand Down
Loading