# Chapter 12. Samplers

`VkSampler` objects represent the state of an image sampler which is used by the implementation to read image data and apply filtering and other transformations for the shader.

Samplers are represented by `VkSampler` handles:

    VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler)

To create a sampler object, call:

    VkResult vkCreateSampler(
        VkDevice                                    device,
        const VkSamplerCreateInfo*                  pCreateInfo,
        const VkAllocationCallbacks*                pAllocator,
        VkSampler*                                  pSampler);

- `device` is the logical device that creates the sampler.
- `pCreateInfo` is a pointer to an instance of the `VkSamplerCreateInfo` structure specifying the state of the sampler object.
- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.
- `pSampler` points to a `VkSampler` handle in which the resulting sampler object is returned.

The `VkSamplerCreateInfo` structure is defined as:

    typedef struct VkSamplerCreateInfo {
        VkStructureType         sType;
        const void*             pNext;
        VkSamplerCreateFlags    flags;
        VkFilter                magFilter;
        VkFilter                minFilter;
        VkSamplerMipmapMode     mipmapMode;
        VkSamplerAddressMode    addressModeU;
        VkSamplerAddressMode    addressModeV;
        VkSamplerAddressMode    addressModeW;
        float                   mipLodBias;
        VkBool32                anisotropyEnable;
        float                   maxAnisotropy;
        VkBool32                compareEnable;
        VkCompareOp             compareOp;
        float                   minLod;
        float                   maxLod;
        VkBorderColor           borderColor;
        VkBool32                unnormalizedCoordinates;
    } VkSamplerCreateInfo;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.
- `flags` is reserved for future use.

- `magFilter` is the magnification filter to apply to lookups, and is of type:

      typedef enum VkFilter {
          VK_FILTER_NEAREST = 0,
          VK_FILTER_LINEAR = 1,
      } VkFilter;

- `minFilter` is the minification filter to apply to lookups, and is of type `VkFilter`.

- `mipmapMode` is the mipmap filter to apply to lookups as described in the Texel Filtering section, and is of type:

      typedef enum VkSamplerMipmapMode {
          VK_SAMPLER_MIPMAP_MODE_NEAREST = 0,
          VK_SAMPLER_MIPMAP_MODE_LINEAR = 1,
      } VkSamplerMipmapMode;

- `addressModeU` is the addressing mode for outside [0..1] range for U coordinate. See `VkSamplerAddressMode`.
- `addressModeV` is the addressing mode for outside [0..1] range for V coordinate. See `VkSamplerAddressMode`.
- `addressModeW` is the addressing mode for outside [0..1] range for W coordinate. See `VkSamplerAddressMode`.
- `mipLodBias` is the bias to be added to mipmap LOD calculation and bias provided by image sampling functions in SPIR-V, as described in the Level-of-Detail Operation section.
- `anisotropyEnable` is `VK_TRUE` to enable anisotropic filtering, as described in the Texel Anisotropic Filtering section, or `VK_FALSE` otherwise.
- `maxAnisotropy` is the anisotropy value clamp.

- `compareEnable` is `VK_TRUE` to enable comparison against a reference value during lookups, or `VK_FALSE` otherwise.

  - Note: Some implementations will default to shader state if this member does not match.
- `compareOp` is the comparison function to apply to fetched data before filtering as described in the Depth Compare Operation section. See `VkCompareOp`.
- `minLod` and `maxLod` are the values used to clamp the computed level-of-detail value, as described in the Level-of-Detail Operation section. `maxLod` must be greater than or equal to `minLod`.

- `borderColor` is the predefined border color to use, as described in the Texel Replacement section, and is of type:

      typedef enum VkBorderColor {
          VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0,
          VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1,
          VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2,
          VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3,
          VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4,
          VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5,
      } VkBorderColor;

