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