Compare commits

...

10 Commits

9 changed files with 168 additions and 123 deletions

View File

@ -121,7 +121,6 @@ rust.unused_crate_dependencies = "warn"
rust.unused_lifetimes = "warn"
rust.unused_macro_rules = "warn"
rust.unused_results = "warn"
rust.variant_size_differences = "warn"
# We want to annotate unsafe inside unsafe fns

View File

@ -1,33 +1,25 @@
//! Loadable
// Imports
use {
crate::AppError,
core::{fmt, task::Poll},
futures::FutureExt,
std::task,
};
use {crate::AppError, core::task::Poll, futures::FutureExt, std::task};
/// Loadable value
pub struct Loadable<T, F> {
#[derive(Debug)]
pub struct Loadable<T> {
/// Current value, if any
value: Option<T>,
/// Loading task
task: Option<tokio::task::JoinHandle<T>>,
/// Loader
loader: F,
}
impl<T, F> Loadable<T, F> {
impl<T> Loadable<T> {
/// Creates a new, empty, loadable
#[must_use]
pub fn new(loader: F) -> Self {
pub fn new() -> Self {
Self {
value: None,
task: None,
loader,
task: None,
}
}
@ -52,11 +44,14 @@ impl<T, F> Loadable<T, F> {
self.value.take()
}
/// Tries to load the inner value
pub fn try_load<Args>(&mut self, args: Args) -> Option<&mut T>
/// Tries to load the inner value.
///
/// If the value isn't loading, `spawn_task` is called to spawn a
/// task that loads the value
pub fn try_load<F>(&mut self, spawn_task: F) -> Option<&mut T>
where
T: Send + 'static,
F: Loader<Args, T>,
F: FnOnce() -> Result<tokio::task::JoinHandle<T>, AppError>,
{
// If the value is loaded, we're done
// Note: We can't use if-let due to a borrow-checker limitation
@ -88,7 +83,7 @@ impl<T, F> Loadable<T, F> {
}
},
None => {
match self.loader.spawn(args) {
match spawn_task() {
Ok(task) => self.task = Some(task),
Err(err) => tracing::warn!("Unable to spawn task: {}", err.pretty()),
}
@ -99,18 +94,8 @@ impl<T, F> Loadable<T, F> {
}
}
/// Loader trait
pub trait Loader<Args, T> {
/// Spawns the loader future
fn spawn(&mut self, args: Args) -> Result<tokio::task::JoinHandle<T>, AppError>;
}
impl<T: fmt::Debug, F> fmt::Debug for Loadable<T, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Loadable")
.field("value", &self.value)
.field("task", &self.task)
.field("loader", &"..")
.finish()
impl<T> Default for Loadable<T> {
fn default() -> Self {
Self::new()
}
}

View File

@ -14,7 +14,6 @@ use {
app_error::Context,
core::sync::atomic::{self, AtomicBool},
image::DynamicImage,
std::path::Path,
wgpu::{util as wgpu_util, util::DeviceExt},
zsw_util::AppError,
};
@ -76,7 +75,7 @@ impl Wgpu {
/// Creates a texture from an image.
pub fn create_texture_from_image(
&self,
path: &Path,
label: &str,
image: DynamicImage,
) -> Result<(wgpu::Texture, wgpu::TextureView), AppError> {
// Get the image's format, converting if necessary.
@ -104,7 +103,7 @@ impl Wgpu {
);
let texture_descriptor = wgpu::TextureDescriptor {
label: Some(&format!("[zsw] Image ({path:?})")),
label: Some(label),
size: wgpu::Extent3d {
width: image.width(),
height: image.height(),
@ -125,7 +124,10 @@ impl Wgpu {
image.as_bytes(),
);
let texture_view_descriptor = wgpu::TextureViewDescriptor::default();
let texture_view_descriptor = wgpu::TextureViewDescriptor {
label: Some(&format!("{label}-view")),
..Default::default()
};
let texture_view = texture.create_view(&texture_view_descriptor);
Ok((texture, texture_view))
@ -136,7 +138,7 @@ impl Wgpu {
async fn create_device(adapter: &wgpu::Adapter) -> Result<(wgpu::Device, wgpu::Queue), AppError> {
// Request the device without any features
let device_descriptor = wgpu::DeviceDescriptor {
label: Some("[zsw] Device"),
label: Some("zsw-device"),
required_features: wgpu::Features::default(),
required_limits: wgpu::Limits::default(),
memory_hints: wgpu::MemoryHints::default(),
@ -148,12 +150,6 @@ async fn create_device(adapter: &wgpu::Adapter) -> Result<(wgpu::Device, wgpu::Q
.await
.context("Unable to request device")?;
// Configure the device to not panic on errors
device.on_uncaptured_error(Box::new(|err| {
let err = AppError::new(&err);
tracing::error!("Wgpu error: {}", err.pretty());
}));
Ok((device, queue))
}
@ -191,7 +187,7 @@ async fn create_adapter(instance: &wgpu::Instance) -> Result<wgpu::Adapter, AppE
fn create_empty_image_texture(device: &wgpu::Device) -> (wgpu::Texture, wgpu::TextureView) {
// TODO: Pass some view formats?
let texture_descriptor = wgpu::TextureDescriptor {
label: Some("[zsw] Empty image"),
label: Some("zsw-texture-empty"),
size: wgpu::Extent3d {
width: 1,
height: 1,
@ -206,7 +202,10 @@ fn create_empty_image_texture(device: &wgpu::Device) -> (wgpu::Texture, wgpu::Te
};
let texture = device.create_texture(&texture_descriptor);
let texture_view_descriptor = wgpu::TextureViewDescriptor::default();
let texture_view_descriptor = wgpu::TextureViewDescriptor {
label: Some("zsw-texture-empty-view"),
..Default::default()
};
let texture_view = texture.create_view(&texture_view_descriptor);
(texture, texture_view)

View File

@ -87,14 +87,14 @@ impl WgpuRenderer {
}
});
let surface_view_descriptor = wgpu::TextureViewDescriptor {
label: Some("[zsw] Window surface texture view"),
label: Some("zsw-frame-surface-texture-view"),
..wgpu::TextureViewDescriptor::default()
};
let surface_texture_view = surface_texture.texture.create_view(&surface_view_descriptor);
// Then create an encoder for our frame
let encoder_descriptor = wgpu::CommandEncoderDescriptor {
label: Some("[zsw] Frame render command encoder"),
label: Some("zsw-frame-command-encoder"),
};
let encoder = wgpu.device.create_command_encoder(&encoder_descriptor);

View File

@ -5,18 +5,18 @@
#import fade::uniforms::{uniforms, ImageUniforms}
// Bindings
@group(1) @binding(0) var texture_prev: texture_2d<f32>;
@group(1) @binding(1) var texture_cur: texture_2d<f32>;
@group(1) @binding(2) var texture_next: texture_2d<f32>;
@group(1) @binding(3) var texture_sampler: sampler;
@group(1) @binding(0) var image_prev: texture_2d<f32>;
@group(1) @binding(1) var image_cur: texture_2d<f32>;
@group(1) @binding(2) var image_next: texture_2d<f32>;
@group(1) @binding(3) var image_sampler: sampler;
struct Sampled {
color: vec4<f32>,
uvs : vec2<f32>,
}
// Samples a texture
fn sample(texture: texture_2d<f32>, in_uvs: vec2<f32>, image_uniforms: ImageUniforms, progress_raw: f32, alpha: f32) -> Sampled {
// Samples an image
fn sample(image: texture_2d<f32>, in_uvs: vec2<f32>, image_uniforms: ImageUniforms, progress_raw: f32, alpha: f32) -> Sampled {
var sampled: Sampled;
var uvs = in_uvs;
@ -42,7 +42,7 @@ fn sample(texture: texture_2d<f32>, in_uvs: vec2<f32>, image_uniforms: ImageUnif
#endif
sampled.color = textureSample(texture, texture_sampler, uvs);
sampled.color = textureSample(image, image_sampler, uvs);
sampled.uvs = uvs;
return sampled;
@ -65,10 +65,10 @@ fn main(in: VertexOutput) -> FragOutput {
let alpha_next = 0.5 * saturate(1.0 - (1.0 - p) / f);
let alpha_cur = 1.0 - max(alpha_prev, alpha_next);
// Sample the textures
let sample_prev = sample(texture_prev, in.uvs, uniforms.prev, progress_prev, alpha_prev);
let sample_cur = sample( texture_cur, in.uvs, uniforms.cur , progress_cur , alpha_cur );
let sample_next = sample(texture_next, in.uvs, uniforms.next, progress_next, alpha_next);
// Sample the images
let sample_prev = sample(image_prev, in.uvs, uniforms.prev, progress_prev, alpha_prev);
let sample_cur = sample( image_cur, in.uvs, uniforms.cur , progress_cur , alpha_cur );
let sample_next = sample(image_next, in.uvs, uniforms.next, progress_next, alpha_next);
// Then mix the color
// TODO: Don't repeat this once we're able to use `defined(FADE_BASIC) || defined(FADE_OUT)`

View File

@ -34,7 +34,6 @@ fn draw_plot(ui: &mut egui::Ui, display: &FrameTimesDisplay, charts: impl IntoIt
/// Display
#[derive(Clone, Copy, Debug)]
#[expect(variant_size_differences, reason = "It'll be heap allocated anyway")]
enum FrameTimesDisplay {
/// Time graph
TimeGraph { stack_charts: bool },

View File

@ -132,13 +132,13 @@ fn draw_fade_panel_editor(
ui.collapsing("Images", |ui| {
ui.collapsing("Previous", |ui| {
self::draw_panel_image(ui, &mut panel_state.images_mut().prev);
self::draw_fade_panel_image(ui, &mut panel_state.images_mut().prev);
});
ui.collapsing("Current", |ui| {
self::draw_panel_image(ui, &mut panel_state.images_mut().cur);
self::draw_fade_panel_image(ui, &mut panel_state.images_mut().cur);
});
ui.collapsing("Next", |ui| {
self::draw_panel_image(ui, &mut panel_state.images_mut().next);
self::draw_fade_panel_image(ui, &mut panel_state.images_mut().next);
});
});
@ -168,8 +168,8 @@ fn draw_fade_panel_editor(
});
}
/// Draws a panel image
fn draw_panel_image(ui: &mut egui::Ui, image: &mut Option<PanelFadeImage>) {
/// Draws a fade panel image
fn draw_fade_panel_image(ui: &mut egui::Ui, image: &mut Option<PanelFadeImage>) {
match image {
None => {
ui.label("[Unloaded]");

View File

@ -36,9 +36,9 @@ use {
/// Panels renderer shared
#[derive(Debug)]
pub struct PanelsRendererShared {
/// Render pipeline for each shader by shader name
/// Render pipeline for each shader
// TODO: Prune ones that aren't used?
render_pipelines: Mutex<HashMap<&'static str, Arc<wgpu::RenderPipeline>>>,
render_pipelines: Mutex<HashMap<RenderPipelineId, Arc<wgpu::RenderPipeline>>>,
/// Vertex buffer
vertices: wgpu::Buffer,
@ -157,7 +157,7 @@ impl PanelsRenderer {
},
};
let render_pass_descriptor = wgpu::RenderPassDescriptor {
label: Some("[zsw::panel] Render pass"),
label: Some("zsw-panel-render-pass"),
color_attachments: &[Some(render_pass_color_attachment)],
depth_stencil_attachment: None,
timestamp_writes: None,
@ -202,8 +202,21 @@ impl PanelsRenderer {
continue;
}
let render_pipeline_id = match &panel.state {
PanelState::None(_) => RenderPipelineId::None,
PanelState::Fade(state) => RenderPipelineId::Fade(match state.shader() {
PanelFadeShader::Basic => RenderPipelineFadeId::Basic,
PanelFadeShader::White { .. } => RenderPipelineFadeId::White,
PanelFadeShader::Out { .. } => RenderPipelineFadeId::Out,
PanelFadeShader::In { .. } => RenderPipelineFadeId::In,
}),
PanelState::Slide(state) => RenderPipelineId::Slide(match state.shader() {
PanelSlideShader::Basic => RenderPipelineSlideId::Basic,
}),
};
#[time(create_render_pipeline)]
let render_pipeline = match shared.render_pipelines.lock().await.entry(panel.state.shader().name()) {
let render_pipeline = match shared.render_pipelines.lock().await.entry(render_pipeline_id) {
hash_map::Entry::Occupied(entry) => Arc::clone(entry.get()),
hash_map::Entry::Vacant(entry) => {
let bind_group_layouts = match panel.state {
@ -218,6 +231,7 @@ impl PanelsRenderer {
let render_pipeline = self::create_render_pipeline(
wgpu_renderer,
wgpu,
render_pipeline_id,
bind_group_layouts,
panel.state.shader(),
self.msaa_samples,
@ -320,7 +334,7 @@ impl PanelsRenderer {
let geometry_uniforms = panel_geometry
.uniforms
.entry(window.id())
.or_insert_with(|| self::create_panel_geometry_uniforms(wgpu, shared));
.or_insert_with(|| self::create_geometry_uniforms(wgpu, &shared.uniforms_bind_group_layout));
let write_uniforms = |uniforms_bytes| {
wgpu.queue.write_buffer(&geometry_uniforms.buffer, 0, uniforms_bytes);
};
@ -404,10 +418,10 @@ impl PanelsRenderer {
}
/// Creates the panel geometry uniforms
fn create_panel_geometry_uniforms(wgpu: &Wgpu, shared: &PanelsRendererShared) -> PanelGeometryUniforms {
fn create_geometry_uniforms(wgpu: &Wgpu, layout: &wgpu::BindGroupLayout) -> PanelGeometryUniforms {
// Create the uniforms
let buffer_descriptor = wgpu::BufferDescriptor {
label: Some("[zsw::panel] Geometry uniforms buffer"),
label: Some("zsw-panel-geometry-uniforms-buffer"),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
size: u64::try_from(MAX_UNIFORM_SIZE).expect("Maximum uniform size didn't fit into a `u64`"),
mapped_at_creation: false,
@ -416,12 +430,12 @@ fn create_panel_geometry_uniforms(wgpu: &Wgpu, shared: &PanelsRendererShared) ->
// Create the uniform bind group
let bind_group_descriptor = wgpu::BindGroupDescriptor {
layout: &shared.uniforms_bind_group_layout,
label: Some("zsw-panel-geometry-uniforms-bind-group"),
layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
}],
label: Some("[zsw::panel] Geometry uniforms bind group"),
};
let bind_group = wgpu.device.create_bind_group(&bind_group_descriptor);
@ -431,7 +445,7 @@ fn create_panel_geometry_uniforms(wgpu: &Wgpu, shared: &PanelsRendererShared) ->
/// Creates the vertices
fn create_vertices(wgpu: &Wgpu) -> wgpu::Buffer {
let descriptor = wgpu::util::BufferInitDescriptor {
label: Some("[zsw::panel] Vertex buffer"),
label: Some("zsw-panel-vertex-buffer"),
contents: bytemuck::cast_slice(&PanelVertex::QUAD),
usage: wgpu::BufferUsages::VERTEX,
};
@ -443,7 +457,7 @@ fn create_vertices(wgpu: &Wgpu) -> wgpu::Buffer {
fn create_indices(wgpu: &Wgpu) -> wgpu::Buffer {
const INDICES: [u32; 6] = [0, 1, 3, 0, 3, 2];
let descriptor = wgpu::util::BufferInitDescriptor {
label: Some("[zsw::panel] Index buffer"),
label: Some("zsw-panel-index-buffer"),
contents: bytemuck::cast_slice(&INDICES),
usage: wgpu::BufferUsages::INDEX,
};
@ -451,16 +465,78 @@ fn create_indices(wgpu: &Wgpu) -> wgpu::Buffer {
wgpu.device.create_buffer_init(&descriptor)
}
/// Render pipeline id
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum RenderPipelineId {
/// None shader
None,
/// Fade shader
Fade(RenderPipelineFadeId),
/// Slide
Slide(RenderPipelineSlideId),
}
impl RenderPipelineId {
/// Returns this pipeline's name
pub fn name(self) -> &'static str {
match self {
Self::None => "none",
Self::Fade(id) => id.name(),
Self::Slide(id) => id.name(),
}
}
}
/// Render pipeline fade id
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum RenderPipelineFadeId {
Basic,
White,
Out,
In,
}
impl RenderPipelineFadeId {
/// Returns this pipeline's name
pub fn name(self) -> &'static str {
match self {
Self::Basic => "fade-basic",
Self::White => "fade-white",
Self::Out => "fade-out",
Self::In => "fade-in",
}
}
}
/// Render pipeline slide id
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum RenderPipelineSlideId {
Basic,
}
impl RenderPipelineSlideId {
/// Returns this pipeline's name
pub fn name(self) -> &'static str {
match self {
Self::Basic => "slide-basic",
}
}
}
/// Creates the render pipeline
fn create_render_pipeline(
wgpu_renderer: &WgpuRenderer,
wgpu: &Wgpu,
id: RenderPipelineId,
bind_group_layouts: &[&wgpu::BindGroupLayout],
shader: PanelShader,
msaa_samples: u32,
) -> Result<wgpu::RenderPipeline, AppError> {
let render_pipeline_name = id.name();
let shader_name = shader.name();
tracing::debug!("Creating render pipeline for shader {shader_name:?}");
tracing::debug!("Creating render pipeline {render_pipeline_name:?} for shader {shader_name:?}");
// Parse the shader from the build script
let shader_module =
@ -468,14 +544,16 @@ fn create_render_pipeline(
// Load the shader
let shader_descriptor = wgpu::ShaderModuleDescriptor {
label: Some(&format!("[zsw::panel] Shader {shader_name:?}")),
label: Some(&format!("zsw-panel-shader[name={shader_name:?}]")),
source: wgpu::ShaderSource::Naga(Cow::Owned(shader_module)),
};
let shader = wgpu.device.create_shader_module(shader_descriptor);
// Create the pipeline layout
let render_pipeline_layout_descriptor = wgpu::PipelineLayoutDescriptor {
label: Some(&format!("[zsw::panel] Shader {shader_name:?} render pipeline layout")),
label: Some(&format!(
"zsw-panel-render-pipeline[name={render_pipeline_name:?}]-layout"
)),
bind_group_layouts,
push_constant_ranges: &[],
};
@ -487,7 +565,7 @@ fn create_render_pipeline(
write_mask: wgpu::ColorWrites::ALL,
})];
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
label: Some(&format!("[zsw::panel] Shader {shader_name:?} render pipeline")),
label: Some(&format!("zsw-panel-render-pipeline[name={render_pipeline_name:?}]")),
layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState {
@ -539,25 +617,28 @@ fn create_msaa_framebuffer(
let surface_config = wgpu_renderer.surface_config();
let msaa_frame_descriptor = wgpu::TextureDescriptor {
label: Some("zsw-panel-framebuffer-msaa"),
size: msaa_texture_extent,
mip_level_count: 1,
sample_count: msaa_samples,
dimension: wgpu::TextureDimension::D2,
format: surface_config.format,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
label: Some("[zsw::panel] MSAA framebuffer"),
view_formats: &surface_config.view_formats,
};
wgpu.device
.create_texture(&msaa_frame_descriptor)
.create_view(&wgpu::TextureViewDescriptor::default())
.create_view(&wgpu::TextureViewDescriptor {
label: Some("zsw-panel-framebuffer-msaa-view"),
..Default::default()
})
}
/// Creates the uniforms bind group layout
fn create_uniforms_bind_group_layout(wgpu: &Wgpu) -> wgpu::BindGroupLayout {
let descriptor = wgpu::BindGroupLayoutDescriptor {
label: Some("[zsw::panel] Geometry uniforms bind group layout"),
label: Some("zsw-panel-geometry-uniforms-bind-group-layout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,

View File

@ -7,7 +7,7 @@ use {
image::{DynamicImage, imageops},
std::{self, mem, path::Path, sync::Arc},
tokio::sync::OnceCell,
zsw_util::{AppError, Loadable, loadable::Loader},
zsw_util::{AppError, Loadable},
zsw_wgpu::Wgpu,
zutil_cloned::cloned,
};
@ -40,14 +40,14 @@ pub struct PanelFadeImages {
/// Next image
pub next: Option<PanelFadeImage>,
/// Texture sampler
/// Image sampler
pub image_sampler: OnceCell<wgpu::Sampler>,
/// Texture bind group
/// Image bind group
pub image_bind_group: OnceCell<wgpu::BindGroup>,
/// Next image
pub next_image: Loadable<ImageLoadRes, NextImageLoader>,
pub next_image: Loadable<ImageLoadRes>,
}
/// Panel's fade image
@ -63,14 +63,6 @@ pub struct PanelFadeImage {
pub path: Arc<Path>,
}
/// Arguments to the next image loader
pub struct NextImageArgs {
playlist_pos: usize,
path: Arc<Path>,
max_image_size: u32,
}
impl PanelFadeImages {
/// Creates a new panel
#[must_use]
@ -81,7 +73,7 @@ impl PanelFadeImages {
next: None,
image_sampler: OnceCell::new(),
image_bind_group: OnceCell::new(),
next_image: Loadable::new(NextImageLoader),
next_image: Loadable::new(),
}
}
@ -187,7 +179,8 @@ impl PanelFadeImages {
};
if let Some(slot) = slot {
let texture_view = match wgpu.create_texture_from_image(&res.path, image) {
let texture_label = format!("zsw-panel-fade-image-texture[path={:?}]", res.path);
let texture_view = match wgpu.create_texture_from_image(&texture_label, image) {
Ok((_, texture_view)) => texture_view,
Err(err) => {
tracing::warn!("Unable to create texture for image {:?}: {}", res.path, err.pretty());
@ -240,10 +233,18 @@ impl PanelFadeImages {
let max_image_size = wgpu.device.limits().max_texture_dimension_2d;
self.next_image.try_load(NextImageArgs {
playlist_pos,
path,
max_image_size,
self.next_image.try_load(|| {
tokio::task::Builder::new()
.name(&format!("Load image {path:?}"))
.spawn_blocking(move || {
let image_res = self::load(&path, max_image_size);
ImageLoadRes {
path,
playlist_pos,
image_res,
}
})
.context("Unable to spawn task")
})
}
@ -253,25 +254,6 @@ impl PanelFadeImages {
}
}
/// Next image loader
pub struct NextImageLoader;
impl Loader<NextImageArgs, ImageLoadRes> for NextImageLoader {
fn spawn(&mut self, args: NextImageArgs) -> Result<tokio::task::JoinHandle<ImageLoadRes>, AppError> {
tokio::task::Builder::new()
.name(&format!("Load image {:?}", args.path))
.spawn_blocking(move || {
let image_res = self::load(&args.path, args.max_image_size);
ImageLoadRes {
path: args.path,
playlist_pos: args.playlist_pos,
image_res,
}
})
.context("Unable to spawn task")
}
}
/// Image slot
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
enum Slot {
@ -313,7 +295,7 @@ pub fn load(path: &Arc<Path>, max_image_size: u32) -> Result<DynamicImage, AppEr
/// Creates the fade image bind group layout
fn create_bind_group_layout(wgpu: &Wgpu) -> wgpu::BindGroupLayout {
let descriptor = wgpu::BindGroupLayoutDescriptor {
label: Some("[zsw::panel] Fade image bind group layout"),
label: Some("zsw-panel-fade-image-bind-group-layout"),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
@ -357,7 +339,7 @@ fn create_bind_group_layout(wgpu: &Wgpu) -> wgpu::BindGroupLayout {
wgpu.device.create_bind_group_layout(&descriptor)
}
/// Creates the texture bind group
/// Creates the image bind group
fn create_image_bind_group(
wgpu: &Wgpu,
bind_group_layout: &wgpu::BindGroupLayout,
@ -367,6 +349,7 @@ fn create_image_bind_group(
sampler: &wgpu::Sampler,
) -> wgpu::BindGroup {
let descriptor = wgpu::BindGroupDescriptor {
label: Some("zsw-panel-fade-image-bind-group"),
layout: bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
@ -386,7 +369,6 @@ fn create_image_bind_group(
resource: wgpu::BindingResource::Sampler(sampler),
},
],
label: Some("[zsw::panel] Image bind group"),
};
wgpu.device.create_bind_group(&descriptor)
}
@ -394,7 +376,7 @@ fn create_image_bind_group(
/// Creates the image sampler
fn create_image_sampler(wgpu: &Wgpu) -> wgpu::Sampler {
let descriptor = wgpu::SamplerDescriptor {
label: Some("[zsw::panel] Image sampler"),
label: Some("zsw-panel-fade-image-sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,