nir: Add a lowering pass for YUV textures
[mesa.git] / src / compiler / nir / nir.h
index 4693ab58a598e05b53a16f6b2b3f1a4168ef7e40..96246f6d634e404c220c9f631d923dc877c9d29f 100644 (file)
@@ -34,6 +34,7 @@
 #include "util/ralloc.h"
 #include "util/set.h"
 #include "util/bitset.h"
+#include "util/macros.h"
 #include "compiler/nir_types.h"
 #include "compiler/shader_enums.h"
 #include <stdio.h>
@@ -516,16 +517,16 @@ nir_src_init(void)
 
 #define NIR_SRC_INIT nir_src_init()
 
-#define nir_foreach_use(reg_or_ssa_def, src) \
+#define nir_foreach_use(src, reg_or_ssa_def) \
    list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
 
-#define nir_foreach_use_safe(reg_or_ssa_def, src) \
+#define nir_foreach_use_safe(src, reg_or_ssa_def) \
    list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
 
-#define nir_foreach_if_use(reg_or_ssa_def, src) \
+#define nir_foreach_if_use(src, reg_or_ssa_def) \
    list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)
 
-#define nir_foreach_if_use_safe(reg_or_ssa_def, src) \
+#define nir_foreach_if_use_safe(src, reg_or_ssa_def) \
    list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)
 
 typedef struct {
@@ -546,10 +547,10 @@ nir_dest_init(void)
 
 #define NIR_DEST_INIT nir_dest_init()
 
-#define nir_foreach_def(reg, dest) \
+#define nir_foreach_def(dest, reg) \
    list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link)
 
-#define nir_foreach_def_safe(reg, dest) \
+#define nir_foreach_def_safe(dest, reg) \
    list_for_each_entry_safe(nir_dest, dest, &(reg)->defs, reg.def_link)
 
 static inline nir_src
@@ -1068,10 +1069,12 @@ typedef enum {
    nir_tex_src_bias,
    nir_tex_src_lod,
    nir_tex_src_ms_index, /* MSAA sample index */
+   nir_tex_src_ms_mcs, /* MSAA compression value */
    nir_tex_src_ddx,
    nir_tex_src_ddy,
    nir_tex_src_texture_offset, /* < dynamically uniform indirect offset */
    nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */
+   nir_tex_src_plane,          /* < selects plane for planar textures */
    nir_num_tex_src_types
 } nir_tex_src_type;
 
