/ chapters / textures.txt
textures.txt
   1  // Copyright (c) 2015-2019 Khronos Group. This work is licensed under a
   2  // Creative Commons Attribution 4.0 International License; see
   3  // http://creativecommons.org/licenses/by/4.0/
   4  
   5  [[textures]]
   6  = Image Operations
   7  
   8  == Image Operations Overview
   9  
  10  Vulkan Image Operations are operations performed by those SPIR-V Image
  11  Instructions which take an code:OpTypeImage (representing a
  12  sname:VkImageView) or code:OpTypeSampledImage (representing a
  13  (sname:VkImageView, sname:VkSampler) pair) and texel coordinates as
  14  operands, and return a value based on one or more neighboring texture
  15  elements (_texels_) in the image.
  16  
  17  [NOTE]
  18  .Note
  19  ====
  20  Texel is a term which is a combination of the words texture and element.
  21  Early interactive computer graphics supported texture operations on
  22  textures, a small subset of the image operations on images described here.
  23  The discrete samples remain essentially equivalent, however, so we retain
  24  the historical term texel to refer to them.
  25  ====
  26  
  27  Image Operations include the functionality of the following SPIR-V Image
  28  Instructions:
  29  
  30    * code:OpImageSample* and code:OpImageSparseSample* read one or more
  31      neighboring texels of the image, and <<textures-texel-filtering,filter>>
  32      the texel values based on the state of the sampler.
  33    ** Instructions with code:ImplicitLod in the name
  34       <<textures-level-of-detail-operation,determine>> the LOD used in the
  35       sampling operation based on the coordinates used in neighboring
  36       fragments.
  37    ** Instructions with code:ExplicitLod in the name
  38       <<textures-level-of-detail-operation,determine>> the LOD used in the
  39       sampling operation based on additional coordinates.
  40    ** Instructions with code:Proj in the name apply homogeneous
  41       <<textures-projection,projection>> to the coordinates.
  42    * code:OpImageFetch and code:OpImageSparseFetch return a single texel of
  43      the image.
  44      No sampler is used.
  45    * code:OpImage*code:Gather and code:OpImageSparse*code:Gather read
  46      neighboring texels and <<textures-gather,return a single component>> of
  47      each.
  48    * code:OpImageRead (and code:OpImageSparseRead) and code:OpImageWrite read
  49      and write, respectively, a texel in the image.
  50      No sampler is used.
  51  ifdef::VK_NV_shader_image_footprint[]
  52    * code:OpImageSampleFootprintNV identifies and returns information about
  53      the set of texels in the image that would be accessed by an equivalent
  54      code:OpImageSample* instruction.
  55  endif::VK_NV_shader_image_footprint[]
  56    * Instructions with code:Dref in the name apply
  57      <<textures-depth-compare-operation,depth comparison>> on the texel
  58      values.
  59    * Instructions with code:Sparse in the name additionally return a
  60      <<textures-sparse-residency,sparse residency>> code.
  61  
  62  [[textures-texel-coordinate-systems]]
  63  === Texel Coordinate Systems
  64  
  65  Images are addressed by _texel coordinates_.
  66  There are three _texel coordinate systems_:
  67  
  68    * normalized texel coordinates [eq]#[0.0, 1.0]#
  69    * unnormalized texel coordinates [eq]#[0.0, width / height / depth)#
  70    * integer texel coordinates [eq]#[0, width / height / depth)#
  71  
  72  SPIR-V code:OpImageFetch, code:OpImageSparseFetch, code:OpImageRead,
  73  code:OpImageSparseRead, and code:OpImageWrite instructions use integer texel
  74  coordinates.
  75  Other image instructions can: use either normalized or unnormalized texel
  76  coordinates (selected by the pname:unnormalizedCoordinates state of the
  77  sampler used in the instruction), but there are
  78  <<samplers-unnormalizedCoordinates,limitations>> on what operations, image
  79  state, and sampler state is supported.
  80  Normalized coordinates are logically
  81  <<textures-normalized-to-unnormalized,converted>> to unnormalized as part of
  82  image operations, and <<textures-normalized-operations,certain steps>> are
  83  only performed on normalized coordinates.
  84  The array layer coordinate is always treated as unnormalized even when other
  85  coordinates are normalized.
  86  
  87  Normalized texel coordinates are referred to as [eq]#(s,t,r,q,a)#, with the
  88  coordinates having the following meanings:
  89  
  90    * [eq]#s#: Coordinate in the first dimension of an image.
  91    * [eq]#t#: Coordinate in the second dimension of an image.
  92    * [eq]#r#: Coordinate in the third dimension of an image.
  93    ** [eq]#(s,t,r)# are interpreted as a direction vector for Cube images.
  94    * [eq]#q#: Fourth coordinate, for homogeneous (projective) coordinates.
  95    * [eq]#a#: Coordinate for array layer.
  96  
  97  The coordinates are extracted from the SPIR-V operand based on the
  98  dimensionality of the image variable and type of instruction.
  99  For code:Proj instructions, the components are in order [eq]#(s [,t] [,r]
 100  q)#, with [eq]#t# and [eq]#r# being conditionally present based on the
 101  code:Dim of the image.
 102  For non-code:Proj instructions, the coordinates are [eq]#(s [,t] [,r]
 103  [,a])#, with [eq]#t# and [eq]#r# being conditionally present based on the
 104  code:Dim of the image and [eq]#a# being conditionally present based on the
 105  code:Arrayed property of the image.
 106  Projective image instructions are not supported on code:Arrayed images.
 107  
 108  Unnormalized texel coordinates are referred to as [eq]#(u,v,w,a)#, with the
 109  coordinates having the following meanings:
 110  
 111    * [eq]#u#: Coordinate in the first dimension of an image.
 112    * [eq]#v#: Coordinate in the second dimension of an image.
 113    * [eq]#w#: Coordinate in the third dimension of an image.
 114    * [eq]#a#: Coordinate for array layer.
 115  
 116  Only the [eq]#u# and [eq]#v# coordinates are directly extracted from the
 117  SPIR-V operand, because only 1D and 2D (non-code:Arrayed) dimensionalities
 118  support unnormalized coordinates.
 119  The components are in order [eq]#(u [,v])#, with [eq]#v# being conditionally
 120  present when the dimensionality is 2D.
 121  When normalized coordinates are converted to unnormalized coordinates, all
 122  four coordinates are used.
 123  
 124  Integer texel coordinates are referred to as [eq]#(i,j,k,l,n)#, with the
 125  coordinates having the following meanings:
 126  
 127    * [eq]#i#: Coordinate in the first dimension of an image.
 128    * [eq]#j#: Coordinate in the second dimension of an image.
 129    * [eq]#k#: Coordinate in the third dimension of an image.
 130    * [eq]#l#: Coordinate for array layer.
 131    * [eq]#n#: Coordinate for the sample index.
 132  
 133  They are extracted from the SPIR-V operand in order [eq]#(i, [,j], [,k],
 134  [,l])#, with [eq]#j# and [eq]#k# conditionally present based on the code:Dim
 135  of the image, and [eq]#l# conditionally present based on the code:Arrayed
 136  property of the image.
 137  [eq]#n# is conditionally present and is taken from the code:Sample image
 138  operand.
 139  
 140  For all coordinate types, unused coordinates are assigned a value of zero.
 141  
 142  [[textures-texel-coordinate-systems-diagrams]]
 143  image::{images}/vulkantexture0-ll.svg[align="center",title="Texel Coordinate Systems, Linear Filtering",opts="{imageopts}"]
 144  The Texel Coordinate Systems - For the example shown of an 8{times}4 texel
 145  two dimensional image.
 146  
 147    * Normalized texel coordinates:
 148    ** The [eq]#s# coordinate goes from 0.0 to 1.0.
 149    ** The [eq]#t# coordinate goes from 0.0 to 1.0.
 150    * Unnormalized texel coordinates:
 151    ** The [eq]#u# coordinate within the range 0.0 to 8.0 is within the image,
 152       otherwise it is outside the image.
 153    ** The [eq]#v# coordinate within the range 0.0 to 4.0 is within the image,
 154       otherwise it is outside the image.
 155    * Integer texel coordinates:
 156    ** The [eq]#i# coordinate within the range 0 to 7 addresses texels within
 157       the image, otherwise it is outside the image.
 158    ** The [eq]#j# coordinate within the range 0 to 3 addresses texels within
 159       the image, otherwise it outside the image.
 160    * Also shown for linear filtering:
 161    ** Given the unnormalized coordinates [eq]#(u,v)#, the four texels
 162       selected are [eq]#i~0~j~0~#, [eq]#i~1~j~0~#, [eq]#i~0~j~1~#, and
 163       [eq]#i~1~j~1~#.
 164    ** The fractions [eq]#{alpha}# and [eq]#{beta}#.
 165    ** Given the offset [eq]#{DeltaUpper}~i~# and [eq]#{DeltaUpper}~j~#, the
 166       four texels selected by the offset are [eq]#i~0~j'~0~#,
 167       [eq]#i~1~j'~0~#, [eq]#i~0~j'~1~#, and [eq]#i~1~j'~1~#.
 168  
 169  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 170  [NOTE]
 171  .Note
 172  ====
 173  For formats with reduced-resolution channels, [eq]#{DeltaUpper}~i~# and
 174  [eq]#{DeltaUpper}~j~# are relative to the resolution of the
 175  highest-resolution channel, and therefore may be divided by two relative to
 176  the unnormalized coordinate space of the lower-resolution channels.
 177  ====
 178  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 179  
 180  image::{images}/vulkantexture1-ll.svg[align="center",title="Texel Coordinate Systems, Nearest Filtering",opts="{imageopts}"]
 181  
 182  The Texel Coordinate Systems - For the example shown of an 8{times}4 texel
 183  two dimensional image.
 184  
 185    * Texel coordinates as above.
 186      Also shown for nearest filtering:
 187    ** Given the unnormalized coordinates [eq]#(u,v)#, the texel selected is
 188       [eq]#ij#.
 189    ** Given the offset [eq]#{DeltaUpper}~i~# and [eq]#{DeltaUpper}~j~#, the
 190       texel selected by the offset is [eq]#ij'#.
 191  
 192  ifdef::VK_NV_corner_sampled_image[]
 193  For corner-sampled images, the texel samples are located at the grid
 194  intersections instead of the texel centers.
 195  
 196  image::{images}/vulkantexture0-corner-alternative-a-ll.svg[align="center",title="Texel Coordinate Systems, Corner Sampling",opts="{imageopts}"]
 197  
 198  endif::VK_NV_corner_sampled_image[]
 199  
 200  == Conversion Formulas
 201  
 202  ifdef::editing-notes[]
 203  [NOTE]
 204  .editing-note
 205  ====
 206  (Bill) These Conversion Formulas will likely move to Section 2.7 Fixed-Point
 207  Data Conversions (RGB to sRGB and sRGB to RGB) and section 2.6 Numeric
 208  Representation and Computation (RGB to Shared Exponent and Shared Exponent
 209  to RGB)
 210  ====
 211  endif::editing-notes[]
 212  
 213  [[textures-RGB-sexp]]
 214  === RGB to Shared Exponent Conversion
 215  
 216  An RGB color [eq]#(red, green, blue)# is transformed to a shared exponent
 217  color [eq]#(red~shared~, green~shared~, blue~shared~, exp~shared~)# as
 218  follows:
 219  
 220  First, the components [eq]#(red, green, blue)# are clamped to
 221  [eq]#(red~clamped~, green~clamped~, blue~clamped~)# as:
 222  
 223    :: [eq]#red~clamped~ = max(0, min(sharedexp~max~, red))#
 224    :: [eq]#green~clamped~ = max(0, min(sharedexp~max~, green))#
 225    :: [eq]#blue~clamped~ = max(0, min(sharedexp~max~, blue))#
 226  
 227  where:
 228  
 229  [latexmath]
 230  +++++++++++++++++++
 231  \begin{aligned}
 232  N               & = 9  & \text{number of mantissa bits per component} \\
 233  B               & = 15 & \text{exponent bias} \\
 234  E_{max}         & = 31 & \text{maximum possible biased exponent value} \\
 235  sharedexp_{max} & = \frac{(2^N-1)}{2^N} \times 2^{(E_{max}-B)}
 236  \end{aligned}
 237  +++++++++++++++++++
 238  
 239  [NOTE]
 240  .Note
 241  ====
 242  [eq]#NaN#, if supported, is handled as in <<ieee-754,IEEE 754-2008>>
 243  `minNum()` and `maxNum()`.
 244  That is the result is a [eq]#NaN# is mapped to zero.
 245  ====
 246  
 247  The largest clamped component, [eq]#max~clamped~# is determined:
 248  
 249    :: [eq]#max~clamped~ = max(red~clamped~, green~clamped~, blue~clamped~)#
 250  
 251  A preliminary shared exponent [eq]#exp'# is computed:
 252  [latexmath]
 253  +++++++++++++++++++
 254  \begin{aligned}
 255  exp' =
 256    \begin{cases}
 257      \left \lfloor \log_2(max_{clamped}) \right \rfloor + (B+1)
 258        & \text{for}\  max_{clamped} > 2^{-(B+1)} \\
 259      0
 260        & \text{for}\  max_{clamped} \leq 2^{-(B+1)}
 261    \end{cases}
 262  \end{aligned}
 263  +++++++++++++++++++
 264  
 265  The shared exponent [eq]#exp~shared~# is computed:
 266  
 267  [latexmath]
 268  +++++++++++++++++++
 269  \begin{aligned}
 270  max_{shared} =
 271      \left \lfloor
 272          { \frac{max_{clamped}}{2^{(exp'-B-N)}} + \frac{1}{2} }
 273      \right \rfloor
 274  \end{aligned}
 275  +++++++++++++++++++
 276  
 277  [latexmath]
 278  +++++++++++++++++++
 279  \begin{aligned}
 280  exp_{shared} =
 281    \begin{cases}
 282      exp'   & \text{for}\  0 \leq max_{shared} < 2^N \\
 283      exp'+1 & \text{for}\  max_{shared} = 2^N
 284    \end{cases}
 285  \end{aligned}
 286  +++++++++++++++++++
 287  
 288  Finally, three integer values in the range [eq]#0# to [eq]#2^N^# are
 289  computed:
 290  
 291  [latexmath]
 292  +++++++++++++++++++
 293  \begin{aligned}
 294  red_{shared} & =
 295      \left \lfloor
 296          { \frac{red_{clamped}}{2^{(exp_{shared}-B-N)}}+ \frac{1}{2} }
 297      \right \rfloor \\
 298  green_{shared} & =
 299      \left \lfloor
 300          { \frac{green_{clamped}}{2^{(exp_{shared}-B-N)}}+ \frac{1}{2} }
 301      \right \rfloor \\
 302  blue_{shared} & =
 303      \left \lfloor
 304          { \frac{blue_{clamped}}{2^{(exp_{shared}-B-N)}}+ \frac{1}{2} }
 305      \right \rfloor
 306  \end{aligned}
 307  +++++++++++++++++++
 308  
 309  
 310  [[textures-sexp-RGB]]
 311  === Shared Exponent to RGB
 312  
 313  A shared exponent color [eq]#(red~shared~, green~shared~, blue~shared~,
 314  exp~shared~)# is transformed to an RGB color [eq]#(red, green, blue)# as
 315  follows:
 316  
 317    :: latexmath:[red = red_{shared} \times {2^{(exp_{shared}-B-N)}}]
 318    :: latexmath:[green = green_{shared} \times {2^{(exp_{shared}-B-N)}}]
 319    :: latexmath:[blue = blue_{shared} \times {2^{(exp_{shared}-B-N)}}]
 320  
 321  where:
 322  
 323    :: [eq]#N = 9# (number of mantissa bits per component)
 324    :: [eq]#B = 15# (exponent bias)
 325  
 326  
 327  == Texel Input Operations
 328  
 329  _Texel input instructions_ are SPIR-V image instructions that read from an
 330  image.
 331  _Texel input operations_ are a set of steps that are performed on state,
 332  coordinates, and texel values while processing a texel input instruction,
 333  and which are common to some or all texel input instructions.
 334  They include the following steps, which are performed in the listed order:
 335  
 336    * <<textures-input-validation,Validation operations>>
 337    ** <<textures-operation-validation,Instruction/Sampler/Image validation>>
 338    ** <<textures-integer-coordinate-validation,Coordinate validation>>
 339    ** <<textures-sparse-validation,Sparse validation>>
 340    ** <<textures-layout-validation,Layout validation>>
 341    * <<textures-format-conversion,Format conversion>>
 342    * <<textures-texel-replacement,Texel replacement>>
 343    * <<textures-depth-compare-operation,Depth comparison>>
 344    * <<textures-conversion-to-rgba,Conversion to RGBA>>
 345    * <<textures-component-swizzle,Component swizzle>>
 346  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 347    * <<textures-chroma-reconstruction,Chroma reconstruction>>
 348    * <<textures-sampler-YCbCr-conversion,Y'C~B~C~R~ conversion>>
 349  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 350  
 351  For texel input instructions involving multiple texels (for sampling or
 352  gathering), these steps are applied for each texel that is used in the
 353  instruction.
 354  Depending on the type of image instruction, other steps are conditionally
 355  performed between these steps or involving multiple coordinate or texel
 356  values.
 357  
 358  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 359  If <<textures-chroma-reconstruction,Chroma Reconstruction>> is implicit,
 360  <<textures-texel-filtering, Texel Filtering>> instead takes place during
 361  chroma reconstruction, before <<textures-sampler-YCbCr-conversion,sampler
 362  Y'C~B~C~R~ conversion>> occurs.
 363  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 364  
 365  
 366  [[textures-input-validation]]
 367  === Texel Input Validation Operations
 368  
 369  _Texel input validation operations_ inspect instruction/image/sampler state
 370  or coordinates, and in certain circumstances cause the texel value to be
 371  replaced or become undefined:.
 372  There are a series of validations that the texel undergoes.
 373  
 374  [[textures-operation-validation]]
 375  ==== Instruction/Sampler/Image View Validation
 376  
 377  There are a number of cases where a SPIR-V instruction can: mismatch with
 378  the sampler, the image view, or both.
 379  There are a number of cases where the sampler can: mismatch with the image
 380  view.
 381  In such cases the value of the texel returned is undefined:.
 382  
 383  These cases include:
 384  
 385  
 386    * The sampler pname:borderColor is an integer type and the image view
 387      pname:format is not one of the elink:VkFormat integer types or a stencil
 388      component of a depth/stencil format.
 389    * The sampler pname:borderColor is a float type and the image view
 390      pname:format is not one of the elink:VkFormat float types or a depth
 391      component of a depth/stencil format.
 392    * The sampler pname:borderColor is one of the opaque black colors
 393      (ename:VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK or
 394      ename:VK_BORDER_COLOR_INT_OPAQUE_BLACK) and the image view
 395      elink:VkComponentSwizzle for any of the slink:VkComponentMapping
 396      components is not ename:VK_COMPONENT_SWIZZLE_IDENTITY.
 397    * The elink:VkImageLayout of any subresource in the image view does not
 398      match that specified in slink:VkDescriptorImageInfo::pname:imageLayout
 399      used to write the image descriptor.
 400    * If the instruction is code:OpImageRead or code:OpImageSparseRead and the
 401      pname:shaderStorageImageReadWithoutFormat feature is not enabled, or the
 402      instruction is code:OpImageWrite and the
 403      pname:shaderStorageImageWriteWithoutFormat feature is not enabled, then
 404      the SPIR-V Image Format must: be <<spirvenv-image-formats,compatible>>
 405      with the image view's pname:format.
 406    * The sampler pname:unnormalizedCoordinates is ename:VK_TRUE and any of
 407      the <<samplers-unnormalizedCoordinates,limitations of unnormalized
 408      coordinates>> are violated.
 409  ifdef::VK_EXT_fragment_density_map[]
 410    * The sampler was created with pname:flags containing
 411      ename:VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT and the image was not created
 412      with pname:flags containing ename:VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT.
 413    * The sampler was not created with pname:flags containing
 414      ename:VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT and the image was created
 415      with pname:flags containing ename:VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT.
 416    * The sampler was created with pname:flags containing
 417      ename:VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT and is used with a function
 418      that is not code:OpImageSampleImplicitLod or
 419      code:OpImageSampleExplicitLod, or is used with operands code:Offset or
 420      code:ConstOffsets.
 421  endif::VK_EXT_fragment_density_map[]
 422    * The SPIR-V instruction is one of the code:OpImage*code:Dref*
 423      instructions and the sampler pname:compareEnable is ename:VK_FALSE
 424    * The SPIR-V instruction is not one of the code:OpImage*code:Dref*
 425      instructions and the sampler pname:compareEnable is ename:VK_TRUE
 426    * The SPIR-V instruction is one of the code:OpImage*code:Dref*
 427      instructions and the image view pname:format is not one of the
 428      depth/stencil formats with a depth component, or the image view aspect
 429      is not ename:VK_IMAGE_ASPECT_DEPTH_BIT.
 430    * The SPIR-V instruction's image variable's properties are not compatible
 431      with the image view:
 432    ** Rules for pname:viewType:
 433    *** ename:VK_IMAGE_VIEW_TYPE_1D must: have code:Dim = 1D, code:Arrayed =
 434        0, code:MS = 0.
 435    *** ename:VK_IMAGE_VIEW_TYPE_2D must: have code:Dim = 2D, code:Arrayed =
 436        0.
 437    *** ename:VK_IMAGE_VIEW_TYPE_3D must: have code:Dim = 3D, code:Arrayed =
 438        0, code:MS = 0.
 439    *** ename:VK_IMAGE_VIEW_TYPE_CUBE must: have code:Dim = Cube, code:Arrayed
 440        = 0, code:MS = 0.
 441    *** ename:VK_IMAGE_VIEW_TYPE_1D_ARRAY must: have code:Dim = 1D,
 442        code:Arrayed = 1, code:MS = 0.
 443    *** ename:VK_IMAGE_VIEW_TYPE_2D_ARRAY must: have code:Dim = 2D,
 444        code:Arrayed = 1.
 445    *** ename:VK_IMAGE_VIEW_TYPE_CUBE_ARRAY must: have code:Dim = Cube,
 446        code:Arrayed = 1, code:MS = 0.
 447    ** If the image was created with slink:VkImageCreateInfo::pname:samples
 448       equal to ename:VK_SAMPLE_COUNT_1_BIT, the instruction must: have
 449       code:MS = 0.
 450    ** If the image was created with slink:VkImageCreateInfo::pname:samples
 451       not equal to ename:VK_SAMPLE_COUNT_1_BIT, the instruction must: have
 452       code:MS = 1.
 453  ifdef::VK_NV_corner_sampled_image[]
 454    * If the image was created with slink:VkImageCreateInfo::pname:flags
 455      containing ename:VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV, the sampler
 456      addressing modes must: only use a elink:VkSamplerAddressMode of
 457      ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
 458  endif::VK_NV_corner_sampled_image[]
 459  ifdef::VK_NV_shader_image_footprint[]
 460    * The SPIR-V instruction is code:OpImageSampleFootprintNV with code:Dim =
 461      2D and pname:addressModeU or pname:addressModeV in the sampler is not
 462      ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
 463    * The SPIR-V instruction is code:OpImageSampleFootprintNV with code:Dim =
 464      3D and pname:addressModeU, pname:addressModeV, or pname:addressModeW in
 465      the sampler is not ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
 466  endif::VK_NV_shader_image_footprint[]
 467  
 468  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 469  Only code:OpImageSample* and code:OpImageSparseSample* can: be used with a
 470  sampler that enables <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~
 471  conversion>>.
 472  
 473  code:OpImageFetch, code:OpImageSparseFetch, code:OpImage*code:Gather, and
 474  code:OpImageSparse*code:Gather must: not be used with a sampler that enables
 475  <<samplers-YCbCr-conversion,sampler Y\'C~B~C~R~ conversion>>.
 476  
 477  The code:ConstOffset and code:Offset operands must: not be used with a
 478  sampler that enables <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~
 479  conversion>>.
 480  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 481  
 482  
 483  [[textures-integer-coordinate-validation]]
 484  ==== Integer Texel Coordinate Validation
 485  
 486  Integer texel coordinates are validated against the size of the image level,
 487  and the number of layers and number of samples in the image.
 488  For SPIR-V instructions that use integer texel coordinates, this is
 489  performed directly on the integer coordinates.
 490  For instructions that use normalized or unnormalized texel coordinates, this
 491  is performed on the coordinates that result after
 492  <<textures-unnormalized-to-integer,conversion>> to integer texel
 493  coordinates.
 494  
 495  If the integer texel coordinates do not satisfy all of the conditions
 496  
 497    :: [eq]#0 {leq} i < w~s~#
 498    :: [eq]#0 {leq} j < h~s~#
 499    :: [eq]#0 {leq} k < d~s~#
 500    :: [eq]#0 {leq} l < layers#
 501    :: [eq]#0 {leq} n < samples#
 502  
 503  where:
 504  
 505    :: [eq]#w~s~ =# width of the image level
 506    :: [eq]#h~s~ =# height of the image level
 507    :: [eq]#d~s~ =# depth of the image level
 508    :: [eq]#layers =# number of layers in the image
 509    :: [eq]#samples =# number of samples per texel in the image
 510  
 511  then the texel fails integer texel coordinate validation.
 512  
 513  There are four cases to consider:
 514  
 515    . Valid Texel Coordinates
 516  +
 517    * If the texel coordinates pass validation (that is, the coordinates lie
 518       within the image),
 519  +
 520  then the texel value comes from the value in image memory.
 521  
 522    . Border Texel
 523  +
 524    * If the texel coordinates fail validation, and
 525    * If the read is the result of an image sample instruction or image gather
 526       instruction, and
 527    * If the image is not a cube image,
 528  +
 529  then the texel is a border texel and <<textures-texel-replacement,texel
 530  replacement>> is performed.
 531  
 532    . Invalid Texel
 533  +
 534    * If the texel coordinates fail validation, and
 535    * If the read is the result of an image fetch instruction, image read
 536      instruction, or atomic instruction,
 537  +
 538  then the texel is an invalid texel and <<textures-texel-replacement,texel
 539  replacement>> is performed.
 540  
 541    . Cube Map Edge or Corner
 542  +
 543  Otherwise the texel coordinates lie beyond the edges or corners of the
 544  selected cube map face, and <<textures-cubemapedge, Cube map edge handling>>
 545  is performed.
 546  
 547  
 548  [[textures-cubemapedge]]
 549  ==== Cube Map Edge Handling
 550  
 551  If the texel coordinates lie beyond the edges or corners of the selected
 552  cube map face, the following steps are performed.
 553  Note that this does not occur when using ename:VK_FILTER_NEAREST filtering
 554  within a mip level, since ename:VK_FILTER_NEAREST is treated as using
 555  ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
 556  
 557    * Cube Map Edge Texel
 558  +
 559    ** If the texel lies beyond the selected cube map face in either only
 560      [eq]#i# or only [eq]#j#, then the coordinates [eq]#(i,j)# and the array
 561      layer [eq]#l# are transformed to select the adjacent texel from the
 562      appropriate neighboring face.
 563  
 564    * Cube Map Corner Texel
 565  +
 566    ** If the texel lies beyond the selected cube map face in both [eq]#i# and
 567       [eq]#j#, then there is no unique neighboring face from which to read
 568       that texel.
 569       The texel should: be replaced by the average of the three values of the
 570       adjacent texels in each incident face.
 571       However, implementations may: replace the cube map corner texel by
 572       other methods.
 573  ifndef::VK_EXT_filter_cubic[]
 574  The methods are subject to the constraint that if the three available texels
 575  have the same value, the resulting filtered texel must: have that value.
 576  endif::VK_EXT_filter_cubic[]
 577  ifdef::VK_EXT_filter_cubic[]
 578  The methods are subject to the constraint that for linear filtering if the
 579  three available texels have the same value, the resulting filtered texel
 580  must: have that value, and for cubic filtering if the twelve available
 581  samples have the same value, the resulting filtered texel must: have that
 582  value.
 583  endif::VK_EXT_filter_cubic[]
 584  
 585  [[textures-sparse-validation]]
 586  ==== Sparse Validation
 587  
 588  If the texel reads from an unbound region of a sparse image, the texel is a
 589  _sparse unbound texel_, and processing continues with
 590  <<textures-texel-replacement,texel replacement>>.
 591  
 592  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 593  
 594  [[textures-layout-validation]]
 595  ==== Layout Validation
 596  
 597  If all planes of a _disjoint_ _multi-planar_ image are not in the same
 598  <<resources-image-layouts,image layout>>, the image must: not be sampled
 599  with <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~ conversion>> enabled.
 600  
 601  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 602  
 603  [[textures-format-conversion]]
 604  === Format Conversion
 605  
 606  Texels undergo a format conversion from the elink:VkFormat of the image view
 607  to a vector of either floating point or signed or unsigned integer
 608  components, with the number of components based on the number of components
 609  present in the format.
 610  
 611    * Color formats have one, two, three, or four components, according to the
 612      format.
 613    * Depth/stencil formats are one component.
 614      The depth or stencil component is selected by the pname:aspectMask of
 615      the image view.
 616  
 617  Each component is converted based on its type and size (as defined in the
 618  <<formats-definition,Format Definition>> section for each elink:VkFormat),
 619  using the appropriate equations in <<fundamentals-fp16,16-Bit Floating-Point
 620  Numbers>>, <<fundamentals-fp11,Unsigned 11-Bit Floating-Point Numbers>>,
 621  <<fundamentals-fp10,Unsigned 10-Bit Floating-Point Numbers>>,
 622  <<fundamentals-fixedconv,Fixed-Point Data Conversion>>, and
 623  <<textures-sexp-RGB,Shared Exponent to RGB>>.
 624  Signed integer components smaller than 32 bits are sign-extended.
 625  
 626  If the image view format is sRGB, the color components are first converted
 627  as if they are UNORM, and then sRGB to linear conversion is applied to the
 628  R, G, and B components as described in the "`sRGB EOTF`" section of the
 629  <<data-format,Khronos Data Format Specification>>.
 630  The A component, if present, is unchanged.
 631  
 632  If the image view format is block-compressed, then the texel value is first
 633  decoded, then converted based on the type and number of components defined
 634  by the compressed format.
 635  
 636  
 637  [[textures-texel-replacement]]
 638  === Texel Replacement
 639  
 640  A texel is replaced if it is one (and only one) of:
 641  
 642    * a border texel,
 643    * an invalid texel, or
 644    * a sparse unbound texel.
 645  
 646  Border texels are replaced with a value based on the image format and the
 647  pname:borderColor of the sampler.
 648  The border color is:
 649  
 650  [[textures-border-replacement-color]]
 651  .Border Color [eq]#B#
 652  [options="header",cols="60%,40%"]
 653  |====
 654  | Sampler pname:borderColor                     | Corresponding Border Color
 655  | ename:VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK | [eq]#[B~r~, B~g~, B~b~, B~a~] = [0.0, 0.0, 0.0, 0.0]#
 656  | ename:VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK      | [eq]#[B~r~, B~g~, B~b~, B~a~] = [0.0, 0.0, 0.0, 1.0]#
 657  | ename:VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE      | [eq]#[B~r~, B~g~, B~b~, B~a~] = [1.0, 1.0, 1.0, 1.0]#
 658  | ename:VK_BORDER_COLOR_INT_TRANSPARENT_BLACK   | [eq]#[B~r~, B~g~, B~b~, B~a~] = [0, 0, 0, 0]#
 659  | ename:VK_BORDER_COLOR_INT_OPAQUE_BLACK        | [eq]#[B~r~, B~g~, B~b~, B~a~] = [0, 0, 0, 1]#
 660  | ename:VK_BORDER_COLOR_INT_OPAQUE_WHITE        | [eq]#[B~r~, B~g~, B~b~, B~a~] = [1, 1, 1, 1]#
 661  |====
 662  
 663  [NOTE]
 664  .Note
 665  ====
 666  The names etext:VK_BORDER_COLOR_*\_TRANSPARENT_BLACK,
 667  etext:VK_BORDER_COLOR_*\_OPAQUE_BLACK, and
 668  etext:VK_BORDER_COLOR_*_OPAQUE_WHITE are meant to describe which components
 669  are zeros and ones in the vocabulary of compositing, and are not meant to
 670  imply that the numerical value of ename:VK_BORDER_COLOR_INT_OPAQUE_WHITE is
 671  a saturating value for integers.
 672  ====
 673  
 674  This is substituted for the texel value by replacing the number of
 675  components in the image format
 676  
 677  [[textures-border-replacement-table]]
 678  .Border Texel Components After Replacement
 679  [width="100%",options="header"]
 680  |====
 681  | Texel Aspect or Format      | Component Assignment
 682  | Depth aspect                | [eq]#D                                     = B~r~#
 683  | Stencil aspect              | [eq]#S                                     = B~r~#
 684  | One component color format  | [eq]#Color~r~                              = B~r~#
 685  | Two component color format  | [eq]#[Color~r~,Color~g~]                   = [B~r~,B~g~]#
 686  | Three component color format| [eq]#[Color~r~,Color~g~,Color~b~]          = [B~r~,B~g~,B~b~]#
 687  | Four component color format | [eq]#[Color~r~,Color~g~,Color~b~,Color~a~] = [B~r~,B~g~,B~b~,B~a~]#
 688  |====
 689  
 690  The value returned by a read of an invalid texel is undefined:, unless that
 691  read operation is from a buffer resource and the pname:robustBufferAccess
 692  feature is enabled.
 693  In that case, an invalid texel is replaced as described by the
 694  <<features-robustBufferAccess,pname:robustBufferAccess feature>>.
 695  
 696  If the
 697  slink:VkPhysicalDeviceSparseProperties::pname:residencyNonResidentStrict
 698  property is ename:VK_TRUE, a sparse unbound texel is replaced with 0 or 0.0
 699  values for integer and floating-point components of the image format,
 700  respectively.
 701  
 702  If pname:residencyNonResidentStrict is ename:VK_FALSE, the value of the
 703  sparse unbound texel is undefined:.
 704  
 705  
 706  [[textures-depth-compare-operation]]
 707  === Depth Compare Operation
 708  
 709  If the image view has a depth/stencil format, the depth component is
 710  selected by the pname:aspectMask, and the operation is a code:Dref
 711  instruction, a depth comparison is performed.
 712  The value of the result [eq]#D# is [eq]#1.0# if the result of the compare
 713  operation is [eq]#true#, and [eq]#0.0# otherwise.
 714  The compare operation is selected by the pname:compareOp member of the
 715  sampler.
 716  
 717  [latexmath]
 718  +++++++++++++++++++
 719  \begin{aligned}
 720  D & = 1.0 &
 721    \begin{cases}
 722      D_{\textit{ref}} \leq D & \text{for LEQUAL}   \\
 723      D_{\textit{ref}} \geq D & \text{for GEQUAL}   \\
 724      D_{\textit{ref}} < D    & \text{for LESS}     \\
 725      D_{\textit{ref}} > D    & \text{for GREATER}  \\
 726      D_{\textit{ref}} = D    & \text{for EQUAL}    \\
 727      D_{\textit{ref}} \neq D & \text{for NOTEQUAL} \\
 728      \textit{true}           & \text{for ALWAYS}   \\
 729      \textit{false}          & \text{for NEVER}
 730    \end{cases} \\
 731  D & = 0.0 & \text{otherwise}
 732  \end{aligned}
 733  +++++++++++++++++++
 734  
 735  where, in the depth comparison:
 736  
 737    :: [eq]#D~ref~ = shaderOp.D~ref~# (from optional: SPIR-V operand)
 738    :: [eq]#D# (texel depth value)
 739  
 740  
 741  [[textures-conversion-to-rgba]]
 742  === Conversion to RGBA
 743  
 744  The texel is expanded from one, two, or three components to four components
 745  based on the image base color:
 746  
 747  [[textures-texel-color-rgba-conversion-table]]
 748  .Texel Color After Conversion To RGBA
 749  [width="100%", options="header", cols="<4,<6"]
 750  |====
 751  | Texel Aspect or Format      | RGBA Color
 752  | Depth aspect                | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [D,0,0,one]#
 753  | Stencil aspect              | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [S,0,0,one]#
 754  | One component color format  | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [Color~r~,0,0,one]#
 755  | Two component color format  | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [Color~r~,Color~g~,0,one]#
 756  | Three component color format| [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [Color~r~,Color~g~,Color~b~,one]#
 757  | Four component color format | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [Color~r~,Color~g~,Color~b~,Color~a~]#
 758  |====
 759  
 760  where [eq]#one = 1.0f# for floating-point formats and depth aspects, and
 761  [eq]#one = 1# for integer formats and stencil aspects.
 762  
 763  
 764  [[textures-component-swizzle]]
 765  === Component Swizzle
 766  
 767  ifndef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 768  All texel input instructions apply a _swizzle_ based on the
 769  elink:VkComponentSwizzle enums in the pname:components member of the
 770  slink:VkImageViewCreateInfo structure for the image being read.
 771  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 772  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 773  All texel input instructions apply a _swizzle_ based on:
 774  
 775    * the elink:VkComponentSwizzle enums in the pname:components member of the
 776      slink:VkImageViewCreateInfo structure for the image being read if
 777      <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~ conversion>> is not
 778      enabled, and
 779    * the elink:VkComponentSwizzle enums in the pname:components member of the
 780      slink:VkSamplerYcbcrConversionCreateInfo structure for the
 781      <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~ conversion>> if sampler
 782      Y'C~B~C~R~ conversion is enabled.
 783  
 784  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 785  
 786  The swizzle can: rearrange the components of the texel, or substitute zero
 787  or one for any components.
 788  It is defined as follows for each color [eq]#component#:
 789  
 790  
 791  [latexmath]
 792  +++++++++++++++++++
 793  \begin{aligned}
 794  Color'_{component} & =
 795  \begin{cases}
 796  Color_r          & \text{for RED swizzle}   \\
 797  Color_g          & \text{for GREEN swizzle} \\
 798  Color_b          & \text{for BLUE swizzle}  \\
 799  Color_a          & \text{for ALPHA swizzle} \\
 800  0                & \text{for ZERO swizzle}  \\
 801  one              & \text{for ONE swizzle} \\
 802  identity         & \text{for IDENTITY swizzle}
 803  \end{cases}
 804  \end{aligned}
 805  +++++++++++++++++++
 806  
 807  where:
 808  
 809  [latexmath]
 810  +++++++++++++++++++
 811  \begin{aligned}
 812  one & =
 813  \begin{cases}
 814  & 1.0\text{f}  & \text{for floating point components} \\
 815  & 1            & \text{for integer components} \\
 816  \end{cases}
 817  \\
 818  identity & =
 819  \begin{cases}
 820  & Color_r          & \text{for}\ component = r \\
 821  & Color_g          & \text{for}\ component = g \\
 822  & Color_b          & \text{for}\ component = b \\
 823  & Color_a          & \text{for}\ component = a \\
 824  \end{cases}
 825  \end{aligned}
 826  +++++++++++++++++++
 827  
 828  If the border color is one of the etext:VK_BORDER_COLOR_*_OPAQUE_BLACK enums
 829  and the elink:VkComponentSwizzle is not ename:VK_COMPONENT_SWIZZLE_IDENTITY
 830  for all components (or the
 831  <<resources-image-views-identity-mappings,equivalent identity mapping>>),
 832  the value of the texel after swizzle is undefined:.
 833  
 834  [[textures-sparse-residency]]
 835  === Sparse Residency
 836  
 837  code:OpImageSparse* instructions return a structure which includes a
 838  _residency code_ indicating whether any texels accessed by the instruction
 839  are sparse unbound texels.
 840  This code can: be interpreted by the code:OpImageSparseTexelsResident
 841  instruction which converts the residency code to a boolean value.
 842  
 843  
 844  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
 845  [[textures-chroma-reconstruction]]
 846  === Chroma Reconstruction
 847  
 848  In some color models, the color representation is defined in terms of
 849  monochromatic light intensity (often called "`luma`") and color differences
 850  relative to this intensity, often called "`chroma`".
 851  It is common for color models other than RGB to represent the chroma
 852  channels at lower spatial resolution than the luma channel.
 853  This approach is used to take advantage of the eye's lower spatial
 854  sensitivity to color compared with its sensitivity to brightness.
 855  Less commonly, the same approach is used with additive color, since the
 856  green channel dominates the eye's sensitivity to light intensity and the
 857  spatial sensitivity to color introduced by red and blue is lower.
 858  
 859  Lower-resolution channels are "`downsampled`" by resizing them to a lower
 860  spatial resolution than the channel representing luminance.
 861  The process of reconstructing a full color value for texture access involves
 862  accessing both chroma and luma values at the same location.
 863  To generate the color accurately, the values of the lower-resolution
 864  channels at the location of the luma samples must be reconstructed from the
 865  lower-resolution sample locations, an operation known here as "`chroma
 866  reconstruction`" irrespective of the actual color model.
 867  
 868  The location of the chroma samples relative to the luma coordinates is
 869  determined by the pname:xChromaOffset and pname:yChromaOffset members of the
 870  slink:VkSamplerYcbcrConversionCreateInfo structure used to create the
 871  sampler Y'C~B~C~R~ conversion.
 872  
 873  The following diagrams show the relationship between unnormalized (_u_,_v_)
 874  coordinates and (_i_,_j_) integer texel positions in the luma channel (shown
 875  in black, with circles showing integer sample positions) and the texel
 876  coordinates of reduced-resolution chroma channels, shown as crosses in red.
 877  
 878  [NOTE]
 879  .Note
 880  ====
 881  If the chroma values are reconstructed at the locations of the luma samples
 882  by means of interpolation, chroma samples from outside the image bounds are
 883  needed; these are determined according to <<textures-wrapping-operation>>.
 884  These diagrams represent this by showing the bounds of the "`chroma texel`"
 885  extending beyond the image bounds, and including additional chroma sample
 886  positions where required for interpolation.
 887  The limits of a sample for etext:NEAREST sampling is shown as a grid.
 888  ====
 889  
 890  image::{images}/chromasamples_422_cosited.svg[align="center",title="422 downsampling, xChromaOffset=COSITED_EVEN",opts="{imageopts}"]
 891  
 892  image::{images}/chromasamples_422_midpoint.svg[align="center",title="422 downsampling, xChromaOffset=MIDPOINT",opts="{imageopts}"]
 893  
 894  image::{images}/chromasamples_420_xcosited_ycosited.svg[align="center",title="420 downsampling, xChromaOffset=COSITED_EVEN, yChromaOffset=COSITED_EVEN",opts="{imageopts}"]
 895  
 896  image::{images}/chromasamples_420_xmidpoint_ycosited.svg[align="center",title="420 downsampling, xChromaOffset=MIDPOINT, yChromaOffset=COSITED_EVEN",opts="{imageopts}"]
 897  
 898  image::{images}/chromasamples_420_xcosited_ymidpoint.svg[align="center",title="420 downsampling, xChromaOffset=COSITED_EVEN, yChromaOffset=MIDPOINT",opts="{imageopts}"]
 899  
 900  image::{images}/chromasamples_420_xmidpoint_ymidpoint.svg[align="center",title="420 downsampling, xChromaOffset=MIDPOINT, yChromaOffset=MIDPOINT",opts="{imageopts}"]
 901  
 902  Reconstruction is implemented in one of two ways:
 903  
 904  If the format of the image that is to be sampled sets
 905  ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT,
 906  or the sname:VkSamplerYcbcrConversionCreateInfo's
 907  pname:forceExplicitReconstruction is set to ename:VK_TRUE, reconstruction is
 908  performed as an explicit step independent of filtering, described in the
 909  <<textures-explicit-reconstruction>> section.
 910  
 911  If the format of the image that is to be sampled does not set
 912  ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT
 913  and if the sname:VkSamplerYcbcrConversionCreateInfo's
 914  pname:forceExplicitReconstruction is set to ename:VK_FALSE, reconstruction
 915  is performed as an implicit part of filtering prior to color model
 916  conversion, with no separate post-conversion texel filtering step, as
 917  described in the <<textures-implict-reconstruction,Implicit Reconstruction>>
 918  section.
 919  
 920  [[textures-explicit-reconstruction]]
 921  ==== Explicit Reconstruction
 922  
 923    * If the pname:chromaFilter member of the
 924      slink:VkSamplerYcbcrConversionCreateInfo structure is
 925      ename:VK_FILTER_NEAREST:
 926    ** If the format's R and B channels are reduced in resolution in just
 927       width by a factor of two relative to the G channel (i.e. this is a
 928       "`etext:_422`" format), the latexmath:[\tau_{ijk}[level\]] values
 929       accessed by <<textures-texel-filtering,texel filtering>> are
 930       reconstructed as follows:
 931  +
 932  [latexmath]
 933  ++++++++++++++
 934  \begin{aligned}
 935  \tau_R'(i, j) & = \tau_R(\lfloor{i\times 0.5}\rfloor, j)[level] \\
 936  \tau_B'(i, j) & = \tau_B(\lfloor{i\times 0.5}\rfloor, j)[level]
 937  \end{aligned}
 938  ++++++++++++++
 939  
 940    ** If the format's R and B channels are reduced in resolution in width and
 941       height by a factor of two relative to the G channel (i.e. this is a
 942       "`etext:_420`" format), the latexmath:[\tau_{ijk}[level\]] values
 943       accessed by <<textures-texel-filtering,texel filtering>> are
 944       reconstructed as follows:
 945  +
 946  [latexmath]
 947  ++++++++++++++
 948  \begin{aligned}
 949  \tau_R'(i, j) & = \tau_R(\lfloor{i\times 0.5}\rfloor, \lfloor{j\times 0.5}\rfloor)[level] \\
 950  \tau_B'(i, j) & = \tau_B(\lfloor{i\times 0.5}\rfloor, \lfloor{j\times 0.5}\rfloor)[level]
 951  \end{aligned}
 952  ++++++++++++++
 953  +
 954  [NOTE]
 955  .Note
 956  ====
 957  pname:xChromaOffset and pname:yChromaOffset have no effect if
 958  pname:chromaFilter is ename:VK_FILTER_NEAREST for explicit reconstruction.
 959  ====
 960  
 961    * If the pname:chromaFilter member of the
 962      slink:VkSamplerYcbcrConversionCreateInfo structure is
 963      ename:VK_FILTER_LINEAR:
 964    ** If the format's R and B channels are reduced in resolution in just
 965       width by a factor of two relative to the G channel (i.e. this is a
 966       "`422`" format):
 967    *** If pname:xChromaOffset is ename:VK_CHROMA_LOCATION_COSITED_EVEN:
 968  +
 969  [latexmath]
 970  +++++
 971  \tau_{RB}'(i,j) = \begin{cases}
 972  \tau_{RB}(\lfloor{i\times 0.5}\rfloor,j)[level], & 0.5 \times i = \lfloor{0.5 \times i}\rfloor\\
 973  0.5\times\tau_{RB}(\lfloor{i\times 0.5}\rfloor,j)[level] + \\
 974  0.5\times\tau_{RB}(\lfloor{i\times 0.5}\rfloor + 1,j)[level], & 0.5 \times i \neq \lfloor{0.5 \times i}\rfloor
 975  \end{cases}
 976  +++++
 977  +
 978    *** If pname:xChromaOffset is ename:VK_CHROMA_LOCATION_MIDPOINT:
 979  +
 980  [latexmath]
 981  +++++
 982  \tau_{RB}(i,j)' = \begin{cases}
 983  0.25 \times \tau_{RB}(\lfloor{i\times 0.5}\rfloor - 1,j)[level] + \\
 984  0.75 \times \tau_{RB}(\lfloor{i\times 0.5}\rfloor,j)[level], & 0.5 \times i = \lfloor{0.5 \times i}\rfloor\\
 985  0.75 \times \tau_{RB}(\lfloor{i\times 0.5}\rfloor,j)[level] + \\
 986  0.25 \times \tau_{RB}(\lfloor{i\times 0.5}\rfloor + 1,j)[level], & 0.5 \times i \neq \lfloor{0.5 \times i}\rfloor
 987  \end{cases}
 988  +++++
 989  
 990    ** If the format's R and B channels are reduced in resolution in width and
 991       height by a factor of two relative to the G channel (i.e. this is a
 992       "`420`" format), a similar relationship applies.
 993       Due to the number of options, these formulae are expressed more
 994       concisely as follows:
 995  +
 996  [latexmath]
 997  +++++
 998  \begin{aligned}
 999    i_{RB} & =
1000      \begin{cases}
1001        0.5 \times (i) & \textrm{If xChromaOffset = COSITED}\_\textrm{EVEN} \\
1002        0.5 \times (i - 0.5) & \textrm{If xChromaOffset = MIDPOINT}
1003      \end{cases}\\
1004    j_{RB} & =
1005      \begin{cases}
1006        0.5 \times (j) & \textrm{If yChromaOffset = COSITED}\_\textrm{EVEN} \\
1007        0.5 \times (j - 0.5) & \textrm{If yChromaOffset = MIDPOINT}
1008      \end{cases}\\
1009    \\
1010    i_{floor} & = \lfloor i_{RB} \rfloor \\
1011    j_{floor} & = \lfloor j_{RB} \rfloor \\
1012    \\
1013    i_{frac} & = i_{RB} - i_{floor} \\
1014    j_{frac} & = j_{RB} - j_{floor}
1015  \end{aligned}
1016  +++++
1017  +
1018  [latexmath]
1019  +++++
1020  \begin{aligned}
1021  \tau_{RB}'(i,j) =
1022      & \tau_{RB}(     i_{floor},     j_{floor})[level]
1023          & \times & ( 1 - i_{frac} ) &
1024          & \times & ( 1 - j_{frac} ) & + \\
1025      & \tau_{RB}( 1 + i_{floor},     j_{floor})[level]
1026          & \times & (     i_{frac} ) &
1027          & \times & ( 1 - j_{frac} ) & + \\
1028      & \tau_{RB}(     i_{floor}, 1 + j_{floor})[level]
1029          & \times & ( 1 - i_{frac} ) &
1030          & \times & (     j_{frac} ) & + \\
1031      & \tau_{RB}( 1 + i_{floor}, 1 + j_{floor})[level]
1032          & \times & (     i_{frac} ) &
1033          & \times & (     j_{frac} ) &
1034  \end{aligned}
1035  +++++
1036  
1037  [NOTE]
1038  .Note
1039  ====
1040  In the case where the texture itself is bilinearly interpolated as described
1041  in <<textures-texel-filtering,Texel Filtering>>, thus requiring four
1042  full-color samples for the filtering operation, and where the reconstruction
1043  of these samples uses bilinear interpolation in the chroma channels due to
1044  pname:chromaFilter=ename:VK_FILTER_LINEAR, up to nine chroma samples may be
1045  required, depending on the sample location.
1046  ====
1047  
1048  
1049  [[textures-implict-reconstruction]]
1050  ==== Implicit Reconstruction
1051  
1052  Implicit reconstruction takes place by the samples being interpolated, as
1053  required by the filter settings of the sampler, except that
1054  pname:chromaFilter takes precedence for the chroma samples.
1055  
1056  If pname:chromaFilter is ename:VK_FILTER_NEAREST, an implementation may:
1057  behave as if pname:xChromaOffset and pname:yChromaOffset were both
1058  ename:VK_CHROMA_LOCATION_MIDPOINT, irrespective of the values set.
1059  
1060  [NOTE]
1061  .Note
1062  ====
1063  This will not have any visible effect if the locations of the luma samples
1064  coincide with the location of the samples used for rasterization.
1065  ====
1066  
1067  The sample coordinates are adjusted by the downsample factor of the channel
1068  (such that, for example, the sample coordinates are divided by two if the
1069  channel has a downsample factor of two relative to the luma channel):
1070  
1071  [latexmath]
1072  ++++++
1073  \begin{aligned}
1074  u_{RB}' (422/420) &=
1075    \begin{cases}
1076       0.5\times (u + 0.5), & \textrm{xChromaOffset = COSITED}\_\textrm{EVEN} \\
1077       0.5\times u, & \textrm{xChromaOffset = MIDPOINT}
1078    \end{cases} \\
1079  v_{RB}' (420) &=
1080    \begin{cases}
1081       0.5\times (v + 0.5), & \textrm{yChromaOffset = COSITED}\_\textrm{EVEN} \\
1082       0.5\times v, & \textrm{yChromaOffset = MIDPOINT}
1083    \end{cases}
1084  \end{aligned}
1085  ++++++
1086  
1087  
1088  [[textures-sampler-YCbCr-conversion]]
1089  === Sampler Y'C~B~C~R~ Conversion
1090  
1091  Sampler Y'C~B~C~R~ conversion performs the following operations, which an
1092  implementation may: combine into a single mathematical operation:
1093  
1094    * <<textures-sampler-YCbCr-conversion-rangeexpand,Sampler Y'C~B~C~R~ Range
1095      Expansion>>
1096    * <<textures-sampler-YCbCr-conversion-modelconversion,Sampler Y'C~B~C~R~
1097      Model Conversion>>
1098  
1099  [[textures-sampler-YCbCr-conversion-rangeexpand]]
1100  ==== Sampler Y'C~B~C~R~ Range Expansion
1101  
1102  Sampler Y'C~B~C~R~ range expansion is applied to color channel values after
1103  all texel input operations which are not specific to sampler Y'C~B~C~R~
1104  conversion.
1105  For example, the input values to this stage have been converted using the
1106  normal <<textures-format-conversion,format conversion>> rules.
1107  
1108  Sampler Y'C~B~C~R~ range expansion is not applied if pname:ycbcrModel is
1109  ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY.
1110  That is, the shader receives the vector C'~rgba~ as output by the Component
1111  Swizzle stage without further modification.
1112  
1113  For other values of pname:ycbcrModel, range expansion is applied to the
1114  texel channel values output by the <<textures-component-swizzle,Component
1115  Swizzle>> defined by the pname:components member of
1116  slink:VkSamplerYcbcrConversionCreateInfo.
1117  Range expansion applies independently to each channel of the image.
1118  For the purposes of range expansion and Y'C~B~C~R~ model conversion, the R
1119  and B channels contain color difference (chroma) values and the G channel
1120  contains luma.
1121  The A channel is not modified by sampler Y'C~B~C~R~ range expansion.
1122  
1123  The range expansion to be applied is defined by the pname:ycbcrRange member
1124  of the sname:VkSamplerYcbcrConversionCreateInfo structure:
1125  
1126    * If pname:ycbcrRange is ename:VK_SAMPLER_YCBCR_RANGE_ITU_FULL, the
1127      following transformations are applied:
1128  +
1129  [latexmath]
1130  +++++++++++++++++++
1131  \begin{aligned}
1132  Y' &= C'_{rgba}[G] \\
1133  C_B &= C'_{rgba}[B] - {{2^{(n-1)}}\over{(2^n) - 1}} \\
1134  C_R &= C'_{rgba}[R] - {{2^{(n-1)}}\over{(2^n) - 1}}
1135  \end{aligned}
1136  +++++++++++++++++++
1137  +
1138  [NOTE]
1139  .Note
1140  ====
1141  These formulae correspond to the "`full range`" encoding in the
1142  <<data-format,Khronos Data Format Specification>>.
1143  
1144  Should any future amendments be made to the ITU specifications from which
1145  these equations are derived, the formulae used by Vulkan may: also be
1146  updated to maintain parity.
1147  ====
1148    * If pname:ycbcrRange is ename:VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, the
1149      following transformations are applied:
1150  +
1151  [latexmath]
1152  +++++++++++++++++++
1153  \begin{aligned}
1154  Y' &= {{C'_{rgba}[G] \times (2^n-1) - 16\times 2^{n-8}}\over{219\times 2^{n-8}}} \\
1155  C_B &= {{C'_{rgba}[B] \times \left(2^n-1\right) - 128\times 2^{n-8}}\over{224\times 2^{n-8}}} \\
1156  C_R &= {{C'_{rgba}[R] \times \left(2^n-1\right) - 128\times 2^{n-8}}\over{224\times 2^{n-8}}}
1157  \end{aligned}
1158  +++++++++++++++++++
1159  +
1160  [NOTE]
1161  .Note
1162  ====
1163  These formulae correspond to the "`narrow range`" encoding in the
1164  <<data-format,Khronos Data Format Specification>>.
1165  ====
1166    * _n_ is the bit-depth of the channels in the format.
1167  
1168  The precision of the operations performed during range expansion must: be at
1169  least that of the source format.
1170  
1171  An implementation may: clamp the results of these range expansion operations
1172  such that Y' falls in the range [0,1], and/or such that C~B~ and C~R~ fall
1173  in the range [-0.5,0.5].
1174  
1175  [[textures-sampler-YCbCr-conversion-modelconversion]]
1176  ==== Sampler Y'C~B~C~R~ Model Conversion
1177  
1178  The range-expanded values are converted between color models, according to
1179  the color model conversion specified in the pname:ycbcrModel member:
1180  
1181  ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY::
1182    The color channels are not modified by the color model conversion since
1183    they are assumed already to represent the desired color model in which the
1184    shader is operating; Y'C~B~C~R~ range expansion is also ignored.
1185  ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY::
1186    The color channels are not modified by the color model conversion and are
1187    assumed to be treated as though in Y'C~B~C~R~ form both in memory and in
1188    the shader; Y'C~B~C~R~ range expansion is applied to the channels as for
1189    other Y'C~B~C~R~ models, with the vector (C~R~,Y',C~B~,A) provided to the
1190    shader.
1191  ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709::
1192    The color channels are transformed from a Y'C~B~C~R~ representation to an
1193    R'G'B' representation as described in the "`BT.709 Y'C~B~C~R~ conversion`"
1194    section of the <<data-format,Khronos Data Format Specification>>.
1195  ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601::
1196    The color channels are transformed from a Y'C~B~C~R~ representation to an
1197    R'G'B' representation as described in the "`BT.601 Y'C~B~C~R~ conversion`"
1198    section of the <<data-format,Khronos Data Format Specification>>.
1199  ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020::
1200    The color channels are transformed from a Y'C~B~C~R~ representation to an
1201    R'G'B' representation as described in the "`BT.2020 Y'C~B~C~R~
1202    conversion`" section of the <<data-format,Khronos Data Format
1203    Specification>>.
1204  
1205  In this operation, each output channel is dependent on each input channel.
1206  
1207  An implementation may: clamp the R'G'B' results of these conversions to the
1208  range [0,1].
1209  
1210  The precision of the operations performed during model conversion must: be
1211  at least that of the source format.
1212  
1213  The alpha channel is not modified by these model conversions.
1214  
1215  [NOTE]
1216  .Note
1217  ====
1218  Sampling operations in a non-linear color space can introduce color and
1219  intensity shifts at sharp transition boundaries.
1220  To avoid this issue, the technically precise color correction sequence
1221  described in the "`Introduction to Color Conversions`" chapter of the
1222  <<data-format,Khronos Data Format Specification>> may be performed as
1223  follows:
1224  
1225    * Calculate the <<textures-normalized-to-unnormalized,unnormalized texel
1226      coordinates>> corresponding to the desired sample position.
1227    * For a pname:minFilter/pname:magFilter of ename:VK_FILTER_NEAREST:
1228      . Calculate (_i_,_j_) for the sample location as described under the
1229        "`nearest filtering`" formulae in <<textures-unnormalized-to-integer>>
1230      . Calculate the normalized texel coordinates corresponding to these
1231        integer coordinates.
1232      . Sample using <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~
1233        conversion>> at this location.
1234    * For a pname:minFilter/pname:magFilter of ename:VK_FILTER_LINEAR:
1235      . Calculate (_i~[0,1]~_,_j~[0,1]~_) for the sample location as described
1236        under the "`linear filtering`" formulae in
1237        <<textures-unnormalized-to-integer>>
1238      . Calculate the normalized texel coordinates corresponding to these
1239        integer coordinates.
1240      . Sample using <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~
1241        conversion>> at each of these locations.
1242      . Convert the non-linear AR'G'B' outputs of the Y'C~B~C~R~ conversions
1243        to linear ARGB values as described in the "`Transfer Functions`"
1244        chapter of the <<data-format,Khronos Data Format Specification>>.
1245      . Interpolate the linear ARGB values using the [eq]#{alpha}# and
1246        [eq]#{beta}# values described in the "`linear filtering`" section of
1247        <<textures-unnormalized-to-integer>> and the equations in
1248        <<textures-texel-filtering>>.
1249  
1250  The additional calculations and, especially, additional number of sampling
1251  operations in the ename:VK_FILTER_LINEAR case can be expected to have a
1252  performance impact compared with using the outputs directly; since the
1253  variation from "`correct`" results are subtle for most content, the
1254  application author should determine whether a more costly implementation is
1255  strictly necessary.
1256  Note that if pname:chromaFilter and pname:minFilter/pname:magFilter are both
1257  ename:VK_FILTER_NEAREST, these operations are redundant and sampling using
1258  <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~ conversion>> at the desired
1259  sample coordinates will produce the "`correct`" results without further
1260  processing.
1261  ====
1262  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
1263  
1264  
1265  == Texel Output Operations
1266  
1267  _Texel output instructions_ are SPIR-V image instructions that write to an
1268  image.
1269  _Texel output operations_ are a set of steps that are performed on state,
1270  coordinates, and texel values while processing a texel output instruction,
1271  and which are common to some or all texel output instructions.
1272  They include the following steps, which are performed in the listed order:
1273  
1274    * <<textures-output-validation,Validation operations>>
1275    ** <<textures-format-validation,Format validation>>
1276    ** <<textures-output-coordinate-validation,Coordinate validation>>
1277    ** <<textures-output-sparse-validation,Sparse validation>>
1278    * <<textures-output-format-conversion,Texel output format conversion>>
1279  
1280  
1281  [[textures-output-validation]]
1282  === Texel Output Validation Operations
1283  
1284  _Texel output validation operations_ inspect instruction/image state or
1285  coordinates, and in certain circumstances cause the write to have no effect.
1286  There are a series of validations that the texel undergoes.
1287  
1288  
1289  [[textures-format-validation]]
1290  ==== Texel Format Validation
1291  
1292  If the image format of the code:OpTypeImage is not compatible with the
1293  sname:VkImageView's pname:format, the write causes the contents of the
1294  image's memory to become undefined:.
1295  
1296  
1297  [[textures-output-coordinate-validation]]
1298  === Integer Texel Coordinate Validation
1299  
1300  The integer texel coordinates are validated according to the same rules as
1301  for texel input <<textures-integer-coordinate-validation,coordinate
1302  validation>>.
1303  
1304  If the texel fails integer texel coordinate validation, then the write has
1305  no effect.
1306  
1307  
1308  [[textures-output-sparse-validation]]
1309  === Sparse Texel Operation
1310  
1311  If the texel attempts to write to an unbound region of a sparse image, the
1312  texel is a sparse unbound texel.
1313  In such a case, if the
1314  slink:VkPhysicalDeviceSparseProperties::pname:residencyNonResidentStrict
1315  property is ename:VK_TRUE, the sparse unbound texel write has no effect.
1316  If pname:residencyNonResidentStrict is ename:VK_FALSE, the write may: have a
1317  side effect that becomes visible to other accesses to unbound texels in any
1318  resource, but will not be visible to any device memory allocated by the
1319  application.
1320  
1321  
1322  [[textures-output-format-conversion]]
1323  === Texel Output Format Conversion
1324  
1325  If the image format is sRGB, a linear to sRGB conversion is applied to the
1326  R, G, and B components as described in the "`sRGB EOTF`" section of the
1327  <<data-format,Khronos Data Format Specification>>.
1328  The A component, if present, is unchanged.
1329  
1330  Texels then undergo a format conversion from the floating point, signed, or
1331  unsigned integer type of the texel data to the elink:VkFormat of the image
1332  view.
1333  Any unused components are ignored.
1334  
1335  Each component is converted based on its type and size (as defined in the
1336  <<formats-definition,Format Definition>> section for each elink:VkFormat).
1337  Floating-point outputs are converted as described in
1338  <<fundamentals-fp-conversion,Floating-Point Format Conversions>> and
1339  <<fundamentals-fixedconv,Fixed-Point Data Conversion>>.
1340  Integer outputs are converted such that their value is preserved.
1341  The converted value of any integer that cannot be represented in the target
1342  format is undefined:.
1343  
1344  
1345  [[texture-derivatives]]
1346  == Derivative Operations
1347  
1348  SPIR-V derivative instructions include code:OpDPdx, code:OpDPdy,
1349  code:OpDPdxFine, code:OpDPdyFine, code:OpDPdxCoarse, and code:OpDPdyCoarse.
1350  Derivative instructions are only available in
1351  ifdef::VK_NV_compute_shader_derivatives[]
1352  compute and
1353  endif::VK_NV_compute_shader_derivatives[]
1354  fragment shaders.
1355  
1356  image::{images}/vulkantexture2-ll.svg[align="center",title="Implicit Derivatives",opts="{imageopts}"]
1357  
1358  Derivatives are computed as if there is a 2{times}2 neighborhood of
1359  fragments for each fragment shader invocation.
1360  These neighboring fragments are used to compute derivatives with the
1361  assumption that the values of P in the neighborhood are piecewise linear.
1362  It is further assumed that the values of P in the neighborhood are locally
1363  continuous.
1364  Applications must: not use derivative instructions in non-uniform control
1365  flow.
1366  
1367  [latexmath]
1368  +++++++++++++++++++
1369  \begin{aligned}
1370  dPdx_0 & = P_{i_1,j_0} - P_{i_0,j_0}  \\
1371  dPdx_1 & = P_{i_1,j_1} - P_{i_0,j_1}  \\
1372  \\
1373  dPdy_0 & = P_{i_0,j_1} - P_{i_0,j_0}  \\
1374  dPdy_1 & = P_{i_1,j_1} - P_{i_1,j_0}
1375  \end{aligned}
1376  +++++++++++++++++++
1377  
1378  For a 2{times}2 neighborhood, for the four fragments labled 0, 1, 2 and 3,
1379  the code:Fine derivative instructions must: return:
1380  
1381  [latexmath]
1382  +++++++++++++++++++
1383  \begin{aligned}
1384  dPdx & =
1385    \begin{cases}
1386      dPdx_0 & \text{for fragments labeled 0 and 1}\\
1387      dPdx_1 & \text{for fragments labeled 2 and 3}
1388    \end{cases} \\
1389  dPdy & =
1390    \begin{cases}
1391      dPdy_0 & \text{for fragments labeled 0 and 2}\\
1392      dPdy_1 & \text{for fragments labeled 1 and 3}
1393    \end{cases}
1394  \end{aligned}
1395  +++++++++++++++++++
1396  
1397  Coarse derivatives may: return only two values.
1398  In this case, the values should: be:
1399  
1400  [latexmath]
1401  +++++++++++++++++++
1402  \begin{aligned}
1403  dPdx & =
1404    \begin{cases}
1405      dPdx_0 & \text{preferred}\\
1406      dPdx_1
1407    \end{cases} \\
1408  dPdy & =
1409    \begin{cases}
1410      dPdy_0 & \text{preferred}\\
1411      dPdy_1
1412    \end{cases}
1413  \end{aligned}
1414  +++++++++++++++++++
1415  
1416  code:OpDPdx and code:OpDPdy must: return the same result as either
1417  code:OpDPdxFine or code:OpDPdxCoarse and either code:OpDPdyFine or
1418  code:OpDPdyCoarse, respectively.
1419  Implementations must: make the same choice of either coarse or fine for both
1420  code:OpDPdx and code:OpDPdy, and implementations should: make the choice
1421  that is more efficient to compute.
1422  
1423  ifdef::VK_VERSION_1_1[]
1424  If the pname:subgroupSize field of slink:VkPhysicalDeviceSubgroupProperties
1425  is at least 4, the 2x2 neighborhood of fragments corresponds exactly to a
1426  subgroup quad.
1427  The order in which the fragments appear within the quad is implementation
1428  defined.
1429  endif::VK_VERSION_1_1[]
1430  
1431  ifdef::VK_NV_compute_shader_derivatives[]
1432  [[texture-derivatives-compute]]
1433  === Compute Shader Derivatives
1434  
1435  For compute shaders, derivatives are also evaluated using a 2{times}2
1436  logical neighborhood of compute shader invocations.
1437  Compute shader invocations are arranged into neighborhoods according to one
1438  of two SPIR-V execution modes.
1439  For the code:DerivativeGroupQuadsNV execution mode, each neighborhood is
1440  assembled from a 2{times}2{times}1 region of invocations based on the
1441  code:LocalInvocationId built-in.
1442  For the code:DerivativeGroupLinearNV execution mode, each neighborhood is
1443  assembled from a group of four invocations based on the
1444  code:LocalInvocationIndex built-in.
1445  The <<texture-derivatives-compute-group>> table specifies the
1446  code:LocalInvocationId or code:LocalInvocationIndex values for the four
1447  values of P in each neighborhood, where __x__ and __y__ are per-neighborhood
1448  integer values.
1449  
1450  [[texture-derivatives-compute-group]]
1451  .Compute shader derivative group assignments
1452  [width="75%",frame="all",options="header",cols="^2,^6,^6"]
1453  |===
1454  |Value
1455  |DerivativeGroupQuadsNV
1456  |DerivativeGroupLinearNV
1457  
1458  |P~i0,j0~ | (2__x__ + 0, 2__y__ + 0, z) | 4__x__ + 0
1459  |P~i1,j0~ | (2__x__ + 1, 2__y__ + 0, z) | 4__x__ + 1
1460  |P~i0,j1~ | (2__x__ + 0, 2__y__ + 1, z) | 4__x__ + 2
1461  |P~i1,j1~ | (2__x__ + 1, 2__y__ + 1, z) | 4__x__ + 3
1462  |===
1463  
1464  endif::VK_NV_compute_shader_derivatives[]
1465  
1466  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
1467  For multi-planar formats, the derivatives are computed based on the plane
1468  with the largest dimensions.
1469  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
1470  
1471  
1472  [[textures-normalized-operations]]
1473  == Normalized Texel Coordinate Operations
1474  
1475  If the image sampler instruction provides normalized texel coordinates, some
1476  of the following operations are performed.
1477  
1478  
1479  [[textures-projection]]
1480  === Projection Operation
1481  
1482  For code:Proj image operations, the normalized texel coordinates
1483  [eq]#(s,t,r,q,a)# and (if present) the [eq]#D~ref~# coordinate are
1484  transformed as follows:
1485  
1486  [latexmath]
1487  +++++++++++++++++++
1488  \begin{aligned}
1489  s       & = \frac{s}{q},       & \text{for 1D, 2D, or 3D image} \\
1490  \\
1491  t       & = \frac{t}{q},       & \text{for 2D or 3D image} \\
1492  \\
1493  r       & = \frac{r}{q},       & \text{for 3D image} \\
1494  \\
1495  D_{\textit{ref}} & = \frac{D_{\textit{ref}}}{q}, & \text{if provided}
1496  \end{aligned}
1497  +++++++++++++++++++
1498  
1499  
1500  [[textures-derivative-image-operations]]
1501  === Derivative Image Operations
1502  
1503  Derivatives are used for LOD selection.
1504  These derivatives are either implicit (in an code:ImplicitLod image
1505  instruction in a fragment shader) or explicit (provided explicitly by shader
1506  to the image instruction in any shader).
1507  
1508  For implicit derivatives image instructions, the derivatives of texel
1509  coordinates are calculated in the same manner as derivative operations
1510  above.
1511  That is:
1512  
1513  [latexmath]
1514  +++++++++++++++++++
1515  \begin{aligned}
1516  \partial{s}/\partial{x} & = dPdx(s), & \partial{s}/\partial{y} & = dPdy(s), & \text{for 1D, 2D, Cube, or 3D image} \\
1517  \partial{t}/\partial{x} & = dPdx(t), & \partial{t}/\partial{y} & = dPdy(t), & \text{for 2D, Cube, or 3D image} \\
1518  \partial{u}/\partial{x} & = dPdx(u), & \partial{u}/\partial{y} & = dPdy(u), & \text{for Cube or 3D image}
1519  \end{aligned}
1520  +++++++++++++++++++
1521  
1522  Partial derivatives not defined above for certain image dimensionalities are
1523  set to zero.
1524  
1525  For explicit LOD image instructions, if the optional: SPIR-V operand
1526  [eq]#Grad# is provided, then the operand values are used for the
1527  derivatives.
1528  The number of components present in each derivative for a given image
1529  dimensionality matches the number of partial derivatives computed above.
1530  
1531  If the optional: SPIR-V operand [eq]#Lod# is provided, then derivatives are
1532  set to zero, the cube map derivative transformation is skipped, and the
1533  scale factor operation is skipped.
1534  Instead, the floating point scalar coordinate is directly assigned to
1535  [eq]#{lambda}~base~# as described in <<textures-level-of-detail-operation,
1536  Level-of-Detail Operation>>.
1537  
1538  For implicit derivative image instructions, the partial derivative values
1539  may: be computed by linear approximation using a 2{times}2 neighborhood of
1540  shader invocations (known as a _quad_), as described above.
1541  If the instruction is in control flow that is not uniform across the quad,
1542  then the derivative values and hence the implicit LOD values are undefined:.
1543  
1544  ifdef::VK_EXT_descriptor_indexing[]
1545  If the image or sampler object used by an implicit derivative image
1546  instruction is not uniform across the quad and
1547  <<limits-quadDivergentImplicitLod,pname:quadDivergentImplicitLod>> is not
1548  supported, then the derivative and LOD values are undefined:.
1549  Implicit derivatives are well-defined when the image and sampler and control
1550  flow are uniform across the quad, even if they diverge between different
1551  quads.
1552  
1553  If <<limits-quadDivergentImplicitLod,pname:quadDivergentImplicitLod>> is
1554  supported, then derivatives and implicit LOD values are well-defined even if
1555  the image or sampler object are not uniform within a quad.
1556  The derivatives are computed as specified above, and the implicit LOD
1557  calculation proceeds for each shader invocation using its respective image
1558  and sampler object.
1559  
1560  For the purposes of implicit derivatives, code:Flat fragment input variables
1561  are uniform within a quad.
1562  endif::VK_EXT_descriptor_indexing[]
1563  
1564  
1565  === Cube Map Face Selection and Transformations
1566  
1567  For cube map image instructions, the [eq]#(s,t,r)# coordinates are treated
1568  as a direction vector [eq]#(r~x~,r~y~,r~z~)#.
1569  The direction vector is used to select a cube map face.
1570  The direction vector is transformed to a per-face texel coordinate system
1571  [eq]#(s~face~,t~face~)#, The direction vector is also used to transform the
1572  derivatives to per-face derivatives.
1573  
1574  
1575  === Cube Map Face Selection
1576  
1577  The direction vector selects one of the cube map's faces based on the
1578  largest magnitude coordinate direction (the major axis direction).
1579  Since two or more coordinates can: have identical magnitude, the
1580  implementation must: have rules to disambiguate this situation.
1581  
1582  The rules should: have as the first rule that [eq]#r~z~# wins over
1583  [eq]#r~y~# and [eq]#r~x~#, and the second rule that [eq]#r~y~# wins over
1584  [eq]#r~x~#.
1585  An implementation may: choose other rules, but the rules must: be
1586  deterministic and depend only on [eq]#(r~x~,r~y~,r~z~)#.
1587  
1588  The layer number (corresponding to a cube map face), the coordinate
1589  selections for [eq]#s~c~#, [eq]#t~c~#, [eq]#r~c~#, and the selection of
1590  derivatives, are determined by the major axis direction as specified in the
1591  following two tables.
1592  
1593  .Cube map face and coordinate selection
1594  [width="75%",frame="all",options="header"]
1595  |====
1596  | Major Axis Direction | Layer Number | Cube Map Face | [eq]#s~c~#  | [eq]#t~c~#  | [eq]#r~c~#
1597  | [eq]#+r~x~#          | [eq]#0#      | Positive X    | [eq]#-r~z~# | [eq]#-r~y~# | [eq]#r~x~#
1598  | [eq]#-r~x~#          | [eq]#1#      | Negative X    | [eq]#+r~z~# | [eq]#-r~y~# | [eq]#r~x~#
1599  | [eq]#+r~y~#          | [eq]#2#      | Positive Y    | [eq]#+r~x~# | [eq]#+r~z~# | [eq]#r~y~#
1600  | [eq]#-r~y~#          | [eq]#3#      | Negative Y    | [eq]#+r~x~# | [eq]#-r~z~# | [eq]#r~y~#
1601  | [eq]#+r~z~#          | [eq]#4#      | Positive Z    | [eq]#+r~x~# | [eq]#-r~y~# | [eq]#r~z~#
1602  | [eq]#-r~z~#          | [eq]#5#      | Negative Z    | [eq]#-r~x~# | [eq]#-r~y~# | [eq]#r~z~#
1603  |====
1604  
1605  
1606  .Cube map derivative selection
1607  [width="75%",frame="all",options="header"]
1608  |====
1609  | Major Axis Direction | [eq]#{partial}s~c~ / {partial}x# | [eq]#{partial}s~c~ / {partial}y# | [eq]#{partial}t~c~ / {partial}x# | [eq]#{partial}t~c~ / {partial}y# | [eq]#{partial}r~c~ / {partial}x# | [eq]#{partial}r~c~ / {partial}y#
1610  
1611  | [eq]#+r~x~#
1612  | [eq]#-{partial}r~z~ / {partial}x# | [eq]#-{partial}r~z~ / {partial}y#
1613  | [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1614  | [eq]#+{partial}r~x~ / {partial}x# | [eq]#+{partial}r~x~ / {partial}y#
1615  
1616  | [eq]#-r~x~#
1617  | [eq]#+{partial}r~z~ / {partial}x# | [eq]#+{partial}r~z~ / {partial}y#
1618  | [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1619  | [eq]#-{partial}r~x~ / {partial}x# | [eq]#-{partial}r~x~ / {partial}y#
1620  
1621  | [eq]#+r~y~#
1622  | [eq]#+{partial}r~x~ / {partial}x# | [eq]#+{partial}r~x~ / {partial}y#
1623  | [eq]#+{partial}r~z~ / {partial}x# | [eq]#+{partial}r~z~ / {partial}y#
1624  | [eq]#+{partial}r~y~ / {partial}x# | [eq]#+{partial}r~y~ / {partial}y#
1625  
1626  | [eq]#-r~y~#
1627  | [eq]#+{partial}r~x~ / {partial}x# | [eq]#+{partial}r~x~ / {partial}y#
1628  | [eq]#-{partial}r~z~ / {partial}x# | [eq]#-{partial}r~z~ / {partial}y#
1629  | [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1630  
1631  | [eq]#+r~z~#
1632  | [eq]#+{partial}r~x~ / {partial}x# | [eq]#+{partial}r~x~ / {partial}y#
1633  | [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1634  | [eq]#+{partial}r~z~ / {partial}x# | [eq]#+{partial}r~z~ / {partial}y#
1635  
1636  | [eq]#-r~z~#
1637  | [eq]#-{partial}r~x~ / {partial}x# | [eq]#-{partial}r~x~ / {partial}y#
1638  | [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1639  | [eq]#-{partial}r~z~ / {partial}x# | [eq]#-{partial}r~z~ / {partial}y#
1640  |====
1641  
1642  
1643  === Cube Map Coordinate Transformation
1644  
1645  [latexmath]
1646  ++++++++++++++++++++++++
1647  \begin{aligned}
1648  s_{\textit{face}} & =
1649      \frac{1}{2} \times \frac{s_c}{|r_c|} + \frac{1}{2} \\
1650  t_{\textit{face}} & =
1651      \frac{1}{2} \times \frac{t_c}{|r_c|} + \frac{1}{2} \\
1652  \end{aligned}
1653  ++++++++++++++++++++++++
1654  
1655  
1656  === Cube Map Derivative Transformation
1657  
1658  [latexmath]
1659  ++++++++++++++++++++++++
1660  \begin{aligned}
1661  \frac{\partial{s_{\textit{face}}}}{\partial{x}} &=
1662      \frac{\partial}{\partial{x}} \left ( \frac{1}{2} \times \frac{s_{c}}{|r_{c}|}
1663      + \frac{1}{2}\right ) \\
1664  \frac{\partial{s_{\textit{face}}}}{\partial{x}} &=
1665      \frac{1}{2} \times \frac{\partial}{\partial{x}}
1666      \left ( \frac{s_{c}}{|r_{c}|}  \right ) \\
1667  \frac{\partial{s_{\textit{face}}}}{\partial{x}} &=
1668      \frac{1}{2} \times
1669      \left (
1670      \frac{
1671        |r_{c}| \times \partial{s_c}/\partial{x}
1672        -s_c \times {\partial{r_{c}}}/{\partial{x}}}
1673      {\left ( r_{c} \right )^2}
1674      \right )
1675  \end{aligned}
1676  ++++++++++++++++++++++++
1677  
1678  [latexmath]
1679  ++++++++++++++++++++++++
1680  \begin{aligned}
1681  \frac{\partial{s_{\textit{face}}}}{\partial{y}} &=
1682      \frac{1}{2} \times
1683      \left (
1684      \frac{
1685        |r_{c}| \times \partial{s_c}/\partial{y}
1686        -s_c \times {\partial{r_{c}}}/{\partial{y}}}
1687      {\left ( r_{c} \right )^2}
1688      \right )\\
1689  \frac{\partial{t_{\textit{face}}}}{\partial{x}} &=
1690      \frac{1}{2} \times
1691      \left (
1692      \frac{
1693        |r_{c}| \times \partial{t_c}/\partial{x}
1694        -t_c \times {\partial{r_{c}}}/{\partial{x}}}
1695      {\left ( r_{c} \right )^2}
1696      \right ) \\
1697  \frac{\partial{t_{\textit{face}}}}{\partial{y}} &=
1698      \frac{1}{2} \times
1699      \left (
1700      \frac{
1701         |r_{c}| \times \partial{t_c}/\partial{y}
1702        -t_c \times {\partial{r_{c}}}/{\partial{y}}}
1703      {\left ( r_{c} \right )^2}
1704      \right )
1705  \end{aligned}
1706  ++++++++++++++++++++++++
1707  
1708  ifdef::editing-notes[]
1709  [NOTE]
1710  .editing-note
1711  ====
1712  (Bill) Note that we never revisited ARB_texture_cubemap after we introduced
1713  dependent texture fetches (ARB_fragment_program and ARB_fragment_shader).
1714  
1715  The derivatives of [eq]#s~face~# and [eq]#t~face~# are only valid for
1716  non-dependent texture fetches (pre OpenGL 2.0).
1717  ====
1718  endif::editing-notes[]
1719  
1720  
1721  === Scale Factor Operation, Level-of-Detail Operation and Image Level(s) Selection
1722  
1723  LOD selection can: be either explicit (provided explicitly by the image
1724  instruction) or implicit (determined from a scale factor calculated from the
1725  derivatives).
1726  The implicit LOD selected can: be queried using the SPIR-V instruction
1727  code:OpImageQueryLod, which gives access to the [eq]#{lambda}#' and
1728  [eq]#d~l~# values, defined below.
1729  These values must: be computed with pname:mipmapPrecisionBits of accuracy
1730  and may: be subject to implementation-specific maxima and minima for very
1731  large, out-of-range values.
1732  
1733  
1734  [[textures-scale-factor]]
1735  ==== Scale Factor Operation
1736  
1737  The magnitude of the derivatives are calculated by:
1738  
1739    :: [eq]#m~ux~ = {vert}{partial}s/{partial}x{vert} {times} w~base~#
1740    :: [eq]#m~vx~ = {vert}{partial}t/{partial}x{vert} {times} h~base~#
1741    :: [eq]#m~wx~ = {vert}{partial}r/{partial}x{vert} {times} d~base~#
1742  
1743    :: [eq]#m~uy~ = {vert}{partial}s/{partial}y{vert} {times} w~base~#
1744    :: [eq]#m~vy~ = {vert}{partial}t/{partial}y{vert} {times} h~base~#
1745    :: [eq]#m~wy~ = {vert}{partial}r/{partial}y{vert} {times} d~base~#
1746  
1747  
1748  where:
1749  
1750    :: [eq]#{partial}t/{partial}x = {partial}t/{partial}y = 0# (for 1D images)
1751    :: [eq]#{partial}r/{partial}x = {partial}r/{partial}y = 0# (for 1D, 2D or
1752       Cube images)
1753  
1754  and:
1755  
1756    :: [eq]#w~base~ = image.w#
1757    :: [eq]#h~base~ = image.h#
1758    :: [eq]#d~base~ = image.d#
1759  
1760  (for the pname:baseMipLevel, from the image descriptor).
1761  
1762  ifdef::VK_NV_corner_sampled_image[]
1763  
1764  For corner-sampled images, the [eq]#w~base~#, [eq]#h~base~#, and
1765  [eq]#d~base~# are instead:
1766  
1767    :: [eq]#w~base~ = image.w - 1#
1768    :: [eq]#h~base~ = image.h - 1#
1769    :: [eq]#d~base~ = image.d - 1#
1770  
1771  endif::VK_NV_corner_sampled_image[]
1772  
1773  A point sampled in screen space has an elliptical footprint in texture
1774  space.
1775  The minimum and maximum scale factors [eq]#({rho}~min~, {rho}~max~)# should:
1776  be the minor and major axes of this ellipse.
1777  
1778  The _scale factors_ [eq]#{rho}~x~# and [eq]#{rho}~y~#, calculated from the
1779  magnitude of the derivatives in x and y, are used to compute the minimum and
1780  maximum scale factors.
1781  
1782  [eq]#{rho}~x~# and [eq]#{rho}~y~# may: be approximated with functions
1783  [eq]#f~x~# and [eq]#f~y~#, subject to the following constraints:
1784  
1785  [latexmath]
1786  ++++++++++++++++++++++++
1787  \begin{aligned}
1788  & f_x \text{\ is\ continuous\ and\ monotonically\ increasing\ in\ each\ of\ }
1789      m_{ux},
1790      m_{vx}, \text{\ and\ }
1791      m_{wx} \\
1792  & f_y \text{\ is\ continuous\ and\ monotonically\ increasing\ in\ each\ of\ }
1793      m_{uy},
1794      m_{vy}, \text{\ and\ }
1795      m_{wy}
1796  \end{aligned}
1797  ++++++++++++++++++++++++
1798  
1799  [latexmath]
1800  ++++++++++++++++++++++++
1801  \begin{aligned}
1802  \max(|m_{ux}|, |m_{vx}|, |m_{wx}|) \leq f_{x}
1803  \leq \sqrt{2} (|m_{ux}| + |m_{vx}| + |m_{wx}|) \\
1804  \max(|m_{uy}|, |m_{vy}|, |m_{wy}|) \leq f_{y}
1805  \leq \sqrt{2} (|m_{uy}| + |m_{vy}| + |m_{wy}|)
1806  \end{aligned}
1807  ++++++++++++++++++++++++
1808  
1809  
1810  ifdef::editing-notes[]
1811  [NOTE]
1812  .editing-note
1813  ====
1814  (Bill) For reviewers only - anticipating questions.
1815  
1816  We only support implicit derivatives for normalized texel coordinates.
1817  
1818  So we are documenting the derivatives in s,t,r (normalized texel
1819  coordinates) rather than u,v,w (unnormalized texel coordinates) as in OpenGL
1820  and OpenGL ES specifications.
1821  (I know, u,v,w is the way it has been documented since OpenGL V1.0.)
1822  
1823  Also there is no reason to have conditional application of [eq]#w~base~,
1824  h~base~, d~base~# for rectangle textures either, since they do not support
1825  implicit derivatives.
1826  ====
1827  endif::editing-notes[]
1828  
1829  
1830  The minimum and maximum scale factors [eq]#({rho}~min~,{rho}~max~)# are
1831  determined by:
1832  
1833    :: [eq]#{rho}~max~ = max({rho}~x~, {rho}~y~)#
1834    :: [eq]#{rho}~min~ = min({rho}~x~, {rho}~y~)#
1835  
1836  The ratio of anisotropy is determined by:
1837  
1838    :: [eq]#{eta} = min({rho}~max~/{rho}~min~, max~Aniso~)#
1839  
1840  where:
1841  
1842    :: [eq]#sampler.max~Aniso~ = pname:maxAnisotropy# (from sampler
1843       descriptor)
1844    :: [eq]#limits.max~Aniso~ = pname:maxSamplerAnisotropy# (from physical
1845       device limits)
1846    :: [eq]#max~Aniso~ = min(sampler.max~Aniso~, limits.max~Aniso~)#
1847  
1848  If [eq]#{rho}~max~ = {rho}~min~ = 0#, then all the partial derivatives are
1849  zero, the fragment's footprint in texel space is a point, and [eq]#N#
1850  should: be treated as 1.
1851  If [eq]#{rho}~max~ {neq} 0# and [eq]#{rho}~min~ = 0# then all partial
1852  derivatives along one axis are zero, the fragment's footprint in texel space
1853  is a line segment, and [eq]#{eta}# should: be treated as [eq]#max~Aniso~#.
1854  However, anytime the footprint is small in texel space the implementation
1855  may: use a smaller value of [eq]#{eta}#, even when [eq]#{rho}~min~# is zero
1856  or close to zero.
1857  If either slink:VkPhysicalDeviceFeatures::pname:samplerAnisotropy or
1858  slink:VkSamplerCreateInfo::pname:anisotropyEnable are ename:VK_FALSE,
1859  [eq]#max~Aniso~# is set to 1.
1860  
1861  If [eq]#{eta} = 1#, sampling is isotropic.
1862  If [eq]#{eta} > 1#, sampling is anisotropic.
1863  
1864  The sampling rate ([eq]#N#) is derived as:
1865  
1866    :: [eq]#N = {lceil}{eta}{rceil}#
1867  
1868  An implementation may: round [eq]#N# up to the nearest supported sampling
1869  rate.
1870  An implementation may: use the value of [eq]#N# as an approximation of
1871  [eq]#{eta}#.
1872  
1873  
1874  [[textures-level-of-detail-operation]]
1875  ==== Level-of-Detail Operation
1876  
1877  The LOD parameter [eq]#{lambda}# is computed as follows:
1878  
1879  [latexmath]
1880  ++++++++++++++++++++++++
1881  \begin{aligned}
1882  \lambda_{base}(x,y) & =
1883    \begin{cases}
1884      shaderOp.Lod                                    & \text{(from optional SPIR-V operand)} \\
1885      \log_2 \left ( \frac{\rho_{max}}{\eta} \right ) & \text{otherwise}
1886    \end{cases} \\
1887  \lambda'(x,y)       & = \lambda_{base} + \mathbin{clamp}(sampler.bias + shaderOp.bias,-maxSamplerLodBias,maxSamplerLodBias) \\
1888  \lambda             & =
1889    \begin{cases}
1890      lod_{max}, & \lambda' > lod_{max} \\
1891      \lambda',  & lod_{min} \leq \lambda' \leq lod_{max} \\
1892      lod_{min}, & \lambda' < lod_{min} \\
1893      \textit{undefined}, & lod_{min} > lod_{max}
1894    \end{cases}
1895  \end{aligned}
1896  ++++++++++++++++++++++++
1897  
1898  where:
1899  
1900  [latexmath]
1901  ++++++++++++++++++++++++
1902  \begin{aligned}
1903  sampler.bias       & = mipLodBias & \text{(from sampler descriptor)} \\
1904  shaderOp.bias      & =
1905    \begin{cases}
1906      Bias & \text{(from optional SPIR-V operand)} \\
1907      0    & \text{otherwise}
1908    \end{cases} \\
1909  sampler.lod_{min}  & = minLod & \text{(from sampler descriptor)} \\
1910  shaderOp.lod_{min} & =
1911    \begin{cases}
1912      MinLod & \text{(from optional SPIR-V operand)} \\
1913      0      & \text{otherwise}
1914    \end{cases} \\
1915  \\
1916  lod_{min}          & = \max(sampler.lod_{min}, shaderOp.lod_{min}) \\
1917  lod_{max}          & = maxLod & \text{(from sampler descriptor)}
1918  \end{aligned}
1919  ++++++++++++++++++++++++
1920  
1921  and [eq]#maxSamplerLodBias# is the value of the slink:VkPhysicalDeviceLimits
1922  feature <<limits-maxSamplerLodBias,pname:maxSamplerLodBias>>.
1923  
1924  
1925  [[textures-image-level-selection]]
1926  ==== Image Level(s) Selection
1927  
1928  The image level(s) [eq]#d#, [eq]#d~hi~#, and [eq]#d~lo~# which texels are
1929  read from are determined by an image-level parameter [eq]#d~l~#, which is
1930  computed based on the LOD parameter, as follows:
1931  
1932  [latexmath]
1933  ++++++++++++++++++++++++
1934  \begin{aligned}
1935  d_{l} =
1936    \begin{cases}
1937      nearest(d'),  & \text{mipmapMode is VK\_SAMPLER\_MIPMAP\_MODE\_NEAREST} \\
1938      d',           & \text{otherwise}
1939    \end{cases}
1940  \end{aligned}
1941  ++++++++++++++++++++++++
1942  
1943  where:
1944  
1945  [latexmath]
1946  ++++++++++++++++++++++++
1947  \begin{aligned}
1948  d' = level_{base} + \text{clamp}(\lambda, 0, q)
1949  \end{aligned}
1950  ++++++++++++++++++++++++
1951  
1952  [latexmath]
1953  ++++++++++++++++++++++++
1954  \begin{aligned}
1955  nearest(d') & =
1956    \begin{cases}
1957      \left \lceil d' + 0.5\right \rceil - 1, &
1958          \text{preferred} \\
1959      \left \lfloor d' + 0.5\right \rfloor,   &
1960          \text{alternative}
1961    \end{cases}
1962  \end{aligned}
1963  ++++++++++++++++++++++++
1964  
1965  and:
1966  
1967    :: [eq]#level~base~ = pname:baseMipLevel#
1968    :: [eq]#q = pname:levelCount - 1#
1969  
1970  pname:baseMipLevel and pname:levelCount are taken from the
1971  pname:subresourceRange of the image view.
1972  
1973  If the sampler's pname:mipmapMode is ename:VK_SAMPLER_MIPMAP_MODE_NEAREST,
1974  then the level selected is [eq]#d = d~l~#.
1975  
1976  If the sampler's pname:mipmapMode is ename:VK_SAMPLER_MIPMAP_MODE_LINEAR,
1977  two neighboring levels are selected:
1978  
1979  [latexmath]
1980  ++++++++++++++++++++++++
1981  \begin{aligned}
1982  d_{hi} & = \lfloor d_{l} \rfloor \\
1983  d_{lo} & = min( d_{hi} + 1, q ) \\
1984  \delta & = d_{l} - d_{hi}
1985  \end{aligned}
1986  ++++++++++++++++++++++++
1987  
1988  [eq]#{delta}# is the fractional value, quantized to the number of
1989  <<limits-mipmapPrecisionBits,mipmap precision bits>>, used for
1990  <<textures-texel-filtering, linear filtering>> between levels.
1991  
1992  [[textures-normalized-to-unnormalized]]
1993  === (s,t,r,q,a) to (u,v,w,a) Transformation
1994  
1995  The normalized texel coordinates are scaled by the image level dimensions
1996  and the array layer is selected.
1997  
1998  This transformation is performed once for each level used in
1999  <<textures-texel-filter,filtering>> (either [eq]#d#, or [eq]#d~hi~# and
2000  [eq]#d~lo~#).
2001  
2002  [latexmath]
2003  ++++++++++++++++++++++++
2004  \begin{aligned}
2005  u(x,y) & = s(x,y) \times width_{scale} + \Delta_i\\
2006  v(x,y) & =
2007    \begin{cases}
2008      0                         & \text{for 1D images} \\
2009      t(x,y) \times height_{scale} + \Delta_j & \text{otherwise}
2010    \end{cases} \\
2011  w(x,y) & =
2012    \begin{cases}
2013      0                         & \text{for 2D or Cube images} \\
2014      r(x,y) \times depth_{scale}  + \Delta_k & \text{otherwise}
2015    \end{cases} \\
2016  \\
2017  a(x,y) & =
2018    \begin{cases}
2019      a(x,y)                    & \text{for array images} \\
2020      0                         & \text{otherwise}
2021    \end{cases}
2022  \end{aligned}
2023  ++++++++++++++++++++++++
2024  
2025  where:
2026  
2027    :: [eq]#width~scale~ = width~level~#
2028    :: [eq]#height~scale~ = height~level~#
2029    :: [eq]#depth~scale~ = depth~level~#
2030  
2031  ifdef::VK_NV_corner_sampled_image[]
2032  for conventional images, and:
2033  
2034    :: [eq]#width~scale~ = width~level~ - 1#
2035    :: [eq]#height~scale~ = height~level~ - 1#
2036    :: [eq]#depth~scale~ = depth~level~ - 1#
2037  
2038  for corner-sampled images.
2039  endif::VK_NV_corner_sampled_image[]
2040  
2041  and where [eq]#({DeltaUpper}~i~, {DeltaUpper}~j~, {DeltaUpper}~k~)# are
2042  taken from the image instruction if it includes a code:ConstOffset or
2043  code:Offset operand, otherwise they are taken to be zero.
2044  
2045  
2046  Operations then proceed to Unnormalized Texel Coordinate Operations.
2047  
2048  
2049  == Unnormalized Texel Coordinate Operations
2050  
2051  
2052  [[textures-unnormalized-to-integer]]
2053  === (u,v,w,a) to (i,j,k,l,n) Transformation And Array Layer Selection
2054  
2055  The unnormalized texel coordinates are transformed to integer texel
2056  coordinates relative to the selected mipmap level.
2057  
2058  The layer index [eq]#l# is computed as:
2059  
2060    :: [eq]#l = clamp(RNE(a), 0, pname:layerCount - 1) {plus}
2061       pname:baseArrayLayer#
2062  
2063  where pname:layerCount is the number of layers in the image subresource
2064  range of the image view, pname:baseArrayLayer is the first layer from the
2065  subresource range, and where:
2066  
2067  [latexmath]
2068  ++++++++++++++++++++++++
2069  \begin{aligned}
2070  \mathbin{RNE}(a) & =
2071    \begin{cases}
2072      \mathbin{roundTiesToEven}(a)                  & \text{preferred, from IEEE Std 754-2008 Floating-Point Arithmetic} \\
2073      \left \lfloor a + 0.5 \right \rfloor & \text{alternative}
2074    \end{cases}
2075  \end{aligned}
2076  ++++++++++++++++++++++++
2077  
2078  The sample index n is assigned the value zero.
2079  
2080  Nearest filtering (ename:VK_FILTER_NEAREST) computes the integer texel
2081  coordinates that the unnormalized coordinates lie within:
2082  
2083  [latexmath]
2084  ++++++++++++++++++++++++
2085  \begin{aligned}
2086  i &= \lfloor u + shift \rfloor \\
2087  j &= \lfloor v + shift \rfloor \\
2088  k &= \lfloor w + shift \rfloor
2089  \end{aligned}
2090  ++++++++++++++++++++++++
2091  where:
2092  
2093    :: [eq]#shift = 0.0#
2094  
2095  ifdef::VK_NV_corner_sampled_image[]
2096  for conventional images, and:
2097  
2098    :: [eq]#shift = 0.5#
2099  
2100  for corner-sampled images.
2101  endif::VK_NV_corner_sampled_image[]
2102  
2103  Linear filtering (ename:VK_FILTER_LINEAR) computes a set of neighboring
2104  coordinates which bound the unnormalized coordinates.
2105  The integer texel coordinates are combinations of [eq]#i~0~# or [eq]#i~1~#,
2106  [eq]#j~0~# or [eq]#j~1~#, [eq]#k~0~# or [eq]#k~1~#, as well as weights
2107  [eq]#{alpha}, {beta}#, and [eq]#{gamma}#.
2108  
2109  [latexmath]
2110  ++++++++++++++++++++++++
2111  \begin{aligned}
2112  i_0 &= \lfloor u - shift \rfloor \\
2113  i_1 &= i_0 + 1 \\
2114  j_0 &= \lfloor v - shift \rfloor \\
2115  j_1 &= j_0 + 1 \\
2116  k_0 &= \lfloor w - shift \rfloor
2117  k_1 &= k_0 + 1
2118  \end{aligned}
2119  ++++++++++++++++++++++++
2120  
2121  [latexmath]
2122  ++++++++++++++++++++++++
2123  \begin{aligned}
2124  \alpha &= \mathbin{frac}\left(u - shift\right)  \\[1em]
2125  \beta &= \mathbin{frac}\left(v - shift\right)  \\[1em]
2126  \gamma &= \mathbin{frac}\left(w - shift\right)
2127  \end{aligned}
2128  ++++++++++++++++++++++++
2129  
2130  where:
2131  
2132    :: [eq]#shift = 0.5#
2133  
2134  ifdef::VK_NV_corner_sampled_image[]
2135  for conventional images, and:
2136  
2137    :: [eq]#shift = 0.0#
2138  
2139  for corner-sampled images,
2140  endif::VK_NV_corner_sampled_image[]
2141  and where:
2142  
2143  [latexmath]
2144  ++++++++++++++++++++++++
2145  \mathbin{frac}(x) = x -  \lfloor x \rfloor
2146  ++++++++++++++++++++++++
2147  where the number of fraction bits retained is specified by
2148  sname:VkPhysicalDeviceLimits::pname:subTexelPrecisionBits.
2149  
2150  ifdef::VK_IMG_filter_cubic,VK_EXT_filter_cubic[]
2151  Cubic filtering (ename:VK_FILTER_CUBIC_EXT) computes a set of neighboring
2152  coordinates which bound the unnormalized coordinates.
2153  The integer texel coordinates are combinations of [eq]#i~0~#, [eq]#i~1~#,
2154  [eq]#i~2~# or [eq]#i~3~#, [eq]#j~0~#, [eq]#j~1~#, [eq]#j~2~# or [eq]#j~3~#,
2155  ifndef::VK_EXT_filter_cubic[]
2156  as well as weights [eq]#{alpha}# and [eq]#{beta}#.
2157  endif::VK_EXT_filter_cubic[]
2158  ifdef::VK_EXT_filter_cubic[]
2159  [eq]#k~0~#, [eq]#k~1~#, [eq]#k~2~# or [eq]#k~3~#, as well as weights
2160  [eq]#{alpha}#, [eq]#{beta}#, and [eq]#{gamma}#.
2161  endif::VK_EXT_filter_cubic[]
2162  
2163  ifndef::VK_EXT_filter_cubic[]
2164  [latexmath]
2165  ++++++++++++++++++++++++
2166  \begin{aligned}
2167  i_{0}  & = {\left \lfloor {u - \frac{3}{2}} \right \rfloor} & i_{1} & = i_{0} + 1 & i_{2} & = i_{1} + 1 & i_{3} & = i_{2} + 1 \\[1em]
2168  j_{0}  & = {\left \lfloor {v - \frac{3}{2}} \right \rfloor} & j_{1} & = j_{0} + 1 & j_{2} & = j_{1} + 1 & j_{3} & = j_{2} + 1
2169  \end{aligned}
2170  ++++++++++++++++++++++++
2171  
2172  [latexmath]
2173  ++++++++++++++++++++++++
2174  \begin{aligned}
2175  alpha &= \mathbin{frac}\left(u - \frac{1}{2}\right)  \\[1em]
2176  \beta &= \mathbin{frac}\left(v - \frac{1}{2}\right)
2177  \end{aligned}
2178  ++++++++++++++++++++++++
2179  
2180  endif::VK_EXT_filter_cubic[]
2181  
2182  ifdef::VK_EXT_filter_cubic[]
2183  [latexmath]
2184  ++++++++++++++++++++++++
2185  \begin{aligned}
2186  i_{0}  & = {\left \lfloor {u - \frac{3}{2}} \right \rfloor} & i_{1} & = i_{0} + 1 & i_{2} & = i_{1} + 1 & i_{3} & = i_{2} + 1 \\[1em]
2187  j_{0}  & = {\left \lfloor {v - \frac{3}{2}} \right \rfloor} & j_{1} & = j_{0} + 1 & j_{2} & = j_{1} + 1 & j_{3} & = j_{2} + 1 \\[1em]
2188  k_{0}  & = {\left \lfloor {w - \frac{3}{2}} \right \rfloor} & k_{1} & = k_{0} + 1 & k_{2} & = k_{1} + 1 & k_{3} & = k_{2} + 1
2189  \end{aligned}
2190  ++++++++++++++++++++++++
2191  
2192  [latexmath]
2193  ++++++++++++++++++++++++
2194  \begin{aligned}
2195  \alpha &= \mathbin{frac}\left(u - \frac{1}{2}\right)  \\[1em]
2196  \beta &= \mathbin{frac}\left(v - \frac{1}{2}\right)  \\[1em]
2197  \gamma &= \mathbin{frac}\left(w - \frac{1}{2}\right)
2198  \end{aligned}
2199  ++++++++++++++++++++++++
2200  
2201  endif::VK_EXT_filter_cubic[]
2202  
2203  where:
2204  
2205  [latexmath]
2206  ++++++++++++++++++++++++
2207  \mathbin{frac}(x) = x -  \lfloor x \rfloor
2208  ++++++++++++++++++++++++
2209  
2210  where the number of fraction bits retained is specified by
2211  sname:VkPhysicalDeviceLimits::pname:subTexelPrecisionBits.
2212  endif::VK_IMG_filter_cubic,VK_EXT_filter_cubic[]
2213  
2214  
2215  [[textures-integer-coordinate-operations]]
2216  == Integer Texel Coordinate Operations
2217  
2218  ifdef::VK_AMD_shader_image_load_store_lod[]
2219  Integer texel coordinate operations may: supply a LOD which texels are to be
2220  read from or written to using the optional SPIR-V operand code:Lod.
2221  endif::VK_AMD_shader_image_load_store_lod[]
2222  ifndef::VK_AMD_shader_image_load_store_lod[]
2223  The code:OpImageFetch and code:OpImageFetchSparse SPIR-V instructions may:
2224  supply a LOD from which texels are to be fetched using the optional SPIR-V
2225  operand code:Lod.
2226  Other integer-coordinate operations must: not.
2227  endif::VK_AMD_shader_image_load_store_lod[]
2228  If the code:Lod is provided then it must: be an integer.
2229  
2230  The image level selected is:
2231  [latexmath]
2232  ++++++++++++++++++++++++
2233  \begin{aligned}
2234  d & = level_{base} +
2235    \begin{cases}
2236      Lod & \text{(from optional SPIR-V operand)} \\
2237      0   & \text{otherwise}
2238    \end{cases} \\
2239  \end{aligned}
2240  ++++++++++++++++++++++++
2241  
2242  If [eq]#d# does not lie in the range [eq]#[pname:baseMipLevel,
2243  pname:baseMipLevel {plus} pname:levelCount)# then any values fetched are
2244  ifndef::VK_AMD_shader_image_load_store_lod[undefined:.]
2245  ifdef::VK_AMD_shader_image_load_store_lod[]
2246  undefined:, and any writes are discarded.
2247  endif::VK_AMD_shader_image_load_store_lod[]
2248  
2249  
2250  [[textures-sample-operations]]
2251  == Image Sample Operations
2252  
2253  
2254  [[textures-wrapping-operation]]
2255  === Wrapping Operation
2256  
2257  code:Cube images ignore the wrap modes specified in the sampler.
2258  Instead, if ename:VK_FILTER_NEAREST is used within a mip level then
2259  ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE is used, and if
2260  ename:VK_FILTER_LINEAR is used within a mip level then sampling at the edges
2261  is performed as described earlier in the <<textures-cubemapedge,Cube map
2262  edge handling>> section.
2263  
2264  The first integer texel coordinate i is transformed based on the
2265  pname:addressModeU parameter of the sampler.
2266  
2267  [latexmath]
2268  ++++++++++++++++++++++++
2269  \begin{aligned}
2270  i &=
2271    \begin{cases}
2272      i \bmod size                                & \text{for repeat} \\
2273      (size - 1) - \mathbin{mirror}
2274          ((i \bmod (2 \times size)) - size)      & \text{for mirrored repeat} \\
2275      \mathbin{clamp}(i,0,size-1)                  & \text{for clamp to edge} \\
2276      \mathbin{clamp}(i,-1,size)                   & \text{for clamp to border} \\
2277      \mathbin{clamp}(\mathbin{mirror}(i),0,size-1) & \text{for mirror clamp to edge}
2278    \end{cases}
2279  \end{aligned}
2280  ++++++++++++++++++++++++
2281  
2282  where:
2283  
2284  [latexmath]
2285  ++++++++++++++++++++++++
2286  \begin{aligned}
2287  & \mathbin{mirror}(n) =
2288    \begin{cases}
2289      n      & \text{for}\  n \geq 0 \\
2290      -(1+n) & \text{otherwise}
2291    \end{cases}
2292  \end{aligned}
2293  ++++++++++++++++++++++++
2294  
2295  [eq]#j# (for 2D and Cube image) and [eq]#k# (for 3D image) are similarly
2296  transformed based on the pname:addressModeV and pname:addressModeW
2297  parameters of the sampler, respectively.
2298  
2299  
2300  [[textures-gather]]
2301  === Texel Gathering
2302  
2303  SPIR-V instructions with code:Gather in the name return a vector derived
2304  from a 2{times}2 rectangular region of texels in the base level of the image
2305  view.
2306  The rules for the ename:VK_FILTER_LINEAR minification filter are applied to
2307  identify the four selected texels.
2308  Each texel is then converted to an RGBA value according to
2309  <<textures-conversion-to-rgba,conversion to RGBA>> and then
2310  <<textures-component-swizzle,swizzled>>.
2311  A four-component vector is then assembled by taking the component indicated
2312  by the code:Component value in the instruction from the swizzled color value
2313  of the four texels:
2314  
2315  [latexmath]
2316  ++++++++++++++++++++++++
2317  \begin{aligned}
2318  \tau[R] &= \tau_{i0j1}[level_{base}][comp] \\
2319  \tau[G] &= \tau_{i1j1}[level_{base}][comp] \\
2320  \tau[B] &= \tau_{i1j0}[level_{base}][comp] \\
2321  \tau[A] &= \tau_{i0j0}[level_{base}][comp]
2322  \end{aligned}
2323  ++++++++++++++++++++++++
2324  
2325  where:
2326  
2327  [latexmath]
2328  ++++++++++++++++++++++++
2329  \begin{aligned}
2330  \tau[level_{base}][comp] &=
2331    \begin{cases}
2332      \tau[level_{base}][R], & \text{for}\  comp = 0 \\
2333      \tau[level_{base}][G], & \text{for}\  comp = 1 \\
2334      \tau[level_{base}][B], & \text{for}\  comp = 2 \\
2335      \tau[level_{base}][A], & \text{for}\  comp = 3
2336    \end{cases}\\
2337  comp & \,\text{from SPIR-V operand Component}
2338  \end{aligned}
2339  ++++++++++++++++++++++++
2340  
2341  ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
2342  code:OpImage*code:Gather must: not be used on a sampled image with
2343  <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~ conversion>> enabled.
2344  endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
2345  
2346  
2347  [[textures-texel-filtering]]
2348  === Texel Filtering
2349  
2350  Texel filtering is first performed for each level (either [eq]#d# or
2351  [eq]#d~hi~# and [eq]#d~lo~#).
2352  
2353  If [eq]#{lambda}# is less than or equal to zero, the texture is said to be
2354  _magnified_, and the filter mode within a mip level is selected by the
2355  pname:magFilter in the sampler.
2356  If [eq]#{lambda}# is greater than zero, the texture is said to be
2357  _minified_, and the filter mode within a mip level is selected by the
2358  pname:minFilter in the sampler.
2359  
2360  [[textures-texel-nearest-filtering]]
2361  ==== Texel Nearest Filtering
2362  
2363  Within a mip level, ename:VK_FILTER_NEAREST filtering selects a single value
2364  using the [eq]#(i, j, k)# texel coordinates, with all texels taken from
2365  layer l.
2366  
2367  [latexmath]
2368  ++++++++++++++++++++++++
2369  \begin{aligned}
2370  \tau[level] &=
2371    \begin{cases}
2372       \tau_{ijk}[level], & \text{for 3D image} \\
2373       \tau_{ij}[level],  & \text{for 2D or Cube image} \\
2374       \tau_{i}[level],   & \text{for 1D image}
2375     \end{cases}
2376  \end{aligned}
2377  ++++++++++++++++++++++++
2378  
2379  [[textures-texel-linear-filtering]]
2380  ==== Texel Linear Filtering
2381  
2382  Within a mip level, ename:VK_FILTER_LINEAR filtering combines 8 (for 3D), 4
2383  (for 2D or Cube), or 2 (for 1D) texel values, together with their linear
2384  weights.
2385  The linear weights are derived from the fractions computed earlier:
2386  
2387  [latexmath]
2388  
2389  ++++++++++++++++++++++++
2390  \begin{aligned}
2391  w_{i_0} &= (1-\alpha) \\
2392  w_{i_1} &= (\alpha)   \\
2393  w_{j_0} &= (1-\beta)  \\
2394  w_{j_1} &= (\beta)    \\
2395  w_{k_0} &= (1-\gamma) \\
2396  w_{k_1} &= (\gamma)
2397  \end{aligned}
2398  ++++++++++++++++++++++++
2399  
2400  ifndef::VK_EXT_sampler_filter_minmax[]
2401  The values of multiple texels, together with their weights, are combined
2402  using a weighted average to produce a filtered value:
2403  endif::VK_EXT_sampler_filter_minmax[]
2404  
2405  ifdef::VK_EXT_sampler_filter_minmax[]
2406  The values of multiple texels, together with their weights, are combined to
2407  produce a filtered value.
2408  
2409  The slink:VkSamplerReductionModeCreateInfoEXT::pname:reductionMode can:
2410  control the process by which multiple texels, together with their weights,
2411  are combined to produce a filtered texture value.
2412  
2413  When the pname:reductionMode is set (explicitly or implicitly) to
2414  ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, a weighted average is
2415  computed:
2416  endif::VK_EXT_sampler_filter_minmax[]
2417  
2418  [latexmath]
2419  ++++++++++++++++++++++++
2420  \begin{aligned}
2421  \tau_{3D} &= \sum_{k=k_0}^{k_1}\sum_{j=j_0}^{j_1}\sum_{i=i_0}^{i_1}(w_{i})(w_{j})(w_{k})\tau_{ijk} \\
2422  \tau_{2D} &= \sum_{j=j_0}^{j_1}\sum_{i=i_0}^{i_1}(w_{i})(w_{j})\tau_{ij} \\
2423  \tau_{1D} &= \sum_{i=i_0}^{i_1}(w_{i})\tau_{i}
2424  \end{aligned}
2425  ++++++++++++++++++++++++
2426  
2427  ifdef::VK_EXT_sampler_filter_minmax[]
2428  However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN_EXT or
2429  ename:VK_SAMPLER_REDUCTION_MODE_MAX_EXT, the process operates on the above
2430  set of multiple texels, together with their weights, computing a
2431  component-wise minimum or maximum, respectively, of the components of the
2432  set of texels with non-zero weights.
2433  endif::VK_EXT_sampler_filter_minmax[]
2434  
2435  ifdef::VK_IMG_filter_cubic,VK_EXT_filter_cubic[]
2436  
2437  [[textures-texel-cubic-filtering]]
2438  ==== Texel Cubic Filtering
2439  
2440  Within a mip level, ename:VK_FILTER_CUBIC_EXT, filtering computes a weighted
2441  average of
2442  ifdef::VK_EXT_filter_cubic[]
2443  64 (for 3D),
2444  endif::VK_EXT_filter_cubic[]
2445  16 (for 2D), or 4 (for 1D) texel values, together with their Catmull-Rom
2446  weights.
2447  
2448  Catmull-Rom weights are derived from the fractions computed earlier.
2449  
2450  ifndef::VK_EXT_filter_cubic[]
2451  [latexmath]
2452  ++++++++++++++++++++++++
2453  \begin{aligned}
2454  \begin{bmatrix}
2455  w_{i_0}\phantom{,} w_{i_1}\phantom{,} w_{i_2}\phantom{,} w_{i_3}
2456  \end{bmatrix}
2457  = \frac{1}{2}
2458  \begin{bmatrix}
2459  1 & \alpha & \alpha^2 & \alpha^3
2460  \end{bmatrix}
2461  \begin{bmatrix}
2462  \phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2463  -1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2464  \phantom{-}2 & -5 &  \phantom{-}4 &  \phantom{-}1 \\
2465  -1 &  \phantom{-}3 & -3 &  \phantom{-}1
2466  \end{bmatrix}
2467  \\
2468  \begin{bmatrix}
2469  w_{j_0}\phantom{,} w_{j_1}\phantom{,} w_{j_2}\phantom{,} w_{j_3}
2470  \end{bmatrix}
2471  = \frac{1}{2}
2472  \begin{bmatrix}
2473  1 & \beta & \beta^2 & \beta^3
2474  \end{bmatrix}
2475  \begin{bmatrix}
2476  \phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2477  -1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2478  \phantom{-}2 & -5 &  \phantom{-}4 &  \phantom{-}1 \\
2479  -1 &  \phantom{-}3 & -3 &  \phantom{-}1
2480  \end{bmatrix}
2481  \end{aligned}
2482  ++++++++++++++++++++++++
2483  
2484  The values of multiple texels, together with their weights, are combined
2485  using a weighted average to produce a filtered value:
2486  
2487  [latexmath]
2488  ++++++++++++++++++++++++
2489  \begin{aligned}
2490  \tau_{2D} &= \sum_{j=j_0}^{j_3}\sum_{i=i_0}^{i_3}(w_{i})(w_{j})\tau_{ij} \\
2491  \tau_{1D} &= \sum_{i=i_0}^{i_3}(w_{i})\tau_{i}
2492  \end{aligned}
2493  ++++++++++++++++++++++++
2494  endif::VK_EXT_filter_cubic[]
2495  
2496  ifdef::VK_EXT_filter_cubic[]
2497  
2498  [latexmath]
2499  ++++++++++++++++++++++++
2500  \begin{aligned}
2501  \begin{bmatrix}
2502  w_{i_0}\phantom{,} w_{i_1}\phantom{,} w_{i_2}\phantom{,} w_{i_3}
2503  \end{bmatrix}
2504  = \frac{1}{2}
2505  \begin{bmatrix}
2506  1 & \alpha & \alpha^2 & \alpha^3
2507  \end{bmatrix}
2508  \begin{bmatrix}
2509  \phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2510  -1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2511  \phantom{-}2 & -5 &  \phantom{-}4 &  \phantom{-}1 \\
2512  -1 &  \phantom{-}3 & -3 &  \phantom{-}1
2513  \end{bmatrix}
2514  \\
2515  \begin{bmatrix}
2516  w_{j_0}\phantom{,} w_{j_1}\phantom{,} w_{j_2}\phantom{,} w_{j_3}
2517  \end{bmatrix}
2518  = \frac{1}{2}
2519  \begin{bmatrix}
2520  1 & \beta & \beta^2 & \beta^3
2521  \end{bmatrix}
2522  \begin{bmatrix}
2523  \phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2524  -1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2525  \phantom{-}2 & -5 &  \phantom{-}4 &  \phantom{-}1 \\
2526  -1 &  \phantom{-}3 & -3 &  \phantom{-}1
2527  \end{bmatrix}
2528  \\
2529  \begin{bmatrix}
2530  w_{k_0}\phantom{,} w_{k_1}\phantom{,} w_{k_2}\phantom{,} w_{k_3}
2531  \end{bmatrix}
2532  = \frac{1}{2}
2533  \begin{bmatrix}
2534  1 & \gamma & \gamma^2 & \gamma^3
2535  \end{bmatrix}
2536  \begin{bmatrix}
2537  \phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2538  -1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2539  \phantom{-}2 & -5 &  \phantom{-}4 &  \phantom{-}1 \\
2540  -1 &  \phantom{-}3 & -3 &  \phantom{-}1
2541  \end{bmatrix}
2542  \end{aligned}
2543  ++++++++++++++++++++++++
2544  
2545  The values of multiple texels, together with their weights, are combined to
2546  produce a filtered value.
2547  
2548  The slink:VkSamplerReductionModeCreateInfoEXT::pname:reductionMode can:
2549  control the process by which multiple texels, together with their weights,
2550  are combined to produce a filtered texture value.
2551  
2552  When the pname:reductionMode is set (explicitly or implicitly) to
2553  ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, a weighted average is
2554  computed:
2555  
2556  [latexmath]
2557  ++++++++++++++++++++++++
2558  \begin{aligned}
2559  \tau_{3D} &= \sum_{k=j_0}^{k_3}\sum_{j=j_0}^{j_3}\sum_{i=i_0}^{i_3}(w_{i})(w_{j})(w_{k})\tau_{ijk} \\
2560  \tau_{2D} &= \sum_{j=j_0}^{j_3}\sum_{i=i_0}^{i_3}(w_{i})(w_{j})\tau_{ij} \\
2561  \tau_{1D} &= \sum_{i=i_0}^{i_3}(w_{i})\tau_{i}
2562  \end{aligned}
2563  ++++++++++++++++++++++++
2564  
2565  ifdef::VK_EXT_sampler_filter_minmax[]
2566  However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN_EXT or
2567  ename:VK_SAMPLER_REDUCTION_MODE_MAX_EXT, the process operates on the above
2568  set of multiple texels, together with their weights, computing a
2569  component-wise minimum or maximum, respectively, of the components of the
2570  set of texels with non-zero weights.
2571  endif::VK_EXT_sampler_filter_minmax[]
2572  
2573  endif::VK_EXT_filter_cubic[]
2574  endif::VK_IMG_filter_cubic,VK_EXT_filter_cubic[]
2575  
2576  [[textures-texel-mipmap-filtering]]
2577  
2578  ==== Texel Mipmap Filtering
2579  
2580  ename:VK_SAMPLER_MIPMAP_MODE_NEAREST filtering returns the value of a single
2581  mipmap level,
2582  
2583  [eq]#{tau} = {tau}[d]#.
2584  
2585  ename:VK_SAMPLER_MIPMAP_MODE_LINEAR filtering combines the values of
2586  multiple mipmap levels ({tau}[hi] and {tau}[lo]), together with their linear
2587  weights.
2588  
2589  The linear weights are derived from the fraction computed earlier:
2590  
2591  [latexmath]
2592  
2593  ++++++++++++++++++++++++
2594  \begin{aligned}
2595  w_{hi} &= (1-\delta) \\
2596  w_{lo} &= (\delta)   \\
2597  \end{aligned}
2598  ++++++++++++++++++++++++
2599  
2600  ifndef::VK_EXT_sampler_filter_minmax[]
2601  The values of multiple mipmap levels together with their linear weights, are
2602  combined using a weighted average to produce a final filtered value:
2603  endif::VK_EXT_sampler_filter_minmax[]
2604  ifdef::VK_EXT_sampler_filter_minmax[]
2605  The values of multiple mipmap levels, together with their weights, are
2606  combined to produce a final filtered value.
2607  
2608  The slink:VkSamplerReductionModeCreateInfoEXT::pname:reductionMode can:
2609  control the process by which multiple texels, together with their weights,
2610  are combined to produce a filtered texture value.
2611  
2612  When the pname:reductionMode is set (explicitly or implicitly) to
2613  ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, a weighted average is
2614  computed:
2615  endif::VK_EXT_sampler_filter_minmax[]
2616  
2617  [latexmath]
2618  ++++++++++++++++++++++++
2619  \begin{aligned}
2620  \tau &= (w_{hi})\tau[hi]+(w_{lo})\tau[lo]
2621  \end{aligned}
2622  ++++++++++++++++++++++++
2623  
2624  [[textures-texel-anisotropic-filtering]]
2625  ==== Texel Anisotropic Filtering
2626  
2627  Anisotropic filtering is enabled by the pname:anisotropyEnable in the
2628  sampler.
2629  When enabled, the image filtering scheme accounts for a degree of
2630  anisotropy.
2631  
2632  The particular scheme for anisotropic texture filtering is implementation
2633  dependent.
2634  Implementations should: consider the pname:magFilter, pname:minFilter and
2635  pname:mipmapMode of the sampler to control the specifics of the anisotropic
2636  filtering scheme used.
2637  In addition, implementations should: consider pname:minLod and pname:maxLod
2638  of the sampler.
2639  
2640  The following describes one particular approach to implementing anisotropic
2641  filtering for the 2D Image case, implementations may: choose other methods:
2642  
2643  Given a pname:magFilter, pname:minFilter of ename:VK_FILTER_LINEAR and a
2644  pname:mipmapMode of ename:VK_SAMPLER_MIPMAP_MODE_NEAREST:
2645  
2646  Instead of a single isotropic sample, N isotropic samples are be sampled
2647  within the image footprint of the image level [eq]#d# to approximate an
2648  anisotropic filter.
2649  The sum [eq]#{tau}~2Daniso~# is defined using the single isotropic
2650  [eq]#{tau}~2D~(u,v)# at level [eq]#d#.
2651  
2652  [latexmath]
2653  ++++++++++++++++++++++++
2654  \begin{aligned}
2655  \tau_{2Daniso} & =
2656       \frac{1}{N}\sum_{i=1}^{N}
2657       {\tau_{2D}\left (
2658         u \left ( x - \frac{1}{2} + \frac{i}{N+1} , y \right ),
2659           \left ( v \left (x-\frac{1}{2}+\frac{i}{N+1} \right ), y
2660  \right )
2661       \right )},
2662       & \text{when}\  \rho_{x} > \rho_{y} \\
2663  \tau_{2Daniso} &=
2664       \frac{1}{N}\sum_{i=1}^{N}
2665       {\tau_{2D}\left (
2666          u \left  ( x, y - \frac{1}{2} + \frac{i}{N+1} \right ),
2667            \left ( v \left (x,y-\frac{1}{2}+\frac{i}{N+1} \right )
2668  \right )
2669       \right )},
2670       & \text{when}\  \rho_{y} \geq \rho_{x}
2671  \end{aligned}
2672  ++++++++++++++++++++++++
2673  
2674  ifdef::VK_EXT_sampler_filter_minmax[]
2675  When slink:VkSamplerReductionModeCreateInfoEXT::pname:reductionMode is set
2676  to ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT, the above summation
2677  is used.
2678  However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN_EXT or
2679  ename:VK_SAMPLER_REDUCTION_MODE_MAX_EXT, the process operates on the above
2680  values, together with their weights, computing a component-wise minimum or
2681  maximum, respectively, of the components of the values with non-zero
2682  weights.
2683  endif::VK_EXT_sampler_filter_minmax[]
2684  
2685  ifdef::VK_NV_shader_image_footprint[]
2686  [[textures-footprint]]
2687  == Texel Footprint Evaluation
2688  
2689  The SPIR-V instruction code:OpImageSampleFootprintNV evaluates the set of
2690  texels from a single mip level that would be accessed during a
2691  <<textures-texel-filtering, texel filtering>> operation.
2692  In addition to the inputs that would be accepted by an equivalent
2693  code:OpImageSample* instruction, code:OpImageSampleFootprintNV accepts two
2694  additional inputs.
2695  The code:Granularity input is an integer identifying the size of texel
2696  groups used to evaluate the footprint.
2697  Each bit in the returned footprint mask corresponds to an aligned block of
2698  texels whose size is given by the following table:
2699  
2700  .Texel footprint granularity values
2701  [width="50%",options="header"]
2702  |=====
2703  | code:Granularity  | code:Dim = 2D |  code:Dim = 3D
2704  |         0         |  unsupported  |  unsupported
2705  |         1         |      2x2      |     2x2x2
2706  |         2         |      4x2      |  unsupported
2707  |         3         |      4x4      |     4x4x2
2708  |         4         |      8x4      |  unsupported
2709  |         5         |      8x8      |  unsupported
2710  |         6         |     16x8      |  unsupported
2711  |         7         |     16x16     |  unsupported
2712  |         8         |  unsupported  |  unsupported
2713  |         9         |  unsupported  |  unsupported
2714  |         10        |  unsupported  |    16x16x16
2715  |         11        |     64x64     |    32x16x16
2716  |         12        |    128x64     |    32x32x16
2717  |         13        |    128x128    |    32x32x32
2718  |         14        |    256x128    |    64x32x32
2719  |         15        |    256x256    |  unsupported
2720  |=====
2721  
2722  The code:Coarse input is used to select between the two mip levels that may:
2723  be accessed during texel filtering when using a pname:mipmapMode of
2724  ename:VK_SAMPLER_MIPMAP_MODE_LINEAR.
2725  When filtering between two mip levels, a code:Coarse value of code:true
2726  requests the footprint in the lower-resolution mip level (higher level
2727  number), while code:false requests the footprint in the higher-resolution
2728  mip level.
2729  If texel filtering would access only a single mip level, the footprint in
2730  that level would be returned when code:Coarse is set to code:false; an empty
2731  footprint would be returned when code:Coarse is set to code:true.
2732  
2733  The footprint for code:OpImageSampleFootprintNV is returned in a structure
2734  with six members:
2735  
2736    * The first member is a boolean value that is true if the texel filtering
2737      operation would access only a single mip level.
2738    * The second member is a two- or three-component integer vector holding
2739      the footprint anchor location.
2740      For two-dimensional images, the returned components are in units of
2741      eight texel groups.
2742      For three-dimensional images, the returned components are in units of
2743      four texel groups.
2744    * The third member is a two- or three-component integer vector holding a
2745      footprint offset relative to the anchor.
2746      All returned components are in units of texel groups.
2747    * The fourth member is a two-component integer vector mask, which holds a
2748      bitfield identifying the set of texel groups in an 8x8 or 4x4x4
2749      neighborhood relative to the anchor and offset.
2750    * The fifth member is an integer identifying the mip level containing the
2751      footprint identified by the anchor, offset, and mask.
2752    * The sixth member is an integer identifying the granularity of the
2753      returned footprint.
2754  
2755  For footprints in two-dimensional images (code:Dim2D), the mask returned by
2756  code:OpImageSampleFootprintNV indicates whether each texel group in a 8x8
2757  local neighborhood of texel groups would have one or more texels accessed
2758  during texel filtering.
2759  In the mask, the texel group with local group coordinates
2760  latexmath:[(lgx,lgy)] is considered covered if and only if
2761  
2762  [latexmath]
2763  +++++++++++++++++++
2764  \begin{aligned}
2765  0 \neq ((mask.x + (mask.y << 32)) \text{ \& } (1 << (lgy \times 8 + lgx)))
2766  \end{aligned}
2767  +++++++++++++++++++
2768  
2769  where:
2770  
2771    * latexmath:[0<=lgx<8] and latexmath:[0<=lgy<8]; and
2772    * latexmath:[mask] is the returned two-component mask.
2773  
2774  The local group with coordinates latexmath:[(lgx,lgy)] in the mask is
2775  considered covered if and only if the texel filtering operation would access
2776  one or more texels latexmath:[\tau_{ij}] in the returned miplevel where:
2777  [latexmath]
2778  +++++++++++++++++++
2779  \begin{aligned}
2780  i0 & =
2781    \begin{cases}
2782      gran.x \times (8 \times anchor.x + lgx), & \text{if } lgx + offset.x < 8 \\
2783      gran.x \times (8 \times (anchor.x - 1) + lgx), & \text{otherwise}
2784    \end{cases} \\
2785  i1 & = i0 + gran.x - 1 \\
2786  j0 & =
2787    \begin{cases}
2788      gran.y \times (8 \times anchor.y + lgy), & \text{if } lgy + offset.y < 8 \\
2789      gran.y \times (8 \times (anchor.y - 1) + lgy), & otherwise
2790    \end{cases} \\
2791  j1 & = j0 + gran.y - 1
2792  \end{aligned}
2793  +++++++++++++++++++
2794  and
2795  
2796    * latexmath:[i0<=i<=i1] and latexmath:[j0<=j<=j1];
2797    * latexmath:[gran] is a two-component vector holding the width and height
2798      of the texel group identified by the granularity;
2799    * latexmath:[anchor] is the returned two-component anchor vector; and
2800    * latexmath:[offset] is the returned two-component offset vector.
2801  
2802  For footprints in three-dimensional images (code:Dim3D), the mask returned
2803  by code:OpImageSampleFootprintNV indicates whether each texel group in a
2804  4x4x4 local neighborhood of texel groups would have one or more texels
2805  accessed during texel filtering.
2806  In the mask, the texel group with local group coordinates
2807  latexmath:[(lgx,lgy,lgz)], is considered covered if and only if:
2808  [latexmath]
2809  +++++++++++++++++++
2810  \begin{aligned}
2811  0 \neq ((mask.x + (mask.y << 32)) \text{ \& } (1 << (lgz \times 16 + lgy \times 4 + lgx)))
2812  \end{aligned}
2813  +++++++++++++++++++
2814  where:
2815  
2816    * latexmath:[0<=lgx<4], latexmath:[0<=lgy<4], and latexmath:[0<=lgz<4];
2817      and
2818    * latexmath:[mask] is the returned two-component mask.
2819  
2820  The local group with coordinates latexmath:[(lgx,lgy,lgz)] in the mask is
2821  considered covered if and only if the texel filtering operation would access
2822  one or more texels latexmath:[\tau_{ijk}] in the returned miplevel where:
2823  [latexmath]
2824  +++++++++++++++++++
2825  \begin{aligned}
2826  i0 & =
2827    \begin{cases}
2828      gran.x \times (4 \times anchor.x + lgx), & \text{if } lgx + offset.x < 4 \\
2829      gran.x \times (4 \times (anchor.x - 1) + lgx), & \text{otherwise}
2830    \end{cases} \\
2831  i1 & = i0 + gran.x - 1 \\
2832  j0 & =
2833    \begin{cases}
2834      gran.y \times (4 \times anchor.y + lgy), & \text{if } lgy + offset.y < 4 \\
2835      gran.y \times (4 \times (anchor.y - 1) + lgy), & otherwise
2836    \end{cases} \\
2837  j1 & = j0 + gran.y - 1 \\
2838  k0 & =
2839    \begin{cases}
2840      gran.z \times (4 \times anchor.z + lgz), & \text{if } lgz + offset.z < 4 \\
2841      gran.z \times (4 \times (anchor.z - 1) + lgz), & otherwise
2842    \end{cases} \\
2843  k1 & = k0 + gran.z - 1
2844  \end{aligned}
2845  +++++++++++++++++++
2846  and
2847  
2848    * latexmath:[i0<=i<=i1], latexmath:[j0<=j<=j1], latexmath:[k0<=k<=k1];
2849    * latexmath:[gran] is a three-component vector holding the width, height,
2850      and depth of the texel group identified by the granularity;
2851    * latexmath:[anchor] is the returned three-component anchor vector; and
2852    * latexmath:[offset] is the returned three-component offset vector.
2853  
2854  If the sampler used by code:OpImageSampleFootprintNV enables anisotropic
2855  texel filtering via pname:anisotropyEnable, it is possible that the set of
2856  texel groups accessed in a mip level may be too large to be expressed using
2857  an 8x8 or 4x4x4 mask using the granularity requested in the instruction.
2858  In this case, the implementation uses a texel group larger than the
2859  requested granularity.
2860  When a larger texel group size is used, code:OpImageSampleFootprintNV
2861  returns an integer granularity value that can: be interpreted in the same
2862  manner as the granularity value provided to the instruction to determine the
2863  texel group size used.
2864  If anisotropic texel filtering is disabled in the sampler, or if an
2865  anisotropic footprint can be represented as an 8x8 or 4x4x4 mask with the
2866  requested granularity, code:OpImageSampleFootprintNV will use the requested
2867  granularity as-is and return a granularity value of zero.
2868  
2869  code:OpImageSampleFootprintNV supports only two- and three-dimensional image
2870  accesses (code:Dim2D and code:Dim3D) and the footprint returned is undefined
2871  if a sampler uses an addressing mode other than
2872  ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
2873  
2874  endif::VK_NV_shader_image_footprint[]
2875  
2876  
2877  [[textures-instructions]]
2878  == Image Operation Steps
2879  
2880  Each step described in this chapter is performed by a subset of the image
2881  instructions:
2882  
2883    * Texel Input Validation Operations, Format Conversion, Texel Replacement,
2884      Conversion to RGBA, and Component Swizzle: Performed by all instructions
2885      except code:OpImageWrite.
2886    * Depth Comparison: Performed by code:OpImage*code:Dref instructions.
2887    * All Texel output operations: Performed by code:OpImageWrite.
2888    * Projection: Performed by all code:OpImage*code:Proj instructions.
2889    * Derivative Image Operations, Cube Map Operations, Scale Factor
2890      Operation, Level-of-Detail Operation and Image Level(s) Selection, and
2891      Texel Anisotropic Filtering: Performed by all code:OpImageSample* and
2892      code:OpImageSparseSample* instructions.
2893    * (s,t,r,q,a) to (u,v,w,a) Transformation, Wrapping, and (u,v,w,a) to
2894      (i,j,k,l,n) Transformation And Array Layer Selection: Performed by all
2895      code:OpImageSample, code:OpImageSparseSample, and
2896      code:OpImage*code:Gather instructions.
2897    * Texel Gathering: Performed by code:OpImage*code:Gather instructions.
2898  ifdef::VK_NV_shader_image_footprint[]
2899    * Texel Footprint Evaluation: Performed by code:OpImageSampleFootprint
2900      instructions.
2901  endif::VK_NV_shader_image_footprint[]
2902    * Texel Filtering: Performed by all code:OpImageSample* and
2903      code:OpImageSparseSample* instructions.
2904    * Sparse Residency: Performed by all code:OpImageSparse* instructions.