116: Validation bits from 0.2 r=kvark a=kvark

Sibling of #114 

Co-authored-by: Dzmitry Malyshau <dmalyshau@mozilla.com>
This commit is contained in:
bors[bot] 2019-04-01 00:08:02 +00:00
commit 81ff6fac05
16 changed files with 295 additions and 79 deletions

View File

@ -1,5 +1,11 @@
# Change Log
## v0.2.5 (31-03-2019)
- fixed submission tracking
- added support for blend colors
- fixed bind group compatibility at the gfx-hal level
- validating the bind groups and blend colors
## v0.2.3 (20-03-2019)
- fixed vertex format mapping
- fixed building with "empty" backend on Windows

14
Cargo.lock generated
View File

@ -325,8 +325,8 @@ name = "examples"
version = "0.1.0"
dependencies = [
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
"wgpu 0.2.1",
"wgpu-native 0.2.4",
"wgpu 0.2.2",
"wgpu-native 0.2.5",
]
[[package]]
@ -503,7 +503,7 @@ dependencies = [
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
"glsl-to-spirv 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"wgpu 0.2.1",
"wgpu 0.2.2",
]
[[package]]
@ -1389,10 +1389,10 @@ dependencies = [
[[package]]
name = "wgpu"
version = "0.2.1"
version = "0.2.2"
dependencies = [
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"wgpu-native 0.2.4",
"wgpu-native 0.2.5",
]
[[package]]
@ -1404,7 +1404,7 @@ dependencies = [
[[package]]
name = "wgpu-native"
version = "0.2.4"
version = "0.2.5"
dependencies = [
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1431,7 +1431,7 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
"wgpu-native 0.2.4",
"wgpu-native 0.2.5",
]
[[package]]

View File

@ -73,6 +73,14 @@ int main() {
.bindings = NULL,
.bindings_length = 0,
});
WGPUBindGroupId bind_group =
wgpu_device_create_bind_group(device,
&(WGPUBindGroupDescriptor){
.layout = bind_group_layout,
.bindings = NULL,
.bindings_length = 0,
});
WGPUBindGroupLayoutId bind_group_layouts[BIND_GROUP_LAYOUTS_LENGTH] = {
bind_group_layout};
@ -211,6 +219,7 @@ int main() {
});
wgpu_render_pass_set_pipeline(rpass, render_pipeline);
wgpu_render_pass_set_bind_group(rpass, 0, bind_group);
wgpu_render_pass_draw(rpass, 3, 1, 0, 0);
WGPUQueueId queue = wgpu_device_get_queue(device);
WGPUCommandBufferId cmd_buf = wgpu_render_pass_end_pass(rpass);

View File

@ -21,6 +21,10 @@ fn main() {
let bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { bindings: &[] });
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
bindings: &[],
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout],
});
@ -113,6 +117,7 @@ fn main() {
depth_stencil_attachment: None,
});
rpass.set_pipeline(&render_pipeline);
rpass.set_bind_group(0, &bind_group);
rpass.draw(0..3, 0..1);
}

View File

