yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Jay KwakSwap the term StdLib with Core-Module or Standard-Module in documents (#5414)a508b264e

master
9.7 KiB205 linesraw

Texture Footprint Queries

Slang supports querying the footprint of a texture sampling operation: the texels that would be accessed when performing that operation. This feature is supported on Vulkan via the GL_NV_shader_texture_footprint extension, and on D3D12 via the NvFootprint* functions exposed by NVAPI.

Background

There are many GPU rendering techniques that involve generating a texture (e.g., by rendering to it) and then sampling from that texture in a 3D rendering pass, such that it is difficult to predict a priori which parts of the texture will be accessed, or not. As one example, consider rendering a shadow map that will be accessed when shading a g-buffer. Depending on the geometry that was rendered into the g-buffer, and the occlusion that might exist, some parts of the shadow map might not be needed at all.

In principle, an application could use a compute pass on the g-buffer to compute, for each pixel, the part of the shadow-map texture that it will access - its footprint. The application could then aggregate these footprints into a stencil mask or other data structure that could be used to optimize the rendering pass that generates the shadow map.

Unfortunately, it is almost impossible for applications to accurately and reliably predict the texel data that particular sampling operations will require, once non-trivial texture filtering modes are considered. Sampling operations support a wide variety of state that affects the lookup and filtering of texels. For example:

  • When bilinear filtering is enabled, a sampling operation typically accesses the four texels closest to the sampling location and blends them.

  • When trilinear filtering is enabled, a sampling operation may access texels at two different mip levels.

  • When anisotropic filtering is enabled, a sampling operation may take up to N taps (where N is the maximum supported degree of anisotropy), each of which may itself access a neighborhood of texels to produce a filtered value for that tap.

  • When sampling a cube map, a sampling operation may straddle the "seam" between two or even three cube faces.

Texture footprint queries are intended to solve this problem by providing application developers with a primitive that can query the footprint of a texture sampling operation using the exact same sampler state and texture coordinates that will be used when sampling the texture later.

Slang Shader API

Rather than exactly mirror the Vulkan GLSL extension or the NVAPI functions, the Slang core module provides a single common interface that can map to either of those implementations.

Basics

A typical 2D texture sampling operation is performed using the Sample() method on Texture2D:

Texture2D<float4> texture = ...;
SamplerState sampler = ...;
float2 coords = ...;

// Sample a 2D texture
float4 color = texture.Sample(
    sampler, coords);

To query the footprint that would be accessed by this operation, we can use an operation like:

uint granularity = ...;
TextureFootprint2D footprint = texture.queryFootprintCoarse(granularity,
    sampler, coords);

Note that the same arguments used to call Sample above are here passed to queryFootprint in the exact same order. The returned footprint encodes a conservative footprint of the texels that would be accessed by the equivalent Sample operation above.

Texture footprints are encoded in terms of blocks of texels, and the size of those blocks determined the granularity of the footprint. The granularity argument to queryFootprintCoarse above indicates the granularity of blocks that the application requests.

In cases where a filtering operation might access two mip levels - one coarse and one fine - a footprint query only returns information about one of the two levels. The application selects between these options by calling either queryFootprintCoarse or queryFootprintFine.

Variations

A wide range of footprint queries are provided, corresponding to various cases of texture sampling operations with different parameters. For 2D textures, the following functions are supported:

TextureFootprint2D Texture2D.queryFootprintCoarse(
    uint granularity, SamplerState sampler, float2 coords);
TextureFootprint2D Texture2D.queryFootprintFine(
    uint granularity, SamplerState sampler, float2 coords);
TextureFootprint2D Texture2D.queryFootprintCoarseBias(
    uint granularity, SamplerState sampler, float2 coords,
    float lodBias);
TextureFootprint2D Texture2D.queryFootprintFineBias(
    uint granularity, SamplerState sampler, float2 coords,
    float lodBias);
TextureFootprint2D Texture2D.queryFootprintCoarseLevel(
    uint granularity, SamplerState sampler, float2 coords,
    float lod);
TextureFootprint2D Texture2D.queryFootprintFineLevel(
    uint granularity, SamplerState sampler, float2 coords,
    float lod);
TextureFootprint2D Texture2D.queryFootprintCoarseGrad(
    uint granularity, SamplerState sampler, float2 coords,
    float2 dx, float2 dy);
TextureFootprint2D Texture2D.queryFootprintFineGrad(
    uint granularity, SamplerState sampler, float2 coords,
    float2 dx, float2 dy);

// Vulkan-only:
TextureFootprint2D Texture2D.queryFootprintCoarseClamp(
    uint granularity, SamplerState sampler, float2 coords,
    float lodClamp);
TextureFootprint2D Texture2D.queryFootprintFineClamp(
    uint granularity, SamplerState sampler, float2 coords,
    float lodClamp);
TextureFootprint2D Texture2D.queryFootprintCoarseBiasClamp(
    uint granularity, SamplerState sampler, float2 coords,
    float lodBias,
    float lodClamp);
TextureFootprint2D Texture2D.queryFootprintFineBiasClamp(
    uint granularity, SamplerState sampler, float2 coords,
    float lodBias,
    float lodClamp);
TextureFootprint2D Texture2D.queryFootprintCoarseGradClamp(
    uint granularity, SamplerState sampler, float2 coords,
    float2 dx, float2 dy,
    float lodClamp);
TextureFootprint2D Texture2D.queryFootprintFineGradClamp(
    uint granularity, SamplerState sampler, float2 coords,
    float2 dx, float2 dy,
    float lodClamp);

For 3D textures, the following functions are supported:

TextureFootprint3D Texture3D.queryFootprintCoarse(
    uint granularity, SamplerState sampler, float3 coords);
TextureFootprint3D Texture3D.queryFootprintFine(
    uint granularity, SamplerState sampler, float3 coords);
TextureFootprint3D Texture3D.queryFootprintCoarseBias(
    uint granularity, SamplerState sampler, float3 coords,
    float lodBias);
TextureFootprint3D Texture3D.queryFootprintFineBias(
    uint granularity, SamplerState sampler, float3 coords,
    float lodBias);
TextureFootprint3D Texture3D.queryFootprintCoarseLevel(
    uint granularity, SamplerState sampler, float3 coords,
    float lod);
TextureFootprint3D Texture3D.queryFootprintFineLevel(
    uint granularity, SamplerState sampler, float3 coords,
    float lod);

// Vulkan-only:
TextureFootprint3D Texture3D.queryFootprintCoarseClamp(
    uint granularity, SamplerState sampler, float3 coords,
    float lodClamp);
TextureFootprint3D Texture3D.queryFootprintFineClamp(
    uint granularity, SamplerState sampler, float3 coords,
    float lodClamp);
TextureFootprint3D Texture3D.queryFootprintCoarseBiasClamp(
    uint granularity, SamplerState sampler, float3 coords,
    float lodBias,
    float lodClamp);
TextureFootprint3D Texture3D.queryFootprintFineBiasClamp(
    uint granularity, SamplerState sampler, float3 coords,
    float lodBias,
    float lodClamp);

Footprint Types

Footprint queries on 2D and 3D textures return values of type TextureFootprint2D and TextureFootprint3D, respectively, which are built-in structs defined in the Slang core module:

struct TextureFootprint2D
{
    typealias Anchor        = uint2;
    typealias Offset        = uint2;
    typealias Mask          = uint2;
    typealias LOD           = uint;
    typealias Granularity   = uint;

    property anchor         : Anchor        { get; }
    property offset         : Offset        { get; }
    property mask           : Mask          { get; }
    property lod            : LOD           { get; }
    property granularity    : Granularity   { get; }
    property isSingleLevel  : bool          { get; }
}

struct TextureFootprint3D
{
    typealias Anchor        = uint3;
    typealias Offset        = uint3;
    typealias Mask          = uint2;
    typealias LOD           = uint;
    typealias Granularity   = uint;

    property anchor         : Anchor        { get; }
    property offset         : Offset        { get; }
    property mask           : Mask          { get; }
    property lod            : LOD           { get; }
    property granularity    : Granularity   { get; }
    property isSingleLevel  : bool          { get; }
}

A footprint is encoded in terms of texel groups, where the granularity determines the size of those groups. When possible, the returned footprint will match the granularity passed into the query operation, but a larger granularity may be selected in cases where the footprint is too large to encode at the requested granularity.

The anchor property specifies an anchor point in the texture, in the vicinity of the footprint. Its components are in multiples of 8 texel groups.

The offset property specifies how the bits in mask map to texel groups in the vicinity of the anchor point.

The mask property is a 64-bit bitfield (encoded as a uint2), where each bit represents footprint coverage of one texel group, within a 8x8 (for 2D textures) or 4x4x4 neighborhood of texel groups.

The lod property indicates the mipmap level that would be accessed by the sampling operation.

The isSingleLevel property indicates if the sampling operation is known to access only a single mip level. Note that this property will always be false when using the D3D/NVAPI path.

1Texture Footprint Queries
2=========================
3
4Slang supports querying the *footprint* of a texture sampling operation: the texels that would be accessed when performing that operation.
5This feature is supported on Vulkan via the `GL_NV_shader_texture_footprint` extension, and on D3D12 via the `NvFootprint*` functions exposed by NVAPI.
6
7# Background
8
9There are many GPU rendering techniques that involve generating a texture (e.g., by rendering to it) and then sampling from that texture in a 3D rendering pass, such that it is difficult to predict *a priori* which parts of the texture will be accessed, or not.
10As one example, consider rendering a shadow map that will be accessed when shading a g-buffer.
11Depending on the geometry that was rendered into the g-buffer, and the occlusion that might exist, some parts of the shadow map might not be needed at all.
12
13In principle, an application could use a compute pass on the g-buffer to compute, for each pixel, the part of the shadow-map texture that it will access - its footprint.
14The application could then aggregate these footprints into a stencil mask or other data structure that could be used to optimize the rendering pass that generates the shadow map.
15
16Unfortunately, it is almost impossible for applications to accurately and reliably predict the texel data that particular sampling operations will require, once non-trivial texture filtering modes are considered.
17Sampling operations support a wide variety of state that affects the lookup and filtering of texels. For example:
18
19* When bilinear filtering is enabled, a sampling operation typically accesses the four texels closest to the sampling location and blends them.
20
21* When trilinear filtering is enabled, a sampling operation may access texels at two different mip levels.
22
23* When anisotropic filtering is enabled, a sampling operation may take up to N *taps* (where N is the maximum supported degree of anisotropy), each of which may itself access a neighborhood of texels to produce a filtered value for that tap.
24
25* When sampling a cube map, a sampling operation may straddle the "seam" between two or even three cube faces.
26
27Texture footprint queries are intended to solve this problem by providing application developers with a primitive that can query the footprint of a texture sampling operation using the exact same sampler state and texture coordinates that will be used when sampling the texture later.
28
29# Slang Shader API
30
31Rather than exactly mirror the Vulkan GLSL extension or the NVAPI functions, the Slang core module provides a single common interface that can map to either of those implementations.
32
33## Basics
34
35A typical 2D texture sampling operation is performed using the `Sample()` method on `Texture2D`:
36
37```hlsl
38Texture2D<float4> texture = ...;
39SamplerState sampler = ...;
40float2 coords = ...;
41
42// Sample a 2D texture
43float4 color = texture.Sample(
44    sampler, coords);
45```
46
47To query the footprint that would be accessed by this operation, we can use an operation like:
48
49```hlsl
50uint granularity = ...;
51TextureFootprint2D footprint = texture.queryFootprintCoarse(granularity,
52    sampler, coords);
53```
54
55Note that the same arguments used to call `Sample` above are here passed to `queryFootprint` in the exact same order.
56The returned `footprint` encodes a conservative footprint of the texels that would be accessed by the equivalent `Sample` operation above.
57
58Texture footprints are encoded in terms of blocks of texels, and the size of those blocks determined the *granularity* of the footprint.
59The `granularity` argument to `queryFootprintCoarse` above indicates the granularity of blocks that the application requests.
60
61In cases where a filtering operation might access two mip levels - one coarse and one fine - a footprint query only returns information about one of the two levels.
62The application selects between these options by calling either `queryFootprintCoarse` or `queryFootprintFine`.
63
64## Variations
65
66A wide range of footprint queries are provided, corresponding to various cases of texture sampling operations with different parameters.
67For 2D textures, the following functions are supported:
68
69```hlsl
70TextureFootprint2D Texture2D.queryFootprintCoarse(
71    uint granularity, SamplerState sampler, float2 coords);
72TextureFootprint2D Texture2D.queryFootprintFine(
73    uint granularity, SamplerState sampler, float2 coords);
74TextureFootprint2D Texture2D.queryFootprintCoarseBias(
75    uint granularity, SamplerState sampler, float2 coords,
76    float lodBias);
77TextureFootprint2D Texture2D.queryFootprintFineBias(
78    uint granularity, SamplerState sampler, float2 coords,
79    float lodBias);
80TextureFootprint2D Texture2D.queryFootprintCoarseLevel(
81    uint granularity, SamplerState sampler, float2 coords,
82    float lod);
83TextureFootprint2D Texture2D.queryFootprintFineLevel(
84    uint granularity, SamplerState sampler, float2 coords,
85    float lod);
86TextureFootprint2D Texture2D.queryFootprintCoarseGrad(
87    uint granularity, SamplerState sampler, float2 coords,
88    float2 dx, float2 dy);
89TextureFootprint2D Texture2D.queryFootprintFineGrad(
90    uint granularity, SamplerState sampler, float2 coords,
91    float2 dx, float2 dy);
92
93// Vulkan-only:
94TextureFootprint2D Texture2D.queryFootprintCoarseClamp(
95    uint granularity, SamplerState sampler, float2 coords,
96    float lodClamp);
97TextureFootprint2D Texture2D.queryFootprintFineClamp(
98    uint granularity, SamplerState sampler, float2 coords,
99    float lodClamp);
100TextureFootprint2D Texture2D.queryFootprintCoarseBiasClamp(
101    uint granularity, SamplerState sampler, float2 coords,
102    float lodBias,
103    float lodClamp);
104TextureFootprint2D Texture2D.queryFootprintFineBiasClamp(
105    uint granularity, SamplerState sampler, float2 coords,
106    float lodBias,
107    float lodClamp);
108TextureFootprint2D Texture2D.queryFootprintCoarseGradClamp(
109    uint granularity, SamplerState sampler, float2 coords,
110    float2 dx, float2 dy,
111    float lodClamp);
112TextureFootprint2D Texture2D.queryFootprintFineGradClamp(
113    uint granularity, SamplerState sampler, float2 coords,
114    float2 dx, float2 dy,
115    float lodClamp);
116```
117
118For 3D textures, the following functions are supported:
119
120```hlsl
121TextureFootprint3D Texture3D.queryFootprintCoarse(
122    uint granularity, SamplerState sampler, float3 coords);
123TextureFootprint3D Texture3D.queryFootprintFine(
124    uint granularity, SamplerState sampler, float3 coords);
125TextureFootprint3D Texture3D.queryFootprintCoarseBias(
126    uint granularity, SamplerState sampler, float3 coords,
127    float lodBias);
128TextureFootprint3D Texture3D.queryFootprintFineBias(
129    uint granularity, SamplerState sampler, float3 coords,
130    float lodBias);
131TextureFootprint3D Texture3D.queryFootprintCoarseLevel(
132    uint granularity, SamplerState sampler, float3 coords,
133    float lod);
134TextureFootprint3D Texture3D.queryFootprintFineLevel(
135    uint granularity, SamplerState sampler, float3 coords,
136    float lod);
137
138// Vulkan-only:
139TextureFootprint3D Texture3D.queryFootprintCoarseClamp(
140    uint granularity, SamplerState sampler, float3 coords,
141    float lodClamp);
142TextureFootprint3D Texture3D.queryFootprintFineClamp(
143    uint granularity, SamplerState sampler, float3 coords,
144    float lodClamp);
145TextureFootprint3D Texture3D.queryFootprintCoarseBiasClamp(
146    uint granularity, SamplerState sampler, float3 coords,
147    float lodBias,
148    float lodClamp);
149TextureFootprint3D Texture3D.queryFootprintFineBiasClamp(
150    uint granularity, SamplerState sampler, float3 coords,
151    float lodBias,
152    float lodClamp);
153```
154
155## Footprint Types
156
157Footprint queries on 2D and 3D textures return values of type `TextureFootprint2D` and `TextureFootprint3D`, respectively, which are built-in `struct`s defined in the Slang core module:
158
159```
160struct TextureFootprint2D
161{
162    typealias Anchor        = uint2;
163    typealias Offset        = uint2;
164    typealias Mask          = uint2;
165    typealias LOD           = uint;
166    typealias Granularity   = uint;
167
168    property anchor         : Anchor        { get; }
169    property offset         : Offset        { get; }
170    property mask           : Mask          { get; }
171    property lod            : LOD           { get; }
172    property granularity    : Granularity   { get; }
173    property isSingleLevel  : bool          { get; }
174}
175
176struct TextureFootprint3D
177{
178    typealias Anchor        = uint3;
179    typealias Offset        = uint3;
180    typealias Mask          = uint2;
181    typealias LOD           = uint;
182    typealias Granularity   = uint;
183
184    property anchor         : Anchor        { get; }
185    property offset         : Offset        { get; }
186    property mask           : Mask          { get; }
187    property lod            : LOD           { get; }
188    property granularity    : Granularity   { get; }
189    property isSingleLevel  : bool          { get; }
190}
191```
192
193A footprint is encoded in terms of *texel groups*, where the `granularity` determines the size of those groups.
194When possible, the returned footprint will match the granularity passed into the query operation, but a larger granularity may be selected in cases where the footprint is too large to encode at the requested granularity.
195
196The `anchor` property specifies an anchor point in the texture, in the vicinity of the footprint. Its components are in multiples of 8 texel groups.
197
198The `offset` property specifies how the bits in `mask` map to texel groups in the vicinity of the `anchor` point.
199
200The `mask` property is a 64-bit bitfield (encoded as a `uint2`), where each bit represents footprint coverage of one texel group, within a 8x8 (for 2D textures) or 4x4x4 neighborhood of texel groups.
201
202The `lod` property indicates the mipmap level that would be accessed by the sampling operation.
203
204The `isSingleLevel` property indicates if the sampling operation is known to access only a single mip level.
205Note that this property will always be `false` when using the D3D/NVAPI path.