radeonsi: split the shader key into 3 logical parts
authorMarek Olšák <marek.olsak@amd.com>
Sun, 13 Nov 2016 02:17:46 +0000 (03:17 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 21 Nov 2016 20:44:35 +0000 (21:44 +0100)
key->part.*: prolog and epilog flags only
key->as_{ls,es}: special flags
key->mono.*: flags for monolithic compilation only

Tested-by: Edmondo Tommasina <edmondo.tommasina@gmail.com>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader.h
src/gallium/drivers/radeonsi/si_state.c
src/gallium/drivers/radeonsi/si_state_shaders.c

index df2f130..847281e 100644 (file)
@@ -463,9 +463,9 @@ static inline struct si_shader* si_get_vs_state(struct si_context *sctx)
 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;
+               return shader->key.part.vs.epilog.export_prim_id;
        else if (shader->selector->type == PIPE_SHADER_TESS_EVAL)
-               return shader->key.tes.epilog.export_prim_id;
+               return shader->key.part.tes.epilog.export_prim_id;
        else
                return false;
 }
index 608cb72..a3388bd 100644 (file)
@@ -68,7 +68,7 @@ static void si_llvm_emit_barrier(const struct lp_build_tgsi_action *action,
                                 struct lp_build_tgsi_context *bld_base,
                                 struct lp_build_emit_data *emit_data);
 
