1use std::error::Error;
21use std::{mem, fmt};
22use {buffer, handle, format, mapping, pso, shade, target, texture};
23use {Capabilities, Resources, ShaderSet,
24 VertexShader, HullShader, DomainShader, GeometryShader, PixelShader};
25use memory::{Bind, Usage, Typed, Pod, cast_slice};
26
27#[derive(Clone, Debug, PartialEq)]
29pub enum ResourceViewError {
30 NoBindFlag,
32 Channel(format::ChannelType),
34 Layer(texture::LayerError),
36 Unsupported,
38}
39
40impl fmt::Display for ResourceViewError {
41 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42 match *self {
43 ResourceViewError::Channel(ref channel_type) => write!(f, "{}: {:?}", self.description(), channel_type),
44 ResourceViewError::Layer(ref le) => write!(f, "{}: {}", self.description(), le),
45 _ => write!(f, "{}", self.description())
46 }
47 }
48}
49
50impl Error for ResourceViewError {
51 fn description(&self) -> &str {
52 match *self {
53 ResourceViewError::NoBindFlag => "The corresponding bind flag is not present in the texture",
54 ResourceViewError::Channel(_) => "Selected channel type is not supported for this texture",
55 ResourceViewError::Layer(_) => "Selected layer can not be viewed for this texture",
56 ResourceViewError::Unsupported => "The backend was refused for some reason",
57 }
58 }
59
60 fn cause(&self) -> Option<&dyn Error> {
61 if let ResourceViewError::Layer(ref e) = *self {
62 Some(e)
63 } else {
64 None
65 }
66 }
67}
68
69#[derive(Clone, Debug, PartialEq)]
71pub enum TargetViewError {
72 NoBindFlag,
74 Level(target::Level),
76 Layer(texture::LayerError),
78 Channel(format::ChannelType),
80 Unsupported,
82 NotDetached
84}
85
86impl fmt::Display for TargetViewError {
87 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88 let description = self.description();
89 match *self {
90 TargetViewError::Level(ref level) => write!(f, "{}: {}", description, level),
91 TargetViewError::Layer(ref layer) => write!(f, "{}: {}", description, layer),
92 TargetViewError::Channel(ref channel) => write!(f, "{}: {:?}", description, channel),
93 _ => write!(f, "{}", description)
94 }
95 }
96}
97
98impl Error for TargetViewError {
99 fn description(&self) -> &str {
100 match *self {
101 TargetViewError::NoBindFlag =>
102 "The `RENDER_TARGET`/`DEPTH_STENCIL` flag is not present in the texture",
103 TargetViewError::Level(_) =>
104 "Selected mip level doesn't exist",
105 TargetViewError::Layer(_) =>
106 "Selected array layer doesn't exist",
107 TargetViewError::Channel(_) =>
108 "Selected channel type is not supported for this texture",
109 TargetViewError::Unsupported =>
110 "The backend was refused for some reason",
111 TargetViewError::NotDetached =>
112 "The RTV cannot be changed due to the references to it existing",
113 }
114 }
115
116 fn cause(&self) -> Option<&dyn Error> {
117 if let TargetViewError::Layer(ref e) = *self {
118 Some(e)
119 } else {
120 None
121 }
122 }
123}
124
125#[derive(Clone, Debug, PartialEq)]
127pub enum CombinedError {
128 Texture(texture::CreationError),
130 Resource(ResourceViewError),
132 Target(TargetViewError),
134}
135
136impl fmt::Display for CombinedError {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 match *self {
139 CombinedError::Texture(ref e) => write!(f, "{}: {}", self.description(), e),
140 CombinedError::Resource(ref e) => write!(f, "{}: {}", self.description(), e),
141 CombinedError::Target(ref e) => write!(f, "{}: {}", self.description(), e),
142 }
143 }
144}
145
146impl Error for CombinedError {
147 fn description(&self) -> &str {
148 match *self {
149 CombinedError::Texture(_) => "Failed to create the raw texture",
150 CombinedError::Resource(_) => "Failed to create SRV or UAV",
151 CombinedError::Target(_) => "Failed to create RTV or DSV",
152 }
153 }
154
155 fn cause(&self) -> Option<&dyn Error> {
156 match *self {
157 CombinedError::Texture(ref e) => Some(e),
158 CombinedError::Resource(ref e) => Some(e),
159 CombinedError::Target(ref e) => Some(e),
160 }
161 }
162}
163
164impl From<texture::CreationError> for CombinedError {
165 fn from(e: texture::CreationError) -> CombinedError {
166 CombinedError::Texture(e)
167 }
168}
169impl From<ResourceViewError> for CombinedError {
170 fn from(e: ResourceViewError) -> CombinedError {
171 CombinedError::Resource(e)
172 }
173}
174impl From<TargetViewError> for CombinedError {
175 fn from(e: TargetViewError) -> CombinedError {
176 CombinedError::Target(e)
177 }
178}
179
180#[allow(missing_docs)]
227pub trait Factory<R: Resources> {
228 fn get_capabilities(&self) -> &Capabilities;
231
232 fn create_buffer_raw(&mut self, buffer::Info) -> Result<handle::RawBuffer<R>, buffer::CreationError>;
234 fn create_buffer_immutable_raw(&mut self, data: &[u8], stride: usize, buffer::Role, Bind)
235 -> Result<handle::RawBuffer<R>, buffer::CreationError>;
236 fn create_buffer_immutable<T: Pod>(&mut self, data: &[T], role: buffer::Role, bind: Bind)
237 -> Result<handle::Buffer<R, T>, buffer::CreationError> {
238 self.create_buffer_immutable_raw(cast_slice(data), mem::size_of::<T>(), role, bind)
239 .map(|raw| Typed::new(raw))
240 }
241 fn create_buffer<T>(&mut self, num: usize, role: buffer::Role, usage: Usage, bind: Bind)
242 -> Result<handle::Buffer<R, T>, buffer::CreationError> {
243 let stride = mem::size_of::<T>();
244 let info = buffer::Info {
245 role: role,
246 usage: usage,
247 bind: bind,
248 size: num * stride,
249 stride: stride,
250 };
251 self.create_buffer_raw(info).map(|raw| Typed::new(raw))
252 }
253
254 fn create_pipeline_state_raw(&mut self, &handle::Program<R>, &pso::Descriptor)
257 -> Result<handle::RawPipelineState<R>, pso::CreationError>;
258
259 fn create_program(&mut self, shader_set: &ShaderSet<R>)
261 -> Result<handle::Program<R>, shade::CreateProgramError>;
262
263 fn create_shader(&mut self, stage: shade::Stage, code: &[u8]) ->
266 Result<handle::Shader<R>, shade::CreateShaderError>;
267 fn create_shader_vertex(&mut self, code: &[u8]) -> Result<VertexShader<R>, shade::CreateShaderError> {
269 self.create_shader(shade::Stage::Vertex, code).map(|s| VertexShader(s))
270 }
271 fn create_shader_hull(&mut self, code: &[u8]) -> Result<HullShader<R>, shade::CreateShaderError> {
273 self.create_shader(shade::Stage::Hull, code).map(|s| HullShader(s))
274 }
275 fn create_shader_domain(&mut self, code: &[u8]) -> Result<DomainShader<R>, shade::CreateShaderError> {
277 self.create_shader(shade::Stage::Domain, code).map(|s| DomainShader(s))
278 }
279 fn create_shader_geometry(&mut self, code: &[u8]) -> Result<GeometryShader<R>, shade::CreateShaderError> {
281 self.create_shader(shade::Stage::Geometry, code).map(|s| GeometryShader(s))
282 }
283 fn create_shader_pixel(&mut self, code: &[u8]) -> Result<PixelShader<R>, shade::CreateShaderError> {
286 self.create_shader(shade::Stage::Pixel, code).map(|s| PixelShader(s))
287 }
288
289 fn create_sampler(&mut self, texture::SamplerInfo) -> handle::Sampler<R>;
290
291 fn read_mapping<'a, 'b, T>(&'a mut self, buf: &'b handle::Buffer<R, T>)
295 -> Result<mapping::Reader<'b, R, T>,
296 mapping::Error>
297 where T: Copy;
298
299 fn write_mapping<'a, 'b, T>(&'a mut self, buf: &'b handle::Buffer<R, T>)
307 -> Result<mapping::Writer<'b, R, T>,
308 mapping::Error>
309 where T: Copy;
310
311 fn create_texture_raw(&mut self, texture::Info, Option<format::ChannelType>, Option<(&[&[u8]], texture::Mipmap)>)
316 -> Result<handle::RawTexture<R>, texture::CreationError>;
317
318 fn view_buffer_as_shader_resource_raw(&mut self, &handle::RawBuffer<R>, format::Format)
319 -> Result<handle::RawShaderResourceView<R>, ResourceViewError>;
320 fn view_buffer_as_unordered_access_raw(&mut self, &handle::RawBuffer<R>)
321 -> Result<handle::RawUnorderedAccessView<R>, ResourceViewError>;
322 fn view_texture_as_shader_resource_raw(&mut self, &handle::RawTexture<R>, texture::ResourceDesc)
323 -> Result<handle::RawShaderResourceView<R>, ResourceViewError>;
324 fn view_texture_as_unordered_access_raw(&mut self, &handle::RawTexture<R>)
325 -> Result<handle::RawUnorderedAccessView<R>, ResourceViewError>;
326 fn view_texture_as_render_target_raw(&mut self, &handle::RawTexture<R>, texture::RenderDesc)
327 -> Result<handle::RawRenderTargetView<R>, TargetViewError>;
328 fn view_texture_as_depth_stencil_raw(&mut self, &handle::RawTexture<R>, texture::DepthStencilDesc)
329 -> Result<handle::RawDepthStencilView<R>, TargetViewError>;
330
331 fn create_texture<S>(&mut self, kind: texture::Kind, levels: target::Level,
332 bind: Bind, usage: Usage, channel_hint: Option<format::ChannelType>)
333 -> Result<handle::Texture<R, S>, texture::CreationError>
334 where S: format::SurfaceTyped
335 {
336 let desc = texture::Info {
337 kind: kind,
338 levels: levels,
339 format: S::get_surface_type(),
340 bind: bind,
341 usage: usage,
342 };
343 let raw = try!(self.create_texture_raw(desc, channel_hint, None));
344 Ok(Typed::new(raw))
345 }
346
347 fn view_buffer_as_shader_resource<T: format::Formatted>(&mut self, buf: &handle::Buffer<R, T>)
348 -> Result<handle::ShaderResourceView<R, T>, ResourceViewError>
349 {
350 self.view_buffer_as_shader_resource_raw(buf.raw(), T::get_format()).map(Typed::new)
352 }
353
354 fn view_buffer_as_unordered_access<T>(&mut self, buf: &handle::Buffer<R, T>)
355 -> Result<handle::UnorderedAccessView<R, T>, ResourceViewError>
356 {
357 self.view_buffer_as_unordered_access_raw(buf.raw()).map(Typed::new)
359 }
360
361 fn view_texture_as_shader_resource<T: format::TextureFormat>(&mut self, tex: &handle::Texture<R, T::Surface>,
362 levels: (target::Level, target::Level), swizzle: format::Swizzle)
363 -> Result<handle::ShaderResourceView<R, T::View>, ResourceViewError>
364 {
365 if !tex.get_info().bind.contains(Bind::SHADER_RESOURCE) {
366 return Err(ResourceViewError::NoBindFlag)
367 }
368 assert!(levels.0 <= levels.1);
369 let desc = texture::ResourceDesc {
370 channel: <T::Channel as format::ChannelTyped>::get_channel_type(),
371 layer: None,
372 min: levels.0,
373 max: levels.1,
374 swizzle: swizzle,
375 };
376 self.view_texture_as_shader_resource_raw(tex.raw(), desc)
377 .map(Typed::new)
378 }
379
380 fn view_texture_as_unordered_access<T: format::TextureFormat>(&mut self, tex: &handle::Texture<R, T::Surface>)
381 -> Result<handle::UnorderedAccessView<R, T::View>, ResourceViewError>
382 {
383 if !tex.get_info().bind.contains(Bind::UNORDERED_ACCESS) {
384 return Err(ResourceViewError::NoBindFlag)
385 }
386 self.view_texture_as_unordered_access_raw(tex.raw())
387 .map(Typed::new)
388 }
389
390 fn view_texture_as_render_target<T: format::RenderFormat>(&mut self, tex: &handle::Texture<R, T::Surface>,
391 level: target::Level, layer: Option<target::Layer>)
392 -> Result<handle::RenderTargetView<R, T>, TargetViewError>
393 {
394 if !tex.get_info().bind.contains(Bind::RENDER_TARGET) {
395 return Err(TargetViewError::NoBindFlag)
396 }
397 let desc = texture::RenderDesc {
398 channel: <T::Channel as format::ChannelTyped>::get_channel_type(),
399 level: level,
400 layer: layer,
401 };
402 self.view_texture_as_render_target_raw(tex.raw(), desc)
403 .map(Typed::new)
404 }
405
406 fn view_texture_as_depth_stencil<T: format::DepthFormat>(&mut self, tex: &handle::Texture<R, T::Surface>,
407 level: target::Level, layer: Option<target::Layer>, flags: texture::DepthStencilFlags)
408 -> Result<handle::DepthStencilView<R, T>, TargetViewError>
409 {
410 if !tex.get_info().bind.contains(Bind::DEPTH_STENCIL) {
411 return Err(TargetViewError::NoBindFlag)
412 }
413 let desc = texture::DepthStencilDesc {
414 level: level,
415 layer: layer,
416 flags: flags,
417 };
418 self.view_texture_as_depth_stencil_raw(tex.raw(), desc)
419 .map(Typed::new)
420 }
421
422 fn view_texture_as_depth_stencil_trivial<T: format::DepthFormat>(&mut self, tex: &handle::Texture<R, T::Surface>)
423 -> Result<handle::DepthStencilView<R, T>, TargetViewError>
424 {
425 self.view_texture_as_depth_stencil(tex, 0, None, texture::DepthStencilFlags::empty())
426 }
427
428 fn create_texture_immutable_u8<T: format::TextureFormat>(&mut self, kind: texture::Kind, mipmap: texture::Mipmap, data: &[&[u8]])
429 -> Result<(handle::Texture<R, T::Surface>,
430 handle::ShaderResourceView<R, T::View>),
431 CombinedError>
432 {
433 let surface = <T::Surface as format::SurfaceTyped>::get_surface_type();
434 let num_slices = kind.get_num_slices().unwrap_or(1) as usize;
435 let num_faces = if kind.is_cube() {6} else {1};
436 let levels = match mipmap {
437 texture::Mipmap::Allocated => if data.len() != num_slices * num_faces {
438 return Err(CombinedError::Texture(texture::CreationError::Level((num_slices * num_faces) as texture::Level)));
439 } else {
440 kind.get_num_levels()
441 },
442 texture::Mipmap::Provided => (data.len() / (num_slices * num_faces)) as texture::Level
443 };
444 let desc = texture::Info {
445 kind: kind,
446 levels: levels,
447 format: surface,
448 bind: Bind::SHADER_RESOURCE,
449 usage: Usage::Data,
450 };
451 let cty = <T::Channel as format::ChannelTyped>::get_channel_type();
452 let raw = try!(self.create_texture_raw(desc, Some(cty), Some((data, mipmap))));
453 let levels = (0, raw.get_info().levels - 1);
454 let tex = Typed::new(raw);
455 let view = try!(self.view_texture_as_shader_resource::<T>(&tex, levels, format::Swizzle::new()));
456 Ok((tex, view))
457 }
458
459 fn create_texture_immutable<T: format::TextureFormat>(
460 &mut self,
461 kind: texture::Kind,
462 mipmap: texture::Mipmap,
463 data: &[&[<T::Surface as format::SurfaceTyped>::DataType]])
464 -> Result<(handle::Texture<R, T::Surface>, handle::ShaderResourceView<R, T::View>),
465 CombinedError>
466 {
467 let mut raw_data: [&[u8]; 0x100] = [&[]; 0x100];
469 assert!(data.len() <= raw_data.len());
470 for (rd, d) in raw_data.iter_mut().zip(data.iter()) {
471 *rd = cast_slice(*d);
472 }
473 self.create_texture_immutable_u8::<T>(kind, mipmap, &raw_data[.. data.len()])
474 }
475
476 fn create_render_target<T: format::RenderFormat + format::TextureFormat>
477 (&mut self, width: texture::Size, height: texture::Size)
478 -> Result<(handle::Texture<R, T::Surface>,
479 handle::ShaderResourceView<R, T::View>,
480 handle::RenderTargetView<R, T>
481 ), CombinedError>
482 {
483 let kind = texture::Kind::D2(width, height, texture::AaMode::Single);
484 let levels = 1;
485 let cty = <T::Channel as format::ChannelTyped>::get_channel_type();
486 let tex = try!(self.create_texture(kind, levels, Bind::SHADER_RESOURCE | Bind::RENDER_TARGET, Usage::Data, Some(cty)));
487 let resource = try!(self.view_texture_as_shader_resource::<T>(&tex, (0, levels-1), format::Swizzle::new()));
488 let target = try!(self.view_texture_as_render_target(&tex, 0, None));
489 Ok((tex, resource, target))
490 }
491
492 fn create_depth_stencil<T: format::DepthFormat + format::TextureFormat>
493 (&mut self, width: texture::Size, height: texture::Size)
494 -> Result<(handle::Texture<R, T::Surface>,
495 handle::ShaderResourceView<R, T::View>,
496 handle::DepthStencilView<R, T>
497 ), CombinedError>
498 {
499 let kind = texture::Kind::D2(width, height, texture::AaMode::Single);
500 let cty = <T::Channel as format::ChannelTyped>::get_channel_type();
501 let tex = try!(self.create_texture(kind, 1, Bind::SHADER_RESOURCE | Bind::DEPTH_STENCIL, Usage::Data, Some(cty)));
502 let resource = try!(self.view_texture_as_shader_resource::<T>(&tex, (0, 0), format::Swizzle::new()));
503 let target = try!(self.view_texture_as_depth_stencil_trivial(&tex));
504 Ok((tex, resource, target))
505 }
506
507 fn create_depth_stencil_view_only<T: format::DepthFormat + format::TextureFormat>
508 (&mut self, width: texture::Size, height: texture::Size)
509 -> Result<handle::DepthStencilView<R, T>, CombinedError>
510 {
511 let kind = texture::Kind::D2(width, height, texture::AaMode::Single);
512 let cty = <T::Channel as format::ChannelTyped>::get_channel_type();
513 let tex = try!(self.create_texture(kind, 1, Bind::DEPTH_STENCIL, Usage::Data, Some(cty)));
514 let target = try!(self.view_texture_as_depth_stencil_trivial(&tex));
515 Ok(target)
516 }
517}