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