1728: Move error formatting functionality  r=kvark a=scoopr

**Connections**
This is an attempt to implement #1082 

**Description**
This is a fairly straightforward move of the error formatting that were in wgpu-rs in to wgpu-code.

The enriching of some of the errors with the additional `ContextError` were still left with the wgpu-rs code, as I realised the current error messages refer to the API names as they appear in rust code and might not make sense for all the consumers of wgpu-core. It could be left as is and other consumers might enrich in their own ways, or the messages could be reformatted to be more conversational

**Testing**
Limited testing with the examples


Co-authored-by: Mikko Lehtonen <scoopr@iki.fi>
This commit is contained in:
bors[bot] 2021-08-03 14:59:38 +00:00 committed by GitHub
commit da39957062
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 391 additions and 341 deletions

View File

@ -1,5 +1,6 @@
use crate::{
device::{DeviceError, MissingDownlevelFlags, MissingFeatures, SHADER_STAGE_COUNT},
error::{ErrorFormatter, PrettyError},
hub::Resource,
id::{BindGroupLayoutId, BufferId, DeviceId, SamplerId, TextureViewId, Valid},
memory_init_tracker::MemoryInitTrackerAction,
@ -155,6 +156,33 @@ pub enum CreateBindGroupError {
ResourceUsageConflict(#[from] UsageConflict),
}
impl PrettyError for CreateBindGroupError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
match *self {
Self::BindingZeroSize(id) => {
fmt.buffer_label(&id);
}
Self::BindingRangeTooLarge { buffer, .. } => {
fmt.buffer_label(&buffer);
}
Self::BindingSizeTooSmall { buffer, .. } => {
fmt.buffer_label(&buffer);
}
Self::InvalidBuffer(id) => {
fmt.buffer_label(&id);
}
Self::InvalidTextureView(id) => {
fmt.texture_view_label(&id);
}
Self::InvalidSampler(id) => {
fmt.sampler_label(&id);
}
_ => {}
};
}
}
#[derive(Clone, Debug, Error)]
pub enum BindingZone {
#[error("stage {0:?}")]
@ -441,6 +469,15 @@ pub enum CreatePipelineLayoutError {
TooManyGroups { actual: usize, max: usize },
}
impl PrettyError for CreatePipelineLayoutError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
if let Self::InvalidBindGroupLayout(id) = *self {
fmt.bind_group_layout_label(&id);
};
}
}
#[derive(Clone, Debug, Error)]
pub enum PushConstantUploadError {
#[error("provided push constant with indices {offset}..{end_offset} overruns matching push constant range at index {idx}, with stage(s) {:?} and indices {:?}", range.stages, range.range)]

View File

@ -43,6 +43,7 @@ use crate::{
AttachmentData, Device, DeviceError, MissingDownlevelFlags, RenderPassContext,
SHADER_STAGE_COUNT,
},
error::{ErrorFormatter, PrettyError},
hub::{GlobalIdentityHandlerFactory, HalApi, Hub, Resource, Storage, Token},
id,
memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction},
@ -560,6 +561,17 @@ pub enum ExecutionError {
#[error("using {0} in a render bundle is not implemented")]
Unimplemented(&'static str),
}
impl PrettyError for ExecutionError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
match *self {
Self::DestroyedBuffer(id) => {
fmt.buffer_label(&id);
}
Self::Unimplemented(_reason) => {}
};
}
}
pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Label<'a>>;
@ -1161,6 +1173,14 @@ impl RenderBundleError {
inner: RenderBundleErrorInner::Device(DeviceError::Invalid),
};
}
impl PrettyError for RenderBundleError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
// This error is wrapper for the inner error,
// but the scope has useful labels
fmt.error(self);
self.scope.fmt_pretty(fmt);
}
}
impl<T, E> MapPassErr<T, RenderBundleError> for Result<T, E>
where

View File

@ -6,6 +6,7 @@ use crate::{
StateChange,
},
device::MissingDownlevelFlags,
error::{ErrorFormatter, PrettyError},
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
id,
memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction},
@ -161,6 +162,24 @@ pub enum ComputePassErrorInner {
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
}
impl PrettyError for ComputePassErrorInner {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
match *self {
Self::InvalidBindGroup(id) => {
fmt.bind_group_label(&id);
}
Self::InvalidPipeline(id) => {
fmt.compute_pipeline_label(&id);
}
Self::InvalidIndirectBuffer(id) => {
fmt.buffer_label(&id);
}
_ => {}
};
}
}
/// Error encountered when performing a compute pass.
#[derive(Clone, Debug, Error)]
#[error("{scope}")]
@ -169,6 +188,14 @@ pub struct ComputePassError {
#[source]
inner: ComputePassErrorInner,
}
impl PrettyError for ComputePassError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
// This error is wrapper for the inner error,
// but the scope has useful labels
fmt.error(self);
self.scope.fmt_pretty(fmt);
}
}
impl<T, E> MapPassErr<T, ComputePassError> for Result<T, E>
where