@ -5,6 +5,8 @@
#define WGPUBITS_PER_BYTE 8
#define WGPUMAX_BIND_GROUPS 4
typedef enum {
WGPUAddressMode_ClampToEdge = 0,
WGPUAddressMode_Repeat = 1,
@ -617,6 +619,8 @@ typedef struct {
#define WGPUColor_WHITE (WGPUColor){ .r = 1, .g = 1, .b = 1, .a = 1 }
#define WGPUPipelineFlags_BLEND_COLOR 1
#define WGPUShaderStageFlags_COMPUTE 4
#define WGPUShaderStageFlags_FRAGMENT 2
@ -789,6 +793,8 @@ void wgpu_render_pass_set_bind_group(WGPURenderPassId pass_id,
uint32_t index,
WGPUBindGroupId bind_group_id);
void wgpu_render_pass_set_blend_color(WGPURenderPassId pass_id, const WGPUColor *color);
void wgpu_render_pass_set_index_buffer(WGPURenderPassId pass_id,
WGPUBufferId buffer_id,
uint32_t offset);

View File

@ -1,6 +1,6 @@
[package]
name = "wgpu-native"
version = "0.2.4"
version = "0.2.5"
authors = [
"Dzmitry Malyshau <kvark@mozilla.com>",
"Joshua Groves <josh@joshgroves.com>",

View File

@ -9,6 +9,7 @@ use hal::{
pool::RawCommandPool,
Device,
};
use log::trace;
use parking_lot::Mutex;
use std::{
@ -17,6 +18,7 @@ use std::{
thread,
};
struct CommandPool<B: hal::Backend> {
raw: B::CommandPool,
available: Vec<B::CommandBuffer>,
@ -109,7 +111,9 @@ impl<B: hal::Backend> CommandAllocator<B> {
pool.available.pop().unwrap()
}
pub fn after_submit(&self, cmd_buf: CommandBuffer<B>) {
pub fn after_submit(&self, cmd_buf: CommandBuffer<B>, submit_index: SubmissionIndex) {
cmd_buf.life_guard.submission_index
.store(submit_index, Ordering::Release);
self.inner.lock().pending.push(cmd_buf);
}
@ -122,6 +126,7 @@ impl<B: hal::Backend> CommandAllocator<B> {
.load(Ordering::Acquire);
if index <= last_done {
let cmd_buf = inner.pending.swap_remove(i);
trace!("recycling comb submitted in {} when {} is done", index, last_done);
inner.recycle(cmd_buf);
}
}

View File

@ -1,6 +1,12 @@
use crate::{BindGroupHandle, BindGroupId, BindGroupLayoutId, PipelineLayoutId, Stored};
use copyless::VecHelper as _;
use log::trace;
use std::convert::identity;
pub const MAX_BIND_GROUPS: usize = 4;
type BindGroupMask = u8;
pub struct BindGroupPair {
@ -8,6 +14,34 @@ pub struct BindGroupPair {
group_id: Stored<BindGroupId>,
}
pub enum LayoutChange {
Unchanged,
Match(BindGroupId),
Mismatch,
}
pub enum Provision {
Unchanged,
Changed {
was_compatible: bool,
now_compatible: bool,
},
}
struct TakeSome<I> {
iter: I,
}
impl<T, I> Iterator for TakeSome<I>
where
I: Iterator<Item = Option<T>>,
{
type Item = T;
fn next(&mut self) -> Option<T> {
self.iter.next().and_then(identity)
}
}
#[derive(Default)]
pub struct BindGroupEntry {
expected_layout_id: Option<BindGroupLayoutId>,
@ -15,33 +49,36 @@ pub struct BindGroupEntry {
}
impl BindGroupEntry {
fn provide(&mut self, bind_group_id: BindGroupId, bind_group: &BindGroupHandle) -> bool {
if let Some(BindGroupPair {
ref layout_id,
ref group_id,
}) = self.provided
{
if group_id.value == bind_group_id {
assert_eq!(*layout_id, bind_group.layout_id);
return false;
fn provide(&mut self, bind_group_id: BindGroupId, bind_group: &BindGroupHandle) -> Provision {
let was_compatible = match self.provided {
Some(BindGroupPair { layout_id, ref group_id }) => {
if group_id.value == bind_group_id {
assert_eq!(layout_id, bind_group.layout_id);
return Provision::Unchanged;
}
self.expected_layout_id == Some(layout_id)
}
}
None => true
};
self.provided = Some(BindGroupPair {
layout_id: bind_group.layout_id.clone(),
layout_id: bind_group.layout_id,
group_id: Stored {
value: bind_group_id,
ref_count: bind_group.life_guard.ref_count.clone(),
},
});
self.expected_layout_id == Some(bind_group.layout_id.clone())
Provision::Changed {
was_compatible,
now_compatible: self.expected_layout_id == Some(bind_group.layout_id),
}
}
pub fn expect_layout(
&mut self,
bind_group_layout_id: BindGroupLayoutId,
) -> Option<BindGroupId> {
) -> LayoutChange {
let some = Some(bind_group_layout_id);
if self.expected_layout_id != some {
self.expected_layout_id = some;
@ -49,39 +86,97 @@ impl BindGroupEntry {
Some(BindGroupPair {
layout_id,
ref group_id,
}) if layout_id == bind_group_layout_id => Some(group_id.value),
Some(_) | None => None,
}) if layout_id == bind_group_layout_id => LayoutChange::Match(group_id.value),
Some(_) | None => LayoutChange::Mismatch,
}
} else {
None
LayoutChange::Unchanged
}
}
fn is_valid(&self) -> bool {
match (self.expected_layout_id, self.provided.as_ref()) {
(None, _) => true,
(Some(_), None) => false,
(Some(layout), Some(pair)) => layout == pair.layout_id,
}
}
fn actual_value(&self) -> Option<BindGroupId> {
self.expected_layout_id
.and_then(|layout_id| self.provided.as_ref().and_then(|pair| {
if pair.layout_id == layout_id {
Some(pair.group_id.value)
} else {
None
}
}))
}
}
#[derive(Default)]
pub struct Binder {
pub(crate) pipeline_layout_id: Option<PipelineLayoutId>, //TODO: strongly `Stored`
pub(crate) entries: Vec<BindGroupEntry>,
pub(crate) entries: [BindGroupEntry; MAX_BIND_GROUPS],
}
impl Binder {
pub fn ensure_length(&mut self, length: usize) {
while self.entries.len() < length {
self.entries.alloc().init(BindGroupEntry::default());
pub(crate) fn reset_expectations(&mut self, length: usize) {
for entry in self.entries[length ..].iter_mut() {
entry.expected_layout_id = None;
}
}
pub(crate) fn provide_entry(
&mut self,
/// Attempt to set the value of the specified bind group index.
/// Returns Some() when the new bind group is ready to be actually bound
/// (i.e. compatible with current expectations). Also returns an iterator
/// of bind group IDs to be bound with it: those are compatible bind groups
/// that were previously blocked because the current one was incompatible.
pub(crate) fn provide_entry<'a>(
&'a mut self,
index: usize,
bind_group_id: BindGroupId,
bind_group: &BindGroupHandle,
) -> Option<PipelineLayoutId> {
self.ensure_length(index + 1);
if self.entries[index].provide(bind_group_id, bind_group) {
self.pipeline_layout_id.as_ref().cloned()
} else {
None
) -> Option<(PipelineLayoutId, impl 'a + Iterator<Item = BindGroupId>)> {
trace!("\tBinding [{}] = group {:?}", index, bind_group_id);
match self.entries[index].provide(bind_group_id, bind_group) {
Provision::Unchanged => {
None
}
Provision::Changed { now_compatible: false, .. } => {
trace!("\t\tnot compatible");
None
}
Provision::Changed { was_compatible, .. } => {
if self.entries[.. index].iter().all(|entry| entry.is_valid()) {
self.pipeline_layout_id.map(move |pipeline_layout_id| {
let end = if was_compatible {
trace!("\t\tgenerating follow-up sequence");
MAX_BIND_GROUPS
} else {
index + 1
};
(pipeline_layout_id, TakeSome {
iter: self.entries[index + 1 .. end]
.iter()
.map(|entry| entry.actual_value()),
})
})
} else {
trace!("\t\tbehind an incompatible");
None
}
}
}
}
pub(crate) fn invalid_mask(&self) -> BindGroupMask {
self.entries.iter().enumerate().fold(0, |mask, (i, entry)| {
if entry.is_valid() {
mask
} else {
mask | 1u8 << i
}
})
}
}

View File

@ -1,5 +1,5 @@
use crate::{
command::bind::Binder,
command::bind::{Binder, LayoutChange},
hub::HUB,
track::{Stitch, TrackerSet},
BindGroupId, CommandBuffer, CommandBufferId, ComputePassId, ComputePipelineId, Stored,
@ -73,20 +73,22 @@ pub extern "C" fn wgpu_compute_pass_set_bind_group(
&*HUB.textures.read(),
);
if let Some(pipeline_layout_id) =
if let Some((pipeline_layout_id, follow_up)) =
pass.binder
.provide_entry(index as usize, bind_group_id, bind_group)
{
let pipeline_layout_guard = HUB.pipeline_layouts.read();
let bind_groups = iter::once(&bind_group.raw)
.chain(follow_up.map(|bg_id| &bind_group_guard[bg_id].raw));
unsafe {
pass.raw.bind_compute_descriptor_sets(
&pipeline_layout_guard[pipeline_layout_id].raw,
index as usize,
iter::once(&bind_group.raw),
bind_groups,
&[],
);
}
}
};
}
#[no_mangle]
@ -109,11 +111,10 @@ pub extern "C" fn wgpu_compute_pass_set_pipeline(
let pipeline_layout_guard = HUB.pipeline_layouts.read();
let pipeline_layout = &pipeline_layout_guard[pipeline.layout_id];
let bing_group_guard = HUB.bind_groups.read();
let bind_group_guard = HUB.bind_groups.read();
pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone());
pass.binder
.ensure_length(pipeline_layout.bind_group_layout_ids.len());
pass.binder.reset_expectations(pipeline_layout.bind_group_layout_ids.len());
for (index, (entry, &bgl_id)) in pass
.binder
@ -122,8 +123,8 @@ pub extern "C" fn wgpu_compute_pass_set_pipeline(
.zip(&pipeline_layout.bind_group_layout_ids)
.enumerate()
{
if let Some(bg_id) = entry.expect_layout(bgl_id) {
let desc_set = &bing_group_guard[bg_id].raw;
if let LayoutChange::Match(bg_id) = entry.expect_layout(bgl_id) {
let desc_set = &bind_group_guard[bg_id].raw;
unsafe {
pass.raw.bind_compute_descriptor_sets(
&pipeline_layout.raw,

View File

@ -321,7 +321,7 @@ pub fn command_encoder_begin_render_pass(
.iter()
.map(|at| {
//TODO: integer types?
let value = hal::command::ClearColor::Float(conv::map_color(at.clear_color));
let value = hal::command::ClearColor::Float(conv::map_color(&at.clear_color));
hal::command::ClearValueRaw::from(hal::command::ClearValue::Color(value))
})
.chain(depth_stencil_attachment.map(|at| {

View File

@ -1,10 +1,12 @@
use crate::{
command::bind::Binder,
command::bind::{Binder, LayoutChange},
conv,
device::RenderPassContext,
hub::HUB,
pipeline::PipelineFlags,
resource::BufferUsageFlags,
track::{Stitch, TrackerSet},
BindGroupId, BufferId, CommandBuffer, CommandBufferId, RenderPassId, RenderPipelineId, Stored,
BindGroupId, BufferId, Color, CommandBuffer, CommandBufferId, RenderPassId, RenderPipelineId, Stored,
};
use hal::command::RawCommandBuffer;
@ -12,12 +14,30 @@ use hal::command::RawCommandBuffer;
use std::{iter, slice};
#[derive(Debug, PartialEq)]
enum BlendColorStatus {
Unused,
Required,
Set,
}
#[derive(Debug, PartialEq)]
enum DrawError {
MissingBlendColor,
IncompatibleBindGroup {
index: u32,
//expected: BindGroupLayoutId,
//provided: Option<(BindGroupLayoutId, BindGroupId)>,
},
}
pub struct RenderPass<B: hal::Backend> {
raw: B::CommandBuffer,
cmb_id: Stored<CommandBufferId>,
context: RenderPassContext,
binder: Binder,
trackers: TrackerSet,
blend_color_status: BlendColorStatus,
}
impl<B: hal::Backend> RenderPass<B> {
@ -32,8 +52,24 @@ impl<B: hal::Backend> RenderPass<B> {
context,
binder: Binder::default(),
trackers: TrackerSet::new(),
blend_color_status: BlendColorStatus::Unused,
}
}
fn is_ready(&self) -> Result<(), DrawError> {
//TODO: vertex buffers
let bind_mask = self.binder.invalid_mask();
if bind_mask != 0 {
//let (expected, provided) = self.binder.entries[index as usize].info();
return Err(DrawError::IncompatibleBindGroup {
index: bind_mask.trailing_zeros() as u32,
});
}
if self.blend_color_status == BlendColorStatus::Required {
return Err(DrawError::MissingBlendColor)
}
Ok(())
}
}
#[no_mangle]
@ -132,8 +168,12 @@ pub extern "C" fn wgpu_render_pass_draw(
first_vertex: u32,
first_instance: u32,
) {
let mut pass_guard = HUB.render_passes.write();
let pass = &mut pass_guard[pass_id];
pass.is_ready().unwrap();
unsafe {
HUB.render_passes.write()[pass_id].raw.draw(
pass.raw.draw(
first_vertex..first_vertex + vertex_count,
first_instance..first_instance + instance_count,
);
@ -149,8 +189,12 @@ pub extern "C" fn wgpu_render_pass_draw_indexed(
base_vertex: i32,
first_instance: u32,
) {
let mut pass_guard = HUB.render_passes.write();
let pass = &mut pass_guard[pass_id];
pass.is_ready().unwrap();
unsafe {
HUB.render_passes.write()[pass_id].raw.draw_indexed(
pass.raw.draw_indexed(
first_index..first_index + index_count,
base_vertex,
first_instance..first_instance + instance_count,
@ -171,21 +215,22 @@ pub extern "C" fn wgpu_render_pass_set_bind_group(
pass.trackers.consume_by_extend(&bind_group.used);
if let Some(pipeline_layout_id) =
if let Some((pipeline_layout_id, follow_up)) =
pass.binder
.provide_entry(index as usize, bind_group_id, bind_group)
{
let pipeline_layout_guard = HUB.pipeline_layouts.read();
let pipeline_layout = &pipeline_layout_guard[pipeline_layout_id];
let bind_groups = iter::once(&bind_group.raw)
.chain(follow_up.map(|bg_id| &bind_group_guard[bg_id].raw));
unsafe {
pass.raw.bind_graphics_descriptor_sets(
&pipeline_layout.raw,
&&pipeline_layout_guard[pipeline_layout_id].raw,
index as usize,
iter::once(&bind_group.raw),
bind_groups,
&[],
);
}
}
};
}
#[no_mangle]
@ -203,6 +248,10 @@ pub extern "C" fn wgpu_render_pass_set_pipeline(
"The render pipeline is not compatible with the pass!"
);
if pipeline.flags.contains(PipelineFlags::BLEND_COLOR) && pass.blend_color_status == BlendColorStatus::Unused {
pass.blend_color_status = BlendColorStatus::Required;
}
unsafe {
pass.raw.bind_graphics_pipeline(&pipeline.raw);
}
@ -216,8 +265,7 @@ pub extern "C" fn wgpu_render_pass_set_pipeline(
let bind_group_guard = HUB.bind_groups.read();
pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone());
pass.binder
.ensure_length(pipeline_layout.bind_group_layout_ids.len());
pass.binder.reset_expectations(pipeline_layout.bind_group_layout_ids.len());
for (index, (entry, &bgl_id)) in pass
.binder
@ -226,7 +274,7 @@ pub extern "C" fn wgpu_render_pass_set_pipeline(
.zip(&pipeline_layout.bind_group_layout_ids)
.enumerate()
{
if let Some(bg_id) = entry.expect_layout(bgl_id) {
if let LayoutChange::Match(bg_id) = entry.expect_layout(bgl_id) {
let desc_set = &bind_group_guard[bg_id].raw;
unsafe {
pass.raw.bind_graphics_descriptor_sets(
@ -239,3 +287,18 @@ pub extern "C" fn wgpu_render_pass_set_pipeline(
}
}
}
#[no_mangle]
pub extern "C" fn wgpu_render_pass_set_blend_color(
pass_id: RenderPassId,
color: &Color,
) {
let mut pass_guard = HUB.render_passes.write();
let pass = &mut pass_guard[pass_id];
pass.blend_color_status = BlendColorStatus::Set;
unsafe {
pass.raw.set_blend_constants(conv::map_color(color));
}
}

View File

@ -571,7 +571,7 @@ pub fn map_load_store_ops(
}
}
pub fn map_color(color: Color) -> hal::pso::ColorValue {
pub fn map_color(color: &Color) -> hal::pso::ColorValue {
[color.r, color.g, color.b, color.a]
}

View File

@ -138,6 +138,7 @@ impl<B: hal::Backend> DestroyedResources<B> {
for i in (0..self.active.len()).rev() {
if unsafe { device.get_fence_status(&self.active[i].fence).unwrap() } {
let a = self.active.swap_remove(i);
trace!("Active submission {} is done", a.index);
last_done = last_done.max(a.index);
self.free.extend(a.resources.into_iter().map(|(_, r)| r));
unsafe {
@ -957,6 +958,7 @@ pub fn device_create_bind_group(
.unwrap();
let alignment = match decl.ty {
binding_model::BindingType::UniformBuffer => device.limits.min_uniform_buffer_offset_alignment,
binding_model::BindingType::StorageBuffer => device.limits.min_storage_buffer_offset_alignment,
_ => panic!("Mismatched buffer binding for {:?}", decl),
};
assert_eq!(bb.offset as hal::buffer::Offset % alignment, 0,
@ -965,10 +967,12 @@ pub fn device_create_bind_group(
hal::pso::Descriptor::Buffer(&buffer.raw, range)
}
binding_model::BindingResource::Sampler(id) => {
assert_eq!(decl.ty, binding_model::BindingType::Sampler);
let sampler = &sampler_guard[id];
hal::pso::Descriptor::Sampler(&sampler.raw)
}
binding_model::BindingResource::TextureView(id) => {
assert_eq!(decl.ty, binding_model::BindingType::SampledTexture);
let view = &texture_view_guard[id];
used.views.query(id, &view.life_guard.ref_count, DummyUsage);
used.textures
@ -1087,7 +1091,7 @@ pub extern "C" fn wgpu_queue_submit(
let command_buffer_ids =
unsafe { slice::from_raw_parts(command_buffer_ptr, command_buffer_count) };
let (old_submit_index, fence) = {
let (submit_index, fence) = {
let mut device_guard = HUB.devices.write();
let device = &mut device_guard[queue_id];
@ -1098,7 +1102,7 @@ pub extern "C" fn wgpu_queue_submit(
destroyed.triage_referenced(&mut *trackers);
destroyed.triage_framebuffers(&mut *device.framebuffers.lock());
let old_submit_index = device
let submit_index = 1 + device
.life_guard
.submission_index
.fetch_add(1, Ordering::Relaxed);
@ -1117,26 +1121,23 @@ pub extern "C" fn wgpu_queue_submit(
let comb = &mut command_buffer_guard[cmb_id];
swap_chain_links.extend(comb.swap_chain_links.drain(..));
// update submission IDs
comb.life_guard
.submission_index
.store(old_submit_index, Ordering::Release);
for id in comb.trackers.buffers.used() {
buffer_guard[id]
.life_guard
.submission_index
.store(old_submit_index, Ordering::Release);
.store(submit_index, Ordering::Release);
}
for id in comb.trackers.textures.used() {
texture_guard[id]
.life_guard
.submission_index
.store(old_submit_index, Ordering::Release);
.store(submit_index, Ordering::Release);
}
for id in comb.trackers.views.used() {
texture_view_guard[id]
.life_guard
.submission_index
.store(old_submit_index, Ordering::Release);
.store(submit_index, Ordering::Release);
}
// execute resource transitions
@ -1201,7 +1202,7 @@ pub extern "C" fn wgpu_queue_submit(
}
}
(old_submit_index, fence)
(submit_index, fence)
};
// No need for write access to the device from here on out
@ -1214,7 +1215,7 @@ pub extern "C" fn wgpu_queue_submit(
destroyed.handle_mapping(&device.raw, &device.limits);
destroyed.active.alloc().init(ActiveSubmission {
index: old_submit_index + 1,
index: submit_index,
fence,
resources: Vec::new(),
mapped: Vec::new(),
@ -1230,7 +1231,7 @@ pub extern "C" fn wgpu_queue_submit(
// finally, return the command buffers to the allocator
for &cmb_id in command_buffer_ids {
let cmd_buf = HUB.command_buffers.unregister(cmb_id);
device.com_allocator.after_submit(cmd_buf);
device.com_allocator.after_submit(cmd_buf, submit_index);
}
}
@ -1435,10 +1436,16 @@ pub fn device_create_render_pipeline(
depth_stencil: depth_stencil_state.map(|state| state.format),
};
let mut flags = pipeline::PipelineFlags::empty();
if color_states.iter().any(|state| state.color.uses_color() | state.alpha.uses_color()) {
flags |= pipeline::PipelineFlags::BLEND_COLOR;
}
pipeline::RenderPipeline {
raw: pipeline,
layout_id: desc.layout,
pass_context,
flags,
}
}
@ -1754,10 +1761,7 @@ pub extern "C" fn wgpu_buffer_set_sub_data(
.com_allocator
.allocate(buffer.device_id.clone(), &device.raw);
// mark as used by the next submission, conservatively
let last_submit_index = device.life_guard.submission_index.load(Ordering::Acquire);
comb.life_guard
.submission_index
.store(last_submit_index + 1, Ordering::Release);
let submit_index = 1 + device.life_guard.submission_index.load(Ordering::Acquire);
unsafe {
let raw = comb.raw.last_mut().unwrap();
raw.begin(
@ -1786,7 +1790,7 @@ pub extern "C" fn wgpu_buffer_set_sub_data(
.submit::<_, _, <back::Backend as hal::Backend>::Semaphore, _, _>(submission, None);
}
device.com_allocator.after_submit(comb);
device.com_allocator.after_submit(comb, submit_index);
}
#[no_mangle]

View File

@ -63,6 +63,16 @@ impl BlendDescriptor {
dst_factor: BlendFactor::Zero,
operation: BlendOperation::Add,
};
pub fn uses_color(&self) -> bool {
match (self.src_factor, self.dst_factor) {
(BlendFactor::BlendColor, _) |
(BlendFactor::OneMinusBlendColor, _) |
(_, BlendFactor::BlendColor) |
(_, BlendFactor::OneMinusBlendColor) => true,
(_, _) => false,
}
}
}
#[repr(C)]
@ -279,8 +289,16 @@ pub struct RenderPipelineDescriptor {
pub sample_count: u32,
}
bitflags! {
#[repr(transparent)]
pub struct PipelineFlags: u32 {
const BLEND_COLOR = 1;
}
}
pub struct RenderPipeline<B: hal::Backend> {
pub(crate) raw: B::GraphicsPipeline,
pub(crate) layout_id: PipelineLayoutId,
pub(crate) pass_context: RenderPassContext,
pub(crate) flags: PipelineFlags,
}

View File

@ -1,6 +1,6 @@
[package]
name = "wgpu"
version = "0.2.1"
version = "0.2.2"
authors = [
"Dzmitry Malyshau <kvark@mozilla.com>",
"Joshua Groves <josh@joshgroves.com>",
@ -23,5 +23,5 @@ dx12 = ["wgpu-native/gfx-backend-dx12"]
vulkan = ["wgpu-native/gfx-backend-vulkan"]
[dependencies]
wgpu-native = { version = "0.2", path = "../wgpu-native", features = ["local", "window-winit"] }
wgpu-native = { version = "0.2.5", path = "../wgpu-native", features = ["local", "window-winit"] }
arrayvec = "0.4"

View File

@ -784,6 +784,10 @@ impl<'a> RenderPass<'a> {
wgn::wgpu_render_pass_set_pipeline(self.id, pipeline.id);
}
pub fn set_blend_color(&mut self, color: Color) {
wgn::wgpu_render_pass_set_blend_color(self.id, &color);
}
pub fn set_index_buffer(&mut self, buffer: &Buffer, offset: u32) {
wgn::wgpu_render_pass_set_index_buffer(self.id, buffer.id, offset);
}