radv/gfx9: fix primitive topology when adjacency is used
[mesa.git] / src / amd / vulkan / radv_pipeline.c
index f23afa42b7022ead428b49cc62aefd172293caa5..14ada20d525c4bf24ed7d04fccee5c411142743c 100644 (file)
@@ -46,6 +46,7 @@
 #include "vk_format.h"
 #include "util/debug.h"
 #include "ac_exp_param.h"
+#include "ac_shader_util.h"
 
 static void
 radv_pipeline_destroy(struct radv_device *device,
@@ -134,7 +135,7 @@ radv_pipeline_scratch_init(struct radv_device *device,
        if (scratch_bytes_per_wave && max_waves < min_waves) {
                /* Not really true at this moment, but will be true on first
                 * execution. Avoid having hanging shaders. */
-               return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+               return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
        }
        pipeline->scratch_bytes_per_wave = scratch_bytes_per_wave;
        pipeline->max_waves = max_waves;
@@ -415,38 +416,6 @@ static unsigned si_choose_spi_color_format(VkFormat vk_format,
                return normal;
 }
 
-static unsigned si_get_cb_shader_mask(unsigned spi_shader_col_format)
-{
-       unsigned i, cb_shader_mask = 0;
-
-       for (i = 0; i < 8; i++) {
-               switch ((spi_shader_col_format >> (i * 4)) & 0xf) {
-               case V_028714_SPI_SHADER_ZERO:
-                       break;
-               case V_028714_SPI_SHADER_32_R:
-                       cb_shader_mask |= 0x1 << (i * 4);
-                       break;
-               case V_028714_SPI_SHADER_32_GR:
-                       cb_shader_mask |= 0x3 << (i * 4);
-                       break;
-               case V_028714_SPI_SHADER_32_AR:
-                       cb_shader_mask |= 0x9 << (i * 4);
-                       break;
-               case V_028714_SPI_SHADER_FP16_ABGR:
-               case V_028714_SPI_SHADER_UNORM16_ABGR:
-               case V_028714_SPI_SHADER_SNORM16_ABGR:
-               case V_028714_SPI_SHADER_UINT16_ABGR:
-               case V_028714_SPI_SHADER_SINT16_ABGR:
-               case V_028714_SPI_SHADER_32_ABGR:
-                       cb_shader_mask |= 0xf << (i * 4);
-                       break;
-               default:
-                       assert(0);
-               }
-       }
-       return cb_shader_mask;
-}
-
 static void
 radv_pipeline_compute_spi_color_formats(struct radv_pipeline *pipeline,
                                        const VkGraphicsPipelineCreateInfo *pCreateInfo,
@@ -476,7 +445,7 @@ radv_pipeline_compute_spi_color_formats(struct radv_pipeline *pipeline,
                col_format |= cf << (4 * i);
        }
 
-       blend->cb_shader_mask = si_get_cb_shader_mask(col_format);
+       blend->cb_shader_mask = ac_get_cb_shader_mask(col_format);
 
        if (blend_mrt0_is_dual_src)
                col_format |= (col_format & 0xf) << 4;
@@ -1019,7 +988,7 @@ static void
 radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline,
                                 const VkGraphicsPipelineCreateInfo *pCreateInfo)
 {
-       radv_cmd_dirty_mask_t states = RADV_CMD_DIRTY_DYNAMIC_ALL;
+       uint32_t states = RADV_CMD_DIRTY_DYNAMIC_ALL;
        RADV_FROM_HANDLE(radv_render_pass, pass, pCreateInfo->renderPass);
        struct radv_subpass *subpass = &pass->subpasses[pCreateInfo->subpass];
 
@@ -1137,31 +1106,9 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline,
                }
        }
 
-       pipeline->dynamic_state_mask = states;
+       pipeline->dynamic_state.mask = states;
 }
 
