yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
a508b264e
master
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 ( 44sampler , 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 , 52sampler , 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 ( 71uint granularity , SamplerState sampler , float2 coords ); 72TextureFootprint2D Texture2D . queryFootprintFine ( 73uint granularity , SamplerState sampler , float2 coords ); 74TextureFootprint2D Texture2D . queryFootprintCoarseBias ( 75uint granularity , SamplerState sampler , float2 coords , 76float lodBias ); 77TextureFootprint2D Texture2D . queryFootprintFineBias ( 78uint granularity , SamplerState sampler , float2 coords , 79float lodBias ); 80TextureFootprint2D Texture2D . queryFootprintCoarseLevel ( 81uint granularity , SamplerState sampler , float2 coords , 82float lod ); 83TextureFootprint2D Texture2D . queryFootprintFineLevel ( 84uint granularity , SamplerState sampler , float2 coords , 85float lod ); 86TextureFootprint2D Texture2D . queryFootprintCoarseGrad ( 87uint granularity , SamplerState sampler , float2 coords , 88float2 dx , float2 dy ); 89TextureFootprint2D Texture2D . queryFootprintFineGrad ( 90uint granularity , SamplerState sampler , float2 coords , 91float2 dx , float2 dy ); 92 93// Vulkan-only: 94TextureFootprint2D Texture2D . queryFootprintCoarseClamp ( 95uint granularity , SamplerState sampler , float2 coords , 96float lodClamp ); 97TextureFootprint2D Texture2D . queryFootprintFineClamp ( 98uint granularity , SamplerState sampler , float2 coords , 99float lodClamp ); 100TextureFootprint2D Texture2D . queryFootprintCoarseBiasClamp ( 101uint granularity , SamplerState sampler , float2 coords , 102float lodBias , 103float lodClamp ); 104TextureFootprint2D Texture2D . queryFootprintFineBiasClamp ( 105uint granularity , SamplerState sampler , float2 coords , 106float lodBias , 107float lodClamp ); 108TextureFootprint2D Texture2D . queryFootprintCoarseGradClamp ( 109uint granularity , SamplerState sampler , float2 coords , 110float2 dx , float2 dy , 111float lodClamp ); 112TextureFootprint2D Texture2D . queryFootprintFineGradClamp ( 113uint granularity , SamplerState sampler , float2 coords , 114float2 dx , float2 dy , 115float lodClamp ); 116``` 117 118For 3D textures, the following functions are supported: 119 120``` hlsl 121TextureFootprint3D Texture3D . queryFootprintCoarse ( 122uint granularity , SamplerState sampler , float3 coords ); 123TextureFootprint3D Texture3D . queryFootprintFine ( 124uint granularity , SamplerState sampler , float3 coords ); 125TextureFootprint3D Texture3D . queryFootprintCoarseBias ( 126uint granularity , SamplerState sampler , float3 coords , 127float lodBias ); 128TextureFootprint3D Texture3D . queryFootprintFineBias ( 129uint granularity , SamplerState sampler , float3 coords , 130float lodBias ); 131TextureFootprint3D Texture3D . queryFootprintCoarseLevel ( 132uint granularity , SamplerState sampler , float3 coords , 133float lod ); 134TextureFootprint3D Texture3D . queryFootprintFineLevel ( 135uint granularity , SamplerState sampler , float3 coords , 136float lod ); 137 138// Vulkan-only: 139TextureFootprint3D Texture3D . queryFootprintCoarseClamp ( 140uint granularity , SamplerState sampler , float3 coords , 141float lodClamp ); 142TextureFootprint3D Texture3D . queryFootprintFineClamp ( 143uint granularity , SamplerState sampler , float3 coords , 144float lodClamp ); 145TextureFootprint3D Texture3D . queryFootprintCoarseBiasClamp ( 146uint granularity , SamplerState sampler , float3 coords , 147float lodBias , 148float lodClamp ); 149TextureFootprint3D Texture3D . queryFootprintFineBiasClamp ( 150uint granularity , SamplerState sampler , float3 coords , 151float lodBias , 152float 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{ 162typealias Anchor = uint2; 163typealias Offset = uint2; 164typealias Mask = uint2; 165typealias LOD = uint; 166typealias Granularity = uint; 167 168property anchor : Anchor { get; } 169property offset : Offset { get; } 170property mask : Mask { get; } 171property lod : LOD { get; } 172property granularity : Granularity { get; } 173property isSingleLevel : bool { get; } 174} 175 176struct TextureFootprint3D 177{ 178typealias Anchor = uint3; 179typealias Offset = uint3; 180typealias Mask = uint2; 181typealias LOD = uint; 182typealias Granularity = uint; 183 184property anchor : Anchor { get; } 185property offset : Offset { get; } 186property mask : Mask { get; } 187property lod : LOD { get; } 188property granularity : Granularity { get; } 189property 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.