// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
//! How to retrieve data from an image within a shader.
//!
//! When you retrieve data from an image, you have to pass the coordinates of the pixel you want
//! to retrieve. The implementation then performs various calculations, and these operations are
//! what the `Sampler` struct describes.
//!
//! Sampling is a very complex topic but that hasn't changed much since the beginnings of 3D
//! rendering. Documentation here is missing, but any tutorial about OpenGL or DirectX can teach
//! you how it works.
//!
//! # Examples
//!
//! A simple sampler for most usages:
//!
//! ```no_run
//! use vulkano::sampler::Sampler;
//!
//! # let device: std::sync::Arc<vulkano::device::Device> = unsafe { ::std::mem::uninitialized() };
//! let _sampler = Sampler::simple_repeat_linear_no_mipmap(&device);
//! ```
//!
//! More detailed sampler creation:
//!
//! ```no_run
//! use vulkano::sampler;
//!
//! # let device: std::sync::Arc<vulkano::device::Device> = unsafe { ::std::mem::uninitialized() };
//! let _sampler = sampler::Sampler::new(&device, sampler::Filter::Linear, sampler::Filter::Linear,
//! sampler::MipmapMode::Nearest,
//! sampler::SamplerAddressMode::Repeat,
//! sampler::SamplerAddressMode::Repeat,
//! sampler::SamplerAddressMode::Repeat, 1.0, 1.0,
//! 0.0, 100.0).unwrap();;
//! ```
//!
//! # About border colors
//!
//! One of the possible values of `SamplerAddressMode` and `UnnormalizedSamplerAddressMode` is
//! `ClampToBorder`. This value indicates that accessing an image outside of its range must return
//! the specified color.
//!
//! However this comes with restrictions. When using a floating-point border color, the sampler can
//! only be used with floating-point or depth image views. When using an integer border color, the
//! sampler can only be used with integer or stencil image views. In addition to this, you can't
//! use an opaque black border color with an image view that uses components swizzling.
//!
//! > **Note**: The reason for this restriction about opaque black borders is that the value of the
//! > alpha is 1.0 while the value of the color components is 0.0. In the other border colors, the
//! > value of all the components is the same.
//!
//! Samplers that don't use `ClampToBorder` are not concerned by these restrictions.
//!
// FIXME: restrictions aren't checked yet
use std::error;
use std::fmt;
use std::mem;
use std::ptr;
use std::sync::Arc;
use device::Device;
use Error;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;
pub use pipeline::depth_stencil::Compare;
/// Describes how to retrieve data from an image within a shader.
pub struct Sampler {
sampler: vk::Sampler,
device: Arc<Device>,
compare_mode: bool,
unnormalized: bool,
usable_with_float_formats: bool,
usable_with_int_formats: bool,
usable_with_swizzling: bool,
}
// TODO: what's the story with VK_KHR_mirror_clamp_to_edge? Is it an extension or is it core?
impl Sampler {
/// Shortcut for creating a sampler with linear sampling, linear mipmaps, and with the repeat
/// mode for borders.
///
/// Useful for prototyping, but can also be used in real projects.
///
/// # Panic
///
/// - Panics if out of memory or the maximum number of samplers has exceeded.
///
#[inline]
pub fn simple_repeat_linear(device: &Arc<Device>) -> Arc<Sampler> {
Sampler::new(device, Filter::Linear, Filter::Linear, MipmapMode::Linear,
SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 1_000.0).unwrap()
}
/// Shortcut for creating a sampler with linear sampling, that only uses the main level of
/// images, and with the repeat mode for borders.
///
/// Useful for prototyping, but can also be used in real projects.
///
/// # Panic
///
/// - Panics if out of memory or the maximum number of samplers has exceeded.
///
#[inline]
pub fn simple_repeat_linear_no_mipmap(device: &Arc<Device>) -> Arc<Sampler> {
Sampler::new(device, Filter::Linear, Filter::Linear, MipmapMode::Nearest,
SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 1.0).unwrap()
}
/// Creates a new `Sampler` with the given behavior.
///
/// `mag_filter` and `min_filter` define how the implementation should sample from the image
/// when it is respectively larger and smaller than the original.
///
/// `mipmap_mode` defines how the implementation should choose which mipmap to use.
///
/// `address_u`, `address_v` and `address_w` define how the implementation should behave when
/// sampling outside of the texture coordinates range `[0.0, 1.0]`.
///
/// `mip_lod_bias` is a value to add to .
///
/// `max_anisotropy` must be superior or equal to 1.0. If superior to 1.0, the implementation
/// will use anistropic filtering. Using a value superior to 1.0 requires the
/// `sampler_anisotropy` feature to be enabled when creating the device.
///
/// `min_lod` and `max_lod` are respectively the minimum and maximum mipmap level to use.
/// `max_lod` must always be superior or equal to `min_lod`.
///
/// # Panic
///
/// - Panics if multiple `ClampToBorder` values are passed and the border color is different.
/// - Panics if `max_anisotropy < 1.0`.
/// - Panics if `min_lod > max_lod`.
///
#[inline(always)]
pub fn new(device: &Arc<Device>, mag_filter: Filter, min_filter: Filter,
mipmap_mode: MipmapMode, address_u: SamplerAddressMode,
address_v: SamplerAddressMode, address_w: SamplerAddressMode, mip_lod_bias: f32,
max_anisotropy: f32, min_lod: f32, max_lod: f32)
-> Result<Arc<Sampler>, SamplerCreationError>
{
Sampler::new_impl(device, mag_filter, min_filter, mipmap_mode, address_u, address_v,
address_w, mip_lod_bias, max_anisotropy, min_lod, max_lod, None)
}
/// Creates a new `Sampler` with the given behavior.
///
/// Contrary to `new`, this creates a sampler that is used to compare depth values.
///
/// A sampler like this can only operate on depth or depth-stencil textures. Instead of
/// returning the value of the texture, this sampler will return a value between 0.0 and 1.0
/// indicating how much the reference value (passed by the shader) compares to the value in the
/// texture.
///
/// Note that it doesn't make sense to create a compare-mode sampler with an integer border
/// color, as such a sampler would be unusable.
///
/// # Panic
///
/// Same panic reasons as `new`.
///
#[inline(always)]
pub fn compare(device: &Arc<Device>, mag_filter: Filter, min_filter: Filter,
mipmap_mode: MipmapMode, address_u: SamplerAddressMode,
address_v: SamplerAddressMode, address_w: SamplerAddressMode, mip_lod_bias: f32,
max_anisotropy: f32, min_lod: f32, max_lod: f32, compare: Compare)
-> Result<Arc<Sampler>, SamplerCreationError>
{
Sampler::new_impl(device, mag_filter, min_filter, mipmap_mode, address_u, address_v,
address_w, mip_lod_bias, max_anisotropy, min_lod, max_lod, Some(compare))
}
fn new_impl(device: &Arc<Device>, mag_filter: Filter, min_filter: Filter,
mipmap_mode: MipmapMode, address_u: SamplerAddressMode,
address_v: SamplerAddressMode, address_w: SamplerAddressMode, mip_lod_bias: f32,
max_anisotropy: f32, min_lod: f32, max_lod: f32, compare: Option<Compare>)
-> Result<Arc<Sampler>, SamplerCreationError>
{
assert!(max_anisotropy >= 1.0);
assert!(min_lod <= max_lod);
// Check max anisotropy.
if max_anisotropy > 1.0 {
if !device.enabled_features().sampler_anisotropy {
return Err(SamplerCreationError::SamplerAnisotropyFeatureNotEnabled);
}
let limit = device.physical_device().limits().max_sampler_anisotropy();
if max_anisotropy > limit {
return Err(SamplerCreationError::AnisotropyLimitExceeded {
requested: max_anisotropy,
maximum: limit,
});
}
}
// Check mip_lod_bias value.
{
let limit = device.physical_device().limits().max_sampler_lod_bias();
if mip_lod_bias > limit {
return Err(SamplerCreationError::MipLodBiasLimitExceeded {
requested: mip_lod_bias,
maximum: limit,
});
}
}
// Handling border color.
let border_color = address_u.border_color();
let border_color = match (border_color, address_v.border_color()) {
(Some(b1), Some(b2)) => { assert_eq!(b1, b2); Some(b1) },
(None, b) => b,
(b, None) => b,
};
let border_color = match (border_color, address_w.border_color()) {
(Some(b1), Some(b2)) => { assert_eq!(b1, b2); Some(b1) },
(None, b) => b,
(b, None) => b,
};
let vk = device.pointers();
let sampler = unsafe {
let infos = vk::SamplerCreateInfo {
sType: vk::STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
pNext: ptr::null(),
flags: 0, // reserved
magFilter: mag_filter as u32,
minFilter: min_filter as u32,
mipmapMode: mipmap_mode as u32,
addressModeU: address_u.to_vk(),
addressModeV: address_v.to_vk(),
addressModeW: address_w.to_vk(),
mipLodBias: mip_lod_bias,
anisotropyEnable: if max_anisotropy > 1.0 { vk::TRUE } else { vk::FALSE },
maxAnisotropy: max_anisotropy,
compareEnable: if compare.is_some() { vk::TRUE } else { vk:: FALSE },
compareOp: compare.map(|c| c as u32).unwrap_or(0),
minLod: min_lod,
maxLod: max_lod,
borderColor: border_color.map(|b| b as u32).unwrap_or(0),
unnormalizedCoordinates: vk::FALSE,
};
let mut output = mem::uninitialized();
try!(check_errors(vk.CreateSampler(device.internal_object(), &infos,
ptr::null(), &mut output)));
output
};
Ok(Arc::new(Sampler {
sampler: sampler,
device: device.clone(),
compare_mode: compare.is_some(),
unnormalized: false,
usable_with_float_formats: match border_color {
Some(BorderColor::FloatTransparentBlack) => true,
Some(BorderColor::FloatOpaqueBlack) => true,
Some(BorderColor::FloatOpaqueWhite) => true,
Some(_) => false,
None => true,
},
usable_with_int_formats: compare.is_none() && match border_color {
Some(BorderColor::IntTransparentBlack) => true,
Some(BorderColor::IntOpaqueBlack) => true,
Some(BorderColor::IntOpaqueWhite) => true,
Some(_) => false,
None => true,
},
usable_with_swizzling: match border_color {
Some(BorderColor::FloatOpaqueBlack) => false,
Some(BorderColor::IntOpaqueBlack) => false,
_ => true,
},
}))
}
/// Creates a sampler with unnormalized coordinates. This means that texture coordinates won't
/// range between `0.0` and `1.0` but use plain pixel offsets.
///
/// Using an unnormalized sampler adds a few restrictions:
///
/// - It can only be used with non-array 1D or 2D images.
/// - It can only be used with images with a single mipmap.
/// - Projection and offsets can't be used by shaders. Only the first mipmap can be accessed.
///
/// # Panic
///
/// - Panics if multiple `ClampToBorder` values are passed and the border color is different.
///
pub fn unnormalized(device: &Arc<Device>, filter: Filter,
address_u: UnnormalizedSamplerAddressMode,
address_v: UnnormalizedSamplerAddressMode)
-> Result<Arc<Sampler>, SamplerCreationError>
{
let vk = device.pointers();
let border_color = address_u.border_color();
let border_color = match (border_color, address_v.border_color()) {
(Some(b1), Some(b2)) => { assert_eq!(b1, b2); Some(b1) },
(None, b) => b,
(b, None) => b,
};
let sampler = unsafe {
let infos = vk::SamplerCreateInfo {
sType: vk::STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
pNext: ptr::null(),
flags: 0, // reserved
magFilter: filter as u32,
minFilter: filter as u32,
mipmapMode: vk::SAMPLER_MIPMAP_MODE_NEAREST,
addressModeU: address_u.to_vk(),
addressModeV: address_v.to_vk(),
addressModeW: vk::SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // unused by the impl
mipLodBias: 0.0,
anisotropyEnable: vk::FALSE,
maxAnisotropy: 0.0,
compareEnable: vk::FALSE,
compareOp: vk::COMPARE_OP_NEVER,
minLod: 0.0,
maxLod: 0.0,
borderColor: border_color.map(|b| b as u32).unwrap_or(0),
unnormalizedCoordinates: vk::TRUE,
};
let mut output = mem::uninitialized();
try!(check_errors(vk.CreateSampler(device.internal_object(), &infos,
ptr::null(), &mut output)));
output
};
Ok(Arc::new(Sampler {
sampler: sampler,
device: device.clone(),
compare_mode: false,
unnormalized: true,
usable_with_float_formats: match border_color {
Some(BorderColor::FloatTransparentBlack) => true,
Some(BorderColor::FloatOpaqueBlack) => true,
Some(BorderColor::FloatOpaqueWhite) => true,
Some(_) => false,
None => true,
},
usable_with_int_formats: match border_color {
Some(BorderColor::IntTransparentBlack) => true,
Some(BorderColor::IntOpaqueBlack) => true,
Some(BorderColor::IntOpaqueWhite) => true,
Some(_) => false,
None => true,
},
usable_with_swizzling: match border_color {
Some(BorderColor::FloatOpaqueBlack) => false,
Some(BorderColor::IntOpaqueBlack) => false,
_ => true,
},
}))
}
/// Returns true if the sampler is a compare-mode sampler.
#[inline]
pub fn compare_mode(&self) -> bool {
self.compare_mode
}
/// Returns true if the sampler is unnormalized.
#[inline]
pub fn is_unnormalized(&self) -> bool {
self.unnormalized
}
/// Returns true if the sampler can be used with floating-point image views. See the
/// documentation of the `sampler` module for more info.
#[inline]
pub fn usable_with_float_formats(&self) -> bool {
self.usable_with_float_formats
}
/// Returns true if the sampler can be used with integer image views. See the documentation of
/// the `sampler` module for more info.
#[inline]
pub fn usable_with_int_formats(&self) -> bool {
self.usable_with_int_formats
}
/// Returns true if the sampler can be used with image views that have non-identity swizzling.
/// See the documentation of the `sampler` module for more info.
#[inline]
pub fn usable_with_swizzling(&self) -> bool {
self.usable_with_swizzling
}
}
unsafe impl VulkanObject for Sampler {
type Object = vk::Sampler;
#[inline]
fn internal_object(&self) -> vk::Sampler {
self.sampler
}
}
impl Drop for Sampler {
#[inline]
fn drop(&mut self) {
unsafe {
let vk = self.device.pointers();
vk.DestroySampler(self.device.internal_object(), self.sampler, ptr::null());
}
}
}
/// Describes how the color of each pixel should be determined.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum Filter {
/// The four pixels whose center surround the requested coordinates are taken, then their
/// values are interpolated.
Linear = vk::FILTER_LINEAR,
/// The pixel whose center is nearest to the requested coordinates is taken from the source
/// and its value is returned as-is.
Nearest = vk::FILTER_NEAREST,
}
/// Describes which mipmap from the source to use.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum MipmapMode {
/// Use the mipmap whose dimensions are the nearest to the dimensions of the destination.
Nearest = vk::SAMPLER_MIPMAP_MODE_NEAREST,
/// Take the two mipmaps whose dimensions are immediately inferior and superior to the
/// dimensions of the destination, calculate the value for both, and interpolate them.
Linear = vk::SAMPLER_MIPMAP_MODE_LINEAR,
}
/// How the sampler should behave when it needs to access a pixel that is out of range of the
/// texture.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum SamplerAddressMode {
/// Repeat the texture. In other words, the pixel at coordinate `x + 1.0` is the same as the
/// one at coordinate `x`.
Repeat,
/// Repeat the texture but mirror it at every repetition. In other words, the pixel at
/// coordinate `x + 1.0` is the same as the one at coordinate `1.0 - x`.
MirroredRepeat,
/// The coordinates are clamped to the valid range. Coordinates below 0.0 have the same value
/// as coordinate 0.0. Coordinates over 1.0 have the same value as coordinate 1.0.
ClampToEdge,
/// Any pixel out of range is considered to be part of the "border" of the image, which has a
/// specific color of your choice.
///
/// Note that if you use `ClampToBorder` multiple times, they must all have the same border
/// color.
ClampToBorder(BorderColor),
/// Similar to `MirroredRepeat`, except that coordinates are clamped to the range
/// `[-1.0, 1.0]`.
MirrorClampToEdge,
}
impl SamplerAddressMode {
#[inline]
fn to_vk(self) -> vk::SamplerAddressMode {
match self {
SamplerAddressMode::Repeat => vk::SAMPLER_ADDRESS_MODE_REPEAT,
SamplerAddressMode::MirroredRepeat => vk::SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
SamplerAddressMode::ClampToEdge => vk::SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
SamplerAddressMode::ClampToBorder(_) => vk::SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
SamplerAddressMode::MirrorClampToEdge => vk::SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
}
}
#[inline]
fn border_color(self) -> Option<BorderColor> {
match self {
SamplerAddressMode::ClampToBorder(c) => Some(c),
_ => None
}
}
}
/// How the sampler should behave when it needs to access a pixel that is out of range of the
/// texture.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum UnnormalizedSamplerAddressMode {
/// The coordinates are clamped to the valid range. Coordinates below 0 have the same value
/// as coordinate 0. Coordinates over *size of texture* have the same value as coordinate
/// *size of texture*.
ClampToEdge,
/// Any pixel out of range is considered to be part of the "border" of the image, which has a
/// specific color of your choice.
///
/// Note that if you use `ClampToBorder` multiple times, they must all have the same border
/// color.
ClampToBorder(BorderColor),
}
impl UnnormalizedSamplerAddressMode {
#[inline]
fn to_vk(self) -> vk::SamplerAddressMode {
match self {
UnnormalizedSamplerAddressMode::ClampToEdge => vk::SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
UnnormalizedSamplerAddressMode::ClampToBorder(_) => {
vk::SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER
},
}
}
#[inline]
fn border_color(self) -> Option<BorderColor> {
match self {
UnnormalizedSamplerAddressMode::ClampToEdge => None,
UnnormalizedSamplerAddressMode::ClampToBorder(c) => Some(c),
}
}
}
/// The color to use for the border of an image.
///
/// Only relevant if you use `ClampToBorder`.
///
/// Using a border color restricts the sampler to either floating-point images or integer images.
/// See the documentation of the `sampler` module for more info.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum BorderColor {
/// The value `(0.0, 0.0, 0.0, 0.0)`. Can only be used with floating-point images.
FloatTransparentBlack = vk::BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
/// The value `(0, 0, 0, 0)`. Can only be used with integer images.
IntTransparentBlack = vk::BORDER_COLOR_INT_TRANSPARENT_BLACK,
/// The value `(0.0, 0.0, 0.0, 1.0)`. Can only be used with floating-point identity-swizzled
/// images.
FloatOpaqueBlack = vk::BORDER_COLOR_FLOAT_OPAQUE_BLACK,
/// The value `(0, 0, 0, 1)`. Can only be used with integer identity-swizzled images.
IntOpaqueBlack = vk::BORDER_COLOR_INT_OPAQUE_BLACK,
/// The value `(1.0, 1.0, 1.0, 1.0)`. Can only be used with floating-point images.
FloatOpaqueWhite = vk::BORDER_COLOR_FLOAT_OPAQUE_WHITE,
/// The value `(1, 1, 1, 1)`. Can only be used with integer images.
IntOpaqueWhite = vk::BORDER_COLOR_INT_OPAQUE_WHITE,
}
/// Error that can happen when creating an instance.
#[derive(Clone, Debug, PartialEq)]
pub enum SamplerCreationError {
/// Not enough memory.
OomError(OomError),
/// Too many sampler objects have been created. You must destroy some before creating new ones.
/// Note the specs guarantee that at least 4000 samplers can exist simultaneously.
TooManyObjects,
/// Using an anisotropy superior to 1.0 requires enabling the `sampler_anisotropy` feature when
/// creating the device.
SamplerAnisotropyFeatureNotEnabled,
/// The requested anisotropy level exceeds the device's limits.
AnisotropyLimitExceeded {
/// The value that was requested.
requested: f32,
/// The maximum supported value.
maximum: f32
},
/// The requested mip lod bias exceeds the device's limits.
MipLodBiasLimitExceeded {
/// The value that was requested.
requested: f32,
/// The maximum supported value.
maximum: f32
},
}
impl error::Error for SamplerCreationError {
#[inline]
fn description(&self) -> &str {
match *self {
SamplerCreationError::OomError(_) => "not enough memory available",
SamplerCreationError::TooManyObjects => "too many simultaneous sampler objects",
SamplerCreationError::SamplerAnisotropyFeatureNotEnabled => "the `sampler_anisotropy` \
feature is not enabled",
SamplerCreationError::AnisotropyLimitExceeded { .. } => "anisotropy limit exceeded",
SamplerCreationError::MipLodBiasLimitExceeded { .. } => "mip lod bias limit exceeded",
}
}
#[inline]
fn cause(&self) -> Option<&error::Error> {
match *self {
SamplerCreationError::OomError(ref err) => Some(err),
_ => None
}
}
}
impl fmt::Display for SamplerCreationError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", error::Error::description(self))
}
}
impl From<OomError> for SamplerCreationError {
#[inline]
fn from(err: OomError) -> SamplerCreationError {
SamplerCreationError::OomError(err)
}
}
impl From<Error> for SamplerCreationError {
#[inline]
fn from(err: Error) -> SamplerCreationError {
match err {
err @ Error::OutOfHostMemory => SamplerCreationError::OomError(OomError::from(err)),
err @ Error::OutOfDeviceMemory => SamplerCreationError::OomError(OomError::from(err)),
Error::TooManyObjects => SamplerCreationError::TooManyObjects,
_ => panic!("unexpected error: {:?}", err)
}
}
}
#[cfg(test)]
mod tests {
use sampler;
#[test]
fn create_regular() {
let (device, queue) = gfx_dev_and_queue!();
let s = sampler::Sampler::new(&device, sampler::Filter::Linear, sampler::Filter::Linear,
sampler::MipmapMode::Nearest,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat, 1.0, 1.0,
0.0, 2.0).unwrap();
assert!(!s.compare_mode());
assert!(!s.is_unnormalized());
}
#[test]
fn create_compare() {
let (device, queue) = gfx_dev_and_queue!();
let s = sampler::Sampler::compare(&device, sampler::Filter::Linear, sampler::Filter::Linear,
sampler::MipmapMode::Nearest,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat, 1.0, 1.0,
0.0, 2.0, sampler::Compare::Less).unwrap();
assert!(s.compare_mode());
assert!(!s.is_unnormalized());
}
#[test]
fn create_unnormalized() {
let (device, queue) = gfx_dev_and_queue!();
let s = sampler::Sampler::unnormalized(&device, sampler::Filter::Linear,
sampler::UnnormalizedSamplerAddressMode::ClampToEdge,
sampler::UnnormalizedSamplerAddressMode::ClampToEdge)
.unwrap();
assert!(!s.compare_mode());
assert!(s.is_unnormalized());
}
#[test]
fn simple_repeat_linear() {
let (device, queue) = gfx_dev_and_queue!();
let _ = sampler::Sampler::simple_repeat_linear(&device);
}
#[test]
fn simple_repeat_linear_no_mipmap() {
let (device, queue) = gfx_dev_and_queue!();
let _ = sampler::Sampler::simple_repeat_linear_no_mipmap(&device);
}
#[test]
#[should_panic]
fn min_lod_inferior() {
let (device, queue) = gfx_dev_and_queue!();
let _ = sampler::Sampler::new(&device, sampler::Filter::Linear, sampler::Filter::Linear,
sampler::MipmapMode::Nearest,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat, 1.0, 1.0, 5.0, 2.0);
}
#[test]
#[should_panic]
fn max_anisotropy() {
let (device, queue) = gfx_dev_and_queue!();
let _ = sampler::Sampler::new(&device, sampler::Filter::Linear, sampler::Filter::Linear,
sampler::MipmapMode::Nearest,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat, 1.0, 0.5, 0.0, 2.0);
}
#[test]
#[should_panic]
fn different_borders() {
let (device, queue) = gfx_dev_and_queue!();
let b1 = sampler::BorderColor::IntTransparentBlack;
let b2 = sampler::BorderColor::FloatOpaqueWhite;
let _ = sampler::Sampler::new(&device, sampler::Filter::Linear, sampler::Filter::Linear,
sampler::MipmapMode::Nearest,
sampler::SamplerAddressMode::ClampToBorder(b1),
sampler::SamplerAddressMode::ClampToBorder(b2),
sampler::SamplerAddressMode::Repeat, 1.0, 1.0, 5.0, 2.0);
}
#[test]
fn anisotropy_feature() {
let (device, queue) = gfx_dev_and_queue!();
let r = sampler::Sampler::new(&device, sampler::Filter::Linear, sampler::Filter::Linear,
sampler::MipmapMode::Nearest,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat, 1.0, 2.0, 0.0, 2.0);
match r {
Err(sampler::SamplerCreationError::SamplerAnisotropyFeatureNotEnabled) => (),
_ => panic!()
}
}
#[test]
fn anisotropy_limit() {
let (device, queue) = gfx_dev_and_queue!(sampler_anisotropy);
let r = sampler::Sampler::new(&device, sampler::Filter::Linear, sampler::Filter::Linear,
sampler::MipmapMode::Nearest,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat, 1.0, 100000000.0, 0.0,
2.0);
match r {
Err(sampler::SamplerCreationError::AnisotropyLimitExceeded { .. }) => (),
_ => panic!()
}
}
#[test]
fn mip_lod_bias_limit() {
let (device, queue) = gfx_dev_and_queue!();
let r = sampler::Sampler::new(&device, sampler::Filter::Linear, sampler::Filter::Linear,
sampler::MipmapMode::Nearest,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat,
sampler::SamplerAddressMode::Repeat, 100000000.0, 1.0, 0.0,
2.0);
match r {
Err(sampler::SamplerCreationError::MipLodBiasLimitExceeded { .. }) => (),
_ => panic!()
}
}
}