-static struct ac_shader_variant_key
-radv_compute_vs_key(const VkGraphicsPipelineCreateInfo *pCreateInfo, bool as_es, bool as_ls)
-{
-       struct ac_shader_variant_key key;
-       const VkPipelineVertexInputStateCreateInfo *input_state =
-                                                pCreateInfo->pVertexInputState;
-
-       memset(&key, 0, sizeof(key));
-       key.vs.instance_rate_inputs = 0;
-       key.vs.as_es = as_es;
-       key.vs.as_ls = as_ls;
-
-       for (unsigned i = 0; i < input_state->vertexAttributeDescriptionCount; ++i) {
-               unsigned binding;
-               binding = input_state->pVertexAttributeDescriptions[i].binding;
-               if (input_state->pVertexBindingDescriptions[binding].inputRate)
-                       key.vs.instance_rate_inputs |= 1u << input_state->pVertexAttributeDescriptions[i].location;
-       }
-       return key;
-}
-
-
 static void calculate_gfx9_gs_info(const VkGraphicsPipelineCreateInfo *pCreateInfo,
                                    struct radv_pipeline *pipeline)
 {
@@ -1175,7 +1122,7 @@ static void calculate_gfx9_gs_info(const VkGraphicsPipelineCreateInfo *pCreateIn
        case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
        case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
        case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
-               uses_adjacency = false;
+               uses_adjacency = true;
                break;
        default:
                uses_adjacency = false;
@@ -1312,6 +1259,7 @@ calculate_gs_ring_sizes(struct radv_pipeline *pipeline)
        if (pipeline->device->physical_device->rad_info.chip_class <= VI)
                pipeline->graphics.esgs_ring_size = CLAMP(esgs_ring_size, min_esgs_ring_size, max_size);
 
+       pipeline->graphics.gs.vgt_esgs_ring_itemsize = es_info->esgs_itemsize / 4;
        pipeline->graphics.gsvs_ring_size = MIN2(gsvs_ring_size, max_size);
 }
 
@@ -1517,30 +1465,6 @@ static const struct radv_prim_vertex_count prim_size_table[] = {
        [V_008958_DI_PT_2D_TRI_STRIP] = {0, 0},
 };
 
-static uint32_t si_vgt_gs_mode(struct radv_shader_variant *gs,
-                               enum chip_class chip_class)
-{
-       unsigned gs_max_vert_out = gs->info.gs.vertices_out;
-       unsigned cut_mode;
-
-       if (gs_max_vert_out <= 128) {
-               cut_mode = V_028A40_GS_CUT_128;
-       } else if (gs_max_vert_out <= 256) {
-               cut_mode = V_028A40_GS_CUT_256;
-       } else if (gs_max_vert_out <= 512) {
-               cut_mode = V_028A40_GS_CUT_512;
-       } else {
-               assert(gs_max_vert_out <= 1024);
-               cut_mode = V_028A40_GS_CUT_1024;
-       }
-
-       return S_028A40_MODE(V_028A40_GS_SCENARIO_G) |
-              S_028A40_CUT_MODE(cut_mode)|
-              S_028A40_ES_WRITE_OPTIMIZE(chip_class <= VI) |
-              S_028A40_GS_WRITE_OPTIMIZE(1) |
-              S_028A40_ONCHIP(chip_class >= GFX9 ? 1 : 0);
-}
-
 static struct ac_vs_output_info *get_vs_output_info(struct radv_pipeline *pipeline)
 {
        if (radv_pipeline_has_gs(pipeline))
@@ -1559,15 +1483,19 @@ static void calculate_vgt_gs_mode(struct radv_pipeline *pipeline)
        pipeline->graphics.vgt_gs_mode = 0;
 
        if (radv_pipeline_has_gs(pipeline)) {
-               pipeline->graphics.vgt_gs_mode = si_vgt_gs_mode(pipeline->shaders[MESA_SHADER_GEOMETRY],
-                                                               pipeline->device->physical_device->rad_info.chip_class);
+               struct radv_shader_variant *gs =
+                       pipeline->shaders[MESA_SHADER_GEOMETRY];
+
+               pipeline->graphics.vgt_gs_mode =
+                       ac_vgt_gs_mode(gs->info.gs.vertices_out,
+                                      pipeline->device->physical_device->rad_info.chip_class);
        } else if (outinfo->export_prim_id) {
                pipeline->graphics.vgt_gs_mode = S_028A40_MODE(V_028A40_GS_SCENARIO_A);
                pipeline->graphics.vgt_primitiveid_en = true;
        }
 }
 
-static void calculate_pa_cl_vs_out_cntl(struct radv_pipeline *pipeline)
+static void calculate_vs_outinfo(struct radv_pipeline *pipeline)
 {
        struct ac_vs_output_info *outinfo = get_vs_output_info(pipeline);
 
@@ -1579,7 +1507,7 @@ static void calculate_pa_cl_vs_out_cntl(struct radv_pipeline *pipeline)
        bool misc_vec_ena = outinfo->writes_pointsize ||
                outinfo->writes_layer ||
                outinfo->writes_viewport_index;
-       pipeline->graphics.pa_cl_vs_out_cntl =
+       pipeline->graphics.vs.pa_cl_vs_out_cntl =
                S_02881C_USE_VTX_POINT_SIZE(outinfo->writes_pointsize) |
                S_02881C_USE_VTX_RENDER_TARGET_INDX(outinfo->writes_layer) |
                S_02881C_USE_VTX_VIEWPORT_INDX(outinfo->writes_viewport_index) |
@@ -1590,6 +1518,21 @@ static void calculate_pa_cl_vs_out_cntl(struct radv_pipeline *pipeline)
                cull_dist_mask << 8 |
                clip_dist_mask;
 
+       pipeline->graphics.vs.spi_shader_pos_format =
+               S_02870C_POS0_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
+               S_02870C_POS1_EXPORT_FORMAT(outinfo->pos_exports > 1 ?
+                                           V_02870C_SPI_SHADER_4COMP :
+                                           V_02870C_SPI_SHADER_NONE) |
+               S_02870C_POS2_EXPORT_FORMAT(outinfo->pos_exports > 2 ?
+                                           V_02870C_SPI_SHADER_4COMP :
+                                           V_02870C_SPI_SHADER_NONE) |
+               S_02870C_POS3_EXPORT_FORMAT(outinfo->pos_exports > 3 ?
+                                           V_02870C_SPI_SHADER_4COMP :
+                                           V_02870C_SPI_SHADER_NONE);
+
+       pipeline->graphics.vs.spi_vs_out_config = S_0286C4_VS_EXPORT_COUNT(MAX2(1, outinfo->param_exports) - 1);
+       /* only emitted on pre-VI */
+       pipeline->graphics.vs.vgt_reuse_off = S_028AB4_REUSE_OFF(outinfo->writes_viewport_index);
 }
 
 static uint32_t offset_to_ps_input(uint32_t offset, bool flat_shade)
@@ -1688,6 +1631,9 @@ radv_link_shaders(struct radv_pipeline *pipeline, nir_shader **shaders)
        }
 
        for (int i = 1; i < shader_count; ++i)  {
+               nir_lower_io_arrays_to_elements(ordered_shaders[i],
+                                               ordered_shaders[i - 1]);
+
                nir_remove_dead_variables(ordered_shaders[i],
                                          nir_var_shader_out);
                nir_remove_dead_variables(ordered_shaders[i - 1],
@@ -1705,11 +1651,116 @@ radv_link_shaders(struct radv_pipeline *pipeline, nir_shader **shaders)
        }
 }
 
