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