Author: The Khronos® Vulkan Working Group

# Vulkan® 1.4.350 - A Specification (with all registered extensions)

The Khronos® Vulkan Working Group
version 1.4.350, 2026-05-14 02:53:14Z
from git branch: makepkg commit: 81b1d516cbf42f04a3c7f781977c499945b5e5dc

Loading… please wait.

Search:

## 21. Fragment Density Map Operations

### 21.1. Fragment Density Map Operations Overview

When a fragment is generated in a render pass that has a fragment density map attachment, its area is determined by the properties of the local framebuffer region that the fragment occupies. The framebuffer is divided into a uniform grid of these local regions, and their fragment area property is derived from the density map with the following operations:

- Fetch density value

  - Component swizzle

  - Component mapping

- Fragment area conversion

  - Fragment area filter

  - Fragment area clamp

### 21.2. Fetch Density Value

Each local framebuffer region at center coordinate (x,y) reads a texel from the fragment density map.

First, the local framebuffer region center coordinate (x,y) is offset by the value specified in VkRenderPassFragmentDensityMapOffsetEndInfoEXT. If no offset is specified, then the default offset (0,0) is used. The offset coordinate (x',y') is computed as follows:

x′y′​=x−pF r a g mentDensit y O ff sets[l a yer]x​=y−pF r a g mentDensit y O ff sets[l a yer]y​​

Note | The offset is relative to the fragment density map, so it is subtracted from the framebuffer coordinates to make the adjustment relative to the framebuffer. In other words, applying a positive offset in the x component will shift the fragment density map to the right relative to the framebuffer. This means the framebuffer coordinates need to undergo a shift to the left.

The offset fragment coordinate (x',y') reads a texel from the fragment density map at image coordinates (x,y,0,layer,0,0), where (x,y) are calculated as:

  x=c l amp(⌊f r a g mentDensit y T exe lS i z e w idth​x′​⌋,0, f r a g mentDensit y M ap w idth​−1)

  y=c l amp(⌊f r a g mentDensit y T exe lS i z e hei g ht​y′​⌋,0, f r a g mentDensit y M ap hei g ht​−1)

Where the size of each region in the framebuffer is:

  f r a g mentDensit y T exe lS i z e w idth′​=2⌈lo g 2​(⌊f r a g mentDensit y M ap w idth​f r amebu ff e r w idth​​⌋)⌉

  f r a g mentDensit y T exe lS i z e hei g ht′​=2⌈lo g 2​(⌊f r a g mentDensit y M ap hei g ht​f r amebu ff e r hei g ht​​⌋)⌉

Note | The original spec did not include the floor in the equation above. Implementations have shipped with and without the floor. Given that the earliest implementations shipped with the floor, the spec now reflects that as most content was written with this behavior. All implementations exposing support for version 3 or greater of the extension must implement with the floor included.

If using vkCmdBeginRendering, then f r amebu ff e r w idth​ and f r amebu ff e r hei g ht​ are defined as:

  f r amebu ff e r w idth​=rend er Area O ff set x​pl usrend er Area E xtent w idth​

  f r amebu ff e r hei g ht​=rend er Area O ff set y​pl usrend er Area E xtent hei g ht​

using VkRenderingInfo::`renderArea`.

This region is subject to the limits in `VkPhysicalDeviceFragmentDensityMapPropertiesEXT` and therefore the final region size is clamped:

  f r a g mentDensit y T exe lS i z e w idth​=c l amp(f r a g mentDensit y T exe lS i z e w idth′​,min F r a g mentDensit y T exe lS i z e w idth​,max F r a g mentDensit y T exe lS i z e w idth​)

  f r a g mentDensit y T exe lS i z e hei g ht​=c l amp(f r a g mentDensit y T exe lS i z e hei g ht′​,min F r a g mentDensit y T exe lS i z e hei g ht​,max F r a g mentDensit y T exe lS i z e hei g ht​)

When multiview is enabled for the render pass and the fragment density map attachment view was created with `layerCount` greater than `1`, the layer used for offsets and for fetching from the fragment density map is:

  l a yer=baseA rr a y La yer+Vie w I ndex

Otherwise, if the render pass was created with VK_RENDER_PASS_CREATE_PER_LAYER_FRAGMENT_DENSITY_BIT_VALVE specified, or the dynamic render pass was begun with VK_RENDERING_PER_LAYER_FRAGMENT_DENSITY_BIT_VALVE specified, then the layer used is:

  l a yer=baseA rr a y La yer+La yer

Otherwise:

  l a yer=baseA rr a y La yer

The texel fetched from the density map at (x,y,0,layer,0,0) is next converted to density with the following operations.

#### 21.2.1. Component Swizzle

The `components` member of VkImageViewCreateInfo is applied to the fetched texel as defined in Image component swizzle.

#### 21.2.2. Component Mapping

The swizzled texel’s components are mapped to a density value:

  densit y Va l ue x y​=(C r′​,C g′​)

### 21.3. Fragment Area Conversion

Fragment area for the framebuffer region is undefined if the density fetched is not a normalized floating-point value greater than `0.0`. Otherwise, the fetched fragment area for that region is derived as:

  f r a g mentArea w h​=densit y Va l ue x y​1.0​

#### 21.3.1. Fragment Area Filter

Optionally, the implementation may fetch additional density map texels in an implementation defined window around (i,j). The texels follow the standard conversion steps up to and including fragment area conversion.

A single fetched fragment area for the framebuffer region is chosen by the implementation and must have an area between the min and max areas of the fetched set.

#### 21.3.2. Fragment Area Clamp

The implementation may clamp the fetched fragment area to one that it supports. The clamped fragment area must have a size less than or equal to the original fetched value. Implementations may vary the supported set of fragment areas per framebuffer region. Fragment area (1,1) must always be in the supported set.

Note | For example, if the fetched fragment area is (1,4) but the implementation only supports areas of {(1,1),(2,2)}, it could choose to clamp the area to (2,2) since it has the same size as (1,4). While this would produce fragments that have lower quality strictly in the x-axis, the overall density is maintained.

The clamped fragment area is assigned to the corresponding framebuffer region.