Home | History | Annotate | Line # | Download | only in compiler
      1 /*
      2  * Copyright (C) 2018-2021 Alyssa Rosenzweig <alyssa (at) rosenzweig.io>
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  */
     23 
     24 #ifndef __AGX_PUBLIC_H_
     25 #define __AGX_PUBLIC_H_
     26 
     27 #include "compiler/nir/nir.h"
     28 #include "util/u_dynarray.h"
     29 #include "asahi/lib/agx_pack.h"
     30 
     31 enum agx_push_type {
     32    /* Array of 64-bit pointers to the base addresses (BASES) and array of
     33     * 16-bit sizes for optional bounds checking (SIZES) */
     34    AGX_PUSH_UBO_BASES = 0,
     35    AGX_PUSH_UBO_SIZES = 1,
     36    AGX_PUSH_VBO_BASES = 2,
     37    AGX_PUSH_VBO_SIZES = 3,
     38    AGX_PUSH_SSBO_BASES = 4,
     39    AGX_PUSH_SSBO_SIZES = 5,
     40 
     41    /* Push the attached constant memory */
     42    AGX_PUSH_CONSTANTS = 6,
     43 
     44    /* Push the content of a UBO */
     45    AGX_PUSH_UBO_DATA = 7,
     46 
     47    /* RGBA blend constant (FP32) */
     48    AGX_PUSH_BLEND_CONST = 8,
     49 
     50    /* Keep last */
     51    AGX_PUSH_NUM_TYPES
     52 };
     53 
     54 struct agx_push {
     55    /* Contents to push */
     56    enum agx_push_type type : 8;
     57 
     58    /* Base of where to push, indexed in 16-bit units. The uniform file contains
     59     * 512 = 2^9 such units. */
     60    unsigned base : 9;
     61 
     62    /* Number of 16-bit units to push */
     63    unsigned length : 9;
     64 
     65    /* If set, rather than pushing the specified data, push a pointer to the
     66     * specified data. This is slower to access but enables indirect access, as
     67     * the uniform file does not support indirection. */
     68    bool indirect : 1;
     69 
     70    union {
     71       struct {
     72          uint16_t ubo;
     73          uint16_t offset;
     74       } ubo_data;
     75    };
     76 };
     77 
     78 /* Arbitrary */
     79 #define AGX_MAX_PUSH_RANGES (16)
     80 #define AGX_MAX_VARYINGS (32)
     81 
     82 struct agx_varyings {
     83    unsigned nr_descs, nr_slots;
     84    struct agx_varying_packed packed[AGX_MAX_VARYINGS];
     85 };
     86 
     87 struct agx_shader_info {
     88    unsigned push_ranges;
     89    struct agx_push push[AGX_MAX_PUSH_RANGES];
     90    struct agx_varyings varyings;
     91 
     92    /* Does the shader read the tilebuffer? */
     93    bool reads_tib;
     94 
     95    /* Does the shader write point size? */
     96    bool writes_psiz;
     97 };
     98 
     99 #define AGX_MAX_RTS (8)
    100 #define AGX_MAX_ATTRIBS (16)
    101 #define AGX_MAX_VBUFS (16)
    102 
    103 enum agx_format {
    104    AGX_FORMAT_I8 = 0,
    105    AGX_FORMAT_I16 = 1,
    106    AGX_FORMAT_I32 = 2,
    107    AGX_FORMAT_F16 = 3,
    108    AGX_FORMAT_U8NORM = 4,
    109    AGX_FORMAT_S8NORM = 5,
    110    AGX_FORMAT_U16NORM = 6,
    111    AGX_FORMAT_S16NORM = 7,
    112    AGX_FORMAT_RGB10A2 = 8,
    113    AGX_FORMAT_SRGBA8 = 10,
    114    AGX_FORMAT_RG11B10F = 12,
    115    AGX_FORMAT_RGB9E5 = 13,
    116 
    117    /* Keep last */
    118    AGX_NUM_FORMATS,
    119 };
    120 
    121 /* Returns the number of bits at the bottom of the address required to be zero.
    122  * That is, returns the base-2 logarithm of the minimum alignment for an
    123  * agx_format, where the minimum alignment is 2^n where n is the result of this
    124  * function. The offset argument to device_load is left-shifted by this amount
    125  * in the hardware */
    126 
    127 static inline unsigned
    128 agx_format_shift(enum agx_format format)
    129 {
    130    switch (format) {
    131    case AGX_FORMAT_I8:
    132    case AGX_FORMAT_U8NORM:
    133    case AGX_FORMAT_S8NORM:
    134    case AGX_FORMAT_SRGBA8:
    135       return 0;
    136 
    137    case AGX_FORMAT_I16:
    138    case AGX_FORMAT_F16:
    139    case AGX_FORMAT_U16NORM:
    140    case AGX_FORMAT_S16NORM:
    141       return 1;
    142 
    143    case AGX_FORMAT_I32:
    144    case AGX_FORMAT_RGB10A2:
    145    case AGX_FORMAT_RG11B10F:
    146    case AGX_FORMAT_RGB9E5:
    147       return 2;
    148 
    149    default:
    150       unreachable("invalid format");
    151    }
    152 }
    153 
    154 struct agx_attribute {
    155    uint32_t divisor;
    156 
    157    unsigned buf : 5;
    158    unsigned src_offset : 16;
    159    unsigned nr_comps_minus_1 : 2;
    160    enum agx_format format : 4;
    161    unsigned padding : 5;
    162 };
    163 
    164 struct agx_vs_shader_key {
    165    unsigned num_vbufs;
    166    unsigned vbuf_strides[AGX_MAX_VBUFS];
    167 
    168    struct agx_attribute attributes[AGX_MAX_ATTRIBS];
    169 
    170    /* Set to true for clip coordinates to range [0, 1] instead of [-1, 1] */
    171    bool clip_halfz : 1;
    172 };
    173 
    174 struct agx_fs_shader_key {
    175    enum agx_format tib_formats[AGX_MAX_RTS];
    176 };
    177 
    178 struct agx_shader_key {
    179    union {
    180       struct agx_vs_shader_key vs;
    181       struct agx_fs_shader_key fs;
    182    };
    183 };
    184 
    185 void
    186 agx_compile_shader_nir(nir_shader *nir,
    187       struct agx_shader_key *key,
    188       struct util_dynarray *binary,
    189       struct agx_shader_info *out);
    190 
    191 static const nir_shader_compiler_options agx_nir_options = {
    192    .lower_scmp = true,
    193    .lower_flrp16 = true,
    194    .lower_flrp32 = true,
    195    .lower_ffract = true,
    196    .lower_fmod = true,
    197    .lower_fdiv = true,
    198    .lower_isign = true,
    199    .lower_iabs = true,
    200    .lower_fpow = true,
    201    .lower_find_lsb = true,
    202    .lower_ifind_msb = true,
    203    .lower_fdph = true,
    204    .lower_wpos_pntc = true,
    205    .lower_fsign = true,
    206    .lower_rotate = true,
    207    .lower_pack_split = true,
    208    .lower_insert_byte = true,
    209    .lower_insert_word = true,
    210    .lower_uniforms_to_ubo = true,
    211    .lower_cs_local_index_from_id = true,
    212 
    213    .lower_doubles_options = nir_lower_dmod,
    214    .lower_int64_options = ~(nir_lower_iadd64 | nir_lower_imul_2x32_64),
    215 
    216    .force_indirect_unrolling = (nir_var_shader_in | nir_var_shader_out | nir_var_function_temp),
    217 
    218    .has_fsub = true,
    219    .has_isub = true,
    220    .has_cs_global_id = true,
    221 
    222    .vectorize_io = true,
    223    .fuse_ffma16 = true,
    224    .fuse_ffma32 = true,
    225    .use_interpolated_input_intrinsics = true,
    226 };
    227 
    228 #endif
    229