-static void si_dump_shader_key(unsigned shader, union si_shader_key *key,
+static void si_dump_shader_key(unsigned shader, struct si_shader_key *key,
                               FILE *f);
 
 static void si_build_vs_prolog_function(struct si_shader_context *ctx,
@@ -416,7 +416,7 @@ static void declare_input_vs(
                                                    input, llvm_chan, "");
        }
 
-       fix_fetch = (ctx->shader->key.vs.fix_fetch >> (2 * input_index)) & 3;
+       fix_fetch = (ctx->shader->key.mono.vs.fix_fetch >> (2 * input_index)) & 3;
        if (fix_fetch) {
                /* The hardware returns an unsigned value; convert it to a
                 * signed one.
@@ -1252,7 +1252,7 @@ static void interp_fs_input(struct si_shader_context *ctx,
        intr_name = interp_param ? "llvm.SI.fs.interp" : "llvm.SI.fs.constant";
 
        if (semantic_name == TGSI_SEMANTIC_COLOR &&
-           ctx->shader->key.ps.prolog.color_two_side) {
+           ctx->shader->key.part.ps.prolog.color_two_side) {
                LLVMValueRef args[4];
                LLVMValueRef is_face_positive;
                LLVMValueRef back_attr_number;
@@ -1360,7 +1360,7 @@ static void declare_input_fs(
 
        if (decl->Semantic.Name == TGSI_SEMANTIC_COLOR &&
            decl->Interp.Interpolate == TGSI_INTERPOLATE_COLOR &&
-           ctx->shader->key.ps.prolog.flatshade_colors)
+           ctx->shader->key.part.ps.prolog.flatshade_colors)
                interp_param = NULL; /* load the constant color */
 
        interp_fs_input(ctx, input_index, decl->Semantic.Name,
@@ -1832,13 +1832,13 @@ static void si_llvm_init_export_args(struct lp_build_tgsi_context *bld_base,
        args[3] = lp_build_const_int32(base->gallivm, target);
 
        if (ctx->type == PIPE_SHADER_FRAGMENT) {
-               const union si_shader_key *key = &ctx->shader->key;
-               unsigned col_formats = key->ps.epilog.spi_shader_col_format;
+               const struct si_shader_key *key = &ctx->shader->key;
+               unsigned col_formats = key->part.ps.epilog.spi_shader_col_format;
                int cbuf = target - V_008DFC_SQ_EXP_MRT;
 
                assert(cbuf >= 0 && cbuf < 8);
                spi_shader_col_format = (col_formats >> (cbuf * 4)) & 0xf;
-               is_int8 = (key->ps.epilog.color_is_int8 >> cbuf) & 0x1;
+               is_int8 = (key->part.ps.epilog.color_is_int8 >> cbuf) & 0x1;
        }
 
        args[4] = uint->zero; /* COMPR flag */
@@ -1991,13 +1991,13 @@ static void si_alpha_test(struct lp_build_tgsi_context *bld_base,
        struct si_shader_context *ctx = si_shader_context(bld_base);
        struct gallivm_state *gallivm = bld_base->base.gallivm;
 
-       if (ctx->shader->key.ps.epilog.alpha_func != PIPE_FUNC_NEVER) {
+       if (ctx->shader->key.part.ps.epilog.alpha_func != PIPE_FUNC_NEVER) {
                LLVMValueRef alpha_ref = LLVMGetParam(ctx->main_fn,
                                SI_PARAM_ALPHA_REF);
 
                LLVMValueRef alpha_pass =
                        lp_build_cmp(&bld_base->base,
-                                    ctx->shader->key.ps.epilog.alpha_func,
+                                    ctx->shader->key.part.ps.epilog.alpha_func,
                                     alpha, alpha_ref);
                LLVMValueRef arg =
                        lp_build_select(&bld_base->base,
@@ -2440,7 +2440,7 @@ static void si_copy_tcs_inputs(struct lp_build_tgsi_context *bld_base)
        lds_base = get_tcs_in_current_patch_offset(ctx);
        lds_base = LLVMBuildAdd(gallivm->builder, lds_base, lds_vertex_offset, "");
 
-       inputs = ctx->shader->key.tcs.epilog.inputs_to_copy;
+       inputs = ctx->shader->key.mono.tcs.inputs_to_copy;
        while (inputs) {
                unsigned i = u_bit_scan64(&inputs);
 
@@ -2487,7 +2487,7 @@ static void si_write_tess_factors(struct lp_build_tgsi_context *bld_base,
                                  invocation_id, bld_base->uint_bld.zero, ""));
 
        /* Determine the layout of one tess factor element in the buffer. */
-       switch (shader->key.tcs.epilog.prim_mode) {
+       switch (shader->key.part.tcs.epilog.prim_mode) {
        case PIPE_PRIM_LINES:
                stride = 2; /* 2 dwords, 1 vec2 store */
                outer_comps = 2;
@@ -2874,31 +2874,31 @@ static void si_export_mrt_color(struct lp_build_tgsi_context *bld_base,
        int i;
 
        /* Clamp color */
-       if (ctx->shader->key.ps.epilog.clamp_color)
+       if (ctx->shader->key.part.ps.epilog.clamp_color)
                for (i = 0; i < 4; i++)
                        color[i] = si_llvm_saturate(bld_base, color[i]);
 
        /* Alpha to one */
-       if (ctx->shader->key.ps.epilog.alpha_to_one)
+       if (ctx->shader->key.part.ps.epilog.alpha_to_one)
                color[3] = base->one;
 
        /* Alpha test */
        if (index == 0 &&
-           ctx->shader->key.ps.epilog.alpha_func != PIPE_FUNC_ALWAYS)
+           ctx->shader->key.part.ps.epilog.alpha_func != PIPE_FUNC_ALWAYS)
                si_alpha_test(bld_base, color[3]);
 
        /* Line & polygon smoothing */
-       if (ctx->shader->key.ps.epilog.poly_line_smoothing)
+       if (ctx->shader->key.part.ps.epilog.poly_line_smoothing)
                color[3] = si_scale_alpha_by_sample_mask(bld_base, color[3],
                                                         samplemask_param);
 
        /* If last_cbuf > 0, FS_COLOR0_WRITES_ALL_CBUFS is true. */
-       if (ctx->shader->key.ps.epilog.last_cbuf > 0) {
+       if (ctx->shader->key.part.ps.epilog.last_cbuf > 0) {
                LLVMValueRef args[8][9];
                int c, last = -1;
 
                /* Get the export arguments, also find out what the last one is. */
-               for (c = 0; c <= ctx->shader->key.ps.epilog.last_cbuf; c++) {
+               for (c = 0; c <= ctx->shader->key.part.ps.epilog.last_cbuf; c++) {
                        si_llvm_init_export_args(bld_base, color,
                                                 V_008DFC_SQ_EXP_MRT + c, args[c]);
                        if (args[c][0] != bld_base->uint_bld.zero)
@@ -2906,7 +2906,7 @@ static void si_export_mrt_color(struct lp_build_tgsi_context *bld_base,
                }
 
                /* Emit all exports. */
-               for (c = 0; c <= ctx->shader->key.ps.epilog.last_cbuf; c++) {
+               for (c = 0; c <= ctx->shader->key.part.ps.epilog.last_cbuf; c++) {
                        if (is_last && last == c) {
                                args[c][1] = bld_base->uint_bld.one; /* whether the EXEC mask is valid */
                                args[c][2] = bld_base->uint_bld.one; /* DONE bit */
@@ -5347,9 +5347,9 @@ static void create_function(struct si_shader_context *ctx)
                params[SI_PARAM_DRAWID] = ctx->i32;
                num_params = SI_PARAM_DRAWID+1;
 
-               if (shader->key.vs.as_es) {
+               if (shader->key.as_es) {
                        params[ctx->param_es2gs_offset = num_params++] = ctx->i32;
-               } else if (shader->key.vs.as_ls) {
+               } else if (shader->key.as_ls) {
                        params[SI_PARAM_LS_OUT_LAYOUT] = ctx->i32;
                        num_params = SI_PARAM_LS_OUT_LAYOUT+1;
                } else {
@@ -5383,7 +5383,7 @@ static void create_function(struct si_shader_context *ctx)
                        num_prolog_vgprs += shader->selector->info.num_inputs;
 
                        /* PrimitiveID output. */
-                       if (!shader->key.vs.as_es && !shader->key.vs.as_ls)
+                       if (!shader->key.as_es && !shader->key.as_ls)
                                for (i = 0; i <= VS_EPILOG_PRIMID_LOC; i++)
                                        returns[num_returns++] = ctx->f32;
                }
@@ -5417,7 +5417,7 @@ static void create_function(struct si_shader_context *ctx)
                params[SI_PARAM_TCS_OFFCHIP_LAYOUT] = ctx->i32;
                num_params = SI_PARAM_TCS_OFFCHIP_LAYOUT+1;
 
-               if (shader->key.tes.as_es) {
+               if (shader->key.as_es) {
                        params[ctx->param_oc_lds = num_params++] = ctx->i32;
                        params[ctx->param_tess_offchip = num_params++] = ctx->i32;
                        params[ctx->param_es2gs_offset = num_params++] = ctx->i32;
@@ -5436,7 +5436,7 @@ static void create_function(struct si_shader_context *ctx)
                params[ctx->param_tes_patch_id = num_params++] = ctx->i32;
 
                /* PrimitiveID output. */
-               if (!shader->key.tes.as_es)
+               if (!shader->key.as_es)
                        for (i = 0; i <= VS_EPILOG_PRIMID_LOC; i++)
                                returns[num_returns++] = ctx->f32;
                break;
@@ -5590,7 +5590,7 @@ static void create_function(struct si_shader_context *ctx)
                                                    "ddxy_lds",
                                                    LOCAL_ADDR_SPACE);
 
-       if ((ctx->type == PIPE_SHADER_VERTEX && shader->key.vs.as_ls) ||
+       if ((ctx->type == PIPE_SHADER_VERTEX && shader->key.as_ls) ||
            ctx->type == PIPE_SHADER_TESS_CTRL ||
            ctx->type == PIPE_SHADER_TESS_EVAL)
                declare_tess_lds(ctx);
@@ -5609,9 +5609,9 @@ static void preload_ring_buffers(struct si_shader_context *ctx)
                                            SI_PARAM_RW_BUFFERS);
 
        if ((ctx->type == PIPE_SHADER_VERTEX &&
-            ctx->shader->key.vs.as_es) ||
+            ctx->shader->key.as_es) ||
            (ctx->type == PIPE_SHADER_TESS_EVAL &&
-            ctx->shader->key.tes.as_es) ||
+            ctx->shader->key.as_es) ||
            ctx->type == PIPE_SHADER_GEOMETRY) {
                unsigned ring =
                        ctx->type == PIPE_SHADER_GEOMETRY ? SI_GS_RING_ESGS
@@ -5976,16 +5976,16 @@ static const char *si_get_shader_name(struct si_shader *shader,
 {
        switch (processor) {
        case PIPE_SHADER_VERTEX:
-               if (shader->key.vs.as_es)
+               if (shader->key.as_es)
                        return "Vertex Shader as ES";
-               else if (shader->key.vs.as_ls)
+               else if (shader->key.as_ls)
                        return "Vertex Shader as LS";
                else
                        return "Vertex Shader as VS";
        case PIPE_SHADER_TESS_CTRL:
                return "Tessellation Control Shader";
        case PIPE_SHADER_TESS_EVAL:
-               if (shader->key.tes.as_es)
+               if (shader->key.as_es)
                        return "Tessellation Evaluation Shader as ES";
                else
                        return "Tessellation Evaluation Shader as VS";
@@ -6227,7 +6227,7 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
        return shader;
 }
 
-static void si_dump_shader_key(unsigned shader, union si_shader_key *key,
+static void si_dump_shader_key(unsigned shader, struct si_shader_key *key,
                               FILE *f)
 {
        int i;
@@ -6236,23 +6236,23 @@ static void si_dump_shader_key(unsigned shader, union si_shader_key *key,
 
        switch (shader) {
        case PIPE_SHADER_VERTEX:
-               fprintf(f, "  instance_divisors = {");
-               for (i = 0; i < ARRAY_SIZE(key->vs.prolog.instance_divisors); i++)
+               fprintf(f, "  part.vs.prolog.instance_divisors = {");
+               for (i = 0; i < ARRAY_SIZE(key->part.vs.prolog.instance_divisors); i++)
                        fprintf(f, !i ? "%u" : ", %u",
-                               key->vs.prolog.instance_divisors[i]);
+                               key->part.vs.prolog.instance_divisors[i]);
                fprintf(f, "}\n");
-               fprintf(f, "  as_es = %u\n", key->vs.as_es);
-               fprintf(f, "  as_ls = %u\n", key->vs.as_ls);
-               fprintf(f, "  export_prim_id = %u\n", key->vs.epilog.export_prim_id);
+               fprintf(f, "  part.vs.epilog.export_prim_id = %u\n", key->part.vs.epilog.export_prim_id);
+               fprintf(f, "  as_es = %u\n", key->as_es);
+               fprintf(f, "  as_ls = %u\n", key->as_ls);
                break;
 
        case PIPE_SHADER_TESS_CTRL:
-               fprintf(f, "  prim_mode = %u\n", key->tcs.epilog.prim_mode);
+               fprintf(f, "  part.tcs.epilog.prim_mode = %u\n", key->part.tcs.epilog.prim_mode);
                break;
 
        case PIPE_SHADER_TESS_EVAL:
-               fprintf(f, "  as_es = %u\n", key->tes.as_es);
-               fprintf(f, "  export_prim_id = %u\n", key->tes.epilog.export_prim_id);
+               fprintf(f, "  part.tes.epilog.export_prim_id = %u\n", key->part.tes.epilog.export_prim_id);
+               fprintf(f, "  as_es = %u\n", key->as_es);
                break;
 
        case PIPE_SHADER_GEOMETRY:
@@ -6260,22 +6260,22 @@ static void si_dump_shader_key(unsigned shader, union si_shader_key *key,
                break;
 
        case PIPE_SHADER_FRAGMENT:
-               fprintf(f, "  prolog.color_two_side = %u\n", key->ps.prolog.color_two_side);
-               fprintf(f, "  prolog.flatshade_colors = %u\n", key->ps.prolog.flatshade_colors);
-               fprintf(f, "  prolog.poly_stipple = %u\n", key->ps.prolog.poly_stipple);
-               fprintf(f, "  prolog.force_persp_sample_interp = %u\n", key->ps.prolog.force_persp_sample_interp);
-               fprintf(f, "  prolog.force_linear_sample_interp = %u\n", key->ps.prolog.force_linear_sample_interp);
-               fprintf(f, "  prolog.force_persp_center_interp = %u\n", key->ps.prolog.force_persp_center_interp);
-               fprintf(f, "  prolog.force_linear_center_interp = %u\n", key->ps.prolog.force_linear_center_interp);
-               fprintf(f, "  prolog.bc_optimize_for_persp = %u\n", key->ps.prolog.bc_optimize_for_persp);
-               fprintf(f, "  prolog.bc_optimize_for_linear = %u\n", key->ps.prolog.bc_optimize_for_linear);
-               fprintf(f, "  epilog.spi_shader_col_format = 0x%x\n", key->ps.epilog.spi_shader_col_format);
-               fprintf(f, "  epilog.color_is_int8 = 0x%X\n", key->ps.epilog.color_is_int8);
-               fprintf(f, "  epilog.last_cbuf = %u\n", key->ps.epilog.last_cbuf);
-               fprintf(f, "  epilog.alpha_func = %u\n", key->ps.epilog.alpha_func);
-               fprintf(f, "  epilog.alpha_to_one = %u\n", key->ps.epilog.alpha_to_one);
-               fprintf(f, "  epilog.poly_line_smoothing = %u\n", key->ps.epilog.poly_line_smoothing);
-               fprintf(f, "  epilog.clamp_color = %u\n", key->ps.epilog.clamp_color);
+               fprintf(f, "  part.ps.prolog.color_two_side = %u\n", key->part.ps.prolog.color_two_side);
+               fprintf(f, "  part.ps.prolog.flatshade_colors = %u\n", key->part.ps.prolog.flatshade_colors);
+               fprintf(f, "  part.ps.prolog.poly_stipple = %u\n", key->part.ps.prolog.poly_stipple);
+               fprintf(f, "  part.ps.prolog.force_persp_sample_interp = %u\n", key->part.ps.prolog.force_persp_sample_interp);
+               fprintf(f, "  part.ps.prolog.force_linear_sample_interp = %u\n", key->part.ps.prolog.force_linear_sample_interp);
+               fprintf(f, "  part.ps.prolog.force_persp_center_interp = %u\n", key->part.ps.prolog.force_persp_center_interp);
+               fprintf(f, "  part.ps.prolog.force_linear_center_interp = %u\n", key->part.ps.prolog.force_linear_center_interp);
+               fprintf(f, "  part.ps.prolog.bc_optimize_for_persp = %u\n", key->part.ps.prolog.bc_optimize_for_persp);
+               fprintf(f, "  part.ps.prolog.bc_optimize_for_linear = %u\n", key->part.ps.prolog.bc_optimize_for_linear);
+               fprintf(f, "  part.ps.epilog.spi_shader_col_format = 0x%x\n", key->part.ps.epilog.spi_shader_col_format);
+               fprintf(f, "  part.ps.epilog.color_is_int8 = 0x%X\n", key->part.ps.epilog.color_is_int8);
+               fprintf(f, "  part.ps.epilog.last_cbuf = %u\n", key->part.ps.epilog.last_cbuf);
+               fprintf(f, "  part.ps.epilog.alpha_func = %u\n", key->part.ps.epilog.alpha_func);
+               fprintf(f, "  part.ps.epilog.alpha_to_one = %u\n", key->part.ps.epilog.alpha_to_one);
+               fprintf(f, "  part.ps.epilog.poly_line_smoothing = %u\n", key->part.ps.epilog.poly_line_smoothing);
+               fprintf(f, "  part.ps.epilog.clamp_color = %u\n", key->part.ps.epilog.clamp_color);
                break;
 
        default:
@@ -6427,9 +6427,7 @@ static void si_eliminate_const_vs_outputs(struct si_shader_context *ctx)
 
        exports.num = 0;
 
-       if ((ctx->type == PIPE_SHADER_VERTEX &&
-            (shader->key.vs.as_es || shader->key.vs.as_ls)) ||
-           (ctx->type == PIPE_SHADER_TESS_EVAL && shader->key.tes.as_es))
+       if (shader->key.as_es || shader->key.as_ls)
                return;
 
        /* Process all LLVM instructions. */
@@ -6519,9 +6517,9 @@ static bool si_compile_tgsi_main(struct si_shader_context *ctx,
        switch (ctx->type) {
        case PIPE_SHADER_VERTEX:
                ctx->load_input = declare_input_vs;
-               if (shader->key.vs.as_ls)
+               if (shader->key.as_ls)
                        bld_base->emit_epilogue = si_llvm_emit_ls_epilogue;
-               else if (shader->key.vs.as_es)
+               else if (shader->key.as_es)
                        bld_base->emit_epilogue = si_llvm_emit_es_epilogue;
                else
                        bld_base->emit_epilogue = si_llvm_emit_vs_epilogue;
@@ -6534,7 +6532,7 @@ static bool si_compile_tgsi_main(struct si_shader_context *ctx,
                break;
        case PIPE_SHADER_TESS_EVAL:
                bld_base->emit_fetch_funcs[TGSI_FILE_INPUT] = fetch_input_tes;
-               if (shader->key.tes.as_es)
+               if (shader->key.as_es)
                        bld_base->emit_epilogue = si_llvm_emit_es_epilogue;
                else
                        bld_base->emit_epilogue = si_llvm_emit_vs_epilogue;
@@ -6587,7 +6585,7 @@ static void si_get_vs_prolog_key(struct si_shader *shader,
        struct tgsi_shader_info *info = &shader->selector->info;
 
        memset(key, 0, sizeof(*key));
-       key->vs_prolog.states = shader->key.vs.prolog;
+       key->vs_prolog.states = shader->key.part.vs.prolog;
        key->vs_prolog.num_input_sgprs = shader->info.num_input_sgprs;
        key->vs_prolog.last_input = MAX2(1, info->num_inputs) - 1;
 
@@ -6609,7 +6607,7 @@ static void si_get_vs_epilog_key(struct si_shader *shader,
        key->vs_epilog.states = *states;
 
        /* Set up the PrimitiveID output. */
-       if (shader->key.vs.epilog.export_prim_id) {
+       if (shader->key.part.vs.epilog.export_prim_id) {
                unsigned index = shader->selector->info.num_outputs;
                unsigned offset = shader->info.nr_param_exports++;
 
@@ -6630,7 +6628,7 @@ static void si_get_ps_prolog_key(struct si_shader *shader,
        struct tgsi_shader_info *info = &shader->selector->info;
 
        memset(key, 0, sizeof(*key));
-       key->ps_prolog.states = shader->key.ps.prolog;
+       key->ps_prolog.states = shader->key.part.ps.prolog;
        key->ps_prolog.colors_read = info->colors_read;
        key->ps_prolog.num_input_sgprs = shader->info.num_input_sgprs;
        key->ps_prolog.num_input_vgprs = shader->info.num_input_vgprs;
@@ -6646,7 +6644,7 @@ static void si_get_ps_prolog_key(struct si_shader *shader,
        if (info->colors_read) {
                unsigned *color = shader->selector->color_attr_index;
 
-               if (shader->key.ps.prolog.color_two_side) {
+               if (shader->key.part.ps.prolog.color_two_side) {
                        /* BCOLORs are stored after the last input. */
                        key->ps_prolog.num_interp_inputs = info->num_inputs;
                        key->ps_prolog.face_vgpr_index = shader->info.face_vgpr_index;
@@ -6662,7 +6660,7 @@ static void si_get_ps_prolog_key(struct si_shader *shader,
 
                        key->ps_prolog.color_attr_index[i] = color[i];
 
-                       if (shader->key.ps.prolog.flatshade_colors &&
+                       if (shader->key.part.ps.prolog.flatshade_colors &&
                            interp == TGSI_INTERPOLATE_COLOR)
                                interp = TGSI_INTERPOLATE_CONSTANT;
 
@@ -6673,9 +6671,9 @@ static void si_get_ps_prolog_key(struct si_shader *shader,
                        case TGSI_INTERPOLATE_PERSPECTIVE:
                        case TGSI_INTERPOLATE_COLOR:
                                /* Force the interpolation location for colors here. */
-                               if (shader->key.ps.prolog.force_persp_sample_interp)
+                               if (shader->key.part.ps.prolog.force_persp_sample_interp)
                                        location = TGSI_INTERPOLATE_LOC_SAMPLE;
-                               if (shader->key.ps.prolog.force_persp_center_interp)
+                               if (shader->key.part.ps.prolog.force_persp_center_interp)
                                        location = TGSI_INTERPOLATE_LOC_CENTER;
 
                                switch (location) {
@@ -6700,9 +6698,9 @@ static void si_get_ps_prolog_key(struct si_shader *shader,
                                break;
                        case TGSI_INTERPOLATE_LINEAR:
                                /* Force the interpolation location for colors here. */
-                               if (shader->key.ps.prolog.force_linear_sample_interp)
+                               if (shader->key.part.ps.prolog.force_linear_sample_interp)
                                        location = TGSI_INTERPOLATE_LOC_SAMPLE;
-                               if (shader->key.ps.prolog.force_linear_center_interp)
+                               if (shader->key.part.ps.prolog.force_linear_center_interp)
                                        location = TGSI_INTERPOLATE_LOC_CENTER;
 
                                /* The VGPR assignment for non-monolithic shaders
@@ -6767,7 +6765,7 @@ static void si_get_ps_epilog_key(struct si_shader *shader,
        key->ps_epilog.writes_z = info->writes_z;
        key->ps_epilog.writes_stencil = info->writes_stencil;
        key->ps_epilog.writes_samplemask = info->writes_samplemask;
-       key->ps_epilog.states = shader->key.ps.epilog;
+       key->ps_epilog.states = shader->key.part.ps.epilog;
 }
 
 /**
@@ -7077,7 +7075,7 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
                bool need_epilog;
 
                need_prolog = sel->info.num_inputs;
-               need_epilog = !shader->key.vs.as_es && !shader->key.vs.as_ls;
+               need_epilog = !shader->key.as_es && !shader->key.as_ls;
 
                parts[need_prolog ? 1 : 0] = ctx.main_fn;
 
@@ -7090,7 +7088,7 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
 
                if (need_epilog) {
                        union si_shader_part_key epilog_key;
-                       si_get_vs_epilog_key(shader, &shader->key.vs.epilog, &epilog_key);
+                       si_get_vs_epilog_key(shader, &shader->key.part.vs.epilog, &epilog_key);
                        si_build_vs_epilog_function(&ctx, &epilog_key);
                        parts[need_prolog ? 2 : 1] = ctx.main_fn;
                }
@@ -7104,19 +7102,19 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
                parts[0] = ctx.main_fn;
 
                memset(&epilog_key, 0, sizeof(epilog_key));
-               epilog_key.tcs_epilog.states = shader->key.tcs.epilog;
+               epilog_key.tcs_epilog.states = shader->key.part.tcs.epilog;
                si_build_tcs_epilog_function(&ctx, &epilog_key);
                parts[1] = ctx.main_fn;
 
                si_build_wrapper_function(&ctx, parts, 2, 0);
        } else if (is_monolithic && ctx.type == PIPE_SHADER_TESS_EVAL &&
-                  !shader->key.tes.as_es) {
+                  !shader->key.as_es) {
                LLVMValueRef parts[2];
                union si_shader_part_key epilog_key;
 
                parts[0] = ctx.main_fn;
 
-               si_get_vs_epilog_key(shader, &shader->key.tes.epilog, &epilog_key);
+               si_get_vs_epilog_key(shader, &shader->key.part.tes.epilog, &epilog_key);
                si_build_vs_epilog_function(&ctx, &epilog_key);
                parts[1] = ctx.main_fn;
 
@@ -7128,7 +7126,7 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
                parts[1] = ctx.main_fn;
 
                memset(&prolog_key, 0, sizeof(prolog_key));
-               prolog_key.gs_prolog.states = shader->key.gs.prolog;
+               prolog_key.gs_prolog.states = shader->key.part.gs.prolog;
                si_build_gs_prolog_function(&ctx, &prolog_key);
                parts[0] = ctx.main_fn;
 
@@ -7319,16 +7317,16 @@ si_get_shader_part(struct si_screen *sscreen,
                break;
        case PIPE_SHADER_TESS_CTRL:
                assert(!prolog);
-               shader.key.tcs.epilog = key->tcs_epilog.states;
+               shader.key.part.tcs.epilog = key->tcs_epilog.states;
                break;
        case PIPE_SHADER_GEOMETRY:
                assert(prolog);
                break;
        case PIPE_SHADER_FRAGMENT:
                if (prolog)
-                       shader.key.ps.prolog = key->ps_prolog.states;
+                       shader.key.part.ps.prolog = key->ps_prolog.states;
                else
-                       shader.key.ps.epilog = key->ps_epilog.states;
+                       shader.key.part.ps.epilog = key->ps_epilog.states;
                break;
        default:
                unreachable("bad shader part");
@@ -7556,9 +7554,9 @@ static bool si_shader_select_vs_parts(struct si_screen *sscreen,
        }
 
        /* Get the epilog. */
-       if (!shader->key.vs.as_es && !shader->key.vs.as_ls &&
+       if (!shader->key.as_es && !shader->key.as_ls &&
            !si_get_vs_epilog(sscreen, tm, shader, debug,
-                             &shader->key.vs.epilog))
+                             &shader->key.part.vs.epilog))
                return false;
 
        return true;
@@ -7572,12 +7570,12 @@ static bool si_shader_select_tes_parts(struct si_screen *sscreen,
                                       struct si_shader *shader,
                                       struct pipe_debug_callback *debug)
 {
-       if (shader->key.tes.as_es)
+       if (shader->key.as_es)
                return true;
 
        /* TES compiled as VS. */
        return si_get_vs_epilog(sscreen, tm, shader, debug,
-                               &shader->key.tes.epilog);
+                               &shader->key.part.tes.epilog);
 }
 
 /**
@@ -7637,7 +7635,7 @@ static bool si_shader_select_tcs_parts(struct si_screen *sscreen,
 
        /* Get the epilog. */
        memset(&epilog_key, 0, sizeof(epilog_key));
-       epilog_key.tcs_epilog.states = shader->key.tcs.epilog;
+       epilog_key.tcs_epilog.states = shader->key.part.tcs.epilog;
 
        shader->epilog = si_get_shader_part(sscreen, &sscreen->tcs_epilogs,
                                            PIPE_SHADER_TESS_CTRL, false,
@@ -7657,11 +7655,11 @@ static bool si_shader_select_gs_parts(struct si_screen *sscreen,
 {
        union si_shader_part_key prolog_key;
 
-       if (!shader->key.gs.prolog.tri_strip_adj_fix)
+       if (!shader->key.part.gs.prolog.tri_strip_adj_fix)
                return true;
 
        memset(&prolog_key, 0, sizeof(prolog_key));
-       prolog_key.gs_prolog.states = shader->key.gs.prolog;
+       prolog_key.gs_prolog.states = shader->key.part.gs.prolog;
 
        shader->prolog = si_get_shader_part(sscreen, &sscreen->gs_prologs,
                                            PIPE_SHADER_GEOMETRY, true,
@@ -8057,34 +8055,34 @@ static bool si_shader_select_ps_parts(struct si_screen *sscreen,
                return false;
 
        /* Enable POS_FIXED_PT if polygon stippling is enabled. */
-       if (shader->key.ps.prolog.poly_stipple) {
+       if (shader->key.part.ps.prolog.poly_stipple) {
                shader->config.spi_ps_input_ena |= S_0286CC_POS_FIXED_PT_ENA(1);
                assert(G_0286CC_POS_FIXED_PT_ENA(shader->config.spi_ps_input_addr));
        }
 
        /* Set up the enable bits for per-sample shading if needed. */
-       if (shader->key.ps.prolog.force_persp_sample_interp &&
+       if (shader->key.part.ps.prolog.force_persp_sample_interp &&
            (G_0286CC_PERSP_CENTER_ENA(shader->config.spi_ps_input_ena) ||
             G_0286CC_PERSP_CENTROID_ENA(shader->config.spi_ps_input_ena))) {
                shader->config.spi_ps_input_ena &= C_0286CC_PERSP_CENTER_ENA;
                shader->config.spi_ps_input_ena &= C_0286CC_PERSP_CENTROID_ENA;
                shader->config.spi_ps_input_ena |= S_0286CC_PERSP_SAMPLE_ENA(1);
        }
-       if (shader->key.ps.prolog.force_linear_sample_interp &&
+       if (shader->key.part.ps.prolog.force_linear_sample_interp &&
            (G_0286CC_LINEAR_CENTER_ENA(shader->config.spi_ps_input_ena) ||
             G_0286CC_LINEAR_CENTROID_ENA(shader->config.spi_ps_input_ena))) {
                shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_CENTER_ENA;
                shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_CENTROID_ENA;
                shader->config.spi_ps_input_ena |= S_0286CC_LINEAR_SAMPLE_ENA(1);
        }
-       if (shader->key.ps.prolog.force_persp_center_interp &&
+       if (shader->key.part.ps.prolog.force_persp_center_interp &&
            (G_0286CC_PERSP_SAMPLE_ENA(shader->config.spi_ps_input_ena) ||
             G_0286CC_PERSP_CENTROID_ENA(shader->config.spi_ps_input_ena))) {
                shader->config.spi_ps_input_ena &= C_0286CC_PERSP_SAMPLE_ENA;
                shader->config.spi_ps_input_ena &= C_0286CC_PERSP_CENTROID_ENA;
                shader->config.spi_ps_input_ena |= S_0286CC_PERSP_CENTER_ENA(1);
        }
-       if (shader->key.ps.prolog.force_linear_center_interp &&
+       if (shader->key.part.ps.prolog.force_linear_center_interp &&
            (G_0286CC_LINEAR_SAMPLE_ENA(shader->config.spi_ps_input_ena) ||
             G_0286CC_LINEAR_CENTROID_ENA(shader->config.spi_ps_input_ena))) {
                shader->config.spi_ps_input_ena &= C_0286CC_LINEAR_SAMPLE_ENA;
@@ -8108,7 +8106,7 @@ static bool si_shader_select_ps_parts(struct si_screen *sscreen,
        /* The sample mask input is always enabled, because the API shader always
         * passes it through to the epilog. Disable it here if it's unused.
         */
-       if (!shader->key.ps.epilog.poly_line_smoothing &&
+       if (!shader->key.part.ps.epilog.poly_line_smoothing &&
            !shader->selector->info.reads_samplemask)
                shader->config.spi_ps_input_ena &= C_0286CC_SAMPLE_COVERAGE_ENA;
 
@@ -8137,14 +8135,12 @@ int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
         * workaround must be applied.
         */
        if (!mainp ||
+           shader->key.as_es != mainp->key.as_es ||
+           shader->key.as_ls != mainp->key.as_ls ||
            (sel->type == PIPE_SHADER_VERTEX &&
-            (shader->key.vs.as_es != mainp->key.vs.as_es ||
-             shader->key.vs.as_ls != mainp->key.vs.as_ls ||
-             shader->key.vs.fix_fetch)) ||
-           (sel->type == PIPE_SHADER_TESS_EVAL &&
-            shader->key.tes.as_es != mainp->key.tes.as_es) ||
+            shader->key.mono.vs.fix_fetch) ||
            (sel->type == PIPE_SHADER_TESS_CTRL &&
-            shader->key.tcs.epilog.inputs_to_copy) ||
+            shader->key.mono.tcs.inputs_to_copy) ||
            sel->type == PIPE_SHADER_COMPUTE) {
                /* Monolithic shader (compiled as a whole, has many variants,
                 * may take a long time to compile).
index 59e7bfb..bed22c1 100644 (file)
@@ -330,7 +330,6 @@ struct si_vs_epilog_bits {
 /* Common TCS bits between the shader key and the epilog key. */
 struct si_tcs_epilog_bits {
        unsigned        prim_mode:3;
-       uint64_t        inputs_to_copy;
 };
 
 struct si_gs_prolog_bits {
@@ -398,30 +397,44 @@ 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 */
-
-               /* One pair of bits for every input: SI_FIX_FETCH_* enums. */
-               uint32_t        fix_fetch;
-       } 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 {
-               struct si_gs_prolog_bits prolog;
-       } gs;
+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 pair of bits for every input: SI_FIX_FETCH_* enums. */
+                       uint32_t        fix_fetch;
+               } vs;
+               struct {
+                       uint64_t        inputs_to_copy; /* for fixed-func TCS */
+               } tcs;
+       } mono;
 };
 
 struct si_shader_config {
@@ -470,7 +483,7 @@ struct si_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;
        bool                            is_binary_shared;
        bool                            is_gs_copy_shader;
 
index 4a41aa8..096c641 100644 (file)
@@ -119,7 +119,7 @@ static void si_emit_cb_render_state(struct si_context *sctx, struct r600_atom *a
        if (sctx->b.family == CHIP_STONEY) {
                unsigned spi_shader_col_format =
                        sctx->ps_shader.cso ?
-                       sctx->ps_shader.current->key.ps.epilog.spi_shader_col_format : 0;
+                       sctx->ps_shader.current->key.part.ps.epilog.spi_shader_col_format : 0;
                unsigned sx_ps_downconvert = 0;
                unsigned sx_blend_opt_epsilon = 0;
                unsigned sx_blend_opt_control = 0;
index d0869e3..3323d3c 100644 (file)
@@ -626,7 +626,7 @@ static unsigned si_get_ps_num_interp(struct si_shader *ps)
        unsigned num_colors = !!(info->colors_read & 0x0f) +
                              !!(info->colors_read & 0xf0);
        unsigned num_interp = ps->selector->info.num_inputs +
-                             (ps->key.ps.prolog.color_two_side ? num_colors : 0);
+                             (ps->key.part.ps.prolog.color_two_side ? num_colors : 0);
 
        assert(num_interp <= 32);
        return MIN2(num_interp, 32);
@@ -634,7 +634,7 @@ static unsigned si_get_ps_num_interp(struct si_shader *ps)
 
 static unsigned si_get_spi_shader_col_format(struct si_shader *shader)
 {
-       unsigned value = shader->key.ps.epilog.spi_shader_col_format;
+       unsigned value = shader->key.part.ps.epilog.spi_shader_col_format;
        unsigned i, num_targets = (util_last_bit(value) + 3) / 4;
 
        /* If the i-th target format is set, all previous target formats must
@@ -705,30 +705,30 @@ static void si_shader_ps(struct si_shader *shader)
               G_0286CC_PERSP_PULL_MODEL_ENA(input_ena));
 
        /* Validate interpolation optimization flags (read as implications). */
-       assert(!shader->key.ps.prolog.bc_optimize_for_persp ||
+       assert(!shader->key.part.ps.prolog.bc_optimize_for_persp ||
               (G_0286CC_PERSP_CENTER_ENA(input_ena) &&
                G_0286CC_PERSP_CENTROID_ENA(input_ena)));
-       assert(!shader->key.ps.prolog.bc_optimize_for_linear ||
+       assert(!shader->key.part.ps.prolog.bc_optimize_for_linear ||
               (G_0286CC_LINEAR_CENTER_ENA(input_ena) &&
                G_0286CC_LINEAR_CENTROID_ENA(input_ena)));
-       assert(!shader->key.ps.prolog.force_persp_center_interp ||
+       assert(!shader->key.part.ps.prolog.force_persp_center_interp ||
               (!G_0286CC_PERSP_SAMPLE_ENA(input_ena) &&
                !G_0286CC_PERSP_CENTROID_ENA(input_ena)));
-       assert(!shader->key.ps.prolog.force_linear_center_interp ||
+       assert(!shader->key.part.ps.prolog.force_linear_center_interp ||
               (!G_0286CC_LINEAR_SAMPLE_ENA(input_ena) &&
                !G_0286CC_LINEAR_CENTROID_ENA(input_ena)));
-       assert(!shader->key.ps.prolog.force_persp_sample_interp ||
+       assert(!shader->key.part.ps.prolog.force_persp_sample_interp ||
               (!G_0286CC_PERSP_CENTER_ENA(input_ena) &&
                !G_0286CC_PERSP_CENTROID_ENA(input_ena)));
-       assert(!shader->key.ps.prolog.force_linear_sample_interp ||
+       assert(!shader->key.part.ps.prolog.force_linear_sample_interp ||
               (!G_0286CC_LINEAR_CENTER_ENA(input_ena) &&
                !G_0286CC_LINEAR_CENTROID_ENA(input_ena)));
 
        /* Validate cases when the optimizations are off (read as implications). */
-       assert(shader->key.ps.prolog.bc_optimize_for_persp ||
+       assert(shader->key.part.ps.prolog.bc_optimize_for_persp ||
               !G_0286CC_PERSP_CENTER_ENA(input_ena) ||
               !G_0286CC_PERSP_CENTROID_ENA(input_ena));
-       assert(shader->key.ps.prolog.bc_optimize_for_linear ||
+       assert(shader->key.part.ps.prolog.bc_optimize_for_linear ||
               !G_0286CC_LINEAR_CENTER_ENA(input_ena) ||
               !G_0286CC_LINEAR_CENTROID_ENA(input_ena));
 
@@ -818,9 +818,9 @@ static void si_shader_init_pm4_state(struct si_screen *sscreen,
 {
        switch (shader->selector->type) {
        case PIPE_SHADER_VERTEX:
-               if (shader->key.vs.as_ls)
+               if (shader->key.as_ls)
                        si_shader_ls(shader);
-               else if (shader->key.vs.as_es)
+               else if (shader->key.as_es)
                        si_shader_es(sscreen, shader);
                else
                        si_shader_vs(sscreen, shader, NULL);
@@ -829,7 +829,7 @@ static void si_shader_init_pm4_state(struct si_screen *sscreen,
                si_shader_hs(shader);
                break;
        case PIPE_SHADER_TESS_EVAL:
-               if (shader->key.tes.as_es)
+               if (shader->key.as_es)
                        si_shader_es(sscreen, shader);
                else
                        si_shader_vs(sscreen, shader, NULL);
@@ -857,7 +857,7 @@ static unsigned si_get_alpha_test_func(struct si_context *sctx)
 /* Compute the key for the hw shader variant */
 static inline void si_shader_selector_key(struct pipe_context *ctx,
                                          struct si_shader_selector *sel,
-                                         union si_shader_key *key)
+                                         struct si_shader_key *key)
 {
        struct si_context *sctx = (struct si_context *)ctx;
        unsigned i;
@@ -870,37 +870,37 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
                        unsigned count = MIN2(sel->info.num_inputs,
                                              sctx->vertex_elements->count);
                        for (i = 0; i < count; ++i)
-                               key->vs.prolog.instance_divisors[i] =
+                               key->part.vs.prolog.instance_divisors[i] =
                                        sctx->vertex_elements->elements[i].instance_divisor;
 
-                       key->vs.fix_fetch =
+                       key->mono.vs.fix_fetch =
                                sctx->vertex_elements->fix_fetch &
                                u_bit_consecutive(0, 2 * count);
                }
                if (sctx->tes_shader.cso)
-                       key->vs.as_ls = 1;
+                       key->as_ls = 1;
                else if (sctx->gs_shader.cso)
-                       key->vs.as_es = 1;
+                       key->as_es = 1;
 
                if (!sctx->gs_shader.cso && sctx->ps_shader.cso &&
                    sctx->ps_shader.cso->info.uses_primid)
-                       key->vs.epilog.export_prim_id = 1;
+                       key->part.vs.epilog.export_prim_id = 1;
                break;
        case PIPE_SHADER_TESS_CTRL:
-               key->tcs.epilog.prim_mode =
+               key->part.tcs.epilog.prim_mode =
                        sctx->tes_shader.cso->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];
 
                if (sel == sctx->fixed_func_tcs_shader.cso)
-                       key->tcs.epilog.inputs_to_copy = sctx->vs_shader.cso->outputs_written;
+                       key->mono.tcs.inputs_to_copy = sctx->vs_shader.cso->outputs_written;
                break;
        case PIPE_SHADER_TESS_EVAL:
                if (sctx->gs_shader.cso)
-                       key->tes.as_es = 1;
+                       key->as_es = 1;
                else if (sctx->ps_shader.cso && sctx->ps_shader.cso->info.uses_primid)
-                       key->tes.epilog.export_prim_id = 1;
+                       key->part.tes.epilog.export_prim_id = 1;
                break;
        case PIPE_SHADER_GEOMETRY:
-               key->gs.prolog.tri_strip_adj_fix = sctx->gs_tri_strip_adj_fix;
+               key->part.gs.prolog.tri_strip_adj_fix = sctx->gs_tri_strip_adj_fix;
                break;
        case PIPE_SHADER_FRAGMENT: {
                struct si_state_rasterizer *rs = sctx->queued.named.rasterizer;
@@ -908,13 +908,13 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
 
                if (sel->info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS] &&
                    sel->info.colors_written == 0x1)
-                       key->ps.epilog.last_cbuf = MAX2(sctx->framebuffer.state.nr_cbufs, 1) - 1;
+                       key->part.ps.epilog.last_cbuf = MAX2(sctx->framebuffer.state.nr_cbufs, 1) - 1;
 
                if (blend) {
                        /* Select the shader color format based on whether
                         * blending or alpha are needed.
                         */
-                       key->ps.epilog.spi_shader_col_format =
+                       key->part.ps.epilog.spi_shader_col_format =
                                (blend->blend_enable_4bit & blend->need_src_alpha_4bit &
                                 sctx->framebuffer.spi_shader_col_format_blend_alpha) |
                                (blend->blend_enable_4bit & ~blend->need_src_alpha_4bit &
@@ -928,29 +928,29 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
                         * the same format as the first output.
                         */
                        if (blend->dual_src_blend)
-                               key->ps.epilog.spi_shader_col_format |=
-                                       (key->ps.epilog.spi_shader_col_format & 0xf) << 4;
+                               key->part.ps.epilog.spi_shader_col_format |=
+                                       (key->part.ps.epilog.spi_shader_col_format & 0xf) << 4;
                } else
-                       key->ps.epilog.spi_shader_col_format = sctx->framebuffer.spi_shader_col_format;
+                       key->part.ps.epilog.spi_shader_col_format = sctx->framebuffer.spi_shader_col_format;
 
                /* If alpha-to-coverage is enabled, we have to export alpha
                 * even if there is no color buffer.
                 */
-               if (!(key->ps.epilog.spi_shader_col_format & 0xf) &&
+               if (!(key->part.ps.epilog.spi_shader_col_format & 0xf) &&
                    blend && blend->alpha_to_coverage)
-                       key->ps.epilog.spi_shader_col_format |= V_028710_SPI_SHADER_32_AR;
+                       key->part.ps.epilog.spi_shader_col_format |= V_028710_SPI_SHADER_32_AR;
 
                /* On SI and CIK except Hawaii, the CB doesn't clamp outputs
                 * to the range supported by the type if a channel has less
                 * than 16 bits and the export format is 16_ABGR.
                 */
                if (sctx->b.chip_class <= CIK && sctx->b.family != CHIP_HAWAII)
-                       key->ps.epilog.color_is_int8 = sctx->framebuffer.color_is_int8;
+                       key->part.ps.epilog.color_is_int8 = sctx->framebuffer.color_is_int8;
 
                /* Disable unwritten outputs (if WRITE_ALL_CBUFS isn't enabled). */
-               if (!key->ps.epilog.last_cbuf) {
-                       key->ps.epilog.spi_shader_col_format &= sel->colors_written_4bit;
-                       key->ps.epilog.color_is_int8 &= sel->info.colors_written;
+               if (!key->part.ps.epilog.last_cbuf) {
+                       key->part.ps.epilog.spi_shader_col_format &= sel->colors_written_4bit;
+                       key->part.ps.epilog.color_is_int8 &= sel->info.colors_written;
                }
 
                if (rs) {
@@ -959,55 +959,55 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
                                       sctx->current_rast_prim >= PIPE_PRIM_TRIANGLES_ADJACENCY;
                        bool is_line = !is_poly && sctx->current_rast_prim != PIPE_PRIM_POINTS;
 
-                       key->ps.prolog.color_two_side = rs->two_side && sel->info.colors_read;
-                       key->ps.prolog.flatshade_colors = rs->flatshade && sel->info.colors_read;
+                       key->part.ps.prolog.color_two_side = rs->two_side && sel->info.colors_read;
+                       key->part.ps.prolog.flatshade_colors = rs->flatshade && sel->info.colors_read;
 
                        if (sctx->queued.named.blend) {
-                               key->ps.epilog.alpha_to_one = sctx->queued.named.blend->alpha_to_one &&
+                               key->part.ps.epilog.alpha_to_one = sctx->queued.named.blend->alpha_to_one &&
                                                              rs->multisample_enable;
                        }
 
-                       key->ps.prolog.poly_stipple = rs->poly_stipple_enable && is_poly;
-                       key->ps.epilog.poly_line_smoothing = ((is_poly && rs->poly_smooth) ||
+                       key->part.ps.prolog.poly_stipple = rs->poly_stipple_enable && is_poly;
+                       key->part.ps.epilog.poly_line_smoothing = ((is_poly && rs->poly_smooth) ||
                                                              (is_line && rs->line_smooth)) &&
                                                             sctx->framebuffer.nr_samples <= 1;
-                       key->ps.epilog.clamp_color = rs->clamp_fragment_color;
+                       key->part.ps.epilog.clamp_color = rs->clamp_fragment_color;
 
                        if (rs->force_persample_interp &&
                            rs->multisample_enable &&
                            sctx->framebuffer.nr_samples > 1 &&
                            sctx->ps_iter_samples > 1) {
-                               key->ps.prolog.force_persp_sample_interp =
+                               key->part.ps.prolog.force_persp_sample_interp =
                                        sel->info.uses_persp_center ||
                                        sel->info.uses_persp_centroid;
 
-                               key->ps.prolog.force_linear_sample_interp =
+                               key->part.ps.prolog.force_linear_sample_interp =
                                        sel->info.uses_linear_center ||
                                        sel->info.uses_linear_centroid;
                        } else if (rs->multisample_enable &&
                                   sctx->framebuffer.nr_samples > 1) {
-                               key->ps.prolog.bc_optimize_for_persp =
+                               key->part.ps.prolog.bc_optimize_for_persp =
                                        sel->info.uses_persp_center &&
                                        sel->info.uses_persp_centroid;
-                               key->ps.prolog.bc_optimize_for_linear =
+                               key->part.ps.prolog.bc_optimize_for_linear =
                                        sel->info.uses_linear_center &&
                                        sel->info.uses_linear_centroid;
                        } else {
                                /* Make sure SPI doesn't compute more than 1 pair
                                 * of (i,j), which is the optimization here. */
-                               key->ps.prolog.force_persp_center_interp =
+                               key->part.ps.prolog.force_persp_center_interp =
                                        sel->info.uses_persp_center +
                                        sel->info.uses_persp_centroid +
                                        sel->info.uses_persp_sample > 1;
 
-                               key->ps.prolog.force_linear_center_interp =
+                               key->part.ps.prolog.force_linear_center_interp =
                                        sel->info.uses_linear_center +
                                        sel->info.uses_linear_centroid +
                                        sel->info.uses_linear_sample > 1;
                        }
                }
 
-               key->ps.epilog.alpha_func = si_get_alpha_test_func(sctx);
+               key->part.ps.epilog.alpha_func = si_get_alpha_test_func(sctx);
                break;
        }
        default:
@@ -1018,7 +1018,7 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
 /* Select the hw shader variant depending on the current state. */
 static int si_shader_select_with_key(struct si_screen *sscreen,
                                     struct si_shader_ctx_state *state,
-                                    union si_shader_key *key,
+                                    struct si_shader_key *key,
                                     LLVMTargetMachineRef tm,
                                     struct pipe_debug_callback *debug,
                                     bool wait,
@@ -1101,7 +1101,7 @@ static int si_shader_select(struct pipe_context *ctx,
                            struct si_shader_ctx_state *state)
 {
        struct si_context *sctx = (struct si_context *)ctx;
-       union si_shader_key key;
+       struct si_shader_key key;
 
        si_shader_selector_key(ctx, state->cso, &key);
        return si_shader_select_with_key(sctx->screen, state, &key,
@@ -1110,7 +1110,7 @@ static int si_shader_select(struct pipe_context *ctx,
 }
 
 static void si_parse_next_shader_property(const struct tgsi_shader_info *info,
-                                         union si_shader_key *key)
+                                         struct si_shader_key *key)
 {
        unsigned next_shader = info->properties[TGSI_PROPERTY_NEXT_SHADER];
 
@@ -1118,11 +1118,11 @@ static void si_parse_next_shader_property(const struct tgsi_shader_info *info,
        case PIPE_SHADER_VERTEX:
                switch (next_shader) {
                case PIPE_SHADER_GEOMETRY:
-                       key->vs.as_es = 1;
+                       key->as_es = 1;
                        break;
                case PIPE_SHADER_TESS_CTRL:
                case PIPE_SHADER_TESS_EVAL:
-                       key->vs.as_ls = 1;
+                       key->as_ls = 1;
                        break;
                default:
                        /* If POSITION isn't written, it can't be a HW VS.
@@ -1136,7 +1136,7 @@ static void si_parse_next_shader_property(const struct tgsi_shader_info *info,
 
        case PIPE_SHADER_TESS_EVAL:
                if (next_shader == PIPE_SHADER_GEOMETRY)
-                       key->tes.as_es = 1;
+                       key->as_es = 1;
                break;
        }
 }
@@ -1214,7 +1214,7 @@ void si_init_shader_selector_async(void *job, int thread_index)
        /* Pre-compilation. */
        if (sscreen->b.debug_flags & DBG_PRECOMPILE) {
                struct si_shader_ctx_state state = {sel};
-               union si_shader_key key;
+               struct si_shader_key key;
 
                memset(&key, 0, sizeof(key));
                si_parse_next_shader_property(&sel->info, &key);
@@ -1224,19 +1224,19 @@ void si_init_shader_selector_async(void *job, int thread_index)
                 */
                switch (sel->type) {
                case PIPE_SHADER_TESS_CTRL:
-                       key.tcs.epilog.prim_mode = PIPE_PRIM_TRIANGLES;
+                       key.part.tcs.epilog.prim_mode = PIPE_PRIM_TRIANGLES;
                        break;
                case PIPE_SHADER_FRAGMENT:
-                       key.ps.prolog.bc_optimize_for_persp =
+                       key.part.ps.prolog.bc_optimize_for_persp =
                                sel->info.uses_persp_center &&
                                sel->info.uses_persp_centroid;
-                       key.ps.prolog.bc_optimize_for_linear =
+                       key.part.ps.prolog.bc_optimize_for_linear =
                                sel->info.uses_linear_center &&
                                sel->info.uses_linear_centroid;
-                       key.ps.epilog.alpha_func = PIPE_FUNC_ALWAYS;
+                       key.part.ps.epilog.alpha_func = PIPE_FUNC_ALWAYS;
                        for (i = 0; i < 8; i++)
                                if (sel->info.colors_written & (1 << i))
-                                       key.ps.epilog.spi_shader_col_format |=
+                                       key.part.ps.epilog.spi_shader_col_format |=
                                                V_028710_SPI_SHADER_FP16_ABGR << (i * 4);
                        break;
                }
@@ -1521,9 +1521,9 @@ static void si_delete_shader(struct si_context *sctx, struct si_shader *shader)
        if (shader->pm4) {
                switch (shader->selector->type) {
                case PIPE_SHADER_VERTEX:
-                       if (shader->key.vs.as_ls)
+                       if (shader->key.as_ls)
                                si_pm4_delete_state(sctx, ls, shader->pm4);
-                       else if (shader->key.vs.as_es)
+                       else if (shader->key.as_es)
                                si_pm4_delete_state(sctx, es, shader->pm4);
                        else
                                si_pm4_delete_state(sctx, vs, shader->pm4);
@@ -1532,7 +1532,7 @@ static void si_delete_shader(struct si_context *sctx, struct si_shader *shader)
                        si_pm4_delete_state(sctx, hs, shader->pm4);
                        break;
                case PIPE_SHADER_TESS_EVAL:
-                       if (shader->key.tes.as_es)
+                       if (shader->key.as_es)
                                si_pm4_delete_state(sctx, es, shader->pm4);
                        else
                                si_pm4_delete_state(sctx, vs, shader->pm4);
@@ -1673,7 +1673,7 @@ static void si_emit_spi_map(struct si_context *sctx, struct r600_atom *atom)
                }
        }
 
-       if (ps->key.ps.prolog.color_two_side) {
+       if (ps->key.part.ps.prolog.color_two_side) {
                unsigned bcol = TGSI_SEMANTIC_BCOLOR;
 
                for (i = 0; i < 2; i++) {
@@ -2281,8 +2281,8 @@ bool si_update_shaders(struct si_context *sctx)
                        si_mark_atom_dirty(sctx, &sctx->db_render_state);
                }
 
-               if (sctx->smoothing_enabled != sctx->ps_shader.current->key.ps.epilog.poly_line_smoothing) {
-                       sctx->smoothing_enabled = sctx->ps_shader.current->key.ps.epilog.poly_line_smoothing;
+               if (sctx->smoothing_enabled != sctx->ps_shader.current->key.part.ps.epilog.poly_line_smoothing) {
+                       sctx->smoothing_enabled = sctx->ps_shader.current->key.part.ps.epilog.poly_line_smoothing;
                        si_mark_atom_dirty(sctx, &sctx->msaa_config);
 
                        if (sctx->b.chip_class == SI)