gfx_core/
command.rs

1// Copyright 2014 The Gfx-rs Developers.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Command Buffer device interface
16
17use std::ops::Deref;
18use std::collections::hash_set::{self, HashSet};
19use {Resources, IndexType, InstanceCount, VertexCount,
20     SubmissionResult, SubmissionError};
21use {state, target, pso, shade, texture, handle};
22
23/// A universal clear color supporting integet formats
24/// as well as the standard floating-point.
25#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
26#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
27pub enum ClearColor {
28    /// Standard floating-point vec4 color
29    Float([f32; 4]),
30    /// Integer vector to clear ivec4 targets.
31    Int([i32; 4]),
32    /// Unsigned int vector to clear uvec4 targets.
33    Uint([u32; 4]),
34}
35
36/// Optional instance parameters: (instance count, buffer offset)
37pub type InstanceParams = (InstanceCount, VertexCount);
38
39/// An interface of the abstract command buffer. It collects commands in an
40/// efficient API-specific manner, to be ready for execution on the device.
41#[allow(missing_docs)]
42pub trait Buffer<R: Resources>: 'static + Send {
43    /// Reset the command buffer contents, retain the allocated storage
44    fn reset(&mut self);
45    /// Bind a pipeline state object
46    fn bind_pipeline_state(&mut self, R::PipelineStateObject);
47    /// Bind a complete set of vertex buffers
48    fn bind_vertex_buffers(&mut self, pso::VertexBufferSet<R>);
49    /// Bind a complete set of constant buffers
50    fn bind_constant_buffers(&mut self, &[pso::ConstantBufferParam<R>]);
51    /// Bind a global constant
52    fn bind_global_constant(&mut self, shade::Location, shade::UniformValue);
53    /// Bind a complete set of shader resource views
54    fn bind_resource_views(&mut self, &[pso::ResourceViewParam<R>]);
55    /// Bind a complete set of unordered access views
56    fn bind_unordered_views(&mut self, &[pso::UnorderedViewParam<R>]);
57    /// Bind a complete set of samplers
58    fn bind_samplers(&mut self, &[pso::SamplerParam<R>]);
59    /// Bind a complete set of pixel targets, including multiple
60    /// colors views and an optional depth/stencil view.
61    fn bind_pixel_targets(&mut self, pso::PixelTargetSet<R>);
62    /// Bind an index buffer
63    fn bind_index(&mut self, R::Buffer, IndexType);
64    /// Set scissor rectangle
65    fn set_scissor(&mut self, target::Rect);
66    /// Set reference values for the blending and stencil front/back
67    fn set_ref_values(&mut self, state::RefValues);
68    /// Copy part of a buffer to another
69    fn copy_buffer(&mut self, src: R::Buffer, dst: R::Buffer,
70                   src_offset_bytes: usize, dst_offset_bytes: usize,
71                   size_bytes: usize);
72    /// Copy part of a buffer to a texture
73    fn copy_buffer_to_texture(&mut self,
74                              src: R::Buffer, src_offset_bytes: usize,
75                              dst: texture::TextureCopyRegion<R::Texture>);
76    /// Copy part of a texture to a buffer
77    fn copy_texture_to_buffer(&mut self,
78                              src: texture::TextureCopyRegion<R::Texture>,
79                              dst: R::Buffer, dst_offset_bytes: usize);
80    /// Copy part of one texture into another
81    fn copy_texture_to_texture(&mut self,
82                               src: texture::TextureCopyRegion<R::Texture>,
83                               dst: texture::TextureCopyRegion<R::Texture>);
84    /// Update a vertex/index/uniform buffer
85    fn update_buffer(&mut self, R::Buffer, data: &[u8], offset: usize);
86    /// Update a texture
87    fn update_texture(&mut self, texture::TextureCopyRegion<R::Texture>, data: &[u8]);
88    fn generate_mipmap(&mut self, R::ShaderResourceView);
89    /// Clear color target
90    fn clear_color(&mut self, R::RenderTargetView, ClearColor);
91    fn clear_depth_stencil(&mut self, R::DepthStencilView,
92                           Option<target::Depth>, Option<target::Stencil>);
93    /// Draw a primitive
94    fn call_draw(&mut self, VertexCount, VertexCount, Option<InstanceParams>);
95    /// Draw a primitive with index buffer
96    fn call_draw_indexed(&mut self, VertexCount, VertexCount, VertexCount, Option<InstanceParams>);
97}
98
99macro_rules! impl_clear {
100    { $( $ty:ty = $sub:ident[$a:expr, $b:expr, $c:expr, $d:expr], )* } => {
101        $(
102            impl From<$ty> for ClearColor {
103                fn from(v: $ty) -> ClearColor {
104                    ClearColor::$sub([v[$a], v[$b], v[$c], v[$d]])
105                }
106            }
107        )*
108    }
109}
110
111impl_clear! {
112    [f32; 4] = Float[0, 1, 2, 3],
113    [f32; 3] = Float[0, 1, 2, 0],
114    [f32; 2] = Float[0, 1, 0, 0],
115    [i32; 4] = Int  [0, 1, 2, 3],
116    [i32; 3] = Int  [0, 1, 2, 0],
117    [i32; 2] = Int  [0, 1, 0, 0],
118    [u32; 4] = Uint [0, 1, 2, 3],
119    [u32; 3] = Uint [0, 1, 2, 0],
120    [u32; 2] = Uint [0, 1, 0, 0],
121}
122
123impl From<f32> for ClearColor {
124    fn from(v: f32) -> Self {
125        ClearColor::Float([v, 0.0, 0.0, 0.0])
126    }
127}
128impl From<i32> for ClearColor {
129    fn from(v: i32) -> Self {
130        ClearColor::Int([v, 0, 0, 0])
131    }
132}
133impl From<u32> for ClearColor {
134    fn from(v: u32) -> Self {
135        ClearColor::Uint([v, 0, 0, 0])
136    }
137}
138
139/// Informations about what is accessed by a bunch of commands.
140#[derive(Clone, Debug, Eq, PartialEq)]
141pub struct AccessInfo<R: Resources> {
142    mapped_reads: HashSet<handle::RawBuffer<R>>,
143    mapped_writes: HashSet<handle::RawBuffer<R>>,
144}
145
146impl<R: Resources> AccessInfo<R> {
147    /// Creates empty access informations
148    pub fn new() -> Self {
149        AccessInfo {
150            mapped_reads: HashSet::new(),
151            mapped_writes: HashSet::new(),
152        }
153    }
154
155    /// Clear access informations
156    pub fn clear(&mut self) {
157        self.mapped_reads.clear();
158        self.mapped_writes.clear();
159    }
160
161    /// Register a buffer read access
162    pub fn buffer_read(&mut self, buffer: &handle::RawBuffer<R>) {
163        if buffer.is_mapped() {
164            self.mapped_reads.insert(buffer.clone());
165        }
166    }
167
168    /// Register a buffer write access
169    pub fn buffer_write(&mut self, buffer: &handle::RawBuffer<R>) {
170        if buffer.is_mapped() {
171            self.mapped_writes.insert(buffer.clone());
172        }
173    }
174
175    /// Returns the mapped buffers that The GPU will read from
176    pub fn mapped_reads(&self) -> AccessInfoBuffers<R> {
177        self.mapped_reads.iter()
178    }
179
180    /// Returns the mapped buffers that The GPU will write to
181    pub fn mapped_writes(&self) -> AccessInfoBuffers<R> {
182        self.mapped_writes.iter()
183    }
184
185    /// Is there any mapped buffer reads ?
186    pub fn has_mapped_reads(&self) -> bool {
187        !self.mapped_reads.is_empty()
188    }
189
190    /// Is there any mapped buffer writes ?
191    pub fn has_mapped_writes(&self) -> bool {
192        !self.mapped_writes.is_empty()
193    }
194
195    /// Takes all the accesses necessary for submission
196    pub fn take_accesses(&self) -> SubmissionResult<AccessGuard<R>> {
197        for buffer in self.mapped_reads().chain(self.mapped_writes()) {
198            unsafe {
199                if !buffer.mapping().unwrap().take_access() {
200                    return Err(SubmissionError::AccessOverlap);
201                }
202            }
203        }
204        Ok(AccessGuard { inner: self })
205    }
206}
207
208#[allow(missing_docs)]
209pub type AccessInfoBuffers<'a, R> = hash_set::Iter<'a, handle::RawBuffer<R>>;
210
211#[allow(missing_docs)]
212#[derive(Debug)]
213pub struct AccessGuard<'a, R: Resources> {
214    inner: &'a AccessInfo<R>,
215}
216
217#[allow(missing_docs)]
218impl<'a, R: Resources> AccessGuard<'a, R> {
219    /// Returns the mapped buffers that The GPU will read from,
220    /// with exclusive acces to their mapping
221    pub fn access_mapped_reads(&mut self) -> AccessGuardBuffers<R> {
222        AccessGuardBuffers {
223            buffers: self.inner.mapped_reads()
224        }
225    }
226
227    /// Returns the mapped buffers that The GPU will write to,
228    /// with exclusive acces to their mapping
229    pub fn access_mapped_writes(&mut self) -> AccessGuardBuffers<R> {
230        AccessGuardBuffers {
231            buffers: self.inner.mapped_writes()
232        }
233    }
234
235    pub fn access_mapped(&mut self) -> AccessGuardBuffersChain<R> {
236        AccessGuardBuffersChain {
237            fst: self.inner.mapped_reads(),
238            snd: self.inner.mapped_writes(),
239        }
240    }
241}
242
243impl<'a, R: Resources> Deref for AccessGuard<'a, R> {
244    type Target = AccessInfo<R>;
245    fn deref(&self) -> &Self::Target {
246        &self.inner
247    }
248}
249
250impl<'a, R: Resources> Drop for AccessGuard<'a, R> {
251    fn drop(&mut self) {
252        for buffer in self.inner.mapped_reads().chain(self.inner.mapped_writes()) {
253            unsafe {
254                buffer.mapping().unwrap().release_access();
255            }
256        }
257    }
258}
259
260#[allow(missing_docs)]
261#[derive(Debug)]
262pub struct AccessGuardBuffers<'a, R: Resources> {
263    buffers: AccessInfoBuffers<'a, R>
264}
265
266impl<'a, R: Resources> Iterator for AccessGuardBuffers<'a, R> {
267    type Item = (&'a handle::RawBuffer<R>, &'a mut R::Mapping);
268
269    fn next(&mut self) -> Option<Self::Item> {
270        self.buffers.next().map(|buffer| unsafe {
271            (buffer, buffer.mapping().unwrap().use_access())
272        })
273    }
274}
275
276#[allow(missing_docs)]
277#[derive(Debug)]
278pub struct AccessGuardBuffersChain<'a, R: Resources> {
279    fst: AccessInfoBuffers<'a, R>,
280    snd: AccessInfoBuffers<'a, R>
281}
282
283impl<'a, R: Resources> Iterator for AccessGuardBuffersChain<'a, R> {
284    type Item = (&'a handle::RawBuffer<R>, &'a mut R::Mapping);
285
286    fn next(&mut self) -> Option<Self::Item> {
287        self.fst.next().or_else(|| self.snd.next())
288            .map(|buffer| unsafe {
289                (buffer, buffer.mapping().unwrap().use_access())
290            })
291    }
292}