1// Copyright 2018-2023 The Khronos Group Inc.
2//
3// SPDX-License-Identifier: CC-BY-4.0
4
5[[fragmentdensitymapops]]
6= Fragment Density Map Operations
7
8
9== Fragment Density Map Operations Overview
10
11When a fragment is generated in a render pass that has a fragment density
12map attachment, its area is determined by the properties of the local
13framebuffer region that the fragment occupies.
14The framebuffer is divided into a uniform grid of these local regions, and
15their fragment area property is derived from the density map with the
16following operations:
17
18  * <<fragmentdensitymap-fetch-density-value,Fetch density value>>
19  ** <<fragmentdensitymap-component-swizzle,Component swizzle>>
20  ** <<fragmentdensitymap-component-mapping,Component mapping>>
21  * <<fragmentdensitymap-conversion-to-fragment-area,Fragment area
22    conversion>>
23  ** <<fragmentdensitymap-fragment-area-filter,Fragment area filter>>
24  ** <<fragmentdensitymap-fragment-area-clamp,Fragment area clamp>>
25
26
27[[fragmentdensitymap-fetch-density-value]]
28== Fetch Density Value
29
30ifndef::VK_QCOM_fragment_density_map_offset[]
31Each local framebuffer region at center coordinate [eq]#(x,y)# fetches a
32texel from the fragment density map at integer coordinates:
33
34  {empty}:: latexmath:[i =
35            \left\lfloor{\frac{x}{fragmentDensityTexelSize_{width}}}\right\rfloor]
36  {empty}:: latexmath:[j =
37            \left\lfloor{\frac{y}{fragmentDensityTexelSize_{height}}}\right\rfloor]
38endif::VK_QCOM_fragment_density_map_offset[]
39
40ifdef::VK_QCOM_fragment_density_map_offset[]
41Each local framebuffer region at center coordinate [eq]#(x,y)# fetches a
42texel from the fragment density map.
43
44First, the local framebuffer region center coordinate [eq]#(x,y)# is offset
45by the value specified in
46slink:VkSubpassFragmentDensityMapOffsetEndInfoQCOM.
47If no offset is specified, then the default offset [eq]#(0,0)# is used.
48The offsetted coordinate [eq]#(x',y')# is computed as follows:
49
50[latexmath]
51[latexmath]
52++++++++++++++++++++++++
53\begin{aligned}
54x' &= \mathbin{clamp}(x + pFragmentDensityOffsets[layer]_{x}, 0, framebuffer_{width} - 1)   \\
55y' &= \mathbin{clamp}(y + pFragmentDensityOffsets[layer]_{y}, 0, framebuffer_{height} - 1)  \\
56\end{aligned}
57++++++++++++++++++++++++
58
59The offsetted coordinate [eq]#(x',y')# fetches a texel from the fragment
60density map at integer coordinates:
61
62  {empty}:: latexmath:[i =
63            \left\lfloor{\frac{x'}{fragmentDensityTexelSize_{width}}}\right\rfloor]
64  {empty}:: latexmath:[j =
65            \left\lfloor{\frac{y'}{fragmentDensityTexelSize_{height}}}\right\rfloor]
66endif::VK_QCOM_fragment_density_map_offset[]
67
68Where the size of each region in the framebuffer is:
69
70  {empty}:: latexmath:[fragmentDensityTexelSize'_{width} =
71            {2^{\lceil{\log_2(\frac{framebuffer_{width}}{fragmentDensityMap_{width}})}\rceil}}]
72  {empty}:: latexmath:[fragmentDensityTexelSize'_{height} =
73            {2^{\lceil{\log_2(\frac{framebuffer_{height}}{fragmentDensityMap_{height}})}\rceil}}]
74
75This region is subject to the limits in
76sname:VkPhysicalDeviceFragmentDensityMapPropertiesEXT and therefore the
77final region size is clamped:
78
79  {empty}:: latexmath:[fragmentDensityTexelSize_{width} =
80            \mathbin{clamp}(fragmentDensityTexelSize'_{width},minFragmentDensityTexelSize_{width},maxFragmentDensityTexelSize_{width})]
81  {empty}:: latexmath:[fragmentDensityTexelSize_{height} =
82            \mathbin{clamp}(fragmentDensityTexelSize'_{height},minFragmentDensityTexelSize_{height},maxFragmentDensityTexelSize_{height})]
83
84When multiview is enabled for the render pass and the fragment density map
85attachment view was created with pname:layerCount greater than `1`, the
86layer used for offsets and for fetching from the fragment density map is:
87
88  {empty}:: latexmath:[layer = baseArrayLayer + ViewIndex]
89
90Otherwise:
91
92  {empty}:: latexmath:[layer = baseArrayLayer]
93
94The texel fetched from the density map at [eq]#(i,j,layer)# is next
95converted to density with the following operations.
96
97
98[[fragmentdensitymap-component-swizzle]]
99=== Component Swizzle
100
101The pname:components member of slink:VkImageViewCreateInfo is applied to the
102fetched texel as defined in <<textures-component-swizzle,Image component
103swizzle>>.
104
105
106[[fragmentdensitymap-component-mapping]]
107=== Component Mapping
108
109The swizzled texel's components are mapped to a density value:
110
111  {empty}:: latexmath:[densityValue_{xy} = (C'_{r},C'_{g})]
112
113
114[[fragmentdensitymap-conversion-to-fragment-area]]
115== Fragment Area Conversion
116
117Fragment area for the framebuffer region is undefined: if the density
118fetched is not a normalized floating-point value greater than `0.0`.
119Otherwise, the fetched fragment area for that region is derived as:
120
121  {empty}:: latexmath:[fragmentArea_{wh} = \frac{1.0}{densityValue_{xy}}]
122
123
124[[fragmentdensitymap-fragment-area-filter]]
125===  Fragment Area Filter
126
127Optionally, the implementation may: fetch additional density map texels in
128an implementation defined window around [eq]#(i,j)#.
129The texels follow the standard conversion steps up to and including
130<<fragmentdensitymap-conversion-to-fragment-area,fragment area conversion>>.
131
132A single fetched fragment area for the framebuffer region is chosen by the
133implementation and must: have an area between the _min_ and _max_ areas of
134the fetched set.
135
136
137[[fragmentdensitymap-fragment-area-clamp]]
138=== Fragment Area Clamp
139
140The implementation may: clamp the fetched fragment area to one that it
141supports.
142The clamped fragment area must: have a size less than or equal to the
143original fetched value.
144Implementations may: vary the supported set of fragment areas per
145framebuffer region.
146Fragment area [eq]#(1,1)# must: always be in the supported set.
147
148[NOTE]
149.Note
150====
151For example, if the fetched fragment area is [eq]#(1,4)# but the
152implementation only supports areas of [eq]#{(1,1),(2,2)}#, it could choose
153to clamp the area to [eq]#(2,2)# since it has the same size as [eq]#(1,4)#.
154While this would produce fragments that have lower quality strictly in the
155x-axis, the overall density is maintained.
156====
157
158The clamped fragment area is assigned to the corresponding framebuffer
159region.
160