@@ -1087,6 +1090,7 @@ typedef enum {
    nir_texop_txd,                /**< Texture look-up with partial derivatvies */
    nir_texop_txf,                /**< Texel fetch with explicit LOD */
    nir_texop_txf_ms,                /**< Multisample texture fetch */
+   nir_texop_txf_ms_mcs,         /**< Multisample compression value fetch */
    nir_texop_txs,                /**< Texture size */
    nir_texop_lod,                /**< Texture lod query */
    nir_texop_tg4,                /**< Texture gather */
@@ -1215,6 +1219,7 @@ nir_tex_instr_is_query(nir_tex_instr *instr)
    case nir_texop_lod:
    case nir_texop_texture_samples:
    case nir_texop_query_levels:
+   case nir_texop_txf_ms_mcs:
       return true;
    case nir_texop_tex:
    case nir_texop_txb:
@@ -1235,6 +1240,9 @@ nir_tex_instr_src_size(nir_tex_instr *instr, unsigned src)
    if (instr->src[src].src_type == nir_tex_src_coord)
       return instr->coord_components;
 
+   /* The MCS value is expected to be a vec4 returned by a txf_ms_mcs */
+   if (instr->src[src].src_type == nir_tex_src_ms_mcs)
+      return 4;
 
    if (instr->src[src].src_type == nir_tex_src_offset ||
        instr->src[src].src_type == nir_tex_src_ddx ||
@@ -1304,10 +1312,10 @@ typedef struct {
    nir_src src;
 } nir_phi_src;
 
-#define nir_foreach_phi_src(phi, entry) \
-   foreach_list_typed(nir_phi_src, entry, node, &(phi)->srcs)
-#define nir_foreach_phi_src_safe(phi, entry) \
-   foreach_list_typed_safe(nir_phi_src, entry, node, &(phi)->srcs)
+#define nir_foreach_phi_src(phi_src, phi) \
+   foreach_list_typed(nir_phi_src, phi_src, node, &(phi)->srcs)
+#define nir_foreach_phi_src_safe(phi_src, phi) \
+   foreach_list_typed_safe(nir_phi_src, phi_src, node, &(phi)->srcs)
 
 typedef struct {
    nir_instr instr;
@@ -1323,7 +1331,7 @@ typedef struct {
    nir_dest dest;
 } nir_parallel_copy_entry;
 
-#define nir_foreach_parallel_copy_entry(pcopy, entry) \
+#define nir_foreach_parallel_copy_entry(entry, pcopy) \
    foreach_list_typed(nir_parallel_copy_entry, entry, node, &(pcopy)->entries)
 
 typedef struct {
@@ -1434,13 +1442,13 @@ nir_block_last_instr(nir_block *block)
    return exec_node_data(nir_instr, tail, node);
 }
 
-#define nir_foreach_instr(block, instr) \
+#define nir_foreach_instr(instr, block) \
    foreach_list_typed(nir_instr, instr, node, &(block)->instr_list)
-#define nir_foreach_instr_reverse(block, instr) \
+#define nir_foreach_instr_reverse(instr, block) \
    foreach_list_typed_reverse(nir_instr, instr, node, &(block)->instr_list)
-#define nir_foreach_instr_safe(block, instr) \
+#define nir_foreach_instr_safe(instr, block) \
    foreach_list_typed_safe(nir_instr, instr, node, &(block)->instr_list)
-#define nir_foreach_instr_reverse_safe(block, instr) \
+#define nir_foreach_instr_reverse_safe(instr, block) \
    foreach_list_typed_reverse_safe(nir_instr, instr, node, &(block)->instr_list)
 
 typedef struct nir_if {
@@ -1544,10 +1552,16 @@ typedef struct {
    nir_metadata valid_metadata;
 } nir_function_impl;
 
-static inline nir_block *
+ATTRIBUTE_RETURNS_NONNULL static inline nir_block *
 nir_start_block(nir_function_impl *impl)
 {
-   return (nir_block *) exec_list_get_head(&impl->body);
+   return (nir_block *) impl->body.head;
+}
+
+ATTRIBUTE_RETURNS_NONNULL static inline nir_block *
+nir_impl_last_block(nir_function_impl *impl)
+{
+   return (nir_block *) impl->body.tail_pred;
 }
 
 static inline nir_cf_node *
@@ -1618,11 +1632,15 @@ typedef struct nir_function {
 typedef struct nir_shader_compiler_options {
    bool lower_fdiv;
    bool lower_ffma;
-   bool lower_flrp;
+   bool fuse_ffma;
+   bool lower_flrp32;
+   /** Lowers flrp when it does not support doubles */
+   bool lower_flrp64;
    bool lower_fpow;
    bool lower_fsat;
    bool lower_fsqrt;
-   bool lower_fmod;
+   bool lower_fmod32;
+   bool lower_fmod64;
    bool lower_bitfield_extract;
    bool lower_bitfield_insert;
    bool lower_uadd_carry;
@@ -1687,6 +1705,8 @@ typedef struct nir_shader_info {
 
    /* Which inputs are actually read */
    uint64_t inputs_read;
+   /* Which inputs are actually read and are double */
+   uint64_t double_inputs_read;
    /* Which outputs are actually written */
    uint64_t outputs_written;
    /* Which system values are actually read */
@@ -1700,6 +1720,9 @@ typedef struct nir_shader_info {
    /* Whether or not this shader ever uses textureGather() */
    bool uses_texture_gather;
 
+   /** Whether or not this shader uses nir_intrinsic_interp_var_at_offset */
+   bool uses_interp_var_at_offset;
+
    /* Whether or not this shader uses the gl_ClipDistance output */
    bool uses_clip_distance_out;
 
@@ -1733,6 +1756,11 @@ typedef struct nir_shader_info {
       struct {
          bool uses_discard;
 
+         /**
+          * Whether any inputs are declared with the "sample" qualifier.
+          */
+         bool uses_sample_qualifier;
+
          /**
           * Whether early fragment tests are enabled as defined by
           * ARB_shader_image_load_store.
@@ -1812,7 +1840,7 @@ nir_shader_get_entrypoint(nir_shader *shader)
    return func;
 }
 
-#define nir_foreach_function(shader, func) \
+#define nir_foreach_function(func, shader) \
    foreach_list_typed(nir_function, func, node, &(shader)->functions)
 
 nir_shader *nir_shader_create(void *mem_ctx,
@@ -2010,7 +2038,7 @@ nir_after_cf_node_and_phis(nir_cf_node *node)
    nir_block *block = nir_cf_node_as_block(nir_cf_node_next(node));
    assert(block->cf_node.type == nir_cf_node_block);
 
-   nir_foreach_instr(block, instr) {
+   nir_foreach_instr(instr, block) {
       if (instr->type != nir_instr_type_phi)
          return nir_before_instr(instr);
    }
@@ -2119,14 +2147,57 @@ void nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src);
 void nir_ssa_def_rewrite_uses_after(nir_ssa_def *def, nir_src new_src,
                                     nir_instr *after_me);
 
-/* visits basic blocks in source-code order */
-typedef bool (*nir_foreach_block_cb)(nir_block *block, void *state);
-bool nir_foreach_block_call(nir_function_impl *impl, nir_foreach_block_cb cb,
-                       void *state);
-bool nir_foreach_block_reverse_call(nir_function_impl *impl, nir_foreach_block_cb cb,
-                               void *state);
-bool nir_foreach_block_in_cf_node_call(nir_cf_node *node, nir_foreach_block_cb cb,
-                                  void *state);
+uint8_t nir_ssa_def_components_read(nir_ssa_def *def);
+
+/*
+ * finds the next basic block in source-code order, returns NULL if there is
+ * none
+ */
+
+nir_block *nir_block_cf_tree_next(nir_block *block);
+
+/* Performs the opposite of nir_block_cf_tree_next() */
+
+nir_block *nir_block_cf_tree_prev(nir_block *block);
+
+/* Gets the first block in a CF node in source-code order */
+
+nir_block *nir_cf_node_cf_tree_first(nir_cf_node *node);
+
+/* Gets the last block in a CF node in source-code order */
+
+nir_block *nir_cf_node_cf_tree_last(nir_cf_node *node);
+
+/* Gets the next block after a CF node in source-code order */
+
+nir_block *nir_cf_node_cf_tree_next(nir_cf_node *node);
+
+/* Macros for loops that visit blocks in source-code order */
+
+#define nir_foreach_block(block, impl) \
+   for (nir_block *block = nir_start_block(impl); block != NULL; \
+        block = nir_block_cf_tree_next(block))
+
+#define nir_foreach_block_safe(block, impl) \
+   for (nir_block *block = nir_start_block(impl), \
+        *next = nir_block_cf_tree_next(block); \
+        block != NULL; \
+        block = next, next = nir_block_cf_tree_next(block))
+
+#define nir_foreach_block_reverse(block, impl) \
+   for (nir_block *block = nir_impl_last_block(impl); block != NULL; \
+        block = nir_block_cf_tree_prev(block))
+
+#define nir_foreach_block_reverse_safe(block, impl) \
+   for (nir_block *block = nir_impl_last_block(impl), \
+        *prev = nir_block_cf_tree_prev(block); \
+        block != NULL; \
+        block = prev, prev = nir_block_cf_tree_prev(block))
+
+#define nir_foreach_block_in_cf_node(block, node) \
+   for (nir_block *block = nir_cf_node_cf_tree_first(node); \
+        block != nir_cf_node_cf_tree_next(node); \
+        block = nir_block_cf_tree_next(block))
 
 /* If the following CF node is an if, this function returns that if.
  * Otherwise, it returns NULL.
@@ -2143,6 +2214,7 @@ unsigned nir_index_instrs(nir_function_impl *impl);
 void nir_index_blocks(nir_function_impl *impl);
 
 void nir_print_shader(nir_shader *shader, FILE *fp);
+void nir_print_shader_annotated(nir_shader *shader, FILE *fp, struct hash_table *errors);
 void nir_print_instr(const nir_instr *instr, FILE *fp);
 
 nir_shader *nir_shader_clone(void *mem_ctx, const nir_shader *s);
@@ -2227,8 +2299,9 @@ bool nir_lower_indirect_derefs(nir_shader *shader, nir_variable_mode modes);
 
 bool nir_lower_locals_to_regs(nir_shader *shader);
 
-void nir_lower_outputs_to_temporaries(nir_shader *shader,
-                                      nir_function *entrypoint);
+void nir_lower_io_to_temporaries(nir_shader *shader, nir_function *entrypoint,
+                                 bool outputs, bool inputs);
+
 void nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint);
 
 void nir_assign_var_locations(struct exec_list *var_list,
@@ -2241,6 +2314,7 @@ void nir_lower_io(nir_shader *shader,
 nir_src *nir_get_io_offset_src(nir_intrinsic_instr *instr);
 nir_src *nir_get_io_vertex_index_src(nir_intrinsic_instr *instr);
 
+void nir_lower_io_types(nir_shader *shader);
 void nir_lower_vars_to_ssa(nir_shader *shader);
 
 bool nir_remove_dead_variables(nir_shader *shader, nir_variable_mode modes);
@@ -2271,6 +2345,13 @@ typedef struct nir_lower_tex_options {
     */
    bool lower_rect;
 
+   /**
+    * If true, convert yuv to rgb.
+    */
+   unsigned lower_y_uv_external;
+   unsigned lower_y_u_v_external;
+   unsigned lower_yx_xuxv_external;
+
    /**
     * To emulate certain texture wrap modes, this can be used
     * to saturate the specified tex coord to [0.0, 1.0].  The
@@ -2313,19 +2394,68 @@ typedef struct nir_lower_tex_options {
 bool nir_lower_tex(nir_shader *shader,
                    const nir_lower_tex_options *options);
 
-void nir_lower_idiv(nir_shader *shader);
+bool nir_lower_idiv(nir_shader *shader);
 
 void nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables);
 void nir_lower_clip_fs(nir_shader *shader, unsigned ucp_enables);
 
 void nir_lower_two_sided_color(nir_shader *shader);
 
+void nir_lower_clamp_color_outputs(nir_shader *shader);
+
+void nir_lower_passthrough_edgeflags(nir_shader *shader);
+
+typedef struct nir_lower_wpos_ytransform_options {
+   int state_tokens[5];
+   bool fs_coord_origin_upper_left :1;
+   bool fs_coord_origin_lower_left :1;
+   bool fs_coord_pixel_center_integer :1;
+   bool fs_coord_pixel_center_half_integer :1;
+} nir_lower_wpos_ytransform_options;
+
+bool nir_lower_wpos_ytransform(nir_shader *shader,
+                               const nir_lower_wpos_ytransform_options *options);
+bool nir_lower_wpos_center(nir_shader *shader);
+
+typedef struct nir_lower_drawpixels_options {
+   int texcoord_state_tokens[5];
+   int scale_state_tokens[5];
+   int bias_state_tokens[5];
+   unsigned drawpix_sampler;
+   unsigned pixelmap_sampler;
+   bool pixel_maps :1;
+   bool scale_and_bias :1;
+} nir_lower_drawpixels_options;
+
+void nir_lower_drawpixels(nir_shader *shader,
+                          const nir_lower_drawpixels_options *options);
+
+typedef struct nir_lower_bitmap_options {
+   unsigned sampler;
+   bool swizzle_xxxx;
+} nir_lower_bitmap_options;
+
+void nir_lower_bitmap(nir_shader *shader, const nir_lower_bitmap_options *options);
+
 void nir_lower_atomics(nir_shader *shader,
                        const struct gl_shader_program *shader_program);
 void nir_lower_to_source_mods(nir_shader *shader);
 
 bool nir_lower_gs_intrinsics(nir_shader *shader);
 
+typedef enum {
+   nir_lower_drcp = (1 << 0),
+   nir_lower_dsqrt = (1 << 1),
+   nir_lower_drsq = (1 << 2),
+   nir_lower_dtrunc = (1 << 3),
+   nir_lower_dfloor = (1 << 4),
+   nir_lower_dceil = (1 << 5),
+   nir_lower_dfract = (1 << 6),
+   nir_lower_dround_even = (1 << 7),
+   nir_lower_dmod = (1 << 8)
+} nir_lower_doubles_options;
+
+void nir_lower_doubles(nir_shader *shader, nir_lower_doubles_options options);
 void nir_lower_double_pack(nir_shader *shader);
 
 bool nir_normalize_cubemap_coords(nir_shader *shader);