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