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