Grand cleanup and refactor of the descriptors in the API

This commit is contained in:
Dzmitry Malyshau 2020-08-12 14:13:32 -04:00
parent 04f5cfd1c8
commit 9d8dc0b04d
14 changed files with 539 additions and 1267 deletions

View File

@ -12,7 +12,7 @@
use wgc::device::trace; 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_export]
macro_rules! gfx_select { macro_rules! gfx_select {
@ -31,24 +31,6 @@ macro_rules! gfx_select {
}; };
} }
struct Label(Option<CString>);
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)] #[derive(Debug)]
pub struct IdentityPassThrough<I>(PhantomData<I>); pub struct IdentityPassThrough<I>(PhantomData<I>);
@ -135,7 +117,7 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
} }
} }
} }
self.command_encoder_finish::<B>(encoder, &wgt::CommandBufferDescriptor { todo: 0 }) self.command_encoder_finish::<B>(encoder, &wgt::CommandBufferDescriptor { label: None })
.unwrap() .unwrap()
} }
@ -154,19 +136,15 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
panic!("Unexpected SwapChain action: winit feature is not enabled") panic!("Unexpected SwapChain action: winit feature is not enabled")
} }
A::CreateBuffer(id, desc) => { A::CreateBuffer(id, desc) => {
let label = Label::new(&desc.label);
self.device_maintain_ids::<B>(device).unwrap(); self.device_maintain_ids::<B>(device).unwrap();
self.device_create_buffer::<B>(device, &desc.map_label(|_| label.as_ptr()), id) self.device_create_buffer::<B>(device, &desc, id).unwrap();
.unwrap();
} }
A::DestroyBuffer(id) => { A::DestroyBuffer(id) => {
self.buffer_drop::<B>(id, true); self.buffer_drop::<B>(id, true);
} }
A::CreateTexture(id, desc) => { A::CreateTexture(id, desc) => {
let label = Label::new(&desc.label);
self.device_maintain_ids::<B>(device).unwrap(); self.device_maintain_ids::<B>(device).unwrap();
self.device_create_texture::<B>(device, &desc.map_label(|_| label.as_ptr()), id) self.device_create_texture::<B>(device, &desc, id).unwrap();
.unwrap();
} }
A::DestroyTexture(id) => { A::DestroyTexture(id) => {
self.texture_drop::<B>(id); self.texture_drop::<B>(id);
@ -176,23 +154,15 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
parent_id, parent_id,
desc, desc,
} => { } => {
let label = desc.as_ref().map_or(Label(None), |d| Label::new(&d.label));
self.device_maintain_ids::<B>(device).unwrap(); self.device_maintain_ids::<B>(device).unwrap();
self.texture_create_view::<B>( self.texture_create_view::<B>(parent_id, &desc, id).unwrap();
parent_id,
desc.map(|d| d.map_label(|_| label.as_ptr())).as_ref(),
id,
)
.unwrap();
} }
A::DestroyTextureView(id) => { A::DestroyTextureView(id) => {
self.texture_view_drop::<B>(id).unwrap(); self.texture_view_drop::<B>(id).unwrap();
} }
A::CreateSampler(id, desc) => { A::CreateSampler(id, desc) => {
let label = Label::new(&desc.label);
self.device_maintain_ids::<B>(device).unwrap(); self.device_maintain_ids::<B>(device).unwrap();
self.device_create_sampler::<B>(device, &desc.map_label(|_| label.as_ptr()), id) self.device_create_sampler::<B>(device, &desc, id).unwrap();
.unwrap();
} }
A::DestroySampler(id) => { A::DestroySampler(id) => {
self.sampler_drop::<B>(id); self.sampler_drop::<B>(id);
@ -263,14 +233,11 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
self.render_pipeline_drop::<B>(id); self.render_pipeline_drop::<B>(id);
} }
A::CreateRenderBundle { id, desc, base } => { A::CreateRenderBundle { id, desc, base } => {
let label = Label::new(&desc.label.as_ref().unwrap());
let bundle = let bundle =
wgc::command::RenderBundleEncoder::new(&desc, device, Some(base)).unwrap(); wgc::command::RenderBundleEncoder::new(&desc, device, Some(base)).unwrap();
self.render_bundle_encoder_finish::<B>( self.render_bundle_encoder_finish::<B>(
bundle, bundle,
&wgt::RenderBundleDescriptor { &wgt::RenderBundleDescriptor { label: desc.label },
label: label.as_ptr(),
},
id, id,
) )
.unwrap(); .unwrap();
@ -309,7 +276,7 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
let encoder = self let encoder = self
.device_create_command_encoder::<B>( .device_create_command_encoder::<B>(
device, device,
&wgt::CommandEncoderDescriptor { label: ptr::null() }, &wgt::CommandEncoderDescriptor { label: None },
comb_manager.alloc(device.backend()), comb_manager.alloc(device.backend()),
) )
.unwrap(); .unwrap();

View File

@ -12,7 +12,7 @@
CreateBuffer( CreateBuffer(
Id(0, 1, Empty), Id(0, 1, Empty),
( (
label: "", label: Some("dummy"),
size: 16, size: 16,
usage: ( usage: (
bits: 41, bits: 41,

View File

@ -7,7 +7,7 @@ use crate::{
id::{BindGroupLayoutId, BufferId, DeviceId, SamplerId, TextureViewId, Valid}, id::{BindGroupLayoutId, BufferId, DeviceId, SamplerId, TextureViewId, Valid},
track::{TrackerSet, DUMMY_SELECTOR}, track::{TrackerSet, DUMMY_SELECTOR},
validation::{MissingBufferUsageError, MissingTextureUsageError}, validation::{MissingBufferUsageError, MissingTextureUsageError},
FastHashMap, LifeGuard, MultiRefCount, RefCount, Stored, MAX_BIND_GROUPS, FastHashMap, Label, LifeGuard, MultiRefCount, RefCount, Stored, MAX_BIND_GROUPS,
}; };
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
@ -182,7 +182,7 @@ pub(crate) struct BindingTypeMaxCountValidator {
impl BindingTypeMaxCountValidator { impl BindingTypeMaxCountValidator {
pub(crate) fn add_binding(&mut self, binding: &wgt::BindGroupLayoutEntry) { 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 { match binding.ty {
wgt::BindingType::UniformBuffer { dynamic, .. } => { wgt::BindingType::UniformBuffer { dynamic, .. } => {
self.uniform_buffers.add(binding.visibility, count); 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<u32, wgt::BindGroupLayoutEntry>; pub(crate) type BindEntryMap = FastHashMap<u32, wgt::BindGroupLayoutEntry>;
#[derive(Debug)] #[derive(Debug)]
@ -335,6 +371,26 @@ pub enum PushConstantUploadError {
Unaligned(u32), 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)] #[derive(Debug)]
pub struct PipelineLayout<B: hal::Backend> { pub struct PipelineLayout<B: hal::Backend> {
pub(crate) raw: B::PipelineLayout, pub(crate) raw: B::PipelineLayout,
@ -446,11 +502,6 @@ pub enum BindingResource<'a> {
TextureViewArray(Cow<'a, [TextureViewId]>), TextureViewArray(Cow<'a, [TextureViewId]>),
} }
pub type BindGroupEntry<'a> = wgt::BindGroupEntry<BindingResource<'a>>;
pub type BindGroupDescriptor<'a> =
wgt::BindGroupDescriptor<'a, BindGroupLayoutId, BindGroupEntry<'a>>;
#[derive(Clone, Debug, Error)] #[derive(Clone, Debug, Error)]
pub enum BindError { pub enum BindError {
#[error("number of dynamic offsets ({actual}) doesn't match the number of dynamic bindings in the bind group layout ({expected})")] #[error("number of dynamic offsets ({actual}) doesn't match the number of dynamic bindings in the bind group layout ({expected})")]

View File

@ -41,8 +41,7 @@ use crate::{
command::{BasePass, DrawError, RenderCommand, RenderCommandError}, command::{BasePass, DrawError, RenderCommand, RenderCommandError},
conv, conv,
device::{ device::{
AttachmentData, DeviceError, Label, RenderPassContext, MAX_VERTEX_BUFFERS, AttachmentData, DeviceError, RenderPassContext, MAX_VERTEX_BUFFERS, SHADER_STAGE_COUNT,
SHADER_STAGE_COUNT,
}, },
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Storage, Token}, hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Storage, Token},
id, id,
@ -50,12 +49,35 @@ use crate::{
span, span,
track::TrackerSet, track::TrackerSet,
validation::check_buffer_usage, validation::check_buffer_usage,
LifeGuard, RefCount, Stored, MAX_BIND_GROUPS, Label, LifeGuard, RefCount, Stored, MAX_BIND_GROUPS,
}; };
use arrayvec::ArrayVec; 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; 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<wgt::TextureFormat>,
/// 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)] #[derive(Debug)]
#[cfg_attr(feature = "serial-pass", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serial-pass", derive(serde::Deserialize, serde::Serialize))]
pub struct RenderBundleEncoder { pub struct RenderBundleEncoder {
@ -66,7 +88,7 @@ pub struct RenderBundleEncoder {
impl RenderBundleEncoder { impl RenderBundleEncoder {
pub fn new( pub fn new(
desc: &wgt::RenderBundleEncoderDescriptor, desc: &RenderBundleEncoderDescriptor,
parent_id: id::DeviceId, parent_id: id::DeviceId,
base: Option<BasePass<RenderCommand>>, base: Option<BasePass<RenderCommand>>,
) -> Result<Self, CreateRenderBundleError> { ) -> Result<Self, CreateRenderBundleError> {
@ -103,6 +125,8 @@ pub enum CreateRenderBundleError {
InvalidSampleCount(u32), InvalidSampleCount(u32),
} }
pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Label<'a>>;
//Note: here, `RenderBundle` is just wrapping a raw stream of render commands. //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, // The plan is to back it by an actual Vulkan secondary buffer, D3D12 Bundle,
// or Metal indirect command buffer. // or Metal indirect command buffer.
@ -613,7 +637,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn render_bundle_encoder_finish<B: GfxBackend>( pub fn render_bundle_encoder_finish<B: GfxBackend>(
&self, &self,
bundle_encoder: RenderBundleEncoder, bundle_encoder: RenderBundleEncoder,
desc: &wgt::RenderBundleDescriptor<Label>, desc: &RenderBundleDescriptor,
id_in: Input<G, id::RenderBundleId>, id_in: Input<G, id::RenderBundleId>,
) -> Result<id::RenderBundleId, RenderBundleError> { ) -> Result<id::RenderBundleId, RenderBundleError> {
span!(_guard, INFO, "RenderBundleEncoder::finish"); span!(_guard, INFO, "RenderBundleEncoder::finish");
@ -908,9 +932,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
use crate::device::trace; use crate::device::trace;
let (bundle_guard, _) = hub.render_bundles.read(&mut token); let (bundle_guard, _) = hub.render_bundles.read(&mut token);
let bundle = &bundle_guard[id]; let bundle = &bundle_guard[id];
let label = desc.label.as_ref().map(|l| l.as_ref());
trace.lock().add(trace::Action::CreateRenderBundle { trace.lock().add(trace::Action::CreateRenderBundle {
id: id.0, id: id.0,
desc: trace::new_render_bundle_encoder_descriptor(desc.label, &bundle.context), desc: trace::new_render_bundle_encoder_descriptor(label, &bundle.context),
base: BasePass::from_ref(bundle.base.as_ref()), base: BasePass::from_ref(bundle.base.as_ref()),
}); });
} }

View File

@ -25,7 +25,7 @@ use crate::{
resource::{Buffer, Texture}, resource::{Buffer, Texture},
span, span,
track::TrackerSet, track::TrackerSet,
PrivateFeatures, Stored, Label, PrivateFeatures, Stored,
}; };
use hal::command::CommandBuffer as _; use hal::command::CommandBuffer as _;
@ -168,7 +168,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn command_encoder_finish<B: GfxBackend>( pub fn command_encoder_finish<B: GfxBackend>(
&self, &self,
encoder_id: id::CommandEncoderId, encoder_id: id::CommandEncoderId,
_desc: &wgt::CommandBufferDescriptor, _desc: &wgt::CommandBufferDescriptor<Label>,
) -> Result<id::CommandBufferId, CommandEncoderError> { ) -> Result<id::CommandBufferId, CommandEncoderError> {
span!(_guard, INFO, "CommandEncoder::finish"); span!(_guard, INFO, "CommandEncoder::finish");

View File

@ -37,7 +37,14 @@ use serde::Deserialize;
#[cfg(any(feature = "serial-pass", feature = "trace"))] #[cfg(any(feature = "serial-pass", feature = "trace"))]
use serde::Serialize; use serde::Serialize;
use std::{borrow::Borrow, collections::hash_map::Entry, fmt, iter, ops::Range, str}; use std::{
borrow::{Borrow, Cow},
collections::hash_map::Entry,
fmt, iter,
num::NonZeroU32,
ops::Range,
str,
};
/// Operation to perform to the output attachment at the start of a renderpass. /// Operation to perform to the output attachment at the start of a renderpass.
#[repr(C)] #[repr(C)]
@ -65,7 +72,7 @@ pub enum StoreOp {
/// Describes an individual channel within a render pass, such as color, depth, or stencil. /// Describes an individual channel within a render pass, such as color, depth, or stencil.
#[repr(C)] #[repr(C)]
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
#[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))] #[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))]
#[cfg_attr(any(feature = "serial-pass", feature = "replay"), derive(Deserialize))] #[cfg_attr(any(feature = "serial-pass", feature = "replay"), derive(Deserialize))]
pub struct PassChannel<V> { pub struct PassChannel<V> {
@ -83,7 +90,7 @@ pub struct PassChannel<V> {
/// Describes a color attachment to a render pass. /// Describes a color attachment to a render pass.
#[repr(C)] #[repr(C)]
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
#[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))] #[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))]
#[cfg_attr(any(feature = "serial-pass", feature = "replay"), derive(Deserialize))] #[cfg_attr(any(feature = "serial-pass", feature = "replay"), derive(Deserialize))]
pub struct ColorAttachmentDescriptor { pub struct ColorAttachmentDescriptor {
@ -97,7 +104,7 @@ pub struct ColorAttachmentDescriptor {
/// Describes a depth/stencil attachment to a render pass. /// Describes a depth/stencil attachment to a render pass.
#[repr(C)] #[repr(C)]
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
#[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))] #[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))]
#[cfg_attr(any(feature = "serial-pass", feature = "replay"), derive(Deserialize))] #[cfg_attr(any(feature = "serial-pass", feature = "replay"), derive(Deserialize))]
pub struct DepthStencilAttachmentDescriptor { pub struct DepthStencilAttachmentDescriptor {
@ -109,27 +116,32 @@ pub struct DepthStencilAttachmentDescriptor {
pub stencil: PassChannel<u32>, pub stencil: PassChannel<u32>,
} }
fn is_depth_stencil_read_only( impl DepthStencilAttachmentDescriptor {
desc: &DepthStencilAttachmentDescriptor, fn is_read_only(&self, aspects: hal::format::Aspects) -> Result<bool, RenderPassError> {
aspects: hal::format::Aspects, if aspects.contains(hal::format::Aspects::DEPTH) && !self.depth.read_only {
) -> Result<bool, RenderPassError> { return Ok(false);
if aspects.contains(hal::format::Aspects::DEPTH) && !desc.depth.read_only { }
return Ok(false); if (self.depth.load_op, self.depth.store_op) != (LoadOp::Load, StoreOp::Store) {
return Err(RenderPassError::InvalidDepthOps);
}
if aspects.contains(hal::format::Aspects::STENCIL) && !self.stencil.read_only {
return Ok(false);
}
if (self.stencil.load_op, self.stencil.store_op) != (LoadOp::Load, StoreOp::Store) {
return Err(RenderPassError::InvalidStencilOps);
}
Ok(true)
} }
if (desc.depth.load_op, desc.depth.store_op) != (LoadOp::Load, StoreOp::Store) {
return Err(RenderPassError::InvalidDepthOps);
}
if aspects.contains(hal::format::Aspects::STENCIL) && !desc.stencil.read_only {
return Ok(false);
}
if (desc.stencil.load_op, desc.stencil.store_op) != (LoadOp::Load, StoreOp::Store) {
return Err(RenderPassError::InvalidStencilOps);
}
Ok(true)
} }
pub type RenderPassDescriptor<'a> = /// Describes the attachments of a render pass.
wgt::RenderPassDescriptor<'a, ColorAttachmentDescriptor, &'a DepthStencilAttachmentDescriptor>; #[derive(Clone, Debug, Default, PartialEq)]
pub struct RenderPassDescriptor<'a> {
/// The color attachments of the render pass.
pub color_attachments: Cow<'a, [ColorAttachmentDescriptor]>,
/// The depth and stencil attachment of the render pass, if any.
pub depth_stencil_attachment: Option<&'a DepthStencilAttachmentDescriptor>,
}
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))] #[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))]
@ -198,7 +210,7 @@ pub enum RenderCommand {
buffer_id: id::BufferId, buffer_id: id::BufferId,
offset: BufferAddress, offset: BufferAddress,
/// Count of `None` represents a non-multi call. /// Count of `None` represents a non-multi call.
count: Option<u32>, count: Option<NonZeroU32>,
indexed: bool, indexed: bool,
}, },
MultiDrawIndirectCount { MultiDrawIndirectCount {
@ -425,7 +437,7 @@ pub enum RenderPassError {
#[error("indirect draw with offset {offset}{} uses bytes {begin_offset}..{end_offset} which overruns indirect buffer of size {buffer_size}", count.map_or_else(String::new, |v| format!(" and count {}", v)))] #[error("indirect draw with offset {offset}{} uses bytes {begin_offset}..{end_offset} which overruns indirect buffer of size {buffer_size}", count.map_or_else(String::new, |v| format!(" and count {}", v)))]
IndirectBufferOverrun { IndirectBufferOverrun {
offset: u64, offset: u64,
count: Option<u32>, count: Option<NonZeroU32>,
begin_offset: u64, begin_offset: u64,
end_offset: u64, end_offset: u64,
buffer_size: u64, buffer_size: u64,
@ -604,7 +616,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let previous_use = base_trackers let previous_use = base_trackers
.textures .textures
.query(source_id.value, view.range.clone()); .query(source_id.value, view.range.clone());
let new_use = if is_depth_stencil_read_only(at, view.range.aspects)? { let new_use = if at.is_read_only(view.range.aspects)? {
is_ds_read_only = true; is_ds_read_only = true;
TextureUse::ATTACHMENT_READ TextureUse::ATTACHMENT_READ
} else { } else {
@ -1414,7 +1426,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.unwrap(); .unwrap();
check_buffer_usage(buffer.usage, BufferUsage::INDIRECT)?; check_buffer_usage(buffer.usage, BufferUsage::INDIRECT)?;
let actual_count = count.unwrap_or(1); let actual_count = count.map_or(1, |c| c.get());
let begin_offset = offset; let begin_offset = offset;
let end_offset = offset + stride * actual_count as u64; let end_offset = offset + stride * actual_count as u64;
@ -1622,7 +1634,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub mod render_ffi { pub mod render_ffi {
use super::{super::Rect, RenderCommand, RenderPass}; use super::{super::Rect, RenderCommand, RenderPass};
use crate::{id, span, RawString}; use crate::{id, span, RawString};
use std::{convert::TryInto, ffi, slice}; use std::{convert::TryInto, ffi, num::NonZeroU32, slice};
use wgt::{BufferAddress, BufferSize, Color, DynamicOffset}; use wgt::{BufferAddress, BufferSize, Color, DynamicOffset};
/// # Safety /// # Safety
@ -1840,7 +1852,7 @@ pub mod render_ffi {
pass.base.commands.push(RenderCommand::MultiDrawIndirect { pass.base.commands.push(RenderCommand::MultiDrawIndirect {
buffer_id, buffer_id,
offset, offset,
count: Some(count), count: NonZeroU32::new(count),
indexed: false, indexed: false,
}); });
} }
@ -1856,7 +1868,7 @@ pub mod render_ffi {
pass.base.commands.push(RenderCommand::MultiDrawIndirect { pass.base.commands.push(RenderCommand::MultiDrawIndirect {
buffer_id, buffer_id,
offset, offset,
count: Some(count), count: NonZeroU32::new(count),
indexed: true, indexed: true,
}); });
} }

View File

@ -244,35 +244,26 @@ pub fn map_depth_stencil_state_descriptor(
hal::pso::DepthStencilDesc { hal::pso::DepthStencilDesc {
depth: if desc.depth_write_enabled || desc.depth_compare != wgt::CompareFunction::Always { depth: if desc.depth_write_enabled || desc.depth_compare != wgt::CompareFunction::Always {
Some(hal::pso::DepthTest { Some(hal::pso::DepthTest {
fun: map_compare_function(desc.depth_compare) fun: map_compare_function(desc.depth_compare),
.expect("DepthStencilStateDescriptor has undefined compare function"),
write: desc.depth_write_enabled, write: desc.depth_write_enabled,
}) })
} else { } else {
None None
}, },
depth_bounds: false, // TODO depth_bounds: false, // TODO
stencil: if desc.stencil_read_mask != !0 stencil: desc.stencil.as_ref().map(|stencil| hal::pso::StencilTest {
|| desc.stencil_write_mask != !0 faces: hal::pso::Sided {
|| desc.stencil_front != wgt::StencilStateFaceDescriptor::IGNORE front: map_stencil_face(&stencil.front),
|| desc.stencil_back != wgt::StencilStateFaceDescriptor::IGNORE back: map_stencil_face(&stencil.back),
{ },
Some(hal::pso::StencilTest { read_masks: hal::pso::State::Static(hal::pso::Sided::new(stencil.read_mask)),
faces: hal::pso::Sided { write_masks: hal::pso::State::Static(hal::pso::Sided::new(stencil.write_mask)),
front: map_stencil_face(&desc.stencil_front), reference_values: if stencil.needs_ref_value() {
back: map_stencil_face(&desc.stencil_back), hal::pso::State::Dynamic
}, } else {
read_masks: hal::pso::State::Static(hal::pso::Sided::new(desc.stencil_read_mask)), hal::pso::State::Static(hal::pso::Sided::new(0))
write_masks: hal::pso::State::Static(hal::pso::Sided::new(desc.stencil_write_mask)), },
reference_values: if desc.needs_stencil_reference() { }),
hal::pso::State::Dynamic
} else {
hal::pso::State::Static(hal::pso::Sided::new(0))
},
})
} else {
None
},
} }
} }
@ -280,29 +271,25 @@ fn map_stencil_face(
stencil_state_face_desc: &wgt::StencilStateFaceDescriptor, stencil_state_face_desc: &wgt::StencilStateFaceDescriptor,
) -> hal::pso::StencilFace { ) -> hal::pso::StencilFace {
hal::pso::StencilFace { hal::pso::StencilFace {
fun: map_compare_function(stencil_state_face_desc.compare) fun: map_compare_function(stencil_state_face_desc.compare),
.expect("StencilStateFaceDescriptor has undefined compare function"),
op_fail: map_stencil_operation(stencil_state_face_desc.fail_op), op_fail: map_stencil_operation(stencil_state_face_desc.fail_op),
op_depth_fail: map_stencil_operation(stencil_state_face_desc.depth_fail_op), op_depth_fail: map_stencil_operation(stencil_state_face_desc.depth_fail_op),
op_pass: map_stencil_operation(stencil_state_face_desc.pass_op), op_pass: map_stencil_operation(stencil_state_face_desc.pass_op),
} }
} }
pub fn map_compare_function( pub fn map_compare_function(compare_function: wgt::CompareFunction) -> hal::pso::Comparison {
compare_function: wgt::CompareFunction,
) -> Option<hal::pso::Comparison> {
use hal::pso::Comparison as H; use hal::pso::Comparison as H;
use wgt::CompareFunction as Cf; use wgt::CompareFunction as Cf;
match compare_function { match compare_function {
Cf::Undefined => None, Cf::Never => H::Never,
Cf::Never => Some(H::Never), Cf::Less => H::Less,
Cf::Less => Some(H::Less), Cf::Equal => H::Equal,
Cf::Equal => Some(H::Equal), Cf::LessEqual => H::LessEqual,
Cf::LessEqual => Some(H::LessEqual), Cf::Greater => H::Greater,
Cf::Greater => Some(H::Greater), Cf::NotEqual => H::NotEqual,
Cf::NotEqual => Some(H::NotEqual), Cf::GreaterEqual => H::GreaterEqual,
Cf::GreaterEqual => Some(H::GreaterEqual), Cf::Always => H::Always,
Cf::Always => Some(H::Always),
} }
} }

View File

@ -12,7 +12,7 @@ use crate::{
id, pipeline, resource, span, swap_chain, id, pipeline, resource, span, swap_chain,
track::{BufferState, TextureState, TrackerSet}, track::{BufferState, TextureState, TrackerSet},
validation::{self, check_buffer_usage, check_texture_usage}, validation::{self, check_buffer_usage, check_texture_usage},
FastHashMap, LifeGuard, MultiRefCount, PrivateFeatures, Stored, SubmissionIndex, FastHashMap, Label, LifeGuard, MultiRefCount, PrivateFeatures, Stored, SubmissionIndex,
MAX_BIND_GROUPS, MAX_BIND_GROUPS,
}; };
@ -30,8 +30,8 @@ use thiserror::Error;
use wgt::{BufferAddress, BufferSize, InputStepMode, TextureDimension, TextureFormat}; use wgt::{BufferAddress, BufferSize, InputStepMode, TextureDimension, TextureFormat};
use std::{ use std::{
borrow::Cow, collections::hash_map::Entry, ffi, iter, marker::PhantomData, mem, ops::Range, borrow::Cow, collections::hash_map::Entry, iter, marker::PhantomData, mem, ops::Range, ptr,
ptr, sync::atomic::Ordering, sync::atomic::Ordering,
}; };
mod life; mod life;
@ -43,18 +43,6 @@ use smallvec::SmallVec;
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
use trace::{Action, Trace}; use trace::{Action, Trace};
pub type Label = *const std::os::raw::c_char;
#[cfg(feature = "trace")]
fn own_label(label: &Label) -> String {
if label.is_null() {
String::new()
} else {
unsafe { ffi::CStr::from_ptr(*label) }
.to_string_lossy()
.to_string()
}
}
pub const MAX_COLOR_TARGETS: usize = 4; pub const MAX_COLOR_TARGETS: usize = 4;
pub const MAX_MIP_LEVELS: u32 = 16; pub const MAX_MIP_LEVELS: u32 = 16;
pub const MAX_VERTEX_BUFFERS: usize = 16; pub const MAX_VERTEX_BUFFERS: usize = 16;
@ -394,7 +382,7 @@ impl<B: GfxBackend> Device<B> {
fn create_buffer( fn create_buffer(
&self, &self,
self_id: id::DeviceId, self_id: id::DeviceId,
desc: &wgt::BufferDescriptor<Label>, desc: &resource::BufferDescriptor,
memory_kind: gfx_memory::Kind, memory_kind: gfx_memory::Kind,
) -> Result<resource::Buffer<B>, resource::CreateBufferError> { ) -> Result<resource::Buffer<B>, resource::CreateBufferError> {
debug_assert_eq!(self_id.backend(), B::VARIANT); debug_assert_eq!(self_id.backend(), B::VARIANT);
@ -428,19 +416,14 @@ impl<B: GfxBackend> Device<B> {
} }
}; };
let mut buffer = unsafe { let mut buffer = unsafe { self.raw.create_buffer(desc.size.max(1), usage) }.map_err(
self.raw |err| match err {
.create_buffer(desc.size.max(1), usage) hal::buffer::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory,
.map_err(|err| match err { _ => panic!("failed to create buffer: {}", err),
hal::buffer::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory, },
_ => panic!("failed to create buffer: {}", err), )?;
})? if let Some(ref label) = desc.label {
}; unsafe { self.raw.set_buffer_name(&mut buffer, label) };
if !desc.label.is_null() {
unsafe {
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
self.raw.set_buffer_name(&mut buffer, &label)
};
} }
let requirements = unsafe { self.raw.get_buffer_requirements(&buffer) }; let requirements = unsafe { self.raw.get_buffer_requirements(&buffer) };
@ -474,7 +457,7 @@ impl<B: GfxBackend> Device<B> {
fn create_texture( fn create_texture(
&self, &self,
self_id: id::DeviceId, self_id: id::DeviceId,
desc: &wgt::TextureDescriptor<Label>, desc: &resource::TextureDescriptor,
) -> Result<resource::Texture<B>, resource::CreateTextureError> { ) -> Result<resource::Texture<B>, resource::CreateTextureError> {
debug_assert_eq!(self_id.backend(), B::VARIANT); debug_assert_eq!(self_id.backend(), B::VARIANT);
@ -527,9 +510,8 @@ impl<B: GfxBackend> Device<B> {
hal::image::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory, hal::image::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory,
_ => panic!("failed to create texture: {}", err), _ => panic!("failed to create texture: {}", err),
})?; })?;
if !desc.label.is_null() { if let Some(ref label) = desc.label {
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy(); self.raw.set_image_name(&mut image, label);
self.raw.set_image_name(&mut image, &label);
} }
image image
}; };
@ -638,10 +620,7 @@ impl<B: GfxBackend> Device<B> {
) -> Result<binding_model::BindGroupLayout<B>, binding_model::CreateBindGroupLayoutError> { ) -> Result<binding_model::BindGroupLayout<B>, binding_model::CreateBindGroupLayoutError> {
// Validate the count parameter // Validate the count parameter
for binding in entry_map.values() { for binding in entry_map.values() {
if let Some(count) = binding.count { if binding.count.is_some() {
if count == 0 {
return Err(binding_model::CreateBindGroupLayoutError::ZeroCount);
}
match binding.ty { match binding.ty {
wgt::BindingType::SampledTexture { .. } => { wgt::BindingType::SampledTexture { .. } => {
if !self if !self
@ -665,7 +644,7 @@ impl<B: GfxBackend> Device<B> {
ty: conv::map_binding_type(entry), ty: conv::map_binding_type(entry),
count: entry count: entry
.count .count
.map_or(1, |v| v as hal::pso::DescriptorArrayIndex), //TODO: consolidate .map_or(1, |v| v.get() as hal::pso::DescriptorArrayIndex), //TODO: consolidate
stage_flags: conv::map_shader_stage_flags(entry.visibility), stage_flags: conv::map_shader_stage_flags(entry.visibility),
immutable_samplers: false, // TODO immutable_samplers: false, // TODO
}) })
@ -703,7 +682,7 @@ impl<B: GfxBackend> Device<B> {
desc_counts: raw_bindings.iter().cloned().collect(), desc_counts: raw_bindings.iter().cloned().collect(),
dynamic_count: entry_map dynamic_count: entry_map
.values() .values()
.filter(|b| b.has_dynamic_offset()) .filter(|b| b.ty.has_dynamic_offset())
.count(), .count(),
count_validator, count_validator,
entries: entry_map, entries: entry_map,
@ -713,7 +692,7 @@ impl<B: GfxBackend> Device<B> {
fn create_pipeline_layout( fn create_pipeline_layout(
&self, &self,
self_id: id::DeviceId, self_id: id::DeviceId,
desc: &wgt::PipelineLayoutDescriptor<id::BindGroupLayoutId>, desc: &binding_model::PipelineLayoutDescriptor,
bgl_guard: &Storage<binding_model::BindGroupLayout<B>, id::BindGroupLayoutId>, bgl_guard: &Storage<binding_model::BindGroupLayout<B>, id::BindGroupLayoutId>,
) -> Result<binding_model::PipelineLayout<B>, CreatePipelineLayoutError> { ) -> Result<binding_model::PipelineLayout<B>, CreatePipelineLayoutError> {
let bind_group_layouts_count = desc.bind_group_layouts.len(); let bind_group_layouts_count = desc.bind_group_layouts.len();
@ -790,12 +769,20 @@ impl<B: GfxBackend> Device<B> {
.iter() .iter()
.map(|pc| (conv::map_shader_stage_flags(pc.stages), pc.range.clone())); .map(|pc| (conv::map_shader_stage_flags(pc.stages), pc.range.clone()));
let raw = unsafe {
let raw_layout = self
.raw
.create_pipeline_layout(descriptor_set_layouts, push_constants)
.or(Err(DeviceError::OutOfMemory))?;
if let Some(_) = desc.label {
//TODO-0.6: needs gfx changes published
//self.raw.set_pipeline_layout_name(&mut raw_layout, label);
}
raw_layout
};
Ok(binding_model::PipelineLayout { Ok(binding_model::PipelineLayout {
raw: unsafe { raw,
self.raw
.create_pipeline_layout(descriptor_set_layouts, push_constants)
.or(Err(DeviceError::OutOfMemory))?
},
device_id: Stored { device_id: Stored {
value: id::Valid(self_id), value: id::Valid(self_id),
ref_count: self.life_guard.add_ref(), ref_count: self.life_guard.add_ref(),
@ -956,7 +943,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_create_buffer<B: GfxBackend>( pub fn device_create_buffer<B: GfxBackend>(
&self, &self,
device_id: id::DeviceId, device_id: id::DeviceId,
desc: &wgt::BufferDescriptor<Label>, desc: &resource::BufferDescriptor,
id_in: Input<G, id::BufferId>, id_in: Input<G, id::BufferId>,
) -> Result<id::BufferId, resource::CreateBufferError> { ) -> Result<id::BufferId, resource::CreateBufferError> {
span!(_guard, INFO, "Device::create_buffer"); span!(_guard, INFO, "Device::create_buffer");
@ -1000,7 +987,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut stage = device.create_buffer( let mut stage = device.create_buffer(
device_id, device_id,
&wgt::BufferDescriptor { &wgt::BufferDescriptor {
label: b"<init_buffer>\0".as_ptr() as *const _, label: Some(Cow::Borrowed("<init_buffer>")),
size: desc.size, size: desc.size,
usage: wgt::BufferUsage::MAP_WRITE | wgt::BufferUsage::COPY_SRC, usage: wgt::BufferUsage::MAP_WRITE | wgt::BufferUsage::COPY_SRC,
mapped_at_creation: false, mapped_at_creation: false,
@ -1025,7 +1012,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
match device.trace { match device.trace {
Some(ref trace) => { Some(ref trace) => {
let mut desc = desc.map_label(own_label); let mut desc = desc.clone();
let mapped_at_creation = mem::replace(&mut desc.mapped_at_creation, false); let mapped_at_creation = mem::replace(&mut desc.mapped_at_creation, false);
if mapped_at_creation && !desc.usage.contains(wgt::BufferUsage::MAP_WRITE) { if mapped_at_creation && !desc.usage.contains(wgt::BufferUsage::MAP_WRITE) {
desc.usage |= wgt::BufferUsage::COPY_DST; desc.usage |= wgt::BufferUsage::COPY_DST;
@ -1222,7 +1209,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_create_texture<B: GfxBackend>( pub fn device_create_texture<B: GfxBackend>(
&self, &self,
device_id: id::DeviceId, device_id: id::DeviceId,
desc: &wgt::TextureDescriptor<Label>, desc: &resource::TextureDescriptor,
id_in: Input<G, id::TextureId>, id_in: Input<G, id::TextureId>,
) -> Result<id::TextureId, resource::CreateTextureError> { ) -> Result<id::TextureId, resource::CreateTextureError> {
span!(_guard, INFO, "Device::create_texture"); span!(_guard, INFO, "Device::create_texture");
@ -1241,10 +1228,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = hub.textures.register_identity(id_in, texture, &mut token); let id = hub.textures.register_identity(id_in, texture, &mut token);
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
match device.trace { match device.trace {
Some(ref trace) => trace.lock().add(trace::Action::CreateTexture( Some(ref trace) => trace
id.0, .lock()
desc.map_label(own_label), .add(trace::Action::CreateTexture(id.0, desc.clone())),
)),
None => (), None => (),
}; };
@ -1306,7 +1292,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn texture_create_view<B: GfxBackend>( pub fn texture_create_view<B: GfxBackend>(
&self, &self,
texture_id: id::TextureId, texture_id: id::TextureId,
desc: Option<&wgt::TextureViewDescriptor<Label>>, desc: &resource::TextureViewDescriptor,
id_in: Input<G, id::TextureViewId>, id_in: Input<G, id::TextureViewId>,
) -> Result<id::TextureViewId, resource::CreateTextureViewError> { ) -> Result<id::TextureViewId, resource::CreateTextureViewError> {
span!(_guard, INFO, "Texture::create_view"); span!(_guard, INFO, "Texture::create_view");
@ -1321,62 +1307,57 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.map_err(|_| resource::CreateTextureViewError::InvalidTexture)?; .map_err(|_| resource::CreateTextureViewError::InvalidTexture)?;
let device = &device_guard[texture.device_id.value]; let device = &device_guard[texture.device_id.value];
let (format, view_kind, range) = match desc { let view_kind = match desc.dimension {
Some(desc) => { Some(dim) => conv::map_texture_view_dimension(dim),
let kind = conv::map_texture_view_dimension(desc.dimension); None => match texture.kind {
let required_level_count = hal::image::Kind::D1(_, 1) => hal::image::ViewKind::D1,
desc.base_mip_level + desc.level_count.map_or(1, |count| count.get()); hal::image::Kind::D1(..) => hal::image::ViewKind::D1Array,
let required_layer_count = hal::image::Kind::D2(_, _, 1, _) => hal::image::ViewKind::D2,
desc.base_array_layer + desc.array_layer_count.map_or(1, |count| count.get()); hal::image::Kind::D2(..) => hal::image::ViewKind::D2Array,
let level_end = texture.full_range.levels.end; hal::image::Kind::D3(..) => hal::image::ViewKind::D3,
let layer_end = texture.full_range.layers.end; },
if required_level_count > level_end as u32 { };
return Err(resource::CreateTextureViewError::InvalidMipLevelCount { let required_level_count =
requested: required_level_count, desc.base_mip_level + desc.level_count.map_or(1, |count| count.get());
total: level_end, let required_layer_count =
}); desc.base_array_layer + desc.array_layer_count.map_or(1, |count| count.get());
} let level_end = texture.full_range.levels.end;
if required_layer_count > layer_end as u32 { let layer_end = texture.full_range.layers.end;
return Err(resource::CreateTextureViewError::InvalidArrayLayerCount { if required_level_count > level_end as u32 {
requested: required_layer_count, return Err(resource::CreateTextureViewError::InvalidMipLevelCount {
total: layer_end, requested: required_level_count,
}); total: level_end,
}; });
let end_level = desc }
.level_count if required_layer_count > layer_end as u32 {
.map_or(level_end, |_| required_level_count as u8); return Err(resource::CreateTextureViewError::InvalidArrayLayerCount {
let end_layer = desc requested: required_layer_count,
.array_layer_count total: layer_end,
.map_or(layer_end, |_| required_layer_count as u16); });
let aspects = match desc.aspect { };
wgt::TextureAspect::All => texture.full_range.aspects, let end_level = desc
wgt::TextureAspect::DepthOnly => hal::format::Aspects::DEPTH, .level_count
wgt::TextureAspect::StencilOnly => hal::format::Aspects::STENCIL, .map_or(level_end, |_| required_level_count as u8);
}; let end_layer = desc
if !texture.full_range.aspects.contains(aspects) { .array_layer_count
return Err(resource::CreateTextureViewError::InvalidAspect { .map_or(layer_end, |_| required_layer_count as u16);
requested: aspects, let aspects = match desc.aspect {
total: texture.full_range.aspects, wgt::TextureAspect::All => texture.full_range.aspects,
}); wgt::TextureAspect::DepthOnly => hal::format::Aspects::DEPTH,
} wgt::TextureAspect::StencilOnly => hal::format::Aspects::STENCIL,
};
if !texture.full_range.aspects.contains(aspects) {
return Err(resource::CreateTextureViewError::InvalidAspect {
requested: aspects,
total: texture.full_range.aspects,
});
}
let range = hal::image::SubresourceRange { let format = desc.format.unwrap_or(texture.format);
aspects, let range = hal::image::SubresourceRange {
levels: desc.base_mip_level as u8..end_level, aspects,
layers: desc.base_array_layer as u16..end_layer, levels: desc.base_mip_level as u8..end_level,
}; layers: desc.base_array_layer as u16..end_layer,
(desc.format, kind, range)
}
None => {
let kind = match texture.kind {
hal::image::Kind::D1(_, 1) => hal::image::ViewKind::D1,
hal::image::Kind::D1(..) => hal::image::ViewKind::D1Array,
hal::image::Kind::D2(_, _, 1, _) => hal::image::ViewKind::D2,
hal::image::Kind::D2(..) => hal::image::ViewKind::D2Array,
hal::image::Kind::D3(..) => hal::image::ViewKind::D3,
};
(texture.format, kind, texture.full_range.clone())
}
}; };
let raw = unsafe { let raw = unsafe {
@ -1414,7 +1395,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Some(ref trace) => trace.lock().add(trace::Action::CreateTextureView { Some(ref trace) => trace.lock().add(trace::Action::CreateTextureView {
id: id.0, id: id.0,
parent_id: texture_id, parent_id: texture_id,
desc: desc.map(|d| d.map_label(own_label)), desc: desc.clone(),
}), }),
None => (), None => (),
}; };
@ -1482,7 +1463,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_create_sampler<B: GfxBackend>( pub fn device_create_sampler<B: GfxBackend>(
&self, &self,
device_id: id::DeviceId, device_id: id::DeviceId,
desc: &wgt::SamplerDescriptor<Label>, desc: &resource::SamplerDescriptor,
id_in: Input<G, id::SamplerId>, id_in: Input<G, id::SamplerId>,
) -> Result<id::SamplerId, resource::CreateSamplerError> { ) -> Result<id::SamplerId, resource::CreateSamplerError> {
span!(_guard, INFO, "Device::create_sampler"); span!(_guard, INFO, "Device::create_sampler");
@ -1495,6 +1476,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.map_err(|_| DeviceError::Invalid)?; .map_err(|_| DeviceError::Invalid)?;
let actual_clamp = if let Some(clamp) = desc.anisotropy_clamp { let actual_clamp = if let Some(clamp) = desc.anisotropy_clamp {
let clamp = clamp.get();
let valid_clamp = clamp <= MAX_ANISOTROPY && conv::is_power_of_two(clamp as u32); let valid_clamp = clamp <= MAX_ANISOTROPY && conv::is_power_of_two(clamp as u32);
if !valid_clamp { if !valid_clamp {
return Err(resource::CreateSamplerError::InvalidClamp(clamp)); return Err(resource::CreateSamplerError::InvalidClamp(clamp));
@ -1513,13 +1495,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
mag_filter: conv::map_filter(desc.mag_filter), mag_filter: conv::map_filter(desc.mag_filter),
mip_filter: conv::map_filter(desc.mipmap_filter), mip_filter: conv::map_filter(desc.mipmap_filter),
wrap_mode: ( wrap_mode: (
conv::map_wrap(desc.address_mode_u), conv::map_wrap(desc.address_modes[0]),
conv::map_wrap(desc.address_mode_v), conv::map_wrap(desc.address_modes[1]),
conv::map_wrap(desc.address_mode_w), conv::map_wrap(desc.address_modes[2]),
), ),
lod_bias: hal::image::Lod(0.0), lod_bias: hal::image::Lod(0.0),
lod_range: hal::image::Lod(desc.lod_min_clamp)..hal::image::Lod(desc.lod_max_clamp), lod_range: hal::image::Lod(desc.lod_min_clamp)..hal::image::Lod(desc.lod_max_clamp),
comparison: desc.compare.and_then(conv::map_compare_function), comparison: desc.compare.map(conv::map_compare_function),
border: hal::image::PackedColor(0), border: hal::image::PackedColor(0),
normalized: true, normalized: true,
anisotropy_clamp: actual_clamp, anisotropy_clamp: actual_clamp,
@ -1549,10 +1531,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = hub.samplers.register_identity(id_in, sampler, &mut token); let id = hub.samplers.register_identity(id_in, sampler, &mut token);
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
match device.trace { match device.trace {
Some(ref trace) => trace.lock().add(trace::Action::CreateSampler( Some(ref trace) => trace
id.0, .lock()
desc.map_label(own_label), .add(trace::Action::CreateSampler(id.0, desc.clone())),
)),
None => (), None => (),
}; };
@ -1603,7 +1584,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_create_bind_group_layout<B: GfxBackend>( pub fn device_create_bind_group_layout<B: GfxBackend>(
&self, &self,
device_id: id::DeviceId, device_id: id::DeviceId,
desc: &wgt::BindGroupLayoutDescriptor, desc: &binding_model::BindGroupLayoutDescriptor,
id_in: Input<G, id::BindGroupLayoutId>, id_in: Input<G, id::BindGroupLayoutId>,
) -> Result<id::BindGroupLayoutId, binding_model::CreateBindGroupLayoutError> { ) -> Result<id::BindGroupLayoutId, binding_model::CreateBindGroupLayoutError> {
span!(_guard, INFO, "Device::create_bind_group_layout"); span!(_guard, INFO, "Device::create_bind_group_layout");
@ -1695,7 +1676,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_create_pipeline_layout<B: GfxBackend>( pub fn device_create_pipeline_layout<B: GfxBackend>(
&self, &self,
device_id: id::DeviceId, device_id: id::DeviceId,
desc: &wgt::PipelineLayoutDescriptor<id::BindGroupLayoutId>, desc: &binding_model::PipelineLayoutDescriptor,
id_in: Input<G, id::PipelineLayoutId>, id_in: Input<G, id::PipelineLayoutId>,
) -> Result<id::PipelineLayoutId, CreatePipelineLayoutError> { ) -> Result<id::PipelineLayoutId, CreatePipelineLayoutError> {
span!(_guard, INFO, "Device::create_pipeline_layout"); span!(_guard, INFO, "Device::create_pipeline_layout");
@ -1810,7 +1791,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Some(dedup_id) => dedup_id, Some(dedup_id) => dedup_id,
None => { None => {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let bgl_desc = wgt::BindGroupLayoutDescriptor { let bgl_desc = binding_model::BindGroupLayoutDescriptor {
label: None, label: None,
entries: if device.trace.is_some() { entries: if device.trace.is_some() {
Cow::Owned(map.values().cloned().collect()) Cow::Owned(map.values().cloned().collect())
@ -1837,7 +1818,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
derived_group_layout_ids.push(processed_id); derived_group_layout_ids.push(processed_id);
} }
let layout_desc = wgt::PipelineLayoutDescriptor { let layout_desc = binding_model::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: Cow::Borrowed(&derived_group_layout_ids), bind_group_layouts: Cow::Borrowed(&derived_group_layout_ids),
push_constant_ranges: Cow::Borrowed(&[]), //TODO? push_constant_ranges: Cow::Borrowed(&[]), //TODO?
}; };
@ -2113,7 +2095,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
if let Some(count) = decl.count { if let Some(count) = decl.count {
let count = count as usize; let count = count.get() as usize;
let num_bindings = bindings_array.len(); let num_bindings = bindings_array.len();
if count != num_bindings { if count != num_bindings {
return Err(CreateBindGroupError::BindingArrayLengthMismatch { return Err(CreateBindGroupError::BindingArrayLengthMismatch {
@ -2433,11 +2415,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
unsafe { unsafe {
let raw_command_buffer = command_buffer.raw.last_mut().unwrap(); let raw_command_buffer = command_buffer.raw.last_mut().unwrap();
if !desc.label.is_null() { if let Some(ref label) = desc.label {
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
device device
.raw .raw
.set_command_buffer_name(raw_command_buffer, &label); .set_command_buffer_name(raw_command_buffer, label);
} }
raw_command_buffer.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT); raw_command_buffer.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT);
} }
@ -2491,7 +2472,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_create_render_bundle_encoder( pub fn device_create_render_bundle_encoder(
&self, &self,
device_id: id::DeviceId, device_id: id::DeviceId,
desc: &wgt::RenderBundleEncoderDescriptor, desc: &command::RenderBundleEncoderDescriptor,
) -> Result<id::RenderBundleEncoderId, command::CreateRenderBundleError> { ) -> Result<id::RenderBundleEncoderId, command::CreateRenderBundleError> {
span!(_guard, INFO, "Device::create_render_bundle_encoder"); span!(_guard, INFO, "Device::create_render_bundle_encoder");
let encoder = command::RenderBundleEncoder::new(desc, device_id, None); let encoder = command::RenderBundleEncoder::new(desc, device_id, None);
@ -2933,7 +2914,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
} }
if let Some(ds) = depth_stencil_state.as_ref() { if let Some(ds) = depth_stencil_state.as_ref() {
if ds.needs_stencil_reference() { if ds.stencil.as_ref().map_or(false, |s| s.needs_ref_value()) {
flags |= pipeline::PipelineFlags::STENCIL_REFERENCE; flags |= pipeline::PipelineFlags::STENCIL_REFERENCE;
} }
if !ds.is_read_only() { if !ds.is_read_only() {
@ -2966,7 +2947,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
match device.trace { match device.trace {
Some(ref trace) => trace.lock().add(trace::Action::CreateRenderPipeline( Some(ref trace) => trace.lock().add(trace::Action::CreateRenderPipeline(
id.0, id.0,
wgt::RenderPipelineDescriptor { pipeline::RenderPipelineDescriptor {
layout: Some(layout_id), layout: Some(layout_id),
..desc.clone() ..desc.clone()
}, },
@ -3185,7 +3166,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
match device.trace { match device.trace {
Some(ref trace) => trace.lock().add(trace::Action::CreateComputePipeline( Some(ref trace) => trace.lock().add(trace::Action::CreateComputePipeline(
id.0, id.0,
wgt::ComputePipelineDescriptor { pipeline::ComputePipelineDescriptor {
layout: Some(layout_id), layout: Some(layout_id),
..desc.clone() ..desc.clone()
}, },

View File

@ -5,7 +5,7 @@
use crate::id; use crate::id;
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
use std::io::Write as _; use std::io::Write as _;
use std::ops::Range; use std::{borrow::Cow, ops::Range};
//TODO: consider a readable Id that doesn't include the backend //TODO: consider a readable Id that doesn't include the backend
@ -14,13 +14,13 @@ type FileName = String;
pub const FILE_NAME: &str = "trace.ron"; pub const FILE_NAME: &str = "trace.ron";
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
pub(crate) fn new_render_bundle_encoder_descriptor( pub(crate) fn new_render_bundle_encoder_descriptor<'a>(
label: super::Label, label: Option<&'a str>,
context: &super::RenderPassContext, context: &'a super::RenderPassContext,
) -> wgt::RenderBundleEncoderDescriptor { ) -> crate::command::RenderBundleEncoderDescriptor<'a> {
wgt::RenderBundleEncoderDescriptor { crate::command::RenderBundleEncoderDescriptor {
label: Some(super::own_label(&label).into()), label: label.map(Cow::Borrowed),
color_formats: context.attachments.colors.to_vec().into(), color_formats: Cow::Borrowed(&context.attachments.colors),
depth_stencil_format: context.attachments.depth_stencil, depth_stencil_format: context.attachments.depth_stencil,
sample_count: context.sample_count as u32, sample_count: context.sample_count as u32,
} }
@ -34,17 +34,17 @@ pub enum Action<'a> {
desc: wgt::DeviceDescriptor, desc: wgt::DeviceDescriptor,
backend: wgt::Backend, backend: wgt::Backend,
}, },
CreateBuffer(id::BufferId, wgt::BufferDescriptor<String>), CreateBuffer(id::BufferId, crate::resource::BufferDescriptor<'a>),
DestroyBuffer(id::BufferId), DestroyBuffer(id::BufferId),
CreateTexture(id::TextureId, wgt::TextureDescriptor<String>), CreateTexture(id::TextureId, crate::resource::TextureDescriptor<'a>),
DestroyTexture(id::TextureId), DestroyTexture(id::TextureId),
CreateTextureView { CreateTextureView {
id: id::TextureViewId, id: id::TextureViewId,
parent_id: id::TextureId, parent_id: id::TextureId,
desc: Option<wgt::TextureViewDescriptor<String>>, desc: crate::resource::TextureViewDescriptor<'a>,
}, },
DestroyTextureView(id::TextureViewId), DestroyTextureView(id::TextureViewId),
CreateSampler(id::SamplerId, wgt::SamplerDescriptor<String>), CreateSampler(id::SamplerId, crate::resource::SamplerDescriptor<'a>),
DestroySampler(id::SamplerId), DestroySampler(id::SamplerId),
CreateSwapChain(id::SwapChainId, wgt::SwapChainDescriptor), CreateSwapChain(id::SwapChainId, wgt::SwapChainDescriptor),
GetSwapChainTexture { GetSwapChainTexture {
@ -52,20 +52,19 @@ pub enum Action<'a> {
parent_id: id::SwapChainId, parent_id: id::SwapChainId,
}, },
PresentSwapChain(id::SwapChainId), PresentSwapChain(id::SwapChainId),
CreateBindGroupLayout(id::BindGroupLayoutId, wgt::BindGroupLayoutDescriptor<'a>), CreateBindGroupLayout(
id::BindGroupLayoutId,
crate::binding_model::BindGroupLayoutDescriptor<'a>,
),
DestroyBindGroupLayout(id::BindGroupLayoutId), DestroyBindGroupLayout(id::BindGroupLayoutId),
CreatePipelineLayout( CreatePipelineLayout(
id::PipelineLayoutId, id::PipelineLayoutId,
wgt::PipelineLayoutDescriptor<'a, id::BindGroupLayoutId>, crate::binding_model::PipelineLayoutDescriptor<'a>,
), ),
DestroyPipelineLayout(id::PipelineLayoutId), DestroyPipelineLayout(id::PipelineLayoutId),
CreateBindGroup( CreateBindGroup(
id::BindGroupId, id::BindGroupId,
wgt::BindGroupDescriptor< crate::binding_model::BindGroupDescriptor<'a>,
'a,
id::BindGroupLayoutId,
wgt::BindGroupEntry<crate::binding_model::BindingResource<'a>>,
>,
), ),
DestroyBindGroup(id::BindGroupId), DestroyBindGroup(id::BindGroupId),
CreateShaderModule { CreateShaderModule {
@ -75,24 +74,17 @@ pub enum Action<'a> {
DestroyShaderModule(id::ShaderModuleId), DestroyShaderModule(id::ShaderModuleId),
CreateComputePipeline( CreateComputePipeline(
id::ComputePipelineId, id::ComputePipelineId,
wgt::ComputePipelineDescriptor< crate::pipeline::ComputePipelineDescriptor<'a>,
id::PipelineLayoutId,
wgt::ProgrammableStageDescriptor<'a, id::ShaderModuleId>,
>,
), ),
DestroyComputePipeline(id::ComputePipelineId), DestroyComputePipeline(id::ComputePipelineId),
CreateRenderPipeline( CreateRenderPipeline(
id::RenderPipelineId, id::RenderPipelineId,
wgt::RenderPipelineDescriptor< crate::pipeline::RenderPipelineDescriptor<'a>,
'a,
id::PipelineLayoutId,
wgt::ProgrammableStageDescriptor<'a, id::ShaderModuleId>,
>,
), ),
DestroyRenderPipeline(id::RenderPipelineId), DestroyRenderPipeline(id::RenderPipelineId),
CreateRenderBundle { CreateRenderBundle {
id: id::RenderBundleId, id: id::RenderBundleId,
desc: wgt::RenderBundleEncoderDescriptor<'a>, desc: crate::command::RenderBundleEncoderDescriptor<'a>,
base: crate::command::BasePass<crate::command::RenderCommand>, base: crate::command::BasePass<crate::command::RenderCommand>,
}, },
DestroyRenderBundle(id::RenderBundleId), DestroyRenderBundle(id::RenderBundleId),

View File

@ -49,7 +49,7 @@ use std::sync::atomic;
use atomic::{AtomicUsize, Ordering}; use atomic::{AtomicUsize, Ordering};
use std::{os::raw::c_char, ptr}; use std::{borrow::Cow, os::raw::c_char, ptr};
pub const MAX_BIND_GROUPS: usize = 8; pub const MAX_BIND_GROUPS: usize = 8;
@ -58,6 +58,7 @@ type Index = u32;
type Epoch = u32; type Epoch = u32;
pub type RawString = *const c_char; pub type RawString = *const c_char;
pub type Label<'a> = Option<Cow<'a, str>>;
/// Reference count object that is 1:1 with each reference. /// Reference count object that is 1:1 with each reference.
#[derive(Debug)] #[derive(Debug)]

View File

@ -36,7 +36,17 @@ pub enum CreateShaderModuleError {
Validation(#[from] naga::proc::ValidationError), Validation(#[from] naga::proc::ValidationError),
} }
pub type ProgrammableStageDescriptor<'a> = wgt::ProgrammableStageDescriptor<'a, ShaderModuleId>; /// Describes a programmable pipeline stage.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ProgrammableStageDescriptor<'a> {
/// The compiled shader module for this stage.
pub module: ShaderModuleId,
/// The name of the entry point in the compiled shader. There must be a function that returns
/// void with this name in the shader.
pub entry_point: Cow<'a, str>,
}
/// Number of implicit bind groups derived at pipeline creation. /// Number of implicit bind groups derived at pipeline creation.
pub type ImplicitBindGroupCount = u8; pub type ImplicitBindGroupCount = u8;
@ -53,8 +63,16 @@ pub enum ImplicitLayoutError {
Pipeline(#[from] CreatePipelineLayoutError), Pipeline(#[from] CreatePipelineLayoutError),
} }
pub type ComputePipelineDescriptor<'a> = /// Describes a compute pipeline.
wgt::ComputePipelineDescriptor<PipelineLayoutId, ProgrammableStageDescriptor<'a>>; #[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ComputePipelineDescriptor<'a> {
/// The layout of bind groups for this pipeline.
pub layout: Option<PipelineLayoutId>,
/// The compiled compute stage and its entry point.
pub compute_stage: ProgrammableStageDescriptor<'a>,
}
#[derive(Clone, Debug, Error)] #[derive(Clone, Debug, Error)]
pub enum CreateComputePipelineError { pub enum CreateComputePipelineError {
@ -82,8 +100,65 @@ impl<B: hal::Backend> Borrow<RefCount> for ComputePipeline<B> {
} }
} }
pub type RenderPipelineDescriptor<'a> = /// Describes how the vertex buffer is interpreted.
wgt::RenderPipelineDescriptor<'a, PipelineLayoutId, ProgrammableStageDescriptor<'a>>; #[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct VertexBufferDescriptor<'a> {
/// The stride, in bytes, between elements of this buffer.
pub stride: BufferAddress,
/// How often this vertex buffer is "stepped" forward.
pub step_mode: InputStepMode,
/// The list of attributes which comprise a single vertex.
pub attributes: Cow<'a, [wgt::VertexAttributeDescriptor]>,
}
/// Describes vertex input state for a render pipeline.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct VertexStateDescriptor<'a> {
/// The format of any index buffers used with this pipeline.
pub index_format: IndexFormat,
/// The format of any vertex buffers used with this pipeline.
pub vertex_buffers: Cow<'a, [VertexBufferDescriptor<'a>]>,
}
/// Describes a render (graphics) pipeline.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct RenderPipelineDescriptor<'a> {
/// The layout of bind groups for this pipeline.
pub layout: Option<PipelineLayoutId>,
/// The compiled vertex stage and its entry point.
pub vertex_stage: ProgrammableStageDescriptor<'a>,
/// The compiled fragment stage and its entry point, if any.
pub fragment_stage: Option<ProgrammableStageDescriptor<'a>>,
/// The rasterization process for this pipeline.
pub rasterization_state: Option<wgt::RasterizationStateDescriptor>,
/// The primitive topology used to interpret vertices.
pub primitive_topology: wgt::PrimitiveTopology,
/// The effect of draw calls on the color aspect of the output target.
pub color_states: Cow<'a, [wgt::ColorStateDescriptor]>,
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
pub depth_stencil_state: Option<wgt::DepthStencilStateDescriptor>,
/// The vertex input state for this pipeline.
pub vertex_state: VertexStateDescriptor<'a>,
/// The number of samples calculated per pixel (for MSAA). For non-multisampled textures,
/// this should be `1`
pub sample_count: u32,
/// Bitmask that restricts the samples of a pixel modified by this pipeline. All samples
/// can be enabled using the value `!0`
pub sample_mask: u32,
/// When enabled, produces another sample mask per pixel based on the alpha output value, that
/// is ANDed with the sample_mask and the primitive coverage to restrict the set of samples
/// affected by a primitive.
///
/// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
/// is guaranteed to be all 1-s.
pub alpha_to_coverage_enabled: bool,
}
#[derive(Clone, Debug, Error)] #[derive(Clone, Debug, Error)]
pub enum CreateRenderPipelineError { pub enum CreateRenderPipelineError {

View File

@ -7,14 +7,17 @@ use crate::{
id::{DeviceId, SwapChainId, TextureId}, id::{DeviceId, SwapChainId, TextureId},
track::DUMMY_SELECTOR, track::DUMMY_SELECTOR,
validation::MissingBufferUsageError, validation::MissingBufferUsageError,
LifeGuard, RefCount, Stored, Label, LifeGuard, RefCount, Stored,
}; };
use gfx_memory::MemoryBlock; use gfx_memory::MemoryBlock;
use thiserror::Error; use thiserror::Error;
use wgt::{BufferAddress, BufferUsage, TextureFormat, TextureUsage};
use std::{borrow::Borrow, ptr::NonNull}; use std::{
borrow::Borrow,
num::{NonZeroU32, NonZeroU8},
ptr::NonNull,
};
bitflags::bitflags! { bitflags::bitflags! {
/// The internal enum mirrored from `BufferUsage`. The values don't have to match! /// The internal enum mirrored from `BufferUsage`. The values don't have to match!
@ -155,13 +158,15 @@ pub(crate) struct BufferPendingMapping {
pub parent_ref_count: RefCount, pub parent_ref_count: RefCount,
} }
pub type BufferDescriptor<'a> = wgt::BufferDescriptor<Label<'a>>;
#[derive(Debug)] #[derive(Debug)]
pub struct Buffer<B: hal::Backend> { pub struct Buffer<B: hal::Backend> {
pub(crate) raw: B::Buffer, pub(crate) raw: B::Buffer,
pub(crate) device_id: Stored<DeviceId>, pub(crate) device_id: Stored<DeviceId>,
pub(crate) usage: BufferUsage, pub(crate) usage: wgt::BufferUsage,
pub(crate) memory: MemoryBlock<B>, pub(crate) memory: MemoryBlock<B>,
pub(crate) size: BufferAddress, pub(crate) size: wgt::BufferAddress,
pub(crate) full_range: (), pub(crate) full_range: (),
pub(crate) sync_mapped_writes: Option<hal::memory::Segment>, pub(crate) sync_mapped_writes: Option<hal::memory::Segment>,
pub(crate) life_guard: LifeGuard, pub(crate) life_guard: LifeGuard,
@ -177,7 +182,7 @@ pub enum CreateBufferError {
#[error("buffers that are mapped at creation have to be aligned to `COPY_BUFFER_ALIGNMENT`")] #[error("buffers that are mapped at creation have to be aligned to `COPY_BUFFER_ALIGNMENT`")]
UnalignedSize, UnalignedSize,
#[error("`MAP` usage can only be combined with the opposite `COPY`, requested {0:?}")] #[error("`MAP` usage can only be combined with the opposite `COPY`, requested {0:?}")]
UsageMismatch(BufferUsage), UsageMismatch(wgt::BufferUsage),
} }
impl<B: hal::Backend> Borrow<RefCount> for Buffer<B> { impl<B: hal::Backend> Borrow<RefCount> for Buffer<B> {
@ -192,14 +197,16 @@ impl<B: hal::Backend> Borrow<()> for Buffer<B> {
} }
} }
pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>>;
#[derive(Debug)] #[derive(Debug)]
pub struct Texture<B: hal::Backend> { pub struct Texture<B: hal::Backend> {
pub(crate) raw: B::Image, pub(crate) raw: B::Image,
pub(crate) device_id: Stored<DeviceId>, pub(crate) device_id: Stored<DeviceId>,
pub(crate) usage: TextureUsage, pub(crate) usage: wgt::TextureUsage,
pub(crate) dimension: wgt::TextureDimension, pub(crate) dimension: wgt::TextureDimension,
pub(crate) kind: hal::image::Kind, pub(crate) kind: hal::image::Kind,
pub(crate) format: TextureFormat, pub(crate) format: wgt::TextureFormat,
pub(crate) full_range: hal::image::SubresourceRange, pub(crate) full_range: hal::image::SubresourceRange,
pub(crate) memory: MemoryBlock<B>, pub(crate) memory: MemoryBlock<B>,
pub(crate) life_guard: LifeGuard, pub(crate) life_guard: LifeGuard,
@ -226,7 +233,7 @@ pub enum CreateTextureError {
#[error("texture descriptor mip level count ({0}) must be less than `MAX_MIP_LEVELS`")] #[error("texture descriptor mip level count ({0}) must be less than `MAX_MIP_LEVELS`")]
InvalidMipLevelCount(u32), InvalidMipLevelCount(u32),
#[error("Feature {0:?} must be enabled to create a texture of type {1:?}")] #[error("Feature {0:?} must be enabled to create a texture of type {1:?}")]
MissingFeature(wgt::Features, TextureFormat), MissingFeature(wgt::Features, wgt::TextureFormat),
} }
impl<B: hal::Backend> Borrow<RefCount> for Texture<B> { impl<B: hal::Backend> Borrow<RefCount> for Texture<B> {
@ -241,6 +248,35 @@ impl<B: hal::Backend> Borrow<hal::image::SubresourceRange> for Texture<B> {
} }
} }
/// Describes a [`TextureView`].
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct TextureViewDescriptor<'a> {
/// Debug label of the texture view. This will show up in graphics debuggers for easy identification.
pub label: Label<'a>,
/// Format of the texture view, or `None` for the same format as the texture itself.
/// At this time, it must be the same the underlying format of the texture.
pub format: Option<wgt::TextureFormat>,
/// The dimension of the texture view. For 1D textures, this must be `1D`. For 2D textures it must be one of
/// `D2`, `D2Array`, `Cube`, and `CubeArray`. For 3D textures it must be `3D`
pub dimension: Option<wgt::TextureViewDimension>,
/// Aspect of the texture. Color textures must be [`TextureAspect::All`].
pub aspect: wgt::TextureAspect,
/// Base mip level.
pub base_mip_level: u32,
/// Mip level count.
/// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count.
/// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total.
pub level_count: Option<NonZeroU32>,
/// Base array layer.
pub base_array_layer: u32,
/// Layer count.
/// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count.
/// If `None`, considered to include the rest of the array layers, but at least 1 in total.
pub array_layer_count: Option<NonZeroU32>,
}
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum TextureViewInner<B: hal::Backend> { pub(crate) enum TextureViewInner<B: hal::Backend> {
Native { Native {
@ -257,7 +293,7 @@ pub(crate) enum TextureViewInner<B: hal::Backend> {
pub struct TextureView<B: hal::Backend> { pub struct TextureView<B: hal::Backend> {
pub(crate) inner: TextureViewInner<B>, pub(crate) inner: TextureViewInner<B>,
//TODO: store device_id for quick access? //TODO: store device_id for quick access?
pub(crate) format: TextureFormat, pub(crate) format: wgt::TextureFormat,
pub(crate) extent: hal::image::Extent, pub(crate) extent: hal::image::Extent,
pub(crate) samples: hal::image::NumSamples, pub(crate) samples: hal::image::NumSamples,
pub(crate) range: hal::image::SubresourceRange, pub(crate) range: hal::image::SubresourceRange,
@ -301,6 +337,47 @@ impl<B: hal::Backend> Borrow<()> for TextureView<B> {
} }
} }
/// Describes a [`Sampler`]
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct SamplerDescriptor<'a> {
/// Debug label of the sampler. This will show up in graphics debuggers for easy identification.
pub label: Label<'a>,
/// How to deal with out of bounds accesses in the u (i.e. x) direction
pub address_modes: [wgt::AddressMode; 3],
/// How to filter the texture when it needs to be magnified (made larger)
pub mag_filter: wgt::FilterMode,
/// How to filter the texture when it needs to be minified (made smaller)
pub min_filter: wgt::FilterMode,
/// How to filter between mip map levels
pub mipmap_filter: wgt::FilterMode,
/// Minimum level of detail (i.e. mip level) to use
pub lod_min_clamp: f32,
/// Maximum level of detail (i.e. mip level) to use
pub lod_max_clamp: f32,
/// If this is enabled, this is a comparison sampler using the given comparison function.
pub compare: Option<wgt::CompareFunction>,
/// Valid values: 1, 2, 4, 8, and 16.
pub anisotropy_clamp: Option<NonZeroU8>,
}
impl Default for SamplerDescriptor<'_> {
fn default() -> Self {
Self {
label: None,
address_modes: Default::default(),
mag_filter: Default::default(),
min_filter: Default::default(),
mipmap_filter: Default::default(),
lod_min_clamp: 0.0,
lod_max_clamp: std::f32::MAX,
compare: None,
anisotropy_clamp: None,
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Sampler<B: hal::Backend> { pub struct Sampler<B: hal::Backend> {
pub(crate) raw: B::Sampler, pub(crate) raw: B::Sampler,

View File

@ -1,45 +0,0 @@
use std::borrow::Cow;
/// Implements conversion into a cow.
pub trait IntoCow<'c, CowType: ?Sized + ToOwned> {
fn into_cow(self) -> Cow<'c, CowType>;
}
impl<'c, T: Clone> IntoCow<'c, [T]> for &'c [T] {
fn into_cow(self) -> Cow<'c, [T]> {
Cow::Borrowed(self)
}
}
impl<'c> IntoCow<'c, str> for &'c str {
fn into_cow(self) -> Cow<'c, str> {
Cow::Borrowed(self)
}
}
impl<T: Clone> IntoCow<'static, [T]> for Vec<T> {
fn into_cow(self) -> Cow<'static, [T]> {
Cow::Owned(self)
}
}
impl IntoCow<'static, str> for String {
fn into_cow(self) -> Cow<'static, str> {
Cow::Owned(self)
}
}
macro_rules! into_cow_array {
($($number:literal),*) => {$(
impl<'c, T: Clone> IntoCow<'c, [T]> for &'c [T; $number] {
fn into_cow(self) -> Cow<'c, [T]> {
Cow::Borrowed(&self[..])
}
}
)*};
}
into_cow_array!(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32
);

File diff suppressed because it is too large Load Diff