use std::ops::Deref;
use std::collections::hash_set::{self, HashSet};
use {Resources, IndexType, InstanceCount, VertexCount,
SubmissionResult, SubmissionError};
use {state, target, pso, shade, texture, handle};
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum ClearColor {
Float([f32; 4]),
Int([i32; 4]),
Uint([u32; 4]),
}
pub type InstanceParams = (InstanceCount, VertexCount);
#[allow(missing_docs)]
pub trait Buffer<R: Resources>: 'static + Send {
fn reset(&mut self);
fn bind_pipeline_state(&mut self, R::PipelineStateObject);
fn bind_vertex_buffers(&mut self, pso::VertexBufferSet<R>);
fn bind_constant_buffers(&mut self, &[pso::ConstantBufferParam<R>]);
fn bind_global_constant(&mut self, shade::Location, shade::UniformValue);
fn bind_resource_views(&mut self, &[pso::ResourceViewParam<R>]);
fn bind_unordered_views(&mut self, &[pso::UnorderedViewParam<R>]);
fn bind_samplers(&mut self, &[pso::SamplerParam<R>]);
fn bind_pixel_targets(&mut self, pso::PixelTargetSet<R>);
fn bind_index(&mut self, R::Buffer, IndexType);
fn set_scissor(&mut self, target::Rect);
fn set_ref_values(&mut self, state::RefValues);
fn copy_buffer(&mut self, src: R::Buffer, dst: R::Buffer,
src_offset_bytes: usize, dst_offset_bytes: usize,
size_bytes: usize);
fn copy_buffer_to_texture(&mut self,
src: R::Buffer, src_offset_bytes: usize,
dst: texture::TextureCopyRegion<R::Texture>);
fn copy_texture_to_buffer(&mut self,
src: texture::TextureCopyRegion<R::Texture>,
dst: R::Buffer, dst_offset_bytes: usize);
fn copy_texture_to_texture(&mut self,
src: texture::TextureCopyRegion<R::Texture>,
dst: texture::TextureCopyRegion<R::Texture>);
fn update_buffer(&mut self, R::Buffer, data: &[u8], offset: usize);
fn update_texture(&mut self, texture::TextureCopyRegion<R::Texture>, data: &[u8]);
fn generate_mipmap(&mut self, R::ShaderResourceView);
fn clear_color(&mut self, R::RenderTargetView, ClearColor);
fn clear_depth_stencil(&mut self, R::DepthStencilView,
Option<target::Depth>, Option<target::Stencil>);
fn call_draw(&mut self, VertexCount, VertexCount, Option<InstanceParams>);
fn call_draw_indexed(&mut self, VertexCount, VertexCount, VertexCount, Option<InstanceParams>);
}
macro_rules! impl_clear {
{ $( $ty:ty = $sub:ident[$a:expr, $b:expr, $c:expr, $d:expr], )* } => {
$(
impl From<$ty> for ClearColor {
fn from(v: $ty) -> ClearColor {
ClearColor::$sub([v[$a], v[$b], v[$c], v[$d]])
}
}
)*
}
}
impl_clear! {
[f32; 4] = Float[0, 1, 2, 3],
[f32; 3] = Float[0, 1, 2, 0],
[f32; 2] = Float[0, 1, 0, 0],
[i32; 4] = Int [0, 1, 2, 3],
[i32; 3] = Int [0, 1, 2, 0],
[i32; 2] = Int [0, 1, 0, 0],
[u32; 4] = Uint [0, 1, 2, 3],
[u32; 3] = Uint [0, 1, 2, 0],
[u32; 2] = Uint [0, 1, 0, 0],
}
impl From<f32> for ClearColor {
fn from(v: f32) -> Self {
ClearColor::Float([v, 0.0, 0.0, 0.0])
}
}
impl From<i32> for ClearColor {
fn from(v: i32) -> Self {
ClearColor::Int([v, 0, 0, 0])
}
}
impl From<u32> for ClearColor {
fn from(v: u32) -> Self {
ClearColor::Uint([v, 0, 0, 0])
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AccessInfo<R: Resources> {
mapped_reads: HashSet<handle::RawBuffer<R>>,
mapped_writes: HashSet<handle::RawBuffer<R>>,
}
impl<R: Resources> AccessInfo<R> {
pub fn new() -> Self {
AccessInfo {
mapped_reads: HashSet::new(),
mapped_writes: HashSet::new(),
}
}
pub fn clear(&mut self) {
self.mapped_reads.clear();
self.mapped_writes.clear();
}
pub fn buffer_read(&mut self, buffer: &handle::RawBuffer<R>) {
if buffer.is_mapped() {
self.mapped_reads.insert(buffer.clone());
}
}
pub fn buffer_write(&mut self, buffer: &handle::RawBuffer<R>) {
if buffer.is_mapped() {
self.mapped_writes.insert(buffer.clone());
}
}
pub fn mapped_reads(&self) -> AccessInfoBuffers<R> {
self.mapped_reads.iter()
}
pub fn mapped_writes(&self) -> AccessInfoBuffers<R> {
self.mapped_writes.iter()
}
pub fn has_mapped_reads(&self) -> bool {
!self.mapped_reads.is_empty()
}
pub fn has_mapped_writes(&self) -> bool {
!self.mapped_writes.is_empty()
}
pub fn take_accesses(&self) -> SubmissionResult<AccessGuard<R>> {
for buffer in self.mapped_reads().chain(self.mapped_writes()) {
unsafe {
if !buffer.mapping().unwrap().take_access() {
return Err(SubmissionError::AccessOverlap);
}
}
}
Ok(AccessGuard { inner: self })
}
}
#[allow(missing_docs)]
pub type AccessInfoBuffers<'a, R> = hash_set::Iter<'a, handle::RawBuffer<R>>;
#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuard<'a, R: Resources> {
inner: &'a AccessInfo<R>,
}
#[allow(missing_docs)]
impl<'a, R: Resources> AccessGuard<'a, R> {
pub fn access_mapped_reads(&mut self) -> AccessGuardBuffers<R> {
AccessGuardBuffers {
buffers: self.inner.mapped_reads()
}
}
pub fn access_mapped_writes(&mut self) -> AccessGuardBuffers<R> {
AccessGuardBuffers {
buffers: self.inner.mapped_writes()
}
}
pub fn access_mapped(&mut self) -> AccessGuardBuffersChain<R> {
AccessGuardBuffersChain {
fst: self.inner.mapped_reads(),
snd: self.inner.mapped_writes(),
}
}
}
impl<'a, R: Resources> Deref for AccessGuard<'a, R> {
type Target = AccessInfo<R>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a, R: Resources> Drop for AccessGuard<'a, R> {
fn drop(&mut self) {
for buffer in self.inner.mapped_reads().chain(self.inner.mapped_writes()) {
unsafe {
buffer.mapping().unwrap().release_access();
}
}
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuardBuffers<'a, R: Resources> {
buffers: AccessInfoBuffers<'a, R>
}
impl<'a, R: Resources> Iterator for AccessGuardBuffers<'a, R> {
type Item = (&'a handle::RawBuffer<R>, &'a mut R::Mapping);
fn next(&mut self) -> Option<Self::Item> {
self.buffers.next().map(|buffer| unsafe {
(buffer, buffer.mapping().unwrap().use_access())
})
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuardBuffersChain<'a, R: Resources> {
fst: AccessInfoBuffers<'a, R>,
snd: AccessInfoBuffers<'a, R>
}
impl<'a, R: Resources> Iterator for AccessGuardBuffersChain<'a, R> {
type Item = (&'a handle::RawBuffer<R>, &'a mut R::Mapping);
fn next(&mut self) -> Option<Self::Item> {
self.fst.next().or_else(|| self.snd.next())
.map(|buffer| unsafe {
(buffer, buffer.mapping().unwrap().use_access())
})
}
}