mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +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 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();
|
||||||
|
@ -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,
|
||||||
|
@ -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})")]
|
||||||
|
@ -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()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
},
|
},
|
||||||
|
@ -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),
|
||||||
|
@ -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)]
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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