+
+static struct radv_pipeline_key
+radv_generate_graphics_pipeline_key(struct radv_pipeline *pipeline,
+                                    const VkGraphicsPipelineCreateInfo *pCreateInfo,
+                                    bool has_view_index)
+{
+       const VkPipelineVertexInputStateCreateInfo *input_state =
+                                                pCreateInfo->pVertexInputState;
+       struct radv_pipeline_key key;
+       memset(&key, 0, sizeof(key));
+
+       key.has_multiview_view_index = has_view_index;
+
+       for (unsigned i = 0; i < input_state->vertexAttributeDescriptionCount; ++i) {
+               unsigned binding;
+               binding = input_state->pVertexAttributeDescriptions[i].binding;
+               if (input_state->pVertexBindingDescriptions[binding].inputRate)
+                       key.instance_rate_inputs |= 1u << input_state->pVertexAttributeDescriptions[i].location;
+       }
+
+       if (pCreateInfo->pTessellationState)
+               key.tess_input_vertices = pCreateInfo->pTessellationState->patchControlPoints;
+
+
+       if (pCreateInfo->pMultisampleState &&
+           pCreateInfo->pMultisampleState->rasterizationSamples > 1)
+               key.multisample = true;
+
+       key.col_format = pipeline->graphics.blend.spi_shader_col_format;
+       if (pipeline->device->physical_device->rad_info.chip_class < VI)
+               radv_pipeline_compute_get_int_clamp(pCreateInfo, &key.is_int8, &key.is_int10);
+
+       return key;
+}
+
+static void
+radv_fill_shader_keys(struct ac_shader_variant_key *keys,
+                      const struct radv_pipeline_key *key,
+                      nir_shader **nir)
+{
+       keys[MESA_SHADER_VERTEX].vs.instance_rate_inputs = key->instance_rate_inputs;
+
+       if (nir[MESA_SHADER_TESS_CTRL]) {
+               keys[MESA_SHADER_VERTEX].vs.as_ls = true;
+               keys[MESA_SHADER_TESS_CTRL].tcs.input_vertices = key->tess_input_vertices;
+               keys[MESA_SHADER_TESS_CTRL].tcs.primitive_mode = nir[MESA_SHADER_TESS_EVAL]->info.tess.primitive_mode;
+
+               keys[MESA_SHADER_TESS_CTRL].tcs.tes_reads_tess_factors = !!(nir[MESA_SHADER_TESS_EVAL]->info.inputs_read & (VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER));
+       }
+
+       if (nir[MESA_SHADER_GEOMETRY]) {
+               if (nir[MESA_SHADER_TESS_CTRL])
+                       keys[MESA_SHADER_TESS_EVAL].tes.as_es = true;
+               else
+                       keys[MESA_SHADER_VERTEX].vs.as_es = true;
+       }
+
+       for(int i = 0; i < MESA_SHADER_STAGES; ++i)
+               keys[i].has_multiview_view_index = key->has_multiview_view_index;
+
+       keys[MESA_SHADER_FRAGMENT].fs.multisample = key->multisample;
+       keys[MESA_SHADER_FRAGMENT].fs.col_format = key->col_format;
+       keys[MESA_SHADER_FRAGMENT].fs.is_int8 = key->is_int8;
+       keys[MESA_SHADER_FRAGMENT].fs.is_int10 = key->is_int10;
+}
+
+static void
+merge_tess_info(struct shader_info *tes_info,
+                const struct shader_info *tcs_info)
+{
+       /* The Vulkan 1.0.38 spec, section 21.1 Tessellator says:
+        *
+        *    "PointMode. Controls generation of points rather than triangles
+        *     or lines. This functionality defaults to disabled, and is
+        *     enabled if either shader stage includes the execution mode.
+        *
+        * and about Triangles, Quads, IsoLines, VertexOrderCw, VertexOrderCcw,
+        * PointMode, SpacingEqual, SpacingFractionalEven, SpacingFractionalOdd,
+        * and OutputVertices, it says:
+        *
+        *    "One mode must be set in at least one of the tessellation
+        *     shader stages."
+        *
+        * So, the fields can be set in either the TCS or TES, but they must
+        * agree if set in both.  Our backend looks at TES, so bitwise-or in
+        * the values from the TCS.
+        */
+       assert(tcs_info->tess.tcs_vertices_out == 0 ||
+              tes_info->tess.tcs_vertices_out == 0 ||
+              tcs_info->tess.tcs_vertices_out == tes_info->tess.tcs_vertices_out);
+       tes_info->tess.tcs_vertices_out |= tcs_info->tess.tcs_vertices_out;
+
+       assert(tcs_info->tess.spacing == TESS_SPACING_UNSPECIFIED ||
+              tes_info->tess.spacing == TESS_SPACING_UNSPECIFIED ||
+              tcs_info->tess.spacing == tes_info->tess.spacing);
+       tes_info->tess.spacing |= tcs_info->tess.spacing;
+
+       assert(tcs_info->tess.primitive_mode == 0 ||
+              tes_info->tess.primitive_mode == 0 ||
+              tcs_info->tess.primitive_mode == tes_info->tess.primitive_mode);
+       tes_info->tess.primitive_mode |= tcs_info->tess.primitive_mode;
+       tes_info->tess.ccw |= tcs_info->tess.ccw;
+       tes_info->tess.point_mode |= tcs_info->tess.point_mode;
+}
+
 static
 void radv_create_shaders(struct radv_pipeline *pipeline,
                          struct radv_device *device,
                          struct radv_pipeline_cache *cache,
-                         struct ac_shader_variant_key *keys,
+                         struct radv_pipeline_key key,
                          const VkPipelineShaderStageCreateInfo **pStages)
 {
        struct radv_shader_module fs_m = {0};
@@ -1717,6 +1768,7 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
        nir_shader *nir[MESA_SHADER_STAGES] = {0};
        void *codes[MESA_SHADER_STAGES] = {0};
        unsigned code_sizes[MESA_SHADER_STAGES] = {0};
+       struct ac_shader_variant_key keys[MESA_SHADER_STAGES] = {{{{0}}}};
        unsigned char hash[20], gs_copy_hash[20];
 
        for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) {
@@ -1729,7 +1781,7 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
                }
        }
 
