blob: 7322358f15b5fc7e1eb1a03110488709913baa32 [file] [log] [blame]
Name
NV_shader_texture_footprint
Name Strings
GL_NV_shader_texture_footprint
Contact
Chris Lentini, NVIDIA (clentini 'at' nvidia.com)
Pat Brown, NVIDIA (pbrown 'at' nvidia.com)
Contributors
Jeff Bolz, NVIDIA
Daniel Koch, NVIDIA
Status
Shipping
Version
Last Modified Date: February 8, 2018
NVIDIA Revision: 2
Number
OpenGL Extension #530
OpenGL ES Extension #313
Dependencies
This extension is written against the OpenGL 4.6 Specification
(Compatibility Profile), dated July 30, 2017.
OpenGL 4.5 or OpenGL ES 3.2 is required.
This extension requires support for the OpenGL Shading Language (GLSL)
extension "NV_shader_texture_footprint", which can be found at the Khronos
Group Github site here:
https://github.com/KhronosGroup/GLSL
Overview
This extension adds OpenGL API support for the OpenGL Shading Language
(GLSL) extension "NV_shader_texture_footprint". That extension adds a new
set of texture query functions ("textureFootprint*NV") to GLSL. These
built-in functions prepare to perform a filtered texture lookup based on
coordinates and other parameters passed in by the calling code. However,
instead of returning data from the provided texture image, these query
functions instead return data identifying the _texture footprint_ for an
equivalent texture access. The texture footprint identifies a set of
texels that may be accessed in order to return a filtered result for the
texture access.
The footprint itself is a structure that includes integer values that
identify a small neighborhood of texels in the texture being accessed and
a bitfield that indicates which texels in that neighborhood would be used.
Each bit in the returned bitfield identifies whether any texel in a small
aligned block of texels would be fetched by the texture lookup. The size
of each block is specified by an access _granularity_ provided by the
shader. The minimum granularity supported by this extension is 2x2 (for
2D textures) and 2x2x2 (for 3D textures); the maximum granularity is
256x256 (for 2D textures) or 64x32x32 (for 3D textures). Each footprint
query returns the footprint from a single texture level. When using
minification filters that combine accesses from multiple mipmap levels,
shaders must perform separate queries for the two levels accessed ("fine"
and "coarse"). The footprint query also returns a flag indicating if the
texture lookup would access texels from only one mipmap level or from two
neighboring levels.
This extension should be useful for multi-pass rendering operations that
do an initial expensive rendering pass to produce a first image that is
then used as a texture for a second pass. If the second pass ends up
accessing only portions of the first image (e.g., due to visibility), the
work spent rendering the non-accessed portion of the first image was
wasted. With this feature, an application can limit this waste using an
initial pass over the geometry in the second image that performs a
footprint query for each visible pixel to determine the set of pixels that
it needs from the first image. This pass would accumulate an aggregate
footprint of all visible pixels into a separate "footprint texture" using
shader atomics. Then, when rendering the first image, the application can
kill all shading work for pixels not in this aggregate footprint.
The implementation of this extension has a number of limitations. The
texture footprint query functions are only supported for two- and
three-dimensional textures (TEXTURE_2D, TEXTURE_3D). Texture footprint
evaluation only supports the CLAMP_TO_EDGE wrap mode; results are
undefined for all other wrap modes. The implementation supports only a
limited set of granularity values and does not support separate coverage
information for each texel in the original texture.
New Procedures and Functions
None
New Tokens
None
Additions to Chapter 8 of the OpenGL 4.6 (Compatibility Profile) Specification
(Textures and Samplers)
(add a new section immediately after section 8.15, Texture Magnification)
Section 8.X, Texture Footprint Queries
The OpenGL Shading Language provides a collection of built-in functions,
all beginning with "textureFootprint", that allow shaders to query a
_texture footprint_. The texture footprint is a set of texels belonging
to a single texture level that would be accessed when performing a
filtered texture lookup. The shader code calling the footprint query
functions passes in a _granularity_ value, which is used to subdivide a
texture level into an array of fixed-size _texel groups_ whose size is
given by the granularity. The texture footprint query functions return
the footprint using a built-in GLSL data structure that identifies the set
of texel groups containing one or more texels that would be accessed in an
equivalent texture lookup. Texture footprint queries are only supported
for two- and three-dimensional textures (targets TEXTURE_2D and
TEXTURE_3D). Additionally, footprint queries require the use of the
CLAMP_TO_EDGE sampler wrap mode in all relevant dimensions; the results of
the footprint query are undefined if any other wrap mode is used.
Each texture footprint query built-in function accepts a set of texture
coordinates and any additional parameters (e.g., explicit level of detail,
level of detail bias, or derivatives) needed to specify a normal texture
lookup operation whose footprint should be evaluated. The footprint query
functions also accept a <granularity> parameter and a <coarse> flag used
to select the level of detail whose footprint is returned. The
granularity parameter identifies the size of the texel groups used for the
footprint query as described in Table X.1. The <coarse> flag is used to
select between the two levels of detail used when minifying using a filter
(NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_LINEAR) that averages texels from
multiple levels of detail. When such minification is performed, a value
of "false" requests the footprint in the higher-resolution (fine) level of
detail, while "true" requests the footprint in the lower-resolution
(coarse) level of detail. When a texture access uses only a single level
of detail, its footprint will be returned for queries with <coarse> set to
false, while queries with <coarse> set to true will return an empty
footprint. Since many texture accesses may use only a single level, the
footprint query functions return a boolean value, which will be true if
and only if all accessed texels are in a single level of detail.
Granularity Value | TEXTURE_2D | TEXTURE_3D
------------------+---------------+----------------
0 | unsupported | unsupported
1 | 2x2 | 2x2x2
2 | 4x2 | unsupported
3 | 4x4 | 4x4x2
4 | 8x4 | unsupported
5 | 8x8 | unsupported
6 | 16x8 | unsupported
7 | 16x16 | unsupported
8 | unsupported | unsupported
9 | unsupported | unsupported
10 | unsupported | 16x16x16
11 | 64x64 | 32x16x16
12 | 128x64 | 32x32x16
13 | 128x128 | 32x32x32
14 | 256x128 | 64x32x32
15 | 256x256 | unsupported
Table X.1: Supported granularities for texture footprint queries, for
two-dimensional (TEXTURE_2D) and three-dimensional (TEXTURE_3D)
accesses. Granularity values not listed in the table or listed as
"unsupported" are not supported by this extension and result in
undefined behavior if used.
In addition to the boolean result, texture footprint queries return
footprint data in a structure of the type gl_TextureFootprint2DNV (for
two-dimensional textures) or gl_TextureFootprint3DNV (for
three-dimensional textures). In either structure, the member <lod>
specifies the level-of-detail number used for the footprint. The
members <anchor> and <offset> identify a small neighborhood of texel
groups in the texture used by the query. The member <mask> specifies 64
bits of data indicating which texel groups in the neighborhood are part
of the footprint. The member <granularity> returns information on the
size of the texel groups in the footprint, which is sometimes larger
than the requested granularity, as described below.
For two-dimensional footprint queries, the neighborhood returned by the
query is an 8x8 array of texel groups, where each texel group in
neighborhood is identified by a coordinate (x,y), where <x> and <y> are
integer values in the range [0,7]. Each texel group corresponds to a
set of texels whose (u,v) coordinates satisfy the inequalities:
u1 <= u <= u2
v1 <= v <= v2
computed using the following logic:
// The footprint logic returns a mask whose bits are aligned to 8x8
// sets of texel groups. This allows shaders to use atomics to
// efficiently accumulate footprint results across many invocations,
// storing an 8x8 array of bits for each group into one RG32UI texel.
// The texel group number in the neighborhood is treated as an offset
// relative to the anchor point.
uvec2 texel_group = 8 * result.anchor + uvec2(x,y);
// If the neighborhood crosses the boundaries of an 8x8 set, the bits
// of the mask are effectively split across multiple sets (up to
// four for 2D). The "offset" parameter returned by the query
// identifies which x/y group values in the neighborhood are
// assigned to which set. An all-zero offset indicates that the
// footprint is fully contained in a single 8x8 set at the anchor.
// "Low" x/y values identify texel groups at the beginning of the 8x8
// set identified by the anchor, while "high" values correspond to
// texel groups at the end of the previous set. The offset
// indicates the number of texel groups assigned to the previous set.
if (x + result.offset.x >= 8) {
texel_group.x -= 8;
}
if (y + result.offset.y >= 8) {
texel_group.y -= 8;
}
// Once we have a group number, u/v texel number ranges are generated by
// multiplying by the texel group size.
uint u1 = texel_group.x * granularity_x;
uint u2 = u1 + granularity_x - 1;
uint v1 = texel_group.y * granularity_y;
uint v2 = v1 + granularity_y - 1;
In the equations above, <granularity_x> and <granularity_y> refer to the
texel group size as in Table X.1. result.anchor and result.offset
specify the <anchor> and <offset> members of the returned structure, and
<x> and <y> specify the texel group number in the neighborhood.
Each bit in the <mask> member of the returned structure corresponds to
one of the texel groups in the 8x8 neighborhood. That bit will be set
if and only if any of the texels in the texel group is covered by the
footprint. The texel group (x,y) is considered to be covered if and
only if the following logic computes true for <covered>:
uint64_t mask = result.mask.x | (result.mask.y << 32);
uint32_t bit = y * 8 + x;
bool covered = (0 != ((mask >> bit) & 1));
For three-dimensional footprint queries, the logic is very similar,
except that the neighborhood returned by the query is a 4x4x4 array of
texel groups. Each texel group in neighborhood is identified by a
coordinate (x,y,z), where <x>, <y>, and <z> are integer values in the
range [0,3]. Each texel group corresponds to a set of texels whose
(u,v,w) coordinates satisfy the inequalities:
u1 <= u <= u2
v1 <= v <= v2
w1 <= w <= w2
computed using the following logic:
uvec3 texel_group = 4 * result.anchor + uvec3(x,y,z);
if (x + result.offset.x >= 4) {
texel_group.x -= 4;
}
if (y + result.offset.y >= 4) {
texel_group.y -= 4;
}
if (z + result.offset.z >= 4) {
texel_group.z -= 4;
}
uint u1 = texel_group.x * granularity_x;
uint u2 = u1 + granularity_x - 1;
uint v1 = texel_group.y * granularity_y;
uint v2 = v1 + granularity_y - 1;
uint w1 = texel_group.z * granularity_z;
uint w2 = w1 + granularity_z - 1;
As in the two-dimensional logic, <granularity_x>, <granularity_y>, and
<granularity_z> refer to the texel group size as in Table X.1.
result.anchor and result.offset specify the <anchor> and <offset>
members of the returned structure, and <x>, <y>, and <z> specify the
texel group number in the neighborhood.
Each bit in the <mask> member of the returned structure corresponds to
one of the texel groups in the 4x4x4 neighborhood. That bit will be set
if and only if any of the texels in the texel group is covered by the
footprint. The texel group (x,y,z) is considered to be covered if and
only if the following logic computes true for <covered>:
uint64_t mask = result.mask.x | (result.mask.y << 32);
uint32_t bit = z * 16 + y * 4 + x;
bool covered = (0 != ((mask >> bit) & 1));
In most cases, the texel group sizes used by the footprint query will
match the value passed to the query, as interpreted according to Table
X.1. However, in some cases, the footprint may be too large to be
expressed as a collection of 8x8 or 4x4x4 set of texel groups using the
requested granularity. In this case, the implementation uses a texel
group size that is larger than the requested granularity. If a larger
texel group size is used, the implementation will return the texel group
size used in the <granularity> member of the footprint structure, which
should also be interpreted according to Table X.1. If the requested
texel group size is used, the implementation will return zero in
<granularity>. The texel group size will only be increased by the
implementation if anisotropic filtering is used. If the texture and
sampler objects used by the footprint query do not enable anisotropic
texture filtering, the footprint query will always use the original
requested granularity and return zero in the <granularity> member.
Errors
None
New State
None
New Implementation Dependent State
None
Issues
None, but please refer to issues in the GLSL extension specification.
Revision History
Revision 2 (pknowles)
- Add ES interactions.
Revision 1 (clentini, pbrown)
- Internal revisions.