mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
Grand cleanup and refactor of the descriptors in the API
This commit is contained in:
parent
04f5cfd1c8
commit
9d8dc0b04d
@ -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<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)]
|
||||
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()
|
||||
}
|
||||
|
||||
@ -154,19 +136,15 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
|
||||
panic!("Unexpected SwapChain action: winit feature is not enabled")
|
||||
}
|
||||
A::CreateBuffer(id, desc) => {
|
||||
let label = Label::new(&desc.label);
|
||||
self.device_maintain_ids::<B>(device).unwrap();
|
||||
self.device_create_buffer::<B>(device, &desc.map_label(|_| label.as_ptr()), id)
|
||||
.unwrap();
|
||||
self.device_create_buffer::<B>(device, &desc, id).unwrap();
|
||||
}
|
||||
A::DestroyBuffer(id) => {
|
||||
self.buffer_drop::<B>(id, true);
|
||||
}
|
||||
A::CreateTexture(id, desc) => {
|
||||
let label = Label::new(&desc.label);
|
||||
self.device_maintain_ids::<B>(device).unwrap();
|
||||
self.device_create_texture::<B>(device, &desc.map_label(|_| label.as_ptr()), id)
|
||||
.unwrap();
|
||||
self.device_create_texture::<B>(device, &desc, id).unwrap();
|
||||
}
|
||||
A::DestroyTexture(id) => {
|
||||
self.texture_drop::<B>(id);
|
||||
@ -176,23 +154,15 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
|
||||
parent_id,
|
||||
desc,
|
||||
} => {
|
||||
let label = desc.as_ref().map_or(Label(None), |d| Label::new(&d.label));
|
||||
self.device_maintain_ids::<B>(device).unwrap();
|
||||
self.texture_create_view::<B>(
|
||||
parent_id,
|
||||
desc.map(|d| d.map_label(|_| label.as_ptr())).as_ref(),
|
||||
id,
|
||||
)
|
||||
.unwrap();
|
||||
self.texture_create_view::<B>(parent_id, &desc, id).unwrap();
|
||||
}
|
||||
A::DestroyTextureView(id) => {
|
||||
self.texture_view_drop::<B>(id).unwrap();
|
||||
}
|
||||
A::CreateSampler(id, desc) => {
|
||||
let label = Label::new(&desc.label);
|
||||
self.device_maintain_ids::<B>(device).unwrap();
|
||||
self.device_create_sampler::<B>(device, &desc.map_label(|_| label.as_ptr()), id)
|
||||
.unwrap();
|
||||
self.device_create_sampler::<B>(device, &desc, id).unwrap();
|
||||
}
|
||||
A::DestroySampler(id) => {
|
||||
self.sampler_drop::<B>(id);
|
||||
@ -263,14 +233,11 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
|
||||
self.render_pipeline_drop::<B>(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::<B>(
|
||||
bundle,
|
||||
&wgt::RenderBundleDescriptor {
|
||||
label: label.as_ptr(),
|
||||
},
|
||||
&wgt::RenderBundleDescriptor { label: desc.label },
|
||||
id,
|
||||
)
|
||||
.unwrap();
|
||||
@ -309,7 +276,7 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
|
||||
let encoder = self
|
||||
.device_create_command_encoder::<B>(
|
||||
device,
|
||||
&wgt::CommandEncoderDescriptor { label: ptr::null() },
|
||||
&wgt::CommandEncoderDescriptor { label: None },
|
||||
comb_manager.alloc(device.backend()),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -12,7 +12,7 @@
|
||||
CreateBuffer(
|
||||
Id(0, 1, Empty),
|
||||
(
|
||||
label: "",
|
||||
label: Some("dummy"),
|
||||
size: 16,
|
||||
usage: (
|
||||
bits: 41,
|
||||
|
@ -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<u32, wgt::BindGroupLayoutEntry>;
|
||||
|
||||
#[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<B: hal::Backend> {
|
||||
pub(crate) raw: B::PipelineLayout,
|
||||
@ -446,11 +502,6 @@ pub enum BindingResource<'a> {
|
||||
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)]
|
||||
pub enum BindError {
|
||||
#[error("number of dynamic offsets ({actual}) doesn't match the number of dynamic bindings in the bind group layout ({expected})")]
|
||||
|
@ -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<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)]
|
||||
#[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<BasePass<RenderCommand>>,
|
||||
) -> Result<Self, CreateRenderBundleError> {
|
||||
@ -103,6 +125,8 @@ pub enum CreateRenderBundleError {
|
||||
InvalidSampleCount(u32),
|
||||
}
|
||||
|
||||
pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Label<'a>>;
|
||||
|
||||
//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<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn render_bundle_encoder_finish<B: GfxBackend>(
|
||||
&self,
|
||||
bundle_encoder: RenderBundleEncoder,
|
||||
desc: &wgt::RenderBundleDescriptor<Label>,
|
||||
desc: &RenderBundleDescriptor,
|
||||
id_in: Input<G, id::RenderBundleId>,
|
||||
) -> Result<id::RenderBundleId, RenderBundleError> {
|
||||
span!(_guard, INFO, "RenderBundleEncoder::finish");
|
||||
@ -908,9 +932,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
use crate::device::trace;
|
||||
let (bundle_guard, _) = hub.render_bundles.read(&mut token);
|
||||
let bundle = &bundle_guard[id];
|
||||
let label = desc.label.as_ref().map(|l| l.as_ref());
|
||||
trace.lock().add(trace::Action::CreateRenderBundle {
|
||||
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()),
|
||||
});
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use crate::{
|
||||
resource::{Buffer, Texture},
|
||||
span,
|
||||
track::TrackerSet,
|
||||
PrivateFeatures, Stored,
|
||||
Label, PrivateFeatures, Stored,
|
||||
};
|
||||
|
||||
use hal::command::CommandBuffer as _;
|
||||
@ -168,7 +168,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn command_encoder_finish<B: GfxBackend>(
|
||||
&self,
|
||||
encoder_id: id::CommandEncoderId,
|
||||
_desc: &wgt::CommandBufferDescriptor,
|
||||
_desc: &wgt::CommandBufferDescriptor<Label>,
|
||||
) -> Result<id::CommandBufferId, CommandEncoderError> {
|
||||
span!(_guard, INFO, "CommandEncoder::finish");
|
||||
|
||||
|
@ -37,7 +37,14 @@ use serde::Deserialize;
|
||||
#[cfg(any(feature = "serial-pass", feature = "trace"))]
|
||||
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.
|
||||
#[repr(C)]
|
||||
@ -65,7 +72,7 @@ pub enum StoreOp {
|
||||
|
||||
/// Describes an individual channel within a render pass, such as color, depth, or stencil.
|
||||
#[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 = "replay"), derive(Deserialize))]
|
||||
pub struct PassChannel<V> {
|
||||
@ -83,7 +90,7 @@ pub struct PassChannel<V> {
|
||||
|
||||
/// Describes a color attachment to a render pass.
|
||||
#[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 = "replay"), derive(Deserialize))]
|
||||
pub struct ColorAttachmentDescriptor {
|
||||
@ -97,7 +104,7 @@ pub struct ColorAttachmentDescriptor {
|
||||
|
||||
/// Describes a depth/stencil attachment to a render pass.
|
||||
#[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 = "replay"), derive(Deserialize))]
|
||||
pub struct DepthStencilAttachmentDescriptor {
|
||||
@ -109,27 +116,32 @@ pub struct DepthStencilAttachmentDescriptor {
|
||||
pub stencil: PassChannel<u32>,
|
||||
}
|
||||
|
||||
fn is_depth_stencil_read_only(
|
||||
desc: &DepthStencilAttachmentDescriptor,
|
||||
aspects: hal::format::Aspects,
|
||||
) -> Result<bool, RenderPassError> {
|
||||
if aspects.contains(hal::format::Aspects::DEPTH) && !desc.depth.read_only {
|
||||
return Ok(false);
|
||||
impl DepthStencilAttachmentDescriptor {
|
||||
fn is_read_only(&self, aspects: hal::format::Aspects) -> Result<bool, RenderPassError> {
|
||||
if aspects.contains(hal::format::Aspects::DEPTH) && !self.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> =
|
||||
wgt::RenderPassDescriptor<'a, ColorAttachmentDescriptor, &'a DepthStencilAttachmentDescriptor>;
|
||||
/// Describes the attachments of a render pass.
|
||||
#[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)]
|
||||
#[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))]
|
||||
@ -198,7 +210,7 @@ pub enum RenderCommand {
|
||||
buffer_id: id::BufferId,
|
||||
offset: BufferAddress,
|
||||
/// Count of `None` represents a non-multi call.
|
||||
count: Option<u32>,
|
||||
count: Option<NonZeroU32>,
|
||||
indexed: bool,
|
||||
},
|
||||
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)))]
|
||||
IndirectBufferOverrun {
|
||||
offset: u64,
|
||||
count: Option<u32>,
|
||||
count: Option<NonZeroU32>,
|
||||
begin_offset: u64,
|
||||
end_offset: u64,
|
||||
buffer_size: u64,
|
||||
@ -604,7 +616,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let previous_use = base_trackers
|
||||
.textures
|
||||
.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;
|
||||
TextureUse::ATTACHMENT_READ
|
||||
} else {
|
||||
@ -1414,7 +1426,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.unwrap();
|
||||
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 end_offset = offset + stride * actual_count as u64;
|
||||
@ -1622,7 +1634,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub mod render_ffi {
|
||||
use super::{super::Rect, RenderCommand, RenderPass};
|
||||
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};
|
||||
|
||||
/// # Safety
|
||||
@ -1840,7 +1852,7 @@ pub mod render_ffi {
|
||||
pass.base.commands.push(RenderCommand::MultiDrawIndirect {
|
||||
buffer_id,
|
||||
offset,
|
||||
count: Some(count),
|
||||
count: NonZeroU32::new(count),
|
||||
indexed: false,
|
||||
});
|
||||
}
|
||||
@ -1856,7 +1868,7 @@ pub mod render_ffi {
|
||||
pass.base.commands.push(RenderCommand::MultiDrawIndirect {
|
||||
buffer_id,
|
||||
offset,
|
||||
count: Some(count),
|
||||
count: NonZeroU32::new(count),
|
||||
indexed: true,
|
||||
});
|
||||
}
|
||||
|
@ -244,35 +244,26 @@ pub fn map_depth_stencil_state_descriptor(
|
||||
hal::pso::DepthStencilDesc {
|
||||
depth: if desc.depth_write_enabled || desc.depth_compare != wgt::CompareFunction::Always {
|
||||
Some(hal::pso::DepthTest {
|
||||
fun: map_compare_function(desc.depth_compare)
|
||||
.expect("DepthStencilStateDescriptor has undefined compare function"),
|
||||
fun: map_compare_function(desc.depth_compare),
|
||||
write: desc.depth_write_enabled,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
depth_bounds: false, // TODO
|
||||
stencil: if desc.stencil_read_mask != !0
|
||||
|| desc.stencil_write_mask != !0
|
||||
|| desc.stencil_front != wgt::StencilStateFaceDescriptor::IGNORE
|
||||
|| desc.stencil_back != wgt::StencilStateFaceDescriptor::IGNORE
|
||||
{
|
||||
Some(hal::pso::StencilTest {
|
||||
faces: hal::pso::Sided {
|
||||
front: map_stencil_face(&desc.stencil_front),
|
||||
back: map_stencil_face(&desc.stencil_back),
|
||||
},
|
||||
read_masks: hal::pso::State::Static(hal::pso::Sided::new(desc.stencil_read_mask)),
|
||||
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
|
||||
},
|
||||
stencil: desc.stencil.as_ref().map(|stencil| hal::pso::StencilTest {
|
||||
faces: hal::pso::Sided {
|
||||
front: map_stencil_face(&stencil.front),
|
||||
back: map_stencil_face(&stencil.back),
|
||||
},
|
||||
read_masks: hal::pso::State::Static(hal::pso::Sided::new(stencil.read_mask)),
|
||||
write_masks: hal::pso::State::Static(hal::pso::Sided::new(stencil.write_mask)),
|
||||
reference_values: if stencil.needs_ref_value() {
|
||||
hal::pso::State::Dynamic
|
||||
} else {
|
||||
hal::pso::State::Static(hal::pso::Sided::new(0))
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,29 +271,25 @@ fn map_stencil_face(
|
||||
stencil_state_face_desc: &wgt::StencilStateFaceDescriptor,
|
||||
) -> hal::pso::StencilFace {
|
||||
hal::pso::StencilFace {
|
||||
fun: map_compare_function(stencil_state_face_desc.compare)
|
||||
.expect("StencilStateFaceDescriptor has undefined compare function"),
|
||||
fun: map_compare_function(stencil_state_face_desc.compare),
|
||||
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_pass: map_stencil_operation(stencil_state_face_desc.pass_op),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_compare_function(
|
||||
compare_function: wgt::CompareFunction,
|
||||
) -> Option<hal::pso::Comparison> {
|
||||
pub fn map_compare_function(compare_function: wgt::CompareFunction) -> hal::pso::Comparison {
|
||||
use hal::pso::Comparison as H;
|
||||
use wgt::CompareFunction as Cf;
|
||||
match compare_function {
|
||||
Cf::Undefined => None,
|
||||
Cf::Never => Some(H::Never),
|
||||
Cf::Less => Some(H::Less),
|
||||
Cf::Equal => Some(H::Equal),
|
||||
Cf::LessEqual => Some(H::LessEqual),
|
||||
Cf::Greater => Some(H::Greater),
|
||||
Cf::NotEqual => Some(H::NotEqual),
|
||||
Cf::GreaterEqual => Some(H::GreaterEqual),
|
||||
Cf::Always => Some(H::Always),
|
||||
Cf::Never => H::Never,
|
||||
Cf::Less => H::Less,
|
||||
Cf::Equal => H::Equal,
|
||||
Cf::LessEqual => H::LessEqual,
|
||||
Cf::Greater => H::Greater,
|
||||
Cf::NotEqual => H::NotEqual,
|
||||
Cf::GreaterEqual => H::GreaterEqual,
|
||||
Cf::Always => H::Always,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
id, pipeline, resource, span, swap_chain,
|
||||
track::{BufferState, TextureState, TrackerSet},
|
||||
validation::{self, check_buffer_usage, check_texture_usage},
|
||||
FastHashMap, LifeGuard, MultiRefCount, PrivateFeatures, Stored, SubmissionIndex,
|
||||
FastHashMap, Label, LifeGuard, MultiRefCount, PrivateFeatures, Stored, SubmissionIndex,
|
||||
MAX_BIND_GROUPS,
|
||||
};
|
||||
|
||||
@ -30,8 +30,8 @@ use thiserror::Error;
|
||||
use wgt::{BufferAddress, BufferSize, InputStepMode, TextureDimension, TextureFormat};
|
||||
|
||||
use std::{
|
||||
borrow::Cow, collections::hash_map::Entry, ffi, iter, marker::PhantomData, mem, ops::Range,
|
||||
ptr, sync::atomic::Ordering,
|
||||
borrow::Cow, collections::hash_map::Entry, iter, marker::PhantomData, mem, ops::Range, ptr,
|
||||
sync::atomic::Ordering,
|
||||
};
|
||||
|
||||
mod life;
|
||||
@ -43,18 +43,6 @@ use smallvec::SmallVec;
|
||||
#[cfg(feature = "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_MIP_LEVELS: u32 = 16;
|
||||
pub const MAX_VERTEX_BUFFERS: usize = 16;
|
||||
@ -394,7 +382,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
fn create_buffer(
|
||||
&self,
|
||||
self_id: id::DeviceId,
|
||||
desc: &wgt::BufferDescriptor<Label>,
|
||||
desc: &resource::BufferDescriptor,
|
||||
memory_kind: gfx_memory::Kind,
|
||||
) -> Result<resource::Buffer<B>, resource::CreateBufferError> {
|
||||
debug_assert_eq!(self_id.backend(), B::VARIANT);
|
||||
@ -428,19 +416,14 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
};
|
||||
|
||||
let mut buffer = unsafe {
|
||||
self.raw
|
||||
.create_buffer(desc.size.max(1), usage)
|
||||
.map_err(|err| match err {
|
||||
hal::buffer::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory,
|
||||
_ => panic!("failed to create buffer: {}", err),
|
||||
})?
|
||||
};
|
||||
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 mut buffer = unsafe { self.raw.create_buffer(desc.size.max(1), usage) }.map_err(
|
||||
|err| match 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) };
|
||||
}
|
||||
|
||||
let requirements = unsafe { self.raw.get_buffer_requirements(&buffer) };
|
||||
@ -474,7 +457,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
fn create_texture(
|
||||
&self,
|
||||
self_id: id::DeviceId,
|
||||
desc: &wgt::TextureDescriptor<Label>,
|
||||
desc: &resource::TextureDescriptor,
|
||||
) -> Result<resource::Texture<B>, resource::CreateTextureError> {
|
||||
debug_assert_eq!(self_id.backend(), B::VARIANT);
|
||||
|
||||
@ -527,9 +510,8 @@ impl<B: GfxBackend> Device<B> {
|
||||
hal::image::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory,
|
||||
_ => panic!("failed to create texture: {}", err),
|
||||
})?;
|
||||
if !desc.label.is_null() {
|
||||
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
|
||||
self.raw.set_image_name(&mut image, &label);
|
||||
if let Some(ref label) = desc.label {
|
||||
self.raw.set_image_name(&mut image, label);
|
||||
}
|
||||
image
|
||||
};
|
||||
@ -638,10 +620,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
) -> Result<binding_model::BindGroupLayout<B>, binding_model::CreateBindGroupLayoutError> {
|
||||
// Validate the count parameter
|
||||
for binding in entry_map.values() {
|
||||
if let Some(count) = binding.count {
|
||||
if count == 0 {
|
||||
return Err(binding_model::CreateBindGroupLayoutError::ZeroCount);
|
||||
}
|
||||
if binding.count.is_some() {
|
||||
match binding.ty {
|
||||
wgt::BindingType::SampledTexture { .. } => {
|
||||
if !self
|
||||
@ -665,7 +644,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
ty: conv::map_binding_type(entry),
|
||||
count: entry
|
||||
.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),
|
||||
immutable_samplers: false, // TODO
|
||||
})
|
||||
@ -703,7 +682,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
desc_counts: raw_bindings.iter().cloned().collect(),
|
||||
dynamic_count: entry_map
|
||||
.values()
|
||||
.filter(|b| b.has_dynamic_offset())
|
||||
.filter(|b| b.ty.has_dynamic_offset())
|
||||
.count(),
|
||||
count_validator,
|
||||
entries: entry_map,
|
||||
@ -713,7 +692,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
fn create_pipeline_layout(
|
||||
&self,
|
||||
self_id: id::DeviceId,
|
||||
desc: &wgt::PipelineLayoutDescriptor<id::BindGroupLayoutId>,
|
||||
desc: &binding_model::PipelineLayoutDescriptor,
|
||||
bgl_guard: &Storage<binding_model::BindGroupLayout<B>, id::BindGroupLayoutId>,
|
||||
) -> Result<binding_model::PipelineLayout<B>, CreatePipelineLayoutError> {
|
||||
let bind_group_layouts_count = desc.bind_group_layouts.len();
|
||||
@ -790,12 +769,20 @@ impl<B: GfxBackend> Device<B> {
|
||||
.iter()
|
||||
.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 {
|
||||
raw: unsafe {
|
||||
self.raw
|
||||
.create_pipeline_layout(descriptor_set_layouts, push_constants)
|
||||
.or(Err(DeviceError::OutOfMemory))?
|
||||
},
|
||||
raw,
|
||||
device_id: Stored {
|
||||
value: id::Valid(self_id),
|
||||
ref_count: self.life_guard.add_ref(),
|
||||
@ -956,7 +943,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn device_create_buffer<B: GfxBackend>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
desc: &wgt::BufferDescriptor<Label>,
|
||||
desc: &resource::BufferDescriptor,
|
||||
id_in: Input<G, id::BufferId>,
|
||||
) -> Result<id::BufferId, resource::CreateBufferError> {
|
||||
span!(_guard, INFO, "Device::create_buffer");
|
||||
@ -1000,7 +987,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let mut stage = device.create_buffer(
|
||||
device_id,
|
||||
&wgt::BufferDescriptor {
|
||||
label: b"<init_buffer>\0".as_ptr() as *const _,
|
||||
label: Some(Cow::Borrowed("<init_buffer>")),
|
||||
size: desc.size,
|
||||
usage: wgt::BufferUsage::MAP_WRITE | wgt::BufferUsage::COPY_SRC,
|
||||
mapped_at_creation: false,
|
||||
@ -1025,7 +1012,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
#[cfg(feature = "trace")]
|
||||
match device.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);
|
||||
if mapped_at_creation && !desc.usage.contains(wgt::BufferUsage::MAP_WRITE) {
|
||||
desc.usage |= wgt::BufferUsage::COPY_DST;
|
||||
@ -1222,7 +1209,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn device_create_texture<B: GfxBackend>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
desc: &wgt::TextureDescriptor<Label>,
|
||||
desc: &resource::TextureDescriptor,
|
||||
id_in: Input<G, id::TextureId>,
|
||||
) -> Result<id::TextureId, resource::CreateTextureError> {
|
||||
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);
|
||||
#[cfg(feature = "trace")]
|
||||
match device.trace {
|
||||
Some(ref trace) => trace.lock().add(trace::Action::CreateTexture(
|
||||
id.0,
|
||||
desc.map_label(own_label),
|
||||
)),
|
||||
Some(ref trace) => trace
|
||||
.lock()
|
||||
.add(trace::Action::CreateTexture(id.0, desc.clone())),
|
||||
None => (),
|
||||
};
|
||||
|
||||
@ -1306,7 +1292,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn texture_create_view<B: GfxBackend>(
|
||||
&self,
|
||||
texture_id: id::TextureId,
|
||||
desc: Option<&wgt::TextureViewDescriptor<Label>>,
|
||||
desc: &resource::TextureViewDescriptor,
|
||||
id_in: Input<G, id::TextureViewId>,
|
||||
) -> Result<id::TextureViewId, resource::CreateTextureViewError> {
|
||||
span!(_guard, INFO, "Texture::create_view");
|
||||
@ -1321,62 +1307,57 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.map_err(|_| resource::CreateTextureViewError::InvalidTexture)?;
|
||||
let device = &device_guard[texture.device_id.value];
|
||||
|
||||
let (format, view_kind, range) = match desc {
|
||||
Some(desc) => {
|
||||
let kind = conv::map_texture_view_dimension(desc.dimension);
|
||||
let required_level_count =
|
||||
desc.base_mip_level + desc.level_count.map_or(1, |count| count.get());
|
||||
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;
|
||||
let layer_end = texture.full_range.layers.end;
|
||||
if required_level_count > level_end as u32 {
|
||||
return Err(resource::CreateTextureViewError::InvalidMipLevelCount {
|
||||
requested: required_level_count,
|
||||
total: level_end,
|
||||
});
|
||||
}
|
||||
if required_layer_count > layer_end as u32 {
|
||||
return Err(resource::CreateTextureViewError::InvalidArrayLayerCount {
|
||||
requested: required_layer_count,
|
||||
total: layer_end,
|
||||
});
|
||||
};
|
||||
let end_level = desc
|
||||
.level_count
|
||||
.map_or(level_end, |_| required_level_count as u8);
|
||||
let end_layer = desc
|
||||
.array_layer_count
|
||||
.map_or(layer_end, |_| required_layer_count as u16);
|
||||
let aspects = match desc.aspect {
|
||||
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 view_kind = match desc.dimension {
|
||||
Some(dim) => conv::map_texture_view_dimension(dim),
|
||||
None => 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,
|
||||
},
|
||||
};
|
||||
let required_level_count =
|
||||
desc.base_mip_level + desc.level_count.map_or(1, |count| count.get());
|
||||
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;
|
||||
let layer_end = texture.full_range.layers.end;
|
||||
if required_level_count > level_end as u32 {
|
||||
return Err(resource::CreateTextureViewError::InvalidMipLevelCount {
|
||||
requested: required_level_count,
|
||||
total: level_end,
|
||||
});
|
||||
}
|
||||
if required_layer_count > layer_end as u32 {
|
||||
return Err(resource::CreateTextureViewError::InvalidArrayLayerCount {
|
||||
requested: required_layer_count,
|
||||
total: layer_end,
|
||||
});
|
||||
};
|
||||
let end_level = desc
|
||||
.level_count
|
||||
.map_or(level_end, |_| required_level_count as u8);
|
||||
let end_layer = desc
|
||||
.array_layer_count
|
||||
.map_or(layer_end, |_| required_layer_count as u16);
|
||||
let aspects = match desc.aspect {
|
||||
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 {
|
||||
aspects,
|
||||
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 format = desc.format.unwrap_or(texture.format);
|
||||
let range = hal::image::SubresourceRange {
|
||||
aspects,
|
||||
levels: desc.base_mip_level as u8..end_level,
|
||||
layers: desc.base_array_layer as u16..end_layer,
|
||||
};
|
||||
|
||||
let raw = unsafe {
|
||||
@ -1414,7 +1395,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
Some(ref trace) => trace.lock().add(trace::Action::CreateTextureView {
|
||||
id: id.0,
|
||||
parent_id: texture_id,
|
||||
desc: desc.map(|d| d.map_label(own_label)),
|
||||
desc: desc.clone(),
|
||||
}),
|
||||
None => (),
|
||||
};
|
||||
@ -1482,7 +1463,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn device_create_sampler<B: GfxBackend>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
desc: &wgt::SamplerDescriptor<Label>,
|
||||
desc: &resource::SamplerDescriptor,
|
||||
id_in: Input<G, id::SamplerId>,
|
||||
) -> Result<id::SamplerId, resource::CreateSamplerError> {
|
||||
span!(_guard, INFO, "Device::create_sampler");
|
||||
@ -1495,6 +1476,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.map_err(|_| DeviceError::Invalid)?;
|
||||
|
||||
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);
|
||||
if !valid_clamp {
|
||||
return Err(resource::CreateSamplerError::InvalidClamp(clamp));
|
||||
@ -1513,13 +1495,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
mag_filter: conv::map_filter(desc.mag_filter),
|
||||
mip_filter: conv::map_filter(desc.mipmap_filter),
|
||||
wrap_mode: (
|
||||
conv::map_wrap(desc.address_mode_u),
|
||||
conv::map_wrap(desc.address_mode_v),
|
||||
conv::map_wrap(desc.address_mode_w),
|
||||
conv::map_wrap(desc.address_modes[0]),
|
||||
conv::map_wrap(desc.address_modes[1]),
|
||||
conv::map_wrap(desc.address_modes[2]),
|
||||
),
|
||||
lod_bias: hal::image::Lod(0.0),
|
||||
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),
|
||||
normalized: true,
|
||||
anisotropy_clamp: actual_clamp,
|
||||
@ -1549,10 +1531,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
let id = hub.samplers.register_identity(id_in, sampler, &mut token);
|
||||
#[cfg(feature = "trace")]
|
||||
match device.trace {
|
||||
Some(ref trace) => trace.lock().add(trace::Action::CreateSampler(
|
||||
id.0,
|
||||
desc.map_label(own_label),
|
||||
)),
|
||||
Some(ref trace) => trace
|
||||
.lock()
|
||||
.add(trace::Action::CreateSampler(id.0, desc.clone())),
|
||||
None => (),
|
||||
};
|
||||
|
||||
@ -1603,7 +1584,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn device_create_bind_group_layout<B: GfxBackend>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
desc: &wgt::BindGroupLayoutDescriptor,
|
||||
desc: &binding_model::BindGroupLayoutDescriptor,
|
||||
id_in: Input<G, id::BindGroupLayoutId>,
|
||||
) -> Result<id::BindGroupLayoutId, binding_model::CreateBindGroupLayoutError> {
|
||||
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>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
desc: &wgt::PipelineLayoutDescriptor<id::BindGroupLayoutId>,
|
||||
desc: &binding_model::PipelineLayoutDescriptor,
|
||||
id_in: Input<G, id::PipelineLayoutId>,
|
||||
) -> Result<id::PipelineLayoutId, CreatePipelineLayoutError> {
|
||||
span!(_guard, INFO, "Device::create_pipeline_layout");
|
||||
@ -1810,7 +1791,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
Some(dedup_id) => dedup_id,
|
||||
None => {
|
||||
#[cfg(feature = "trace")]
|
||||
let bgl_desc = wgt::BindGroupLayoutDescriptor {
|
||||
let bgl_desc = binding_model::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: if device.trace.is_some() {
|
||||
Cow::Owned(map.values().cloned().collect())
|
||||
@ -1837,7 +1818,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
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),
|
||||
push_constant_ranges: Cow::Borrowed(&[]), //TODO?
|
||||
};
|
||||
@ -2113,7 +2095,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}
|
||||
|
||||
if let Some(count) = decl.count {
|
||||
let count = count as usize;
|
||||
let count = count.get() as usize;
|
||||
let num_bindings = bindings_array.len();
|
||||
if count != num_bindings {
|
||||
return Err(CreateBindGroupError::BindingArrayLengthMismatch {
|
||||
@ -2433,11 +2415,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
|
||||
unsafe {
|
||||
let raw_command_buffer = command_buffer.raw.last_mut().unwrap();
|
||||
if !desc.label.is_null() {
|
||||
let label = ffi::CStr::from_ptr(desc.label).to_string_lossy();
|
||||
if let Some(ref label) = desc.label {
|
||||
device
|
||||
.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);
|
||||
}
|
||||
@ -2491,7 +2472,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
pub fn device_create_render_bundle_encoder(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
desc: &wgt::RenderBundleEncoderDescriptor,
|
||||
desc: &command::RenderBundleEncoderDescriptor,
|
||||
) -> Result<id::RenderBundleEncoderId, command::CreateRenderBundleError> {
|
||||
span!(_guard, INFO, "Device::create_render_bundle_encoder");
|
||||
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 ds.needs_stencil_reference() {
|
||||
if ds.stencil.as_ref().map_or(false, |s| s.needs_ref_value()) {
|
||||
flags |= pipeline::PipelineFlags::STENCIL_REFERENCE;
|
||||
}
|
||||
if !ds.is_read_only() {
|
||||
@ -2966,7 +2947,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
match device.trace {
|
||||
Some(ref trace) => trace.lock().add(trace::Action::CreateRenderPipeline(
|
||||
id.0,
|
||||
wgt::RenderPipelineDescriptor {
|
||||
pipeline::RenderPipelineDescriptor {
|
||||
layout: Some(layout_id),
|
||||
..desc.clone()
|
||||
},
|
||||
@ -3185,7 +3166,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
match device.trace {
|
||||
Some(ref trace) => trace.lock().add(trace::Action::CreateComputePipeline(
|
||||
id.0,
|
||||
wgt::ComputePipelineDescriptor {
|
||||
pipeline::ComputePipelineDescriptor {
|
||||
layout: Some(layout_id),
|
||||
..desc.clone()
|
||||
},
|
||||
|
@ -5,7 +5,7 @@
|
||||
use crate::id;
|
||||
#[cfg(feature = "trace")]
|
||||
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
|
||||
|
||||
@ -14,13 +14,13 @@ type FileName = String;
|
||||
pub const FILE_NAME: &str = "trace.ron";
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
pub(crate) fn new_render_bundle_encoder_descriptor(
|
||||
label: super::Label,
|
||||
context: &super::RenderPassContext,
|
||||
) -> wgt::RenderBundleEncoderDescriptor {
|
||||
wgt::RenderBundleEncoderDescriptor {
|
||||
label: Some(super::own_label(&label).into()),
|
||||
color_formats: context.attachments.colors.to_vec().into(),
|
||||
pub(crate) fn new_render_bundle_encoder_descriptor<'a>(
|
||||
label: Option<&'a str>,
|
||||
context: &'a super::RenderPassContext,
|
||||
) -> crate::command::RenderBundleEncoderDescriptor<'a> {
|
||||
crate::command::RenderBundleEncoderDescriptor {
|
||||
label: label.map(Cow::Borrowed),
|
||||
color_formats: Cow::Borrowed(&context.attachments.colors),
|
||||
depth_stencil_format: context.attachments.depth_stencil,
|
||||
sample_count: context.sample_count as u32,
|
||||
}
|
||||
@ -34,17 +34,17 @@ pub enum Action<'a> {
|
||||
desc: wgt::DeviceDescriptor,
|
||||
backend: wgt::Backend,
|
||||
},
|
||||
CreateBuffer(id::BufferId, wgt::BufferDescriptor<String>),
|
||||
CreateBuffer(id::BufferId, crate::resource::BufferDescriptor<'a>),
|
||||
DestroyBuffer(id::BufferId),
|
||||
CreateTexture(id::TextureId, wgt::TextureDescriptor<String>),
|
||||
CreateTexture(id::TextureId, crate::resource::TextureDescriptor<'a>),
|
||||
DestroyTexture(id::TextureId),
|
||||
CreateTextureView {
|
||||
id: id::TextureViewId,
|
||||
parent_id: id::TextureId,
|
||||
desc: Option<wgt::TextureViewDescriptor<String>>,
|
||||
desc: crate::resource::TextureViewDescriptor<'a>,
|
||||
},
|
||||
DestroyTextureView(id::TextureViewId),
|
||||
CreateSampler(id::SamplerId, wgt::SamplerDescriptor<String>),
|
||||
CreateSampler(id::SamplerId, crate::resource::SamplerDescriptor<'a>),
|
||||
DestroySampler(id::SamplerId),
|
||||
CreateSwapChain(id::SwapChainId, wgt::SwapChainDescriptor),
|
||||
GetSwapChainTexture {
|
||||
@ -52,20 +52,19 @@ pub enum Action<'a> {
|
||||
parent_id: id::SwapChainId,
|
||||
},
|
||||
PresentSwapChain(id::SwapChainId),
|
||||
CreateBindGroupLayout(id::BindGroupLayoutId, wgt::BindGroupLayoutDescriptor<'a>),
|
||||
CreateBindGroupLayout(
|
||||
id::BindGroupLayoutId,
|
||||
crate::binding_model::BindGroupLayoutDescriptor<'a>,
|
||||
),
|
||||
DestroyBindGroupLayout(id::BindGroupLayoutId),
|
||||
CreatePipelineLayout(
|
||||
id::PipelineLayoutId,
|
||||
wgt::PipelineLayoutDescriptor<'a, id::BindGroupLayoutId>,
|
||||
crate::binding_model::PipelineLayoutDescriptor<'a>,
|
||||
),
|
||||
DestroyPipelineLayout(id::PipelineLayoutId),
|
||||
CreateBindGroup(
|
||||
id::BindGroupId,
|
||||
wgt::BindGroupDescriptor<
|
||||
'a,
|
||||
id::BindGroupLayoutId,
|
||||
wgt::BindGroupEntry<crate::binding_model::BindingResource<'a>>,
|
||||
>,
|
||||
crate::binding_model::BindGroupDescriptor<'a>,
|
||||
),
|
||||
DestroyBindGroup(id::BindGroupId),
|
||||
CreateShaderModule {
|
||||
@ -75,24 +74,17 @@ pub enum Action<'a> {
|
||||
DestroyShaderModule(id::ShaderModuleId),
|
||||
CreateComputePipeline(
|
||||
id::ComputePipelineId,
|
||||
wgt::ComputePipelineDescriptor<
|
||||
id::PipelineLayoutId,
|
||||
wgt::ProgrammableStageDescriptor<'a, id::ShaderModuleId>,
|
||||
>,
|
||||
crate::pipeline::ComputePipelineDescriptor<'a>,
|
||||
),
|
||||
DestroyComputePipeline(id::ComputePipelineId),
|
||||
CreateRenderPipeline(
|
||||
id::RenderPipelineId,
|
||||
wgt::RenderPipelineDescriptor<
|
||||
'a,
|
||||
id::PipelineLayoutId,
|
||||
wgt::ProgrammableStageDescriptor<'a, id::ShaderModuleId>,
|
||||
>,
|
||||
crate::pipeline::RenderPipelineDescriptor<'a>,
|
||||
),
|
||||
DestroyRenderPipeline(id::RenderPipelineId),
|
||||
CreateRenderBundle {
|
||||
id: id::RenderBundleId,
|
||||
desc: wgt::RenderBundleEncoderDescriptor<'a>,
|
||||
desc: crate::command::RenderBundleEncoderDescriptor<'a>,
|
||||
base: crate::command::BasePass<crate::command::RenderCommand>,
|
||||
},
|
||||
DestroyRenderBundle(id::RenderBundleId),
|
||||
|
@ -49,7 +49,7 @@ use std::sync::atomic;
|
||||
|
||||
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;
|
||||
|
||||
@ -58,6 +58,7 @@ type Index = u32;
|
||||
type Epoch = u32;
|
||||
|
||||
pub type RawString = *const c_char;
|
||||
pub type Label<'a> = Option<Cow<'a, str>>;
|
||||
|
||||
/// Reference count object that is 1:1 with each reference.
|
||||
#[derive(Debug)]
|
||||
|
@ -36,7 +36,17 @@ pub enum CreateShaderModuleError {
|
||||
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.
|
||||
pub type ImplicitBindGroupCount = u8;
|
||||
@ -53,8 +63,16 @@ pub enum ImplicitLayoutError {
|
||||
Pipeline(#[from] CreatePipelineLayoutError),
|
||||
}
|
||||
|
||||
pub type ComputePipelineDescriptor<'a> =
|
||||
wgt::ComputePipelineDescriptor<PipelineLayoutId, ProgrammableStageDescriptor<'a>>;
|
||||
/// Describes a compute pipeline.
|
||||
#[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)]
|
||||
pub enum CreateComputePipelineError {
|
||||
@ -82,8 +100,65 @@ impl<B: hal::Backend> Borrow<RefCount> for ComputePipeline<B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub type RenderPipelineDescriptor<'a> =
|
||||
wgt::RenderPipelineDescriptor<'a, PipelineLayoutId, ProgrammableStageDescriptor<'a>>;
|
||||
/// Describes how the vertex buffer is interpreted.
|
||||
#[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)]
|
||||
pub enum CreateRenderPipelineError {
|
||||
|
@ -7,14 +7,17 @@ use crate::{
|
||||
id::{DeviceId, SwapChainId, TextureId},
|
||||
track::DUMMY_SELECTOR,
|
||||
validation::MissingBufferUsageError,
|
||||
LifeGuard, RefCount, Stored,
|
||||
Label, LifeGuard, RefCount, Stored,
|
||||
};
|
||||
|
||||
use gfx_memory::MemoryBlock;
|
||||
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! {
|
||||
/// 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 type BufferDescriptor<'a> = wgt::BufferDescriptor<Label<'a>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Buffer<B: hal::Backend> {
|
||||
pub(crate) raw: B::Buffer,
|
||||
pub(crate) device_id: Stored<DeviceId>,
|
||||
pub(crate) usage: BufferUsage,
|
||||
pub(crate) usage: wgt::BufferUsage,
|
||||
pub(crate) memory: MemoryBlock<B>,
|
||||
pub(crate) size: BufferAddress,
|
||||
pub(crate) size: wgt::BufferAddress,
|
||||
pub(crate) full_range: (),
|
||||
pub(crate) sync_mapped_writes: Option<hal::memory::Segment>,
|
||||
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`")]
|
||||
UnalignedSize,
|
||||
#[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> {
|
||||
@ -192,14 +197,16 @@ impl<B: hal::Backend> Borrow<()> for Buffer<B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Texture<B: hal::Backend> {
|
||||
pub(crate) raw: B::Image,
|
||||
pub(crate) device_id: Stored<DeviceId>,
|
||||
pub(crate) usage: TextureUsage,
|
||||
pub(crate) usage: wgt::TextureUsage,
|
||||
pub(crate) dimension: wgt::TextureDimension,
|
||||
pub(crate) kind: hal::image::Kind,
|
||||
pub(crate) format: TextureFormat,
|
||||
pub(crate) format: wgt::TextureFormat,
|
||||
pub(crate) full_range: hal::image::SubresourceRange,
|
||||
pub(crate) memory: MemoryBlock<B>,
|
||||
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`")]
|
||||
InvalidMipLevelCount(u32),
|
||||
#[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> {
|
||||
@ -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)]
|
||||
pub(crate) enum TextureViewInner<B: hal::Backend> {
|
||||
Native {
|
||||
@ -257,7 +293,7 @@ pub(crate) enum TextureViewInner<B: hal::Backend> {
|
||||
pub struct TextureView<B: hal::Backend> {
|
||||
pub(crate) inner: TextureViewInner<B>,
|
||||
//TODO: store device_id for quick access?
|
||||
pub(crate) format: TextureFormat,
|
||||
pub(crate) format: wgt::TextureFormat,
|
||||
pub(crate) extent: hal::image::Extent,
|
||||
pub(crate) samples: hal::image::NumSamples,
|
||||
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)]
|
||||
pub struct Sampler<B: hal::Backend> {
|
||||
pub(crate) raw: B::Sampler,
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user