Refactor downlevel support a bit, implement blending for hal/gles

This commit is contained in:
Dzmitry Malyshau
2021-06-25 00:52:12 -04:00
committed by Dzmitry Malyshau
parent 13b0a61dc8
commit 91df157462
11 changed files with 344 additions and 79 deletions

View File

@@ -11,7 +11,7 @@ use crate::{
resource::{Buffer, Texture},
track::{StatefulTrackerSubset, TrackerSet, UsageConflict, UseExtendError},
validation::{check_buffer_usage, MissingBufferUsageError},
Label, DOWNLEVEL_ERROR_WARNING_MESSAGE,
Label,
};
use hal::CommandEncoder as _;
@@ -149,11 +149,6 @@ pub enum ComputePassErrorInner {
MissingBufferUsage(#[from] MissingBufferUsageError),
#[error("cannot pop debug group, because number of pushed debug groups is zero")]
InvalidPopDebugGroup,
#[error(
"Compute shaders are not supported by the underlying platform. {}",
DOWNLEVEL_ERROR_WARNING_MESSAGE
)]
ComputeShadersUnsupported,
#[error(transparent)]
Dispatch(#[from] DispatchError),
#[error(transparent)]
@@ -276,17 +271,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
});
}
if !cmd_buf
.downlevel
.flags
.contains(wgt::DownlevelFlags::COMPUTE_SHADERS)
{
return Err(ComputePassError {
scope: PassErrorScope::Pass(encoder_id),
inner: ComputePassErrorInner::ComputeShadersUnsupported,
});
}
let (_, mut token) = hub.render_bundles.read(&mut token);
let (pipeline_layout_guard, mut token) = hub.pipeline_layouts.read(&mut token);
let (bind_group_guard, mut token) = hub.bind_groups.read(&mut token);

View File

