radeonsi: have separate LS and ES main shader parts in the shader selector
[mesa.git] / src / gallium / drivers / radeonsi / si_shader.h
index 7b1cbf9f6b0fbdd2d076a8db0efb5fa0ef72adb7..d4b57c97d59ecf32c2b79fff4bf41064de2b9d51 100644 (file)
@@ -69,7 +69,9 @@
 #define SI_SHADER_H
 
 #include <llvm-c/Core.h> /* LLVMModuleRef */
+#include <llvm-c/TargetMachine.h>
 #include "tgsi/tgsi_scan.h"
+#include "util/u_queue.h"
 #include "si_state.h"
 
 struct radeon_shader_binary;
@@ -96,6 +98,7 @@ enum {
        SI_SGPR_VERTEX_BUFFERS_HI,
        SI_SGPR_BASE_VERTEX,
        SI_SGPR_START_INSTANCE,
+       SI_SGPR_DRAWID,
        SI_ES_NUM_USER_SGPR,
 
        /* hw VS only */
@@ -107,12 +110,13 @@ enum {
        SI_LS_NUM_USER_SGPR,
 
        /* both TCS and TES */
-       SI_SGPR_TCS_OUT_OFFSETS = SI_NUM_RESOURCE_SGPRS,
-       SI_SGPR_TCS_OUT_LAYOUT,
+       SI_SGPR_TCS_OFFCHIP_LAYOUT = SI_NUM_RESOURCE_SGPRS,
        SI_TES_NUM_USER_SGPR,
 
        /* TCS only */
-       SI_SGPR_TCS_IN_LAYOUT = SI_TES_NUM_USER_SGPR,
+       SI_SGPR_TCS_OUT_OFFSETS = SI_TES_NUM_USER_SGPR,
+       SI_SGPR_TCS_OUT_LAYOUT,
+       SI_SGPR_TCS_IN_LAYOUT,
        SI_TCS_NUM_USER_SGPR,
 
        /* GS limits */
@@ -125,7 +129,8 @@ enum {
 
        /* CS only */
        SI_SGPR_GRID_SIZE = SI_NUM_RESOURCE_SGPRS,
-       SI_CS_NUM_USER_SGPR = SI_SGPR_GRID_SIZE + 3
+       SI_SGPR_BLOCK_SIZE = SI_SGPR_GRID_SIZE + 3,
+       SI_CS_NUM_USER_SGPR = SI_SGPR_BLOCK_SIZE + 3
 };
 
 /* LLVM function parameter indices */
@@ -141,32 +146,41 @@ enum {
        SI_PARAM_VERTEX_BUFFERS = SI_NUM_RESOURCE_PARAMS,
        SI_PARAM_BASE_VERTEX,
        SI_PARAM_START_INSTANCE,
+       SI_PARAM_DRAWID,
        /* [0] = clamp vertex color, VS as VS only */
        SI_PARAM_VS_STATE_BITS,
        /* same value as TCS_IN_LAYOUT, VS as LS only */
-       SI_PARAM_LS_OUT_LAYOUT = SI_PARAM_START_INSTANCE + 1,
+       SI_PARAM_LS_OUT_LAYOUT = SI_PARAM_DRAWID + 1,
        /* the other VS parameters are assigned dynamically */
 
+       /* Layout of TCS outputs in the offchip buffer
+        *   [0:8] = the number of patches per threadgroup.
+        *   [9:15] = the number of output vertices per patch.
+        *   [16:31] = the offset of per patch attributes in the buffer in bytes.
+        */
+       SI_PARAM_TCS_OFFCHIP_LAYOUT = SI_NUM_RESOURCE_PARAMS, /* for TCS & TES */
+
+       /* TCS only parameters. */
+
        /* Offsets where TCS outputs and TCS patch outputs live in LDS:
         *   [0:15] = TCS output patch0 offset / 16, max = NUM_PATCHES * 32 * 32
         *   [16:31] = TCS output patch0 offset for per-patch / 16, max = NUM_PATCHES*32*32* + 32*32
         */
-       SI_PARAM_TCS_OUT_OFFSETS = SI_NUM_RESOURCE_PARAMS, /* for TCS & TES */
+       SI_PARAM_TCS_OUT_OFFSETS,
 
        /* Layout of TCS outputs / TES inputs:
         *   [0:12] = stride between output patches in dwords, num_outputs * num_vertices * 4, max = 32*32*4
         *   [13:20] = stride between output vertices in dwords = num_inputs * 4, max = 32*4
         *   [26:31] = gl_PatchVerticesIn, max = 32
         */
-       SI_PARAM_TCS_OUT_LAYOUT, /* for TCS & TES */
+       SI_PARAM_TCS_OUT_LAYOUT,
 
        /* Layout of LS outputs / TCS inputs
         *   [0:12] = stride between patches in dwords = num_inputs * num_vertices * 4, max = 32*32*4
         *   [13:20] = stride between vertices in dwords = num_inputs * 4, max = 32*4
         */
-       SI_PARAM_TCS_IN_LAYOUT,  /* TCS only */
+       SI_PARAM_TCS_IN_LAYOUT,
 
-       /* TCS only parameters. */
        SI_PARAM_TCS_OC_LDS,
        SI_PARAM_TESS_FACTOR_OFFSET,
        SI_PARAM_PATCH_ID,
@@ -206,6 +220,7 @@ enum {
 
        /* CS only parameters */
        SI_PARAM_GRID_SIZE = SI_NUM_RESOURCE_PARAMS,
+       SI_PARAM_BLOCK_SIZE,
        SI_PARAM_BLOCK_ID,
        SI_PARAM_THREAD_ID,
 
@@ -218,12 +233,52 @@ enum {
        TGSI_SEMANTIC_DEFAULT_TESSINNER_SI,
 };
 
+/* For VS shader key fix_fetch. */
+enum {
+       SI_FIX_FETCH_NONE = 0,
+       SI_FIX_FETCH_A2_SNORM,
+       SI_FIX_FETCH_A2_SSCALED,
+       SI_FIX_FETCH_A2_SINT,
+       SI_FIX_FETCH_RGBA_32_UNORM,
+       SI_FIX_FETCH_RGBX_32_UNORM,
+       SI_FIX_FETCH_RGBA_32_SNORM,
+       SI_FIX_FETCH_RGBX_32_SNORM,
+       SI_FIX_FETCH_RGBA_32_USCALED,
+       SI_FIX_FETCH_RGBA_32_SSCALED,
+       SI_FIX_FETCH_RGBA_32_FIXED,
+       SI_FIX_FETCH_RGBX_32_FIXED,
+       SI_FIX_FETCH_RG_64_FLOAT,
+       SI_FIX_FETCH_RGB_64_FLOAT,
+       SI_FIX_FETCH_RGBA_64_FLOAT,
+       SI_FIX_FETCH_RGB_8,     /* A = 1.0 */
+       SI_FIX_FETCH_RGB_8_INT, /* A = 1 */
+       SI_FIX_FETCH_RGB_16,
+       SI_FIX_FETCH_RGB_16_INT,
+};
+
 struct si_shader;
 
+/* State of the context creating the shader object. */
+struct si_compiler_ctx_state {
+       /* Should only be used by si_init_shader_selector_async and
+        * si_build_shader_variant if thread_index == -1 (non-threaded). */
+       LLVMTargetMachineRef            tm;
+
+       /* Used if thread_index == -1 or if debug.async is true. */
+       struct pipe_debug_callback      debug;
+
+       /* Used for creating the log string for gallium/ddebug. */
+       bool                            is_debug_context;
+};
+
 /* A shader selector is a gallium CSO and contains shader variants and
  * binaries for one TGSI program. This can be shared by multiple contexts.
  */
 struct si_shader_selector {
+       struct si_screen        *screen;
+       struct util_queue_fence ready;
+       struct si_compiler_ctx_state compiler_ctx_state;
+
        pipe_mutex              mutex;
        struct si_shader        *first_variant; /* immutable after the first variant */
        struct si_shader        *last_variant; /* mutable */
@@ -232,6 +287,10 @@ struct si_shader_selector {
         * uploaded to a buffer).
         */
        struct si_shader        *main_shader_part;
+       struct si_shader        *main_shader_part_ls; /* as_ls is set in the key */
+       struct si_shader        *main_shader_part_es; /* as_es is set in the key */
+
+       struct si_shader        *gs_copy_shader;
 
        struct tgsi_token       *tokens;
        struct pipe_stream_output_info  so;
@@ -261,9 +320,12 @@ struct si_shader_selector {
        /* CS parameters */
        unsigned local_size;
 
-       /* masks of "get_unique_index" bits */
-       uint64_t        outputs_written;
-       uint32_t        patch_outputs_written;
+       uint64_t        outputs_written;        /* "get_unique_index" bits */
+       uint32_t        patch_outputs_written;  /* "get_unique_index" bits */
+       uint32_t        outputs_written2;       /* "get_unique_index2" bits */
+
+       uint64_t        inputs_read;            /* "get_unique_index" bits */
+       uint32_t        inputs_read2;           /* "get_unique_index2" bits */
 };
 
 /* Valid shader configurations:
@@ -285,12 +347,6 @@ struct si_vs_prolog_bits {
 /* Common VS bits between the shader key and the epilog key. */
 struct si_vs_epilog_bits {
        unsigned        export_prim_id:1; /* when PS needs it and GS is disabled */
-       /* TODO:
-        * - skip clipdist, culldist (including clipvertex code) exports based
-        *   on which clip_plane_enable bits are set
-        * - skip layer, viewport, clipdist, and culldist parameter exports
-        *   if PS doesn't read them
-        */
 };
 
 /* Common TCS bits between the shader key and the epilog key. */
@@ -298,19 +354,21 @@ struct si_tcs_epilog_bits {
        unsigned        prim_mode:3;
 };
 
+struct si_gs_prolog_bits {
+       unsigned        tri_strip_adj_fix:1;
+};
+
 /* Common PS bits between the shader key and the prolog key. */
 struct si_ps_prolog_bits {
        unsigned        color_two_side:1;
-       /* TODO: add a flatshade bit that skips interpolation for colors */
+       unsigned        flatshade_colors:1;
        unsigned        poly_stipple:1;
-       unsigned        force_persample_interp:1;
-       /* TODO:
-        * - add force_center_interp if MSAA is disabled and centroid or
-        *   sample are present
-        * - add force_center_interp_bc_optimize to force center interpolation
-        *   based on the bc_optimize SGPR bit if MSAA is enabled, centroid is
-        *   present and sample isn't present.
-        */
+       unsigned        force_persp_sample_interp:1;
+       unsigned        force_linear_sample_interp:1;
+       unsigned        force_persp_center_interp:1;
+       unsigned        force_linear_center_interp:1;
+       unsigned        bc_optimize_for_persp:1;
+       unsigned        bc_optimize_for_linear:1;
 };
 
 /* Common PS bits between the shader key and the epilog key. */
@@ -337,6 +395,9 @@ union si_shader_part_key {
        struct {
                struct si_tcs_epilog_bits states;
        } tcs_epilog;
+       struct {
+               struct si_gs_prolog_bits states;
+       } gs_prolog;
        struct {
                struct si_ps_prolog_bits states;
                unsigned        num_input_sgprs:5;
@@ -345,6 +406,7 @@ union si_shader_part_key {
                unsigned        colors_read:8; /* color input components read */
                unsigned        num_interp_inputs:5; /* BCOLOR is at this location */
                unsigned        face_vgpr_index:5;
+               unsigned        wqm:1;
                char            color_attr_index[2];
                char            color_interp_vgpr_index[2]; /* -1 == constant */
        } ps_prolog;
@@ -357,29 +419,61 @@ union si_shader_part_key {
        } ps_epilog;
 };
 
-union si_shader_key {
-       struct {
-               struct si_ps_prolog_bits prolog;
-               struct si_ps_epilog_bits epilog;
-       } ps;
-       struct {
-               struct si_vs_prolog_bits prolog;
-               struct si_vs_epilog_bits epilog;
-               unsigned        as_es:1; /* export shader */
-               unsigned        as_ls:1; /* local shader */
-       } vs;
-       struct {
-               struct si_tcs_epilog_bits epilog;
-       } tcs; /* tessellation control shader */
-       struct {
-               struct si_vs_epilog_bits epilog; /* same as VS */
-               unsigned        as_es:1; /* export shader */
-       } tes; /* tessellation evaluation shader */
+struct si_shader_key {
+       /* Prolog and epilog flags. */
+       union {
+               struct {
+                       struct si_ps_prolog_bits prolog;
+                       struct si_ps_epilog_bits epilog;
+               } ps;
+               struct {
+                       struct si_vs_prolog_bits prolog;
+                       struct si_vs_epilog_bits epilog;
+               } vs;
+               struct {
+                       struct si_tcs_epilog_bits epilog;
+               } tcs; /* tessellation control shader */
+               struct {
+                       struct si_vs_epilog_bits epilog; /* same as VS */
+               } tes; /* tessellation evaluation shader */
+               struct {
+                       struct si_gs_prolog_bits prolog;
+               } gs;
+       } part;
+
+       /* These two are initially set according to the NEXT_SHADER property,
+        * or guessed if the property doesn't seem correct.
+        */
+       unsigned as_es:1; /* export shader */
+       unsigned as_ls:1; /* local shader */
+
+       /* Flags for monolithic compilation only. */
+       union {
+               struct {
+                       /* One byte for every input: SI_FIX_FETCH_* enums. */
+                       uint8_t         fix_fetch[SI_MAX_ATTRIBS];
+               } vs;
+               struct {
+                       uint64_t        inputs_to_copy; /* for fixed-func TCS */
+               } tcs;
+       } mono;
+
+       /* Optimization flags for asynchronous compilation only. */
+       union {
+               struct {
+                       uint64_t        kill_outputs; /* "get_unique_index" bits */
+                       uint32_t        kill_outputs2; /* "get_unique_index2" bits */
+                       unsigned        clip_disable:1;
+               } hw_vs; /* HW VS (it can be VS, TES, GS) */
+       } opt;
 };
 
 struct si_shader_config {
        unsigned                        num_sgprs;
        unsigned                        num_vgprs;
+       unsigned                        spilled_sgprs;
+       unsigned                        spilled_vgprs;
+       unsigned                        private_mem_vgprs;
        unsigned                        lds_size;
        unsigned                        spi_ps_input_ena;
        unsigned                        spi_ps_input_addr;
@@ -389,6 +483,18 @@ struct si_shader_config {
        unsigned                        rsrc2;
 };
 
+enum {
+       /* SPI_PS_INPUT_CNTL_i.OFFSET[0:4] */
+       EXP_PARAM_OFFSET_0 = 0,
+       EXP_PARAM_OFFSET_31 = 31,
+       /* SPI_PS_INPUT_CNTL_i.DEFAULT_VAL[0:1] */
+       EXP_PARAM_DEFAULT_VAL_0000 = 64,
+       EXP_PARAM_DEFAULT_VAL_0001,
+       EXP_PARAM_DEFAULT_VAL_1110,
+       EXP_PARAM_DEFAULT_VAL_1111,
+       EXP_PARAM_UNDEFINED = 255,
+};
+
 /* GCN-specific shader info. */
 struct si_shader_info {
        ubyte                   vs_output_param_offset[SI_MAX_VS_OUTPUTS];
@@ -401,24 +507,35 @@ struct si_shader_info {
 };
 
 struct si_shader {
+       struct si_compiler_ctx_state    compiler_ctx_state;
+
        struct si_shader_selector       *selector;
        struct si_shader                *next_variant;
 
        struct si_shader_part           *prolog;
        struct si_shader_part           *epilog;
 
-       struct si_shader                *gs_copy_shader;
        struct si_pm4_state             *pm4;
        struct r600_resource            *bo;
        struct r600_resource            *scratch_bo;
-       union si_shader_key             key;
+       struct si_shader_key            key;
+       struct util_queue_fence         optimized_ready;
+       bool                            compilation_failed;
+       bool                            is_monolithic;
+       bool                            is_optimized;
        bool                            is_binary_shared;
-       unsigned                        z_order;
+       bool                            is_gs_copy_shader;
 
        /* The following data is all that's needed for binary shaders. */
        struct radeon_shader_binary     binary;
        struct si_shader_config         config;
        struct si_shader_info           info;
+
+       /* Shader key + LLVM IR + disassembly + statistics.
+        * Generated for debug contexts only.
+        */
+       char                            *shader_log;
+       size_t                          shader_log_size;
 };
 
 struct si_shader_part {
@@ -428,39 +545,12 @@ struct si_shader_part {
        struct si_shader_config config;
 };
 
-static inline struct tgsi_shader_info *si_get_vs_info(struct si_context *sctx)
-{
-       if (sctx->gs_shader.cso)
-               return &sctx->gs_shader.cso->info;
-       else if (sctx->tes_shader.cso)
-               return &sctx->tes_shader.cso->info;
-       else if (sctx->vs_shader.cso)
-               return &sctx->vs_shader.cso->info;
-       else
-               return NULL;
-}
-
-static inline struct si_shader* si_get_vs_state(struct si_context *sctx)
-{
-       if (sctx->gs_shader.current)
-               return sctx->gs_shader.current->gs_copy_shader;
-       else if (sctx->tes_shader.current)
-               return sctx->tes_shader.current;
-       else
-               return sctx->vs_shader.current;
-}
-
-static inline bool si_vs_exports_prim_id(struct si_shader *shader)
-{
-       if (shader->selector->type == PIPE_SHADER_VERTEX)
-               return shader->key.vs.epilog.export_prim_id;
-       else if (shader->selector->type == PIPE_SHADER_TESS_EVAL)
-               return shader->key.tes.epilog.export_prim_id;
-       else
-               return false;
-}
-
 /* si_shader.c */
+struct si_shader *
+si_generate_gs_copy_shader(struct si_screen *sscreen,
+                          LLVMTargetMachineRef tm,
+                          struct si_shader_selector *gs_selector,
+                          struct pipe_debug_callback *debug);
 int si_compile_tgsi_shader(struct si_screen *sscreen,
                           LLVMTargetMachineRef tm,
                           struct si_shader *shader,
@@ -469,7 +559,6 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
 int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
                     struct si_shader *shader,
                     struct pipe_debug_callback *debug);
-void si_dump_shader_key(unsigned shader, union si_shader_key *key, FILE *f);
 int si_compile_llvm(struct si_screen *sscreen,
                    struct radeon_shader_binary *binary,
                    struct si_shader_config *conf,
@@ -480,10 +569,13 @@ int si_compile_llvm(struct si_screen *sscreen,
                    const char *name);
 void si_shader_destroy(struct si_shader *shader);
 unsigned si_shader_io_get_unique_index(unsigned semantic_name, unsigned index);
+unsigned si_shader_io_get_unique_index2(unsigned name, unsigned index);
 int si_shader_binary_upload(struct si_screen *sscreen, struct si_shader *shader);
 void si_shader_dump(struct si_screen *sscreen, struct si_shader *shader,
                    struct pipe_debug_callback *debug, unsigned processor,
-                   FILE *f);
+                   FILE *f, bool check_debug_option);
+void si_multiwave_lds_size_workaround(struct si_screen *sscreen,
+                                     unsigned *lds_size);
 void si_shader_apply_scratch_relocs(struct si_context *sctx,
                        struct si_shader *shader,
                        struct si_shader_config *config,
@@ -491,5 +583,22 @@ void si_shader_apply_scratch_relocs(struct si_context *sctx,
 void si_shader_binary_read_config(struct radeon_shader_binary *binary,
                                  struct si_shader_config *conf,
                                  unsigned symbol_offset);
+unsigned si_get_spi_shader_z_format(bool writes_z, bool writes_stencil,
+                                   bool writes_samplemask);
+const char *si_get_shader_name(struct si_shader *shader, unsigned processor);
+
+/* Inline helpers. */
+
+/* Return the pointer to the main shader part's pointer. */
+static inline struct si_shader **
+si_get_main_shader_part(struct si_shader_selector *sel,
+                       struct si_shader_key *key)
+{
+       if (key->as_ls)
+               return &sel->main_shader_part_ls;
+       if (key->as_es)
+               return &sel->main_shader_part_es;
+       return &sel->main_shader_part;
+}
 
 #endif