633: Port to the updated wgpu error model r=scoopr a=kvark

Depends on https://github.com/gfx-rs/wgpu/pull/1034

I removed most of the helping sugar we had before, in exchange for simple `match` and a `handle_error` function.
I believe this way it's easier to maintain and debug (stepping through closures is a pain today).

Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
bors[bot] 2020-11-23 23:04:54 +00:00 committed by GitHub
commit 6f712d59bd
9 changed files with 603 additions and 532 deletions

View File

@ -26,14 +26,14 @@ vulkan-portability = ["wgc/gfx-backend-vulkan", "gfx-backend-vulkan"]
package = "wgpu-core"
#version = "0.6"
git = "https://github.com/gfx-rs/wgpu"
rev = "feac96d3151f08188bdd270fdf021117944c01b0"
rev = "385ee9fecfbe185b63d788b4007f131a6ef34cf0"
features = ["raw-window-handle"]
[dependencies.wgt]
package = "wgpu-types"
#version = "0.6"
git = "https://github.com/gfx-rs/wgpu"
rev = "feac96d3151f08188bdd270fdf021117944c01b0"
rev = "385ee9fecfbe185b63d788b4007f131a6ef34cf0"
[dependencies]
arrayvec = "0.5"

View File

@ -36,6 +36,7 @@ async fn create_red_image_with_dimensions(
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
shader_validation: true,

View File

@ -149,6 +149,7 @@ async fn setup<E: Example>(title: &str) -> Setup {
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: (optional_features & adapter_features) | required_features,
limits: needed_limits,
shader_validation: true,

View File

@ -34,6 +34,7 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
shader_validation: true,

View File

@ -21,6 +21,7 @@ async fn run(event_loop: EventLoop<()>, window: Window, swapchain_format: wgpu::
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
shader_validation: true,

View File

@ -85,6 +85,7 @@ async fn run(
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
shader_validation: true,

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +1,90 @@
use std::{error::Error, fmt::Display};
use std::{error::Error, fmt};
use super::Context;
pub(crate) fn format_error(err: &(impl Error + 'static), context: &Context) -> String {
let mut err_descs = Vec::new();
err_descs.push(fmt_pretty_any(err, context));
let mut source_opt = err.source();
while let Some(source) = source_opt {
err_descs.push(fmt_pretty_any(source, context));
source_opt = source.source();
}
let desc = format!("Validation Error\n\nCaused by:\n{}", err_descs.join(""));
desc
#[derive(Debug)]
pub(super) struct ContextError {
pub string: &'static str,
pub cause: Box<dyn Error + Send + Sync + 'static>,
pub label_key: &'static str,
pub label: String,
}
fn fmt_pretty_any(error: &(dyn Error + 'static), context: &Context) -> String {
if let Some(pretty_err) = error.downcast_ref::<super::direct::ContextError>() {
return pretty_err.fmt_pretty(context);
impl fmt::Display for ContextError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "In {}", self.string)
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::RenderCommandError>() {
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::binding_model::CreateBindGroupError>() {
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::binding_model::CreatePipelineLayoutError>()
{
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::ExecutionError>() {
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::RenderPassErrorInner>() {
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::RenderPassError>() {
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::ComputePassErrorInner>() {
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::ComputePassError>() {
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::RenderBundleError>() {
return pretty_err.fmt_pretty(context);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::TransferError>() {
return pretty_err.fmt_pretty(context);
}
// default
format_error_line(error.as_display())
}
pub(crate) fn format_error_line(err: &dyn Display) -> String {
impl Error for ContextError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(self.cause.as_ref())
}
}
impl super::Context {
pub(super) fn format_error(&self, err: &(impl Error + 'static)) -> String {
let mut err_descs = Vec::new();
err_descs.push(self.format_pretty_any(err));
let mut source_opt = err.source();
while let Some(source) = source_opt {
err_descs.push(self.format_pretty_any(source));
source_opt = source.source();
}
format!("Validation Error\n\nCaused by:\n{}", err_descs.join(""))
}
fn format_pretty_any(&self, error: &(dyn Error + 'static)) -> String {
if let Some(pretty_err) = error.downcast_ref::<ContextError>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::RenderCommandError>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::binding_model::CreateBindGroupError>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) =
error.downcast_ref::<wgc::binding_model::CreatePipelineLayoutError>()
{
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::ExecutionError>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::RenderPassErrorInner>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::RenderPassError>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::ComputePassErrorInner>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::ComputePassError>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::RenderBundleError>() {
return pretty_err.fmt_pretty(self);
}
if let Some(pretty_err) = error.downcast_ref::<wgc::command::TransferError>() {
return pretty_err.fmt_pretty(self);
}
// default
format_error_line(error.as_display())
}
}
pub(super) fn format_error_line(err: &dyn fmt::Display) -> String {
format!(" {}\n", err)
}
pub(crate) fn format_note_line(note: &dyn Display) -> String {
pub(super) fn format_note_line(note: &dyn fmt::Display) -> String {
format!(" note: {}\n", note)
}
pub(crate) fn format_label_line(label_key: &str, label_value: &str) -> String {
pub(super) fn format_label_line(label_key: &str, label_value: &str) -> String {
if label_key.is_empty() || label_value.is_empty() {
String::new()
} else {
@ -74,29 +93,29 @@ pub(crate) fn format_label_line(label_key: &str, label_value: &str) -> String {
}
trait AsDisplay {
fn as_display(&self) -> &dyn Display;
fn as_display(&self) -> &dyn fmt::Display;
}
impl<T: Display> AsDisplay for T {
fn as_display(&self) -> &dyn Display {
impl<T: fmt::Display> AsDisplay for T {
fn as_display(&self) -> &dyn fmt::Display {
self
}
}
pub trait PrettyError: Error {
fn fmt_pretty(&self, _context: &Context) -> String {
fn fmt_pretty(&self, _context: &super::Context) -> String {
format_error_line(self.as_display())
}
}
impl PrettyError for super::direct::ContextError {
fn fmt_pretty(&self, _context: &Context) -> String {
impl PrettyError for ContextError {
fn fmt_pretty(&self, _context: &super::Context) -> String {
format_error_line(self.as_display()) + &format_label_line(self.label_key, &self.label)
}
}
impl PrettyError for wgc::command::RenderCommandError {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
@ -118,7 +137,7 @@ impl PrettyError for wgc::command::RenderCommandError {
}
}
impl PrettyError for wgc::binding_model::CreateBindGroupError {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
@ -141,7 +160,7 @@ impl PrettyError for wgc::binding_model::CreateBindGroupError {
}
impl PrettyError for wgc::binding_model::CreatePipelineLayoutError {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
@ -156,7 +175,7 @@ impl PrettyError for wgc::binding_model::CreatePipelineLayoutError {
}
impl PrettyError for wgc::command::ExecutionError {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
@ -170,7 +189,7 @@ impl PrettyError for wgc::command::ExecutionError {
}
impl PrettyError for wgc::command::RenderPassErrorInner {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
@ -185,7 +204,7 @@ impl PrettyError for wgc::command::RenderPassErrorInner {
}
impl PrettyError for wgc::command::RenderPassError {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
// This error is wrapper for the inner error,
// but the scope has useful labels
format_error_line(self) + &self.scope.fmt_pretty(context)
@ -193,14 +212,14 @@ impl PrettyError for wgc::command::RenderPassError {
}
impl PrettyError for wgc::command::ComputePassError {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
// This error is wrapper for the inner error,
// but the scope has useful labels
format_error_line(self) + &self.scope.fmt_pretty(context)
}
}
impl PrettyError for wgc::command::RenderBundleError {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
// This error is wrapper for the inner error,
// but the scope has useful labels
format_error_line(self) + &self.scope.fmt_pretty(context)
@ -208,7 +227,7 @@ impl PrettyError for wgc::command::RenderBundleError {
}
impl PrettyError for wgc::command::ComputePassErrorInner {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
@ -231,7 +250,7 @@ impl PrettyError for wgc::command::ComputePassErrorInner {
}
impl PrettyError for wgc::command::TransferError {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
@ -270,7 +289,7 @@ impl PrettyError for wgc::command::TransferError {
}
impl PrettyError for wgc::command::PassErrorScope {
fn fmt_pretty(&self, context: &Context) -> String {
fn fmt_pretty(&self, context: &super::Context) -> String {
// This error is not in the error chain, only notes are needed
let global = context.global();
match *self {

View File

@ -35,10 +35,10 @@ pub use wgt::{
AddressMode, Backend, BackendBit, BindGroupLayoutEntry, BindingType, BlendDescriptor,
BlendFactor, BlendOperation, BufferAddress, BufferSize, BufferUsage, Color,
ColorStateDescriptor, ColorWrite, CommandBufferDescriptor, CompareFunction, CullMode,
DepthStencilStateDescriptor, DeviceDescriptor, DynamicOffset, Extent3d, Features, FilterMode,
FrontFace, IndexFormat, InputStepMode, Limits, Origin3d, PolygonMode, PowerPreference,
PresentMode, PrimitiveTopology, PushConstantRange, RasterizationStateDescriptor,
SamplerBorderColor, ShaderLocation, ShaderStage, StencilOperation, StencilStateDescriptor,
DepthStencilStateDescriptor, DynamicOffset, Extent3d, Features, FilterMode, FrontFace,
IndexFormat, InputStepMode, Limits, Origin3d, PolygonMode, PowerPreference, PresentMode,
PrimitiveTopology, PushConstantRange, RasterizationStateDescriptor, SamplerBorderColor,
ShaderLocation, ShaderStage, StencilOperation, StencilStateDescriptor,
StencilStateFaceDescriptor, SwapChainDescriptor, SwapChainStatus, TextureAspect,
TextureComponentType, TextureDataLayout, TextureDimension, TextureFormat, TextureUsage,
TextureViewDimension, VertexAttributeDescriptor, VertexFormat, BIND_BUFFER_ALIGNMENT,
@ -969,58 +969,21 @@ pub struct RenderPassDepthStencilAttachmentDescriptor<'a> {
// The underlying types are also exported so that documentation shows up for them
/// Object label.
pub type Label<'a> = Option<&'a str>;
pub use wgt::RequestAdapterOptions as RequestAdapterOptionsBase;
/// Additional information required when requesting an adapter.
pub type RequestAdapterOptions<'a> = RequestAdapterOptionsBase<&'a Surface>;
/// Describes a [`Device`].
pub type DeviceDescriptor<'a> = wgt::DeviceDescriptor<Label<'a>>;
/// Describes a [`Buffer`].
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct BufferDescriptor<'a> {
/// Debug label of a buffer. This will show up in graphics debuggers for easy identification.
pub label: Option<&'a str>,
/// Size of a buffer.
pub size: BufferAddress,
/// Usages of a buffer. If the buffer is used in any way that isn't specified here, the operation
/// will panic.
pub usage: BufferUsage,
/// Allows a buffer to be mapped immediately after they are made. It does not have to be [`BufferUsage::MAP_READ`] or
/// [`BufferUsage::MAP_WRITE`], all buffers are allowed to be mapped at creation.
pub mapped_at_creation: bool,
}
pub type BufferDescriptor<'a> = wgt::BufferDescriptor<Label<'a>>;
/// Describes a [`CommandEncoder`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
pub struct CommandEncoderDescriptor<'a> {
/// Debug label for the command encoder. This will show up in graphics debuggers for easy identification.
pub label: Option<&'a str>,
}
pub type CommandEncoderDescriptor<'a> = wgt::CommandEncoderDescriptor<Label<'a>>;
/// Describes a [`RenderBundle`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)]
pub struct RenderBundleDescriptor<'a> {
/// Debug label of the render bundle encoder. This will show up in graphics debuggers for easy identification.
pub label: Option<&'a str>,
}
pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Label<'a>>;
/// Describes a [`Texture`].
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TextureDescriptor<'a> {
/// Debug label of the texture. This will show up in graphics debuggers for easy identification.
pub label: Option<&'a str>,
/// Size of the texture. For a regular 1D/2D texture, the unused sizes will be 1. For 2DArray textures, Z is the
/// number of 2D textures in that array.
pub size: Extent3d,
/// Mip count of texture. For a texture with no extra mips, this must be 1.
pub mip_level_count: u32,
/// Sample count of texture. If this is not 1, texture must have [`BindingType::SampledTexture::multisampled`] set to true.
pub sample_count: u32,
/// Dimensions of the texture.
pub dimension: TextureDimension,
/// Format of the texture.
pub format: TextureFormat,
/// Allowed usages of the texture. If used in other ways, the operation will panic.
pub usage: TextureUsage,
}
pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>>;
/// Describes a [`TextureView`].
#[derive(Clone, Debug, Default, PartialEq)]