Skip to content

Commit

Permalink
check bindgroup samplers
Browse files Browse the repository at this point in the history
  • Loading branch information
robtfm committed Aug 12, 2024
1 parent c89ef89 commit 2553b61
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 3 deletions.
3 changes: 3 additions & 0 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,9 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
Err(AsBindGroupError::RetryNextUpdate) => {
Err(PrepareAssetError::RetryNextUpdate(material))
}
Err(AsBindGroupError::InvalidData(msg)) => {
Err(PrepareAssetError::InvalidData(msg))
}
}
}
}
Expand Down
41 changes: 40 additions & 1 deletion crates/bevy_render/macros/src/as_bind_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,14 +355,53 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {

let fallback_image = get_fallback_image(&render_path, *dimension);

let expected_samplers = match sampler_binding_type {
SamplerBindingType::Filtering => {
quote!( [#render_path::render_resource::TextureSampleType::Float { filterable: true }] )
}
SamplerBindingType::NonFiltering => quote!([
#render_path::render_resource::TextureSampleType::Float { filterable: false },
#render_path::render_resource::TextureSampleType::Sint,
#render_path::render_resource::TextureSampleType::Uint,
]),
SamplerBindingType::Comparison => {
quote!( [#render_path::render_resource::TextureSampleType::Depth] )
}
};

// insert fallible texture-based entries at 0 so that if we fail here, we exit before allocating any buffers
binding_impls.insert(0, quote! {
(
#binding_index,
#render_path::render_resource::OwnedBindingResource::Sampler({
let handle: Option<&#asset_path::Handle<#render_path::texture::Image>> = (&self.#field_name).into();
if let Some(handle) = handle {
images.get(handle).ok_or_else(|| #render_path::render_resource::AsBindGroupError::RetryNextUpdate)?.sampler.clone()
let image = images.get(handle).ok_or_else(|| #render_path::render_resource::AsBindGroupError::RetryNextUpdate)?;

let Some(sample_type) = image.texture_format.sample_type(None, None) else {
return Err(#render_path::render_resource::AsBindGroupError::InvalidData(
format!(
"binding index {}: no sampler for format `{:?}`",
#binding_index,
image.texture_format,
)
));
};

let valid = #expected_samplers.contains(&sample_type);

if !valid {
return Err(#render_path::render_resource::AsBindGroupError::InvalidData(
format!(
"binding index {}: image sampler type `{:?}` must be one of `{:?}`",
#binding_index,
sample_type,
#expected_samplers
)
));
}

image.sampler.clone()
} else {
#fallback_image.sampler.clone()
}
Expand Down
10 changes: 9 additions & 1 deletion crates/bevy_render/src/render_asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use bevy_ecs::{
};
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render_macros::ExtractResource;
use bevy_utils::{tracing::debug, HashMap, HashSet};
use bevy_utils::{tracing::{debug, warn}, HashMap, HashSet};
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use thiserror::Error;
Expand All @@ -18,6 +18,8 @@ use thiserror::Error;
pub enum PrepareAssetError<E: Send + Sync + 'static> {
#[error("Failed to prepare asset")]
RetryNextUpdate(E),
#[error("The bindgroup data is invalid: {0}")]
InvalidData(String),
}

/// Describes how an asset gets extracted and prepared for rendering.
Expand Down Expand Up @@ -349,6 +351,9 @@ pub fn prepare_assets<A: RenderAsset>(
Err(PrepareAssetError::RetryNextUpdate(extracted_asset)) => {
prepare_next_frame.assets.push((id, extracted_asset));
}
Err(PrepareAssetError::InvalidData(msg)) => {
warn!("Material2d<{}> Bind group contains invalid data: {msg}", std::any::type_name::<A>());
}
}
}

Expand Down Expand Up @@ -381,6 +386,9 @@ pub fn prepare_assets<A: RenderAsset>(
Err(PrepareAssetError::RetryNextUpdate(extracted_asset)) => {
prepare_next_frame.assets.push((id, extracted_asset));
}
Err(PrepareAssetError::InvalidData(msg)) => {
warn!("Material2d<{}> Bind group contains invalid data: {msg}", std::any::type_name::<A>());
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_render/src/render_resource/bind_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ pub enum AsBindGroupError {
/// The bind group could not be generated. Try again next frame.
#[error("The bind group could not be generated")]
RetryNextUpdate,
#[error("The bindgroup data is invalid: {0}")]
InvalidData(String),
}

/// A prepared bind group returned as a result of [`AsBindGroup::as_bind_group`].
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_render/src/texture/image_loader.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ffi::OsStr;

use bevy_asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext};
use bevy_ecs::prelude::{FromWorld, World};
use thiserror::Error;
Expand Down Expand Up @@ -97,7 +99,7 @@ impl AssetLoader for ImageLoader {
let image_type = match settings.format {
ImageFormatSetting::FromExtension => {
// use the file extension for the image type
let ext = load_context.path().extension().unwrap().to_str().unwrap();
let ext = load_context.path().extension().and_then(OsStr::to_str).unwrap_or("image");
ImageType::Extension(ext)
}
ImageFormatSetting::Format(format) => ImageType::Format(format),
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_sprite/src/mesh2d/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,9 @@ impl<M: Material2d> RenderAsset for PreparedMaterial2d<M> {
Err(AsBindGroupError::RetryNextUpdate) => {
Err(PrepareAssetError::RetryNextUpdate(material))
}
Err(AsBindGroupError::InvalidData(msg)) => {
Err(PrepareAssetError::InvalidData(msg))
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_ui/src/render/ui_material_pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,9 @@ impl<M: UiMaterial> RenderAsset for PreparedUiMaterial<M> {
Err(AsBindGroupError::RetryNextUpdate) => {
Err(PrepareAssetError::RetryNextUpdate(material))
}
Err(AsBindGroupError::InvalidData(msg)) => {
Err(PrepareAssetError::InvalidData(msg))
}
}
}
}
Expand Down

0 comments on commit 2553b61

Please sign in to comment.