-       radv_hash_shaders(hash, pStages, pipeline->layout, keys, get_hash_flags(device));
+       radv_hash_shaders(hash, pStages, pipeline->layout, &key, get_hash_flags(device));
        memcpy(gs_copy_hash, hash, 20);
        gs_copy_hash[0] ^= 1;
 
@@ -1756,6 +1808,18 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
                modules[MESA_SHADER_FRAGMENT] = &fs_m;
        }
 
+       /* Determine first and last stage. */
+       unsigned first = MESA_SHADER_STAGES;
+       unsigned last = 0;
+       for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+               if (!pStages[i])
+                       continue;
+               if (first == MESA_SHADER_STAGES)
+                       first = i;
+               last = i;
+       }
+
+       int prev = -1;
        for (unsigned i = 0; i < MESA_SHADER_STAGES; ++i) {
                const VkPipelineShaderStageCreateInfo *stage = pStages[i];
 
@@ -1766,33 +1830,60 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
                                                    stage ? stage->pName : "main", i,
                                                    stage ? stage->pSpecializationInfo : NULL);
                pipeline->active_stages |= mesa_to_vk_shader_stage(i);
+
+               /* We don't want to alter meta shaders IR directly so clone it
+                * first.
+                */
+               if (nir[i]->info.name) {
+                       nir[i] = nir_shader_clone(NULL, nir[i]);
+               }
+
+               if (first != last) {
+                       nir_variable_mode mask = 0;
+
+                       if (i != first)
+                               mask = mask | nir_var_shader_in;
+
+                       if (i != last)
+                               mask = mask | nir_var_shader_out;
+
+                       nir_lower_io_to_scalar_early(nir[i], mask);
+                       radv_optimize_nir(nir[i]);
+               }
+
+               if (prev != -1) {
+                       nir_compact_varyings(nir[prev], nir[i], true);
+               }
+               prev = i;
        }
 
        if (nir[MESA_SHADER_TESS_CTRL]) {
-               /* TODO: This is no longer used as a key we should refactor this */
-               if (keys)
-                       keys[MESA_SHADER_TESS_CTRL].tcs.primitive_mode = nir[MESA_SHADER_TESS_EVAL]->info.tess.primitive_mode;
-
                nir_lower_tes_patch_vertices(nir[MESA_SHADER_TESS_EVAL], nir[MESA_SHADER_TESS_CTRL]->info.tess.tcs_vertices_out);
+               merge_tess_info(&nir[MESA_SHADER_TESS_EVAL]->info, &nir[MESA_SHADER_TESS_CTRL]->info);
        }
 
        radv_link_shaders(pipeline, nir);
 
