mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
hal/gles: stencil and vertex state
This commit is contained in:
parent
205327d3aa
commit
13b0a61dc8
@ -232,7 +232,8 @@ impl super::Adapter {
|
|||||||
0
|
0
|
||||||
},
|
},
|
||||||
max_vertex_buffers: gl.get_parameter_i32(glow::MAX_VERTEX_ATTRIB_BINDINGS) as u32,
|
max_vertex_buffers: gl.get_parameter_i32(glow::MAX_VERTEX_ATTRIB_BINDINGS) as u32,
|
||||||
max_vertex_attributes: gl.get_parameter_i32(glow::MAX_VERTEX_ATTRIBS) as u32,
|
max_vertex_attributes: (gl.get_parameter_i32(glow::MAX_VERTEX_ATTRIBS) as u32)
|
||||||
|
.min(super::MAX_VERTEX_ATTRIBUTES as u32),
|
||||||
max_vertex_buffer_array_stride: 2048,
|
max_vertex_buffer_array_stride: 2048,
|
||||||
max_push_constant_size: 0,
|
max_push_constant_size: 0,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,26 @@
|
|||||||
use super::{conv, Command as C};
|
use super::{conv, Command as C};
|
||||||
|
use arrayvec::ArrayVec;
|
||||||
use std::{mem, ops::Range};
|
use std::{mem, ops::Range};
|
||||||
|
|
||||||
|
bitflags::bitflags! {
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Dirty: u32 {
|
||||||
|
const VERTEX_BUFFERS = 0x0001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub(super) struct State {
|
||||||
|
topology: u32,
|
||||||
|
index_format: wgt::IndexFormat,
|
||||||
|
index_offset: wgt::BufferAddress,
|
||||||
|
vertex_buffers: [super::VertexBufferDesc; crate::MAX_VERTEX_BUFFERS],
|
||||||
|
vertex_attributes: ArrayVec<[super::AttributeDesc; super::MAX_VERTEX_ATTRIBUTES]>,
|
||||||
|
stencil: super::StencilState,
|
||||||
|
has_pass_label: bool,
|
||||||
|
dirty: Dirty,
|
||||||
|
}
|
||||||
|
|
||||||
impl super::CommandBuffer {
|
impl super::CommandBuffer {
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
self.label = None;
|
self.label = None;
|
||||||
@ -16,9 +36,62 @@ impl super::CommandBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl super::CommandEncoder {
|
||||||
|
fn rebind_stencil_func(&mut self) {
|
||||||
|
fn make(s: &super::StencilSide, face: u32) -> C {
|
||||||
|
C::SetStencilFunc {
|
||||||
|
face,
|
||||||
|
function: s.function,
|
||||||
|
reference: s.reference,
|
||||||
|
read_mask: s.mask_read,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = &self.state.stencil;
|
||||||
|
if s.front.function == s.back.function
|
||||||
|
&& s.front.mask_read == s.back.mask_read
|
||||||
|
&& s.front.reference == s.back.reference
|
||||||
|
{
|
||||||
|
self.cmd_buffer
|
||||||
|
.commands
|
||||||
|
.push(make(&s.front, glow::FRONT_AND_BACK));
|
||||||
|
} else {
|
||||||
|
self.cmd_buffer.commands.push(make(&s.front, glow::FRONT));
|
||||||
|
self.cmd_buffer.commands.push(make(&s.back, glow::BACK));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 mut vat = attribute.clone();
|
||||||
|
vat.offset += vb.offset as u32;
|
||||||
|
|
||||||
|
if vb.step == wgt::InputStepMode::Instance {
|
||||||
|
vat.offset += vb.stride * first_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cmd_buffer
|
||||||
|
.commands
|
||||||
|
.push(C::SetVertexAttribute(vat, vb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_draw(&mut self, first_instance: u32) {
|
||||||
|
if first_instance != 0 {
|
||||||
|
self.rebind_vertex_attributes(first_instance);
|
||||||
|
self.state.dirty.set(Dirty::VERTEX_BUFFERS, true);
|
||||||
|
} else if self.state.dirty.contains(Dirty::VERTEX_BUFFERS) {
|
||||||
|
self.rebind_vertex_attributes(0);
|
||||||
|
self.state.dirty.set(Dirty::VERTEX_BUFFERS, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||||
unsafe fn begin_encoding(&mut self, label: crate::Label) -> Result<(), crate::DeviceError> {
|
unsafe fn begin_encoding(&mut self, label: crate::Label) -> Result<(), crate::DeviceError> {
|
||||||
self.state = super::CommandState::default();
|
self.state = State::default();
|
||||||
self.cmd_buffer.label = label.map(str::to_string);
|
self.cmd_buffer.label = label.map(str::to_string);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -63,18 +136,22 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut combined_usage = crate::TextureUse::empty();
|
||||||
for bar in barriers {
|
for bar in barriers {
|
||||||
// GLES only synchronizes storage -> anything explicitly
|
// GLES only synchronizes storage -> anything explicitly
|
||||||
if !bar.usage.start.contains(crate::TextureUse::STORAGE_STORE) {
|
if !bar.usage.start.contains(crate::TextureUse::STORAGE_STORE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let raw = match bar.texture.inner {
|
// unlike buffers, there is no need for a concrete texture
|
||||||
super::TextureInner::Texture { raw, .. } => raw,
|
// object to be bound anywhere for a barrier
|
||||||
super::TextureInner::Renderbuffer { .. } => continue,
|
combined_usage |= bar.usage.end;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
if !combined_usage.is_empty() {
|
||||||
self.cmd_buffer
|
self.cmd_buffer
|
||||||
.commands
|
.commands
|
||||||
.push(C::TextureBarrier(raw, bar.usage.end));
|
.push(C::TextureBarrier(combined_usage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,9 +312,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set the framebuffer
|
// set the framebuffer
|
||||||
self.cmd_buffer
|
self.cmd_buffer.commands.push(C::ResetFramebuffer);
|
||||||
.commands
|
|
||||||
.push(C::ResetFramebuffer(desc.extent));
|
|
||||||
for (i, cat) in desc.color_attachments.iter().enumerate() {
|
for (i, cat) in desc.color_attachments.iter().enumerate() {
|
||||||
let attachment = glow::COLOR_ATTACHMENT0 + i as u32;
|
let attachment = glow::COLOR_ATTACHMENT0 + i as u32;
|
||||||
self.cmd_buffer.commands.push(C::SetFramebufferAttachment {
|
self.cmd_buffer.commands.push(C::SetFramebufferAttachment {
|
||||||
@ -257,9 +332,22 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the draw buffers and states
|
||||||
self.cmd_buffer
|
self.cmd_buffer
|
||||||
.commands
|
.commands
|
||||||
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
|
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
|
||||||
|
let rect = crate::Rect {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
w: desc.extent.width as i32,
|
||||||
|
h: desc.extent.height as i32,
|
||||||
|
};
|
||||||
|
self.cmd_buffer.commands.push(C::SetScissor(rect.clone()));
|
||||||
|
self.cmd_buffer.commands.push(C::SetViewport {
|
||||||
|
rect,
|
||||||
|
depth: 0.0..1.0,
|
||||||
|
});
|
||||||
|
|
||||||
// issue the clears
|
// issue the clears
|
||||||
for (i, cat) in desc.color_attachments.iter().enumerate() {
|
for (i, cat) in desc.color_attachments.iter().enumerate() {
|
||||||
if !cat.ops.contains(crate::AttachmentOp::LOAD) {
|
if !cat.ops.contains(crate::AttachmentOp::LOAD) {
|
||||||
@ -302,6 +390,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
self.cmd_buffer.commands.push(C::PopDebugGroup);
|
self.cmd_buffer.commands.push(C::PopDebugGroup);
|
||||||
self.state.has_pass_label = false;
|
self.state.has_pass_label = false;
|
||||||
}
|
}
|
||||||
|
self.state.dirty = Dirty::empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn set_bind_group(
|
unsafe fn set_bind_group(
|
||||||
@ -335,6 +424,46 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
|
|
||||||
unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) {
|
unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) {
|
||||||
self.state.topology = conv::map_primitive_topology(pipeline.primitive.topology);
|
self.state.topology = conv::map_primitive_topology(pipeline.primitive.topology);
|
||||||
|
self.state.dirty |= Dirty::VERTEX_BUFFERS;
|
||||||
|
|
||||||
|
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
|
||||||
|
.state
|
||||||
|
.vertex_buffers
|
||||||
|
.iter_mut()
|
||||||
|
.zip(pipeline.vertex_buffers.iter())
|
||||||
|
{
|
||||||
|
state_desc.step = pipe_desc.step;
|
||||||
|
state_desc.stride = pipe_desc.stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref stencil) = pipeline.stencil {
|
||||||
|
self.state.stencil = stencil.clone();
|
||||||
|
self.rebind_stencil_func();
|
||||||
|
if stencil.front.ops == stencil.back.ops
|
||||||
|
&& stencil.front.mask_write == stencil.back.mask_write
|
||||||
|
{
|
||||||
|
self.cmd_buffer.commands.push(C::SetStencilOps {
|
||||||
|
face: glow::FRONT_AND_BACK,
|
||||||
|
write_mask: stencil.front.mask_write,
|
||||||
|
ops: stencil.front.ops.clone(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.cmd_buffer.commands.push(C::SetStencilOps {
|
||||||
|
face: glow::FRONT,
|
||||||
|
write_mask: stencil.front.mask_write,
|
||||||
|
ops: stencil.front.ops.clone(),
|
||||||
|
});
|
||||||
|
self.cmd_buffer.commands.push(C::SetStencilOps {
|
||||||
|
face: glow::BACK,
|
||||||
|
write_mask: stencil.back.mask_write,
|
||||||
|
ops: stencil.back.ops.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn set_index_buffer<'a>(
|
unsafe fn set_index_buffer<'a>(
|
||||||
@ -353,10 +482,35 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
index: u32,
|
index: u32,
|
||||||
binding: crate::BufferBinding<'a, super::Api>,
|
binding: crate::BufferBinding<'a, super::Api>,
|
||||||
) {
|
) {
|
||||||
|
self.state.dirty |= Dirty::VERTEX_BUFFERS;
|
||||||
|
let vb = &mut self.state.vertex_buffers[index as usize];
|
||||||
|
vb.raw = binding.buffer.raw;
|
||||||
|
vb.offset = binding.offset;
|
||||||
|
}
|
||||||
|
unsafe fn set_viewport(&mut self, rect: &crate::Rect<f32>, depth: Range<f32>) {
|
||||||
|
self.cmd_buffer.commands.push(C::SetViewport {
|
||||||
|
rect: crate::Rect {
|
||||||
|
x: rect.x as i32,
|
||||||
|
y: rect.y as i32,
|
||||||
|
w: rect.w as i32,
|
||||||
|
h: rect.h as i32,
|
||||||
|
},
|
||||||
|
depth,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect<u32>) {
|
||||||
|
self.cmd_buffer.commands.push(C::SetScissor(crate::Rect {
|
||||||
|
x: rect.x as i32,
|
||||||
|
y: rect.y as i32,
|
||||||
|
w: rect.w as i32,
|
||||||
|
h: rect.h as i32,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
unsafe fn set_stencil_reference(&mut self, value: u32) {
|
||||||
|
self.state.stencil.front.reference = value;
|
||||||
|
self.state.stencil.back.reference = value;
|
||||||
|
self.rebind_stencil_func();
|
||||||
}
|
}
|
||||||
unsafe fn set_viewport(&mut self, rect: &crate::Rect<f32>, depth_range: Range<f32>) {}
|
|
||||||
unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect<u32>) {}
|
|
||||||
unsafe fn set_stencil_reference(&mut self, value: u32) {}
|
|
||||||
unsafe fn set_blend_constants(&mut self, color: &wgt::Color) {}
|
unsafe fn set_blend_constants(&mut self, color: &wgt::Color) {}
|
||||||
|
|
||||||
unsafe fn draw(
|
unsafe fn draw(
|
||||||
@ -366,7 +520,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
start_instance: u32,
|
start_instance: u32,
|
||||||
instance_count: u32,
|
instance_count: u32,
|
||||||
) {
|
) {
|
||||||
debug_assert_eq!(start_instance, 0);
|
self.prepare_draw(start_instance);
|
||||||
self.cmd_buffer.commands.push(C::Draw {
|
self.cmd_buffer.commands.push(C::Draw {
|
||||||
topology: self.state.topology,
|
topology: self.state.topology,
|
||||||
start_vertex,
|
start_vertex,
|
||||||
@ -382,7 +536,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
start_instance: u32,
|
start_instance: u32,
|
||||||
instance_count: u32,
|
instance_count: u32,
|
||||||
) {
|
) {
|
||||||
debug_assert_eq!(start_instance, 0);
|
self.prepare_draw(start_instance);
|
||||||
let (index_size, index_type) = match self.state.index_format {
|
let (index_size, index_type) = match self.state.index_format {
|
||||||
wgt::IndexFormat::Uint16 => (2, glow::UNSIGNED_SHORT),
|
wgt::IndexFormat::Uint16 => (2, glow::UNSIGNED_SHORT),
|
||||||
wgt::IndexFormat::Uint32 => (4, glow::UNSIGNED_INT),
|
wgt::IndexFormat::Uint32 => (4, glow::UNSIGNED_INT),
|
||||||
@ -403,6 +557,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
offset: wgt::BufferAddress,
|
offset: wgt::BufferAddress,
|
||||||
draw_count: u32,
|
draw_count: u32,
|
||||||
) {
|
) {
|
||||||
|
self.prepare_draw(0);
|
||||||
for draw in 0..draw_count as wgt::BufferAddress {
|
for draw in 0..draw_count as wgt::BufferAddress {
|
||||||
let indirect_offset =
|
let indirect_offset =
|
||||||
offset + draw * mem::size_of::<wgt::DrawIndirectArgs>() as wgt::BufferAddress;
|
offset + draw * mem::size_of::<wgt::DrawIndirectArgs>() as wgt::BufferAddress;
|
||||||
@ -419,6 +574,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
offset: wgt::BufferAddress,
|
offset: wgt::BufferAddress,
|
||||||
draw_count: u32,
|
draw_count: u32,
|
||||||
) {
|
) {
|
||||||
|
self.prepare_draw(0);
|
||||||
let index_type = match self.state.index_format {
|
let index_type = match self.state.index_format {
|
||||||
wgt::IndexFormat::Uint16 => glow::UNSIGNED_SHORT,
|
wgt::IndexFormat::Uint16 => glow::UNSIGNED_SHORT,
|
||||||
wgt::IndexFormat::Uint32 => glow::UNSIGNED_INT,
|
wgt::IndexFormat::Uint32 => glow::UNSIGNED_INT,
|
||||||
@ -469,6 +625,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||||||
self.cmd_buffer.commands.push(C::PopDebugGroup);
|
self.cmd_buffer.commands.push(C::PopDebugGroup);
|
||||||
self.state.has_pass_label = false;
|
self.state.has_pass_label = false;
|
||||||
}
|
}
|
||||||
|
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) {}
|
||||||
|
|||||||
@ -232,3 +232,44 @@ pub fn map_view_dimension(dim: wgt::TextureViewDimension) -> u32 {
|
|||||||
Tvd::D3 => glow::TEXTURE_3D,
|
Tvd::D3 => glow::TEXTURE_3D,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn map_stencil_op(operation: wgt::StencilOperation) -> u32 {
|
||||||
|
use wgt::StencilOperation as So;
|
||||||
|
match operation {
|
||||||
|
So::Keep => glow::KEEP,
|
||||||
|
So::Zero => glow::ZERO,
|
||||||
|
So::Replace => glow::REPLACE,
|
||||||
|
So::Invert => glow::INVERT,
|
||||||
|
So::IncrementClamp => glow::INCR,
|
||||||
|
So::DecrementClamp => glow::DECR,
|
||||||
|
So::IncrementWrap => glow::INCR_WRAP,
|
||||||
|
So::DecrementWrap => glow::DECR_WRAP,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_stencil_ops(face: &wgt::StencilFaceState) -> super::StencilOps {
|
||||||
|
super::StencilOps {
|
||||||
|
pass: map_stencil_op(face.pass_op),
|
||||||
|
fail: map_stencil_op(face.fail_op),
|
||||||
|
depth_fail: map_stencil_op(face.depth_fail_op),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn map_stencil(state: &wgt::StencilState) -> super::StencilState {
|
||||||
|
super::StencilState {
|
||||||
|
front: super::StencilSide {
|
||||||
|
function: map_compare_func(state.front.compare),
|
||||||
|
mask_read: state.read_mask,
|
||||||
|
mask_write: state.write_mask,
|
||||||
|
reference: 0,
|
||||||
|
ops: map_stencil_ops(&state.front),
|
||||||
|
},
|
||||||
|
back: super::StencilSide {
|
||||||
|
function: map_compare_func(state.back.compare),
|
||||||
|
mask_read: state.read_mask,
|
||||||
|
mask_write: state.write_mask,
|
||||||
|
reference: 0,
|
||||||
|
ops: map_stencil_ops(&state.back),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -518,7 +518,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
) -> Result<super::CommandEncoder, crate::DeviceError> {
|
) -> Result<super::CommandEncoder, crate::DeviceError> {
|
||||||
Ok(super::CommandEncoder {
|
Ok(super::CommandEncoder {
|
||||||
cmd_buffer: super::CommandBuffer::default(),
|
cmd_buffer: super::CommandBuffer::default(),
|
||||||
state: super::CommandState::default(),
|
state: Default::default(),
|
||||||
private_caps: self.shared.private_caps,
|
private_caps: self.shared.private_caps,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -665,11 +665,16 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
);
|
);
|
||||||
let inner = self.create_pipeline(shaders, desc.layout)?;
|
let inner = self.create_pipeline(shaders, desc.layout)?;
|
||||||
|
|
||||||
let attributes = {
|
let (vertex_buffers, vertex_attributes) = {
|
||||||
let gl = &self.shared.context;
|
let mut buffers = Vec::new();
|
||||||
let mut attributes = Vec::new();
|
let mut attributes = Vec::new();
|
||||||
|
|
||||||
for (index, vb_layout) in desc.vertex_buffers.iter().enumerate() {
|
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,
|
||||||
|
});
|
||||||
for vat in vb_layout.attributes.iter() {
|
for vat in vb_layout.attributes.iter() {
|
||||||
let format_desc = conv::describe_vertex_format(vat.format);
|
let format_desc = conv::describe_vertex_format(vat.format);
|
||||||
attributes.push(super::AttributeDesc {
|
attributes.push(super::AttributeDesc {
|
||||||
@ -680,15 +685,23 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(buffers.into_boxed_slice(), attributes.into_boxed_slice())
|
||||||
attributes.into_boxed_slice()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(super::RenderPipeline {
|
Ok(super::RenderPipeline {
|
||||||
inner,
|
inner,
|
||||||
primitive: desc.primitive,
|
primitive: desc.primitive,
|
||||||
attributes,
|
vertex_buffers,
|
||||||
depth: desc.depth_stencil.clone(),
|
vertex_attributes,
|
||||||
|
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),
|
||||||
|
stencil: desc
|
||||||
|
.depth_stencil
|
||||||
|
.as_ref()
|
||||||
|
.map(|ds| conv::map_stencil(&ds.stencil)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
|
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
|
||||||
|
|||||||
@ -22,6 +22,7 @@ pub struct Api;
|
|||||||
//Note: we can support more samplers if not every one of them is used at a time,
|
//Note: we can support more samplers if not every one of them is used at a time,
|
||||||
// but it probably doesn't worth it.
|
// but it probably doesn't worth it.
|
||||||
const MAX_TEXTURE_SLOTS: usize = 16;
|
const MAX_TEXTURE_SLOTS: usize = 16;
|
||||||
|
const MAX_VERTEX_ATTRIBUTES: usize = 16;
|
||||||
|
|
||||||
impl crate::Api for Api {
|
impl crate::Api for Api {
|
||||||
type Instance = Instance;
|
type Instance = Instance;
|
||||||
@ -159,6 +160,12 @@ enum VertexAttribKind {
|
|||||||
//Double, // glVertexAttribLPointer
|
//Double, // glVertexAttribLPointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for VertexAttribKind {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Float
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TextureFormatDesc {
|
struct TextureFormatDesc {
|
||||||
internal: u32,
|
internal: u32,
|
||||||
@ -296,12 +303,14 @@ pub struct ShaderModule {
|
|||||||
naga: crate::NagaShader,
|
naga: crate::NagaShader,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
struct VertexFormatDesc {
|
struct VertexFormatDesc {
|
||||||
element_count: i32,
|
element_count: i32,
|
||||||
element_format: u32,
|
element_format: u32,
|
||||||
attrib_kind: VertexAttribKind,
|
attrib_kind: VertexAttribKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
struct AttributeDesc {
|
struct AttributeDesc {
|
||||||
location: u32,
|
location: u32,
|
||||||
offset: u32,
|
offset: u32,
|
||||||
@ -309,6 +318,14 @@ struct AttributeDesc {
|
|||||||
format_desc: VertexFormatDesc,
|
format_desc: VertexFormatDesc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
struct VertexBufferDesc {
|
||||||
|
raw: glow::Buffer,
|
||||||
|
offset: wgt::BufferAddress,
|
||||||
|
step: wgt::InputStepMode,
|
||||||
|
stride: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct UniformDesc {
|
struct UniformDesc {
|
||||||
location: glow::UniformLocation,
|
location: glow::UniformLocation,
|
||||||
@ -326,13 +343,20 @@ struct PipelineInner {
|
|||||||
uniforms: Box<[UniformDesc]>,
|
uniforms: Box<[UniformDesc]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DepthState {
|
||||||
|
function: u32,
|
||||||
|
mask: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct RenderPipeline {
|
pub struct RenderPipeline {
|
||||||
inner: PipelineInner,
|
inner: PipelineInner,
|
||||||
//blend_targets: Vec<pso::ColorBlendDesc>,
|
//blend_targets: Vec<pso::ColorBlendDesc>,
|
||||||
attributes: Box<[AttributeDesc]>,
|
vertex_buffers: Box<[VertexBufferDesc]>,
|
||||||
//vertex_buffers: Box<[wgt::VertexBufferLayout]>,
|
vertex_attributes: Box<[AttributeDesc]>,
|
||||||
primitive: wgt::PrimitiveState,
|
primitive: wgt::PrimitiveState,
|
||||||
depth: Option<wgt::DepthStencilState>,
|
depth: Option<DepthState>,
|
||||||
|
depth_bias: Option<wgt::DepthBiasState>,
|
||||||
|
stencil: Option<StencilState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ComputePipeline {
|
pub struct ComputePipeline {
|
||||||
@ -387,6 +411,50 @@ struct TextureCopyInfo {
|
|||||||
texel_size: u8,
|
texel_size: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
struct StencilOps {
|
||||||
|
pass: u32,
|
||||||
|
fail: u32,
|
||||||
|
depth_fail: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StencilOps {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
pass: glow::KEEP,
|
||||||
|
fail: glow::KEEP,
|
||||||
|
depth_fail: glow::KEEP,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
struct StencilSide {
|
||||||
|
function: u32,
|
||||||
|
mask_read: u32,
|
||||||
|
mask_write: u32,
|
||||||
|
reference: u32,
|
||||||
|
ops: StencilOps,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StencilSide {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
function: glow::ALWAYS,
|
||||||
|
mask_read: 0xFF,
|
||||||
|
mask_write: 0xFF,
|
||||||
|
reference: 0,
|
||||||
|
ops: StencilOps::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
struct StencilState {
|
||||||
|
front: StencilSide,
|
||||||
|
back: StencilSide,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Command {
|
enum Command {
|
||||||
Draw {
|
Draw {
|
||||||
@ -463,7 +531,7 @@ enum Command {
|
|||||||
dst_target: BindTarget,
|
dst_target: BindTarget,
|
||||||
dst_offset: wgt::BufferAddress,
|
dst_offset: wgt::BufferAddress,
|
||||||
},
|
},
|
||||||
ResetFramebuffer(wgt::Extent3d),
|
ResetFramebuffer,
|
||||||
SetFramebufferAttachment {
|
SetFramebufferAttachment {
|
||||||
attachment: u32,
|
attachment: u32,
|
||||||
view: TextureView,
|
view: TextureView,
|
||||||
@ -475,7 +543,24 @@ enum Command {
|
|||||||
ClearDepth(f32),
|
ClearDepth(f32),
|
||||||
ClearStencil(u32),
|
ClearStencil(u32),
|
||||||
BufferBarrier(glow::Buffer, crate::BufferUse),
|
BufferBarrier(glow::Buffer, crate::BufferUse),
|
||||||
TextureBarrier(glow::Texture, crate::TextureUse),
|
TextureBarrier(crate::TextureUse),
|
||||||
|
SetViewport {
|
||||||
|
rect: crate::Rect<i32>,
|
||||||
|
depth: Range<f32>,
|
||||||
|
},
|
||||||
|
SetScissor(crate::Rect<i32>),
|
||||||
|
SetStencilFunc {
|
||||||
|
face: u32,
|
||||||
|
function: u32,
|
||||||
|
reference: u32,
|
||||||
|
read_mask: u32,
|
||||||
|
},
|
||||||
|
SetStencilOps {
|
||||||
|
face: u32,
|
||||||
|
write_mask: u32,
|
||||||
|
ops: StencilOps,
|
||||||
|
},
|
||||||
|
SetVertexAttribute(AttributeDesc, VertexBufferDesc),
|
||||||
InsertDebugMarker(Range<u32>),
|
InsertDebugMarker(Range<u32>),
|
||||||
PushDebugGroup(Range<u32>),
|
PushDebugGroup(Range<u32>),
|
||||||
PopDebugGroup,
|
PopDebugGroup,
|
||||||
@ -489,20 +574,12 @@ pub struct CommandBuffer {
|
|||||||
data_words: Vec<u32>,
|
data_words: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct CommandState {
|
|
||||||
topology: u32,
|
|
||||||
index_format: wgt::IndexFormat,
|
|
||||||
index_offset: wgt::BufferAddress,
|
|
||||||
has_pass_label: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: we would have something like `Arc<typed_arena::Arena>`
|
//TODO: we would have something like `Arc<typed_arena::Arena>`
|
||||||
// here and in the command buffers. So that everything grows
|
// here and in the command buffers. So that everything grows
|
||||||
// inside the encoder and stays there until `reset_all`.
|
// inside the encoder and stays there until `reset_all`.
|
||||||
|
|
||||||
pub struct CommandEncoder {
|
pub struct CommandEncoder {
|
||||||
cmd_buffer: CommandBuffer,
|
cmd_buffer: CommandBuffer,
|
||||||
state: CommandState,
|
state: command::State,
|
||||||
private_caps: PrivateCapability,
|
private_caps: PrivateCapability,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -292,7 +292,7 @@ impl super::Queue {
|
|||||||
gl.bind_buffer(dst_target, Some(dst));
|
gl.bind_buffer(dst_target, Some(dst));
|
||||||
gl.buffer_sub_data_u8_slice(dst_target, dst_offset as i32, query_data);
|
gl.buffer_sub_data_u8_slice(dst_target, dst_offset as i32, query_data);
|
||||||
}
|
}
|
||||||
C::ResetFramebuffer(extent) => {
|
C::ResetFramebuffer => {
|
||||||
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.draw_fbo));
|
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.draw_fbo));
|
||||||
gl.framebuffer_texture_2d(
|
gl.framebuffer_texture_2d(
|
||||||
glow::DRAW_FRAMEBUFFER,
|
glow::DRAW_FRAMEBUFFER,
|
||||||
@ -317,8 +317,6 @@ impl super::Queue {
|
|||||||
gl.disable(glow::DEPTH_TEST);
|
gl.disable(glow::DEPTH_TEST);
|
||||||
gl.disable(glow::STENCIL_TEST);
|
gl.disable(glow::STENCIL_TEST);
|
||||||
gl.disable(glow::SCISSOR_TEST);
|
gl.disable(glow::SCISSOR_TEST);
|
||||||
gl.scissor(0, 0, extent.width as i32, extent.height as i32);
|
|
||||||
gl.viewport(0, 0, extent.width as i32, extent.height as i32);
|
|
||||||
}
|
}
|
||||||
C::SetFramebufferAttachment {
|
C::SetFramebufferAttachment {
|
||||||
attachment,
|
attachment,
|
||||||
@ -409,7 +407,7 @@ impl super::Queue {
|
|||||||
}
|
}
|
||||||
gl.memory_barrier(flags);
|
gl.memory_barrier(flags);
|
||||||
}
|
}
|
||||||
C::TextureBarrier(_raw, usage) => {
|
C::TextureBarrier(usage) => {
|
||||||
let mut flags = 0;
|
let mut flags = 0;
|
||||||
if usage.contains(crate::TextureUse::SAMPLED) {
|
if usage.contains(crate::TextureUse::SAMPLED) {
|
||||||
flags |= glow::TEXTURE_FETCH_BARRIER_BIT;
|
flags |= glow::TEXTURE_FETCH_BARRIER_BIT;
|
||||||
@ -431,6 +429,55 @@ impl super::Queue {
|
|||||||
}
|
}
|
||||||
gl.memory_barrier(flags);
|
gl.memory_barrier(flags);
|
||||||
}
|
}
|
||||||
|
C::SetViewport {
|
||||||
|
ref rect,
|
||||||
|
ref depth,
|
||||||
|
} => {
|
||||||
|
gl.viewport(rect.x, rect.y, rect.w, rect.h);
|
||||||
|
gl.depth_range_f32(depth.start, depth.end);
|
||||||
|
}
|
||||||
|
C::SetScissor(ref rect) => {
|
||||||
|
gl.scissor(rect.x, rect.y, rect.w, rect.h);
|
||||||
|
}
|
||||||
|
C::SetStencilFunc {
|
||||||
|
face,
|
||||||
|
function,
|
||||||
|
reference,
|
||||||
|
read_mask,
|
||||||
|
} => {
|
||||||
|
gl.stencil_func_separate(face, function, reference as i32, read_mask);
|
||||||
|
}
|
||||||
|
C::SetStencilOps {
|
||||||
|
face,
|
||||||
|
write_mask,
|
||||||
|
ref ops,
|
||||||
|
} => {
|
||||||
|
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;
|
||||||
|
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,
|
||||||
|
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,
|
||||||
|
offset,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
gl.vertex_attrib_divisor(vat.location, vb.step as u32);
|
||||||
|
gl.enable_vertex_attrib_array(vat.location);
|
||||||
|
}
|
||||||
C::InsertDebugMarker(ref range) => {
|
C::InsertDebugMarker(ref range) => {
|
||||||
let marker = extract_marker(data_bytes, range);
|
let marker = extract_marker(data_bytes, range);
|
||||||
gl.debug_message_insert(
|
gl.debug_message_insert(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user