@@ -77,7 +77,6 @@ pub struct CommandBuffer<A: hal::Api> {
pub(crate) used_swap_chains: SmallVec<[Stored<id::SwapChainId>; 1]>,
pub(crate) buffer_memory_init_actions: Vec<MemoryInitTrackerAction<id::BufferId>>,
limits: wgt::Limits,
downlevel: wgt::DownlevelCapabilities,
support_fill_buffer_texture: bool,
#[cfg(feature = "trace")]
pub(crate) commands: Option<Vec<crate::device::trace::Command>>,
@@ -88,7 +87,7 @@ impl<A: HalApi> CommandBuffer<A> {
encoder: A::CommandEncoder,
device_id: Stored<id::DeviceId>,
limits: wgt::Limits,
downlevel: wgt::DownlevelCapabilities,
_downlevel: wgt::DownlevelCapabilities,
features: wgt::Features,
#[cfg(feature = "trace")] enable_tracing: bool,
label: &Label,
@@ -106,7 +105,6 @@ impl<A: HalApi> CommandBuffer<A> {
used_swap_chains: Default::default(),
buffer_memory_init_actions: Default::default(),
limits,
downlevel,
support_fill_buffer_texture: features.contains(wgt::Features::CLEAR_COMMANDS),
#[cfg(feature = "trace")]
commands: if enable_tracing {

View File

@@ -8,6 +8,7 @@ use crate::{
track::{BufferState, TextureSelector, TextureState, TrackerSet, UsageConflict},
validation::{self, check_buffer_usage, check_texture_usage},
FastHashMap, Label, LabelHelpers as _, LifeGuard, MultiRefCount, Stored, SubmissionIndex,
DOWNLEVEL_ERROR_WARNING_MESSAGE,
};
use arrayvec::ArrayVec;
@@ -319,6 +320,17 @@ impl<A: HalApi> Device<A> {
}
}
pub(crate) fn require_downlevel_flags(
&self,
flags: wgt::DownlevelFlags,
) -> Result<(), MissingDownlevelFlags> {
if self.downlevel.flags.contains(flags) {
Ok(())
} else {
Err(MissingDownlevelFlags(flags))
}
}
fn lock_life_internal<'this, 'token: 'this>(
tracker: &'this Mutex<life::LifetimeTracker<A>>,
_token: &mut Token<'token, Self>,
@@ -1729,13 +1741,7 @@ impl<A: HalApi> Device<A> {
}
}
if !self
.downlevel
.flags
.contains(wgt::DownlevelFlags::COMPUTE_SHADERS)
{
return Err(pipeline::CreateComputePipelineError::ComputeShadersUnsupported);
}
self.require_downlevel_flags(wgt::DownlevelFlags::COMPUTE_SHADERS)?;
let mut derived_group_layouts =
ArrayVec::<[binding_model::BindEntryMap; hal::MAX_BIND_GROUPS]>::new();
@@ -1858,6 +1864,16 @@ impl<A: HalApi> Device<A> {
.map_or(&[][..], |fragment| &fragment.targets);
let depth_stencil_state = desc.depth_stencil.as_ref();
if !color_targets.is_empty() && {
let first = &color_targets[0];
color_targets[1..]
.iter()
.any(|ct| ct.write_mask != first.write_mask || ct.blend != first.blend)
} {
log::error!("Color targets: {:?}", color_targets);
self.require_downlevel_flags(wgt::DownlevelFlags::INDEPENDENT_BLENDING)?;
}
let mut io = validation::StageIo::default();
let mut validated_stages = wgt::ShaderStage::empty();
@@ -2405,6 +2421,13 @@ impl From<hal::DeviceError> for DeviceError {
#[error("Features {0:?} are required but not enabled on the device")]
pub struct MissingFeatures(pub wgt::Features);
#[derive(Clone, Debug, Error)]
#[error(
"Downlevel flags {0:?} are required but not supported on the device. {}",
DOWNLEVEL_ERROR_WARNING_MESSAGE
)]
pub struct MissingDownlevelFlags(pub wgt::DownlevelFlags);
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]

View File

@@ -1,9 +1,9 @@
use crate::{
binding_model::{CreateBindGroupLayoutError, CreatePipelineLayoutError},
device::{DeviceError, MissingFeatures, RenderPassContext},
device::{DeviceError, MissingDownlevelFlags, MissingFeatures, RenderPassContext},
hub::Resource,
id::{DeviceId, PipelineLayoutId, ShaderModuleId},
validation, Label, LifeGuard, Stored, DOWNLEVEL_ERROR_WARNING_MESSAGE,
validation, Label, LifeGuard, Stored,
};
use std::borrow::Cow;
use thiserror::Error;
@@ -109,11 +109,8 @@ pub enum CreateComputePipelineError {
Stage(#[from] validation::StageError),
#[error("Internal error: {0}")]
Internal(String),
#[error(
"Compute shaders are not supported by the underlying platform. {}",
DOWNLEVEL_ERROR_WARNING_MESSAGE
)]
ComputeShadersUnsupported,
#[error(transparent)]
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
}
#[derive(Debug)]
@@ -258,6 +255,8 @@ pub enum CreateRenderPipelineError {
ConservativeRasterizationNonFillPolygonMode,
#[error(transparent)]
MissingFeatures(#[from] MissingFeatures),
#[error(transparent)]
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
#[error("error matching {stage:?} shader requirements against the pipeline")]
Stage {
stage: wgt::ShaderStage,

View File

@@ -52,7 +52,7 @@ impl super::Adapter {
None => false,
};
let (version, vendor_info) = match src.find(' ') {
let (version, _vendor_info) = match src.find(' ') {
Some(i) => (&src[..i], src[i + 1..].to_string()),
None => (src, String::new()),
};
@@ -196,6 +196,10 @@ impl super::Adapter {
);
downlevel_flags.set(wgt::DownlevelFlags::INDIRECT_EXECUTION, ver >= (3, 1));
downlevel_flags.set(wgt::DownlevelFlags::BASE_VERTEX, ver >= (3, 2));
downlevel_flags.set(
wgt::DownlevelFlags::INDEPENDENT_BLENDING,
ver >= (3, 2) || extensions.contains("GL_EXT_draw_buffers_indexed"),
);
let max_texture_size = gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) as u32;
let max_texture_3d_size = gl.get_parameter_i32(glow::MAX_3D_TEXTURE_SIZE) as u32;

View File

@@ -14,9 +14,11 @@ pub(super) struct State {
topology: u32,
index_format: wgt::IndexFormat,
index_offset: wgt::BufferAddress,
vertex_buffers: [super::VertexBufferDesc; crate::MAX_VERTEX_BUFFERS],
vertex_buffers: [(super::VertexBufferDesc, super::BufferBinding); crate::MAX_VERTEX_BUFFERS],
vertex_attributes: ArrayVec<[super::AttributeDesc; super::MAX_VERTEX_ATTRIBUTES]>,
color_targets: ArrayVec<[super::ColorTargetDesc; crate::MAX_COLOR_TARGETS]>,
stencil: super::StencilState,
depth_bias: wgt::DepthBiasState,
has_pass_label: bool,
dirty: Dirty,
}
@@ -63,18 +65,19 @@ impl super::CommandEncoder {
fn rebind_vertex_attributes(&mut self, first_instance: u32) {
for attribute in self.state.vertex_attributes.iter() {
let vb = self.state.vertex_buffers[attribute.buffer_index as usize].clone();
let (buffer_desc, buffer) =
self.state.vertex_buffers[attribute.buffer_index as usize].clone();
let mut vat = attribute.clone();
vat.offset += vb.offset as u32;
if vb.step == wgt::InputStepMode::Instance {
vat.offset += vb.stride * first_instance;
let mut attribute_desc = attribute.clone();
if buffer_desc.step == wgt::InputStepMode::Instance {
attribute_desc.offset += buffer_desc.stride * first_instance;
}
self.cmd_buffer
.commands
.push(C::SetVertexAttribute(vat, vb));
self.cmd_buffer.commands.push(C::SetVertexAttribute {
buffer_desc,
buffer,
attribute_desc,
});
}
}
@@ -391,6 +394,8 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.state.has_pass_label = false;
}
self.state.dirty = Dirty::empty();
self.state.color_targets.clear();
self.state.vertex_attributes.clear();
}
unsafe fn set_bind_group(
@@ -426,11 +431,15 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.state.topology = conv::map_primitive_topology(pipeline.primitive.topology);
self.state.dirty |= Dirty::VERTEX_BUFFERS;
self.cmd_buffer
.commands
.push(C::SetProgram(pipeline.inner.program));
self.state.vertex_attributes.clear();
for vat in pipeline.vertex_attributes.iter() {
self.state.vertex_attributes.push(vat.clone());
}
for (state_desc, pipe_desc) in self
for (&mut (ref mut state_desc, _), pipe_desc) in self
.state
.vertex_buffers
.iter_mut()
@@ -440,7 +449,19 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
state_desc.stride = pipe_desc.stride;
}
let mut aspects = crate::FormatAspect::empty();
if pipeline.depth_bias != self.state.depth_bias {
self.state.depth_bias = pipeline.depth_bias;
self.cmd_buffer
.commands
.push(C::SetDepthBias(pipeline.depth_bias));
}
if let Some(ref depth) = pipeline.depth {
aspects |= crate::FormatAspect::DEPTH;
self.cmd_buffer.commands.push(C::SetDepth(depth.clone()));
}
if let Some(ref stencil) = pipeline.stencil {
aspects |= crate::FormatAspect::STENCIL;
self.state.stencil = stencil.clone();
self.rebind_stencil_func();
if stencil.front.ops == stencil.back.ops
@@ -464,6 +485,34 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
});
}
}
self.cmd_buffer
.commands
.push(C::ConfigureDepthStencil(aspects));
if self.state.color_targets[..] != pipeline.color_targets[..] {
if pipeline
.color_targets
.iter()
.skip(1)
.any(|ct| *ct != pipeline.color_targets[0])
{
for (index, ct) in pipeline.color_targets.iter().enumerate() {
self.cmd_buffer.commands.push(C::SetColorTarget {
draw_buffer_index: Some(index as u32),
desc: ct.clone(),
});
}
} else {
self.cmd_buffer.commands.push(C::SetColorTarget {
draw_buffer_index: None,
desc: pipeline.color_targets.first().cloned().unwrap_or_default(),
});
}
}
self.state.color_targets.clear();
for ct in pipeline.color_targets.iter() {
self.state.color_targets.push(ct.clone());
}
}
unsafe fn set_index_buffer<'a>(
@@ -483,7 +532,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
binding: crate::BufferBinding<'a, super::Api>,
) {
self.state.dirty |= Dirty::VERTEX_BUFFERS;
let vb = &mut self.state.vertex_buffers[index as usize];
let vb = &mut self.state.vertex_buffers[index as usize].1;
vb.raw = binding.buffer.raw;
vb.offset = binding.offset;
}
@@ -511,7 +560,15 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.state.stencil.back.reference = value;
self.rebind_stencil_func();
}
unsafe fn set_blend_constants(&mut self, color: &wgt::Color) {}
unsafe fn set_blend_constants(&mut self, color: &wgt::Color) {
let color = [
color.r as f32,
color.g as f32,
color.b as f32,
color.a as f32,
];
self.cmd_buffer.commands.push(C::SetBlendConstant(color));
}
unsafe fn draw(
&mut self,
@@ -628,7 +685,11 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.state.dirty = Dirty::empty();
}
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {}
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
self.cmd_buffer
.commands
.push(C::SetProgram(pipeline.inner.program));
}
unsafe fn dispatch(&mut self, count: [u32; 3]) {
self.cmd_buffer.commands.push(C::Dispatch(count));

View File

@@ -273,3 +273,43 @@ pub(super) fn map_stencil(state: &wgt::StencilState) -> super::StencilState {
},
}
}
fn map_blend_factor(factor: wgt::BlendFactor) -> u32 {
use wgt::BlendFactor as Bf;
match factor {
Bf::Zero => glow::ZERO,
Bf::One => glow::ONE,
Bf::Src => glow::SRC_COLOR,
Bf::OneMinusSrc => glow::ONE_MINUS_SRC_COLOR,
Bf::Dst => glow::DST_COLOR,
Bf::OneMinusDst => glow::ONE_MINUS_DST_COLOR,
Bf::SrcAlpha => glow::SRC_ALPHA,
Bf::OneMinusSrcAlpha => glow::ONE_MINUS_SRC_ALPHA,
Bf::DstAlpha => glow::DST_ALPHA,
Bf::OneMinusDstAlpha => glow::ONE_MINUS_DST_ALPHA,
Bf::Constant => glow::CONSTANT_COLOR,
Bf::OneMinusConstant => glow::ONE_MINUS_CONSTANT_COLOR,
Bf::SrcAlphaSaturated => glow::SRC_ALPHA_SATURATE,
}
}
fn map_blend_component(component: &wgt::BlendComponent) -> super::BlendComponent {
super::BlendComponent {
src: map_blend_factor(component.src_factor),
dst: map_blend_factor(component.dst_factor),
equation: match component.operation {
wgt::BlendOperation::Add => glow::FUNC_ADD,
wgt::BlendOperation::Subtract => glow::FUNC_SUBTRACT,
wgt::BlendOperation::ReverseSubtract => glow::FUNC_REVERSE_SUBTRACT,
wgt::BlendOperation::Min => glow::MIN,
wgt::BlendOperation::Max => glow::MAX,
},
}
}
pub(super) fn map_blend(blend: &wgt::BlendState) -> super::BlendDesc {
super::BlendDesc {
color: map_blend_component(&blend.color),
alpha: map_blend_component(&blend.alpha),
}
}

