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