+       for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+               if (modules[i] && radv_can_dump_shader(device, modules[i]))
+                       nir_print_shader(nir[i], stderr);
+       }
+
+       radv_fill_shader_keys(keys, &key, nir);
+
        if (nir[MESA_SHADER_FRAGMENT]) {
                if (!pipeline->shaders[MESA_SHADER_FRAGMENT]) {
                        pipeline->shaders[MESA_SHADER_FRAGMENT] =
                               radv_shader_variant_create(device, modules[MESA_SHADER_FRAGMENT], &nir[MESA_SHADER_FRAGMENT], 1,
-                                                         pipeline->layout, keys ? keys + MESA_SHADER_FRAGMENT : 0,
+                                                         pipeline->layout, keys + MESA_SHADER_FRAGMENT,
                                                          &codes[MESA_SHADER_FRAGMENT], &code_sizes[MESA_SHADER_FRAGMENT]);
                }
 
                /* TODO: These are no longer used as keys we should refactor this */
-               if (keys) {
-                       keys[MESA_SHADER_VERTEX].vs.export_prim_id =
-                               pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input;
-                       keys[MESA_SHADER_TESS_EVAL].tes.export_prim_id =
-                               pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input;
-               }
+               keys[MESA_SHADER_VERTEX].vs.export_prim_id =
+                       pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input;
+               keys[MESA_SHADER_TESS_EVAL].tes.export_prim_id =
+                       pipeline->shaders[MESA_SHADER_FRAGMENT]->info.fs.prim_id_input;
        }
 
        if (device->physical_device->rad_info.chip_class >= GFX9 && modules[MESA_SHADER_TESS_CTRL]) {
@@ -1824,7 +1915,7 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
                if(modules[i] && !pipeline->shaders[i]) {
                        pipeline->shaders[i] = radv_shader_variant_create(device, modules[i], &nir[i], 1,
                                                                          pipeline->layout,
-                                                                         keys ? keys + i : 0, &codes[i],
+                                                                         keys + i, &codes[i],
                                                                          &code_sizes[i]);
                }
        }