View File

@ -3,6 +3,7 @@
use crate::{
binding_model::PushConstantUploadError,
error::ErrorFormatter,
id,
track::UseExtendError,
validation::{MissingBufferUsageError, MissingTextureUsageError},
@ -93,6 +94,23 @@ pub enum RenderCommandError {
#[error("Support for {0} is not implemented yet")]
Unimplemented(&'static str),
}
impl crate::error::PrettyError for RenderCommandError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
match *self {
Self::InvalidBindGroup(id) => {
fmt.bind_group_label(&id);
}
Self::InvalidPipeline(id) => {
fmt.render_pipeline_label(&id);
}
Self::Buffer(id, ..) | Self::DestroyedBuffer(id) => {
fmt.buffer_label(&id);
}
_ => {}
};
}
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(

View File

@ -14,6 +14,7 @@ pub use self::query::*;
pub use self::render::*;
pub use self::transfer::*;
use crate::error::{ErrorFormatter, PrettyError};
use crate::{
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
id,
@ -499,3 +500,40 @@ pub enum PassErrorScope {
#[error("In a pop_debug_group command")]
PopDebugGroup,
}
impl PrettyError for PassErrorScope {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
// This error is not in the error chain, only notes are needed
match *self {
Self::Pass(id) => {
fmt.command_buffer_label(&id);
}
Self::SetBindGroup(id) => {
fmt.bind_group_label(&id);
}
Self::SetPipelineRender(id) => {
fmt.render_pipeline_label(&id);
}
Self::SetPipelineCompute(id) => {
fmt.compute_pipeline_label(&id);
}
Self::SetVertexBuffer(id) => {
fmt.buffer_label(&id);
}
Self::SetIndexBuffer(id) => {
fmt.buffer_label(&id);
}
Self::Draw {
pipeline: Some(id), ..
} => {
fmt.render_pipeline_label(&id);
}
Self::Dispatch {
pipeline: Some(id), ..
} => {
fmt.compute_pipeline_label(&id);
}
_ => {}
}
}
}

View File

@ -10,6 +10,7 @@ use crate::{
AttachmentData, MissingDownlevelFlags, MissingFeatures, RenderPassCompatibilityError,
RenderPassContext,
},
error::{ErrorFormatter, PrettyError},
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
id,
memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction},
@ -458,6 +459,15 @@ pub enum RenderPassErrorInner {
QueryUse(#[from] QueryUseError),
}
impl PrettyError for RenderPassErrorInner {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
if let Self::InvalidAttachment(id) = *self {
fmt.texture_view_label_with_key(&id, "attachment");
};
}
}
impl From<MissingBufferUsageError> for RenderPassErrorInner {
fn from(error: MissingBufferUsageError) -> Self {
Self::RenderCommand(error.into())
@ -478,6 +488,14 @@ pub struct RenderPassError {
#[source]
inner: RenderPassErrorInner,
}
impl PrettyError for RenderPassError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
// This error is wrapper for the inner error,
// but the scope has useful labels
fmt.error(self);
self.scope.fmt_pretty(fmt);
}
}
impl<T, E> MapPassErr<T, RenderPassError> for Result<T, E>
where

View File

@ -3,6 +3,7 @@ use crate::device::trace::Command as TraceCommand;
use crate::{
command::{CommandBuffer, CommandEncoderError},
conv,
error::{ErrorFormatter, PrettyError},
hub::{Global, GlobalIdentityHandlerFactory, HalApi, Storage, Token},
id::{BufferId, CommandEncoderId, TextureId},
memory_init_tracker::{MemoryInitKind, MemoryInitTrackerAction},
@ -92,6 +93,38 @@ pub enum TransferError {
CopyToForbiddenTextureFormat(wgt::TextureFormat),
}
impl PrettyError for TransferError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
match *self {
Self::InvalidBuffer(id) => {
fmt.buffer_label(&id);
}
Self::InvalidTexture(id) => {
fmt.texture_label(&id);
}
// Self::MissingCopySrcUsageFlag(buf_opt, tex_opt) => {
// if let Some(buf) = buf_opt {
// let name = crate::gfx_select!(buf => global.buffer_label(buf));
// ret.push_str(&format_label_line("source", &name));
// }
// if let Some(tex) = tex_opt {
// let name = crate::gfx_select!(tex => global.texture_label(tex));
// ret.push_str(&format_label_line("source", &name));
// }
// }
Self::MissingCopyDstUsageFlag(buf_opt, tex_opt) => {
if let Some(buf) = buf_opt {
fmt.buffer_label_with_key(&buf, "destination");
}
if let Some(tex) = tex_opt {
fmt.texture_label_with_key(&tex, "destination");
}
}
_ => {}
};
}
}
/// Error encountered while attempting to do a copy on a command encoder.
#[derive(Clone, Debug, Error)]
pub enum CopyError {

175
wgpu-core/src/error.rs Normal file
View File

@ -0,0 +1,175 @@
use core::fmt;
use std::error::Error;
use crate::{
gfx_select,
hub::{Global, IdentityManagerFactory},
};
pub struct ErrorFormatter<'a> {
writer: &'a mut dyn fmt::Write,
global: &'a Global<IdentityManagerFactory>,
}
impl<'a> ErrorFormatter<'a> {
pub fn error(&mut self, err: &dyn Error) {
writeln!(self.writer, " {}", err).expect("Error formatting error");
}
pub fn note(&mut self, note: &dyn fmt::Display) {
writeln!(self.writer, " note: {}", note).expect("Error formatting error");
}
pub fn label(&mut self, label_key: &str, label_value: &str) {
if !label_key.is_empty() && !label_value.is_empty() {
self.note(&format!("{} = `{}`", label_key, label_value));
}
}
pub fn bind_group_label(&mut self, id: &crate::id::BindGroupId) {
let global = self.global;
let label = gfx_select!(id => global.bind_group_label(*id));
self.label("bind group", &label);
}
pub fn bind_group_layout_label(&mut self, id: &crate::id::BindGroupLayoutId) {
let global = self.global;
let label = gfx_select!(id => global.bind_group_layout_label(*id));
self.label("bind group layout", &label);
}
pub fn render_pipeline_label(&mut self, id: &crate::id::RenderPipelineId) {
let global = self.global;
let label = gfx_select!(id => global.render_pipeline_label(*id));
self.label("render pipeline", &label);
}
pub fn compute_pipeline_label(&mut self, id: &crate::id::ComputePipelineId) {
let global = self.global;
let label = gfx_select!(id => global.compute_pipeline_label(*id));
self.label("compute pipeline", &label);
}
pub fn buffer_label_with_key(&mut self, id: &crate::id::BufferId, key: &str) {
let global = self.global;
let label = gfx_select!(id => global.buffer_label(*id));
self.label(key, &label);
}
pub fn buffer_label(&mut self, id: &crate::id::BufferId) {
self.buffer_label_with_key(id, "buffer");
}
pub fn texture_label_with_key(&mut self, id: &crate::id::TextureId, key: &str) {
let global = self.global;
let label = gfx_select!(id => global.texture_label(*id));
self.label(key, &label);
}
pub fn texture_label(&mut self, id: &crate::id::TextureId) {
self.texture_label_with_key(id, "texture");
}
pub fn texture_view_label_with_key(&mut self, id: &crate::id::TextureViewId, key: &str) {
let global = self.global;
let label = gfx_select!(id => global.texture_view_label(*id));
self.label(key, &label);
}
pub fn texture_view_label(&mut self, id: &crate::id::TextureViewId) {
self.texture_view_label_with_key(id, "texture view");
}
pub fn sampler_label(&mut self, id: &crate::id::SamplerId) {
let global = self.global;
let label = gfx_select!(id => global.sampler_label(*id));
self.label("sampler", &label);
}
pub fn command_buffer_label(&mut self, id: &crate::id::CommandBufferId) {
let global = self.global;
let label = gfx_select!(id => global.command_buffer_label(*id));
self.label("command buffer", &label);
}
}
pub trait PrettyError: Error + Sized {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
}
}
pub fn format_pretty_any(
writer: &mut dyn fmt::Write,
global: &Global<IdentityManagerFactory>,
error: &(dyn Error + 'static),
) {
let mut fmt = ErrorFormatter { writer, global };
if let Some(pretty_err) = error.downcast_ref::<ContextError>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::command::RenderCommandError>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::binding_model::CreateBindGroupError>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) =
error.downcast_ref::<crate::binding_model::CreatePipelineLayoutError>()
{
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::command::ExecutionError>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::command::RenderPassErrorInner>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::command::RenderPassError>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::command::ComputePassErrorInner>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::command::ComputePassError>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::command::RenderBundleError>() {
return pretty_err.fmt_pretty(&mut fmt);
}
if let Some(pretty_err) = error.downcast_ref::<crate::command::TransferError>() {
return pretty_err.fmt_pretty(&mut fmt);
}
// default
fmt.error(error)
}
#[derive(Debug)]
pub struct ContextError {
pub string: &'static str,
pub cause: Box<dyn Error + Send + Sync + 'static>,
pub label_key: &'static str,
pub label: String,
}
impl PrettyError for ContextError {
fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
fmt.error(self);
fmt.label(self.label_key, &self.label);
}
}
impl fmt::Display for ContextError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "In {}", self.string)
}
}
impl Error for ContextError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(self.cause.as_ref())
}
}

