diff --git a/player/src/lib.rs b/player/src/lib.rs index f39e8df3a..5d52748bf 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -12,7 +12,7 @@ use wgc::device::trace; -use std::{borrow::Cow, ffi::CString, fmt::Debug, fs, marker::PhantomData, path::Path, ptr}; +use std::{borrow::Cow, fmt::Debug, fs, marker::PhantomData, path::Path}; #[macro_export] macro_rules! gfx_select { @@ -31,24 +31,6 @@ macro_rules! gfx_select { }; } -struct Label(Option); -impl Label { - fn new(text: &str) -> Self { - Self(if text.is_empty() { - None - } else { - Some(CString::new(text).expect("invalid label")) - }) - } - - fn as_ptr(&self) -> *const std::os::raw::c_char { - match self.0 { - Some(ref c_string) => c_string.as_ptr(), - None => ptr::null(), - } - } -} - #[derive(Debug)] pub struct IdentityPassThrough(PhantomData); @@ -135,7 +117,7 @@ impl GlobalPlay for wgc::hub::Global { } } } - self.command_encoder_finish::(encoder, &wgt::CommandBufferDescriptor { todo: 0 }) + self.command_encoder_finish::(encoder, &wgt::CommandBufferDescriptor { label: None }) .unwrap() } @@ -154,19 +136,15 @@ impl GlobalPlay for wgc::hub::Global { panic!("Unexpected SwapChain action: winit feature is not enabled") } A::CreateBuffer(id, desc) => { - let label = Label::new(&desc.label); self.device_maintain_ids::(device).unwrap(); - self.device_create_buffer::(device, &desc.map_label(|_| label.as_ptr()), id) - .unwrap(); + self.device_create_buffer::(device, &desc, id).unwrap(); } A::DestroyBuffer(id) => { self.buffer_drop::(id, true); } A::CreateTexture(id, desc) => { - let label = Label::new(&desc.label); self.device_maintain_ids::(device).unwrap(); - self.device_create_texture::(device, &desc.map_label(|_| label.as_ptr()), id) - .unwrap(); + self.device_create_texture::(device, &desc, id).unwrap(); } A::DestroyTexture(id) => { self.texture_drop::(id); @@ -176,23 +154,15 @@ impl GlobalPlay for wgc::hub::Global { parent_id, desc, } => { - let label = desc.as_ref().map_or(Label(None), |d| Label::new(&d.label)); self.device_maintain_ids::(device).unwrap(); - self.texture_create_view::( - parent_id, - desc.map(|d| d.map_label(|_| label.as_ptr())).as_ref(), - id, - ) - .unwrap(); + self.texture_create_view::(parent_id, &desc, id).unwrap(); } A::DestroyTextureView(id) => { self.texture_view_drop::(id).unwrap(); } A::CreateSampler(id, desc) => { - let label = Label::new(&desc.label); self.device_maintain_ids::(device).unwrap(); - self.device_create_sampler::(device, &desc.map_label(|_| label.as_ptr()), id) - .unwrap(); + self.device_create_sampler::(device, &desc, id).unwrap(); } A::DestroySampler(id) => { self.sampler_drop::(id); @@ -263,14 +233,11 @@ impl GlobalPlay for wgc::hub::Global { self.render_pipeline_drop::(id); } A::CreateRenderBundle { id, desc, base } => { - let label = Label::new(&desc.label.as_ref().unwrap()); let bundle = wgc::command::RenderBundleEncoder::new(&desc, device, Some(base)).unwrap(); self.render_bundle_encoder_finish::( bundle, - &wgt::RenderBundleDescriptor { - label: label.as_ptr(), - }, + &wgt::RenderBundleDescriptor { label: desc.label }, id, ) .unwrap(); @@ -309,7 +276,7 @@ impl GlobalPlay for wgc::hub::Global { let encoder = self .device_create_command_encoder::( device, - &wgt::CommandEncoderDescriptor { label: ptr::null() }, + &wgt::CommandEncoderDescriptor { label: None }, comb_manager.alloc(device.backend()), ) .unwrap(); diff --git a/player/tests/data/buffer-copy.ron b/player/tests/data/buffer-copy.ron index e0b606978..d8f598fe9 100644 --- a/player/tests/data/buffer-copy.ron +++ b/player/tests/data/buffer-copy.ron @@ -12,7 +12,7 @@ CreateBuffer( Id(0, 1, Empty), ( - label: "", + label: Some("dummy"), size: 16, usage: ( bits: 41, diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index acafe3903..3c6841560 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -7,7 +7,7 @@ use crate::{ id::{BindGroupLayoutId, BufferId, DeviceId, SamplerId, TextureViewId, Valid}, track::{TrackerSet, DUMMY_SELECTOR}, validation::{MissingBufferUsageError, MissingTextureUsageError}, - FastHashMap, LifeGuard, MultiRefCount, RefCount, Stored, MAX_BIND_GROUPS, + FastHashMap, Label, LifeGuard, MultiRefCount, RefCount, Stored, MAX_BIND_GROUPS, }; use arrayvec::ArrayVec; @@ -182,7 +182,7 @@ pub(crate) struct BindingTypeMaxCountValidator { impl BindingTypeMaxCountValidator { pub(crate) fn add_binding(&mut self, binding: &wgt::BindGroupLayoutEntry) { - let count = binding.count.unwrap_or(1); + let count = binding.count.map_or(1, |count| count.get()); match binding.ty { wgt::BindingType::UniformBuffer { dynamic, .. } => { self.uniform_buffers.add(binding.visibility, count); @@ -261,6 +261,42 @@ impl BindingTypeMaxCountValidator { } } +/// Bindable resource and the slot to bind it to. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "trace", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub struct BindGroupEntry<'a> { + /// Slot for which binding provides resource. Corresponds to an entry of the same + /// binding index in the [`BindGroupLayoutDescriptor`]. + pub binding: u32, + /// Resource to attach to the binding + pub resource: BindingResource<'a>, +} + +/// Describes a group of bindings and the resources to be bound. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "trace", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub struct BindGroupDescriptor<'a> { + /// Debug label of the bind group. This will show up in graphics debuggers for easy identification. + pub label: Label<'a>, + /// The [`BindGroupLayout`] that corresponds to this bind group. + pub layout: BindGroupLayoutId, + /// The resources to bind to this bind group. + pub entries: Cow<'a, [BindGroupEntry<'a>]>, +} + +/// Describes a [`BindGroupLayout`]. +#[derive(Clone, Debug)] +#[cfg_attr(feature = "trace", derive(serde::Serialize))] +#[cfg_attr(feature = "replay", derive(serde::Deserialize))] +pub struct BindGroupLayoutDescriptor<'a> { + /// Debug label of the bind group layout. This will show up in graphics debuggers for easy identification. + pub label: Label<'a>, + /// Array of entries in this BindGroupLayout + pub entries: Cow<'a, [wgt::BindGroupLayoutEntry]>, +} + pub(crate) type BindEntryMap = FastHashMap; #[derive(Debug)] @@ -335,6 +371,26 @@ pub enum PushConstantUploadError { Unaligned(u32), } +/// Describes a pipeline layout. +/// +/// A `PipelineLayoutDescriptor` can be used to create a pipeline layout. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "trace", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub struct PipelineLayoutDescriptor<'a> { + /// Debug label of the pipeine layout. This will show up in graphics debuggers for easy identification. + pub label: Label<'a>, + /// Bind groups that this pipeline uses. The first entry will provide all the bindings for + /// "set = 0", second entry will provide all the bindings for "set = 1" etc. + pub bind_group_layouts: Cow<'a, [BindGroupLayoutId]>, + /// Set of push constant ranges this pipeline uses. Each shader stage that uses push constants + /// must define the range in push constant memory that corresponds to its single `layout(push_constant)` + /// uniform block. + /// + /// If this array is non-empty, the [`Features::PUSH_CONSTANTS`] must be enabled. + pub push_constant_ranges: Cow<'a, [wgt::PushConstantRange]>, +} + #[derive(Debug)] pub struct PipelineLayout { pub(crate) raw: B::PipelineLayout, @@ -446,11 +502,6 @@ pub enum BindingResource<'a> { TextureViewArray(Cow<'a, [TextureViewId]>), } -pub type BindGroupEntry<'a> = wgt::BindGroupEntry>; - -pub type BindGroupDescriptor<'a> = - wgt::BindGroupDescriptor<'a, BindGroupLayoutId, BindGroupEntry<'a>>; - #[derive(Clone, Debug, Error)] pub enum BindError { #[error("number of dynamic offsets ({actual}) doesn't match the number of dynamic bindings in the bind group layout ({expected})")] diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 4279ffdba..4947cdc49 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -41,8 +41,7 @@ use crate::{ command::{BasePass, DrawError, RenderCommand, RenderCommandError}, conv, device::{ - AttachmentData, DeviceError, Label, RenderPassContext, MAX_VERTEX_BUFFERS, - SHADER_STAGE_COUNT, + AttachmentData, DeviceError, RenderPassContext, MAX_VERTEX_BUFFERS, SHADER_STAGE_COUNT, }, hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Storage, Token}, id, @@ -50,12 +49,35 @@ use crate::{ span, track::TrackerSet, validation::check_buffer_usage, - LifeGuard, RefCount, Stored, MAX_BIND_GROUPS, + Label, LifeGuard, RefCount, Stored, MAX_BIND_GROUPS, }; use arrayvec::ArrayVec; -use std::{borrow::Borrow, iter, marker::PhantomData, ops::Range}; +use std::{ + borrow::{Borrow, Cow}, + iter, + marker::PhantomData, + ops::Range, +}; use thiserror::Error; +/// Describes a [`RenderBundleEncoder`]. +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "trace", derive(serde::Serialize))] +#[cfg_attr(feature = "replay", derive(serde::Deserialize))] +pub struct RenderBundleEncoderDescriptor<'a> { + /// Debug label of the render bundle encoder. This will show up in graphics debuggers for easy identification. + pub label: Label<'a>, + /// The formats of the color attachments that this render bundle is capable to rendering to. This + /// must match the formats of the color attachments in the renderpass this render bundle is executed in. + pub color_formats: Cow<'a, [wgt::TextureFormat]>, + /// The formats of the depth attachment that this render bundle is capable to rendering to. This + /// must match the formats of the depth attachments in the renderpass this render bundle is executed in. + pub depth_stencil_format: Option, + /// Sample count this render bundle is capable of rendering to. This must match the pipelines and + /// the renderpasses it is used in. + pub sample_count: u32, +} + #[derive(Debug)] #[cfg_attr(feature = "serial-pass", derive(serde::Deserialize, serde::Serialize))] pub struct RenderBundleEncoder { @@ -66,7 +88,7 @@ pub struct RenderBundleEncoder { impl RenderBundleEncoder { pub fn new( - desc: &wgt::RenderBundleEncoderDescriptor, + desc: &RenderBundleEncoderDescriptor, parent_id: id::DeviceId, base: Option>, ) -> Result { @@ -103,6 +125,8 @@ pub enum CreateRenderBundleError { InvalidSampleCount(u32), } +pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor>; + //Note: here, `RenderBundle` is just wrapping a raw stream of render commands. // The plan is to back it by an actual Vulkan secondary buffer, D3D12 Bundle, // or Metal indirect command buffer. @@ -613,7 +637,7 @@ impl Global { pub fn render_bundle_encoder_finish( &self, bundle_encoder: RenderBundleEncoder, - desc: &wgt::RenderBundleDescriptor