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