View File

@@ -465,7 +465,7 @@ impl crate::Device<super::Api> for super::Device {
super::TextureInner::Renderbuffer { raw, .. } => {
gl.delete_renderbuffer(raw);
}
super::TextureInner::Texture { raw, target } => {
super::TextureInner::Texture { raw, .. } => {
gl.delete_texture(raw);
}
}
@@ -514,7 +514,7 @@ impl crate::Device<super::Api> for super::Device {
unsafe fn create_command_encoder(
&self,
desc: &crate::CommandEncoderDescriptor<super::Api>,
_desc: &crate::CommandEncoderDescriptor<super::Api>,
) -> Result<super::CommandEncoder, crate::DeviceError> {
Ok(super::CommandEncoder {
cmd_buffer: super::CommandBuffer::default(),
@@ -585,7 +585,7 @@ impl crate::Device<super::Api> for super::Device {
group_infos: group_infos.into_boxed_slice(),
})
}
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {}
unsafe fn destroy_pipeline_layout(&self, _pipeline_layout: super::PipelineLayout) {}
unsafe fn create_bind_group(
&self,
@@ -640,7 +640,7 @@ impl crate::Device<super::Api> for super::Device {
unsafe fn create_shader_module(
&self,
desc: &crate::ShaderModuleDescriptor,
_desc: &crate::ShaderModuleDescriptor,
shader: crate::ShaderInput,
) -> Result<super::ShaderModule, crate::ShaderError> {
Ok(super::ShaderModule {
@@ -670,8 +670,6 @@ impl crate::Device<super::Api> for super::Device {
let mut attributes = Vec::new();
for (index, vb_layout) in desc.vertex_buffers.iter().enumerate() {
buffers.push(super::VertexBufferDesc {
raw: 0,
offset: 0,
step: vb_layout.step_mode,
stride: vb_layout.array_stride as u32,
});
@@ -688,16 +686,34 @@ impl crate::Device<super::Api> for super::Device {
(buffers.into_boxed_slice(), attributes.into_boxed_slice())
};
let color_targets = {
let mut targets = Vec::new();
for ct in desc.color_targets.iter() {
targets.push(super::ColorTargetDesc {
mask: ct.write_mask,
blend: ct.blend.as_ref().map(conv::map_blend),
});
}
//Note: if any of the states are different, and `INDEPENDENT_BLEND` flag
// is not exposed, then this pipeline will not bind correctly.
targets.into_boxed_slice()
};
Ok(super::RenderPipeline {
inner,
primitive: desc.primitive,
vertex_buffers,
vertex_attributes,
color_targets,
depth: desc.depth_stencil.as_ref().map(|ds| super::DepthState {
function: conv::map_compare_func(ds.depth_compare),
mask: ds.depth_write_enabled,
}),
depth_bias: desc.depth_stencil.as_ref().map(|ds| ds.bias),
depth_bias: desc
.depth_stencil
.as_ref()
.map(|ds| ds.bias)
.unwrap_or_default(),
stencil: desc
.depth_stencil
.as_ref()

View File

@@ -1,5 +1,3 @@
#![allow(unused_variables)]
#[cfg(not(target_arch = "wasm32"))]
mod egl;
@@ -319,9 +317,13 @@ struct AttributeDesc {
}
#[derive(Clone, Debug, Default)]
struct VertexBufferDesc {
struct BufferBinding {
raw: glow::Buffer,
offset: wgt::BufferAddress,
}
#[derive(Clone, Debug, Default)]
struct VertexBufferDesc {
step: wgt::InputStepMode,
stride: u32,
}
@@ -343,19 +345,39 @@ struct PipelineInner {
uniforms: Box<[UniformDesc]>,
}
#[derive(Clone, Debug)]
struct DepthState {
function: u32,
mask: bool,
}
#[derive(Clone, Debug, PartialEq)]
struct BlendComponent {
src: u32,
dst: u32,
equation: u32,
}
#[derive(Clone, Debug, PartialEq)]
struct BlendDesc {
alpha: BlendComponent,
color: BlendComponent,
}
#[derive(Clone, Debug, Default, PartialEq)]
struct ColorTargetDesc {
mask: wgt::ColorWrite,
blend: Option<BlendDesc>,
}
pub struct RenderPipeline {
inner: PipelineInner,
//blend_targets: Vec<pso::ColorBlendDesc>,
primitive: wgt::PrimitiveState,
vertex_buffers: Box<[VertexBufferDesc]>,
vertex_attributes: Box<[AttributeDesc]>,
primitive: wgt::PrimitiveState,
color_targets: Box<[ColorTargetDesc]>,
depth: Option<DepthState>,
depth_bias: Option<wgt::DepthBiasState>,
depth_bias: wgt::DepthBiasState,
stencil: Option<StencilState>,
}
@@ -560,7 +582,20 @@ enum Command {
write_mask: u32,
ops: StencilOps,
},
SetVertexAttribute(AttributeDesc, VertexBufferDesc),
SetDepth(DepthState),
SetDepthBias(wgt::DepthBiasState),
ConfigureDepthStencil(crate::FormatAspect),
SetVertexAttribute {
buffer: BufferBinding,
buffer_desc: VertexBufferDesc,
attribute_desc: AttributeDesc,
},
SetProgram(glow::Program),
SetBlendConstant([f32; 4]),
SetColorTarget {
draw_buffer_index: Option<u32>,
desc: ColorTargetDesc,
},
InsertDebugMarker(Range<u32>),
PushDebugGroup(Range<u32>),
PopDebugGroup,

View File

@@ -17,6 +17,16 @@ fn is_3d_target(target: super::BindTarget) -> bool {
}
impl super::Queue {
unsafe fn reset_state(&self) {
let gl = &self.shared.context;
gl.use_program(None);
gl.polygon_offset(0.0, 0.0);
gl.disable(glow::DEPTH_TEST);
gl.disable(glow::STENCIL_TEST);
gl.disable(glow::SCISSOR_TEST);
gl.disable(glow::BLEND);
}
unsafe fn process(&mut self, command: &C, data_bytes: &[u8], data_words: &[u32]) {
let gl = &self.shared.context;
match *command {
@@ -161,7 +171,7 @@ impl super::Queue {
}
C::CopyBufferToTexture {
src,
src_target,
src_target: _,
dst,
dst_target,
ref dst_info,
@@ -213,7 +223,7 @@ impl super::Queue {
src_target,
ref src_info,
dst,
dst_target,
dst_target: _,
ref copy,
} => {
//TODO: compressed data
@@ -355,6 +365,9 @@ impl super::Queue {
.map(|i| glow::COLOR_ATTACHMENT0 + i)
.collect::<ArrayVec<[_; crate::MAX_COLOR_TARGETS]>>();
gl.draw_buffers(&indices);
for draw_buffer in 0..count as u32 {
gl.disable_draw_buffer(glow::BLEND, draw_buffer);
}
}
C::ClearColorF(draw_buffer, mut color) => {
gl.clear_buffer_f32_slice(glow::COLOR, draw_buffer, &mut color);
@@ -438,6 +451,7 @@ impl super::Queue {
}
C::SetScissor(ref rect) => {
gl.scissor(rect.x, rect.y, rect.w, rect.h);
gl.enable(glow::SCISSOR_TEST);
}
C::SetStencilFunc {
face,
@@ -455,29 +469,119 @@ impl super::Queue {
gl.stencil_mask_separate(face, write_mask);
gl.stencil_op_separate(face, ops.fail, ops.depth_fail, ops.pass);
}
C::SetVertexAttribute(ref vat, ref vb) => {
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vb.raw));
let offset = vat.offset as i32 + vb.offset as i32;
C::SetVertexAttribute {
ref buffer_desc,
ref buffer,
attribute_desc: ref vat,
} => {
gl.bind_buffer(glow::ARRAY_BUFFER, Some(buffer.raw));
let offset = vat.offset as i32 + buffer.offset as i32;
match vat.format_desc.attrib_kind {
super::VertexAttribKind::Float => gl.vertex_attrib_pointer_f32(
vat.location,
vat.format_desc.element_count,
vat.format_desc.element_format,
true, // always normalized
vb.stride as i32,
buffer_desc.stride as i32,
offset,
),
super::VertexAttribKind::Integer => gl.vertex_attrib_pointer_i32(
vat.location,
vat.format_desc.element_count,
vat.format_desc.element_format,
vb.stride as i32,
buffer_desc.stride as i32,
offset,
),
}
gl.vertex_attrib_divisor(vat.location, vb.step as u32);
gl.vertex_attrib_divisor(vat.location, buffer_desc.step as u32);
gl.enable_vertex_attrib_array(vat.location);
}
C::SetDepth(ref depth) => {
gl.depth_func(depth.function);
gl.depth_mask(depth.mask);
}
C::SetDepthBias(bias) => {
gl.polygon_offset(bias.constant as f32, bias.slope_scale);
}
C::ConfigureDepthStencil(aspects) => {
if aspects.contains(crate::FormatAspect::DEPTH) {
gl.enable(glow::DEPTH_TEST);
} else {
gl.disable(glow::DEPTH_TEST);
}
if aspects.contains(crate::FormatAspect::STENCIL) {
gl.enable(glow::STENCIL_TEST);
} else {
gl.disable(glow::STENCIL_TEST);
}
}
C::SetProgram(program) => {
gl.use_program(Some(program));
}
C::SetBlendConstant(c) => {
gl.blend_color(c[0], c[1], c[2], c[3]);
}
C::SetColorTarget {
draw_buffer_index,
desc: super::ColorTargetDesc { mask, ref blend },
} => {
use wgt::ColorWrite as Cw;
if let Some(index) = draw_buffer_index {
gl.color_mask_draw_buffer(
index,
mask.contains(Cw::RED),
mask.contains(Cw::GREEN),
mask.contains(Cw::BLUE),
mask.contains(Cw::ALPHA),
);
if let Some(ref blend) = *blend {
gl.enable_draw_buffer(index, glow::BLEND);
if blend.color != blend.alpha {
gl.blend_equation_separate_draw_buffer(
index,
blend.color.equation,
blend.alpha.equation,
);
gl.blend_func_separate_draw_buffer(
index,
blend.color.src,
blend.color.dst,
blend.alpha.src,
blend.alpha.dst,
);
} else {
gl.blend_equation_draw_buffer(index, blend.color.equation);
gl.blend_func_draw_buffer(index, blend.color.src, blend.color.dst);
}
} else {
gl.disable_draw_buffer(index, glow::BLEND);
}
} else {
gl.color_mask(
mask.contains(Cw::RED),
mask.contains(Cw::GREEN),
mask.contains(Cw::BLUE),
mask.contains(Cw::ALPHA),
);
if let Some(ref blend) = *blend {
gl.enable(glow::BLEND);
if blend.color != blend.alpha {
gl.blend_equation_separate(blend.color.equation, blend.alpha.equation);
gl.blend_func_separate(
blend.color.src,
blend.color.dst,
blend.alpha.src,
blend.alpha.dst,
);
} else {
gl.blend_equation(blend.color.equation);
gl.blend_func(blend.color.src, blend.color.dst);
}
} else {
gl.disable(glow::BLEND);
}
}
}
C::InsertDebugMarker(ref range) => {
let marker = extract_marker(data_bytes, range);
gl.debug_message_insert(
@@ -505,6 +609,7 @@ impl crate::Queue<super::Api> for super::Queue {
command_buffers: &[&super::CommandBuffer],
signal_fence: Option<(&mut super::Fence, crate::FenceValue)>,
) -> Result<(), crate::DeviceError> {
self.reset_state();
for cmd_buf in command_buffers.iter() {
for command in cmd_buf.commands.iter() {
self.process(command, &cmd_buf.data_bytes, &cmd_buf.data_words);

View File

@@ -625,24 +625,24 @@ bitflags::bitflags! {
const INDIRECT_EXECUTION = 0x0000_0004;
/// Supports non-zero `base_vertex` parameter to indexed draw calls.
const BASE_VERTEX = 0x0000_0008;
/// Supports non-zero `base_instance` parameter to draw calls.
const BASE_INSTANCE = 0x0000_0010;
/// Supports reading from a depth/stencil buffer while using as a read-only depth/stencil attachment.
const READ_ONLY_DEPTH_STENCIL = 0x0000_0020;
const READ_ONLY_DEPTH_STENCIL = 0x0000_0010;
/// Supports:
/// - copy_image_to_image
/// - copy_buffer_to_image and copy_image_to_buffer with a buffer without a MAP_* usage
const DEVICE_LOCAL_IMAGE_COPIES = 0x0000_0040;
const DEVICE_LOCAL_IMAGE_COPIES = 0x0000_0020;
/// Supports textures with mipmaps which have a non power of two size.
const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 0x0000_0080;
const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 0x0000_0040;
/// Supports textures that are cube arrays.
const CUBE_ARRAY_TEXTURES = 0x0000_0100;
const CUBE_ARRAY_TEXTURES = 0x0000_0080;
/// Supports comparison samplers.
const COMPARISON_SAMPLERS = 0x0000_0200;
const COMPARISON_SAMPLERS = 0x0000_0100;
/// Supports different blending modes per color target.
const INDEPENDENT_BLENDING = 0x0000_0200;
/// Supports samplers with anisotropic filtering
const ANISOTROPIC_FILTERING = 0x0001_0000;
/// All flags are in their compliant state.
const COMPLIANT = 0x0000_02FF;
const COMPLIANT = 0x0000_13FF;
}
}