View File

@ -34,6 +34,7 @@ pub mod binding_model;
pub mod command;
mod conv;
pub mod device;
pub mod error;
pub mod hub;
pub mod id;
pub mod instance;

View File

@ -1,9 +1,8 @@
use crate::{
backend::{error::ContextError, native_gpu_future},
AdapterInfo, BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource, BufferBinding,
CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor,
DownlevelCapabilities, Features, Label, Limits, LoadOp, MapMode, Operations,
PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor,
backend::native_gpu_future, AdapterInfo, BindGroupDescriptor, BindGroupLayoutDescriptor,
BindingResource, BufferBinding, CommandEncoderDescriptor, ComputePassDescriptor,
ComputePipelineDescriptor, DownlevelCapabilities, Features, Label, Limits, LoadOp, MapMode,
Operations, PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor,
SamplerDescriptor, ShaderModuleDescriptor, ShaderModuleDescriptorSpirV, ShaderSource,
SwapChainStatus, TextureDescriptor, TextureFormat, TextureViewDescriptor,
};
@ -144,7 +143,7 @@ impl Context {
label: Label,
string: &'static str,
) {
let error = ContextError {
let error = wgc::error::ContextError {
string,
cause: Box::new(cause),
label: label.unwrap_or_default().to_string(),
@ -186,6 +185,25 @@ impl Context {
) -> ! {
panic!("Error in {}: {}", string, cause);
}
fn format_error(&self, err: &(impl Error + 'static)) -> String {
let global = self.global();
let mut err_descs = vec![];
let mut err_str = String::new();
wgc::error::format_pretty_any(&mut err_str, global, err);
err_descs.push(err_str);
let mut source_opt = err.source();
while let Some(source) = source_opt {
let mut source_str = String::new();
wgc::error::format_pretty_any(&mut source_str, global, source);
err_descs.push(source_str);
source_opt = source.source();
}
format!("Validation Error\n\nCaused by:\n{}", err_descs.join(""))
}
}
mod pass_impl {

View File

@ -1,333 +0,0 @@
use std::{error::Error, fmt};
#[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,
}
impl fmt::Display for ContextError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "In {}", self.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![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(super) fn format_note_line(note: &dyn fmt::Display) -> String {
format!(" note: {}\n", note)
}
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 {
format_note_line(&format!("{} = `{}`", label_key, label_value))
}
}
trait AsDisplay {
fn as_display(&self) -> &dyn fmt::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: &super::Context) -> String {
format_error_line(self.as_display())
}
}
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: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
Self::InvalidBindGroup(id) => {
let name = wgc::gfx_select!(id => global.bind_group_label(id));
ret.push_str(&format_label_line("bind group", &name));
}
Self::InvalidPipeline(id) => {
let name = wgc::gfx_select!(id => global.render_pipeline_label(id));
ret.push_str(&format_label_line("render pipeline", &name));
}
Self::Buffer(id, ..) | Self::DestroyedBuffer(id) => {
let name = wgc::gfx_select!(id => global.buffer_label(id));
ret.push_str(&format_label_line("buffer", &name));
}
_ => {}
};
ret
}
}
impl PrettyError for wgc::binding_model::CreateBindGroupError {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
Self::InvalidBuffer(id) => {
let name = wgc::gfx_select!(id => global.buffer_label(id));
ret.push_str(&format_label_line("buffer", &name));
}
Self::InvalidTextureView(id) => {
let name = wgc::gfx_select!(id => global.texture_view_label(id));
ret.push_str(&format_label_line("texture view", &name));
}
Self::InvalidSampler(id) => {
let name = wgc::gfx_select!(id => global.sampler_label(id));
ret.push_str(&format_label_line("sampler", &name));
}
_ => {}
};
ret
}
}
impl PrettyError for wgc::binding_model::CreatePipelineLayoutError {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
if let Self::InvalidBindGroupLayout(id) = *self {
let name = wgc::gfx_select!(id => global.bind_group_layout_label(id));
ret.push_str(&format_label_line("bind group layout", &name));
};
ret
}
}
impl PrettyError for wgc::command::ExecutionError {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
Self::DestroyedBuffer(id) => {
let name = wgc::gfx_select!(id => global.buffer_label(id));
ret.push_str(&format_label_line("buffer", &name));
}
Self::Unimplemented(_reason) => {}
};
ret
}
}
impl PrettyError for wgc::command::RenderPassErrorInner {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
if let Self::InvalidAttachment(id) = *self {
let name = wgc::gfx_select!(id => global.texture_view_label(id));
ret.push_str(&format_label_line("attachment", &name));
};
ret
}
}
impl PrettyError for wgc::command::RenderPassError {
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::ComputePassError {
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: &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::ComputePassErrorInner {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
Self::InvalidBindGroup(id) => {
let name = wgc::gfx_select!(id => global.bind_group_label(id));
ret.push_str(&format_label_line("bind group", &name));
}
Self::InvalidPipeline(id) => {
let name = wgc::gfx_select!(id => global.compute_pipeline_label(id));
ret.push_str(&format_label_line("pipeline", &name));
}
Self::InvalidIndirectBuffer(id) => {
let name = wgc::gfx_select!(id => global.buffer_label(id));
ret.push_str(&format_label_line("indirect buffer", &name));
}
_ => {}
};
ret
}
}
impl PrettyError for wgc::command::TransferError {
fn fmt_pretty(&self, context: &super::Context) -> String {
let global = context.global();
let mut ret = format_error_line(self);
match *self {
Self::InvalidBuffer(id) => {
let name = wgc::gfx_select!(id => global.buffer_label(id));
ret.push_str(&format_label_line("label", &name));
}
Self::InvalidTexture(id) => {
let name = wgc::gfx_select!(id => global.texture_label(id));
ret.push_str(&format_label_line("texture", &name));
}
// Self::MissingCopySrcUsageFlag(buf_opt, tex_opt) => {
// if let Some(buf) = buf_opt {
// let name = wgc::gfx_select!(buf => global.buffer_label(buf));
// ret.push_str(&format_label_line("source", &name));
// }
// if let Some(tex) = tex_opt {
// let name = wgc::gfx_select!(tex => global.texture_label(tex));
// ret.push_str(&format_label_line("source", &name));
// }
// }
Self::MissingCopyDstUsageFlag(buf_opt, tex_opt) => {
if let Some(buf) = buf_opt {
let name = wgc::gfx_select!(buf => global.buffer_label(buf));
ret.push_str(&format_label_line("destination", &name));
}
if let Some(tex) = tex_opt {
let name = wgc::gfx_select!(tex => global.texture_label(tex));
ret.push_str(&format_label_line("destination", &name));
}
}
_ => {}
};
ret
}
}
impl PrettyError for wgc::command::PassErrorScope {
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 {
Self::Pass(id) => {
let name = wgc::gfx_select!(id => global.command_buffer_label(id));
format_label_line("command buffer", &name)
}
Self::SetBindGroup(id) => {
let name = wgc::gfx_select!(id => global.bind_group_label(id));
format_label_line("bind group", &name)
}
Self::SetPipelineRender(id) => {
let name = wgc::gfx_select!(id => global.render_pipeline_label(id));
format_label_line("render pipeline", &name)
}
Self::SetPipelineCompute(id) => {
let name = wgc::gfx_select!(id => global.compute_pipeline_label(id));
format_label_line("compute pipeline", &name)
}
Self::SetVertexBuffer(id) => {
let name = wgc::gfx_select!(id => global.buffer_label(id));
format_label_line("buffer", &name)
}
Self::SetIndexBuffer(id) => {
let name = wgc::gfx_select!(id => global.buffer_label(id));
format_label_line("buffer", &name)
}
Self::Draw { pipeline, .. } => {
if let Some(id) = pipeline {
let name = wgc::gfx_select!(id => global.render_pipeline_label(id));
format_label_line("render pipeline", &name)
} else {
String::new()
}
}
Self::Dispatch { pipeline, .. } => {
if let Some(id) = pipeline {
let name = wgc::gfx_select!(id => global.compute_pipeline_label(id));
format_label_line("compute pipeline", &name)
} else {
String::new()
}
}
_ => String::new(),
}
}
}

View File

@ -6,8 +6,6 @@ pub(crate) use web::{BufferMappedRange, Context};
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
mod direct;
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
mod error;
#[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
pub(crate) use direct::{BufferMappedRange, Context};