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