1// Copyright 2015-2023 The Khronos Group Inc.
2//
3// SPDX-License-Identifier: CC-BY-4.0
4
5[[textures]]
6= Image Operations
7
8
9== Image Operations Overview
10
11Vulkan Image Operations are operations performed by those SPIR-V Image
12Instructions which take an code:OpTypeImage (representing a
13sname:VkImageView) or code:OpTypeSampledImage (representing a
14(sname:VkImageView, sname:VkSampler) pair).
15Read, write, and atomic operations also take texel coordinates as operands,
16and return a value based on a neighborhood of texture elements (_texels_)
17within the image.
18Query operations return properties of the bound image or of the lookup
19itself.
20The "`Depth`" operand of code:OpTypeImage is ignored.
21
22[NOTE]
23.Note
24====
25Texel is a term which is a combination of the words texture and element.
26Early interactive computer graphics supported texture operations on
27textures, a small subset of the image operations on images described here.
28The discrete samples remain essentially equivalent, however, so we retain
29the historical term texel to refer to them.
30====
31
32Image Operations include the functionality of the following SPIR-V Image
33Instructions:
34
35  * code:OpImageSample* and code:OpImageSparseSample* read one or more
36    neighboring texels of the image, and <<textures-texel-filtering,filter>>
37    the texel values based on the state of the sampler.
38  ** Instructions with code:ImplicitLod in the name
39     <<textures-level-of-detail-operation,determine>> the LOD used in the
40     sampling operation based on the coordinates used in neighboring
41     fragments.
42  ** Instructions with code:ExplicitLod in the name
43     <<textures-level-of-detail-operation,determine>> the LOD used in the
44     sampling operation based on additional coordinates.
45  ** Instructions with code:Proj in the name apply homogeneous
46     <<textures-projection,projection>> to the coordinates.
47  * code:OpImageFetch and code:OpImageSparseFetch return a single texel of
48    the image.
49    No sampler is used.
50  * code:OpImage*Gather and code:OpImageSparse*Gather read neighboring
51    texels and <<textures-gather,return a single component>> of each.
52  * code:OpImageRead (and code:OpImageSparseRead) and code:OpImageWrite read
53    and write, respectively, a texel in the image.
54    No sampler is used.
55ifdef::VK_NV_shader_image_footprint[]
56  * code:OpImageSampleFootprintNV identifies and returns information about
57    the set of texels in the image that would be accessed by an equivalent
58    code:OpImageSample* instruction.
59endif::VK_NV_shader_image_footprint[]
60  * code:OpImage*Dref* instructions apply
61    <<textures-depth-compare-operation,depth comparison>> on the texel
62    values.
63  * code:OpImageSparse* instructions additionally return a
64    <<textures-sparse-residency,sparse residency>> code.
65  * code:OpImageQuerySize, code:OpImageQuerySizeLod,
66    code:OpImageQueryLevels, and code:OpImageQuerySamples return properties
67    of the image descriptor that would be accessed.
68    The image itself is not accessed.
69  * code:OpImageQueryLod returns the LOD parameters that would be used in a
70    sample operation.
71    The actual operation is not performed.
72ifdef::VK_QCOM_image_processing[]
73  * code:OpImageWeightedSampleQCOM reads a 2D neighborhood of texels and
74    computes a weighted average using weight values from a separate weight
75    texture.
76  * code:opImageBlockMatchSADQCOM and code:opTextureBlockMatchSSD compare 2D
77    neighborhoods of texels from two textures.
78  * code:OpImageBoxFilterQCOM reads a 2D neighborhood of texels and computes
79    a weighted average of the texels.
80endif::VK_QCOM_image_processing[]
81ifdef::VK_QCOM_image_processing2[]
82  * code:opImageBlockMatchWindowSADQCOM and
83    code:opImageBlockMatchWindowSSDQCOM compare 2D neighborhoods of texels
84    from two textures with the comparison repeated across a window region in
85    the target texture.
86  * code:opImageBlockMatchGatherSADQCOM and
87    code:opImageBlockMatchWindowSSDQCOM compares four 2D neighborhoods of
88    texels from a target texture with a single 2D neighborhood in the
89    reference texture.
90    The R component of each comparison is gathered and returned in the
91    output.
92endif::VK_QCOM_image_processing2[]
93
94
95[[textures-texel-coordinate-systems]]
96=== Texel Coordinate Systems
97
98Images are addressed by _texel coordinates_.
99There are three _texel coordinate systems_:
100
101  * normalized texel coordinates [eq]#[0.0, 1.0]#
102  * unnormalized texel coordinates [eq]#[0.0, width / height / depth)#
103  * integer texel coordinates [eq]#[0, width / height / depth)#
104
105SPIR-V code:OpImageFetch, code:OpImageSparseFetch, code:OpImageRead,
106code:OpImageSparseRead,
107ifdef::VK_QCOM_image_processing[]
108code:opImageBlockMatchSADQCOM, code:opImageBlockMatchSSDQCOM,
109endif::VK_QCOM_image_processing[]
110ifdef::VK_QCOM_image_processing2[]
111code:opImageBlockMatchWindowSADQCOM, code:opImageBlockMatchWindowSSDQCOM,
112endif::VK_QCOM_image_processing2[]
113and code:OpImageWrite instructions use integer texel coordinates.
114
115Other image instructions can: use either normalized or unnormalized texel
116coordinates (selected by the pname:unnormalizedCoordinates state of the
117sampler used in the instruction), but there are
118<<samplers-unnormalizedCoordinates,limitations>> on what operations, image
119state, and sampler state is supported.
120Normalized coordinates are logically
121<<textures-normalized-to-unnormalized,converted>> to unnormalized as part of
122image operations, and <<textures-normalized-operations,certain steps>> are
123only performed on normalized coordinates.
124The array layer coordinate is always treated as unnormalized even when other
125coordinates are normalized.
126
127Normalized texel coordinates are referred to as [eq]#(s,t,r,q,a)#, with the
128coordinates having the following meanings:
129
130  * [eq]#s#: Coordinate in the first dimension of an image.
131  * [eq]#t#: Coordinate in the second dimension of an image.
132  * [eq]#r#: Coordinate in the third dimension of an image.
133  ** [eq]#(s,t,r)# are interpreted as a direction vector for Cube images.
134  * [eq]#q#: Fourth coordinate, for homogeneous (projective) coordinates.
135  * [eq]#a#: Coordinate for array layer.
136
137The coordinates are extracted from the SPIR-V operand based on the
138dimensionality of the image variable and type of instruction.
139For code:Proj instructions, the components are in order [eq]#(s, [t,] [r,]
140q)#, with [eq]#t# and [eq]#r# being conditionally present based on the
141code:Dim of the image.
142For non-code:Proj instructions, the coordinates are [eq]#(s [,t] [,r]
143[,a])#, with [eq]#t# and [eq]#r# being conditionally present based on the
144code:Dim of the image and [eq]#a# being conditionally present based on the
145code:Arrayed property of the image.
146Projective image instructions are not supported on code:Arrayed images.
147
148Unnormalized texel coordinates are referred to as [eq]#(u,v,w,a)#, with the
149coordinates having the following meanings:
150
151  * [eq]#u#: Coordinate in the first dimension of an image.
152  * [eq]#v#: Coordinate in the second dimension of an image.
153  * [eq]#w#: Coordinate in the third dimension of an image.
154  * [eq]#a#: Coordinate for array layer.
155
156Only the [eq]#u# and [eq]#v# coordinates are directly extracted from the
157SPIR-V operand, because only 1D and 2D (non-code:Arrayed) dimensionalities
158support unnormalized coordinates.
159The components are in order [eq]#(u [,v])#, with [eq]#v# being conditionally
160present when the dimensionality is 2D.
161When normalized coordinates are converted to unnormalized coordinates, all
162four coordinates are used.
163
164Integer texel coordinates are referred to as [eq]#(i,j,k,l,n)#, with the
165coordinates having the following meanings:
166
167  * [eq]#i#: Coordinate in the first dimension of an image.
168  * [eq]#j#: Coordinate in the second dimension of an image.
169  * [eq]#k#: Coordinate in the third dimension of an image.
170  * [eq]#l#: Coordinate for array layer.
171  * [eq]#n#: Index of the sample within the texel.
172
173They are extracted from the SPIR-V operand in order [eq]#(i [,j] [,k] [,l]
174[,n])#, with [eq]#j# and [eq]#k# conditionally present based on the code:Dim
175of the image, and [eq]#l# conditionally present based on the code:Arrayed
176property of the image.
177[eq]#n# is conditionally present and is taken from the code:Sample image
178operand.
179
180ifdef::VK_EXT_image_sliced_view_of_3d[]
181If an accessed image was created from a view using
182slink:VkImageViewSlicedCreateInfoEXT and accessed through a
183ename:VK_DESCRIPTOR_TYPE_STORAGE_IMAGE descriptor, then the value of [eq]#k#
184is incremented by slink:VkImageViewSlicedCreateInfoEXT::pname:sliceOffset,
185giving [eq]#k <- sliceOffset {plus} k#.
186The image's accessible range in the third dimension is [eq]#k < sliceOffset
187+ sliceCount#.
188If slink:VkImageViewSlicedCreateInfoEXT::pname:sliceCount is
189ename:VK_REMAINING_3D_SLICES_EXT, the range is inherited from the image's
190depth extent as specified by <<resources-image-mip-level-sizing, Image Mip
191Level Sizing>>.
192endif::VK_EXT_image_sliced_view_of_3d[]
193
194For all coordinate types, unused coordinates are assigned a value of zero.
195
196[[textures-texel-coordinate-systems-diagrams]]
197image::{images}/vulkantexture0-ll.svg[align="center",title="Texel Coordinate Systems, Linear Filtering",opts="{imageopts}"]
198The Texel Coordinate Systems - For the example shown of an 8{times}4 texel
199two dimensional image.
200
201  * Normalized texel coordinates:
202  ** The [eq]#s# coordinate goes from 0.0 to 1.0.
203  ** The [eq]#t# coordinate goes from 0.0 to 1.0.
204  * Unnormalized texel coordinates:
205  ** The [eq]#u# coordinate within the range 0.0 to 8.0 is within the image,
206     otherwise it is outside the image.
207  ** The [eq]#v# coordinate within the range 0.0 to 4.0 is within the image,
208     otherwise it is outside the image.
209  * Integer texel coordinates:
210  ** The [eq]#i# coordinate within the range 0 to 7 addresses texels within
211     the image, otherwise it is outside the image.
212  ** The [eq]#j# coordinate within the range 0 to 3 addresses texels within
213     the image, otherwise it is outside the image.
214  * Also shown for linear filtering:
215  ** Given the unnormalized coordinates [eq]#(u,v)#, the four texels
216     selected are [eq]#i~0~j~0~#, [eq]#i~1~j~0~#, [eq]#i~0~j~1~#, and
217     [eq]#i~1~j~1~#.
218  ** The fractions [eq]#{alpha}# and [eq]#{beta}#.
219  ** Given the offset [eq]#{DeltaUpper}~i~# and [eq]#{DeltaUpper}~j~#, the
220     four texels selected by the offset are [eq]#i~0~j'~0~#,
221     [eq]#i~1~j'~0~#, [eq]#i~0~j'~1~#, and [eq]#i~1~j'~1~#.
222
223ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
224[NOTE]
225.Note
226====
227For formats with reduced-resolution components, [eq]#{DeltaUpper}~i~# and
228[eq]#{DeltaUpper}~j~# are relative to the resolution of the
229highest-resolution component, and therefore may be divided by two relative
230to the unnormalized coordinate space of the lower-resolution components.
231====
232endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
233
234image::{images}/vulkantexture1-ll.svg[align="center",title="Texel Coordinate Systems, Nearest Filtering",opts="{imageopts}"]
235
236The Texel Coordinate Systems - For the example shown of an 8{times}4 texel
237two dimensional image.
238
239  * Texel coordinates as above.
240    Also shown for nearest filtering:
241  ** Given the unnormalized coordinates [eq]#(u,v)#, the texel selected is
242     [eq]#ij#.
243  ** Given the offset [eq]#{DeltaUpper}~i~# and [eq]#{DeltaUpper}~j~#, the
244     texel selected by the offset is [eq]#ij'#.
245
246ifdef::VK_NV_corner_sampled_image[]
247For corner-sampled images, the texel samples are located at the grid
248intersections instead of the texel centers.
249
250image::{images}/vulkantexture0-corner-alternative-a-ll.svg[align="center",title="Texel Coordinate Systems, Corner Sampling",opts="{imageopts}"]
251
252endif::VK_NV_corner_sampled_image[]
253
254
255== Conversion Formulas
256
257ifdef::editing-notes[]
258[NOTE]
259.editing-note
260====
261(Bill) These Conversion Formulas will likely move to Section 2.7 Fixed-Point
262Data Conversions (RGB to sRGB and sRGB to RGB) and section 2.6 Numeric
263Representation and Computation (RGB to Shared Exponent and Shared Exponent
264to RGB)
265====
266endif::editing-notes[]
267
268
269[[textures-RGB-sexp]]
270=== RGB to Shared Exponent Conversion
271
272An RGB color [eq]#(red, green, blue)# is transformed to a shared exponent
273color [eq]#(red~shared~, green~shared~, blue~shared~, exp~shared~)# as
274follows:
275
276First, the components [eq]#(red, green, blue)# are clamped to
277[eq]#(red~clamped~, green~clamped~, blue~clamped~)# as:
278
279  {empty}:: [eq]#red~clamped~ = max(0, min(sharedexp~max~, red))#
280  {empty}:: [eq]#green~clamped~ = max(0, min(sharedexp~max~, green))#
281  {empty}:: [eq]#blue~clamped~ = max(0, min(sharedexp~max~, blue))#
282
283where:
284
285[latexmath]
286+++++++++++++++++++
287\begin{aligned}
288N               & = 9  & \text{number of mantissa bits per component} \\
289B               & = 15 & \text{exponent bias} \\
290E_{max}         & = 31 & \text{maximum possible biased exponent value} \\
291sharedexp_{max} & = \frac{(2^N-1)}{2^N} \times 2^{(E_{max}-B)}
292\end{aligned}
293+++++++++++++++++++
294
295[NOTE]
296.Note
297====
298// The trailing + is to avoid the asciidoc parser treating the custom role
299// as a block attribute in some cases.
300[eq]#NaN#, if supported, is handled as in +
301<<ieee-754,IEEE 754-2008>> `minNum()` and `maxNum()`.
302This results in any [eq]#NaN# being mapped to zero.
303====
304
305The largest clamped component, [eq]#max~clamped~# is determined:
306
307  {empty}:: [eq]#max~clamped~ = max(red~clamped~, green~clamped~,
308            blue~clamped~)#
309
310A preliminary shared exponent [eq]#exp'# is computed:
311[latexmath]
312+++++++++++++++++++
313\begin{aligned}
314exp' =
315  \begin{cases}
316    \left \lfloor \log_2(max_{clamped}) \right \rfloor + (B+1)
317      & \text{for}\  max_{clamped} > 2^{-(B+1)} \\
318    0
319      & \text{for}\  max_{clamped} \leq 2^{-(B+1)}
320  \end{cases}
321\end{aligned}
322+++++++++++++++++++
323
324The shared exponent [eq]#exp~shared~# is computed:
325
326[latexmath]
327+++++++++++++++++++
328\begin{aligned}
329max_{shared} =
330    \left \lfloor
331        { \frac{max_{clamped}}{2^{(exp'-B-N)}} + \frac{1}{2} }
332    \right \rfloor
333\end{aligned}
334+++++++++++++++++++
335
336[latexmath]
337+++++++++++++++++++
338\begin{aligned}
339exp_{shared} =
340  \begin{cases}
341    exp'   & \text{for}\  0 \leq max_{shared} < 2^N \\
342    exp'+1 & \text{for}\  max_{shared} = 2^N
343  \end{cases}
344\end{aligned}
345+++++++++++++++++++
346
347Finally, three integer values in the range [eq]#0# to [eq]#2^N^# are
348computed:
349
350[latexmath]
351+++++++++++++++++++
352\begin{aligned}
353red_{shared} & =
354    \left \lfloor
355        { \frac{red_{clamped}}{2^{(exp_{shared}-B-N)}}+ \frac{1}{2} }
356    \right \rfloor \\
357green_{shared} & =
358    \left \lfloor
359        { \frac{green_{clamped}}{2^{(exp_{shared}-B-N)}}+ \frac{1}{2} }
360    \right \rfloor \\
361blue_{shared} & =
362    \left \lfloor
363        { \frac{blue_{clamped}}{2^{(exp_{shared}-B-N)}}+ \frac{1}{2} }
364    \right \rfloor
365\end{aligned}
366+++++++++++++++++++
367
368
369[[textures-sexp-RGB]]
370=== Shared Exponent to RGB
371
372A shared exponent color [eq]#(red~shared~, green~shared~, blue~shared~,
373exp~shared~)# is transformed to an RGB color [eq]#(red, green, blue)# as
374follows:
375
376  {empty}:: latexmath:[red = red_{shared} \times {2^{(exp_{shared}-B-N)}}]
377  {empty}:: latexmath:[green = green_{shared} \times
378            {2^{(exp_{shared}-B-N)}}]
379  {empty}:: latexmath:[blue = blue_{shared} \times {2^{(exp_{shared}-B-N)}}]
380
381where:
382
383  {empty}:: [eq]#N = 9# (number of mantissa bits per component)
384  {empty}:: [eq]#B = 15# (exponent bias)
385
386
387== Texel Input Operations
388
389_Texel input instructions_ are SPIR-V image instructions that read from an
390image.
391_Texel input operations_ are a set of steps that are performed on state,
392coordinates, and texel values while processing a texel input instruction,
393and which are common to some or all texel input instructions.
394They include the following steps, which are performed in the listed order:
395
396  * <<textures-input-validation,Validation operations>>
397  ** <<textures-operation-validation,Instruction/Sampler/Image validation>>
398  ** <<textures-integer-coordinate-validation,Coordinate validation>>
399  ** <<textures-sparse-validation,Sparse validation>>
400ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
401  ** <<textures-layout-validation,Layout validation>>
402endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
403  * <<textures-format-conversion,Format conversion>>
404  * <<textures-texel-replacement,Texel replacement>>
405  * <<textures-depth-compare-operation,Depth comparison>>
406  * <<textures-conversion-to-rgba,Conversion to RGBA>>
407  * <<textures-component-swizzle,Component swizzle>>
408ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
409  * <<textures-chroma-reconstruction,Chroma reconstruction>>
410  * <<textures-sampler-YCbCr-conversion,{YCbCr} conversion>>
411endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
412
413For texel input instructions involving multiple texels (for sampling or
414gathering), these steps are applied for each texel that is used in the
415instruction.
416Depending on the type of image instruction, other steps are conditionally
417performed between these steps or involving multiple coordinate or texel
418values.
419
420ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
421If <<textures-chroma-reconstruction,Chroma Reconstruction>> is implicit,
422<<textures-texel-filtering, Texel Filtering>> instead takes place during
423chroma reconstruction, before <<textures-sampler-YCbCr-conversion,sampler
424{YCbCr} conversion>> occurs.
425endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
426
427ifdef::VK_QCOM_image_processing[]
428The operations described in <<textures-blockmatch,block matching>> and
429<<textures-weightimage,weight image sampling>> are performed before
430<<textures-conversion-to-rgba,Conversion to RGBA>> and
431<<textures-component-swizzle,Component swizzle>>.
432endif::VK_QCOM_image_processing[]
433
434
435[[textures-input-validation]]
436=== Texel Input Validation Operations
437
438_Texel input validation operations_ inspect instruction/image/sampler state
439or coordinates, and in certain circumstances cause the texel value to be
440replaced or become undefined:.
441There are a series of validations that the texel undergoes.
442
443
444[[textures-operation-validation]]
445==== Instruction/Sampler/Image View Validation
446
447There are a number of cases where a SPIR-V instruction can: mismatch with
448the sampler, the image view, or both, and a number of further cases where
449the sampler can: mismatch with the image view.
450In such cases the value of the texel returned is undefined:.
451
452These cases include:
453
454  * The sampler pname:borderColor is an integer type and the image view
455    pname:format is not one of the elink:VkFormat integer types or a stencil
456    component of a depth/stencil format.
457  * The sampler pname:borderColor is a float type and the image view
458    pname:format is not one of the elink:VkFormat float types or a depth
459    component of a depth/stencil format.
460ifndef::VK_EXT_border_color_swizzle[]
461  * The sampler pname:borderColor is one of the opaque black colors
462    (ename:VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK or
463    ename:VK_BORDER_COLOR_INT_OPAQUE_BLACK) and the image view
464    elink:VkComponentSwizzle for any of the slink:VkComponentMapping
465    components is not the <<resources-image-views-identity-mappings,identity
466    swizzle>>.
467endif::VK_EXT_border_color_swizzle[]
468ifdef::VK_EXT_border_color_swizzle[]
469  * The sampler pname:borderColor is one of the opaque black colors
470    (ename:VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK or
471    ename:VK_BORDER_COLOR_INT_OPAQUE_BLACK) and the image view
472    elink:VkComponentSwizzle for any of the slink:VkComponentMapping
473    components is not the <<resources-image-views-identity-mappings,identity
474    swizzle>>, and
475    slink:VkPhysicalDeviceBorderColorSwizzleFeaturesEXT::pname:borderColorSwizzleFromImage
476    feature is not enabled, and
477    slink:VkSamplerBorderColorComponentMappingCreateInfoEXT is not
478    specified.
479  * slink:VkSamplerBorderColorComponentMappingCreateInfoEXT::pname:components,
480    if specified, has a component swizzle that does not match the component
481    swizzle of the image view, and either component swizzle is not a form of
482    identity swizzle.
483  * slink:VkSamplerBorderColorComponentMappingCreateInfoEXT::pname:srgb, if
484    specified, does not match the sRGB encoding of the image view.
485endif::VK_EXT_border_color_swizzle[]
486ifdef::VK_EXT_custom_border_color[]
487  * The sampler pname:borderColor is a custom color
488    (ename:VK_BORDER_COLOR_FLOAT_CUSTOM_EXT or
489    ename:VK_BORDER_COLOR_INT_CUSTOM_EXT) and the supplied
490    slink:VkSamplerCustomBorderColorCreateInfoEXT::pname:customBorderColor
491    is outside the bounds of the values representable in the image view's
492    pname:format.
493ifndef::VK_EXT_border_color_swizzle[]
494  * The sampler pname:borderColor is a custom color
495    (ename:VK_BORDER_COLOR_FLOAT_CUSTOM_EXT or
496    ename:VK_BORDER_COLOR_INT_CUSTOM_EXT) and the image view
497    elink:VkComponentSwizzle for any of the slink:VkComponentMapping
498    components is not the <<resources-image-views-identity-mappings,identity
499    swizzle>>.
500endif::VK_EXT_border_color_swizzle[]
501ifdef::VK_EXT_border_color_swizzle[]
502  * The sampler pname:borderColor is a custom color
503    (ename:VK_BORDER_COLOR_FLOAT_CUSTOM_EXT or
504    ename:VK_BORDER_COLOR_INT_CUSTOM_EXT) and the image view
505    elink:VkComponentSwizzle for any of the slink:VkComponentMapping
506    components is not the <<resources-image-views-identity-mappings,identity
507    swizzle>>, and
508    slink:VkPhysicalDeviceBorderColorSwizzleFeaturesEXT::pname:borderColorSwizzleFromImage
509    feature is not enabled, and
510    slink:VkSamplerBorderColorComponentMappingCreateInfoEXT is not
511    specified.
512endif::VK_EXT_border_color_swizzle[]
513endif::VK_EXT_custom_border_color[]
514  * The elink:VkImageLayout of any subresource in the image view does not
515    match the slink:VkDescriptorImageInfo::pname:imageLayout used to write
516    the image descriptor.
517  * The SPIR-V Image Format is not <<spirvenv-image-formats,compatible>>
518    with the image view's pname:format.
519  * The sampler pname:unnormalizedCoordinates is ename:VK_TRUE and any of
520    the <<samplers-unnormalizedCoordinates,limitations of unnormalized
521    coordinates>> are violated.
522ifdef::VK_EXT_fragment_density_map[]
523  * The sampler was created with pname:flags containing
524    ename:VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT and the image was not created
525    with pname:flags containing ename:VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT.
526  * The sampler was not created with pname:flags containing
527    ename:VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT and the image was created
528    with pname:flags containing ename:VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT.
529  * The sampler was created with pname:flags containing
530    ename:VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT and is used with a function
531    that is not code:OpImageSampleImplicitLod or
532    code:OpImageSampleExplicitLod, or is used with operands code:Offset or
533    code:ConstOffsets.
534endif::VK_EXT_fragment_density_map[]
535  * The SPIR-V instruction is one of the code:OpImage*Dref* instructions and
536    the sampler pname:compareEnable is ename:VK_FALSE
537  * The SPIR-V instruction is not one of the code:OpImage*Dref* instructions
538    and the sampler pname:compareEnable is ename:VK_TRUE
539ifndef::VK_VERSION_1_3,VK_KHR_format_feature_flags2[]
540  * The SPIR-V instruction is one of the code:OpImage*Dref* instructions and
541    the image view pname:format is not one of the depth/stencil formats with
542    a depth component, or the image view aspect is not
543    ename:VK_IMAGE_ASPECT_DEPTH_BIT.
544endif::VK_VERSION_1_3,VK_KHR_format_feature_flags2[]
545ifdef::VK_VERSION_1_3,VK_KHR_format_feature_flags2[]
546  * The SPIR-V instruction is one of the code:OpImage*Dref* instructions,
547    the image view pname:format is one of the depth/stencil formats, and the
548    image view aspect is not ename:VK_IMAGE_ASPECT_DEPTH_BIT.
549endif::VK_VERSION_1_3,VK_KHR_format_feature_flags2[]
550  * The SPIR-V instruction's image variable's properties are not compatible
551    with the image view:
552  ** Rules for pname:viewType:
553  *** ename:VK_IMAGE_VIEW_TYPE_1D must: have code:Dim = 1D, code:Arrayed =
554      0, code:MS = 0.
555  *** ename:VK_IMAGE_VIEW_TYPE_2D must: have code:Dim = 2D, code:Arrayed = 0.
556  *** ename:VK_IMAGE_VIEW_TYPE_3D must: have code:Dim = 3D, code:Arrayed =
557      0, code:MS = 0.
558  *** ename:VK_IMAGE_VIEW_TYPE_CUBE must: have code:Dim = Cube, code:Arrayed
559      = 0, code:MS = 0.
560  *** ename:VK_IMAGE_VIEW_TYPE_1D_ARRAY must: have code:Dim = 1D,
561      code:Arrayed = 1, code:MS = 0.
562  *** ename:VK_IMAGE_VIEW_TYPE_2D_ARRAY must: have code:Dim = 2D,
563      code:Arrayed = 1.
564  *** ename:VK_IMAGE_VIEW_TYPE_CUBE_ARRAY must: have code:Dim = Cube,
565      code:Arrayed = 1, code:MS = 0.
566  ** If the image was created with slink:VkImageCreateInfo::pname:samples
567     equal to ename:VK_SAMPLE_COUNT_1_BIT, the instruction must: have
568     code:MS = 0.
569  ** If the image was created with slink:VkImageCreateInfo::pname:samples
570     not equal to ename:VK_SAMPLE_COUNT_1_BIT, the instruction must: have
571     code:MS = 1.
572  ** If the code:Sampled code:Type of the code:OpTypeImage does not match
573     the <<spirv-type,SPIR-V Type>>.
574  ** If the <<spirvenv-image-signedness,signedness of any read or sample
575     operation>> does not match the signedness of the image's format.
576ifdef::VK_NV_corner_sampled_image[]
577  * If the image was created with slink:VkImageCreateInfo::pname:flags
578    containing ename:VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV, the sampler
579    addressing modes must: only use a elink:VkSamplerAddressMode of
580    ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
581endif::VK_NV_corner_sampled_image[]
582ifdef::VK_NV_shader_image_footprint[]
583  * The SPIR-V instruction is code:OpImageSampleFootprintNV with code:Dim =
584    2D and pname:addressModeU or pname:addressModeV in the sampler is not
585    ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
586  * The SPIR-V instruction is code:OpImageSampleFootprintNV with code:Dim =
587    3D and pname:addressModeU, pname:addressModeV, or pname:addressModeW in
588    the sampler is not ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
589endif::VK_NV_shader_image_footprint[]
590ifdef::VK_EXT_custom_border_color[]
591  * The sampler was created with a specified
592    slink:VkSamplerCustomBorderColorCreateInfoEXT::pname:format which does
593    not match the elink:VkFormat of the image view(s) it is sampling.
594  * The sampler is sampling an image view of
595    ename:VK_FORMAT_B4G4R4A4_UNORM_PACK16,
596    ename:VK_FORMAT_B5G6R5_UNORM_PACK16, or
597    ename:VK_FORMAT_B5G5R5A1_UNORM_PACK16 format without a specified
598    slink:VkSamplerCustomBorderColorCreateInfoEXT::pname:format.
599endif::VK_EXT_custom_border_color[]
600
601ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
602Only code:OpImageSample* and code:OpImageSparseSample* can: be used with a
603sampler or image view that enables <<samplers-YCbCr-conversion,sampler
604{YCbCr} conversion>>.
605
606code:OpImageFetch, code:OpImageSparseFetch, code:OpImage*Gather, and
607code:OpImageSparse*Gather must: not be used with a sampler or image view
608that enables <<samplers-YCbCr-conversion,sampler {YCbCr} conversion>>.
609
610The code:ConstOffset and code:Offset operands must: not be used with a
611sampler or image view that enables <<samplers-YCbCr-conversion,sampler
612{YCbCr} conversion>>.
613endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
614
615
616[[textures-integer-coordinate-validation]]
617==== Integer Texel Coordinate Validation
618
619Integer texel coordinates are validated against the size of the image level,
620and the number of layers and number of samples in the image.
621For SPIR-V instructions that use integer texel coordinates, this is
622performed directly on the integer coordinates.
623For instructions that use normalized or unnormalized texel coordinates, this
624is performed on the coordinates that result after
625<<textures-unnormalized-to-integer,conversion>> to integer texel
626coordinates.
627
628If the integer texel coordinates do not satisfy all of the conditions
629
630  {empty}:: [eq]#0 {leq} i < w~s~#
631  {empty}:: [eq]#0 {leq} j < h~s~#
632  {empty}:: [eq]#0 {leq} k < d~s~#
633  {empty}:: [eq]#0 {leq} l < layers#
634  {empty}:: [eq]#0 {leq} n < samples#
635
636where:
637
638  {empty}:: [eq]#w~s~ =# width of the image level
639  {empty}:: [eq]#h~s~ =# height of the image level
640  {empty}:: [eq]#d~s~ =# depth of the image level
641  {empty}:: [eq]#layers =# number of layers in the image
642  {empty}:: [eq]#samples =# number of samples per texel in the image
643
644then the texel fails integer texel coordinate validation.
645
646There are four cases to consider:
647
648  . Valid Texel Coordinates
649+
650  * If the texel coordinates pass validation (that is, the coordinates lie
651    within the image),
652+
653then the texel value comes from the value in image memory.
654
655  . Border Texel
656+
657  * If the texel coordinates fail validation, and
658  * If the read is the result of an image sample instruction or image gather
659    instruction, and
660  * If the image is not a cube image,
661ifdef::VK_EXT_non_seamless_cube_map[]
662    or if a sampler created with
663    ename:VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT is used,
664endif::VK_EXT_non_seamless_cube_map[]
665
666+
667then the texel is a border texel and <<textures-texel-replacement,texel
668replacement>> is performed.
669
670  . Invalid Texel
671+
672  * If the texel coordinates fail validation, and
673  * If the read is the result of an image fetch instruction, image read
674    instruction, or atomic instruction,
675+
676then the texel is an invalid texel and <<textures-texel-replacement,texel
677replacement>> is performed.
678
679  . Cube Map Edge or Corner
680+
681Otherwise the texel coordinates lie beyond the edges or corners of the
682selected cube map face, and <<textures-cubemapedge, Cube map edge handling>>
683is performed.
684
685
686[[textures-cubemapedge]]
687==== Cube Map Edge Handling
688
689If the texel coordinates lie beyond the edges or corners of the selected
690cube map face (as described in the prior section), the following steps are
691performed.
692Note that this does not occur when using ename:VK_FILTER_NEAREST filtering
693within a mip level, since ename:VK_FILTER_NEAREST is treated as using
694ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
695
696  * Cube Map Edge Texel
697+
698  ** If the texel lies beyond the selected cube map face in either only
699     [eq]#i# or only [eq]#j#, then the coordinates [eq]#(i,j)# and the array
700     layer [eq]#l# are transformed to select the adjacent texel from the
701     appropriate neighboring face.
702
703  * Cube Map Corner Texel
704+
705  ** If the texel lies beyond the selected cube map face in both [eq]#i# and
706     [eq]#j#, then there is no unique neighboring face from which to read
707     that texel.
708     The texel should: be replaced by the average of the three values of the
709     adjacent texels in each incident face.
710     However, implementations may: replace the cube map corner texel by
711     other methods.
712ifndef::VK_EXT_filter_cubic[]
713The methods are subject to the constraint that if the three available texels
714have the same value, the resulting filtered texel must: have that value.
715endif::VK_EXT_filter_cubic[]
716ifdef::VK_EXT_filter_cubic[]
717The methods are subject to the constraint that for linear filtering if the
718three available texels have the same value, the resulting filtered texel
719must: have that value, and for cubic filtering if the twelve available
720samples have the same value, the resulting filtered texel must: have that
721value.
722endif::VK_EXT_filter_cubic[]
723
724
725[[textures-sparse-validation]]
726==== Sparse Validation
727
728If the texel reads from an unbound region of a sparse image, the texel is a
729_sparse unbound texel_, and processing continues with
730<<textures-texel-replacement,texel replacement>>.
731
732
733ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
734[[textures-layout-validation]]
735==== Layout Validation
736
737If all planes of a _disjoint_ _multi-planar_ image are not in the same
738<<resources-image-layouts,image layout>>, the image must: not be sampled
739with <<samplers-YCbCr-conversion,sampler {YCbCr} conversion>> enabled.
740
741endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
742
743
744[[textures-format-conversion]]
745=== Format Conversion
746
747Texels undergo a format conversion from the elink:VkFormat of the image view
748to a vector of either floating point or signed or unsigned integer
749components, with the number of components based on the number of components
750present in the format.
751
752  * Color formats have one, two, three, or four components, according to the
753    format.
754  * Depth/stencil formats are one component.
755    The depth or stencil component is selected by the pname:aspectMask of
756    the image view.
757
758Each component is converted based on its type and size (as defined in the
759<<formats-definition,Format Definition>> section for each elink:VkFormat),
760using the appropriate equations in <<fundamentals-fp16,16-Bit Floating-Point
761Numbers>>, <<fundamentals-fp11,Unsigned 11-Bit Floating-Point Numbers>>,
762<<fundamentals-fp10,Unsigned 10-Bit Floating-Point Numbers>>,
763<<fundamentals-fixedconv,Fixed-Point Data Conversion>>, and
764<<textures-sexp-RGB,Shared Exponent to RGB>>.
765Signed integer components smaller than 32 bits are sign-extended.
766
767If the image view format is sRGB, the color components are first converted
768as if they are UNORM, and then sRGB to linear conversion is applied to the
769R, G, and B components as described in the "`sRGB EOTF`" section of the
770<<data-format,Khronos Data Format Specification>>.
771The A component, if present, is unchanged.
772
773ifdef::VK_QCOM_ycbcr_degamma[]
774[[textures-ycbcr-degamma]]
775If
776slink:VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM::pname:enableYDegamma
777is equal to ename:VK_TRUE, then sRGB to linear conversion is applied to the
778G component as described in the "`sRGB EOTF`" section of the
779<<data-format,Khronos Data Format Specification>>.
780If
781slink:VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM::pname:enableCbCrDegamma
782is equal to ename:VK_TRUE, then sRGB to linear conversion is applied to the
783R and B components as described in the "`sRGB EOTF`" section of the
784<<data-format,Khronos Data Format Specification>>.
785The A component, if present, is unchanged.
786endif::VK_QCOM_ycbcr_degamma[]
787
788If the image view format is block-compressed, then the texel value is first
789decoded, then converted based on the type and number of components defined
790by the compressed format.
791
792
793[[textures-texel-replacement]]
794=== Texel Replacement
795
796A texel is replaced if it is one (and only one) of:
797
798  * a border texel,
799  * an invalid texel, or
800  * a sparse unbound texel.
801
802Border texels are replaced with a value based on the image format and the
803pname:borderColor of the sampler.
804The border color is:
805
806[[textures-border-replacement-color]]
807ifdef::VK_EXT_custom_border_color[]
808.Border Color [eq]#B#, Custom Border Color slink:VkSamplerCustomBorderColorCreateInfoEXT::pname:customBorderColor [eq]#U#
809endif::VK_EXT_custom_border_color[]
810ifndef::VK_EXT_custom_border_color[]
811.Border Color [eq]#B#
812endif::VK_EXT_custom_border_color[]
813[options="header",cols="60%,40%"]
814|====
815| Sampler pname:borderColor                     | Corresponding Border Color
816| ename:VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK | [eq]#[B~r~, B~g~, B~b~, B~a~] = [0.0, 0.0, 0.0, 0.0]#
817| ename:VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK      | [eq]#[B~r~, B~g~, B~b~, B~a~] = [0.0, 0.0, 0.0, 1.0]#
818| ename:VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE      | [eq]#[B~r~, B~g~, B~b~, B~a~] = [1.0, 1.0, 1.0, 1.0]#
819| ename:VK_BORDER_COLOR_INT_TRANSPARENT_BLACK   | [eq]#[B~r~, B~g~, B~b~, B~a~] = [0, 0, 0, 0]#
820| ename:VK_BORDER_COLOR_INT_OPAQUE_BLACK        | [eq]#[B~r~, B~g~, B~b~, B~a~] = [0, 0, 0, 1]#
821| ename:VK_BORDER_COLOR_INT_OPAQUE_WHITE        | [eq]#[B~r~, B~g~, B~b~, B~a~] = [1, 1, 1, 1]#
822ifdef::VK_EXT_custom_border_color[]
823| ename:VK_BORDER_COLOR_FLOAT_CUSTOM_EXT        | [eq]#[B~r~, B~g~, B~b~, B~a~] = [U~r~, U~g~, U~b~, U~a~]#
824| ename:VK_BORDER_COLOR_INT_CUSTOM_EXT          | [eq]#[B~r~, B~g~, B~b~, B~a~] = [U~r~, U~g~, U~b~, U~a~]#
825endif::VK_EXT_custom_border_color[]
826|====
827
828ifdef::VK_EXT_custom_border_color[]
829The custom border color ([eq]#U#) may: be rounded by implementations prior
830to texel replacement, but the error introduced by such a rounding must: not
831exceed one ULP of the image's pname:format.
832endif::VK_EXT_custom_border_color[]
833
834[NOTE]
835.Note
836====
837The names etext:VK_BORDER_COLOR_*\_TRANSPARENT_BLACK,
838etext:VK_BORDER_COLOR_*\_OPAQUE_BLACK, and
839etext:VK_BORDER_COLOR_*_OPAQUE_WHITE are meant to describe which components
840are zeros and ones in the vocabulary of compositing, and are not meant to
841imply that the numerical value of ename:VK_BORDER_COLOR_INT_OPAQUE_WHITE is
842a saturating value for integers.
843====
844
845This is substituted for the texel value by replacing the number of
846components in the image format
847
848[[textures-border-replacement-table]]
849.Border Texel Components After Replacement
850[width="100%",options="header"]
851|====
852| Texel Aspect or Format      | Component Assignment
853| Depth aspect                | [eq]#D                                     = B~r~#
854ifdef::VK_EXT_custom_border_color[]
855| Stencil aspect              | [eq]#S                                     = B~r~#{sym2}
856endif::VK_EXT_custom_border_color[]
857ifndef::VK_EXT_custom_border_color[]
858| Stencil aspect              | [eq]#S                                     = B~r~#
859endif::VK_EXT_custom_border_color[]
860| One component color format  | [eq]#Color~r~                              = B~r~#
861| Two component color format  | [eq]#[Color~r~,Color~g~]                   = [B~r~,B~g~]#
862| Three component color format| [eq]#[Color~r~,Color~g~,Color~b~]          = [B~r~,B~g~,B~b~]#
863| Four component color format | [eq]#[Color~r~,Color~g~,Color~b~,Color~a~] = [B~r~,B~g~,B~b~,B~a~]#
864ifdef::VK_KHR_maintenance5[]
865| Single component alpha format | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [0,0,0,B~a~]#
866endif::VK_KHR_maintenance5[]
867|====
868ifdef::VK_EXT_custom_border_color[]
869{sym2} [eq]#S = B~g~# may: be substituted as the replacement method by the
870implementation when slink:VkSamplerCreateInfo::pname:borderColor is
871ename:VK_BORDER_COLOR_INT_CUSTOM_EXT and
872slink:VkSamplerCustomBorderColorCreateInfoEXT::pname:format is
873ename:VK_FORMAT_UNDEFINED.
874Implementations should: use [eq]#S = B~r~# as the replacement method.
875endif::VK_EXT_custom_border_color[]
876
877The value returned by a read of an invalid texel is undefined:, unless that
878read operation is from a buffer resource and the pname:robustBufferAccess
879feature is enabled.
880In that case, an invalid texel is replaced as described by the
881<<features-robustBufferAccess, pname:robustBufferAccess>> feature.
882ifdef::VK_VERSION_1_3,VK_EXT_image_robustness,VK_EXT_robustness2[]
883If the access is to an image resource and the x, y, z, or layer coordinate
884validation fails and
885ifdef::VK_VERSION_1_3,VK_EXT_image_robustness[]
886the <<features-robustImageAccess, pname:robustImageAccess>> feature is
887enabled, then zero must: be returned for the R, G, and B components, if
888present.
889Either zero or one must: be returned for the A component, if present.
890ifdef::VK_EXT_robustness2[If]
891endif::VK_VERSION_1_3,VK_EXT_image_robustness[]
892ifdef::VK_EXT_robustness2[]
893If the <<features-robustImageAccess2, pname:robustImageAccess2>> feature is
894enabled, zero values must: be returned.
895endif::VK_EXT_robustness2[]
896If only the sample index was invalid, the values returned are undefined:.
897endif::VK_VERSION_1_3,VK_EXT_image_robustness,VK_EXT_robustness2[]
898
899ifdef::VK_VERSION_1_3,VK_EXT_image_robustness[]
900Additionally, if the <<features-robustImageAccess, pname:robustImageAccess>>
901feature is enabled,
902ifdef::VK_EXT_robustness2[]
903but the <<features-robustImageAccess2, pname:robustImageAccess2>> feature is
904not,
905endif::VK_EXT_robustness2[]
906any invalid texels may: be expanded to four components prior to texel
907replacement.
908This means that components not present in the image format may be replaced
909with 0 or may undergo <<textures-conversion-to-rgba,conversion to RGBA>> as
910normal.
911endif::VK_VERSION_1_3,VK_EXT_image_robustness[]
912
913ifdef::VK_EXT_robustness2[]
914Loads from a null descriptor return a four component color value of all
915zeros.
916However, for storage images and storage texel buffers using an explicit
917SPIR-V Image Format, loads from a null descriptor may: return an alpha value
918of 1 (float or integer, depending on format) if the format does not include
919alpha.
920endif::VK_EXT_robustness2[]
921
922If the
923slink:VkPhysicalDeviceSparseProperties::pname:residencyNonResidentStrict
924property is ename:VK_TRUE, a sparse unbound texel is replaced with 0 or 0.0
925values for integer and floating-point components of the image format,
926respectively.
927
928If pname:residencyNonResidentStrict is ename:VK_FALSE, the value of the
929sparse unbound texel is undefined:.
930
931
932[[textures-depth-compare-operation]]
933=== Depth Compare Operation
934
935If the image view has a depth/stencil format, the depth component is
936selected by the pname:aspectMask, and the operation is an code:OpImage*Dref*
937instruction, a depth comparison is performed.
938The result is [eq]#1.0# if the comparison evaluates to [eq]#true#, and
939[eq]#0.0# otherwise.
940This value replaces the depth component [eq]#D#.
941
942The compare operation is selected by the elink:VkCompareOp value set by
943slink:VkSamplerCreateInfo::pname:compareOp.
944The reference value from the SPIR-V operand [eq]#D~ref~# and the texel depth
945value [eq]#D~tex~# are used as the _reference_ and _test_ values,
946respectively, in that operation.
947
948If the image being sampled has an unsigned normalized fixed-point format,
949then [eq]#D~ref~# is clamped to [eq]#[0,1]# before the compare operation.
950
951
952[[textures-conversion-to-rgba]]
953=== Conversion to RGBA
954
955The texel is expanded from one, two, or three components to four components
956based on the image base color:
957
958[[textures-texel-color-rgba-conversion-table]]
959.Texel Color After Conversion To RGBA
960[width="100%", options="header", cols="<4,<6"]
961|====
962| Texel Aspect or Format      | RGBA Color
963| Depth aspect                | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [D,0,0,one]#
964| Stencil aspect              | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [S,0,0,one]#
965| One component color format  | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [Color~r~,0,0,one]#
966| Two component color format  | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [Color~r~,Color~g~,0,one]#
967| Three component color format| [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [Color~r~,Color~g~,Color~b~,one]#
968| Four component color format | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [Color~r~,Color~g~,Color~b~,Color~a~]#
969ifdef::VK_KHR_maintenance5[]
970| One alpha component color format | [eq]#[Color~r~,Color~g~,Color~b~, Color~a~] = [0,0,0,Color~a~]#
971endif::VK_KHR_maintenance5[]
972|====
973
974where [eq]#one = 1.0f# for floating-point formats and depth aspects, and
975[eq]#one = 1# for integer formats and stencil aspects.
976
977
978[[textures-component-swizzle]]
979=== Component Swizzle
980
981ifndef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
982All texel input instructions apply a _swizzle_ based on the
983elink:VkComponentSwizzle enums in the pname:components member of the
984slink:VkImageViewCreateInfo structure for the image being read.
985endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
986ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
987All texel input instructions apply a _swizzle_ based on:
988
989  * the elink:VkComponentSwizzle enums in the pname:components member of the
990    slink:VkImageViewCreateInfo structure for the image being read if
991    <<samplers-YCbCr-conversion,sampler {YCbCr} conversion>> is not enabled,
992    and
993  * the elink:VkComponentSwizzle enums in the pname:components member of the
994    slink:VkSamplerYcbcrConversionCreateInfo structure for the
995    <<samplers-YCbCr-conversion,sampler {YCbCr} conversion>> if sampler
996    {YCbCr} conversion is enabled.
997
998endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
999
1000The swizzle can: rearrange the components of the texel, or substitute zero
1001or one for any components.
1002It is defined as follows for each color [eq]#component#:
1003
1004
1005[latexmath]
1006+++++++++++++++++++
1007\begin{aligned}
1008Color'_{component} & =
1009\begin{cases}
1010Color_r          & \text{for RED swizzle}   \\
1011Color_g          & \text{for GREEN swizzle} \\
1012Color_b          & \text{for BLUE swizzle}  \\
1013Color_a          & \text{for ALPHA swizzle} \\
10140                & \text{for ZERO swizzle}  \\
1015one              & \text{for ONE swizzle} \\
1016identity         & \text{for IDENTITY swizzle}
1017\end{cases}
1018\end{aligned}
1019+++++++++++++++++++
1020
1021where:
1022
1023[latexmath]
1024+++++++++++++++++++
1025\begin{aligned}
1026one & =
1027\begin{cases}
1028& 1.0\text{f}  & \text{for floating point components} \\
1029& 1            & \text{for integer components} \\
1030\end{cases}
1031\\
1032identity & =
1033\begin{cases}
1034& Color_r          & \text{for}\ component = r \\
1035& Color_g          & \text{for}\ component = g \\
1036& Color_b          & \text{for}\ component = b \\
1037& Color_a          & \text{for}\ component = a \\
1038\end{cases}
1039\end{aligned}
1040+++++++++++++++++++
1041
1042If the border color is one of the etext:VK_BORDER_COLOR_*_OPAQUE_BLACK enums
1043and the elink:VkComponentSwizzle is not the
1044<<resources-image-views-identity-mappings,identity swizzle>> for all
1045components, the value of the texel after swizzle is undefined:.
1046
1047ifndef::VK_KHR_maintenance5[]
1048If the image view has a depth/stencil format and the
1049elink:VkComponentSwizzle is ename:VK_COMPONENT_SWIZZLE_ONE, the value of the
1050texel after swizzle is undefined:.
1051endif::VK_KHR_maintenance5[]
1052ifdef::VK_KHR_maintenance5[]
1053If the image view has a depth/stencil format and the
1054elink:VkComponentSwizzle is ename:VK_COMPONENT_SWIZZLE_ONE, and
1055sname:VkPhysicalDeviceMaintenance5PropertiesKHR::pname:depthStencilSwizzleOneSupport
1056is not set to ename:VK_TRUE, the value of the texel after swizzle is
1057undefined:.
1058endif::VK_KHR_maintenance5[]
1059
1060
1061[[textures-sparse-residency]]
1062=== Sparse Residency
1063
1064code:OpImageSparse* instructions return a structure which includes a
1065_residency code_ indicating whether any texels accessed by the instruction
1066are sparse unbound texels.
1067This code can: be interpreted by the code:OpImageSparseTexelsResident
1068instruction which converts the residency code to a boolean value.
1069
1070
1071ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
1072[[textures-chroma-reconstruction]]
1073=== Chroma Reconstruction
1074
1075In some color models, the color representation is defined in terms of
1076monochromatic light intensity (often called "`luma`") and color differences
1077relative to this intensity, often called "`chroma`".
1078It is common for color models other than RGB to represent the chroma
1079components at lower spatial resolution than the luma component.
1080This approach is used to take advantage of the eye's lower spatial
1081sensitivity to color compared with its sensitivity to brightness.
1082Less commonly, the same approach is used with additive color, since the
1083green component dominates the eye's sensitivity to light intensity and the
1084spatial sensitivity to color introduced by red and blue is lower.
1085
1086Lower-resolution components are "`downsampled`" by resizing them to a lower
1087spatial resolution than the component representing luminance.
1088This process is also commonly known as "`chroma subsampling`".
1089There is one luminance sample in each texture texel, but each chrominance
1090sample may be shared among several texels in one or both texture dimensions.
1091
1092  * "`etext:_444`" formats do not spatially downsample chroma values
1093    compared with luma: there are unique chroma samples for each texel.
1094  * "`etext:_422`" formats have downsampling in the x dimension
1095    (corresponding to _u_ or _s_ coordinates): they are sampled at half the
1096    resolution of luma in that dimension.
1097  * "`etext:_420`" formats have downsampling in the x dimension
1098    (corresponding to _u_ or _s_ coordinates) and the y dimension
1099    (corresponding to _v_ or _t_ coordinates): they are sampled at half the
1100    resolution of luma in both dimensions.
1101
1102The process of reconstructing a full color value for texture access involves
1103accessing both chroma and luma values at the same location.
1104To generate the color accurately, the values of the lower-resolution
1105components at the location of the luma samples must be reconstructed from
1106the lower-resolution sample locations, an operation known here as "`chroma
1107reconstruction`" irrespective of the actual color model.
1108
1109The location of the chroma samples relative to the luma coordinates is
1110determined by the pname:xChromaOffset and pname:yChromaOffset members of the
1111slink:VkSamplerYcbcrConversionCreateInfo structure used to create the
1112sampler {YCbCr} conversion.
1113
1114The following diagrams show the relationship between unnormalized (_u_,_v_)
1115coordinates and (_i_,_j_) integer texel positions in the luma component
1116(shown in black, with circles showing integer sample positions) and the
1117texel coordinates of reduced-resolution chroma components, shown as crosses
1118in red.
1119
1120[NOTE]
1121.Note
1122====
1123If the chroma values are reconstructed at the locations of the luma samples
1124by means of interpolation, chroma samples from outside the image bounds are
1125needed; these are determined according to <<textures-wrapping-operation>>.
1126These diagrams represent this by showing the bounds of the "`chroma texel`"
1127extending beyond the image bounds, and including additional chroma sample
1128positions where required for interpolation.
1129The limits of a sample for etext:NEAREST sampling is shown as a grid.
1130====
1131
1132image::{images}/chromasamples_422_cosited.svg[align="center",title="422 downsampling, xChromaOffset=COSITED_EVEN",opts="{imageopts}"]
1133
1134image::{images}/chromasamples_422_midpoint.svg[align="center",title="422 downsampling, xChromaOffset=MIDPOINT",opts="{imageopts}"]
1135
1136image::{images}/chromasamples_420_xcosited_ycosited.svg[align="center",title="420 downsampling, xChromaOffset=COSITED_EVEN, yChromaOffset=COSITED_EVEN",opts="{imageopts}"]
1137
1138image::{images}/chromasamples_420_xmidpoint_ycosited.svg[align="center",title="420 downsampling, xChromaOffset=MIDPOINT, yChromaOffset=COSITED_EVEN",opts="{imageopts}"]
1139
1140image::{images}/chromasamples_420_xcosited_ymidpoint.svg[align="center",title="420 downsampling, xChromaOffset=COSITED_EVEN, yChromaOffset=MIDPOINT",opts="{imageopts}"]
1141
1142image::{images}/chromasamples_420_xmidpoint_ymidpoint.svg[align="center",title="420 downsampling, xChromaOffset=MIDPOINT, yChromaOffset=MIDPOINT",opts="{imageopts}"]
1143
1144Reconstruction is implemented in one of two ways:
1145
1146If the format of the image that is to be sampled sets
1147ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT,
1148or the slink:VkSamplerYcbcrConversionCreateInfo's
1149pname:forceExplicitReconstruction is set to ename:VK_TRUE, reconstruction is
1150performed as an explicit step independent of filtering, described in the
1151<<textures-explicit-reconstruction>> section.
1152
1153If the format of the image that is to be sampled does not set
1154ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT
1155and if the slink:VkSamplerYcbcrConversionCreateInfo's
1156pname:forceExplicitReconstruction is set to ename:VK_FALSE, reconstruction
1157is performed as an implicit part of filtering prior to color model
1158conversion, with no separate post-conversion texel filtering step, as
1159described in the <<textures-implict-reconstruction,Implicit Reconstruction>>
1160section.
1161
1162
1163[[textures-explicit-reconstruction]]
1164==== Explicit Reconstruction
1165
1166  * If the pname:chromaFilter member of the
1167    slink:VkSamplerYcbcrConversionCreateInfo structure is
1168    ename:VK_FILTER_NEAREST:
1169  ** If the format's R and B components are reduced in resolution in just
1170     width by a factor of two relative to the G component (i.e. this is a
1171     "`etext:_422`" format), the latexmath:[\tau_{ijk}[level\]] values
1172     accessed by <<textures-texel-filtering,texel filtering>> are
1173     reconstructed as follows:
1174+
1175[latexmath]
1176++++++++++++++
1177\begin{aligned}
1178\tau_R'(i, j) & = \tau_R(\left\lfloor{i\times 0.5}\right\rfloor, j)[level] \\
1179\tau_B'(i, j) & = \tau_B(\left\lfloor{i\times 0.5}\right\rfloor, j)[level]
1180\end{aligned}
1181++++++++++++++
1182
1183  ** If the format's R and B components are reduced in resolution in width
1184     and height by a factor of two relative to the G component (i.e. this is
1185     a "`etext:_420`" format), the latexmath:[\tau_{ijk}[level\]] values
1186     accessed by <<textures-texel-filtering,texel filtering>> are
1187     reconstructed as follows:
1188+
1189[latexmath]
1190++++++++++++++
1191\begin{aligned}
1192\tau_R'(i, j) & = \tau_R(\left\lfloor{i\times 0.5}\right\rfloor, \left\lfloor{j\times 0.5}\right\rfloor)[level] \\
1193\tau_B'(i, j) & = \tau_B(\left\lfloor{i\times 0.5}\right\rfloor, \left\lfloor{j\times 0.5}\right\rfloor)[level]
1194\end{aligned}
1195++++++++++++++
1196+
1197[NOTE]
1198.Note
1199====
1200pname:xChromaOffset and pname:yChromaOffset have no effect if
1201pname:chromaFilter is ename:VK_FILTER_NEAREST for explicit reconstruction.
1202====
1203
1204  * If the pname:chromaFilter member of the
1205    slink:VkSamplerYcbcrConversionCreateInfo structure is
1206    ename:VK_FILTER_LINEAR:
1207  ** If the format's R and B components are reduced in resolution in just
1208     width by a factor of two relative to the G component (i.e. this is a
1209     "`etext:_422`" format):
1210  *** If pname:xChromaOffset is ename:VK_CHROMA_LOCATION_COSITED_EVEN:
1211+
1212[latexmath]
1213+++++
1214\tau_{RB}'(i,j) = \begin{cases}
1215\tau_{RB}(\left\lfloor{i\times 0.5}\right\rfloor,j)[level], & 0.5 \times i = \left\lfloor{0.5 \times i}\right\rfloor\\
12160.5\times\tau_{RB}(\left\lfloor{i\times 0.5}\right\rfloor,j)[level] + \\
12170.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
1218\end{cases}
1219+++++
1220+
1221  *** If pname:xChromaOffset is ename:VK_CHROMA_LOCATION_MIDPOINT:
1222+
1223[latexmath]
1224+++++
1225\tau_{RB}'(i,j) = \begin{cases}
12260.25 \times \tau_{RB}(\left\lfloor{i\times 0.5}\right\rfloor - 1,j)[level] + \\
12270.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\\
12280.75 \times \tau_{RB}(\left\lfloor{i\times 0.5}\right\rfloor,j)[level] + \\
12290.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
1230\end{cases}
1231+++++
1232
1233  ** If the format's R and B components are reduced in resolution in width
1234     and height by a factor of two relative to the G component (i.e. this is
1235     a "`etext:_420`" format), a similar relationship applies.
1236     Due to the number of options, these formulae are expressed more
1237     concisely as follows:
1238+
1239[latexmath]
1240+++++
1241\begin{aligned}
1242  i_{RB} & =
1243    \begin{cases}
1244      0.5 \times (i) & \textrm{xChromaOffset = COSITED}\_\textrm{EVEN} \\
1245      0.5 \times (i - 0.5) & \textrm{xChromaOffset = MIDPOINT}
1246    \end{cases}\\
1247  j_{RB} & =
1248    \begin{cases}
1249      0.5 \times (j) & \textrm{yChromaOffset = COSITED}\_\textrm{EVEN} \\
1250      0.5 \times (j - 0.5) & \textrm{yChromaOffset = MIDPOINT}
1251    \end{cases}\\
1252  \\
1253  i_{floor} & = \left\lfloor i_{RB} \right\rfloor \\
1254  j_{floor} & = \left\lfloor j_{RB} \right\rfloor \\
1255  \\
1256  i_{frac} & = i_{RB} - i_{floor} \\
1257  j_{frac} & = j_{RB} - j_{floor}
1258\end{aligned}
1259+++++
1260+
1261[latexmath]
1262+++++
1263\begin{aligned}
1264\tau_{RB}'(i,j) =
1265    & \tau_{RB}(     i_{floor},     j_{floor})[level]
1266        & \times & ( 1 - i_{frac} ) &
1267        & \times & ( 1 - j_{frac} ) & + \\
1268    & \tau_{RB}( 1 + i_{floor},     j_{floor})[level]
1269        & \times & (     i_{frac} ) &
1270        & \times & ( 1 - j_{frac} ) & + \\
1271    & \tau_{RB}(     i_{floor}, 1 + j_{floor})[level]
1272        & \times & ( 1 - i_{frac} ) &
1273        & \times & (     j_{frac} ) & + \\
1274    & \tau_{RB}( 1 + i_{floor}, 1 + j_{floor})[level]
1275        & \times & (     i_{frac} ) &
1276        & \times & (     j_{frac} ) &
1277\end{aligned}
1278+++++
1279
1280[NOTE]
1281.Note
1282====
1283In the case where the texture itself is bilinearly interpolated as described
1284in <<textures-texel-filtering,Texel Filtering>>, thus requiring four
1285full-color samples for the filtering operation, and where the reconstruction
1286of these samples uses bilinear interpolation in the chroma components due to
1287pname:chromaFilter=ename:VK_FILTER_LINEAR, up to nine chroma samples may be
1288required, depending on the sample location.
1289====
1290
1291
1292[[textures-implict-reconstruction]]
1293==== Implicit Reconstruction
1294
1295Implicit reconstruction takes place by the samples being interpolated, as
1296required by the filter settings of the sampler, except that
1297pname:chromaFilter takes precedence for the chroma samples.
1298
1299If pname:chromaFilter is ename:VK_FILTER_NEAREST, an implementation may:
1300behave as if pname:xChromaOffset and pname:yChromaOffset were both
1301ename:VK_CHROMA_LOCATION_MIDPOINT, irrespective of the values set.
1302
1303[NOTE]
1304.Note
1305====
1306This will not have any visible effect if the locations of the luma samples
1307coincide with the location of the samples used for rasterization.
1308====
1309
1310The sample coordinates are adjusted by the downsample factor of the
1311component (such that, for example, the sample coordinates are divided by two
1312if the component has a downsample factor of two relative to the luma
1313component):
1314
1315[latexmath]
1316++++++
1317\begin{aligned}
1318u_{RB}' (422/420) &=
1319  \begin{cases}
1320     0.5\times (u + 0.5), & \textrm{xChromaOffset = COSITED}\_\textrm{EVEN} \\
1321     0.5\times u, & \textrm{xChromaOffset = MIDPOINT}
1322  \end{cases} \\
1323v_{RB}' (420) &=
1324  \begin{cases}
1325     0.5\times (v + 0.5), & \textrm{yChromaOffset = COSITED}\_\textrm{EVEN} \\
1326     0.5\times v, & \textrm{yChromaOffset = MIDPOINT}
1327  \end{cases}
1328\end{aligned}
1329++++++
1330
1331
1332[[textures-sampler-YCbCr-conversion]]
1333=== Sampler {YCbCr} Conversion
1334
1335Sampler {YCbCr} conversion performs the following operations, which an
1336implementation may: combine into a single mathematical operation:
1337
1338  * <<textures-sampler-YCbCr-conversion-rangeexpand,Sampler {YCbCr} Range
1339    Expansion>>
1340  * <<textures-sampler-YCbCr-conversion-modelconversion,Sampler {YCbCr}
1341    Model Conversion>>
1342
1343
1344[[textures-sampler-YCbCr-conversion-rangeexpand]]
1345==== Sampler {YCbCr} Range Expansion
1346
1347Sampler {YCbCr} range expansion is applied to color component values after
1348all texel input operations which are not specific to sampler {YCbCr}
1349conversion.
1350For example, the input values to this stage have been converted using the
1351normal <<textures-format-conversion,format conversion>> rules.
1352
1353ifdef::VK_QCOM_ycbcr_degamma[]
1354The input values to this stage may have been converted using sRGB to linear
1355conversion if <<features-ycbcr-degamma,pname:ycbcrDegamma>> is enabled.
1356endif::VK_QCOM_ycbcr_degamma[]
1357
1358Sampler {YCbCr} range expansion is not applied if pname:ycbcrModel is
1359ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY.
1360That is, the shader receives the vector C'~rgba~ as output by the Component
1361Swizzle stage without further modification.
1362
1363For other values of pname:ycbcrModel, range expansion is applied to the
1364texel component values output by the <<textures-component-swizzle,Component
1365Swizzle>> defined by the pname:components member of
1366slink:VkSamplerYcbcrConversionCreateInfo.
1367Range expansion applies independently to each component of the image.
1368For the purposes of range expansion and {YCbCr} model conversion, the R and
1369B components contain color difference (chroma) values and the G component
1370contains luma.
1371The A component is not modified by sampler {YCbCr} range expansion.
1372
1373The range expansion to be applied is defined by the pname:ycbcrRange member
1374of the slink:VkSamplerYcbcrConversionCreateInfo structure:
1375
1376  * If pname:ycbcrRange is ename:VK_SAMPLER_YCBCR_RANGE_ITU_FULL, the
1377    following transformations are applied:
1378+
1379[latexmath]
1380+++++++++++++++++++
1381\begin{aligned}
1382Y' &= C'_{rgba}[G] \\
1383C_B &= C'_{rgba}[B] - {{2^{(n-1)}}\over{(2^n) - 1}} \\
1384C_R &= C'_{rgba}[R] - {{2^{(n-1)}}\over{(2^n) - 1}}
1385\end{aligned}
1386+++++++++++++++++++
1387+
1388[NOTE]
1389.Note
1390====
1391These formulae correspond to the "`full range`" encoding in the
1392"`Quantization schemes`" chapter of the <<data-format,Khronos Data Format
1393Specification>>.
1394
1395Should any future amendments be made to the ITU specifications from which
1396these equations are derived, the formulae used by Vulkan may: also be
1397updated to maintain parity.
1398====
1399  * If pname:ycbcrRange is ename:VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, the
1400    following transformations are applied:
1401+
1402[latexmath]
1403+++++++++++++++++++
1404\begin{aligned}
1405Y' &= {{C'_{rgba}[G] \times (2^n-1) - 16\times 2^{n-8}}\over{219\times 2^{n-8}}} \\
1406C_B &= {{C'_{rgba}[B] \times \left(2^n-1\right) - 128\times 2^{n-8}}\over{224\times 2^{n-8}}} \\
1407C_R &= {{C'_{rgba}[R] \times \left(2^n-1\right) - 128\times 2^{n-8}}\over{224\times 2^{n-8}}}
1408\end{aligned}
1409+++++++++++++++++++
1410+
1411[NOTE]
1412.Note
1413====
1414These formulae correspond to the "`narrow range`" encoding in the
1415"`Quantization schemes`" chapter of the <<data-format,Khronos Data Format
1416Specification>>.
1417====
1418  * _n_ is the bit-depth of the components in the format.
1419
1420The precision of the operations performed during range expansion must: be at
1421least that of the source format.
1422
1423An implementation may: clamp the results of these range expansion operations
1424such that Y{prime} falls in the range [0,1], and/or such that C~B~ and C~R~
1425fall in the range [-0.5,0.5].
1426
1427
1428[[textures-sampler-YCbCr-conversion-modelconversion]]
1429==== Sampler {YCbCr} Model Conversion
1430
1431The range-expanded values are converted between color models, according to
1432the color model conversion specified in the pname:ycbcrModel member:
1433
1434ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY::
1435    The color components are not modified by the color model conversion
1436    since they are assumed already to represent the desired color model in
1437    which the shader is operating; {YCbCr} range expansion is also ignored.
1438ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY::
1439    The color components are not modified by the color model conversion and
1440    are assumed to be treated as though in {YCbCr} form both in memory and
1441    in the shader; {YCbCr} range expansion is applied to the components as
1442    for other {YCbCr} models, with the vector (C~R~,Y{prime},C~B~,A)
1443    provided to the shader.
1444ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709::
1445    The color components are transformed from a {YCbCr} representation to an
1446    {RGBprime} representation as described in the "`BT.709 {YCbCr}
1447    conversion`" section of the <<data-format,Khronos Data Format
1448    Specification>>.
1449ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601::
1450    The color components are transformed from a {YCbCr} representation to an
1451    {RGBprime} representation as described in the "`BT.601 {YCbCr}
1452    conversion`" section of the <<data-format,Khronos Data Format
1453    Specification>>.
1454ename:VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020::
1455    The color components are transformed from a {YCbCr} representation to an
1456    {RGBprime} representation as described in the "`BT.2020 {YCbCr}
1457    conversion`" section of the <<data-format,Khronos Data Format
1458    Specification>>.
1459
1460In this operation, each output component is dependent on each input
1461component.
1462
1463An implementation may: clamp the {RGBprime} results of these conversions to
1464the range [0,1].
1465
1466The precision of the operations performed during model conversion must: be
1467at least that of the source format.
1468
1469The alpha component is not modified by these model conversions.
1470
1471[NOTE]
1472.Note
1473====
1474Sampling operations in a non-linear color space can introduce color and
1475intensity shifts at sharp transition boundaries.
1476To avoid this issue, the technically precise color correction sequence
1477described in the "`Introduction to Color Conversions`" chapter of the
1478<<data-format,Khronos Data Format Specification>> may be performed as
1479follows:
1480
1481  * Calculate the <<textures-normalized-to-unnormalized,unnormalized texel
1482    coordinates>> corresponding to the desired sample position.
1483  * For a pname:minFilter or pname:magFilter of ename:VK_FILTER_NEAREST:
1484    . Calculate (_i_,_j_) for the sample location as described under the
1485      "`nearest filtering`" formulae in <<textures-unnormalized-to-integer>>
1486    . Calculate the normalized texel coordinates corresponding to these
1487      integer coordinates.
1488    . Sample using <<samplers-YCbCr-conversion,sampler {YCbCr} conversion>>
1489      at this location.
1490  * For a pname:minFilter or pname:magFilter of ename:VK_FILTER_LINEAR:
1491    . Calculate (_i~[0,1]~_,_j~[0,1]~_) for the sample location as described
1492      under the "`linear filtering`" formulae in
1493      <<textures-unnormalized-to-integer>>
1494    . Calculate the normalized texel coordinates corresponding to these
1495      integer coordinates.
1496    . Sample using <<samplers-YCbCr-conversion,sampler {YCbCr} conversion>>
1497      at each of these locations.
1498    . Convert the non-linear A{prime}{RGBprime} outputs of the {YCbCr}
1499      conversions to linear ARGB values as described in the "`Transfer
1500      Functions`" chapter of the <<data-format,Khronos Data Format
1501      Specification>>.
1502    . Interpolate the linear ARGB values using the [eq]#{alpha}# and
1503      [eq]#{beta}# values described in the "`linear filtering`" section of
1504      <<textures-unnormalized-to-integer>> and the equations in
1505      <<textures-texel-filtering>>.
1506
1507The additional calculations and, especially, additional number of sampling
1508operations in the ename:VK_FILTER_LINEAR case can be expected to have a
1509performance impact compared with using the outputs directly.
1510Since the variations from "`correct`" results are subtle for most content,
1511the application author should determine whether a more costly implementation
1512is strictly necessary.
1513
1514If pname:chromaFilter, and pname:minFilter or pname:magFilter are both
1515ename:VK_FILTER_NEAREST, these operations are redundant and sampling using
1516<<samplers-YCbCr-conversion,sampler {YCbCr} conversion>> at the desired
1517sample coordinates will produce the "`correct`" results without further
1518processing.
1519====
1520endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
1521
1522
1523== Texel Output Operations
1524
1525_Texel output instructions_ are SPIR-V image instructions that write to an
1526image.
1527_Texel output operations_ are a set of steps that are performed on state,
1528coordinates, and texel values while processing a texel output instruction,
1529and which are common to some or all texel output instructions.
1530They include the following steps, which are performed in the listed order:
1531
1532  * <<textures-output-validation,Validation operations>>
1533  ** <<textures-format-validation,Format validation>>
1534  ** <<textures-type-validation,Type validation>>
1535  ** <<textures-output-coordinate-validation,Coordinate validation>>
1536  ** <<textures-output-sparse-validation,Sparse validation>>
1537  * <<textures-output-format-conversion,Texel output format conversion>>
1538
1539
1540[[textures-output-validation]]
1541=== Texel Output Validation Operations
1542
1543_Texel output validation operations_ inspect instruction/image state or
1544coordinates, and in certain circumstances cause the write to have no effect.
1545There are a series of validations that the texel undergoes.
1546
1547
1548[[textures-format-validation]]
1549==== Texel Format Validation
1550
1551If the image format of the code:OpTypeImage is not
1552<<spirvenv-image-formats,compatible>> with the sname:VkImageView's
1553pname:format, the write causes the contents of the image's memory to become
1554undefined:.
1555
1556
1557[[textures-type-validation]]
1558==== Texel Type Validation
1559
1560If the code:Sampled code:Type of the code:OpTypeImage does not match the
1561<<spirv-type,SPIR-V Type>>, the write causes the value of the texel to
1562become undefined:.
1563For integer types, if the <<spirvenv-image-signedness,signedness of the
1564access>> does not match the signedness of the accessed resource, the write
1565causes the value of the texel to become undefined:.
1566
1567
1568[[textures-output-coordinate-validation]]
1569=== Integer Texel Coordinate Validation
1570
1571The integer texel coordinates are validated according to the same rules as
1572for texel input <<textures-integer-coordinate-validation,coordinate
1573validation>>.
1574
1575If the texel fails integer texel coordinate validation, then the write has
1576no effect.
1577
1578
1579[[textures-output-sparse-validation]]
1580=== Sparse Texel Operation
1581
1582If the texel attempts to write to an unbound region of a sparse image, the
1583texel is a sparse unbound texel.
1584In such a case, if the
1585slink:VkPhysicalDeviceSparseProperties::pname:residencyNonResidentStrict
1586property is ename:VK_TRUE, the sparse unbound texel write has no effect.
1587If pname:residencyNonResidentStrict is ename:VK_FALSE, the write may: have a
1588side effect that becomes visible to other accesses to unbound texels in any
1589resource, but will not be visible to any device memory allocated by the
1590application.
1591
1592
1593[[textures-output-format-conversion]]
1594=== Texel Output Format Conversion
1595
1596If the image format is sRGB, a linear to sRGB conversion is applied to the
1597R, G, and B components as described in the "`sRGB EOTF`" section of the
1598<<data-format,Khronos Data Format Specification>>.
1599The A component, if present, is unchanged.
1600
1601Texels then undergo a format conversion from the floating point, signed, or
1602unsigned integer type of the texel data to the elink:VkFormat of the image
1603view.
1604If the number of components in the texel data is larger than the number of
1605components in the format, additional components are discarded.
1606
1607Each component is converted based on its type and size (as defined in the
1608<<formats-definition,Format Definition>> section for each elink:VkFormat).
1609Floating-point outputs are converted as described in
1610<<fundamentals-fp-conversion,Floating-Point Format Conversions>> and
1611<<fundamentals-fixedconv,Fixed-Point Data Conversion>>.
1612Integer outputs are converted such that their value is preserved.
1613The converted value of any integer that cannot be represented in the target
1614format is undefined:.
1615
1616
1617[[textures-normalized-operations]]
1618== Normalized Texel Coordinate Operations
1619
1620If the image sampler instruction provides normalized texel coordinates, some
1621of the following operations are performed.
1622
1623
1624[[textures-projection]]
1625=== Projection Operation
1626
1627For code:Proj image operations, the normalized texel coordinates
1628[eq]#(s,t,r,q,a)# and (if present) the [eq]#D~ref~# coordinate are
1629transformed as follows:
1630
1631[latexmath]
1632+++++++++++++++++++
1633\begin{aligned}
1634s       & = \frac{s}{q},       & \text{for 1D, 2D, or 3D image} \\
1635\\
1636t       & = \frac{t}{q},       & \text{for 2D or 3D image} \\
1637\\
1638r       & = \frac{r}{q},       & \text{for 3D image} \\
1639\\
1640D_{\textit{ref}} & = \frac{D_{\textit{ref}}}{q}, & \text{if provided}
1641\end{aligned}
1642+++++++++++++++++++
1643
1644
1645[[textures-derivative-image-operations]]
1646=== Derivative Image Operations
1647
1648Derivatives are used for LOD selection.
1649These derivatives are either implicit (in an code:ImplicitLod image
1650instruction in a fragment shader) or explicit (provided explicitly by shader
1651to the image instruction in any shader).
1652
1653For implicit derivatives image instructions, the derivatives of texel
1654coordinates are calculated in the same manner as
1655<<shaders-derivative-operations, derivative operations>>.
1656That is:
1657
1658[latexmath]
1659+++++++++++++++++++
1660\begin{aligned}
1661\partial{s}/\partial{x} & = dPdx(s), & \partial{s}/\partial{y} & = dPdy(s), & \text{for 1D, 2D, Cube, or 3D image} \\
1662\partial{t}/\partial{x} & = dPdx(t), & \partial{t}/\partial{y} & = dPdy(t), & \text{for 2D, Cube, or 3D image} \\
1663\partial{r}/\partial{x} & = dPdx(r), & \partial{r}/\partial{y} & = dPdy(r), & \text{for Cube or 3D image}
1664\end{aligned}
1665+++++++++++++++++++
1666
1667Partial derivatives not defined above for certain image dimensionalities are
1668set to zero.
1669
1670For explicit LOD image instructions, if the optional: SPIR-V operand
1671code:Grad is provided, then the operand values are used for the derivatives.
1672The number of components present in each derivative for a given image
1673dimensionality matches the number of partial derivatives computed above.
1674
1675If the optional: SPIR-V operand code:Lod is provided, then derivatives are
1676set to zero, the cube map derivative transformation is skipped, and the
1677scale factor operation is skipped.
1678Instead, the floating point scalar coordinate is directly assigned to
1679[eq]#{lambda}~base~# as described in <<textures-level-of-detail-operation,
1680LOD Operation>>.
1681
1682ifdef::VK_VERSION_1_2,VK_EXT_descriptor_indexing[]
1683If the image or sampler object used by an implicit derivative image
1684instruction is not uniform across the quad and
1685<<limits-quadDivergentImplicitLod, pname:quadDivergentImplicitLod>> is not
1686supported, then the derivative and LOD values are undefined:.
1687Implicit derivatives are well-defined when the image and sampler and control
1688flow are uniform across the quad, even if they diverge between different
1689quads.
1690
1691If <<limits-quadDivergentImplicitLod, pname:quadDivergentImplicitLod>> is
1692supported, then derivatives and implicit LOD values are well-defined even if
1693the image or sampler object are not uniform within a quad.
1694The derivatives are computed as specified above, and the implicit LOD
1695calculation proceeds for each shader invocation using its respective image
1696and sampler object.
1697endif::VK_VERSION_1_2,VK_EXT_descriptor_indexing[]
1698
1699
1700=== Cube Map Face Selection and Transformations
1701
1702For cube map image instructions, the [eq]#(s,t,r)# coordinates are treated
1703as a direction vector [eq]#(r~x~,r~y~,r~z~)#.
1704The direction vector is used to select a cube map face.
1705The direction vector is transformed to a per-face texel coordinate system
1706[eq]#(s~face~,t~face~)#, The direction vector is also used to transform the
1707derivatives to per-face derivatives.
1708
1709
1710=== Cube Map Face Selection
1711
1712The direction vector selects one of the cube map's faces based on the
1713largest magnitude coordinate direction (the major axis direction).
1714Since two or more coordinates can: have identical magnitude, the
1715implementation must: have rules to disambiguate this situation.
1716
1717The rules should: have as the first rule that [eq]#r~z~# wins over
1718[eq]#r~y~# and [eq]#r~x~#, and the second rule that [eq]#r~y~# wins over
1719[eq]#r~x~#.
1720An implementation may: choose other rules, but the rules must: be
1721deterministic and depend only on [eq]#(r~x~,r~y~,r~z~)#.
1722
1723The layer number (corresponding to a cube map face), the coordinate
1724selections for [eq]#s~c~#, [eq]#t~c~#, [eq]#r~c~#, and the selection of
1725derivatives, are determined by the major axis direction as specified in the
1726following two tables.
1727
1728.Cube map face and coordinate selection
1729[width="75%",frame="all",options="header"]
1730|====
1731| Major Axis Direction | Layer Number | Cube Map Face | [eq]#s~c~#  | [eq]#t~c~#  | [eq]#r~c~#
1732| [eq]#+r~x~#          | [eq]#0#      | Positive X    | [eq]#-r~z~# | [eq]#-r~y~# | [eq]#r~x~#
1733| [eq]#-r~x~#          | [eq]#1#      | Negative X    | [eq]#+r~z~# | [eq]#-r~y~# | [eq]#r~x~#
1734| [eq]#+r~y~#          | [eq]#2#      | Positive Y    | [eq]#+r~x~# | [eq]#+r~z~# | [eq]#r~y~#
1735| [eq]#-r~y~#          | [eq]#3#      | Negative Y    | [eq]#+r~x~# | [eq]#-r~z~# | [eq]#r~y~#
1736| [eq]#+r~z~#          | [eq]#4#      | Positive Z    | [eq]#+r~x~# | [eq]#-r~y~# | [eq]#r~z~#
1737| [eq]#-r~z~#          | [eq]#5#      | Negative Z    | [eq]#-r~x~# | [eq]#-r~y~# | [eq]#r~z~#
1738|====
1739
1740
1741.Cube map derivative selection
1742[width="75%",frame="all",options="header"]
1743|====
1744| 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#
1745
1746| [eq]#+r~x~#
1747| [eq]#-{partial}r~z~ / {partial}x# | [eq]#-{partial}r~z~ / {partial}y#
1748| [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1749| [eq]#+{partial}r~x~ / {partial}x# | [eq]#+{partial}r~x~ / {partial}y#
1750
1751| [eq]#-r~x~#
1752| [eq]#+{partial}r~z~ / {partial}x# | [eq]#+{partial}r~z~ / {partial}y#
1753| [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1754| [eq]#-{partial}r~x~ / {partial}x# | [eq]#-{partial}r~x~ / {partial}y#
1755
1756| [eq]#+r~y~#
1757| [eq]#+{partial}r~x~ / {partial}x# | [eq]#+{partial}r~x~ / {partial}y#
1758| [eq]#+{partial}r~z~ / {partial}x# | [eq]#+{partial}r~z~ / {partial}y#
1759| [eq]#+{partial}r~y~ / {partial}x# | [eq]#+{partial}r~y~ / {partial}y#
1760
1761| [eq]#-r~y~#
1762| [eq]#+{partial}r~x~ / {partial}x# | [eq]#+{partial}r~x~ / {partial}y#
1763| [eq]#-{partial}r~z~ / {partial}x# | [eq]#-{partial}r~z~ / {partial}y#
1764| [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1765
1766| [eq]#+r~z~#
1767| [eq]#+{partial}r~x~ / {partial}x# | [eq]#+{partial}r~x~ / {partial}y#
1768| [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1769| [eq]#+{partial}r~z~ / {partial}x# | [eq]#+{partial}r~z~ / {partial}y#
1770
1771| [eq]#-r~z~#
1772| [eq]#-{partial}r~x~ / {partial}x# | [eq]#-{partial}r~x~ / {partial}y#
1773| [eq]#-{partial}r~y~ / {partial}x# | [eq]#-{partial}r~y~ / {partial}y#
1774| [eq]#-{partial}r~z~ / {partial}x# | [eq]#-{partial}r~z~ / {partial}y#
1775|====
1776
1777
1778=== Cube Map Coordinate Transformation
1779
1780[latexmath]
1781++++++++++++++++++++++++
1782\begin{aligned}
1783s_{\textit{face}} & =
1784    \frac{1}{2} \times \frac{s_c}{|r_c|} + \frac{1}{2} \\
1785t_{\textit{face}} & =
1786    \frac{1}{2} \times \frac{t_c}{|r_c|} + \frac{1}{2} \\
1787\end{aligned}
1788++++++++++++++++++++++++
1789
1790
1791=== Cube Map Derivative Transformation
1792
1793[latexmath]
1794++++++++++++++++++++++++
1795\begin{aligned}
1796\frac{\partial{s_{\textit{face}}}}{\partial{x}} &=
1797    \frac{\partial}{\partial{x}} \left ( \frac{1}{2} \times \frac{s_{c}}{|r_{c}|}
1798    + \frac{1}{2}\right ) \\
1799\frac{\partial{s_{\textit{face}}}}{\partial{x}} &=
1800    \frac{1}{2} \times \frac{\partial}{\partial{x}}
1801    \left ( \frac{s_{c}}{|r_{c}|}  \right ) \\
1802\frac{\partial{s_{\textit{face}}}}{\partial{x}} &=
1803    \frac{1}{2} \times
1804    \left (
1805    \frac{
1806      |r_{c}| \times \partial{s_c}/\partial{x}
1807      -s_c \times {\partial{r_{c}}}/{\partial{x}}}
1808    {\left ( r_{c} \right )^2}
1809    \right )
1810\end{aligned}
1811++++++++++++++++++++++++
1812
1813[latexmath]
1814++++++++++++++++++++++++
1815\begin{aligned}
1816\frac{\partial{s_{\textit{face}}}}{\partial{y}} &=
1817    \frac{1}{2} \times
1818    \left (
1819    \frac{
1820      |r_{c}| \times \partial{s_c}/\partial{y}
1821      -s_c \times {\partial{r_{c}}}/{\partial{y}}}
1822    {\left ( r_{c} \right )^2}
1823    \right )\\
1824\frac{\partial{t_{\textit{face}}}}{\partial{x}} &=
1825    \frac{1}{2} \times
1826    \left (
1827    \frac{
1828      |r_{c}| \times \partial{t_c}/\partial{x}
1829      -t_c \times {\partial{r_{c}}}/{\partial{x}}}
1830    {\left ( r_{c} \right )^2}
1831    \right ) \\
1832\frac{\partial{t_{\textit{face}}}}{\partial{y}} &=
1833    \frac{1}{2} \times
1834    \left (
1835    \frac{
1836       |r_{c}| \times \partial{t_c}/\partial{y}
1837      -t_c \times {\partial{r_{c}}}/{\partial{y}}}
1838    {\left ( r_{c} \right )^2}
1839    \right )
1840\end{aligned}
1841++++++++++++++++++++++++
1842
1843ifdef::editing-notes[]
1844[NOTE]
1845.editing-note
1846====
1847(Bill) Note that we never revisited ARB_texture_cubemap after we introduced
1848dependent texture fetches (ARB_fragment_program and ARB_fragment_shader).
1849
1850The derivatives of [eq]#s~face~# and [eq]#t~face~# are only valid for
1851non-dependent texture fetches (pre OpenGL 2.0).
1852====
1853endif::editing-notes[]
1854
1855
1856[[textures-lod-and-scale-factor]]
1857=== Scale Factor Operation, LOD Operation and Image Level(s) Selection
1858
1859LOD selection can: be either explicit (provided explicitly by the image
1860instruction) or implicit (determined from a scale factor calculated from the
1861derivatives).
1862The LOD must: be computed with pname:mipmapPrecisionBits of accuracy.
1863
1864
1865[[textures-scale-factor]]
1866==== Scale Factor Operation
1867
1868The magnitude of the derivatives are calculated by:
1869
1870  {empty}:: [eq]#m~ux~ = {vert}{partial}s/{partial}x{vert} {times} w~base~#
1871  {empty}:: [eq]#m~vx~ = {vert}{partial}t/{partial}x{vert} {times} h~base~#
1872  {empty}:: [eq]#m~wx~ = {vert}{partial}r/{partial}x{vert} {times} d~base~#
1873
1874  {empty}:: [eq]#m~uy~ = {vert}{partial}s/{partial}y{vert} {times} w~base~#
1875  {empty}:: [eq]#m~vy~ = {vert}{partial}t/{partial}y{vert} {times} h~base~#
1876  {empty}:: [eq]#m~wy~ = {vert}{partial}r/{partial}y{vert} {times} d~base~#
1877
1878
1879where:
1880
1881  {empty}:: [eq]#{partial}t/{partial}x = {partial}t/{partial}y = 0# (for 1D
1882            images)
1883  {empty}:: [eq]#{partial}r/{partial}x = {partial}r/{partial}y = 0# (for 1D,
1884            2D or Cube images)
1885
1886and:
1887
1888  {empty}:: [eq]#w~base~ = image.w#
1889  {empty}:: [eq]#h~base~ = image.h#
1890  {empty}:: [eq]#d~base~ = image.d#
1891
1892(for the pname:baseMipLevel, from the image descriptor).
1893
1894ifdef::VK_NV_corner_sampled_image[]
1895
1896For corner-sampled images, the [eq]#w~base~#, [eq]#h~base~#, and
1897[eq]#d~base~# are instead:
1898
1899  {empty}:: [eq]#w~base~ = image.w - 1#
1900  {empty}:: [eq]#h~base~ = image.h - 1#
1901  {empty}:: [eq]#d~base~ = image.d - 1#
1902
1903endif::VK_NV_corner_sampled_image[]
1904
1905A point sampled in screen space has an elliptical footprint in texture
1906space.
1907The minimum and maximum scale factors [eq]#({rho}~min~, {rho}~max~)# should:
1908be the minor and major axes of this ellipse.
1909
1910The _scale factors_ [eq]#{rho}~x~# and [eq]#{rho}~y~#, calculated from the
1911magnitude of the derivatives in x and y, are used to compute the minimum and
1912maximum scale factors.
1913
1914[eq]#{rho}~x~# and [eq]#{rho}~y~# may: be approximated with functions
1915[eq]#f~x~# and [eq]#f~y~#, subject to the following constraints:
1916
1917[latexmath]
1918++++++++++++++++++++++++
1919\begin{aligned}
1920& f_x \text{\ is\ continuous\ and\ monotonically\ increasing\ in\ each\ of\ }
1921    m_{ux},
1922    m_{vx}, \text{\ and\ }
1923    m_{wx} \\
1924& f_y \text{\ is\ continuous\ and\ monotonically\ increasing\ in\ each\ of\ }
1925    m_{uy},
1926    m_{vy}, \text{\ and\ }
1927    m_{wy}
1928\end{aligned}
1929++++++++++++++++++++++++
1930
1931[latexmath]
1932++++++++++++++++++++++++
1933\begin{aligned}
1934\max(|m_{ux}|, |m_{vx}|, |m_{wx}|) \leq f_{x}
1935\leq \sqrt{2} (|m_{ux}| + |m_{vx}| + |m_{wx}|) \\
1936\max(|m_{uy}|, |m_{vy}|, |m_{wy}|) \leq f_{y}
1937\leq \sqrt{2} (|m_{uy}| + |m_{vy}| + |m_{wy}|)
1938\end{aligned}
1939++++++++++++++++++++++++
1940
1941
1942ifdef::editing-notes[]
1943[NOTE]
1944.editing-note
1945====
1946(Bill) For reviewers only - anticipating questions.
1947
1948We only support implicit derivatives for normalized texel coordinates.
1949
1950So we are documenting the derivatives in s,t,r (normalized texel
1951coordinates) rather than u,v,w (unnormalized texel coordinates) as in OpenGL
1952and OpenGL ES specifications.
1953(I know, u,v,w is the way it has been documented since OpenGL V1.0.)
1954
1955Also there is no reason to have conditional application of [eq]#w~base~,
1956h~base~, d~base~# for rectangle textures either, since they do not support
1957implicit derivatives.
1958====
1959endif::editing-notes[]
1960
1961
1962The minimum and maximum scale factors [eq]#({rho}~min~,{rho}~max~)# are
1963determined by:
1964
1965  {empty}:: [eq]#{rho}~max~ = max({rho}~x~, {rho}~y~)#
1966  {empty}:: [eq]#{rho}~min~ = min({rho}~x~, {rho}~y~)#
1967
1968The ratio of anisotropy is determined by:
1969
1970  {empty}:: [eq]#{eta} = min({rho}~max~/{rho}~min~, max~Aniso~)#
1971
1972where:
1973
1974  {empty}:: [eq]#sampler.max~Aniso~ = pname:maxAnisotropy# (from sampler
1975            descriptor)
1976  {empty}:: [eq]#limits.max~Aniso~ = pname:maxSamplerAnisotropy# (from
1977            physical device limits)
1978  {empty}:: [eq]#max~Aniso~ = min(sampler.max~Aniso~, limits.max~Aniso~)#
1979
1980If [eq]#{rho}~max~ = {rho}~min~ = 0#, then all the partial derivatives are
1981zero, the fragment's footprint in texel space is a point, and [eq]#{eta}#
1982should: be treated as 1.
1983If [eq]#{rho}~max~ {neq} 0# and [eq]#{rho}~min~ = 0# then all partial
1984derivatives along one axis are zero, the fragment's footprint in texel space
1985is a line segment, and [eq]#{eta}# should: be treated as [eq]#max~Aniso~#.
1986However, anytime the footprint is small in texel space the implementation
1987may: use a smaller value of [eq]#{eta}#, even when [eq]#{rho}~min~# is zero
1988or close to zero.
1989If either slink:VkPhysicalDeviceFeatures::pname:samplerAnisotropy or
1990slink:VkSamplerCreateInfo::pname:anisotropyEnable are ename:VK_FALSE,
1991[eq]#max~Aniso~# is set to 1.
1992
1993If [eq]#{eta} = 1#, sampling is isotropic.
1994If [eq]#{eta} > 1#, sampling is anisotropic.
1995
1996The sampling rate ([eq]#N#) is derived as:
1997
1998  {empty}:: [eq]#N = {lceil}{eta}{rceil}#
1999
2000An implementation may: round [eq]#N# up to the nearest supported sampling
2001rate.
2002An implementation may: use the value of [eq]#N# as an approximation of
2003[eq]#{eta}#.
2004
2005
2006[[textures-level-of-detail-operation]]
2007==== LOD Operation
2008
2009The LOD parameter [eq]#{lambda}# is computed as follows:
2010
2011[latexmath]
2012++++++++++++++++++++++++
2013\begin{aligned}
2014\lambda_{base}(x,y) & =
2015  \begin{cases}
2016    shaderOp.Lod                                    & \text{(from optional SPIR-V operand)} \\
2017    \log_2 \left ( \frac{\rho_{max}}{\eta} \right ) & \text{otherwise}
2018  \end{cases} \\
2019\lambda'(x,y)       & = \lambda_{base} + \mathbin{clamp}(sampler.bias + shaderOp.bias,-maxSamplerLodBias,maxSamplerLodBias) \\
2020\lambda             & =
2021  \begin{cases}
2022    lod_{max}, & \lambda' > lod_{max} \\
2023    \lambda',  & lod_{min} \leq \lambda' \leq lod_{max} \\
2024    lod_{min}, & \lambda' < lod_{min} \\
2025    \textit{undefined}, & lod_{min} > lod_{max}
2026  \end{cases}
2027\end{aligned}
2028++++++++++++++++++++++++
2029
2030where:
2031
2032[latexmath]
2033++++++++++++++++++++++++
2034\begin{aligned}
2035sampler.bias       & = mipLodBias & \text{(from sampler descriptor)} \\
2036shaderOp.bias      & =
2037  \begin{cases}
2038    Bias & \text{(from optional SPIR-V operand)} \\
2039    0    & \text{otherwise}
2040  \end{cases} \\
2041sampler.lod_{min}  & = minLod & \text{(from sampler descriptor)} \\
2042shaderOp.lod_{min} & =
2043  \begin{cases}
2044    MinLod & \text{(from optional SPIR-V operand)} \\
2045    0      & \text{otherwise}
2046  \end{cases} \\
2047\\
2048lod_{min}          & = \max(sampler.lod_{min}, shaderOp.lod_{min}) \\
2049lod_{max}          & = maxLod & \text{(from sampler descriptor)}
2050\end{aligned}
2051++++++++++++++++++++++++
2052
2053and [eq]#maxSamplerLodBias# is the value of the slink:VkPhysicalDeviceLimits
2054feature <<limits-maxSamplerLodBias, pname:maxSamplerLodBias>>.
2055
2056
2057[[textures-image-level-selection]]
2058==== Image Level(s) Selection
2059
2060The image level(s) [eq]#d#, [eq]#d~hi~#, and [eq]#d~lo~# which texels are
2061read from are determined by an image-level parameter [eq]#d~l~#, which is
2062computed based on the LOD parameter, as follows:
2063
2064[latexmath]
2065++++++++++++++++++++++++
2066\begin{aligned}
2067d_{l} =
2068  \begin{cases}
2069    nearest(d'),  & \text{mipmapMode is VK\_SAMPLER\_MIPMAP\_MODE\_NEAREST} \\
2070    d',           & \text{otherwise}
2071  \end{cases}
2072\end{aligned}
2073++++++++++++++++++++++++
2074
2075where:
2076
2077[latexmath]
2078++++++++++++++++++++++++
2079\begin{aligned}
2080ifdef::VK_EXT_image_view_min_lod[]
2081d' = max(level_{base} + \text{clamp}(\lambda, 0, q), minLod_{imageView})
2082endif::VK_EXT_image_view_min_lod[]
2083ifndef::VK_EXT_image_view_min_lod[]
2084d' = level_{base} + \text{clamp}(\lambda, 0, q)
2085endif::VK_EXT_image_view_min_lod[]
2086
2087\end{aligned}
2088++++++++++++++++++++++++
2089
2090[latexmath]
2091++++++++++++++++++++++++
2092\begin{aligned}
2093nearest(d') & =
2094  \begin{cases}
2095    \left \lceil d' + 0.5\right \rceil - 1, &
2096        \text{preferred} \\
2097    \left \lfloor d' + 0.5\right \rfloor,   &
2098        \text{alternative}
2099  \end{cases}
2100\end{aligned}
2101++++++++++++++++++++++++
2102
2103and:
2104
2105ifdef::VK_EXT_image_view_min_lod[]
2106[latexmath]
2107++++++++++++++++++++++++
2108\begin{aligned}
2109minLod_{imageView} & =
2110  \begin{cases}
2111    minLodFloat_{imageView}, & \text{preferred} \\
2112    minLodInteger_{imageView}, & \text{alternative}
2113  \end{cases} \\
2114level_{base}       & = baseMipLevel \\
2115q                  & = levelCount - 1
2116\end{aligned}
2117++++++++++++++++++++++++
2118endif::VK_EXT_image_view_min_lod[]
2119ifndef::VK_EXT_image_view_min_lod[]
2120[latexmath]
2121++++++++++++++++++++++++
2122\begin{aligned}
2123level_{base}       & = baseMipLevel \\
2124q                  & = levelCount - 1
2125\end{aligned}
2126++++++++++++++++++++++++
2127endif::VK_EXT_image_view_min_lod[]
2128
2129pname:baseMipLevel and pname:levelCount are taken from the
2130pname:subresourceRange of the image view.
2131
2132ifdef::VK_EXT_image_view_min_lod[]
2133[eq]#minLod~imageView~# must: be less or equal to [eq]#level~base~ + q#.
2134endif::VK_EXT_image_view_min_lod[]
2135
2136If the sampler's pname:mipmapMode is ename:VK_SAMPLER_MIPMAP_MODE_NEAREST,
2137then the level selected is [eq]#d = d~l~#.
2138
2139If the sampler's pname:mipmapMode is ename:VK_SAMPLER_MIPMAP_MODE_LINEAR,
2140two neighboring levels are selected:
2141
2142[latexmath]
2143++++++++++++++++++++++++
2144\begin{aligned}
2145d_{hi} & = \left\lfloor d_{l} \right\rfloor \\
2146d_{lo} & = min( d_{hi} + 1, level_{base} + q ) \\
2147\delta & = d_{l} - d_{hi}
2148\end{aligned}
2149++++++++++++++++++++++++
2150
2151[eq]#{delta}# is the fractional value, quantized to the number of
2152<<limits-mipmapPrecisionBits, mipmap precision bits>>, used for
2153<<textures-texel-filtering, linear filtering>> between levels.
2154
2155
2156[[textures-normalized-to-unnormalized]]
2157=== (s,t,r,q,a) to (u,v,w,a) Transformation
2158
2159The normalized texel coordinates are scaled by the image level dimensions
2160and the array layer is selected.
2161
2162This transformation is performed once for each level used in
2163<<textures-texel-filtering,filtering>> (either [eq]#d#, or [eq]#d~hi~# and
2164[eq]#d~lo~#).
2165
2166[latexmath]
2167++++++++++++++++++++++++
2168\begin{aligned}
2169u(x,y) & = s(x,y) \times width_{scale} + \Delta_i\\
2170v(x,y) & =
2171  \begin{cases}
2172    0                         & \text{for 1D images} \\
2173    t(x,y) \times height_{scale} + \Delta_j & \text{otherwise}
2174  \end{cases} \\
2175w(x,y) & =
2176  \begin{cases}
2177    0                         & \text{for 2D or Cube images} \\
2178    r(x,y) \times depth_{scale}  + \Delta_k & \text{otherwise}
2179  \end{cases} \\
2180\\
2181a(x,y) & =
2182  \begin{cases}
2183    a(x,y)                    & \text{for array images} \\
2184    0                         & \text{otherwise}
2185  \end{cases}
2186\end{aligned}
2187++++++++++++++++++++++++
2188
2189where:
2190
2191  {empty}:: [eq]#width~scale~ = width~level~#
2192  {empty}:: [eq]#height~scale~ = height~level~#
2193  {empty}:: [eq]#depth~scale~ = depth~level~#
2194
2195ifdef::VK_NV_corner_sampled_image[]
2196for conventional images, and:
2197
2198  {empty}:: [eq]#width~scale~ = width~level~ - 1#
2199  {empty}:: [eq]#height~scale~ = height~level~ - 1#
2200  {empty}:: [eq]#depth~scale~ = depth~level~ - 1#
2201
2202for corner-sampled images.
2203endif::VK_NV_corner_sampled_image[]
2204
2205and where [eq]#({DeltaUpper}~i~, {DeltaUpper}~j~, {DeltaUpper}~k~)# are
2206taken from the image instruction if it includes a code:ConstOffset or
2207code:Offset operand, otherwise they are taken to be zero.
2208
2209
2210Operations then proceed to Unnormalized Texel Coordinate Operations.
2211
2212
2213== Unnormalized Texel Coordinate Operations
2214
2215
2216[[textures-unnormalized-to-integer]]
2217=== (u,v,w,a) to (i,j,k,l,n) Transformation and Array Layer Selection
2218
2219The unnormalized texel coordinates are transformed to integer texel
2220coordinates relative to the selected mipmap level.
2221
2222The layer index [eq]#l# is computed as:
2223
2224  {empty}:: [eq]#l = clamp(RNE(a), 0, pname:layerCount - 1) {plus}
2225            pname:baseArrayLayer#
2226
2227where pname:layerCount is the number of layers in the image subresource
2228range of the image view, pname:baseArrayLayer is the first layer from the
2229subresource range, and where:
2230
2231[latexmath]
2232++++++++++++++++++++++++
2233\begin{aligned}
2234\mathbin{RNE}(a) & =
2235  \begin{cases}
2236    \mathbin{roundTiesToEven}(a)                  & \text{preferred, from IEEE Std 754-2008 Floating-Point Arithmetic} \\
2237    \left \lfloor a + 0.5 \right \rfloor & \text{alternative}
2238  \end{cases}
2239\end{aligned}
2240++++++++++++++++++++++++
2241
2242The sample index [eq]#n# is assigned the value 0.
2243
2244Nearest filtering (ename:VK_FILTER_NEAREST) computes the integer texel
2245coordinates that the unnormalized coordinates lie within:
2246
2247[latexmath]
2248++++++++++++++++++++++++
2249\begin{aligned}
2250i &= \left\lfloor u + shift \right\rfloor \\
2251j &= \left\lfloor v + shift \right\rfloor \\
2252k &= \left\lfloor w + shift \right\rfloor
2253\end{aligned}
2254++++++++++++++++++++++++
2255where:
2256
2257  {empty}:: [eq]#shift = 0.0#
2258
2259ifdef::VK_NV_corner_sampled_image[]
2260for conventional images, and:
2261
2262  {empty}:: [eq]#shift = 0.5#
2263
2264for corner-sampled images.
2265endif::VK_NV_corner_sampled_image[]
2266
2267Linear filtering (ename:VK_FILTER_LINEAR) computes a set of neighboring
2268coordinates which bound the unnormalized coordinates.
2269The integer texel coordinates are combinations of [eq]#i~0~# or [eq]#i~1~#,
2270[eq]#j~0~# or [eq]#j~1~#, [eq]#k~0~# or [eq]#k~1~#, as well as weights
2271[eq]#{alpha}, {beta}#, and [eq]#{gamma}#.
2272
2273[latexmath]
2274++++++++++++++++++++++++
2275\begin{aligned}
2276i_0 &= \left\lfloor u - shift \right\rfloor \\
2277i_1 &= i_0 + 1 \\
2278j_0 &= \left\lfloor v - shift \right\rfloor \\
2279j_1 &= j_0 + 1 \\
2280k_0 &= \left\lfloor w - shift \right\rfloor \\
2281k_1 &= k_0 + 1
2282\end{aligned}
2283++++++++++++++++++++++++
2284
2285[latexmath]
2286++++++++++++++++++++++++
2287\begin{aligned}
2288\alpha &= \mathbin{frac}\left(u - shift\right)  \\[1em]
2289\beta &= \mathbin{frac}\left(v - shift\right)  \\[1em]
2290\gamma &= \mathbin{frac}\left(w - shift\right)
2291\end{aligned}
2292++++++++++++++++++++++++
2293
2294where:
2295
2296  {empty}:: [eq]#shift = 0.5#
2297
2298ifdef::VK_NV_corner_sampled_image[]
2299for conventional images, and:
2300
2301  {empty}:: [eq]#shift = 0.0#
2302
2303for corner-sampled images,
2304endif::VK_NV_corner_sampled_image[]
2305and where:
2306
2307[latexmath]
2308++++++++++++++++++++++++
2309\mathbin{frac}(x) = x -  \left\lfloor x \right\rfloor
2310++++++++++++++++++++++++
2311where the number of fraction bits retained is specified by
2312sname:VkPhysicalDeviceLimits::pname:subTexelPrecisionBits.
2313
2314ifdef::VK_IMG_filter_cubic,VK_EXT_filter_cubic[]
2315Cubic filtering (ename:VK_FILTER_CUBIC_EXT) computes a set of neighboring
2316coordinates which bound the unnormalized coordinates.
2317The integer texel coordinates are combinations of [eq]#i~0~#, [eq]#i~1~#,
2318[eq]#i~2~# or [eq]#i~3~#, [eq]#j~0~#, [eq]#j~1~#, [eq]#j~2~# or [eq]#j~3~#,
2319ifndef::VK_EXT_filter_cubic[]
2320as well as weights [eq]#{alpha}# and [eq]#{beta}#.
2321endif::VK_EXT_filter_cubic[]
2322ifdef::VK_EXT_filter_cubic[]
2323[eq]#k~0~#, [eq]#k~1~#, [eq]#k~2~# or [eq]#k~3~#, as well as weights
2324[eq]#{alpha}#, [eq]#{beta}#, and [eq]#{gamma}#.
2325endif::VK_EXT_filter_cubic[]
2326
2327ifndef::VK_EXT_filter_cubic[]
2328[latexmath]
2329++++++++++++++++++++++++
2330\begin{aligned}
2331i_{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]
2332j_{0}  & = {\left \lfloor {v - \frac{3}{2}} \right \rfloor} & j_{1} & = j_{0} + 1 & j_{2} & = j_{1} + 1 & j_{3} & = j_{2} + 1
2333\end{aligned}
2334++++++++++++++++++++++++
2335
2336[latexmath]
2337++++++++++++++++++++++++
2338\begin{aligned}
2339alpha &= \mathbin{frac}\left(u - \frac{1}{2}\right)  \\[1em]
2340\beta &= \mathbin{frac}\left(v - \frac{1}{2}\right)
2341\end{aligned}
2342++++++++++++++++++++++++
2343
2344endif::VK_EXT_filter_cubic[]
2345
2346ifdef::VK_EXT_filter_cubic[]
2347[latexmath]
2348++++++++++++++++++++++++
2349\begin{aligned}
2350i_{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]
2351j_{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]
2352k_{0}  & = {\left \lfloor {w - \frac{3}{2}} \right \rfloor} & k_{1} & = k_{0} + 1 & k_{2} & = k_{1} + 1 & k_{3} & = k_{2} + 1
2353\end{aligned}
2354++++++++++++++++++++++++
2355
2356[latexmath]
2357++++++++++++++++++++++++
2358\begin{aligned}
2359\alpha &= \mathbin{frac}\left(u - \frac{1}{2}\right)  \\[1em]
2360\beta &= \mathbin{frac}\left(v - \frac{1}{2}\right)  \\[1em]
2361\gamma &= \mathbin{frac}\left(w - \frac{1}{2}\right)
2362\end{aligned}
2363++++++++++++++++++++++++
2364
2365endif::VK_EXT_filter_cubic[]
2366
2367where:
2368
2369[latexmath]
2370++++++++++++++++++++++++
2371\mathbin{frac}(x) = x -  \left\lfloor x \right\rfloor
2372++++++++++++++++++++++++
2373
2374where the number of fraction bits retained is specified by
2375sname:VkPhysicalDeviceLimits::pname:subTexelPrecisionBits.
2376endif::VK_IMG_filter_cubic,VK_EXT_filter_cubic[]
2377
2378
2379[[textures-integer-coordinate-operations]]
2380== Integer Texel Coordinate Operations
2381
2382ifdef::VK_AMD_shader_image_load_store_lod[]
2383Integer texel coordinate operations may: supply a LOD which texels are to be
2384read from or written to using the optional SPIR-V operand code:Lod.
2385endif::VK_AMD_shader_image_load_store_lod[]
2386ifndef::VK_AMD_shader_image_load_store_lod[]
2387The code:OpImageFetch and code:OpImageFetchSparse SPIR-V instructions may:
2388supply a LOD from which texels are to be fetched using the optional SPIR-V
2389operand code:Lod.
2390Other integer-coordinate operations must: not.
2391endif::VK_AMD_shader_image_load_store_lod[]
2392If the code:Lod is provided then it must: be an integer.
2393
2394The image level selected is:
2395[latexmath]
2396++++++++++++++++++++++++
2397\begin{aligned}
2398d & = level_{base} +
2399  \begin{cases}
2400    Lod & \text{(from optional SPIR-V operand)} \\
2401    0   & \text{otherwise}
2402  \end{cases} \\
2403\end{aligned}
2404++++++++++++++++++++++++
2405
2406If [eq]#d# does not lie in the range [eq]#[pname:baseMipLevel,
2407pname:baseMipLevel {plus} pname:levelCount)#
2408ifdef::VK_EXT_image_view_min_lod[]
2409or [eq]#d# is less than minLodInteger~imageView~,
2410endif::VK_EXT_image_view_min_lod[]
2411then any values fetched are
2412ifdef::VK_EXT_robustness2[]
2413zero if the <<features-robustImageAccess2, pname:robustImageAccess2>>
2414feature is enabled, otherwise are
2415endif::VK_EXT_robustness2[]
2416undefined:, and any writes (if supported) are discarded.
2417
2418
2419[[textures-sample-operations]]
2420== Image Sample Operations
2421
2422
2423[[textures-wrapping-operation]]
2424=== Wrapping Operation
2425
2426ifdef::VK_EXT_non_seamless_cube_map[]
2427If the used sampler was created without
2428ename:VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT,
2429endif::VK_EXT_non_seamless_cube_map[]
2430code:Cube images ignore the wrap modes specified in the sampler.
2431Instead, if ename:VK_FILTER_NEAREST is used within a mip level then
2432ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE is used, and if
2433ename:VK_FILTER_LINEAR is used within a mip level then sampling at the edges
2434is performed as described earlier in the <<textures-cubemapedge,Cube map
2435edge handling>> section.
2436
2437The first integer texel coordinate i is transformed based on the
2438pname:addressModeU parameter of the sampler.
2439
2440[latexmath]
2441++++++++++++++++++++++++
2442\begin{aligned}
2443i &=
2444  \begin{cases}
2445    i \bmod size                                & \text{for repeat} \\
2446    (size - 1) - \mathbin{mirror}
2447        ((i \bmod (2 \times size)) - size)      & \text{for mirrored repeat} \\
2448    \mathbin{clamp}(i,0,size-1)                  & \text{for clamp to edge} \\
2449    \mathbin{clamp}(i,-1,size)                   & \text{for clamp to border} \\
2450    \mathbin{clamp}(\mathbin{mirror}(i),0,size-1) & \text{for mirror clamp to edge}
2451  \end{cases}
2452\end{aligned}
2453++++++++++++++++++++++++
2454
2455where:
2456
2457[latexmath]
2458++++++++++++++++++++++++
2459\begin{aligned}
2460& \mathbin{mirror}(n) =
2461  \begin{cases}
2462    n      & \text{for}\  n \geq 0 \\
2463    -(1+n) & \text{otherwise}
2464  \end{cases}
2465\end{aligned}
2466++++++++++++++++++++++++
2467
2468[eq]#j# (for 2D and Cube image) and [eq]#k# (for 3D image) are similarly
2469transformed based on the pname:addressModeV and pname:addressModeW
2470parameters of the sampler, respectively.
2471
2472
2473[[textures-gather]]
2474=== Texel Gathering
2475
2476SPIR-V instructions with code:Gather in the name return a vector derived
2477from 4 texels in the base level of the image view.
2478The rules for the ename:VK_FILTER_LINEAR minification filter are applied to
2479identify the four selected texels.
2480Each texel is then converted to an RGBA value according to
2481<<textures-conversion-to-rgba,conversion to RGBA>> and then
2482<<textures-component-swizzle,swizzled>>.
2483A four-component vector is then assembled by taking the component indicated
2484by the code:Component value in the instruction from the swizzled color value
2485of the four texels.
2486If the operation does not use the code:ConstOffsets image operand then the
2487four texels form the 2 {times} 2 rectangle used for texture filtering:
2488
2489[latexmath]
2490++++++++++++++++++++++++
2491\begin{aligned}
2492\tau[R] &= \tau_{i0j1}[level_{base}][comp] \\
2493\tau[G] &= \tau_{i1j1}[level_{base}][comp] \\
2494\tau[B] &= \tau_{i1j0}[level_{base}][comp] \\
2495\tau[A] &= \tau_{i0j0}[level_{base}][comp]
2496\end{aligned}
2497++++++++++++++++++++++++
2498
2499If the operation does use the code:ConstOffsets image operand then the
2500offsets allow a custom filter to be defined:
2501
2502[latexmath]
2503++++++++++++++++++++++++
2504\begin{aligned}
2505\tau[R] &= \tau_{i0j0 + \Delta_0}[level_{base}][comp] \\
2506\tau[G] &= \tau_{i0j0 + \Delta_1}[level_{base}][comp] \\
2507\tau[B] &= \tau_{i0j0 + \Delta_2}[level_{base}][comp] \\
2508\tau[A] &= \tau_{i0j0 + \Delta_3}[level_{base}][comp]
2509\end{aligned}
2510++++++++++++++++++++++++
2511
2512where:
2513
2514[latexmath]
2515++++++++++++++++++++++++
2516\begin{aligned}
2517\tau[level_{base}][comp] &=
2518  \begin{cases}
2519    \tau[level_{base}][R], & \text{for}\  comp = 0 \\
2520    \tau[level_{base}][G], & \text{for}\  comp = 1 \\
2521    \tau[level_{base}][B], & \text{for}\  comp = 2 \\
2522    \tau[level_{base}][A], & \text{for}\  comp = 3
2523  \end{cases}\\
2524comp & \,\text{from SPIR-V operand Component}
2525\end{aligned}
2526++++++++++++++++++++++++
2527
2528ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
2529code:OpImage*Gather must: not be used on a sampled image with
2530<<samplers-YCbCr-conversion,sampler {YCbCr} conversion>> enabled.
2531endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
2532
2533ifdef::VK_EXT_image_view_min_lod[]
2534If [eq]#level~base~ < minLodInteger~imageView~#, then any values fetched are
2535ifdef::VK_EXT_robustness2[]
2536zero if <<features-robustImageAccess2, pname:robustImageAccess2>> is
2537enabled.
2538Otherwise values are
2539endif::VK_EXT_robustness2[]
2540undefined:.
2541endif::VK_EXT_image_view_min_lod[]
2542
2543
2544[[textures-texel-filtering]]
2545=== Texel Filtering
2546
2547Texel filtering is first performed for each level (either [eq]#d# or
2548[eq]#d~hi~# and [eq]#d~lo~#).
2549
2550If [eq]#{lambda}# is less than or equal to zero, the texture is said to be
2551_magnified_, and the filter mode within a mip level is selected by the
2552pname:magFilter in the sampler.
2553If [eq]#{lambda}# is greater than zero, the texture is said to be
2554_minified_, and the filter mode within a mip level is selected by the
2555pname:minFilter in the sampler.
2556
2557
2558[[textures-texel-nearest-filtering]]
2559==== Texel Nearest Filtering
2560
2561Within a mip level, ename:VK_FILTER_NEAREST filtering selects a single value
2562using the [eq]#(i, j, k)# texel coordinates, with all texels taken from
2563layer l.
2564
2565[latexmath]
2566++++++++++++++++++++++++
2567\begin{aligned}
2568\tau[level] &=
2569  \begin{cases}
2570     \tau_{ijk}[level], & \text{for 3D image} \\
2571     \tau_{ij}[level],  & \text{for 2D or Cube image} \\
2572     \tau_{i}[level],   & \text{for 1D image}
2573   \end{cases}
2574\end{aligned}
2575++++++++++++++++++++++++
2576
2577
2578[[textures-texel-linear-filtering]]
2579==== Texel Linear Filtering
2580
2581Within a mip level, ename:VK_FILTER_LINEAR filtering combines 8 (for 3D), 4
2582(for 2D or Cube), or 2 (for 1D) texel values, together with their linear
2583weights.
2584The linear weights are derived from the fractions computed earlier:
2585
2586[latexmath]
2587
2588++++++++++++++++++++++++
2589\begin{aligned}
2590w_{i_0} &= (1-\alpha) \\
2591w_{i_1} &= (\alpha)   \\
2592w_{j_0} &= (1-\beta)  \\
2593w_{j_1} &= (\beta)    \\
2594w_{k_0} &= (1-\gamma) \\
2595w_{k_1} &= (\gamma)
2596\end{aligned}
2597++++++++++++++++++++++++
2598
2599ifndef::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2600The values of multiple texels, together with their weights, are combined
2601using a weighted average to produce a filtered value:
2602endif::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2603
2604ifdef::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2605The values of multiple texels, together with their weights, are combined to
2606produce a filtered value.
2607
2608The slink:VkSamplerReductionModeCreateInfo::pname:reductionMode can: control
2609the process by which multiple texels, together with their weights, are
2610combined to produce a filtered texture value.
2611
2612When the pname:reductionMode is set (explicitly or implicitly) to
2613ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, a weighted average is
2614computed:
2615endif::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2616
2617[latexmath]
2618++++++++++++++++++++++++
2619\begin{aligned}
2620\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} \\
2621\tau_{2D} &= \sum_{j=j_0}^{j_1}\sum_{i=i_0}^{i_1}(w_{i})(w_{j})\tau_{ij} \\
2622\tau_{1D} &= \sum_{i=i_0}^{i_1}(w_{i})\tau_{i}
2623\end{aligned}
2624++++++++++++++++++++++++
2625
2626ifdef::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2627However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN or
2628ename:VK_SAMPLER_REDUCTION_MODE_MAX, the process operates on the above set
2629of multiple texels, together with their weights, computing a component-wise
2630minimum or maximum, respectively, of the components of the set of texels
2631with non-zero weights.
2632endif::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2633
2634
2635ifdef::VK_IMG_filter_cubic,VK_EXT_filter_cubic[]
2636[[textures-texel-cubic-filtering]]
2637==== Texel Cubic Filtering
2638
2639Within a mip level, ename:VK_FILTER_CUBIC_EXT, filtering computes a weighted
2640average of
2641ifdef::VK_EXT_filter_cubic[]
264264 (for 3D),
2643endif::VK_EXT_filter_cubic[]
264416 (for 2D), or 4 (for 1D) texel values, together with their
2645ifndef::VK_QCOM_filter_cubic_weights[]
2646Catmull-Rom weights.
2647endif::VK_QCOM_filter_cubic_weights[]
2648ifdef::VK_QCOM_filter_cubic_weights[]
2649Catmull-Rom, Zero Tangent Cardinal, B-Spline, or Mitchell-Netravali weights
2650as specified by slink:VkSamplerCubicWeightsCreateInfoQCOM.
2651endif::VK_QCOM_filter_cubic_weights[]
2652
2653
2654Catmull-Rom weights
2655ifdef::VK_QCOM_filter_cubic_weights[]
2656specified by ename:VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM
2657endif::VK_QCOM_filter_cubic_weights[]
2658are derived from the fractions computed earlier.
2659
2660ifndef::VK_EXT_filter_cubic[]
2661[latexmath]
2662++++++++++++++++++++++++
2663\begin{aligned}
2664\begin{bmatrix}
2665w_{i_0}\phantom{,} w_{i_1}\phantom{,} w_{i_2}\phantom{,} w_{i_3}
2666\end{bmatrix}
2667= \frac{1}{2}
2668\begin{bmatrix}
26691 & \alpha & \alpha^2 & \alpha^3
2670\end{bmatrix}
2671\begin{bmatrix}
2672\phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2673-1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2674\phantom{-}2 & -5 &  \phantom{-}4 &  -1 \\
2675-1 &  \phantom{-}3 & -3 &  \phantom{-}1
2676\end{bmatrix}
2677\\
2678\begin{bmatrix}
2679w_{j_0}\phantom{,} w_{j_1}\phantom{,} w_{j_2}\phantom{,} w_{j_3}
2680\end{bmatrix}
2681= \frac{1}{2}
2682\begin{bmatrix}
26831 & \beta & \beta^2 & \beta^3
2684\end{bmatrix}
2685\begin{bmatrix}
2686\phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2687-1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2688\phantom{-}2 & -5 &  \phantom{-}4 &  -1 \\
2689-1 &  \phantom{-}3 & -3 &  \phantom{-}1
2690\end{bmatrix}
2691\end{aligned}
2692++++++++++++++++++++++++
2693
2694The values of multiple texels, together with their weights, are combined
2695using a weighted average to produce a filtered value:
2696
2697[latexmath]
2698++++++++++++++++++++++++
2699\begin{aligned}
2700\tau_{2D} &= \sum_{j=j_0}^{j_3}\sum_{i=i_0}^{i_3}(w_{i})(w_{j})\tau_{ij} \\
2701\tau_{1D} &= \sum_{i=i_0}^{i_3}(w_{i})\tau_{i}
2702\end{aligned}
2703++++++++++++++++++++++++
2704endif::VK_EXT_filter_cubic[]
2705
2706ifdef::VK_EXT_filter_cubic[]
2707
2708[latexmath]
2709++++++++++++++++++++++++
2710\begin{aligned}
2711\begin{bmatrix}
2712w_{i_0}\phantom{,} w_{i_1}\phantom{,} w_{i_2}\phantom{,} w_{i_3}
2713\end{bmatrix}
2714= \frac{1}{2}
2715\begin{bmatrix}
27161 & \alpha & \alpha^2 & \alpha^3
2717\end{bmatrix}
2718\begin{bmatrix}
2719\phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2720-1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2721\phantom{-}2 & -5 &  \phantom{-}4 &  -1 \\
2722-1 &  \phantom{-}3 & -3 &  \phantom{-}1
2723\end{bmatrix}
2724\\
2725\begin{bmatrix}
2726w_{j_0}\phantom{,} w_{j_1}\phantom{,} w_{j_2}\phantom{,} w_{j_3}
2727\end{bmatrix}
2728= \frac{1}{2}
2729\begin{bmatrix}
27301 & \beta & \beta^2 & \beta^3
2731\end{bmatrix}
2732\begin{bmatrix}
2733\phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2734-1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2735\phantom{-}2 & -5 &  \phantom{-}4 &  -1 \\
2736-1 &  \phantom{-}3 & -3 &  \phantom{-}1
2737\end{bmatrix}
2738\\
2739\begin{bmatrix}
2740w_{k_0}\phantom{,} w_{k_1}\phantom{,} w_{k_2}\phantom{,} w_{k_3}
2741\end{bmatrix}
2742= \frac{1}{2}
2743\begin{bmatrix}
27441 & \gamma & \gamma^2 & \gamma^3
2745\end{bmatrix}
2746\begin{bmatrix}
2747\phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2748-1 &  \phantom{-}0 &  \phantom{-}1 &  \phantom{-}0 \\
2749\phantom{-}2 & -5 &  \phantom{-}4 &  -1 \\
2750-1 &  \phantom{-}3 & -3 &  \phantom{-}1
2751\end{bmatrix}
2752\end{aligned}
2753++++++++++++++++++++++++
2754
2755ifdef::VK_QCOM_filter_cubic_weights[]
2756Zero Tangent Cardinal weights specified by
2757ename:VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM are derived from
2758the fractions computed earlier.
2759
2760[latexmath]
2761++++++++++++++++++++++++
2762\begin{aligned}
2763\begin{bmatrix}
2764w_{i_0}\phantom{,} w_{i_1}\phantom{,} w_{i_2}\phantom{,} w_{i_3}
2765\end{bmatrix}
2766= \frac{1}{2}
2767\begin{bmatrix}
27681 & \alpha & \alpha^2 & \alpha^3
2769\end{bmatrix}
2770\begin{bmatrix}
2771\phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2772-2 &  \phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 \\
2773\phantom{-}4 & -4 &  \phantom{-}2 &  -2 \\
2774-2 &  \phantom{-}2 & -2 &  \phantom{-}1
2775\end{bmatrix}
2776\\
2777\begin{bmatrix}
2778w_{j_0}\phantom{,} w_{j_1}\phantom{,} w_{j_2}\phantom{,} w_{j_3}
2779\end{bmatrix}
2780= \frac{1}{2}
2781\begin{bmatrix}
27821 & \beta & \beta^2 & \beta^3
2783\end{bmatrix}
2784\begin{bmatrix}
2785\phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2786-2 &  \phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 \\
2787\phantom{-}4 & -4 &  \phantom{-}2 &  -2 \\
2788-2 &  \phantom{-}2 & -2 &  \phantom{-}1
2789\end{bmatrix}
2790\\
2791\begin{bmatrix}
2792w_{k_0}\phantom{,} w_{k_1}\phantom{,} w_{k_2}\phantom{,} w_{k_3}
2793\end{bmatrix}
2794= \frac{1}{2}
2795\begin{bmatrix}
27961 & \gamma & \gamma^2 & \gamma^3
2797\end{bmatrix}
2798\begin{bmatrix}
2799\phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 &  \phantom{-}0 \\
2800-2 &  \phantom{-}0 &  \phantom{-}2 &  \phantom{-}0 \\
2801\phantom{-}4 & -4 &  \phantom{-}2 &  -2 \\
2802-2 &  \phantom{-}2 & -2 &  \phantom{-}1
2803\end{bmatrix}
2804\end{aligned}
2805++++++++++++++++++++++++
2806
2807B-Spline weights specified by ename:VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM
2808are derived from the fractions computed earlier.
2809
2810[latexmath]
2811++++++++++++++++++++++++
2812\begin{aligned}
2813\begin{bmatrix}
2814w_{i_0}\phantom{,} w_{i_1}\phantom{,} w_{i_2}\phantom{,} w_{i_3}
2815\end{bmatrix}
2816= \frac{1}{6}
2817\begin{bmatrix}
28181 & \alpha & \alpha^2 & \alpha^3
2819\end{bmatrix}
2820\begin{bmatrix}
2821\phantom{-}1 &  \phantom{-}4 &  \phantom{-}1 &  \phantom{-}0 \\
2822-3 &  \phantom{-}0 &  \phantom{-}3 &  \phantom{-}0 \\
2823\phantom{-}3 & -6 &  \phantom{-}3 &  \phantom{-}0 \\
2824-1 &  \phantom{-}3 & -3 &  \phantom{-}1
2825\end{bmatrix}
2826\\
2827\begin{bmatrix}
2828w_{j_0}\phantom{,} w_{j_1}\phantom{,} w_{j_2}\phantom{,} w_{j_3}
2829\end{bmatrix}
2830= \frac{1}{6}
2831\begin{bmatrix}
28321 & \beta & \beta^2 & \beta^3
2833\end{bmatrix}
2834\begin{bmatrix}
2835\phantom{-}1 &  \phantom{-}4 &  \phantom{-}1 &  \phantom{-}0 \\
2836-3 &  \phantom{-}0 &  \phantom{-}3 &  \phantom{-}0 \\
2837\phantom{-}3 & -6 &  \phantom{-}3 &  \phantom{-}0 \\
2838-1 &  \phantom{-}3 & -3 &  \phantom{-}1
2839\end{bmatrix}
2840\\
2841\begin{bmatrix}
2842w_{k_0}\phantom{,} w_{k_1}\phantom{,} w_{k_2}\phantom{,} w_{k_3}
2843\end{bmatrix}
2844= \frac{1}{6}
2845\begin{bmatrix}
28461 & \gamma & \gamma^2 & \gamma^3
2847\end{bmatrix}
2848\begin{bmatrix}
2849\phantom{-}1 &  \phantom{-}4 &  \phantom{-}1 &  \phantom{-}0 \\
2850-3 &  \phantom{-}0 &  \phantom{-}3 &  \phantom{-}0 \\
2851\phantom{-}3 & -6 &  \phantom{-}3 &  \phantom{-}0 \\
2852-1 &  \phantom{-}3 & -3 &  \phantom{-}1
2853\end{bmatrix}
2854\end{aligned}
2855++++++++++++++++++++++++
2856
2857Mitchell-Netravali weights specified by
2858ename:VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM are derived from the
2859fractions computed earlier.
2860
2861[latexmath]
2862++++++++++++++++++++++++
2863\begin{aligned}
2864\begin{bmatrix}
2865w_{i_0}\phantom{,} w_{i_1}\phantom{,} w_{i_2}\phantom{,} w_{i_3}
2866\end{bmatrix}
2867= \frac{1}{18}
2868\begin{bmatrix}
28691 & \alpha & \alpha^2 & \alpha^3
2870\end{bmatrix}
2871\begin{bmatrix}
2872\phantom{-}1 &  \phantom{-}16 &  \phantom{-}1 &  \phantom{-}0 \\
2873-9 &  \phantom{-}0 &  \phantom{-}9 &  \phantom{-}0 \\
2874\phantom{-}15 & -36 &  \phantom{-}27 &  -6 \\
2875-7 &  \phantom{-}21 & -21 &  \phantom{-}7
2876\end{bmatrix}
2877\\
2878\begin{bmatrix}
2879w_{j_0}\phantom{,} w_{j_1}\phantom{,} w_{j_2}\phantom{,} w_{j_3}
2880\end{bmatrix}
2881= \frac{1}{18}
2882\begin{bmatrix}
28831 & \beta & \beta^2 & \beta^3
2884\end{bmatrix}
2885\begin{bmatrix}
2886\phantom{-}1 &  \phantom{-}16 &  \phantom{-}1 &  \phantom{-}0 \\
2887-9 &  \phantom{-}0 &  \phantom{-}9 &  \phantom{-}0 \\
2888\phantom{-}15 & -36 &  \phantom{-}27 &  -6 \\
2889-7 &  \phantom{-}21 & -21 &  \phantom{-}7
2890\end{bmatrix}
2891\\
2892\begin{bmatrix}
2893w_{k_0}\phantom{,} w_{k_1}\phantom{,} w_{k_2}\phantom{,} w_{k_3}
2894\end{bmatrix}
2895= \frac{1}{18}
2896\begin{bmatrix}
28971 & \gamma & \gamma^2 & \gamma^3
2898\end{bmatrix}
2899\begin{bmatrix}
2900\phantom{-}1 &  \phantom{-}16 &  \phantom{-}1 &  \phantom{-}0 \\
2901-9 &  \phantom{-}0 &  \phantom{-}9 &  \phantom{-}0 \\
2902\phantom{-}15 & -36 &  \phantom{-}27 &  -6 \\
2903-7 &  \phantom{-}21 & -21 &  \phantom{-}7
2904\end{bmatrix}
2905\end{aligned}
2906++++++++++++++++++++++++
2907
2908endif::VK_QCOM_filter_cubic_weights[]
2909
2910
2911The values of multiple texels, together with their weights, are combined to
2912produce a filtered value.
2913
2914The slink:VkSamplerReductionModeCreateInfo::pname:reductionMode can: control
2915the process by which multiple texels, together with their weights, are
2916combined to produce a filtered texture value.
2917
2918When the pname:reductionMode is set (explicitly or implicitly) to
2919ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE
2920ifdef::VK_QCOM_filter_cubic_clamp[]
2921or ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM
2922endif::VK_QCOM_filter_cubic_clamp[]
2923, a weighted average is computed:
2924
2925[latexmath]
2926++++++++++++++++++++++++
2927\begin{aligned}
2928\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} \\
2929\tau_{2D} &= \sum_{j=j_0}^{j_3}\sum_{i=i_0}^{i_3}(w_{i})(w_{j})\tau_{ij} \\
2930\tau_{1D} &= \sum_{i=i_0}^{i_3}(w_{i})\tau_{i}
2931\end{aligned}
2932++++++++++++++++++++++++
2933
2934ifdef::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2935However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN or
2936ename:VK_SAMPLER_REDUCTION_MODE_MAX, the process operates on the above set
2937of multiple texels, together with their weights, computing a component-wise
2938minimum or maximum, respectively, of the components of the set of texels
2939with non-zero weights.
2940endif::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2941
2942
2943ifdef::VK_QCOM_filter_cubic_clamp[]
2944[[textures-texel-range-clamp]]
2945==== Texel Range Clamp
2946When the pname:reductionMode is set to
2947ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM, the
2948weighted average is clamped to be within the component-wise minimum and
2949maximum of the set of texels with non-zero weights.
2950endif::VK_QCOM_filter_cubic_clamp[]
2951
2952endif::VK_EXT_filter_cubic[]
2953endif::VK_IMG_filter_cubic,VK_EXT_filter_cubic[]
2954
2955
2956[[textures-texel-mipmap-filtering]]
2957==== Texel Mipmap Filtering
2958
2959ename:VK_SAMPLER_MIPMAP_MODE_NEAREST filtering returns the value of a single
2960mipmap level,
2961
2962[eq]#{tau} = {tau}[d]#.
2963
2964ename:VK_SAMPLER_MIPMAP_MODE_LINEAR filtering combines the values of
2965multiple mipmap levels ({tau}[hi] and {tau}[lo]), together with their linear
2966weights.
2967
2968The linear weights are derived from the fraction computed earlier:
2969
2970[latexmath]
2971++++++++++++++++++++++++
2972\begin{aligned}
2973w_{hi} &= (1-\delta) \\
2974w_{lo} &= (\delta)   \\
2975\end{aligned}
2976++++++++++++++++++++++++
2977
2978ifndef::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2979The values of multiple mipmap levels together with their linear weights, are
2980combined using a weighted average to produce a final filtered value:
2981endif::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2982ifdef::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2983The values of multiple mipmap levels, together with their weights, are
2984combined to produce a final filtered value.
2985
2986The slink:VkSamplerReductionModeCreateInfo::pname:reductionMode can: control
2987the process by which multiple texels, together with their weights, are
2988combined to produce a filtered texture value.
2989
2990When the pname:reductionMode is set (explicitly or implicitly) to
2991ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, a weighted average is
2992computed:
2993endif::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
2994
2995[latexmath]
2996++++++++++++++++++++++++
2997\begin{aligned}
2998\tau &= (w_{hi})\tau[hi]+(w_{lo})\tau[lo]
2999\end{aligned}
3000++++++++++++++++++++++++
3001
3002ifdef::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
3003However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN or
3004ename:VK_SAMPLER_REDUCTION_MODE_MAX, the process operates on the above
3005values, together with their weights, computing a component-wise minimum or
3006maximum, respectively, of the components of the values with non-zero
3007weights.
3008endif::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
3009
3010
3011[[textures-texel-anisotropic-filtering]]
3012==== Texel Anisotropic Filtering
3013
3014Anisotropic filtering is enabled by the pname:anisotropyEnable in the
3015sampler.
3016When enabled, the image filtering scheme accounts for a degree of
3017anisotropy.
3018
3019The particular scheme for anisotropic texture filtering is
3020implementation-dependent.
3021Implementations should: consider the pname:magFilter, pname:minFilter and
3022pname:mipmapMode of the sampler to control the specifics of the anisotropic
3023filtering scheme used.
3024In addition, implementations should: consider pname:minLod and pname:maxLod
3025of the sampler.
3026
3027[NOTE]
3028.Note
3029====
3030For historical reasons, vendor implementations of anisotropic filtering
3031interpret these sampler parameters in different ways, particularly in corner
3032cases such as pname:magFilter, pname:minFilter of ename:NEAREST or
3033pname:maxAnisotropy equal to 1.0.
3034Applications should not expect consistent behavior in such cases, and should
3035use anisotropic filtering only with parameters which are expected to give a
3036quality improvement relative to etext:LINEAR filtering.
3037
3038The following describes one particular approach to implementing anisotropic
3039filtering for the 2D Image case; implementations may: choose other methods:
3040
3041Given a pname:magFilter, pname:minFilter of ename:VK_FILTER_LINEAR and a
3042pname:mipmapMode of ename:VK_SAMPLER_MIPMAP_MODE_NEAREST:
3043
3044Instead of a single isotropic sample, N isotropic samples are sampled within
3045the image footprint of the image level [eq]#d# to approximate an anisotropic
3046filter.
3047The sum [eq]#{tau}~2Daniso~# is defined using the single isotropic
3048[eq]#{tau}~2D~(u,v)# at level [eq]#d#.
3049
3050[latexmath]
3051++++++++++++++++++++++++
3052\begin{aligned}
3053\tau_{2Daniso} & =
3054     \frac{1}{N}\sum_{i=1}^{N}
3055     {\tau_{2D}\left (
3056       u \left ( x - \frac{1}{2} + \frac{i}{N+1} , y \right ),
3057       v \left (x-\frac{1}{2}+\frac{i}{N+1}, y \right )
3058     \right )},
3059     & \text{when}\  \rho_{x} > \rho_{y} \\
3060\tau_{2Daniso} &=
3061     \frac{1}{N}\sum_{i=1}^{N}
3062     {\tau_{2D}\left (
3063        u \left ( x, y - \frac{1}{2} + \frac{i}{N+1} \right ),
3064        v \left (x,y-\frac{1}{2}+\frac{i}{N+1} \right )
3065     \right )},
3066     & \text{when}\  \rho_{y} \geq \rho_{x}
3067\end{aligned}
3068++++++++++++++++++++++++
3069
3070ifdef::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
3071When slink:VkSamplerReductionModeCreateInfo::pname:reductionMode is set to
3072ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, the above summation is
3073used.
3074However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN or
3075ename:VK_SAMPLER_REDUCTION_MODE_MAX, the process operates on the above
3076values, together with their weights, computing a component-wise minimum or
3077maximum, respectively, of the components of the values with non-zero
3078weights.
3079endif::VK_VERSION_1_2,VK_EXT_sampler_filter_minmax[]
3080====
3081
3082
3083ifdef::VK_NV_shader_image_footprint[]
3084[[textures-footprint]]
3085== Texel Footprint Evaluation
3086
3087The SPIR-V instruction code:OpImageSampleFootprintNV evaluates the set of
3088texels from a single mip level that would be accessed during a
3089<<textures-texel-filtering, texel filtering>> operation.
3090In addition to the inputs that would be accepted by an equivalent
3091code:OpImageSample* instruction, code:OpImageSampleFootprintNV accepts two
3092additional inputs.
3093The code:Granularity input is an integer identifying the size of texel
3094groups used to evaluate the footprint.
3095Each bit in the returned footprint mask corresponds to an aligned block of
3096texels whose size is given by the following table:
3097
3098.Texel footprint granularity values
3099[width="50%",options="header"]
3100|====
3101| code:Granularity  | code:Dim = 2D |  code:Dim = 3D
3102|         0         |  unsupported  |  unsupported
3103|         1         |      2x2      |     2x2x2
3104|         2         |      4x2      |  unsupported
3105|         3         |      4x4      |     4x4x2
3106|         4         |      8x4      |  unsupported
3107|         5         |      8x8      |  unsupported
3108|         6         |     16x8      |  unsupported
3109|         7         |     16x16     |  unsupported
3110|         8         |  unsupported  |  unsupported
3111|         9         |  unsupported  |  unsupported
3112|         10        |  unsupported  |    16x16x16
3113|         11        |     64x64     |    32x16x16
3114|         12        |    128x64     |    32x32x16
3115|         13        |    128x128    |    32x32x32
3116|         14        |    256x128    |    64x32x32
3117|         15        |    256x256    |  unsupported
3118|====
3119
3120The code:Coarse input is used to select between the two mip levels that may:
3121be accessed during texel filtering when using a pname:mipmapMode of
3122ename:VK_SAMPLER_MIPMAP_MODE_LINEAR.
3123When filtering between two mip levels, a code:Coarse value of code:true
3124requests the footprint in the lower-resolution mip level (higher level
3125number), while code:false requests the footprint in the higher-resolution
3126mip level.
3127If texel filtering would access only a single mip level, the footprint in
3128that level would be returned when code:Coarse is set to code:false; an empty
3129footprint would be returned when code:Coarse is set to code:true.
3130
3131The footprint for code:OpImageSampleFootprintNV is returned in a structure
3132with six members:
3133
3134  * The first member is a boolean value that is true if the texel filtering
3135    operation would access only a single mip level.
3136  * The second member is a two- or three-component integer vector holding
3137    the footprint anchor location.
3138    For two-dimensional images, the returned components are in units of
3139    eight texel groups.
3140    For three-dimensional images, the returned components are in units of
3141    four texel groups.
3142  * The third member is a two- or three-component integer vector holding a
3143    footprint offset relative to the anchor.
3144    All returned components are in units of texel groups.
3145  * The fourth member is a two-component integer vector mask, which holds a
3146    bitfield identifying the set of texel groups in an 8x8 or 4x4x4
3147    neighborhood relative to the anchor and offset.
3148  * The fifth member is an integer identifying the mip level containing the
3149    footprint identified by the anchor, offset, and mask.
3150  * The sixth member is an integer identifying the granularity of the
3151    returned footprint.
3152
3153For footprints in two-dimensional images (code:Dim2D), the mask returned by
3154code:OpImageSampleFootprintNV indicates whether each texel group in a 8x8
3155local neighborhood of texel groups would have one or more texels accessed
3156during texel filtering.
3157In the mask, the texel group with local group coordinates
3158latexmath:[(lgx,lgy)] is considered covered if and only if
3159
3160[latexmath]
3161+++++++++++++++++++
3162\begin{aligned}
31630 \neq ((mask.x + (mask.y << 32)) \text{ \& } (1 << (lgy \times 8 + lgx)))
3164\end{aligned}
3165+++++++++++++++++++
3166
3167where:
3168
3169  * latexmath:[0 \leq lgx < 8] and latexmath:[0 \leq lgy < 8]; and
3170  * latexmath:[mask] is the returned two-component mask.
3171
3172The local group with coordinates latexmath:[(lgx,lgy)] in the mask is
3173considered covered if and only if the texel filtering operation would access
3174one or more texels latexmath:[\tau_{ij}] in the returned mip level where:
3175[latexmath]
3176+++++++++++++++++++
3177\begin{aligned}
3178i0 & =
3179  \begin{cases}
3180    gran.x \times (8 \times anchor.x + lgx), & \text{if } lgx + offset.x < 8 \\
3181    gran.x \times (8 \times (anchor.x - 1) + lgx), & \text{otherwise}
3182  \end{cases} \\
3183i1 & = i0 + gran.x - 1 \\
3184j0 & =
3185  \begin{cases}
3186    gran.y \times (8 \times anchor.y + lgy), & \text{if } lgy + offset.y < 8 \\
3187    gran.y \times (8 \times (anchor.y - 1) + lgy), & otherwise
3188  \end{cases} \\
3189j1 & = j0 + gran.y - 1
3190\end{aligned}
3191+++++++++++++++++++
3192and
3193
3194  * latexmath:[i0 \leq i \leq i1] and latexmath:[j0 \leq j \leq j1];
3195  * latexmath:[gran] is a two-component vector holding the width and height
3196    of the texel group identified by the granularity;
3197  * latexmath:[anchor] is the returned two-component anchor vector; and
3198  * latexmath:[offset] is the returned two-component offset vector.
3199
3200For footprints in three-dimensional images (code:Dim3D), the mask returned
3201by code:OpImageSampleFootprintNV indicates whether each texel group in a
32024x4x4 local neighborhood of texel groups would have one or more texels
3203accessed during texel filtering.
3204In the mask, the texel group with local group coordinates
3205latexmath:[(lgx,lgy,lgz)], is considered covered if and only if:
3206[latexmath]
3207+++++++++++++++++++
3208\begin{aligned}
32090 \neq ((mask.x + (mask.y << 32)) \text{ \& } (1 << (lgz \times 16 + lgy \times 4 + lgx)))
3210\end{aligned}
3211+++++++++++++++++++
3212where:
3213
3214  * latexmath:[0 \leq lgx < 4], latexmath:[0 \leq lgy < 4], and latexmath:[0
3215    \leq lgz < 4]; and
3216  * latexmath:[mask] is the returned two-component mask.
3217
3218The local group with coordinates latexmath:[(lgx,lgy,lgz)] in the mask is
3219considered covered if and only if the texel filtering operation would access
3220one or more texels latexmath:[\tau_{ijk}] in the returned mip level where:
3221[latexmath]
3222+++++++++++++++++++
3223\begin{aligned}
3224i0 & =
3225  \begin{cases}
3226    gran.x \times (4 \times anchor.x + lgx), & \text{if } lgx + offset.x < 4 \\
3227    gran.x \times (4 \times (anchor.x - 1) + lgx), & \text{otherwise}
3228  \end{cases} \\
3229i1 & = i0 + gran.x - 1 \\
3230j0 & =
3231  \begin{cases}
3232    gran.y \times (4 \times anchor.y + lgy), & \text{if } lgy + offset.y < 4 \\
3233    gran.y \times (4 \times (anchor.y - 1) + lgy), & otherwise
3234  \end{cases} \\
3235j1 & = j0 + gran.y - 1 \\
3236k0 & =
3237  \begin{cases}
3238    gran.z \times (4 \times anchor.z + lgz), & \text{if } lgz + offset.z < 4 \\
3239    gran.z \times (4 \times (anchor.z - 1) + lgz), & otherwise
3240  \end{cases} \\
3241k1 & = k0 + gran.z - 1
3242\end{aligned}
3243+++++++++++++++++++
3244and
3245
3246  * latexmath:[i0 \leq i \leq i1], latexmath:[j0 \leq j \leq j1],
3247    latexmath:[k0 \leq k \leq k1];
3248  * latexmath:[gran] is a three-component vector holding the width, height,
3249    and depth of the texel group identified by the granularity;
3250  * latexmath:[anchor] is the returned three-component anchor vector; and
3251  * latexmath:[offset] is the returned three-component offset vector.
3252
3253If the sampler used by code:OpImageSampleFootprintNV enables anisotropic
3254texel filtering via pname:anisotropyEnable, it is possible that the set of
3255texel groups accessed in a mip level may be too large to be expressed using
3256an 8x8 or 4x4x4 mask using the granularity requested in the instruction.
3257In this case, the implementation uses a texel group larger than the
3258requested granularity.
3259When a larger texel group size is used, code:OpImageSampleFootprintNV
3260returns an integer granularity value that can: be interpreted in the same
3261manner as the granularity value provided to the instruction to determine the
3262texel group size used.
3263If anisotropic texel filtering is disabled in the sampler, or if an
3264anisotropic footprint can be represented as an 8x8 or 4x4x4 mask with the
3265requested granularity, code:OpImageSampleFootprintNV will use the requested
3266granularity as-is and return a granularity value of zero.
3267
3268code:OpImageSampleFootprintNV supports only two- and three-dimensional image
3269accesses (code:Dim2D and code:Dim3D), and the footprint returned is
3270undefined: if a sampler uses an addressing mode other than
3271ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
3272
3273endif::VK_NV_shader_image_footprint[]
3274
3275
3276ifdef::VK_QCOM_image_processing[]
3277[[textures-weightimage]]
3278== Weight Image Sampling
3279
3280The SPIR-V instruction code:OpImageWeightedSampleQCOM specifies a texture
3281sampling operation involving two images: the _sampled image_ and the _weight
3282image_.
3283It is similar to bilinear filtering except more than 2x2 texels may
3284participate in the filter and the filter weights are user-specified rather
3285than computed by fixed-function hardware.
3286The weight image view defines a 2D kernel weights used during sampling.
3287
3288The code:OpImageWeightedSampleQCOM support normalized or unnormalized texel
3289coordinates.
3290In addition to the inputs that would be accepted by an equivalent
3291code:OpImageSample* instruction, code:OpImageWeightedSampleQCOM accepts a
3292code:weight input that specifies the view of a sample weight image
3293
3294The input code:weight must: be a view of a 2D or 1D image with
3295code:miplevels equal to `1`, code:samples equal to
3296ename:VK_SAMPLE_COUNT_1_BIT, created with an identity swizzle, and created
3297with code:usage that includes ename:VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM.
3298The slink:VkImageViewSampleWeightCreateInfoQCOM specifies additional
3299parameters of the view: pname:filterCenter, pname:filterSize, and
3300pname:numPhases.
3301described in more detail below.
3302
3303The code:weight input must: be bound using a
3304<<descriptorsets-weightimage,sample weight image>> descriptor type.
3305The code:weight view defines a filtering kernel that is a region of view's
3306subresource range.
3307The kernel spans a region from integer texel coordinate [eq]#(0,0)# to
3308[eq]#(pname:filterSize.x-1, pname:filterSize.y-1)#.
3309It is valid for the view's subresource to have dimensions larger than the
3310kernel but the texels with integer coordinates greater than
3311[eq]#(pname:filterSize.width-1, pname:filterSize.height-1)# are ignored by
3312weight sampling.
3313The value returned by queries code:OpImageQuerySize,
3314code:OpImageQuerySizeLod, code:OpImageQueryLevels, and
3315code:OpImageQuerySamples return for a weight image is undefined:.
3316
3317pname:filterCenter designates an integer texel coordinate within the filter
3318kernel as being the 'center' of the kernel.
3319The center must: be in the range [eq]#(0,0)# to [eq]#(pname:filterSize.x-1,
3320pname:filterSize.y-1)#.
3321pname:numPhases describes the number of filter phases used to provide
3322sub-pixel filtering.
3323Both are described in more detail below.
3324
3325
3326[[textures-weightimage-layout]]
3327=== Weight Image Layout
3328
3329The weight image specifies filtering kernel weight values.
3330A 2D image view can be used to specify a 2D matrix of filter weights.
3331For separable filers, a 1D image view can be used to specity the horizontal
3332and vertical weights.
3333
3334
3335==== 2D Non-Separable Weight Filters
3336
3337A 2D image view defined with slink:VkImageViewSampleWeightCreateInfoQCOM
3338describes a 2D matrix [eq]#(pname:filterSize.width {times}
3339pname:filterSize.height)# of weight elements with filter's center point at
3340pname:filterCenter.
3341Note that pname:filterSize can be smaller than the view's subresource, but
3342the filter will always be located starting at integer texel coordinate
3343[eq]#(0,0)#.
3344
3345The following figure illustrates a 2D convolution filter having
3346pname:filterSize of [eq]#(4,3)# and pname:filterCenter at [eq]#(1, 1)#.
3347
3348image::{images}/weight_filter_2d.svg[align="center",title="2D Convolution Filter",opts="{imageopts}"]
3349
3350For a 2D weight filter, the phases are stored as layers of a 2D array image.
3351The width and height of the view's subresource range must: be less than or
3352equal to
3353slink:VkPhysicalDeviceImageProcessingPropertiesQCOM::pname:maxWeightFilterDimension.
3354The layers are stored in horizontal phase major order.
3355Expressed as a formula, the layer index for a each filter phase is computed
3356as:
3357
3358[source,c]
3359----
3360layerIndex(horizPhase,vertPhase,horizPhaseCount) = (vertPhase * horizPhaseCount) + horizPhase
3361----
3362
3363
3364==== 1D Separable Weight Filters
3365
3366A separable weight filter is a 2D filter that can be specified by two 1D
3367filters in the [eq]#x# and [eq]#y# directions such that their product yields
3368the 2D filter.
3369The following example shows a 2D filter and its associated separable 1D
3370horizontal and vertical filters.
3371
3372image::{images}/weight_filter_1d_separable.svg[align="center",title="Separable 2D Convolution Filter",opts="{imageopts}"]
3373
3374A 1D array image view defined with
3375slink:VkImageViewSampleWeightCreateInfoQCOM and with pname:layerCount equal
3376to '2' describes a separable weight filter.
3377The horizontal weights are specified in slice '0' and the vertical weights
3378in slice '1'.
3379The pname:filterSize and pname:filterCenter specify the size and origin of
3380the of the horizontal and vertical filters.
3381For many use cases, 1D separable filters can offer a performance advantage
3382over 2D filters.
3383
3384For a 1D separable weight filter, the phases are arranged into a 1D array
3385image with two layers.
3386The horizontal weights are stored in layer 0 and the vertical weights in
3387layer 1.
3388Within each layer of the 1D array image, the weights are arranged into
3389groups of 4, and then arranged by phase.
3390Expressed as a formula, the 1D texel offset for each weight within each
3391layer is computed as:
3392
3393[source,c]
3394----
3395// Let horizontal weights have a weightIndex of [0, filterSize.width - 1]
3396// Let vertical weights have a weightIndex of [0, filterSize.height - 1]
3397// Let phaseCount be the number of phases in either the vertical or horizontal direction.
3398
3399texelOffset(phaseIndex,weightIndex,phaseCount) = (phaseCount * 4 * (weightIndex / 4)) + (phaseIndex * 4) + (weightIndex % 4)
3400----
3401
3402
3403[[textures-weightimage-filterphases]]
3404=== Weight Sampling Phases
3405
3406When using weight image sampling, the texture coordinates may not align with
3407a texel center in the sampled image.
3408In this case, the filter weights can be adjusted based on the subpixel
3409location.
3410This is termed "`subpixel filtering`" to indicate that the origin of the
3411filter lies at a subpixel location other than the texel center.
3412Conceptually, this means that the weight filter is positioned such that
3413filter taps do not align with sampled texels exactly.
3414In such a case, modified filter weights may be needed to adjust for the
3415off-center filter taps.
3416Unlike bilinear filtering where the subpixel weights are computed by the
3417implementation, subpixel weight image sampling requires that the per-phase
3418filter weights are pre-computed by the application and stored in an array
3419where each slice of the array is a "`filter phase`".
3420The array is indexed by the implementation based on subpixel positioning.
3421Rather than a single 2D kernel of filter weights, the application provides
3422an array of kernels, one set of filter weights per phase.
3423
3424The number of phases are restricted by following requirements, which apply
3425to both separable and non-separable filters:
3426
3427  * The number of phases in the vertical direction, [eq]#phaseCount~vert~#,
3428    must: be a power of two (i.e., 1, 2, 4, etc.).
3429  * The number of phases in the horizontal direction
3430    [eq]#phaseCount~horiz~#, must: equal [eq]#phaseCount~vert~#.
3431  * The total number of phases, [eq]#phaseCount~vert~ {times}
3432    phaseCount~horiz~#, must: be less than or equal to
3433    slink:VkPhysicalDeviceImageProcessingPropertiesQCOM::pname:maxWeightFilterPhases.
3434
3435
3436[[textures-weightimage-sampler]]
3437=== Weight Sampler Parameters
3438
3439Weight sampling requires sname:VkSamplerCreateInfo pname:addressModeU and
3440pname:addressModeV must: be set to
3441ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE or
3442ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER.
3443If ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER is used, then the border
3444color must: be set to transparent black.
3445
3446
3447[[textures-weightimage-filteroperation]]
3448=== Weight Sampling Operation
3449
3450The 2D unnormalized texel coordinates latexmath:[(u,v)] are transformed by
3451latexmath:[filterCenter] to specify coordinates latexmath:[i_{0}, j_{0}].
3452
3453[latexmath]
3454++++++++++++++++++++++++
3455\begin{aligned}
3456i_{0} &= \left\lfloor u - filterCenter_{x} \right\rfloor \\[1em]
3457j_{0} &= \left\lfloor v - filterCenter_{y} \right\rfloor
3458\end{aligned}
3459++++++++++++++++++++++++
3460where latexmath:[filterCenter] is specified by
3461slink:VkImageViewSampleWeightCreateInfoQCOM::pname:filterCenter.
3462
3463
3464Two sets of neighboring integer 2D texel coordinates are generated.
3465The first set is used for selecting texels from the sampled image
3466latexmath:[\tau] and the second set used for selecting texels from the
3467weight image latexmath:[w].
3468The first set of neighboring coordinates are combinations of
3469latexmath:[i_{0}] to latexmath:[i_{filterWidth-1}] and latexmath:[j_{0}] to
3470latexmath:[j_{filterHeight-1}].
3471The second set of neighboring coordinates are combinations of
3472latexmath:[k_{0}] to latexmath:[k_{filterWidth-1}] and latexmath:[l_{0}] to
3473latexmath:[l_{filterHeight-1}].
3474The first and second sets each contain latexmath:[(filterWidth \times
3475filterHeight)] of pairs of latexmath:[(i,j)] and latexmath:[(k,l)]
3476coordinates respectively.
3477
3478[latexmath]
3479++++++++++++++++++++++++
3480\begin{aligned}
3481\{i_q\}_{q=0}^{q=filterWidth-1} \quad &= i_{0} + q  \\[1em]
3482\{j_q\}_{q=0}^{q=filterHeight-1} \quad &= j_{0} + q \\[1em]
3483\{k_q\}_{q=0}^{q=filterWidth-1} \quad &= q  \\[1em]
3484\{l_q\}_{q=0}^{q=filterHeight-1} \quad &= q
3485\end{aligned}
3486++++++++++++++++++++++++
3487
3488where latexmath:[filterWidth] and latexmath:[filterHeight] are specified by
3489slink:VkImageViewSampleWeightCreateInfoQCOM::pname:filterSize.
3490
3491Each of the generated integer coordinates latexmath:[({i_q}, {j_q})] is
3492transformed by <<textures-wrapping-operation, texture wrapping operation>>,
3493followed by <<textures-integer-coordinate-validation,integer texel
3494coordinate validation>>, If any coordinate fails coordinate validation, it
3495is a Border Texel and <<textures-texel-replacement,texel replacement>> is
3496performed.
3497
3498
3499The phase index latexmath:[\psi] is computed from the fraction bits of the
3500unnormalized 2D texel coordinates:
3501
3502[latexmath]
3503++++++++++++++++++++++++
3504\begin{aligned}
3505phaseCount_{h} = phaseCount_{v} &= \sqrt{numPhases}  \\[1em]
3506hPhase &= \left\lfloor\mathbin{frac}\left( u \right) \times phaseCount_{h} \right\rfloor  \\[1em]
3507vPhase &= \left\lfloor\mathbin{frac}\left( v \right) \times phaseCount_{v} \right\rfloor  \\[1em]
3508\psi &= \left(vPhase \times phaseCount_{h}\right) + hPhase
3509\end{aligned}
3510++++++++++++++++++++++++
3511
3512where the number of fraction bits retained is
3513latexmath:[\mathbin{log2}\left( numPhases \right)] specified by
3514slink:VkImageViewSampleWeightCreateInfoQCOM::pname:numPhases
3515
3516Each pair of texel coordinates latexmath:[(i,j)] in the first set selects a
3517single texel value latexmath:[\tau_{ij}] from the sampled image.
3518Each pair of texel coordinates latexmath:[(k,l)] in the second set, combined
3519with phaseIndex latexmath:[\psi], selects a single weight from the weight
3520image latexmath:[w(k,l,\psi)] .
3521
3522
3523[latexmath]
3524++++++++++++++++++++++++
3525\begin{aligned}
3526w(k,l,\psi) &=
3527  \begin{cases}
3528    w_{kl}[\psi]\quad\text{(}\psi\text{ as layer index)}   & \text{for 2D array view (non-separable filter) } \\
3529    weight_{h} \times weight_{v}                           & \text{for 1D array view (separable filter) } \\
3530  \end{cases}
3531\end{aligned}
3532++++++++++++++++++++++++
3533
3534If latexmath:[w] is a 2D array view, then non-separable filtering is
3535specified, and integer coordinates latexmath:[(k,l)] are used to select
3536texels from layer latexmath:[\psi] of latexmath:[(w)].
3537If latexmath:[w] is a 1D array view, then separable filtering is specified
3538and integer coordinates latexmath:[(k,l)] are transformed to
3539latexmath:[(k_{packed},l_{packed})], and used to select horizontal weight
3540latexmath:[(weight_{h})] and vertical weight latexmath:[(weight_{v})] texels
3541from layer 0 and layer 1 of latexmath:[(w)] respectively.
3542
3543[latexmath]
3544++++++++++++++++++++++++
3545\begin{aligned}
3546k_{packed} &= \left(phaseCount_{h} \times 4 \times \left\lfloor k / 4 \right\rfloor\right) + \left(hPhase \times 4\right) + \left(k \mathbin{\%} 4\right)  \\[1em]
3547l_{packed}& = \left(phaseCount_{v} \times 4 \times \left\lfloor l / 4 \right\rfloor\right) + \left(vPhase  \times 4\right) + \left(l \mathbin{\%} 4\right) \\[1em]
3548weight_{h} &= w_{k_{packed}}[0]  & \text{(horizontal weights packed in layer 0)}  \\[1em]
3549weight_{v}  &= w_{l_{packed}}[1]  & \text{(vertical weights packed in layer 1)}
3550
3551\end{aligned}
3552++++++++++++++++++++++++
3553
3554Where latexmath:[\mathbin{\%}] refers to the integer modulo operator.
3555
3556The values of multiple texels, together with their weights, are combined to
3557produce a filtered value.
3558
3559
3560[latexmath]
3561++++++++++++++++++++++++
3562\begin{aligned}
3563\tau_{weightSampling} &= \sum_{{j=j_0} \atop {l=l_0}}^{j_{blockHeight-1} \atop {l_{blockHeight-1}}}\quad \sum_{{i=i_0}\atop {k=k_0}}^{i_{blockWidth-1} \atop {k_{blockWidth-1}}}w(k,l,\psi)\tau_{ij} \\
3564\end{aligned}
3565++++++++++++++++++++++++
3566
3567When slink:VkSamplerReductionModeCreateInfo::pname:reductionMode is set to
3568ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, the above summation is
3569used.
3570However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN or
3571ename:VK_SAMPLER_REDUCTION_MODE_MAX, the process operates on the above
3572values, computing a component-wise minimum or maximum of the texels with
3573non-zero weights.
3574If the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN or
3575ename:VK_SAMPLER_REDUCTION_MODE_MAX, each latexmath:[w(k,l,\psi)] weight
3576must: be equal to 0.0 or 1.0, otherwise the undefined: values are returned.
3577
3578Finally, the operations described in
3579<<textures-conversion-to-rgba,Conversion to RGBA>> and
3580<<textures-component-swizzle,Component swizzle>> are performed and the final
3581result is returned to the shader.
3582
3583
3584[[textures-blockmatch]]
3585== Block Matching
3586
3587The SPIR-V instruction code:opImageBlockMatchSAD and
3588code:opImageBlockMatchSSD specify texture block matching operations where a
3589block or region of texels within a _target image_ is compared with a
3590same-sized region a _reference image_.
3591The instructions make use of two image views: the _target view_ and the
3592_reference view_.
3593The target view and reference view can be the same view, allowing block
3594matching of two blocks within a single image.
3595
3596Similar to an equivalent code:OpImageFetch instruction,
3597code:opImageBlockMatchSAD and code:opImageBlockMatchSAD specify a code:image
3598and an integer texel code:coordinate which which describes the bottom-left
3599texel of the target block.
3600There are three additional inputs.
3601The code:reference and code:refCoodinate specifies bottom-left texel of the
3602reference block.
3603The code:blockSize specifies the integer width and height of the target and
3604reference blocks to be compared, and must: not be greater than
3605slink:VkPhysicalDeviceImageProcessingPropertiesQCOM.code:maxBlockMatchRegion.
3606
3607ifdef::VK_QCOM_image_processing2[]
3608code:opImageBlockMatchWindowSAD and code:opImageBlockMatchWindowSAD take the
3609same input parameters as the corresponding non-window instructions.
3610The block matching comparison is performed for all pixel values within a 2D
3611window whose dimensions are specified in the sampler.
3612endif::VK_QCOM_image_processing2[]
3613
3614
3615[[textures-blockmatch-sampler]]
3616=== Block Matching Sampler Parameters
3617
3618For code:opImageBlockMatchSAD and code:opImageBlockMatchSSD, the input
3619code:sampler must: be created with code:addressModeU and code:addressModeV,
3620equal to ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, or
3621ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER with
3622ename:VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK.
3623The input code:sampler must: be created with code:unnormalizedCoordinates
3624equal to ename:VK_TRUE.
3625The input code:sampler must: be created with pname:components equal to
3626ename:VK_COMPONENT_SWIZZLE_IDENTITY.
3627
3628
3629ifdef::VK_QCOM_image_processing2[]
3630For code:opImageBlockMatchWindowSAD and code:opImageBlockMatchWindowSSD
3631instructions, the code:target sampler must: have been created with
3632slink:VkSamplerBlockMatchWindowCreateInfoQCOM in the code:pNext chain.
3633
3634For code:opImageBlockMatchWindowSAD, code:opImageBlockMatchWindowSSD,
3635code:opImageBlockMatchGatherSAD, or
3636code:opImageBlockMatchGatherSSDinstructions, the input code:sampler must: be
3637created with code:addressModeU and code:addressModeV, equal to
3638ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER with
3639ename:VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK.
3640endif::VK_QCOM_image_processing2[]
3641
3642Other sampler states are ignored.
3643
3644
3645[[textures-blockmatch-filteroperation]]
3646=== Block Matching Operation
3647
3648Block matching SPIR-V instructions code:opImageBlockMatchSAD and
3649code:opImageBlockMatchSSD specify two sets of 2D integer texel coordinates:
3650target coordinates latexmath:[(u,v)] and reference coordinates
3651latexmath:[(s,t)].
3652
3653The coordinates define the bottom-left texel of the target block
3654latexmath:[(i_{0}, j_{0})] and the reference block latexmath:[(k_{0},
3655l_{0})].
3656
3657[latexmath]
3658++++++++++++++++++++++++
3659\begin{aligned}
3660i_{0} &= u  \\[1em]
3661j_{0} &= v  \\[1em]
3662k_{0} &= s  \\[1em]
3663l_{0} &= t
3664\end{aligned}
3665++++++++++++++++++++++++
3666
3667For the target block, a set of neighboring integer texel coordinates are
3668generated.
3669The neighboring coordinates are combinations of latexmath:[i_{0}] to
3670latexmath:[i_{blockWidth-1}] and latexmath:[j_{0}] to
3671latexmath:[j_{blockHeight-1}].
3672The set is of size latexmath:[blockWidth \times blockHeight].
3673
3674[latexmath]
3675++++++++++++++++++++++++
3676\begin{aligned}
3677\{i_q\}_{q=0}^{q=blockWidth-1} \quad &= i_{0} + q  \\[1em]
3678\{j_q\}_{q=0}^{q=blockHeight-1} \quad &= j_{0} + q
3679\end{aligned}
3680++++++++++++++++++++++++
3681
3682where latexmath:[blockWidth] and latexmath:[blockHeight] is specified by the
3683code:blockSize operand.
3684
3685If any target integer texel coordinate latexmath:[(i,j)] in the set fails
3686<<textures-integer-coordinate-validation,integer texel coordinate
3687validation>>, then the texel is an invalid texel and
3688<<textures-texel-replacement,texel replacement>> is performed.
3689
3690Similarly for the reference block, a set of neighboring integer texel
3691coordinates are generated.
3692
3693[latexmath]
3694++++++++++++++++++++++++
3695\begin{aligned}
3696\{k_q\}_{q=0}^{q=blockWidth-1} \quad &= k_{0} + q  \\[1em]
3697\{l_q\}_{q=0}^{q=blockHeight-1} \quad &= l_{0} + q
3698\end{aligned}
3699++++++++++++++++++++++++
3700
3701Each reference texel coordinate latexmath:[(k,l)] in the set must: not fail
3702<<textures-integer-coordinate-validation,integer texel coordinate
3703validation>>.
3704To avoid undefined: behavior, application shader should guarantee that the
3705reference block is fully within the bounds of the reference image.
3706
3707Each pair of texel coordinates latexmath:[(i,j)] in the set selects a single
3708texel value from the target image latexmath:[\tau_{ij}].
3709Each pair of texel coordinates latexmath:[(k,l)] in the set selects a single
3710texel value from the reference image latexmath:[\upsilon_{kl}].
3711
3712The difference between target and reference texel values is summed to
3713compute a difference metric.
3714The code:opTextureBlockMatchSAD computes the sum of absolute differences.
3715
3716[latexmath]
3717++++++++++++++++++++++++
3718\begin{aligned}
3719\tau_{SAD} &= \sum_{{j=j_0} \atop {l=l_0}}^{{j_{blockHeight-1}} \atop {l_{blockHeight-1}}} \quad\sum_{{i=i_0} \atop {k=k_0}}^{{i_{blockWidth-1}} \atop {k_{blockWidth-1}}}|\upsilon_{kl}-\tau_{ij}| \\
3720\end{aligned}
3721++++++++++++++++++++++++
3722
3723The code:opImageBlockMatchSSD computes the sum of the squared differences.
3724
3725[latexmath]
3726++++++++++++++++++++++++
3727\begin{aligned}
3728\tau_{SSD} &= \sum_{{j=j_0} \atop {l=l_0}}^{{j_{blockHeight-1}} \atop {l_{blockHeight-1}}} \quad\sum_{{i=i_0} \atop {k=k_0}}^{{i_{blockWidth-1}} \atop {k_{blockWidth-1}}}|\upsilon_{kl}-\tau_{ij}|^2 \\
3729\end{aligned}
3730++++++++++++++++++++++++
3731
3732When slink:VkSamplerReductionModeCreateInfo::pname:reductionMode is set to
3733ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, the above summation is
3734used.
3735However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN or
3736ename:VK_SAMPLER_REDUCTION_MODE_MAX, the process operates on the above
3737values, computing a component-wise minimum or maximum of
3738latexmath:[|\upsilon_{kl}-\tau_{ij}|], respectively.
3739For latexmath:[\tau_{SAD}], the minimum or maximum difference is computed
3740and for latexmath:[\tau_{SSD}], the square of the minimum or maximum is
3741computed.
3742
3743Finally, the operations described in
3744<<textures-conversion-to-rgba,Conversion to RGBA>> and
3745<<textures-component-swizzle,Component swizzle>> are performed and the final
3746result is returned to the shader.
3747The component swizzle is specified by the _target image_ descriptor; any
3748swizzle specified by the _reference image_ descriptor is ignored.
3749
3750
3751ifdef::VK_QCOM_image_processing2[]
3752[[textures-blockmatchwindow-filteroperation]]
3753==== Block Matching Window Operation
3754
3755Window block matching SPIR-V instructions code:opImageBlockMatchWindowSAD
3756and code:opImageBlockMatchWindowSSD specify two sets of 2D integer texel
3757coordinates: target coordinates latexmath:[(u,v)] and reference coordinates
3758latexmath:[(s,t)].
3759The <<textures-blockmatch-filteroperation,block matching operation>> is
3760performed repeatedly, for multiple sets of target integer coordinates within
3761the specified window.
3762These instructions effectively search a region or "`window`" within the
3763target texture and identify the window coordinates where the minimum or
3764maximum error metric is found.
3765These instructions only support single component image formats.
3766
3767The target coordinates are combinations of coordinates from
3768latexmath:[(u,v)] to latexmath:[(u + windowWidth - 1, v + windowHeight - 1)]
3769where latexmath:[windowHeight] and latexmath:[windowWidth] are specified by
3770slink:VkSamplerBlockMatchWindowCreateInfoQCOM::pname:windowExtent.
3771At each each target coordinate, a
3772<<textures-blockmatch-filteroperation,block matching operation>> is
3773performed, resulting in a difference metric.
3774The the reference coordinate latexmath:[(s,t)] is fixed.
3775The block matching operation is repeated latexmath:[windowWidth \times
3776windowHeight] times.
3777
3778The resulting minimum or maximum error is returned in the R component of the
3779output.
3780The integer window coordinates latexmath:[(x,y)] are returned in the G and B
3781components of the output.
3782The A component is 0.
3783The minimum or maximum behavior is selected by
3784slink:VkSamplerBlockMatchWindowCreateInfoQCOM::pname:windowCompareMode.
3785
3786The following psuedocode describes the operation
3787code:opImageBlockMatchWindowSAD.
3788The pseudocode for code:opImageBlockMatchWindowSSD follows an identical
3789pattern.
3790
3791[source,c]
3792----
3793vec4 opImageBlockMatchGatherSAD( sampler2D target,
3794                                 uvec2 targetCoord,
3795                                 samler2D reference,
3796                                 uvec2 refCoord,
3797                                 uvec2 blocksize) {
3798    // Two parameters are sourced from the VkSampler associated with
3799    // `target`:
3800    //    compareMode  (which can be either `MIN` or `MAX`)
3801    //    uvec2 window (which defines the search window)
3802
3803    minSAD = INF;
3804    maxSAD = -INF;
3805    uvec2 minCoord;
3806    uvec2 maxCoord;
3807
3808    for (uint x=0, x<window.width; x++) {
3809        for (uint y=0; y<window.height; y++) {
3810            float SAD = textureBlockMatchSAD(target,
3811                                             targetCoord + uvec2(x, y),
3812                                             reference,
3813                                             refCoord,
3814                                             blocksize).x;
3815            if (SAD < minSAD) {
3816                minSAD = SAD;
3817                minCoord = uvec2(x,y);
3818            }
3819            if (SAD > maxSAD) {
3820                maxSAD = SAD;
3821                maxCoord = uvec2(x,y);
3822            }
3823        }
3824    }
3825    if (compareMode==MIN) {
3826        return vec4(minSAD, minCoord.x, minCoord.y, 0.0);
3827    } else {
3828        return vec4(maxSAD, maxCoord.x, maxCoord.y, 0.0);
3829    }
3830}
3831----
3832
3833
3834[[textures-blockmatchgather-filteroperation]]
3835==== Block Matching Gather Operation
3836
3837Block matching Gather SPIR-V instructions code:opImageBlockMatchGatherSAD
3838and code:opImageBlockMatchGatherSSD specify two sets of 2D integer texel
3839coordinates: target coordinates latexmath:[(u,v)] and reference coordinates
3840latexmath:[(s,t)].
3841
3842These instructions perform the <<textures-blockmatch-filteroperation,block
3843matching operation>> 4 times, using integer target coordinates
3844latexmath:[(u,v)], latexmath:[(u+1,v)], latexmath:[(u+2,v)], and
3845latexmath:[(u+3,v)].
3846The R component from each of those 4 operations is gathered and returned in
3847the R, G, B, and A components of the output respectively.
3848For each block match operation, the reference coordinate is
3849latexmath:[(s,t)].
3850For each block match operation, only the R component of the target and
3851reference images are compared.
3852The following psuedocode describes the operation opImageBlockMatchGatherSAD.
3853The pseudocode for opImageBlockMatchGatherSSD follows an identical pattern.
3854
3855[source,c]
3856----
3857vec4 opImageBlockMatchGatherSAD(sampler2D target,
3858                                uvec2 targetCoord,
3859                                samler2D reference,
3860                                uvec2 refCoord,
3861                                uvec2 blocksize) {
3862    vec4 out;
3863    for (uint x=0, x<4; x++) {
3864            float SAD = textureBlockMatchSAD(target,
3865                                             targetCoord + uvec2(x, 0),
3866                                             reference,
3867                                             refCoord,
3868                                             blocksize).x;
3869            if (x == 0) {
3870                out.x = SAD;
3871            }
3872            if (x == 1) {
3873                out.y = SAD;
3874            }
3875            if (x == 2) {
3876                out.z = SAD;
3877            }
3878            if (x == 3) {
3879                out.w = SAD;
3880            }
3881    }
3882    return out;
3883}
3884----
3885endif::VK_QCOM_image_processing2[]
3886
3887
3888[[textures-boxfilter]]
3889== Box Filter Sampling
3890
3891The SPIR-V instruction code:OpImageBoxFilterQCOM specifies texture box
3892filtering operation where a weighted average of a region of texels is
3893computed, with the weights proportional to the coverage of each of the
3894texels.
3895
3896In addition to the inputs that would be accepted by an equivalent
3897code:OpImageSample* instruction, code:OpImageBoxFilterQCOM accepts one
3898additional input, code:boxSize which specifies the width and height in
3899texels of the region to be averaged.
3900
3901The figure below shows an example of using code:OpImageBoxFilterQCOM to
3902sample from a [eq]#8 {times} 4# texel two-dimensional image, with
3903unnormalized texture coordinates [eq]#(4.125, 2.625)# and code:boxSize of
3904[eq]#(2.75, 2.25)#.
3905The filter will read 12 texel values and compute a weights based portion of
3906of each texel covered by the box.
3907
3908[[textures-box-filter-diagrams]]
3909image::{images}/vulkantexture_boxFilter.svg[align="center",title="Box Filter Sampling Example",opts="{imageopts}"]
3910
3911If code:boxSize has height and width both equal to 1.0, then this
3912instruction will behave as traditional bilinear filtering.
3913The code:boxSize parameter must: be greater than or equal to 1.0 and must:
3914not be greater than
3915slink:VkPhysicalDeviceImageProcessingPropertiesQCOM.code:maxBoxFilterBlockSize.
3916
3917
3918[[textures-boxfilter-sampler]]
3919=== Box Filter Sampler Parameters
3920
3921The input code:sampler must: be created with code:addressModeU and
3922code:addressModeV, equal to ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, or
3923ename:VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER with
3924ename:VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK.
3925
3926
3927[[textures-boxfilter-filteroperation]]
3928=== Box Filter Operation
3929
3930The 2D unnormalized texel coordinates latexmath:[(u,v)] are transformed by
3931latexmath:[boxSize] to specify integer texel coordinates latexmath:[(i_{0},
3932j_{0})] of the bottom left texel for the filter.
3933
3934[latexmath]
3935++++++++++++++++++++++++
3936\begin{aligned}
3937i_{0} &= \left\lfloor u - \frac{boxWidth}{2} \right\rfloor \\[1em]
3938j_{0} &= \left\lfloor v - \frac{boxHeight}{2} \right\rfloor
3939\end{aligned}
3940++++++++++++++++++++++++
3941
3942where latexmath:[boxWidth] and latexmath:[boxHeight] are specified by the
3943code:(x,y) components of the code:boxSize operand.
3944
3945The filter dimensions latexmath:[(filterWidth \times filterHeight)] are
3946computed from the fractional portion of the latexmath:[(u,v)] coordinates
3947and the latexmath:[boxSize].
3948
3949[latexmath]
3950++++++++++++++++++++++++
3951\begin{aligned}
3952startFracU &= \mathbin{frac}\left(u - \frac{boxWidth}{2} \right) \\[1em]
3953startFracV &= \mathbin{frac}\left(v - \frac{boxHeight}{2} \right) \\[1em]
3954endFracU &= \mathbin{frac}\left( startFracU + boxWidth \right) \\[1em]
3955endFracV &= \mathbin{frac}\left( startFracV + boxHeight \right) \\[1em]
3956filterWidth &= \left\lceil startFracU + boxWidth \right\rceil  \\[1em]
3957filterHeight &= \left\lceil startFracV + boxHeight \right\rceil
3958\end{aligned}
3959++++++++++++++++++++++++
3960
3961where the number of fraction bits retained by latexmath:[frac()] is
3962specified by sname:VkPhysicalDeviceLimits::pname:subTexelPrecisionBits.
3963
3964A set of neighboring integer texel coordinates are generated.
3965The neighboring coordinates are combinations of latexmath:[i_{0}] to
3966latexmath:[i_{filterWidth-1}] and latexmath:[j_{0}] to
3967latexmath:[j_{filterHeight-1}], with latexmath:[i_{0}, j_{0}] being the
3968top-left coordinate of this set.
3969The set is of size latexmath:[(filterWidth \times filterHeight)].
3970
3971[latexmath]
3972++++++++++++++++++++++++
3973\begin{aligned}
3974\{i_q\}_{q=0}^{q=filterWidth-1} \quad &= i_{0} + q  \\[1em]
3975\{j_q\}_{q=0}^{q=filterHeight-1} \quad &= j_{0} + q
3976\end{aligned}
3977++++++++++++++++++++++++
3978
3979Each of the generated integer coordinates latexmath:[({i_q}, {j_q})] is
3980transformed by <<textures-wrapping-operation, texture wrapping operation>>,
3981followed by <<textures-integer-coordinate-validation,integer texel
3982coordinate validation>>, If any coordinate fails coordinate validation, it
3983is a Border Texel and <<textures-texel-replacement,texel replacement>> is
3984performed.
3985
3986Horizontal weights latexmath:[horizWeight_{0}] to
3987latexmath:[horizWeight_{boxWidth-1}] and vertical weights
3988latexmath:[vertWeight_{0}] to latexmath:[vertWeight_{boxHeight-1}] are
3989computed.
3990Texels that are fully covered by the box will have a horizontal and vertical
3991weight of 1.
3992Texels partially covered by the box will have will have a reduced weights
3993proportional to the coverage.
3994
3995[latexmath]
3996++++++++++++++++++++++++
3997\begin{aligned}
3998horizWeight_{i} &=
3999  \begin{cases}
4000    \left(1-startFracU \right),         & \text{for }  (i == 0) \\
4001    \left(endFracU \right),             & \text{for }  (i == filterWidth-1) \text{ and } (endFracU != 0) \\
4002    \left(1\right),                     & \text{otherwise} \\
4003  \end{cases}
4004\end{aligned}
4005++++++++++++++++++++++++
4006
4007[latexmath]
4008++++++++++++++++++++++++
4009\begin{aligned}
4010vertWeight_{j} &=
4011  \begin{cases}
4012    \left(1-startFracV \right),         & \text{for } (j == 0)            \\
4013    \left(endFracV \right),             & \text{for } (j == filterHeight-1) \text{ and } (endFracV !=0)   \\
4014     \left(1\right),                    & \text{otherwise}  \\
4015  \end{cases}
4016\end{aligned}
4017++++++++++++++++++++++++
4018
4019
4020The values of multiple texels, together with their horizontal and vertical
4021weights, are combined to produce a box filtered value.
4022
4023[latexmath]
4024++++++++++++++++++++++++
4025\begin{aligned}
4026\tau_{boxFilter} &= \frac{1}{boxHeight \times boxWidth} \sum_{j=j_0}^{j_{filterHeight-1}}\quad\sum_{i=i_0}^{i_{filterWidth-1}}(horizWeight_i)(vertWeight_j)\tau_{ij} \\
4027\end{aligned}
4028++++++++++++++++++++++++
4029
4030When slink:VkSamplerReductionModeCreateInfo::pname:reductionMode is set to
4031ename:VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, the above summation is
4032used.
4033However, if the reduction mode is ename:VK_SAMPLER_REDUCTION_MODE_MIN or
4034ename:VK_SAMPLER_REDUCTION_MODE_MAX, the process operates on the above
4035values, computing a component-wise minimum or maximum of the texels.
4036
4037endif::VK_QCOM_image_processing[]
4038
4039
4040[[textures-instructions]]
4041== Image Operation Steps
4042
4043Each step described in this chapter is performed by a subset of the image
4044instructions:
4045
4046  * Texel Input Validation Operations, Format Conversion, Texel Replacement,
4047    Conversion to RGBA, and Component Swizzle: Performed by all instructions
4048    except code:OpImageWrite.
4049  * Depth Comparison: Performed by code:OpImage*Dref instructions.
4050  * All Texel output operations: Performed by code:OpImageWrite.
4051  * Projection: Performed by all code:OpImage*Proj instructions.
4052  * Derivative Image Operations, Cube Map Operations, Scale Factor
4053    Operation, LOD Operation and Image Level(s) Selection, and Texel
4054    Anisotropic Filtering: Performed by all code:OpImageSample* and
4055    code:OpImageSparseSample* instructions.
4056  * (s,t,r,q,a) to (u,v,w,a) Transformation, Wrapping, and (u,v,w,a) to
4057    (i,j,k,l,n) Transformation And Array Layer Selection: Performed by all
4058    code:OpImageSample, code:OpImageSparseSample, and code:OpImage*Gather
4059    instructions.
4060  * Texel Gathering: Performed by code:OpImage*Gather instructions.
4061ifdef::VK_NV_shader_image_footprint[]
4062  * Texel Footprint Evaluation: Performed by code:OpImageSampleFootprint
4063    instructions.
4064endif::VK_NV_shader_image_footprint[]
4065  * Texel Filtering: Performed by all code:OpImageSample* and
4066    code:OpImageSparseSample* instructions.
4067  * Sparse Residency: Performed by all code:OpImageSparse* instructions.
4068ifdef::VK_QCOM_image_processing[]
4069  * (s,t,r,q,a) to (u,v,w,a) Transformation, Wrapping, and Weight Image
4070    Sampling: Performed by code:OpImageWeightedSample* instructions.
4071  * (s,t,r,q,a) to (u,v,w,a) Transformation, Wrapping, and Block Matching:
4072    Performed by code:opImageBlockMatch* instructions.
4073  * (s,t,r,q,a) to (u,v,w,a) Transformation, Wrapping, and Box Filter
4074    Sampling: Performed by code:OpImageBoxFilter* instructions.
4075endif::VK_QCOM_image_processing[]
4076
4077
4078[[textures-queries]]
4079== Image Query Instructions
4080
4081
4082=== Image Property Queries
4083
4084code:OpImageQuerySize, code:OpImageQuerySizeLod, code:OpImageQueryLevels,
4085and code:OpImageQuerySamples query properties of the image descriptor that
4086would be accessed by a shader image operation.
4087ifdef::VK_EXT_robustness2[]
4088They return 0 if the bound descriptor is a null descriptor.
4089endif::VK_EXT_robustness2[]
4090
4091code:OpImageQuerySizeLod returns the size of the image level identified by
4092the code:Level code:of code:Detail operand.
4093If that level does not exist in the image,
4094ifdef::VK_EXT_robustness2[and the descriptor is not null,]
4095then the value returned is undefined:.
4096
4097
4098=== Lod Query
4099
4100code:OpImageQueryLod returns the Lod parameters that would be used in an
4101image operation with the given image and coordinates.
4102ifdef::VK_EXT_robustness2[]
4103If the descriptor that would be accessed is a null descriptor then
4104[eq]#(0,0)# is returned.
4105endif::VK_EXT_robustness2[]
4106ifdef::VK_EXT_robustness2[Otherwise, the]
4107ifndef::VK_EXT_robustness2[The]
4108steps described in this chapter are performed as if for
4109code:OpImageSampleImplicitLod, up to <<textures-lod-and-scale-factor>>.
4110The return value is the vector [eq]#({lambda}', d~l~)#.
4111These values may: be subject to implementation-specific maxima and minima
4112for very large, out-of-range values.
4113