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 | δ~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 | δ~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