| 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. |