mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 08:13:27 +00:00
Support dual source blending (#4022)
Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>
This commit is contained in:
parent
5c26841d66
commit
dc5beac8c9
@ -100,6 +100,7 @@ By @wumpf in [#4147](https://github.com/gfx-rs/wgpu/pull/4147)
|
|||||||
- Add validation in accordance with WebGPU `setViewport` valid usage for `x`, `y` and `this.[[attachment_size]]`. By @James2022-rgb in [#4058](https://github.com/gfx-rs/wgpu/pull/4058)
|
- Add validation in accordance with WebGPU `setViewport` valid usage for `x`, `y` and `this.[[attachment_size]]`. By @James2022-rgb in [#4058](https://github.com/gfx-rs/wgpu/pull/4058)
|
||||||
- `wgpu::CreateSurfaceError` and `wgpu::RequestDeviceError` now give details of the failure, but no longer implement `PartialEq` and cannot be constructed. By @kpreid in [#4066](https://github.com/gfx-rs/wgpu/pull/4066) and [#4145](https://github.com/gfx-rs/wgpu/pull/4145)
|
- `wgpu::CreateSurfaceError` and `wgpu::RequestDeviceError` now give details of the failure, but no longer implement `PartialEq` and cannot be constructed. By @kpreid in [#4066](https://github.com/gfx-rs/wgpu/pull/4066) and [#4145](https://github.com/gfx-rs/wgpu/pull/4145)
|
||||||
- Make `WGPU_POWER_PREF=none` a valid value. By @fornwall in [4076](https://github.com/gfx-rs/wgpu/pull/4076)
|
- Make `WGPU_POWER_PREF=none` a valid value. By @fornwall in [4076](https://github.com/gfx-rs/wgpu/pull/4076)
|
||||||
|
- Support dual source blending in OpenGL ES, Metal, Vulkan & DX12. By @freqmod in [4022](https://github.com/gfx-rs/wgpu/pull/4022)
|
||||||
|
|
||||||
#### Vulkan
|
#### Vulkan
|
||||||
|
|
||||||
|
@ -1276,6 +1276,10 @@ impl<A: HalApi> Device<A> {
|
|||||||
.flags
|
.flags
|
||||||
.contains(wgt::DownlevelFlags::MULTISAMPLED_SHADING),
|
.contains(wgt::DownlevelFlags::MULTISAMPLED_SHADING),
|
||||||
);
|
);
|
||||||
|
caps.set(
|
||||||
|
Caps::DUAL_SOURCE_BLENDING,
|
||||||
|
self.features.contains(wgt::Features::DUAL_SOURCE_BLENDING),
|
||||||
|
);
|
||||||
|
|
||||||
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
|
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
|
||||||
.validate(&module)
|
.validate(&module)
|
||||||
@ -2560,6 +2564,8 @@ impl<A: HalApi> Device<A> {
|
|||||||
let mut vertex_steps = Vec::with_capacity(desc.vertex.buffers.len());
|
let mut vertex_steps = Vec::with_capacity(desc.vertex.buffers.len());
|
||||||
let mut vertex_buffers = Vec::with_capacity(desc.vertex.buffers.len());
|
let mut vertex_buffers = Vec::with_capacity(desc.vertex.buffers.len());
|
||||||
let mut total_attributes = 0;
|
let mut total_attributes = 0;
|
||||||
|
let mut shader_expects_dual_source_blending = false;
|
||||||
|
let mut pipeline_expects_dual_source_blending = false;
|
||||||
for (i, vb_state) in desc.vertex.buffers.iter().enumerate() {
|
for (i, vb_state) in desc.vertex.buffers.iter().enumerate() {
|
||||||
vertex_steps.push(pipeline::VertexStep {
|
vertex_steps.push(pipeline::VertexStep {
|
||||||
stride: vb_state.array_stride,
|
stride: vb_state.array_stride,
|
||||||
@ -2700,7 +2706,25 @@ impl<A: HalApi> Device<A> {
|
|||||||
{
|
{
|
||||||
break Some(pipeline::ColorStateError::FormatNotMultisampled(cs.format));
|
break Some(pipeline::ColorStateError::FormatNotMultisampled(cs.format));
|
||||||
}
|
}
|
||||||
|
if let Some(blend_mode) = cs.blend {
|
||||||
|
for factor in [
|
||||||
|
blend_mode.color.src_factor,
|
||||||
|
blend_mode.color.dst_factor,
|
||||||
|
blend_mode.alpha.src_factor,
|
||||||
|
blend_mode.alpha.dst_factor,
|
||||||
|
] {
|
||||||
|
if factor.ref_second_blend_source() {
|
||||||
|
self.require_features(wgt::Features::DUAL_SOURCE_BLENDING)?;
|
||||||
|
if i == 0 {
|
||||||
|
pipeline_expects_dual_source_blending = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
return Err(crate::pipeline::CreateRenderPipelineError
|
||||||
|
::BlendFactorOnUnsupportedTarget { factor, target: i as u32 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break None;
|
break None;
|
||||||
};
|
};
|
||||||
if let Some(e) = error {
|
if let Some(e) = error {
|
||||||
@ -2857,6 +2881,15 @@ impl<A: HalApi> Device<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ref interface) = shader_module.interface {
|
||||||
|
shader_expects_dual_source_blending = interface
|
||||||
|
.fragment_uses_dual_source_blending(&fragment.stage.entry_point)
|
||||||
|
.map_err(|error| pipeline::CreateRenderPipelineError::Stage {
|
||||||
|
stage: flag,
|
||||||
|
error,
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
Some(hal::ProgrammableStage {
|
Some(hal::ProgrammableStage {
|
||||||
module: &shader_module.raw,
|
module: &shader_module.raw,
|
||||||
entry_point: fragment.stage.entry_point.as_ref(),
|
entry_point: fragment.stage.entry_point.as_ref(),
|
||||||
@ -2865,6 +2898,17 @@ impl<A: HalApi> Device<A> {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !pipeline_expects_dual_source_blending && shader_expects_dual_source_blending {
|
||||||
|
return Err(
|
||||||
|
pipeline::CreateRenderPipelineError::ShaderExpectsPipelineToUseDualSourceBlending,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if pipeline_expects_dual_source_blending && !shader_expects_dual_source_blending {
|
||||||
|
return Err(
|
||||||
|
pipeline::CreateRenderPipelineError::PipelineExpectsShaderToUseDualSourceBlending,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if validated_stages.contains(wgt::ShaderStages::FRAGMENT) {
|
if validated_stages.contains(wgt::ShaderStages::FRAGMENT) {
|
||||||
for (i, output) in io.iter() {
|
for (i, output) in io.iter() {
|
||||||
match color_targets.get(*i as usize) {
|
match color_targets.get(*i as usize) {
|
||||||
|
@ -384,6 +384,15 @@ pub enum CreateRenderPipelineError {
|
|||||||
},
|
},
|
||||||
#[error("In the provided shader, the type given for group {group} binding {binding} has a size of {size}. As the device does not support `DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED`, the type must have a size that is a multiple of 16 bytes.")]
|
#[error("In the provided shader, the type given for group {group} binding {binding} has a size of {size}. As the device does not support `DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED`, the type must have a size that is a multiple of 16 bytes.")]
|
||||||
UnalignedShader { group: u32, binding: u32, size: u64 },
|
UnalignedShader { group: u32, binding: u32, size: u64 },
|
||||||
|
#[error("Using the blend factor {factor:?} for render target {target} is not possible. Only the first render target may be used when dual-source blending.")]
|
||||||
|
BlendFactorOnUnsupportedTarget {
|
||||||
|
factor: wgt::BlendFactor,
|
||||||
|
target: u32,
|
||||||
|
},
|
||||||
|
#[error("Pipeline expects the shader entry point to make use of dual-source blending.")]
|
||||||
|
PipelineExpectsShaderToUseDualSourceBlending,
|
||||||
|
#[error("Shader entry point expects the pipeline to make use of dual-source blending.")]
|
||||||
|
ShaderExpectsPipelineToUseDualSourceBlending,
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
|
@ -116,6 +116,7 @@ struct EntryPoint {
|
|||||||
spec_constants: Vec<SpecializationConstant>,
|
spec_constants: Vec<SpecializationConstant>,
|
||||||
sampling_pairs: FastHashSet<(naga::Handle<Resource>, naga::Handle<Resource>)>,
|
sampling_pairs: FastHashSet<(naga::Handle<Resource>, naga::Handle<Resource>)>,
|
||||||
workgroup_size: [u32; 3],
|
workgroup_size: [u32; 3],
|
||||||
|
dual_source_blending: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -903,7 +904,7 @@ impl Interface {
|
|||||||
ep.sampling_pairs
|
ep.sampling_pairs
|
||||||
.insert((resource_mapping[&key.image], resource_mapping[&key.sampler]));
|
.insert((resource_mapping[&key.image], resource_mapping[&key.sampler]));
|
||||||
}
|
}
|
||||||
|
ep.dual_source_blending = info.dual_source_blending;
|
||||||
ep.workgroup_size = entry_point.workgroup_size;
|
ep.workgroup_size = entry_point.workgroup_size;
|
||||||
|
|
||||||
entry_points.insert((entry_point.stage, entry_point.name.clone()), ep);
|
entry_points.insert((entry_point.stage, entry_point.name.clone()), ep);
|
||||||
@ -1177,4 +1178,15 @@ impl Interface {
|
|||||||
.collect();
|
.collect();
|
||||||
Ok(outputs)
|
Ok(outputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fragment_uses_dual_source_blending(
|
||||||
|
&self,
|
||||||
|
entry_point_name: &str,
|
||||||
|
) -> Result<bool, StageError> {
|
||||||
|
let pair = (naga::ShaderStage::Fragment, entry_point_name.to_string());
|
||||||
|
self.entry_points
|
||||||
|
.get(&pair)
|
||||||
|
.ok_or(StageError::MissingEntryPoint(pair.1))
|
||||||
|
.map(|ep| ep.dual_source_blending)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,9 @@ impl super::Adapter {
|
|||||||
| wgt::Features::TEXTURE_FORMAT_16BIT_NORM
|
| wgt::Features::TEXTURE_FORMAT_16BIT_NORM
|
||||||
| wgt::Features::PUSH_CONSTANTS
|
| wgt::Features::PUSH_CONSTANTS
|
||||||
| wgt::Features::SHADER_PRIMITIVE_INDEX
|
| wgt::Features::SHADER_PRIMITIVE_INDEX
|
||||||
| wgt::Features::RG11B10UFLOAT_RENDERABLE;
|
| wgt::Features::RG11B10UFLOAT_RENDERABLE
|
||||||
|
| wgt::Features::DUAL_SOURCE_BLENDING;
|
||||||
|
|
||||||
//TODO: in order to expose this, we need to run a compute shader
|
//TODO: in order to expose this, we need to run a compute shader
|
||||||
// that extract the necessary statistics out of the D3D12 result.
|
// that extract the necessary statistics out of the D3D12 result.
|
||||||
// Alternatively, we could allocate a buffer for the query set,
|
// Alternatively, we could allocate a buffer for the query set,
|
||||||
|
@ -246,12 +246,12 @@ fn map_blend_factor(factor: wgt::BlendFactor, is_alpha: bool) -> d3d12_ty::D3D12
|
|||||||
Bf::Constant => d3d12_ty::D3D12_BLEND_BLEND_FACTOR,
|
Bf::Constant => d3d12_ty::D3D12_BLEND_BLEND_FACTOR,
|
||||||
Bf::OneMinusConstant => d3d12_ty::D3D12_BLEND_INV_BLEND_FACTOR,
|
Bf::OneMinusConstant => d3d12_ty::D3D12_BLEND_INV_BLEND_FACTOR,
|
||||||
Bf::SrcAlphaSaturated => d3d12_ty::D3D12_BLEND_SRC_ALPHA_SAT,
|
Bf::SrcAlphaSaturated => d3d12_ty::D3D12_BLEND_SRC_ALPHA_SAT,
|
||||||
//Bf::Src1Color if is_alpha => d3d12_ty::D3D12_BLEND_SRC1_ALPHA,
|
Bf::Src1 if is_alpha => d3d12_ty::D3D12_BLEND_SRC1_ALPHA,
|
||||||
//Bf::Src1Color => d3d12_ty::D3D12_BLEND_SRC1_COLOR,
|
Bf::Src1 => d3d12_ty::D3D12_BLEND_SRC1_COLOR,
|
||||||
//Bf::OneMinusSrc1Color if is_alpha => d3d12_ty::D3D12_BLEND_INV_SRC1_ALPHA,
|
Bf::OneMinusSrc1 if is_alpha => d3d12_ty::D3D12_BLEND_INV_SRC1_ALPHA,
|
||||||
//Bf::OneMinusSrc1Color => d3d12_ty::D3D12_BLEND_INV_SRC1_COLOR,
|
Bf::OneMinusSrc1 => d3d12_ty::D3D12_BLEND_INV_SRC1_COLOR,
|
||||||
//Bf::Src1Alpha => d3d12_ty::D3D12_BLEND_SRC1_ALPHA,
|
Bf::Src1Alpha => d3d12_ty::D3D12_BLEND_SRC1_ALPHA,
|
||||||
//Bf::OneMinusSrc1Alpha => d3d12_ty::D3D12_BLEND_INV_SRC1_ALPHA,
|
Bf::OneMinusSrc1Alpha => d3d12_ty::D3D12_BLEND_INV_SRC1_ALPHA,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,6 +363,10 @@ impl super::Adapter {
|
|||||||
wgt::Features::MULTIVIEW,
|
wgt::Features::MULTIVIEW,
|
||||||
extensions.contains("OVR_multiview2"),
|
extensions.contains("OVR_multiview2"),
|
||||||
);
|
);
|
||||||
|
features.set(
|
||||||
|
wgt::Features::DUAL_SOURCE_BLENDING,
|
||||||
|
extensions.contains("GL_EXT_blend_func_extended"),
|
||||||
|
);
|
||||||
features.set(
|
features.set(
|
||||||
wgt::Features::SHADER_PRIMITIVE_INDEX,
|
wgt::Features::SHADER_PRIMITIVE_INDEX,
|
||||||
ver >= (3, 2) || extensions.contains("OES_geometry_shader"),
|
ver >= (3, 2) || extensions.contains("OES_geometry_shader"),
|
||||||
|
@ -376,6 +376,10 @@ fn map_blend_factor(factor: wgt::BlendFactor) -> u32 {
|
|||||||
Bf::Constant => glow::CONSTANT_COLOR,
|
Bf::Constant => glow::CONSTANT_COLOR,
|
||||||
Bf::OneMinusConstant => glow::ONE_MINUS_CONSTANT_COLOR,
|
Bf::OneMinusConstant => glow::ONE_MINUS_CONSTANT_COLOR,
|
||||||
Bf::SrcAlphaSaturated => glow::SRC_ALPHA_SATURATE,
|
Bf::SrcAlphaSaturated => glow::SRC_ALPHA_SATURATE,
|
||||||
|
Bf::Src1 => glow::SRC1_COLOR,
|
||||||
|
Bf::OneMinusSrc1 => glow::ONE_MINUS_SRC1_COLOR,
|
||||||
|
Bf::Src1Alpha => glow::SRC1_ALPHA,
|
||||||
|
Bf::OneMinusSrc1Alpha => glow::ONE_MINUS_SRC1_ALPHA,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,6 +833,10 @@ impl super::PrivateCapabilities {
|
|||||||
self.timestamp_query_support
|
self.timestamp_query_support
|
||||||
.contains(TimestampQuerySupport::INSIDE_WGPU_PASSES),
|
.contains(TimestampQuerySupport::INSIDE_WGPU_PASSES),
|
||||||
);
|
);
|
||||||
|
features.set(
|
||||||
|
F::DUAL_SOURCE_BLENDING,
|
||||||
|
self.msl_version >= MTLLanguageVersion::V1_2 && self.dual_source_blending,
|
||||||
|
);
|
||||||
features.set(F::TEXTURE_COMPRESSION_ASTC, self.format_astc);
|
features.set(F::TEXTURE_COMPRESSION_ASTC, self.format_astc);
|
||||||
features.set(F::TEXTURE_COMPRESSION_ASTC_HDR, self.format_astc_hdr);
|
features.set(F::TEXTURE_COMPRESSION_ASTC_HDR, self.format_astc_hdr);
|
||||||
features.set(F::TEXTURE_COMPRESSION_BC, self.format_bc);
|
features.set(F::TEXTURE_COMPRESSION_BC, self.format_bc);
|
||||||
|
@ -152,13 +152,11 @@ pub fn map_blend_factor(factor: wgt::BlendFactor) -> metal::MTLBlendFactor {
|
|||||||
Bf::OneMinusDstAlpha => OneMinusDestinationAlpha,
|
Bf::OneMinusDstAlpha => OneMinusDestinationAlpha,
|
||||||
Bf::Constant => BlendColor,
|
Bf::Constant => BlendColor,
|
||||||
Bf::OneMinusConstant => OneMinusBlendColor,
|
Bf::OneMinusConstant => OneMinusBlendColor,
|
||||||
//Bf::ConstantAlpha => BlendAlpha,
|
|
||||||
//Bf::OneMinusConstantAlpha => OneMinusBlendAlpha,
|
|
||||||
Bf::SrcAlphaSaturated => SourceAlphaSaturated,
|
Bf::SrcAlphaSaturated => SourceAlphaSaturated,
|
||||||
//Bf::Src1 => Source1Color,
|
Bf::Src1 => Source1Color,
|
||||||
//Bf::OneMinusSrc1 => OneMinusSource1Color,
|
Bf::OneMinusSrc1 => OneMinusSource1Color,
|
||||||
//Bf::Src1Alpha => Source1Alpha,
|
Bf::Src1Alpha => Source1Alpha,
|
||||||
//Bf::OneMinusSrc1Alpha => OneMinusSource1Alpha,
|
Bf::OneMinusSrc1Alpha => OneMinusSource1Alpha,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +177,7 @@ impl PhysicalDeviceFeatures {
|
|||||||
//.shader_resource_residency(requested_features.contains(wgt::Features::SHADER_RESOURCE_RESIDENCY))
|
//.shader_resource_residency(requested_features.contains(wgt::Features::SHADER_RESOURCE_RESIDENCY))
|
||||||
.geometry_shader(requested_features.contains(wgt::Features::SHADER_PRIMITIVE_INDEX))
|
.geometry_shader(requested_features.contains(wgt::Features::SHADER_PRIMITIVE_INDEX))
|
||||||
.depth_clamp(requested_features.contains(wgt::Features::DEPTH_CLIP_CONTROL))
|
.depth_clamp(requested_features.contains(wgt::Features::DEPTH_CLIP_CONTROL))
|
||||||
|
.dual_src_blend(requested_features.contains(wgt::Features::DUAL_SOURCE_BLENDING))
|
||||||
.build(),
|
.build(),
|
||||||
descriptor_indexing: if requested_features.intersects(indexing_features()) {
|
descriptor_indexing: if requested_features.intersects(indexing_features()) {
|
||||||
Some(
|
Some(
|
||||||
@ -460,6 +461,7 @@ impl PhysicalDeviceFeatures {
|
|||||||
}
|
}
|
||||||
|
|
||||||
features.set(F::DEPTH_CLIP_CONTROL, self.core.depth_clamp != 0);
|
features.set(F::DEPTH_CLIP_CONTROL, self.core.depth_clamp != 0);
|
||||||
|
features.set(F::DUAL_SOURCE_BLENDING, self.core.dual_src_blend != 0);
|
||||||
|
|
||||||
if let Some(ref multiview) = self.multiview {
|
if let Some(ref multiview) = self.multiview {
|
||||||
features.set(F::MULTIVIEW, multiview.multiview != 0);
|
features.set(F::MULTIVIEW, multiview.multiview != 0);
|
||||||
|
@ -792,6 +792,10 @@ fn map_blend_factor(factor: wgt::BlendFactor) -> vk::BlendFactor {
|
|||||||
Bf::SrcAlphaSaturated => vk::BlendFactor::SRC_ALPHA_SATURATE,
|
Bf::SrcAlphaSaturated => vk::BlendFactor::SRC_ALPHA_SATURATE,
|
||||||
Bf::Constant => vk::BlendFactor::CONSTANT_COLOR,
|
Bf::Constant => vk::BlendFactor::CONSTANT_COLOR,
|
||||||
Bf::OneMinusConstant => vk::BlendFactor::ONE_MINUS_CONSTANT_COLOR,
|
Bf::OneMinusConstant => vk::BlendFactor::ONE_MINUS_CONSTANT_COLOR,
|
||||||
|
Bf::Src1 => vk::BlendFactor::SRC1_COLOR,
|
||||||
|
Bf::OneMinusSrc1 => vk::BlendFactor::ONE_MINUS_SRC1_COLOR,
|
||||||
|
Bf::Src1Alpha => vk::BlendFactor::SRC1_ALPHA,
|
||||||
|
Bf::OneMinusSrc1Alpha => vk::BlendFactor::ONE_MINUS_SRC1_ALPHA,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,7 +781,17 @@ bitflags::bitflags! {
|
|||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const SHADER_EARLY_DEPTH_TEST = 1 << 62;
|
const SHADER_EARLY_DEPTH_TEST = 1 << 62;
|
||||||
|
|
||||||
// 62..64 available
|
/// Allows two outputs from a shader to be used for blending.
|
||||||
|
/// Note that dual-source blending doesn't support multiple render targets.
|
||||||
|
///
|
||||||
|
/// For more info see the OpenGL ES extension GL_EXT_blend_func_extended.
|
||||||
|
///
|
||||||
|
/// Supported platforms:
|
||||||
|
/// - OpenGL ES (with GL_EXT_blend_func_extended)
|
||||||
|
/// - Metal (with MSL 1.2+)
|
||||||
|
/// - Vulkan (with dualSrcBlend)
|
||||||
|
/// - DX12
|
||||||
|
const DUAL_SOURCE_BLENDING = 1 << 63;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1549,6 +1559,8 @@ impl TextureViewDimension {
|
|||||||
///
|
///
|
||||||
/// Corresponds to [WebGPU `GPUBlendFactor`](
|
/// Corresponds to [WebGPU `GPUBlendFactor`](
|
||||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendfactor).
|
/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendfactor).
|
||||||
|
/// Values using S1 requires [`Features::DUAL_SOURCE_BLENDING`] and can only be
|
||||||
|
/// used with the first render target.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||||
@ -1581,6 +1593,29 @@ pub enum BlendFactor {
|
|||||||
Constant = 11,
|
Constant = 11,
|
||||||
/// 1.0 - Constant
|
/// 1.0 - Constant
|
||||||
OneMinusConstant = 12,
|
OneMinusConstant = 12,
|
||||||
|
/// S1.component
|
||||||
|
Src1 = 13,
|
||||||
|
/// 1.0 - S1.component
|
||||||
|
OneMinusSrc1 = 14,
|
||||||
|
/// S1.alpha
|
||||||
|
Src1Alpha = 15,
|
||||||
|
/// 1.0 - S1.alpha
|
||||||
|
OneMinusSrc1Alpha = 16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlendFactor {
|
||||||
|
/// Returns `true` if the blend factor references the second blend source.
|
||||||
|
///
|
||||||
|
/// Note that the usage of those blend factors require [`Features::DUAL_SOURCE_BLENDING`].
|
||||||
|
pub fn ref_second_blend_source(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
BlendFactor::Src1
|
||||||
|
| BlendFactor::OneMinusSrc1
|
||||||
|
| BlendFactor::Src1Alpha
|
||||||
|
| BlendFactor::OneMinusSrc1Alpha => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alpha blend operation.
|
/// Alpha blend operation.
|
||||||
|
@ -421,6 +421,15 @@ fn map_blend_factor(factor: wgt::BlendFactor) -> web_sys::GpuBlendFactor {
|
|||||||
BlendFactor::SrcAlphaSaturated => bf::SrcAlphaSaturated,
|
BlendFactor::SrcAlphaSaturated => bf::SrcAlphaSaturated,
|
||||||
BlendFactor::Constant => bf::Constant,
|
BlendFactor::Constant => bf::Constant,
|
||||||
BlendFactor::OneMinusConstant => bf::OneMinusConstant,
|
BlendFactor::OneMinusConstant => bf::OneMinusConstant,
|
||||||
|
BlendFactor::Src1
|
||||||
|
| BlendFactor::OneMinusSrc1
|
||||||
|
| BlendFactor::Src1Alpha
|
||||||
|
| BlendFactor::OneMinusSrc1Alpha => {
|
||||||
|
panic!(
|
||||||
|
"{:?} is not enabled for this backend",
|
||||||
|
wgt::Features::DUAL_SOURCE_BLENDING
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user