@@ -1862,7 +1953,7 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
 
        for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
                free(codes[i]);
-               if (modules[i] && !modules[i]->nir && !pipeline->device->trace_bo)
+               if (modules[i] && !pipeline->device->keep_shader_info)
                        ralloc_free(nir[i]);
        }
 
@@ -1870,6 +1961,48 @@ void radv_create_shaders(struct radv_pipeline *pipeline,
                ralloc_free(fs_m.nir);
 }
 
+static uint32_t
+radv_pipeline_stage_to_user_data_0(struct radv_pipeline *pipeline,
+                                  gl_shader_stage stage, enum chip_class chip_class)
+{
+       bool has_gs = radv_pipeline_has_gs(pipeline);
+       bool has_tess = radv_pipeline_has_tess(pipeline);
+       switch (stage) {
+       case MESA_SHADER_FRAGMENT:
+               return R_00B030_SPI_SHADER_USER_DATA_PS_0;
+       case MESA_SHADER_VERTEX:
+               if (chip_class >= GFX9) {
+                       return has_tess ? R_00B430_SPI_SHADER_USER_DATA_LS_0 :
+                              has_gs ? R_00B330_SPI_SHADER_USER_DATA_ES_0 :
+                              R_00B130_SPI_SHADER_USER_DATA_VS_0;
+               }
+               if (has_tess)
+                       return R_00B530_SPI_SHADER_USER_DATA_LS_0;
+               else
+                       return has_gs ? R_00B330_SPI_SHADER_USER_DATA_ES_0 : R_00B130_SPI_SHADER_USER_DATA_VS_0;
+       case MESA_SHADER_GEOMETRY:
+               return chip_class >= GFX9 ? R_00B330_SPI_SHADER_USER_DATA_ES_0 :
+                                           R_00B230_SPI_SHADER_USER_DATA_GS_0;
+       case MESA_SHADER_COMPUTE:
+               return R_00B900_COMPUTE_USER_DATA_0;
+       case MESA_SHADER_TESS_CTRL:
+               return chip_class >= GFX9 ? R_00B430_SPI_SHADER_USER_DATA_LS_0 :
+                                           R_00B430_SPI_SHADER_USER_DATA_HS_0;
+       case MESA_SHADER_TESS_EVAL:
+               if (chip_class >= GFX9) {
+                       return has_gs ? R_00B330_SPI_SHADER_USER_DATA_ES_0 :
+                              R_00B130_SPI_SHADER_USER_DATA_VS_0;
+               }
+               if (has_gs)
+                       return R_00B330_SPI_SHADER_USER_DATA_ES_0;
+               else
+                       return R_00B130_SPI_SHADER_USER_DATA_VS_0;
+       default:
+               unreachable("unknown shader");
+       }
+}
+
+
 static VkResult
 radv_pipeline_init(struct radv_pipeline *pipeline,
                   struct radv_device *device,
@@ -1890,6 +2023,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline,
 
        pipeline->device = device;
        pipeline->layout = radv_pipeline_layout_from_handle(pCreateInfo->layout);
+       assert(pipeline->layout);
 
        radv_pipeline_init_dynamic_state(pipeline, pCreateInfo);
        radv_pipeline_init_blend_state(pipeline, pCreateInfo, extra);
@@ -1900,44 +2034,9 @@ radv_pipeline_init(struct radv_pipeline *pipeline,
                pStages[stage] = &pCreateInfo->pStages[i];
        }
 
-       struct ac_shader_variant_key keys[MESA_SHADER_STAGES];
-       memset(keys, 0, sizeof(keys));
-
-       if (pStages[MESA_SHADER_VERTEX]) {
-               bool as_es = false;
-               bool as_ls = false;
-               if (pStages[MESA_SHADER_TESS_CTRL])
-                       as_ls = true;
-               else if (pStages[MESA_SHADER_GEOMETRY])
-                       as_es = true;
-
-               keys[MESA_SHADER_VERTEX] = radv_compute_vs_key(pCreateInfo, as_es, as_ls);
-               keys[MESA_SHADER_VERTEX].has_multiview_view_index = has_view_index;
-       }
-
-       if (pStages[MESA_SHADER_TESS_EVAL]) {
-               keys[MESA_SHADER_TESS_EVAL].has_multiview_view_index = has_view_index;
-               if (pStages[MESA_SHADER_GEOMETRY])
-                       keys[MESA_SHADER_TESS_EVAL].tes.as_es = true;
-       }
-
-       if (pCreateInfo->pTessellationState)
-               keys[MESA_SHADER_TESS_CTRL].tcs.input_vertices = pCreateInfo->pTessellationState->patchControlPoints;
-
-       if (pStages[MESA_SHADER_GEOMETRY]) {
-               keys[MESA_SHADER_GEOMETRY] = radv_compute_vs_key(pCreateInfo, false, false);
-               keys[MESA_SHADER_GEOMETRY].has_multiview_view_index = has_view_index;
-       }
-
-       if (pCreateInfo->pMultisampleState &&
-           pCreateInfo->pMultisampleState->rasterizationSamples > 1)
-               keys[MESA_SHADER_FRAGMENT].fs.multisample = true;
-
-       keys[MESA_SHADER_FRAGMENT].fs.col_format = pipeline->graphics.blend.spi_shader_col_format;
-       if (pipeline->device->physical_device->rad_info.chip_class < VI)
-               radv_pipeline_compute_get_int_clamp(pCreateInfo, &keys[MESA_SHADER_FRAGMENT].fs.is_int8, &keys[MESA_SHADER_FRAGMENT].fs.is_int10);
-
-       radv_create_shaders(pipeline, device, cache, keys, pStages);
+       radv_create_shaders(pipeline, device, cache, 
+                           radv_generate_graphics_pipeline_key(pipeline, pCreateInfo, has_view_index),
+                           pStages);
 
        radv_pipeline_init_depth_stencil_state(pipeline, pCreateInfo, extra);
        radv_pipeline_init_raster_state(pipeline, pCreateInfo);
@@ -1999,14 +2098,14 @@ radv_pipeline_init(struct radv_pipeline *pipeline,
        if (pipeline->device->physical_device->has_rbplus)
                pipeline->graphics.db_shader_control |= S_02880C_DUAL_QUAD_DISABLE(1);
 
-       pipeline->graphics.shader_z_format =
-               ps->info.fs.writes_sample_mask ? V_028710_SPI_SHADER_32_ABGR :
-               ps->info.fs.writes_stencil ? V_028710_SPI_SHADER_32_GR :
-               ps->info.fs.writes_z ? V_028710_SPI_SHADER_32_R :
-               V_028710_SPI_SHADER_ZERO;
+       unsigned shader_z_format =
+               ac_get_spi_shader_z_format(ps->info.fs.writes_z,
+                                          ps->info.fs.writes_stencil,
+                                          ps->info.fs.writes_sample_mask);
+       pipeline->graphics.shader_z_format = shader_z_format;
 
        calculate_vgt_gs_mode(pipeline);
-       calculate_pa_cl_vs_out_cntl(pipeline);
+       calculate_vs_outinfo(pipeline);
        calculate_ps_inputs(pipeline);
 
        for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
@@ -2167,10 +2266,13 @@ radv_pipeline_init(struct radv_pipeline *pipeline,
                pipeline->binding_stride[desc->binding] = desc->stride;
        }
 
+       for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++)
+               pipeline->user_data_0[i] = radv_pipeline_stage_to_user_data_0(pipeline, i, device->physical_device->rad_info.chip_class);
+
        struct ac_userdata_info *loc = radv_lookup_user_sgpr(pipeline, MESA_SHADER_VERTEX,
                                                             AC_UD_VS_BASE_VERTEX_START_INSTANCE);
        if (loc->sgpr_idx != -1) {
-               pipeline->graphics.vtx_base_sgpr = radv_shader_stage_to_user_data_0(MESA_SHADER_VERTEX, device->physical_device->rad_info.chip_class, radv_pipeline_has_gs(pipeline), radv_pipeline_has_tess(pipeline));
+               pipeline->graphics.vtx_base_sgpr = pipeline->user_data_0[MESA_SHADER_VERTEX];
                pipeline->graphics.vtx_base_sgpr += loc->sgpr_idx * 4;
                if (radv_get_vertex_shader(pipeline)->info.info.vs.needs_draw_id)
                        pipeline->graphics.vtx_emit_num = 3;
@@ -2206,12 +2308,11 @@ radv_graphics_pipeline_create(
        struct radv_pipeline *pipeline;
        VkResult result;
 
-       pipeline = vk_alloc2(&device->alloc, pAllocator, sizeof(*pipeline), 8,
-                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       pipeline = vk_zalloc2(&device->alloc, pAllocator, sizeof(*pipeline), 8,
+                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
        if (pipeline == NULL)
                return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-       memset(pipeline, 0, sizeof(*pipeline));
        result = radv_pipeline_init(pipeline, device, cache,
                                    pCreateInfo, extra, pAllocator);
        if (result != VK_SUCCESS) {
@@ -2263,19 +2364,19 @@ static VkResult radv_compute_pipeline_create(
        struct radv_pipeline *pipeline;
        VkResult result;
 
-       pipeline = vk_alloc2(&device->alloc, pAllocator, sizeof(*pipeline), 8,
-                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       pipeline = vk_zalloc2(&device->alloc, pAllocator, sizeof(*pipeline), 8,
+                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
        if (pipeline == NULL)
                return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-       memset(pipeline, 0, sizeof(*pipeline));
        pipeline->device = device;
        pipeline->layout = radv_pipeline_layout_from_handle(pCreateInfo->layout);
+       assert(pipeline->layout);
 
        pStages[MESA_SHADER_COMPUTE] = &pCreateInfo->stage;
-       radv_create_shaders(pipeline, device, cache, NULL, pStages);
-
+       radv_create_shaders(pipeline, device, cache, (struct radv_pipeline_key) {0}, pStages);
 
+       pipeline->user_data_0[MESA_SHADER_COMPUTE] = radv_pipeline_stage_to_user_data_0(pipeline, MESA_SHADER_COMPUTE, device->physical_device->rad_info.chip_class);
        pipeline->need_indirect_descriptor_sets |= pipeline->shaders[MESA_SHADER_COMPUTE]->info.need_indirect_descriptor_sets;
        result = radv_pipeline_scratch_init(device, pipeline);
        if (result != VK_SUCCESS) {