- `unnormalizedCoordinates` controls whether to use unnormalized or normalized texel coordinates to address texels of the image. When set to `VK_TRUE`, the range of the image coordinates used to lookup the texel is in the range of zero to the image dimensions for x, y and z. When set to `VK_FALSE` the range of image coordinates is zero to one. When `unnormalizedCoordinates` is `VK_TRUE`, samplers have the following requirements:

  - `minFilter` and `magFilter` must be equal.
  - `mipmapMode` must be `VK_SAMPLER_MIPMAP_MODE_NEAREST`.
  - `minLod` and `maxLod` must be zero.
  - `addressModeU` and `addressModeV` must each be either `VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE` or `VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER`.
  - `anisotropyEnable` must be `VK_FALSE`.
  - `compareEnable` must be `VK_FALSE`.

- When `unnormalizedCoordinates` is `VK_TRUE`, images the sampler is used with in the shader have the following requirements:

  - The `viewType` must be either `VK_IMAGE_VIEW_TYPE_1D` or `VK_IMAGE_VIEW_TYPE_2D`.
  - The image view must have a single layer and a single mip level.

- When `unnormalizedCoordinates` is `VK_TRUE`, image built-in functions in the shader that use the sampler have the following requirements:

  - The functions must not use projection.
  - The functions must not use offsets.

| Mapping of OpenGL to Vulkan filter modes
`magFilter` values of `VK_FILTER_NEAREST` and `VK_FILTER_LINEAR` directly correspond to `GL_NEAREST` and `GL_LINEAR` magnification filters. `minFilter` and `mipmapMode` combine to correspond to the similarly named OpenGL minification filter of `GL_minFilter_MIPMAP_mipmapMode` (e.g. `minFilter` of `VK_FILTER_LINEAR` and `mipmapMode` of `VK_SAMPLER_MIPMAP_MODE_NEAREST` correspond to `GL_LINEAR_MIPMAP_NEAREST`). There are no Vulkan filter modes that directly correspond to OpenGL minification filters of `GL_LINEAR` or `GL_NEAREST`, but they can be emulated using `VK_SAMPLER_MIPMAP_MODE_NEAREST`, `minLod` = 0, and `maxLod` = 0.25, and using `minFilter` = `VK_FILTER_LINEAR` or `minFilter` = `VK_FILTER_NEAREST`, respectively. Note that using a `maxLod` of zero would cause magnification to always be performed, and the `magFilter` to always be used. This is valid, just not an exact match for OpenGL behavior. Clamping the maximum LOD to 0.25 allows the λ value to be non-zero and minification to be performed, while still always rounding down to the base level. If the `minFilter` and `magFilter` are equal, then using a `maxLod` of zero also works.

`addressModeU`, `addressModeV`, and `addressModeW` must each have one of the following values:

    typedef enum VkSamplerAddressMode {
        VK_SAMPLER_ADDRESS_MODE_REPEAT = 0,
        VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1,
        VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2,
        VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3,
        VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4,
    } VkSamplerAddressMode;

These values control the behavior of sampling with coordinates outside the range [0,1] for the respective u, v, or w coordinate as defined in the Wrapping Operation section.

- `VK_SAMPLER_ADDRESS_MODE_REPEAT` indicates that the repeat wrap mode will be used.
- `VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT` indicates that the mirrored repeat wrap mode will be used.
- `VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE` indicates that the clamp to edge wrap mode will be used.
- `VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER` indicates that the clamp to border wrap mode will be used.
- `VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE` indicates that the mirror clamp to edge wrap mode will be used. This is only valid if the `VK_KHR_mirror_clamp_to_edge` extension is enabled.

The maximum number of sampler objects which can be simultaneously created on a device is implementation-dependent and specified by the `maxSamplerAllocationCount` member of the `VkPhysicalDeviceLimits` structure. If `maxSamplerAllocationCount` is exceeded, `vkCreateSampler` will return `VK_ERROR_TOO_MANY_OBJECTS`.

Since `VkSampler` is a non-dispatchable handle type, implementations may return the same handle for sampler state vectors that are identical. In such cases, all such objects would only count once against the `maxSamplerAllocationCount` limit.

To destroy a sampler, call:

    void vkDestroySampler(
        VkDevice                                    device,
        VkSampler                                   sampler,
        const VkAllocationCallbacks*                pAllocator);

- `device` is the logical device that destroys the sampler.
- `sampler` is the sampler to destroy.
- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.