Mesa (main): docs,nir: Document NIR texture instructions
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Jul 23 16:25:50 UTC 2021
Module: Mesa
Branch: main
Commit: fa717a202cb0287be8fbf73f68f58c71fff49fae
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=fa717a202cb0287be8fbf73f68f58c71fff49fae
Author: Jason Ekstrand <jason at jlekstrand.net>
Date: Wed Jul 7 17:44:27 2021 -0500
docs,nir: Document NIR texture instructions
Reviewed-by: Emma Anholt <emma at anholt.net>
Reviewed-by: Adam Jackson <ajax at redhat.com>
Reviewed-by: Alyssa Rosenzweig <alyssa at collabora.com>
Reviewed-by: Connor Abbott <cwabbott0 at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11775>
---
docs/nir/index.rst | 1 +
docs/nir/tex.rst | 67 ++++++++++++++
src/compiler/nir/nir.h | 240 ++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 274 insertions(+), 34 deletions(-)
diff --git a/docs/nir/index.rst b/docs/nir/index.rst
index 630ba011885..ea773c5b32c 100644
--- a/docs/nir/index.rst
+++ b/docs/nir/index.rst
@@ -11,3 +11,4 @@ stack.
:maxdepth: 2
alu
+ tex
diff --git a/docs/nir/tex.rst b/docs/nir/tex.rst
new file mode 100644
index 00000000000..492142ae18a
--- /dev/null
+++ b/docs/nir/tex.rst
@@ -0,0 +1,67 @@
+NIR Texture Instructions
+========================
+
+Even though texture instructions *could* be supported as intrinsics, the vast
+number of combinations mean that doing so is practically impossible. Instead,
+NIR has a dedicated texture instruction. There are several texture operations:
+
+.. doxygenenum:: nir_texop
+
+As with other instruction types, there is still an array of sources, except
+that each source also has a *type* associated with it. There are various
+source types, each corresponding to a piece of information that the different
+texture operations require.
+
+.. doxygenenum:: nir_tex_src_type
+
+Of particular interest are the texture/sampler deref/index/handle source types.
+First, note that textures and samplers are specified separately in NIR. While
+not required for OpenGL, this is required for Vulkan and OpenCL. Some
+OpenGL [ES] drivers have to deal with hardware that does not have separate
+samplers and textures. While not recommended, an OpenGL-only driver may assume
+that the texture and sampler derefs will always point to the same resource, if
+needed. Note that this pretty well paints your compiler into a corner and
+makes any future port to Vulkan or OpenCL harder, so such assumptions should
+really only be made if targeting OpenGL ES 2.0 era hardware.
+
+Also, like a lot of other resources, there are multiple ways to represent a
+texture in NIR. It can be referenced by a variable dereference, an index, or a
+bindless handle. When using an index or a bindless handle, the texture type
+information is generally not available. To handle this, various information
+from the type is redundantly stored in the :cpp:struct:`nir_tex_instr` itself.
+
+.. doxygenstruct:: nir_tex_instr
+ :members:
+
+.. doxygenstruct:: nir_tex_src
+ :members:
+
+Texture instruction helpers
+---------------------------
+
+There are a number of helper functions for working with NIR texture
+instructions. They are documented here in no particular order.
+
+.. doxygenfunction:: nir_tex_instr_create
+.. doxygenfunction:: nir_tex_instr_need_sampler
+.. doxygenfunction:: nir_tex_instr_result_size
+.. doxygenfunction:: nir_tex_instr_dest_size
+.. doxygenfunction:: nir_tex_instr_is_query
+.. doxygenfunction:: nir_tex_instr_has_implicit_derivative
+.. doxygenfunction:: nir_tex_instr_src_type
+.. doxygenfunction:: nir_tex_instr_src_size
+.. doxygenfunction:: nir_tex_instr_src_index
+.. doxygenfunction:: nir_tex_instr_add_src
+.. doxygenfunction:: nir_tex_instr_remove_src
+
+Texture instruction lowering
+----------------------------
+
+Because most hardware only supports some subset of all possible GLSL/SPIR-V
+texture operations, NIR provides a quite powerful lowering pass which is able
+to implement more complex texture operations in terms of simpler ones.
+
+.. doxygenfunction:: nir_lower_tex
+.. doxygenstruct:: nir_lower_tex_options
+ :members:
+.. doxygenenum:: nir_lower_tex_packing
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index b2b3531fd1d..e1bd3e8051c 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2010,40 +2010,135 @@ nir_intrinsic_can_reorder(nir_intrinsic_instr *instr)
bool nir_intrinsic_writes_external_memory(const nir_intrinsic_instr *instr);
-/**
- * \group texture information
- *
- * This gives semantic information about textures which is useful to the
- * frontend, the backend, and lowering passes, but not the optimizer.
- */
-
+/** Texture instruction source type */
typedef enum {
+ /** Texture coordinate
+ *
+ * Must have nir_tex_instr::coord_components components.
+ */
nir_tex_src_coord,
+
+ /** Projector
+ *
+ * The texture coordinate (except for the array component, if any) is
+ * divided by this value before LOD computation and sampling.
+ *
+ * Must be a float scalar.
+ */
nir_tex_src_projector,
- nir_tex_src_comparator, /* shadow comparator */
+
+ /** Shadow comparator
+ *
+ * For shadow sampling, the fetched texel values are compared against the
+ * shadow comparator using the compare op specified by the sampler object
+ * and converted to 1.0 if the comparison succeeds and 0.0 if it fails.
+ * Interpolation happens after this conversion so the actual result may be
+ * anywhere in the range [0.0, 1.0].
+ *
+ * Only valid if nir_tex_instr::is_shadow and must be a float scalar.
+ */
+ nir_tex_src_comparator,
+
+ /** Coordinate offset
+ *
+ * An integer value that is added to the texel address before sampling.
+ * This is only allowed with operations that take an explicit LOD as it is
+ * applied in integer texel space after LOD selection and not normalized
+ * coordinate space.
+ */
nir_tex_src_offset,
+
+ /** LOD bias
+ *
+ * This value is added to the computed LOD before mip-mapping.
+ */
nir_tex_src_bias,
+
+ /** Explicit LOD */
nir_tex_src_lod,
+
+ /** Min LOD
+ *
+ * The computed LOD is clamped to be at least as large as min_lod before
+ * mip-mapping.
+ */
nir_tex_src_min_lod,
- nir_tex_src_ms_index, /* MSAA sample index */
- nir_tex_src_ms_mcs_intel, /* MSAA compression value */
+
+ /** MSAA sample index */
+ nir_tex_src_ms_index,
+
+ /** Intel-specific MSAA compression data */
+ nir_tex_src_ms_mcs_intel,
+
+ /** Explicit horizontal (X-major) coordinate derivative */
nir_tex_src_ddx,
+
+ /** Explicit vertical (Y-major) coordinate derivative */
nir_tex_src_ddy,
- nir_tex_src_texture_deref, /* < deref pointing to the texture */
- nir_tex_src_sampler_deref, /* < deref pointing to the sampler */
- nir_tex_src_texture_offset, /* < dynamically uniform indirect offset */
- nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */
- nir_tex_src_texture_handle, /* < bindless texture handle */
- nir_tex_src_sampler_handle, /* < bindless sampler handle */
- nir_tex_src_plane, /* < selects plane for planar textures */
+
+ /** Texture variable dereference */
+ nir_tex_src_texture_deref,
+
+ /** Sampler variable dereference */
+ nir_tex_src_sampler_deref,
+
+ /** Texture index offset
+ *
+ * This is added to nir_tex_instr::texture_index. Unless
+ * nir_tex_instr::texture_non_uniform is set, this is guaranteed to be
+ * dynamically uniform.
+ */
+ nir_tex_src_texture_offset,
+
+ /** Dynamically uniform sampler index offset
+ *
+ * This is added to nir_tex_instr::sampler_index. Unless
+ * nir_tex_instr::sampler_non_uniform is set, this is guaranteed to be
+ * dynamically uniform.
+ */
+ nir_tex_src_sampler_offset,
+
+ /** Bindless texture handle
+ *
+ * This is, unfortunately, a bit overloaded at the moment. There are
+ * generally two types of bindless handles:
+ *
+ * 1. For GL_ARB_bindless bindless handles. These are part of the
+ * GL/Gallium-level API and are always a 64-bit integer.
+ *
+ * 2. HW-specific handles. GL_ARB_bindless handles may be lowered to
+ * these. Also, these are used by many Vulkan drivers to implement
+ * descriptor sets, especially for UPDATE_AFTER_BIND descriptors.
+ * The details of hardware handles (bit size, format, etc.) is
+ * HW-specific.
+ *
+ * Because of this overloading and the resulting ambiguity, we currently
+ * don't validate anything for these.
+ */
+ nir_tex_src_texture_handle,
+
+ /** Bindless sampler handle
+ *
+ * See nir_tex_src_texture_handle,
+ */
+ nir_tex_src_sampler_handle,
+
+ /** Plane index for multi-plane YCbCr textures */
+ nir_tex_src_plane,
+
nir_num_tex_src_types
} nir_tex_src_type;
+/** A texture instruction source */
typedef struct {
+ /** Base source */
nir_src src;
+
+ /** Type of this source */
nir_tex_src_type src_type;
} nir_tex_src;
+/** Texture instruction opcode */
typedef enum {
nir_texop_tex, /**< Regular texture look-up */
nir_texop_txb, /**< Texture look-up with LOD bias */
@@ -2066,43 +2161,88 @@ typedef enum {
nir_texop_fragment_mask_fetch,/**< Multisample fragment mask texture fetch */
} nir_texop;
+/** Represents a texture instruction */
typedef struct {
+ /** Base instruction */
nir_instr instr;
+ /** Dimensionality of the texture operation
+ *
+ * This will typically match the dimensionality of the texture deref type
+ * if a nir_tex_src_texture_deref is present. However, it may not if
+ * texture lowering has occurred.
+ */
enum glsl_sampler_dim sampler_dim;
+
+ /** ALU type of the destination
+ *
+ * This is the canonical sampled type for this texture operation and may
+ * not exactly match the sampled type of the deref type when a
+ * nir_tex_src_texture_deref is present. For OpenCL, the sampled type of
+ * the texture deref will be GLSL_TYPE_VOID and this is allowed to be
+ * anything. With SPIR-V, the signedness of integer types is allowed to
+ * differ. For all APIs, the bit size may differ if the driver has done
+ * any sort of mediump or similar lowering since texture types always have
+ * 32-bit sampled types.
+ */
nir_alu_type dest_type;
+ /** Texture opcode */
nir_texop op;
+
+ /** Destination */
nir_dest dest;
+
+ /** Array of sources
+ *
+ * This array has nir_tex_instr::num_srcs elements
+ */
nir_tex_src *src;
- unsigned num_srcs, coord_components;
- bool is_array, is_shadow;
+
+ /** Number of sources */
+ unsigned num_srcs;
+
+ /** Number of components in the coordinate, if any */
+ unsigned coord_components;
+
+ /** True if the texture instruction acts on an array texture */
+ bool is_array;
+
+ /** True if the texture instruction performs a shadow comparison
+ *
+ * If this is true, the texture instruction must have a
+ * nir_tex_src_comparator.
+ */
+ bool is_shadow;
/**
- * If is_shadow is true, whether this is the old-style shadow that outputs 4
- * components or the new-style shadow that outputs 1 component.
+ * If is_shadow is true, whether this is the old-style shadow that outputs
+ * 4 components or the new-style shadow that outputs 1 component.
*/
bool is_new_style_shadow;
/**
- * If this texture instruction should return a sparse residency code. The
- * code is in the last component of the result.
+ * True if this texture instruction should return a sparse residency code.
+ * The code is in the last component of the result.
*/
bool is_sparse;
- /* gather component selector */
+ /** nir_texop_tg4 component selector
+ *
+ * This determines which RGBA component is gathered.
+ */
unsigned component : 2;
- /* Validation needs to know this for gradient component count */
+ /** Validation needs to know this for gradient component count */
unsigned array_is_lowered_cube : 1;
- /* gather offsets */
+ /** Gather offsets */
int8_t tg4_offsets[4][2];
- /* True if the texture index or handle is not dynamically uniform */
+ /** True if the texture index or handle is not dynamically uniform */
bool texture_non_uniform;
- /* True if the sampler index or handle is not dynamically uniform */
+ /** True if the sampler index or handle is not dynamically uniform */
bool sampler_non_uniform;
/** The texture index
@@ -2129,12 +2269,13 @@ typedef struct {
unsigned sampler_index;
} nir_tex_instr;
-/*
- * Returns true if the texture operation requires a sampler as a general rule,
- * see the documentation of sampler_index.
+/**
+ * Returns true if the texture operation requires a sampler as a general rule
*
* Note that the specific hw/driver backend could require to a sampler
* object/configuration packet in any case, for some other reason.
+ *
+ * @see nir_tex_instr::sampler_index.
*/
static inline bool
nir_tex_instr_need_sampler(const nir_tex_instr *instr)
@@ -2152,6 +2293,12 @@ nir_tex_instr_need_sampler(const nir_tex_instr *instr)
}
}
+/** Returns the number of components returned by this nir_tex_instr
+ *
+ * Useful for code building texture instructions when you don't want to think
+ * about how many components a particular texture op returns. This does not
+ * include the sparse residency code.
+ */
static inline unsigned
nir_tex_instr_result_size(const nir_tex_instr *instr)
{
@@ -2199,6 +2346,10 @@ nir_tex_instr_result_size(const nir_tex_instr *instr)
}
}
+/**
+ * Returns the destination size of this nir_tex_instr including the sparse
+ * residency code, if any.
+ */
static inline unsigned
nir_tex_instr_dest_size(const nir_tex_instr *instr)
{
@@ -2206,7 +2357,8 @@ nir_tex_instr_dest_size(const nir_tex_instr *instr)
return nir_tex_instr_result_size(instr) + instr->is_sparse;
}
-/* Returns true if this texture operation queries something about the texture
+/**
+ * Returns true if this texture operation queries something about the texture
* rather than actually sampling it.
*/
static inline bool
@@ -2233,6 +2385,11 @@ nir_tex_instr_is_query(const nir_tex_instr *instr)
}
}
+/** Returns true if this texture instruction does implicit derivatives
+ *
+ * This is important as there are extra control-flow rules around derivatives
+ * and texture instructions which perform them implicitly.
+ */
static inline bool
nir_tex_instr_has_implicit_derivative(const nir_tex_instr *instr)
{
@@ -2246,6 +2403,7 @@ nir_tex_instr_has_implicit_derivative(const nir_tex_instr *instr)
}
}
+/** Returns the ALU type of the given texture instruction source */
static inline nir_alu_type
nir_tex_instr_src_type(const nir_tex_instr *instr, unsigned src)
{
@@ -2303,6 +2461,10 @@ nir_tex_instr_src_type(const nir_tex_instr *instr, unsigned src)
unreachable("Invalid texture source type");
}
+/**
+ * Returns the number of components required by the given texture instruction
+ * source
+ */
static inline unsigned
nir_tex_instr_src_size(const nir_tex_instr *instr, unsigned src)
{
@@ -2337,6 +2499,10 @@ nir_tex_instr_src_size(const nir_tex_instr *instr, unsigned src)
return 1;
}
+/**
+ * Returns the index of the texture instruction source with the given
+ * nir_tex_src_type or -1 if no such source exists.
+ */
static inline int
nir_tex_instr_src_index(const nir_tex_instr *instr, nir_tex_src_type type)
{
@@ -2347,10 +2513,12 @@ nir_tex_instr_src_index(const nir_tex_instr *instr, nir_tex_src_type type)
return -1;
}
+/** Adds a source to a texture instruction */
void nir_tex_instr_add_src(nir_tex_instr *tex,
nir_tex_src_type src_type,
nir_src src);
+/** Removes a source from a texture instruction */
void nir_tex_instr_remove_src(nir_tex_instr *tex, unsigned src_idx);
bool nir_tex_instr_has_explicit_tg4_offsets(nir_tex_instr *tex);
@@ -3674,6 +3842,7 @@ nir_intrinsic_instr *nir_intrinsic_instr_create(nir_shader *shader,
nir_call_instr *nir_call_instr_create(nir_shader *shader,
nir_function *callee);
+/** Creates a NIR texture instruction */
nir_tex_instr *nir_tex_instr_create(nir_shader *shader, unsigned num_srcs);
nir_phi_instr *nir_phi_instr_create(nir_shader *shader);
@@ -4753,12 +4922,14 @@ bool nir_lower_compute_system_values(nir_shader *shader,
const nir_lower_compute_system_values_options *options);
enum PACKED nir_lower_tex_packing {
+ /** No packing */
nir_lower_tex_packing_none = 0,
- /* The sampler returns up to 2 32-bit words of half floats or 16-bit signed
+ /**
+ * The sampler returns up to 2 32-bit words of half floats or 16-bit signed
* or unsigned ints based on the sampler type
*/
nir_lower_tex_packing_16,
- /* The sampler returns 1 32-bit word of 4x8 unorm */
+ /** The sampler returns 1 32-bit word of 4x8 unorm */
nir_lower_tex_packing_8,
};
@@ -4938,6 +5109,7 @@ typedef struct nir_lower_tex_options {
enum nir_lower_tex_packing lower_tex_packing[32];
} nir_lower_tex_options;
+/** Lowers complex texture instructions to simpler ones */
bool nir_lower_tex(nir_shader *shader,
const nir_lower_tex_options *options);
More information about the mesa-commit
mailing list