mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 23:04:07 +00:00
Merge #1176
1176: Rewrite RenderPipelineDescriptor according to aspects r=grovesNL,cwfitzgerald a=kvark **Connections** Fixes #1166 **Description** Totally re-imagines the structure tree for describing the rendering pipeline, based on the aspects instead of logical steps. **Testing** Just local testing. I don't think there is any concern that these changes might not work, they just need the clients to adapt. Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
commit
63b0d36074
21
CHANGELOG.md
21
CHANGELOG.md
@ -1,5 +1,26 @@
|
||||
# Change Log
|
||||
|
||||
## v0.7 (TBD)
|
||||
- Major API changes:
|
||||
- `RenderPipelineDescriptor`
|
||||
- `BindingType`
|
||||
- Features:
|
||||
- (beta) WGSL support, including the ability to bypass SPIR-V entirely
|
||||
- (beta) implicit bind group layout support
|
||||
- timestamp and pipeline statistics queries
|
||||
- ETC2 and ASTC compressed textures
|
||||
- (beta) targeting WASM with WebGL backend
|
||||
- reduced dependencies
|
||||
- Native-only:
|
||||
- clamp-to-border addressing
|
||||
- polygon fill modes
|
||||
- query a format for extra capabilities
|
||||
- `f64` support in shaders
|
||||
- Validation:
|
||||
- shader interface
|
||||
- render pipeline descriptor
|
||||
- vertex buffers
|
||||
|
||||
## v0.6 (2020-08-17)
|
||||
- Crates:
|
||||
- C API is moved to [another repository](https://github.com/gfx-rs/wgpu-native)
|
||||
|
@ -18,7 +18,7 @@
|
||||
CreateComputePipeline(Id(0, 1, Empty), (
|
||||
label: None,
|
||||
layout: Some(Id(0, 1, Empty)),
|
||||
compute_stage: (
|
||||
stage: (
|
||||
module: Id(0, 1, Empty),
|
||||
entry_point: "main",
|
||||
),
|
||||
|
@ -56,42 +56,24 @@
|
||||
CreateRenderPipeline(Id(0, 1, Empty), (
|
||||
label: None,
|
||||
layout: Some(Id(0, 1, Empty)),
|
||||
vertex_stage: (
|
||||
module: Id(0, 1, Empty),
|
||||
entry_point: "vs_main",
|
||||
),
|
||||
fragment_stage: Some((
|
||||
module: Id(0, 1, Empty),
|
||||
entry_point: "fs_main",
|
||||
)),
|
||||
rasterization_state: None,
|
||||
primitive_topology: TriangleList,
|
||||
color_states: [
|
||||
(
|
||||
format: Rgba8Unorm,
|
||||
alpha_blend: (
|
||||
src_factor: One,
|
||||
dst_factor: Zero,
|
||||
operation: Add,
|
||||
),
|
||||
color_blend: (
|
||||
src_factor: One,
|
||||
dst_factor: Zero,
|
||||
operation: Add,
|
||||
),
|
||||
write_mask: (
|
||||
bits: 15,
|
||||
),
|
||||
vertex: (
|
||||
stage: (
|
||||
module: Id(0, 1, Empty),
|
||||
entry_point: "vs_main",
|
||||
),
|
||||
],
|
||||
depth_stencil_state: None,
|
||||
vertex_state: (
|
||||
index_format: None,
|
||||
vertex_buffers: [],
|
||||
buffers: [],
|
||||
),
|
||||
sample_count: 1,
|
||||
sample_mask: 4294967295,
|
||||
alpha_to_coverage_enabled: false,
|
||||
fragment: Some((
|
||||
stage: (
|
||||
module: Id(0, 1, Empty),
|
||||
entry_point: "fs_main",
|
||||
),
|
||||
targets: [
|
||||
(
|
||||
format: Rgba8Unorm,
|
||||
),
|
||||
],
|
||||
)),
|
||||
)),
|
||||
Submit(1, [
|
||||
RunRenderPass(
|
||||
|
@ -233,7 +233,7 @@ impl RenderBundleEncoder {
|
||||
pipeline_layout_id = Some(pipeline.layout_id.value);
|
||||
|
||||
state.set_pipeline(
|
||||
pipeline.index_format,
|
||||
pipeline.strip_index_format,
|
||||
&pipeline.vertex_strides,
|
||||
&layout.bind_group_layout_ids,
|
||||
&layout.push_constant_ranges,
|
||||
|
@ -1248,7 +1248,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
}
|
||||
}
|
||||
|
||||
state.index.pipeline_format = pipeline.index_format;
|
||||
state.index.pipeline_format = pipeline.strip_index_format;
|
||||
|
||||
let vertex_strides_len = pipeline.vertex_strides.len();
|
||||
state.vertex.buffers_required = vertex_strides_len as u32;
|
||||
|
@ -177,14 +177,14 @@ pub fn map_primitive_topology(primitive_topology: wgt::PrimitiveTopology) -> hal
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_color_state_descriptor(desc: &wgt::ColorStateDescriptor) -> hal::pso::ColorBlendDesc {
|
||||
pub fn map_color_target_state(desc: &wgt::ColorTargetState) -> hal::pso::ColorBlendDesc {
|
||||
let color_mask = desc.write_mask;
|
||||
let blend_state = if desc.color_blend != wgt::BlendDescriptor::REPLACE
|
||||
|| desc.alpha_blend != wgt::BlendDescriptor::REPLACE
|
||||
let blend_state = if desc.color_blend != wgt::BlendState::REPLACE
|
||||
|| desc.alpha_blend != wgt::BlendState::REPLACE
|
||||
{
|
||||
Some(hal::pso::BlendState {
|
||||
color: map_blend_descriptor(&desc.color_blend),
|
||||
alpha: map_blend_descriptor(&desc.alpha_blend),
|
||||
color: map_blend_state(&desc.color_blend),
|
||||
alpha: map_blend_state(&desc.alpha_blend),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@ -215,7 +215,7 @@ fn map_color_write_flags(flags: wgt::ColorWrite) -> hal::pso::ColorMask {
|
||||
value
|
||||
}
|
||||
|
||||
fn map_blend_descriptor(blend_desc: &wgt::BlendDescriptor) -> hal::pso::BlendOp {
|
||||
fn map_blend_state(blend_desc: &wgt::BlendState) -> hal::pso::BlendOp {
|
||||
use hal::pso::BlendOp as H;
|
||||
use wgt::BlendOperation as Bo;
|
||||
match blend_desc.operation {
|
||||
@ -256,9 +256,7 @@ fn map_blend_factor(blend_factor: wgt::BlendFactor) -> hal::pso::Factor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_depth_stencil_state_descriptor(
|
||||
desc: &wgt::DepthStencilStateDescriptor,
|
||||
) -> hal::pso::DepthStencilDesc {
|
||||
pub fn map_depth_stencil_state(desc: &wgt::DepthStencilState) -> hal::pso::DepthStencilDesc {
|
||||
hal::pso::DepthStencilDesc {
|
||||
depth: if desc.is_depth_enabled() {
|
||||
Some(hal::pso::DepthTest {
|
||||
@ -290,9 +288,7 @@ pub fn map_depth_stencil_state_descriptor(
|
||||
}
|
||||
}
|
||||
|
||||
fn map_stencil_face(
|
||||
stencil_state_face_desc: &wgt::StencilStateFaceDescriptor,
|
||||
) -> hal::pso::StencilFace {
|
||||
fn map_stencil_face(stencil_state_face_desc: &wgt::StencilStateFace) -> hal::pso::StencilFace {
|
||||
hal::pso::StencilFace {
|
||||
fun: map_compare_function(stencil_state_face_desc.compare),
|
||||
op_fail: map_stencil_operation(stencil_state_face_desc.fail_op),
|
||||
@ -774,12 +770,38 @@ pub fn map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_rasterization_state_descriptor(
|
||||
desc: &wgt::RasterizationStateDescriptor,
|
||||
pub fn map_primitive_state_to_input_assembler(
|
||||
desc: &wgt::PrimitiveState,
|
||||
) -> hal::pso::InputAssemblerDesc {
|
||||
hal::pso::InputAssemblerDesc {
|
||||
primitive: map_primitive_topology(desc.topology),
|
||||
with_adjacency: false,
|
||||
restart_index: desc.strip_index_format.map(map_index_format),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_primitive_state_to_rasterizer(
|
||||
desc: &wgt::PrimitiveState,
|
||||
depth_stencil: Option<&wgt::DepthStencilState>,
|
||||
) -> hal::pso::Rasterizer {
|
||||
use hal::pso;
|
||||
let (depth_clamping, depth_bias) = match depth_stencil {
|
||||
Some(dsd) => {
|
||||
let bias = if dsd.has_depth_bias() {
|
||||
Some(pso::State::Static(pso::DepthBias {
|
||||
const_factor: dsd.depth_bias as f32,
|
||||
slope_factor: dsd.depth_bias_slope_scale,
|
||||
clamp: dsd.depth_bias_clamp,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
(dsd.clamp_depth, bias)
|
||||
}
|
||||
None => (false, None),
|
||||
};
|
||||
pso::Rasterizer {
|
||||
depth_clamping: desc.clamp_depth,
|
||||
depth_clamping,
|
||||
polygon_mode: match desc.polygon_mode {
|
||||
wgt::PolygonMode::Fill => pso::PolygonMode::Fill,
|
||||
wgt::PolygonMode::Line => pso::PolygonMode::Line,
|
||||
@ -794,23 +816,22 @@ pub fn map_rasterization_state_descriptor(
|
||||
wgt::FrontFace::Ccw => pso::FrontFace::CounterClockwise,
|
||||
wgt::FrontFace::Cw => pso::FrontFace::Clockwise,
|
||||
},
|
||||
depth_bias: if desc.depth_bias != 0
|
||||
|| desc.depth_bias_slope_scale != 0.0
|
||||
|| desc.depth_bias_clamp != 0.0
|
||||
{
|
||||
Some(pso::State::Static(pso::DepthBias {
|
||||
const_factor: desc.depth_bias as f32,
|
||||
slope_factor: desc.depth_bias_slope_scale,
|
||||
clamp: desc.depth_bias_clamp,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
depth_bias,
|
||||
conservative: false,
|
||||
line_width: pso::State::Static(1.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_multisample_state(desc: &wgt::MultisampleState) -> hal::pso::Multisampling {
|
||||
hal::pso::Multisampling {
|
||||
rasterization_samples: desc.count as _,
|
||||
sample_shading: None,
|
||||
sample_mask: desc.mask,
|
||||
alpha_coverage: desc.alpha_to_coverage_enabled,
|
||||
alpha_to_one: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_index_format(index_format: wgt::IndexFormat) -> hal::IndexType {
|
||||
match index_format {
|
||||
wgt::IndexFormat::Uint16 => hal::IndexType::U16,
|
||||
|
@ -1778,15 +1778,12 @@ impl<B: GfxBackend> Device<B> {
|
||||
ArrayVec::<[binding_model::BindEntryMap; MAX_BIND_GROUPS]>::new();
|
||||
|
||||
let io = validation::StageIo::default();
|
||||
let pipeline_stage = &desc.compute_stage;
|
||||
let (shader_module_guard, _) = hub.shader_modules.read(&mut token);
|
||||
|
||||
let entry_point_name = &pipeline_stage.entry_point;
|
||||
let shader_module = shader_module_guard
|
||||
.get(pipeline_stage.module)
|
||||
.map_err(|_| {
|
||||
pipeline::CreateComputePipelineError::Stage(validation::StageError::InvalidModule)
|
||||
})?;
|
||||
let entry_point_name = &desc.stage.entry_point;
|
||||
let shader_module = shader_module_guard.get(desc.stage.module).map_err(|_| {
|
||||
pipeline::CreateComputePipelineError::Stage(validation::StageError::InvalidModule)
|
||||
})?;
|
||||
|
||||
let flag = wgt::ShaderStage::COMPUTE;
|
||||
if let Some(ref interface) = shader_module.interface {
|
||||
@ -1898,47 +1895,37 @@ impl<B: GfxBackend> Device<B> {
|
||||
let mut derived_group_layouts =
|
||||
ArrayVec::<[binding_model::BindEntryMap; MAX_BIND_GROUPS]>::new();
|
||||
|
||||
let samples = {
|
||||
let sc = desc.sample_count;
|
||||
if sc == 0 || sc > 32 || !conv::is_power_of_two(sc) {
|
||||
return Err(pipeline::CreateRenderPipelineError::InvalidSampleCount(sc));
|
||||
}
|
||||
sc as u8
|
||||
};
|
||||
|
||||
let color_states = &desc.color_states;
|
||||
let depth_stencil_state = desc.depth_stencil_state.as_ref();
|
||||
|
||||
let rasterization_state = desc
|
||||
.rasterization_state
|
||||
let color_states = desc
|
||||
.fragment
|
||||
.as_ref()
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
let rasterizer = conv::map_rasterization_state_descriptor(&rasterization_state);
|
||||
.map_or(&[][..], |fragment| &fragment.targets);
|
||||
let depth_stencil_state = desc.depth_stencil.as_ref();
|
||||
let rasterizer =
|
||||
conv::map_primitive_state_to_rasterizer(&desc.primitive, depth_stencil_state);
|
||||
|
||||
let mut io = validation::StageIo::default();
|
||||
let mut validated_stages = wgt::ShaderStage::empty();
|
||||
|
||||
let desc_vbs = &desc.vertex_state.vertex_buffers;
|
||||
let desc_vbs = &desc.vertex.buffers;
|
||||
let mut vertex_strides = Vec::with_capacity(desc_vbs.len());
|
||||
let mut vertex_buffers = Vec::with_capacity(desc_vbs.len());
|
||||
let mut attributes = Vec::new();
|
||||
for (i, vb_state) in desc_vbs.iter().enumerate() {
|
||||
vertex_strides
|
||||
.alloc()
|
||||
.init((vb_state.stride, vb_state.step_mode));
|
||||
.init((vb_state.array_stride, vb_state.step_mode));
|
||||
if vb_state.attributes.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if vb_state.stride % wgt::VERTEX_STRIDE_ALIGNMENT != 0 {
|
||||
if vb_state.array_stride % wgt::VERTEX_STRIDE_ALIGNMENT != 0 {
|
||||
return Err(pipeline::CreateRenderPipelineError::UnalignedVertexStride {
|
||||
index: i as u32,
|
||||
stride: vb_state.stride,
|
||||
stride: vb_state.array_stride,
|
||||
});
|
||||
}
|
||||
vertex_buffers.alloc().init(hal::pso::VertexBufferDesc {
|
||||
binding: i as u32,
|
||||
stride: vb_state.stride as u32,
|
||||
stride: vb_state.array_stride as u32,
|
||||
rate: match vb_state.step_mode {
|
||||
InputStepMode::Vertex => hal::pso::VertexInputRate::Vertex,
|
||||
InputStepMode::Instance => hal::pso::VertexInputRate::Instance(1),
|
||||
@ -1985,33 +1972,25 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
}
|
||||
|
||||
let input_assembler = hal::pso::InputAssemblerDesc {
|
||||
primitive: conv::map_primitive_topology(desc.primitive_topology),
|
||||
with_adjacency: false,
|
||||
restart_index: None, //TODO
|
||||
};
|
||||
let input_assembler = conv::map_primitive_state_to_input_assembler(&desc.primitive);
|
||||
|
||||
let blender = hal::pso::BlendDesc {
|
||||
logic_op: None, // TODO
|
||||
targets: color_states
|
||||
.iter()
|
||||
.map(conv::map_color_state_descriptor)
|
||||
.map(conv::map_color_target_state)
|
||||
.collect(),
|
||||
};
|
||||
let depth_stencil = depth_stencil_state
|
||||
.map(conv::map_depth_stencil_state_descriptor)
|
||||
.unwrap_or_default();
|
||||
|
||||
let multisampling: Option<hal::pso::Multisampling> = if samples == 1 {
|
||||
None
|
||||
} else {
|
||||
Some(hal::pso::Multisampling {
|
||||
rasterization_samples: samples,
|
||||
sample_shading: None,
|
||||
sample_mask: desc.sample_mask as u64,
|
||||
alpha_coverage: desc.alpha_to_coverage_enabled,
|
||||
alpha_to_one: false,
|
||||
})
|
||||
let depth_stencil = match depth_stencil_state {
|
||||
Some(dsd) => {
|
||||
if dsd.clamp_depth && !self.features.contains(wgt::Features::DEPTH_CLAMPING) {
|
||||
return Err(pipeline::CreateRenderPipelineError::MissingFeature(
|
||||
wgt::Features::DEPTH_CLAMPING,
|
||||
));
|
||||
}
|
||||
conv::map_depth_stencil_state(dsd)
|
||||
}
|
||||
None => hal::pso::DepthStencilDesc::default(),
|
||||
};
|
||||
|
||||
// TODO
|
||||
@ -2022,13 +2001,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
depth_bounds: None,
|
||||
};
|
||||
|
||||
if rasterization_state.clamp_depth && !self.features.contains(wgt::Features::DEPTH_CLAMPING)
|
||||
{
|
||||
return Err(pipeline::CreateRenderPipelineError::MissingFeature(
|
||||
wgt::Features::DEPTH_CLAMPING,
|
||||
));
|
||||
}
|
||||
if rasterization_state.polygon_mode != wgt::PolygonMode::Fill
|
||||
if desc.primitive.polygon_mode != wgt::PolygonMode::Fill
|
||||
&& !self.features.contains(wgt::Features::NON_FILL_POLYGON_MODE)
|
||||
{
|
||||
return Err(pipeline::CreateRenderPipelineError::MissingFeature(
|
||||
@ -2042,7 +2015,18 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
}
|
||||
|
||||
let (shader_module_guard, _) = hub.shader_modules.read(&mut token);
|
||||
let samples = {
|
||||
let sc = desc.multisample.count;
|
||||
if sc == 0 || sc > 32 || !conv::is_power_of_two(sc) {
|
||||
return Err(pipeline::CreateRenderPipelineError::InvalidSampleCount(sc));
|
||||
}
|
||||
sc as u8
|
||||
};
|
||||
let multisampling = if samples == 1 {
|
||||
None
|
||||
} else {
|
||||
Some(conv::map_multisample_state(&desc.multisample))
|
||||
};
|
||||
|
||||
let rp_key = RenderPassKey {
|
||||
colors: color_states
|
||||
@ -2081,17 +2065,18 @@ impl<B: GfxBackend> Device<B> {
|
||||
}),
|
||||
};
|
||||
|
||||
let (shader_module_guard, _) = hub.shader_modules.read(&mut token);
|
||||
|
||||
let vertex = {
|
||||
let entry_point_name = &desc.vertex_stage.entry_point;
|
||||
let stage = &desc.vertex.stage;
|
||||
let flag = wgt::ShaderStage::VERTEX;
|
||||
|
||||
let shader_module =
|
||||
shader_module_guard
|
||||
.get(desc.vertex_stage.module)
|
||||
.map_err(|_| pipeline::CreateRenderPipelineError::Stage {
|
||||
flag,
|
||||
error: validation::StageError::InvalidModule,
|
||||
})?;
|
||||
let shader_module = shader_module_guard.get(stage.module).map_err(|_| {
|
||||
pipeline::CreateRenderPipelineError::Stage {
|
||||
flag,
|
||||
error: validation::StageError::InvalidModule,
|
||||
}
|
||||
})?;
|
||||
|
||||
if let Some(ref interface) = shader_module.interface {
|
||||
let provided_layouts = match desc.layout {
|
||||
@ -2108,7 +2093,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
.check_stage(
|
||||
provided_layouts.as_ref().map(|p| p.as_slice()),
|
||||
&mut derived_group_layouts,
|
||||
&entry_point_name,
|
||||
&stage.entry_point,
|
||||
flag,
|
||||
io,
|
||||
)
|
||||
@ -2117,23 +2102,24 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
|
||||
hal::pso::EntryPoint::<B> {
|
||||
entry: &entry_point_name, // TODO
|
||||
entry: &stage.entry_point,
|
||||
module: &shader_module.raw,
|
||||
specialization: hal::pso::Specialization::EMPTY,
|
||||
}
|
||||
};
|
||||
|
||||
let fragment = match &desc.fragment_stage {
|
||||
Some(stage) => {
|
||||
let entry_point_name = &stage.entry_point;
|
||||
let fragment = match &desc.fragment {
|
||||
Some(fragment) => {
|
||||
let entry_point_name = &fragment.stage.entry_point;
|
||||
let flag = wgt::ShaderStage::FRAGMENT;
|
||||
|
||||
let shader_module = shader_module_guard.get(stage.module).map_err(|_| {
|
||||
pipeline::CreateRenderPipelineError::Stage {
|
||||
flag,
|
||||
error: validation::StageError::InvalidModule,
|
||||
}
|
||||
})?;
|
||||
let shader_module =
|
||||
shader_module_guard
|
||||
.get(fragment.stage.module)
|
||||
.map_err(|_| pipeline::CreateRenderPipelineError::Stage {
|
||||
flag,
|
||||
error: validation::StageError::InvalidModule,
|
||||
})?;
|
||||
|
||||
let provided_layouts = match desc.layout {
|
||||
Some(pipeline_layout_id) => Some(Device::get_introspection_bind_group_layouts(
|
||||
@ -2199,7 +2185,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
}
|
||||
}
|
||||
let last_stage = match desc.fragment_stage {
|
||||
let last_stage = match desc.fragment {
|
||||
Some(_) => wgt::ShaderStage::FRAGMENT,
|
||||
None => wgt::ShaderStage::VERTEX,
|
||||
};
|
||||
@ -2310,7 +2296,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
},
|
||||
pass_context,
|
||||
flags,
|
||||
index_format: desc.vertex_state.index_format,
|
||||
strip_index_format: desc.primitive.strip_index_format,
|
||||
vertex_strides,
|
||||
life_guard: LifeGuard::new(desc.label.borrow_or_default()),
|
||||
};
|
||||
|
@ -11,7 +11,6 @@ use crate::{
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use thiserror::Error;
|
||||
use wgt::{BufferAddress, IndexFormat, InputStepMode};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ShaderModuleSource<'a> {
|
||||
@ -99,7 +98,7 @@ 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>,
|
||||
pub stage: ProgrammableStageDescriptor<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
@ -134,24 +133,35 @@ impl<B: hal::Backend> Resource for ComputePipeline<B> {
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
||||
pub struct VertexBufferDescriptor<'a> {
|
||||
pub struct VertexBufferLayout<'a> {
|
||||
/// The stride, in bytes, between elements of this buffer.
|
||||
pub stride: BufferAddress,
|
||||
pub array_stride: wgt::BufferAddress,
|
||||
/// How often this vertex buffer is "stepped" forward.
|
||||
pub step_mode: InputStepMode,
|
||||
pub step_mode: wgt::InputStepMode,
|
||||
/// The list of attributes which comprise a single vertex.
|
||||
pub attributes: Cow<'a, [wgt::VertexAttributeDescriptor]>,
|
||||
pub attributes: Cow<'a, [wgt::VertexAttribute]>,
|
||||
}
|
||||
|
||||
/// Describes vertex input state for a render pipeline.
|
||||
/// Describes the vertex process in 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: Option<IndexFormat>,
|
||||
pub struct VertexState<'a> {
|
||||
/// The compiled vertex stage and its entry point.
|
||||
pub stage: ProgrammableStageDescriptor<'a>,
|
||||
/// The format of any vertex buffers used with this pipeline.
|
||||
pub vertex_buffers: Cow<'a, [VertexBufferDescriptor<'a>]>,
|
||||
pub buffers: Cow<'a, [VertexBufferLayout<'a>]>,
|
||||
}
|
||||
|
||||
/// Describes fragment processing in a render pipeline.
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
||||
pub struct FragmentState<'a> {
|
||||
/// The compiled fragment stage and its entry point.
|
||||
pub stage: ProgrammableStageDescriptor<'a>,
|
||||
/// The effect of draw calls on the color aspect of the output target.
|
||||
pub targets: Cow<'a, [wgt::ColorTargetState]>,
|
||||
}
|
||||
|
||||
/// Describes a render (graphics) pipeline.
|
||||
@ -162,33 +172,19 @@ pub struct RenderPipelineDescriptor<'a> {
|
||||
pub label: Label<'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 vertex processing state for this pipeline.
|
||||
pub vertex: VertexState<'a>,
|
||||
/// The properties of the pipeline at the primitive assembly and rasterization level.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
pub primitive: wgt::PrimitiveState,
|
||||
/// 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,
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
pub depth_stencil: Option<wgt::DepthStencilState>,
|
||||
/// The multi-sampling properties of the pipeline.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
pub multisample: wgt::MultisampleState,
|
||||
/// The fragment processing state for this pipeline.
|
||||
pub fragment: Option<FragmentState<'a>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
@ -206,11 +202,14 @@ pub enum CreateRenderPipelineError {
|
||||
#[error("invalid sample count {0}")]
|
||||
InvalidSampleCount(u32),
|
||||
#[error("vertex buffer {index} stride {stride} does not respect `VERTEX_STRIDE_ALIGNMENT`")]
|
||||
UnalignedVertexStride { index: u32, stride: BufferAddress },
|
||||
UnalignedVertexStride {
|
||||
index: u32,
|
||||
stride: wgt::BufferAddress,
|
||||
},
|
||||
#[error("vertex attribute at location {location} has invalid offset {offset}")]
|
||||
InvalidVertexAttributeOffset {
|
||||
location: wgt::ShaderLocation,
|
||||
offset: BufferAddress,
|
||||
offset: wgt::BufferAddress,
|
||||
},
|
||||
#[error("missing required device features {0:?}")]
|
||||
MissingFeature(wgt::Features),
|
||||
@ -238,8 +237,8 @@ pub struct RenderPipeline<B: hal::Backend> {
|
||||
pub(crate) device_id: Stored<DeviceId>,
|
||||
pub(crate) pass_context: RenderPassContext,
|
||||
pub(crate) flags: PipelineFlags,
|
||||
pub(crate) index_format: Option<IndexFormat>,
|
||||
pub(crate) vertex_strides: Vec<(BufferAddress, InputStepMode)>,
|
||||
pub(crate) strip_index_format: Option<wgt::IndexFormat>,
|
||||
pub(crate) vertex_strides: Vec<(wgt::BufferAddress, wgt::InputStepMode)>,
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,16 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*! This library describes the API surface of WebGPU that is agnostic of the backend.
|
||||
* This API is used for targeting both Web and Native.
|
||||
*/
|
||||
|
||||
// The intra doc links to the wgpu crate in this crate actually succesfully link to the types in the wgpu crate, when built from the wgpu crate.
|
||||
// However when building from both the wgpu crate or this crate cargo doc will claim all the links cannot be resolved
|
||||
// despite the fact that it works fine when it needs to.
|
||||
// So we just disable those warnings.
|
||||
#![allow(broken_intra_doc_links)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -46,12 +51,19 @@ pub const QUERY_SIZE: u32 = 8;
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum Backend {
|
||||
/// Dummy backend, used for testing.
|
||||
Empty = 0,
|
||||
/// Vulkan API
|
||||
Vulkan = 1,
|
||||
/// Metal API (Apple platforms)
|
||||
Metal = 2,
|
||||
/// Direct3D-12 (Windows)
|
||||
Dx12 = 3,
|
||||
/// Direct3D-11 (Windows)
|
||||
Dx11 = 4,
|
||||
/// OpenGL ES-3 (Linux, Android)
|
||||
Gl = 5,
|
||||
/// WebGPU in the browser
|
||||
BrowserWebGpu = 6,
|
||||
}
|
||||
|
||||
@ -529,6 +541,7 @@ pub struct DeviceDescriptor<L> {
|
||||
}
|
||||
|
||||
impl<L> DeviceDescriptor<L> {
|
||||
///
|
||||
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> DeviceDescriptor<K> {
|
||||
DeviceDescriptor {
|
||||
label: fun(&self.label),
|
||||
@ -559,6 +572,9 @@ bitflags::bitflags! {
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Flags controlling the shader processing.
|
||||
///
|
||||
/// Note: These flags are internal tweaks, they don't affect the API.
|
||||
#[repr(transparent)]
|
||||
#[derive(Default)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
@ -620,18 +636,31 @@ impl TextureViewDimension {
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum BlendFactor {
|
||||
/// 0.0
|
||||
Zero = 0,
|
||||
/// 1.0
|
||||
One = 1,
|
||||
/// S.color
|
||||
SrcColor = 2,
|
||||
/// 1.0 - S.color
|
||||
OneMinusSrcColor = 3,
|
||||
/// S.alpha
|
||||
SrcAlpha = 4,
|
||||
/// 1.0 - S.alpha
|
||||
OneMinusSrcAlpha = 5,
|
||||
/// D.color
|
||||
DstColor = 6,
|
||||
/// 1.0 - D.color
|
||||
OneMinusDstColor = 7,
|
||||
/// D.alpha
|
||||
DstAlpha = 8,
|
||||
/// 1.0 - D.alpha
|
||||
OneMinusDstAlpha = 9,
|
||||
/// min(S.alpha, 1.0 - D.alpha)
|
||||
SrcAlphaSaturated = 10,
|
||||
/// Constant
|
||||
BlendColor = 11,
|
||||
/// 1.0 - Constant
|
||||
OneMinusBlendColor = 12,
|
||||
}
|
||||
|
||||
@ -643,10 +672,15 @@ pub enum BlendFactor {
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum BlendOperation {
|
||||
/// Src + Dst
|
||||
Add = 0,
|
||||
/// Src - Dst
|
||||
Subtract = 1,
|
||||
/// Dst - Src
|
||||
ReverseSubtract = 2,
|
||||
/// min(Src, Dst)
|
||||
Min = 3,
|
||||
/// max(Src, Dst)
|
||||
Max = 4,
|
||||
}
|
||||
|
||||
@ -663,19 +697,26 @@ impl Default for BlendOperation {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct BlendDescriptor {
|
||||
pub struct BlendState {
|
||||
/// Multiplier for the source, which is produced by the fragment shader.
|
||||
pub src_factor: BlendFactor,
|
||||
/// Multiplier for the destination, which is stored in the target.
|
||||
pub dst_factor: BlendFactor,
|
||||
/// The binary operation applied to the source and destination,
|
||||
/// multiplied by their respective factors.
|
||||
pub operation: BlendOperation,
|
||||
}
|
||||
|
||||
impl BlendDescriptor {
|
||||
pub const REPLACE: Self = BlendDescriptor {
|
||||
impl BlendState {
|
||||
/// Default blending state that replaces destination with the source.
|
||||
pub const REPLACE: Self = BlendState {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::Zero,
|
||||
operation: BlendOperation::Add,
|
||||
};
|
||||
|
||||
/// Returns true if the state relies on the constant color, which is
|
||||
/// set independently on a render command encoder.
|
||||
pub fn uses_color(&self) -> bool {
|
||||
match (self.src_factor, self.dst_factor) {
|
||||
(BlendFactor::BlendColor, _)
|
||||
@ -687,7 +728,7 @@ impl BlendDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BlendDescriptor {
|
||||
impl Default for BlendState {
|
||||
fn default() -> Self {
|
||||
Self::REPLACE
|
||||
}
|
||||
@ -698,24 +739,27 @@ impl Default for BlendDescriptor {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct ColorStateDescriptor {
|
||||
pub struct ColorTargetState {
|
||||
/// The [`TextureFormat`] of the image that this pipeline will render to. Must match the the format
|
||||
/// of the corresponding color attachment in [`CommandEncoder::begin_render_pass`].
|
||||
pub format: TextureFormat,
|
||||
/// The alpha blending that is used for this pipeline.
|
||||
pub alpha_blend: BlendDescriptor,
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub alpha_blend: BlendState,
|
||||
/// The color blending that is used for this pipeline.
|
||||
pub color_blend: BlendDescriptor,
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub color_blend: BlendState,
|
||||
/// Mask which enables/disables writes to different color/alpha channel.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub write_mask: ColorWrite,
|
||||
}
|
||||
|
||||
impl From<TextureFormat> for ColorStateDescriptor {
|
||||
impl From<TextureFormat> for ColorTargetState {
|
||||
fn from(format: TextureFormat) -> Self {
|
||||
Self {
|
||||
format,
|
||||
alpha_blend: BlendDescriptor::REPLACE,
|
||||
color_blend: BlendDescriptor::REPLACE,
|
||||
alpha_blend: BlendState::REPLACE,
|
||||
color_blend: BlendState::REPLACE,
|
||||
write_mask: ColorWrite::ALL,
|
||||
}
|
||||
}
|
||||
@ -747,6 +791,12 @@ pub enum PrimitiveTopology {
|
||||
TriangleStrip = 4,
|
||||
}
|
||||
|
||||
impl Default for PrimitiveTopology {
|
||||
fn default() -> Self {
|
||||
PrimitiveTopology::TriangleList
|
||||
}
|
||||
}
|
||||
|
||||
/// Winding order which classifies the "front" face.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
@ -809,25 +859,59 @@ impl Default for PolygonMode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the state of the rasterizer in a render pipeline.
|
||||
/// Describes the state of primitive assembly and rasterization in a render pipeline.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct RasterizationStateDescriptor {
|
||||
pub struct PrimitiveState {
|
||||
/// The primitive topology used to interpret vertices.
|
||||
pub topology: PrimitiveTopology,
|
||||
/// The format of index buffers for strip topologies. Should be left `None` for non-strip.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub strip_index_format: Option<IndexFormat>,
|
||||
/// The face to consider the front for the purpose of culling and stencil operations.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub front_face: FrontFace,
|
||||
/// The fact culling mode.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub cull_mode: CullMode,
|
||||
/// Controls the way each polygon is rasterized. Can be either `Fill` (default), `Line` or `Point`
|
||||
///
|
||||
/// Setting this to something other than `Fill` requires `Features::NON_FILL_POLYGON_MODE` to be enabled.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub polygon_mode: PolygonMode,
|
||||
/// If enabled polygon depth is clamped to 0-1 range instead of being clipped.
|
||||
}
|
||||
|
||||
/// Describes the multi-sampling state of a render pipeline.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct MultisampleState {
|
||||
/// The number of samples calculated per pixel (for MSAA). For non-multisampled textures,
|
||||
/// this should be `1`
|
||||
pub count: u32,
|
||||
/// Bitmask that restricts the samples of a pixel modified by this pipeline. All samples
|
||||
/// can be enabled using the value `!0`
|
||||
pub mask: u64,
|
||||
/// 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.
|
||||
///
|
||||
/// Requires `Features::DEPTH_CLAMPING` enabled.
|
||||
pub clamp_depth: bool,
|
||||
pub depth_bias: i32,
|
||||
pub depth_bias_slope_scale: f32,
|
||||
pub depth_bias_clamp: f32,
|
||||
/// 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,
|
||||
}
|
||||
|
||||
impl Default for MultisampleState {
|
||||
fn default() -> Self {
|
||||
MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
@ -848,7 +932,9 @@ bitflags::bitflags! {
|
||||
/// Features are defined by WebGPU specification unless `Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled.
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct TextureFormatFeatures {
|
||||
/// Valid bits for `TextureDescriptor::Usage` provided for format creation.
|
||||
pub allowed_usages: TextureUsage,
|
||||
/// Additional property flags for the format.
|
||||
pub flags: TextureFormatFeatureFlags,
|
||||
}
|
||||
|
||||
@ -1437,30 +1523,33 @@ impl Default for ColorWrite {
|
||||
}
|
||||
}
|
||||
|
||||
/// State of the stencil operation (fixed-pipeline stage).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct StencilStateDescriptor {
|
||||
pub struct StencilState {
|
||||
/// Front face mode.
|
||||
pub front: StencilStateFaceDescriptor,
|
||||
pub front: StencilStateFace,
|
||||
/// Back face mode.
|
||||
pub back: StencilStateFaceDescriptor,
|
||||
pub back: StencilStateFace,
|
||||
/// Stencil values are AND'd with this mask when reading and writing from the stencil buffer. Only low 8 bits are used.
|
||||
pub read_mask: u32,
|
||||
/// Stencil values are AND'd with this mask when writing to the stencil buffer. Only low 8 bits are used.
|
||||
pub write_mask: u32,
|
||||
}
|
||||
|
||||
impl StencilStateDescriptor {
|
||||
impl StencilState {
|
||||
/// Returns true if the stencil test is enabled.
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
(self.front != StencilStateFaceDescriptor::IGNORE
|
||||
|| self.back != StencilStateFaceDescriptor::IGNORE)
|
||||
(self.front != StencilStateFace::IGNORE || self.back != StencilStateFace::IGNORE)
|
||||
&& (self.read_mask != 0 || self.write_mask != 0)
|
||||
}
|
||||
/// Returns true if the state doesn't mutate the target values.
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
self.write_mask == 0
|
||||
}
|
||||
/// Returns true if the stencil state uses the reference value for testing.
|
||||
pub fn needs_ref_value(&self) -> bool {
|
||||
self.front.compare.needs_ref_value() || self.back.compare.needs_ref_value()
|
||||
}
|
||||
@ -1468,10 +1557,10 @@ impl StencilStateDescriptor {
|
||||
|
||||
/// Describes the depth/stencil state in a render pipeline.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct DepthStencilStateDescriptor {
|
||||
pub struct DepthStencilState {
|
||||
/// Format of the depth/stencil buffer, must be special depth format. Must match the the format
|
||||
/// of the depth/stencil attachment in [`CommandEncoder::begin_render_pass`].
|
||||
pub format: TextureFormat,
|
||||
@ -1479,16 +1568,40 @@ pub struct DepthStencilStateDescriptor {
|
||||
pub depth_write_enabled: bool,
|
||||
/// Comparison function used to compare depth values in the depth test.
|
||||
pub depth_compare: CompareFunction,
|
||||
pub stencil: StencilStateDescriptor,
|
||||
/// Stencil state.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub stencil: StencilState,
|
||||
|
||||
/// Constant depth biasing factor, in basic units of the depth format.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub depth_bias: i32,
|
||||
/// Slope depth biasing factor.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub depth_bias_slope_scale: f32,
|
||||
/// Depth bias clamp value (absolute).
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub depth_bias_clamp: f32,
|
||||
|
||||
/// If enabled polygon depth is clamped to 0-1 range instead of being clipped.
|
||||
///
|
||||
/// Requires `Features::DEPTH_CLAMPING` enabled.
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub clamp_depth: bool,
|
||||
}
|
||||
|
||||
impl DepthStencilStateDescriptor {
|
||||
impl DepthStencilState {
|
||||
/// Returns true if the depth testing is enabled.
|
||||
pub fn is_depth_enabled(&self) -> bool {
|
||||
self.depth_compare != CompareFunction::Always || self.depth_write_enabled
|
||||
}
|
||||
/// Returns true if the state doesn't mutate either depth or stencil of the target.
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
!self.depth_write_enabled && self.stencil.is_read_only()
|
||||
}
|
||||
/// Returns true if the depth bias is applied.
|
||||
pub fn has_depth_bias(&self) -> bool {
|
||||
self.depth_bias != 0 || self.depth_bias_slope_scale != 0.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Format of indices used with pipeline.
|
||||
@ -1540,12 +1653,12 @@ impl Default for StencilOperation {
|
||||
|
||||
/// Describes stencil state in a render pipeline.
|
||||
///
|
||||
/// If you are not using stencil state, set this to [`StencilStateFaceDescriptor::IGNORE`].
|
||||
/// If you are not using stencil state, set this to [`StencilStateFace::IGNORE`].
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct StencilStateFaceDescriptor {
|
||||
pub struct StencilStateFace {
|
||||
/// Comparison function that determines if the fail_op or pass_op is used on the stencil buffer.
|
||||
pub compare: CompareFunction,
|
||||
/// Operation that is preformed when stencil test fails.
|
||||
@ -1556,8 +1669,9 @@ pub struct StencilStateFaceDescriptor {
|
||||
pub pass_op: StencilOperation,
|
||||
}
|
||||
|
||||
impl StencilStateFaceDescriptor {
|
||||
pub const IGNORE: Self = StencilStateFaceDescriptor {
|
||||
impl StencilStateFace {
|
||||
/// Ignore the stencil state for the face.
|
||||
pub const IGNORE: Self = StencilStateFace {
|
||||
compare: CompareFunction::Always,
|
||||
fail_op: StencilOperation::Keep,
|
||||
depth_fail_op: StencilOperation::Keep,
|
||||
@ -1565,7 +1679,7 @@ impl StencilStateFaceDescriptor {
|
||||
};
|
||||
}
|
||||
|
||||
impl Default for StencilStateFaceDescriptor {
|
||||
impl Default for StencilStateFace {
|
||||
fn default() -> Self {
|
||||
Self::IGNORE
|
||||
}
|
||||
@ -1596,6 +1710,7 @@ pub enum CompareFunction {
|
||||
}
|
||||
|
||||
impl CompareFunction {
|
||||
/// Returns true if the comparison depends on the reference value.
|
||||
pub fn needs_ref_value(self) -> bool {
|
||||
match self {
|
||||
Self::Never | Self::Always => false,
|
||||
@ -1616,6 +1731,12 @@ pub enum InputStepMode {
|
||||
Instance = 1,
|
||||
}
|
||||
|
||||
impl Default for InputStepMode {
|
||||
fn default() -> Self {
|
||||
InputStepMode::Vertex
|
||||
}
|
||||
}
|
||||
|
||||
/// Vertex inputs (attributes) to shaders.
|
||||
///
|
||||
/// Arrays of these can be made with the [`vertex_attr_array`] macro. Vertex attributes are assumed to be tightly packed.
|
||||
@ -1623,11 +1744,11 @@ pub enum InputStepMode {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct VertexAttributeDescriptor {
|
||||
/// Byte offset of the start of the input
|
||||
pub offset: BufferAddress,
|
||||
pub struct VertexAttribute {
|
||||
/// Format of the input
|
||||
pub format: VertexFormat,
|
||||
/// Byte offset of the start of the input
|
||||
pub offset: BufferAddress,
|
||||
/// Location for this input. Must match the location in the shader.
|
||||
pub shader_location: ShaderLocation,
|
||||
}
|
||||
@ -1709,6 +1830,7 @@ pub enum VertexFormat {
|
||||
}
|
||||
|
||||
impl VertexFormat {
|
||||
/// Returns the byte size of the format.
|
||||
pub const fn size(&self) -> u64 {
|
||||
match self {
|
||||
Self::Uchar2 | Self::Char2 | Self::Uchar2Norm | Self::Char2Norm => 2,
|
||||
@ -1800,6 +1922,7 @@ pub struct BufferDescriptor<L> {
|
||||
}
|
||||
|
||||
impl<L> BufferDescriptor<L> {
|
||||
///
|
||||
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> BufferDescriptor<K> {
|
||||
BufferDescriptor {
|
||||
label: fun(&self.label),
|
||||
@ -1821,6 +1944,7 @@ pub struct CommandEncoderDescriptor<L> {
|
||||
}
|
||||
|
||||
impl<L> CommandEncoderDescriptor<L> {
|
||||
///
|
||||
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandEncoderDescriptor<K> {
|
||||
CommandEncoderDescriptor {
|
||||
label: fun(&self.label),
|
||||
@ -1904,10 +2028,16 @@ pub struct SwapChainDescriptor {
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub enum SwapChainStatus {
|
||||
/// No issues.
|
||||
Good,
|
||||
/// The swap chain is operational, but it does no longer perfectly
|
||||
/// match the surface. A re-configuration is needed.
|
||||
Suboptimal,
|
||||
/// Unable to get the next frame, timed out.
|
||||
Timeout,
|
||||
/// The surface under the swap chain has changed.
|
||||
Outdated,
|
||||
/// The surface under the swap chain is lost.
|
||||
Lost,
|
||||
}
|
||||
|
||||
@ -1918,12 +2048,17 @@ pub enum SwapChainStatus {
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct Color {
|
||||
///
|
||||
pub r: f64,
|
||||
///
|
||||
pub g: f64,
|
||||
///
|
||||
pub b: f64,
|
||||
///
|
||||
pub a: f64,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
impl Color {
|
||||
pub const TRANSPARENT: Self = Self {
|
||||
r: 0.0,
|
||||
@ -1983,12 +2118,16 @@ pub enum TextureDimension {
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct Origin3d {
|
||||
///
|
||||
pub x: u32,
|
||||
///
|
||||
pub y: u32,
|
||||
///
|
||||
pub z: u32,
|
||||
}
|
||||
|
||||
impl Origin3d {
|
||||
/// Zero origin.
|
||||
pub const ZERO: Self = Self { x: 0, y: 0, z: 0 };
|
||||
}
|
||||
|
||||
@ -2004,8 +2143,11 @@ impl Default for Origin3d {
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct Extent3d {
|
||||
///
|
||||
pub width: u32,
|
||||
///
|
||||
pub height: u32,
|
||||
///
|
||||
pub depth: u32,
|
||||
}
|
||||
|
||||
@ -2137,6 +2279,7 @@ pub struct TextureDescriptor<L> {
|
||||
}
|
||||
|
||||
impl<L> TextureDescriptor<L> {
|
||||
///
|
||||
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> TextureDescriptor<K> {
|
||||
TextureDescriptor {
|
||||
label: fun(&self.label),
|
||||
@ -2246,10 +2389,12 @@ pub struct PushConstantRange {
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct CommandBufferDescriptor<L> {
|
||||
/// Debug label of this command buffer.
|
||||
pub label: L,
|
||||
}
|
||||
|
||||
impl<L> CommandBufferDescriptor<L> {
|
||||
///
|
||||
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandBufferDescriptor<K> {
|
||||
CommandBufferDescriptor {
|
||||
label: fun(&self.label),
|
||||
@ -2268,6 +2413,7 @@ pub struct RenderBundleDescriptor<L> {
|
||||
}
|
||||
|
||||
impl<L> RenderBundleDescriptor<L> {
|
||||
///
|
||||
pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> RenderBundleDescriptor<K> {
|
||||
RenderBundleDescriptor {
|
||||
label: fun(&self.label),
|
||||
@ -2360,15 +2506,16 @@ impl Default for BufferBindingType {
|
||||
pub enum TextureSampleType {
|
||||
/// Sampling returns floats.
|
||||
///
|
||||
/// If `filterable` is false, the texture can't be sampled with
|
||||
/// a filtering sampler.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform texture2D t;
|
||||
/// ```
|
||||
Float { filterable: bool },
|
||||
Float {
|
||||
/// If `filterable` is false, the texture can't be sampled with
|
||||
/// a filtering sampler.
|
||||
filterable: bool,
|
||||
},
|
||||
/// Sampling does the depth reference comparison.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
@ -2445,16 +2592,17 @@ pub enum StorageTextureAccess {
|
||||
pub enum BindingType {
|
||||
/// A buffer binding.
|
||||
Buffer {
|
||||
/// Sub-type of the buffer binding.
|
||||
ty: BufferBindingType,
|
||||
/// Indicates that the binding has a dynamic offset.
|
||||
/// One offset must be passed to [`RenderPass::set_bind_group`] for each dynamic binding in increasing order of binding number.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
has_dynamic_offset: bool,
|
||||
/// Minimum size of the corresponding `BufferBinding` required to match this entry.
|
||||
/// When pipeline is created, the size has to cover at least the corresponding structure in the shader
|
||||
/// plus one element of the unbound array, which can only be last in the structure.
|
||||
/// If `None`, the check is performed at draw call time instead of pipeline and bind group creation.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
min_binding_size: Option<BufferSize>,
|
||||
},
|
||||
/// A sampler that can be used to sample a texture.
|
||||
@ -2510,6 +2658,7 @@ pub enum BindingType {
|
||||
}
|
||||
|
||||
impl BindingType {
|
||||
/// Returns true for buffer bindings with dynamic offset enabled.
|
||||
pub fn has_dynamic_offset(&self) -> bool {
|
||||
match *self {
|
||||
Self::Buffer {
|
||||
@ -2537,7 +2686,7 @@ pub struct BindGroupLayoutEntry {
|
||||
/// If this value is Some and `ty` is `BindingType::Texture`, [`Features::SAMPLED_TEXTURE_BINDING_ARRAY`] must be supported.
|
||||
///
|
||||
/// If this value is Some and `ty` is any other variant, bind group creation will fail.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub count: Option<NonZeroU32>,
|
||||
}
|
||||
|
||||
@ -2564,7 +2713,7 @@ pub struct TextureCopyView<T> {
|
||||
/// The target mip level of the texture.
|
||||
pub mip_level: u32,
|
||||
/// The base texel of the texture in the selected `mip_level`.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
#[cfg_attr(any(feature = "trace", feature = "replay"), serde(default))]
|
||||
pub origin: Origin3d,
|
||||
}
|
||||
|
||||
@ -2574,8 +2723,11 @@ pub struct TextureCopyView<T> {
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
||||
pub enum SamplerBorderColor {
|
||||
/// [0, 0, 0, 0]
|
||||
TransparentBlack,
|
||||
/// [0, 0, 0, 1]
|
||||
OpaqueBlack,
|
||||
/// [1, 1, 1, 1]
|
||||
OpaqueWhite,
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user