lavapipe: Use the vk_graphics_pipeline_state
authorJason Ekstrand <jason.ekstrand@collabora.com>
Wed, 20 Jul 2022 02:33:41 +0000 (21:33 -0500)
committerMarge Bot <emma+marge@anholt.net>
Tue, 26 Jul 2022 00:45:26 +0000 (00:45 +0000)
Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17669>

src/gallium/frontends/lavapipe/lvp_execute.c
src/gallium/frontends/lavapipe/lvp_pipeline.c
src/gallium/frontends/lavapipe/lvp_private.h

index aff07c8..acefd4e 100644 (file)
@@ -150,7 +150,6 @@ struct rendering_state {
    enum gs_output gs_output_lines : 2;
 
    uint32_t color_write_disables:8;
-   bool has_color_write_disables:1;
    uint32_t pad:13;
 
    void *ss_cso[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
@@ -406,7 +405,7 @@ static void emit_state(struct rendering_state *state)
    if (state->blend_dirty) {
       uint32_t mask = 0;
       /* zero out the colormask values for disabled attachments */
-      if (state->has_color_write_disables && state->color_write_disables) {
+      if (state->color_write_disables) {
          u_foreach_bit(att, state->color_write_disables) {
             mask |= state->blend_state.rt[att].colormask << (att * 4);
             state->blend_state.rt[att].colormask = 0;
@@ -414,7 +413,7 @@ static void emit_state(struct rendering_state *state)
       }
       cso_set_blend(state->cso, &state->blend_state);
       /* reset colormasks using saved bitmask */
-      if (state->has_color_write_disables && state->color_write_disables) {
+      if (state->color_write_disables) {
          const uint32_t att_mask = BITFIELD_MASK(4);
          u_foreach_bit(att, state->color_write_disables) {
             state->blend_state.rt[att].colormask = (mask >> (att * 4)) & att_mask;
@@ -609,75 +608,12 @@ get_viewport_xform(struct rendering_state *state,
    memcpy(&state->depth[idx].min, &viewport->minDepth, sizeof(float) * 2);
 }
 
-/* enum re-indexing:
-
-    VK_DYNAMIC_STATE_VIEWPORT
-    VK_DYNAMIC_STATE_SCISSOR
-    VK_DYNAMIC_STATE_LINE_WIDTH
-    VK_DYNAMIC_STATE_DEPTH_BIAS
-    VK_DYNAMIC_STATE_BLEND_CONSTANTS
-    VK_DYNAMIC_STATE_DEPTH_BOUNDS
-    VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK
-    VK_DYNAMIC_STATE_STENCIL_WRITE_MASK
-    VK_DYNAMIC_STATE_STENCIL_REFERENCE
-
-    VK_DYNAMIC_STATE_LINE_STIPPLE_EXT
-
-    VK_DYNAMIC_STATE_CULL_MODE
-    VK_DYNAMIC_STATE_FRONT_FACE
-    VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY
-    VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT
-    VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT
-    VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE
-    VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE
-    VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE
-    VK_DYNAMIC_STATE_DEPTH_COMPARE_OP
-    VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE
-    VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE
-    VK_DYNAMIC_STATE_STENCIL_OP
-
-    VK_DYNAMIC_STATE_VERTEX_INPUT_EXT
-
-    VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT
-    VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE
-    VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE
-    VK_DYNAMIC_STATE_LOGIC_OP_EXT
-    VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE
-
-    VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT
-*/
-static int conv_dynamic_state_idx(VkDynamicState dyn_state)
-{
-   if (dyn_state <= VK_DYNAMIC_STATE_STENCIL_REFERENCE)
-      return dyn_state;
-   if (dyn_state == VK_DYNAMIC_STATE_LINE_STIPPLE_EXT)
-      /* this one has a weird id, map after the normal dynamic state ones */
-      return VK_DYNAMIC_STATE_STENCIL_REFERENCE + 1;
-   if (dyn_state >= VK_DYNAMIC_STATE_CULL_MODE &&
-       dyn_state <= VK_DYNAMIC_STATE_STENCIL_OP)
-      return dyn_state - VK_DYNAMIC_STATE_CULL_MODE + VK_DYNAMIC_STATE_STENCIL_REFERENCE + 2;
-   if (dyn_state == VK_DYNAMIC_STATE_VERTEX_INPUT_EXT)
-      return (VK_DYNAMIC_STATE_STENCIL_OP - VK_DYNAMIC_STATE_CULL_MODE) + VK_DYNAMIC_STATE_STENCIL_REFERENCE + 2 + 1;
-   if (dyn_state >= VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT &&
-       dyn_state <= VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE)
-      return dyn_state - VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT +
-             VK_DYNAMIC_STATE_STENCIL_OP - VK_DYNAMIC_STATE_CULL_MODE +
-             VK_DYNAMIC_STATE_STENCIL_REFERENCE + 2 + 1 + 1;
-   if (dyn_state == VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT)
-      return VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE - VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT +
-             VK_DYNAMIC_STATE_STENCIL_OP - VK_DYNAMIC_STATE_CULL_MODE +
-             VK_DYNAMIC_STATE_STENCIL_REFERENCE + 2 + 1 + 1 + 1;
-   assert(0);
-   return -1;
-}
-
 static void handle_graphics_pipeline(struct vk_cmd_queue_entry *cmd,
                                      struct rendering_state *state)
 {
    LVP_FROM_HANDLE(lvp_pipeline, pipeline, cmd->u.bind_pipeline.pipeline);
-   bool dynamic_states[VK_DYNAMIC_STATE_STENCIL_REFERENCE+32];
+   const struct vk_graphics_pipeline_state *ps = &pipeline->graphics_state;
    unsigned fb_samples = 0;
-   bool clip_halfz = state->rs_state.clip_halfz;
 
    for (enum pipe_shader_type sh = PIPE_SHADER_VERTEX; sh < PIPE_SHADER_COMPUTE; sh++) {
       state->iv_dirty[sh] |= state->num_shader_images[sh] &&
@@ -687,20 +623,6 @@ static void handle_graphics_pipeline(struct vk_cmd_queue_entry *cmd,
    }
    memcpy(state->access, pipeline->access, sizeof(struct lvp_access_info) * 5); //4 vertex stages + fragment
 
-   memset(dynamic_states, 0, sizeof(dynamic_states));
-   if (pipeline->graphics_create_info.pDynamicState)
-   {
-      const VkPipelineDynamicStateCreateInfo *dyn = pipeline->graphics_create_info.pDynamicState;
-      int i;
-      for (i = 0; i < dyn->dynamicStateCount; i++) {
-         int idx = conv_dynamic_state_idx(dyn->pDynamicStates[i]);
-         if (idx == -1)
-            continue;
-         dynamic_states[idx] = true;
-      }
-   }
-   state->has_color_write_disables = dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT)];
-
    for (enum pipe_shader_type sh = PIPE_SHADER_VERTEX; sh < PIPE_SHADER_COMPUTE; sh++)
       state->has_pcbuf[sh] = false;
 
@@ -726,10 +648,9 @@ static void handle_graphics_pipeline(struct vk_cmd_queue_entry *cmd,
       state->pctx->bind_tes_state(state->pctx, NULL);
    state->gs_output_lines = GS_OUTPUT_NONE;
    {
-      int i;
-      for (i = 0; i < pipeline->graphics_create_info.stageCount; i++) {
-         const VkPipelineShaderStageCreateInfo *sh = &pipeline->graphics_create_info.pStages[i];
-         switch (sh->stage) {
+      u_foreach_bit(b, pipeline->graphics_state.shader_stages) {
+         VkShaderStageFlagBits vk_stage = (1 << b);
+         switch (vk_stage) {
          case VK_SHADER_STAGE_FRAGMENT_BIT:
             state->inlines_dirty[PIPE_SHADER_FRAGMENT] = pipeline->inlines[MESA_SHADER_FRAGMENT].can_inline;
             if (!pipeline->inlines[MESA_SHADER_FRAGMENT].can_inline)
@@ -779,131 +700,125 @@ static void handle_graphics_pipeline(struct vk_cmd_queue_entry *cmd,
       state->pctx->bind_tes_state(state->pctx, NULL);
 
    /* rasterization state */
-   if (pipeline->graphics_create_info.pRasterizationState) {
-      const VkPipelineRasterizationStateCreateInfo *rsc = pipeline->graphics_create_info.pRasterizationState;
-      const VkPipelineRasterizationDepthClipStateCreateInfoEXT *depth_clip_state =
-         vk_find_struct_const(rsc->pNext, PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT);
-      state->rs_state.depth_clamp = rsc->depthClampEnable;
-      if (!depth_clip_state)
-         state->rs_state.depth_clip_near = state->rs_state.depth_clip_far = !rsc->depthClampEnable;
-      else
-         state->rs_state.depth_clip_near = state->rs_state.depth_clip_far = depth_clip_state->depthClipEnable;
+   if (ps->rs) {
+      state->rs_state.depth_clamp = ps->rs->depth_clamp_enable;
+      state->rs_state.depth_clip_near = ps->rs->depth_clip_enable;
 
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE)])
-         state->rs_state.rasterizer_discard = rsc->rasterizerDiscardEnable;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_RS_RASTERIZER_DISCARD_ENABLE))
+         state->rs_state.rasterizer_discard = ps->rs->rasterizer_discard_enable;
 
       state->rs_state.line_smooth = pipeline->line_smooth;
-      state->rs_state.line_stipple_enable = pipeline->line_stipple_enable;
-      state->rs_state.fill_front = vk_polygon_mode_to_pipe(rsc->polygonMode);
-      state->rs_state.fill_back = vk_polygon_mode_to_pipe(rsc->polygonMode);
+      state->rs_state.line_stipple_enable = ps->rs->line.stipple.enable;
+      state->rs_state.fill_front = vk_polygon_mode_to_pipe(ps->rs->polygon_mode);
+      state->rs_state.fill_back = vk_polygon_mode_to_pipe(ps->rs->polygon_mode);
       state->rs_state.point_size_per_vertex = true;
-      state->rs_state.flatshade_first = !pipeline->provoking_vertex_last;
+      state->rs_state.flatshade_first =
+         ps->rs->provoking_vertex == VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
       state->rs_state.point_quad_rasterization = true;
       state->rs_state.half_pixel_center = true;
       state->rs_state.scissor = true;
       state->rs_state.no_ms_sample_mask_out = true;
       state->rs_state.line_rectangular = pipeline->line_rectangular;
 
-      if (!dynamic_states[VK_DYNAMIC_STATE_LINE_WIDTH])
-         state->rs_state.line_width = rsc->lineWidth;
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_LINE_STIPPLE_EXT)]) {
-         state->rs_state.line_stipple_factor = pipeline->line_stipple_factor;
-         state->rs_state.line_stipple_pattern = pipeline->line_stipple_pattern;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_RS_LINE_WIDTH))
+         state->rs_state.line_width = ps->rs->line.width;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_RS_LINE_STIPPLE)) {
+         state->rs_state.line_stipple_factor = ps->rs->line.stipple.factor - 1;
+         state->rs_state.line_stipple_pattern = ps->rs->line.stipple.pattern;
       }
 
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE)])
-         state->depth_bias.enabled = pipeline->graphics_create_info.pRasterizationState->depthBiasEnable;
-      if (!dynamic_states[VK_DYNAMIC_STATE_DEPTH_BIAS]) {
-         state->depth_bias.offset_units = rsc->depthBiasConstantFactor;
-         state->depth_bias.offset_scale = rsc->depthBiasSlopeFactor;
-         state->depth_bias.offset_clamp = rsc->depthBiasClamp;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_ENABLE))
+         state->depth_bias.enabled = ps->rs->depth_bias.enable;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_RS_DEPTH_BIAS_FACTORS)) {
+         state->depth_bias.offset_units = ps->rs->depth_bias.constant;
+         state->depth_bias.offset_scale = ps->rs->depth_bias.slope;
+         state->depth_bias.offset_clamp = ps->rs->depth_bias.clamp;
       }
 
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_CULL_MODE)])
-         state->rs_state.cull_face = vk_cull_to_pipe(rsc->cullMode);
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_RS_CULL_MODE))
+         state->rs_state.cull_face = vk_cull_to_pipe(ps->rs->cull_mode);
 
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_FRONT_FACE)])
-         state->rs_state.front_ccw = (rsc->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_RS_FRONT_FACE))
+         state->rs_state.front_ccw = (ps->rs->front_face == VK_FRONT_FACE_COUNTER_CLOCKWISE);
       state->rs_dirty = true;
    }
 
-   if (pipeline->graphics_create_info.pDepthStencilState) {
-      const VkPipelineDepthStencilStateCreateInfo *dsa = pipeline->graphics_create_info.pDepthStencilState;
-
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE)])
-         state->dsa_state.depth_enabled = dsa->depthTestEnable;
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE)])
-         state->dsa_state.depth_writemask = dsa->depthWriteEnable;
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_DEPTH_COMPARE_OP)])
-         state->dsa_state.depth_func = dsa->depthCompareOp;
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE)])
-         state->dsa_state.depth_bounds_test = dsa->depthBoundsTestEnable;
-
-      if (!dynamic_states[VK_DYNAMIC_STATE_DEPTH_BOUNDS]) {
-         state->dsa_state.depth_bounds_min = dsa->minDepthBounds;
-         state->dsa_state.depth_bounds_max = dsa->maxDepthBounds;
+   if (ps->ds) {
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_DEPTH_TEST_ENABLE))
+         state->dsa_state.depth_enabled = ps->ds->depth.test_enable;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_DEPTH_WRITE_ENABLE))
+         state->dsa_state.depth_writemask = ps->ds->depth.write_enable;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_DEPTH_COMPARE_OP))
+         state->dsa_state.depth_func = ps->ds->depth.compare_op;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE))
+         state->dsa_state.depth_bounds_test = ps->ds->depth.bounds_test.enable;
+
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_BOUNDS)) {
+         state->dsa_state.depth_bounds_min = ps->ds->depth.bounds_test.min;
+         state->dsa_state.depth_bounds_max = ps->ds->depth.bounds_test.max;
       }
 
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE)]) {
-         state->dsa_state.stencil[0].enabled = dsa->stencilTestEnable;
-         state->dsa_state.stencil[1].enabled = dsa->stencilTestEnable;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE)) {
+         state->dsa_state.stencil[0].enabled = ps->ds->stencil.test_enable;
+         state->dsa_state.stencil[1].enabled = ps->ds->stencil.test_enable;
       }
 
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_STENCIL_OP)]) {
-         state->dsa_state.stencil[0].func = dsa->front.compareOp;
-         state->dsa_state.stencil[0].fail_op = vk_conv_stencil_op(dsa->front.failOp);
-         state->dsa_state.stencil[0].zpass_op = vk_conv_stencil_op(dsa->front.passOp);
-         state->dsa_state.stencil[0].zfail_op = vk_conv_stencil_op(dsa->front.depthFailOp);
+      const struct vk_stencil_test_face_state *front = &ps->ds->stencil.front;
+      const struct vk_stencil_test_face_state *back = &ps->ds->stencil.back;
 
-         state->dsa_state.stencil[1].func = dsa->back.compareOp;
-         state->dsa_state.stencil[1].fail_op = vk_conv_stencil_op(dsa->back.failOp);
-         state->dsa_state.stencil[1].zpass_op = vk_conv_stencil_op(dsa->back.passOp);
-         state->dsa_state.stencil[1].zfail_op = vk_conv_stencil_op(dsa->back.depthFailOp);
-      }
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_OP)) {
+         state->dsa_state.stencil[0].func = front->op.compare;
+         state->dsa_state.stencil[0].fail_op = vk_conv_stencil_op(front->op.fail);
+         state->dsa_state.stencil[0].zpass_op = vk_conv_stencil_op(front->op.pass);
+         state->dsa_state.stencil[0].zfail_op = vk_conv_stencil_op(front->op.depth_fail);
 
-      if (!dynamic_states[VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK]) {
-         state->dsa_state.stencil[0].valuemask = dsa->front.compareMask;
-         state->dsa_state.stencil[1].valuemask = dsa->back.compareMask;
+         state->dsa_state.stencil[1].func = back->op.compare;
+         state->dsa_state.stencil[1].fail_op = vk_conv_stencil_op(back->op.fail);
+         state->dsa_state.stencil[1].zpass_op = vk_conv_stencil_op(back->op.pass);
+         state->dsa_state.stencil[1].zfail_op = vk_conv_stencil_op(back->op.depth_fail);
       }
 
-      if (!dynamic_states[VK_DYNAMIC_STATE_STENCIL_WRITE_MASK]) {
-         state->dsa_state.stencil[0].writemask = dsa->front.writeMask;
-         state->dsa_state.stencil[1].writemask = dsa->back.writeMask;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK)) {
+         state->dsa_state.stencil[0].valuemask = front->compare_mask;
+         state->dsa_state.stencil[1].valuemask = back->compare_mask;
       }
 
-      if (dsa->stencilTestEnable) {
-         if (!dynamic_states[VK_DYNAMIC_STATE_STENCIL_REFERENCE]) {
-            state->stencil_ref.ref_value[0] = dsa->front.reference;
-            state->stencil_ref.ref_value[1] = dsa->back.reference;
-            state->stencil_ref_dirty = true;
-         }
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK)) {
+         state->dsa_state.stencil[0].writemask = front->write_mask;
+         state->dsa_state.stencil[1].writemask = back->write_mask;
       }
-   } else
-      memset(&state->dsa_state, 0, sizeof(state->dsa_state));
-   state->dsa_dirty = true;
 
-   if (pipeline->graphics_create_info.pColorBlendState) {
-      const VkPipelineColorBlendStateCreateInfo *cb = pipeline->graphics_create_info.pColorBlendState;
-      int i;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE)) {
+         state->stencil_ref.ref_value[0] = front->reference;
+         state->stencil_ref.ref_value[1] = back->reference;
+         state->stencil_ref_dirty = true;
+      }
+      state->dsa_dirty = true;
+   }
 
-      state->blend_state.logicop_enable = cb->logicOpEnable;
-      if (cb->logicOpEnable) {
-         if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_LOGIC_OP_EXT)])
-            state->blend_state.logicop_func = vk_conv_logic_op(cb->logicOp);
+   if (ps->cb) {
+      state->blend_state.logicop_enable = ps->cb->logic_op_enable;
+      if (ps->cb->logic_op_enable) {
+         if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_CB_LOGIC_OP))
+            state->blend_state.logicop_func = vk_conv_logic_op(ps->cb->logic_op);
       }
 
-      state->blend_state.independent_blend_enable = (cb->attachmentCount > 1);
-
-      for (i = 0; i < cb->attachmentCount; i++) {
-         state->blend_state.rt[i].colormask = cb->pAttachments[i].colorWriteMask;
-         state->blend_state.rt[i].blend_enable = cb->pAttachments[i].blendEnable;
-         if (state->blend_state.rt[i].blend_enable) {
-            state->blend_state.rt[i].rgb_func = vk_conv_blend_func(cb->pAttachments[i].colorBlendOp);
-            state->blend_state.rt[i].rgb_src_factor = vk_conv_blend_factor(cb->pAttachments[i].srcColorBlendFactor);
-            state->blend_state.rt[i].rgb_dst_factor = vk_conv_blend_factor(cb->pAttachments[i].dstColorBlendFactor);
-            state->blend_state.rt[i].alpha_func = vk_conv_blend_func(cb->pAttachments[i].alphaBlendOp);
-            state->blend_state.rt[i].alpha_src_factor = vk_conv_blend_factor(cb->pAttachments[i].srcAlphaBlendFactor);
-            state->blend_state.rt[i].alpha_dst_factor = vk_conv_blend_factor(cb->pAttachments[i].dstAlphaBlendFactor);
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES))
+         state->color_write_disables = ~ps->cb->color_write_enables;
+
+      state->blend_state.independent_blend_enable = (ps->cb->attachment_count > 1);
+
+      for (unsigned i = 0; i < ps->cb->attachment_count; i++) {
+         const struct vk_color_blend_attachment_state *att = &ps->cb->attachments[i];
+         state->blend_state.rt[i].colormask = att->write_mask;
+         state->blend_state.rt[i].blend_enable = att->blend_enable;
+         if (att->blend_enable) {
+            state->blend_state.rt[i].rgb_func = vk_conv_blend_func(att->color_blend_op);
+            state->blend_state.rt[i].rgb_src_factor = vk_conv_blend_factor(att->src_color_blend_factor);
+            state->blend_state.rt[i].rgb_dst_factor = vk_conv_blend_factor(att->dst_color_blend_factor);
+            state->blend_state.rt[i].alpha_func = vk_conv_blend_func(att->alpha_blend_op);
+            state->blend_state.rt[i].alpha_src_factor = vk_conv_blend_factor(att->src_alpha_blend_factor);
+            state->blend_state.rt[i].alpha_dst_factor = vk_conv_blend_factor(att->dst_alpha_blend_factor);
          } else {
             state->blend_state.rt[i].rgb_func = 0;
             state->blend_state.rt[i].rgb_src_factor = 0;
@@ -917,21 +832,21 @@ static void handle_graphics_pipeline(struct vk_cmd_queue_entry *cmd,
           * regardless of what function is used. (like i965 hardware).
           * It means for MIN/MAX the blend factor has to be stomped to ONE.
           */
-         if (cb->pAttachments[i].colorBlendOp == VK_BLEND_OP_MIN ||
-             cb->pAttachments[i].colorBlendOp == VK_BLEND_OP_MAX) {
+         if (att->color_blend_op == VK_BLEND_OP_MIN ||
+             att->color_blend_op == VK_BLEND_OP_MAX) {
             state->blend_state.rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
             state->blend_state.rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
          }
 
-         if (cb->pAttachments[i].alphaBlendOp == VK_BLEND_OP_MIN ||
-             cb->pAttachments[i].alphaBlendOp == VK_BLEND_OP_MAX) {
+         if (att->alpha_blend_op == VK_BLEND_OP_MIN ||
+             att->alpha_blend_op == VK_BLEND_OP_MAX) {
             state->blend_state.rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
             state->blend_state.rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
          }
       }
       state->blend_dirty = true;
-      if (!dynamic_states[VK_DYNAMIC_STATE_BLEND_CONSTANTS]) {
-         memcpy(state->blend_color.color, cb->blendConstants, 4 * sizeof(float));
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS)) {
+         memcpy(state->blend_color.color, ps->cb->blend_constants, 4 * sizeof(float));
          state->blend_color_dirty = true;
       }
    } else {
@@ -940,26 +855,26 @@ static void handle_graphics_pipeline(struct vk_cmd_queue_entry *cmd,
    }
 
    state->disable_multisample = pipeline->disable_multisample;
-   if (pipeline->graphics_create_info.pMultisampleState) {
-      const VkPipelineMultisampleStateCreateInfo *ms = pipeline->graphics_create_info.pMultisampleState;
-      state->rs_state.multisample = ms->rasterizationSamples > 1;
-      state->sample_mask = ms->pSampleMask ? ms->pSampleMask[0] : 0xffffffff;
-      state->blend_state.alpha_to_coverage = ms->alphaToCoverageEnable;
-      state->blend_state.alpha_to_one = ms->alphaToOneEnable;
+   if (ps->ms) {
+      state->rs_state.multisample = ps->ms->rasterization_samples > 1;
+      state->sample_mask = ps->ms->sample_mask;
+      state->blend_state.alpha_to_coverage = ps->ms->alpha_to_coverage_enable;
+      state->blend_state.alpha_to_one = ps->ms->alpha_to_one_enable;
       state->blend_dirty = true;
       state->rs_dirty = true;
       state->min_samples = 1;
       state->sample_mask_dirty = true;
-      fb_samples = ms->rasterizationSamples;
-      if (ms->sampleShadingEnable) {
-         state->min_samples = ceil(ms->rasterizationSamples * ms->minSampleShading);
+      fb_samples = ps->ms->rasterization_samples;
+      if (ps->ms->sample_shading_enable) {
+         state->min_samples = ceil(ps->ms->rasterization_samples *
+                                   ps->ms->min_sample_shading);
          if (state->min_samples > 1)
-            state->min_samples = ms->rasterizationSamples;
+            state->min_samples = ps->ms->rasterization_samples;
          if (state->min_samples < 1)
             state->min_samples = 1;
       }
       if (pipeline->force_min_sample)
-         state->min_samples = ms->rasterizationSamples;
+         state->min_samples = ps->ms->rasterization_samples;
       state->min_samples_dirty = true;
    } else {
       state->rs_state.multisample = false;
@@ -973,131 +888,83 @@ static void handle_graphics_pipeline(struct vk_cmd_queue_entry *cmd,
       state->rs_dirty = true;
    }
 
-   if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT)]) {
-      const VkPipelineVertexInputStateCreateInfo *vi = pipeline->graphics_create_info.pVertexInputState;
-      int i;
-      const VkPipelineVertexInputDivisorStateCreateInfoEXT *div_state =
-         vk_find_struct_const(vi->pNext,
-                              PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
-
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE)]) {
-         for (i = 0; i < vi->vertexBindingDescriptionCount; i++) {
-            state->vb[vi->pVertexBindingDescriptions[i].binding].stride = vi->pVertexBindingDescriptions[i].stride;
-         }
-      }
+   if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_VI_BINDING_STRIDES)) {
+      u_foreach_bit(b, ps->vi->bindings_valid)
+         state->vb[b].stride = ps->vi->bindings[b].stride;
+      state->vb_dirty = true;
+   }
 
-      int max_location = -1;
-      for (i = 0; i < vi->vertexAttributeDescriptionCount; i++) {
-         unsigned location = vi->pVertexAttributeDescriptions[i].location;
-         unsigned binding = vi->pVertexAttributeDescriptions[i].binding;
-         const struct VkVertexInputBindingDescription *desc_binding = NULL;
-         for (unsigned j = 0; j < vi->vertexBindingDescriptionCount; j++) {
-            const struct VkVertexInputBindingDescription *b = &vi->pVertexBindingDescriptions[j];
-            if (b->binding == binding) {
-               desc_binding = b;
-               break;
-            }
-         }
-         assert(desc_binding);
-         state->velem.velems[location].src_offset = vi->pVertexAttributeDescriptions[i].offset;
-         state->velem.velems[location].vertex_buffer_index = binding;
-         state->velem.velems[location].src_format = lvp_vk_format_to_pipe_format(vi->pVertexAttributeDescriptions[i].format);
-         state->velem.velems[location].dual_slot = false;
+   if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_VI)) {
+      u_foreach_bit(a, ps->vi->attributes_valid) {
+         uint32_t b = ps->vi->attributes[a].binding;
+         state->velem.velems[a].src_offset = ps->vi->attributes[a].offset;
+         state->velem.velems[a].vertex_buffer_index = b;
+         state->velem.velems[a].src_format =
+            lvp_vk_format_to_pipe_format(ps->vi->attributes[a].format);
+         state->velem.velems[a].dual_slot = false;
 
-         switch (desc_binding->inputRate) {
+         uint32_t d = ps->vi->bindings[b].divisor;
+         switch (ps->vi->bindings[b].input_rate) {
          case VK_VERTEX_INPUT_RATE_VERTEX:
-            state->velem.velems[location].instance_divisor = 0;
+            state->velem.velems[a].instance_divisor = 0;
             break;
          case VK_VERTEX_INPUT_RATE_INSTANCE:
-            if (div_state) {
-               for (unsigned j = 0; j < div_state->vertexBindingDivisorCount; j++) {
-                  const VkVertexInputBindingDivisorDescriptionEXT *desc =
-                     &div_state->pVertexBindingDivisors[j];
-                  if (desc->binding == state->velem.velems[location].vertex_buffer_index) {
-                     state->velem.velems[location].instance_divisor = desc->divisor;
-                     break;
-                  }
-               }
-            } else
-               state->velem.velems[location].instance_divisor = 1;
+            state->velem.velems[a].instance_divisor = d ? d : UINT32_MAX;
             break;
          default:
-            assert(0);
-            break;
+            unreachable("Invalid vertex input rate");
          }
-
-         if ((int)location > max_location)
-            max_location = location;
       }
-      state->velem.count = max_location + 1;
+
+      state->velem.count = util_last_bit(ps->vi->attributes_valid);
       state->vb_dirty = true;
       state->ve_dirty = true;
    }
 
-   {
-      const VkPipelineInputAssemblyStateCreateInfo *ia = pipeline->graphics_create_info.pInputAssemblyState;
-
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY)]) {
-         state->info.mode = vk_conv_topology(ia->topology);
-         state->rs_dirty = true;
-      }
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE)])
-         state->info.primitive_restart = ia->primitiveRestartEnable;
-   }
-
-   if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT)]) {
-      if (pipeline->graphics_create_info.pTessellationState) {
-         const VkPipelineTessellationStateCreateInfo *ts = pipeline->graphics_create_info.pTessellationState;
-         state->patch_vertices = ts->patchControlPoints;
-      } else {
-         state->patch_vertices = 0;
-      }
-   }
-
-   bool halfz_changed = false;
-   if (!pipeline->negative_one_to_one != clip_halfz) {
-      state->rs_state.clip_halfz = !pipeline->negative_one_to_one;
-      halfz_changed = state->rs_dirty = true;
+   if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_IA_PRIMITIVE_TOPOLOGY)) {
+      state->info.mode = vk_conv_topology(ps->ia->primitive_topology);
+      state->rs_dirty = true;
    }
+   if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_IA_PRIMITIVE_RESTART_ENABLE))
+      state->info.primitive_restart = ps->ia->primitive_restart_enable;
 
-   if (pipeline->graphics_create_info.pViewportState) {
-      const VkPipelineViewportStateCreateInfo *vpi= pipeline->graphics_create_info.pViewportState;
-      int i;
+   if (ps->ts && !BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_TS_PATCH_CONTROL_POINTS))
+      state->patch_vertices = ps->ts->patch_control_points;
 
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT)]) {
-         state->num_viewports = vpi->viewportCount;
+   if (ps->vp) {
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_VP_VIEWPORT_COUNT)) {
+         state->num_viewports = ps->vp->viewport_count;
          state->vp_dirty = true;
       }
-      if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT)]) {
-         state->num_scissors = vpi->scissorCount;
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_VP_SCISSOR_COUNT)) {
+         state->num_scissors = ps->vp->scissor_count;
          state->scissor_dirty = true;
       }
 
-      if (!dynamic_states[VK_DYNAMIC_STATE_VIEWPORT] &&
-          !dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT)]) {
-         for (i = 0; i < vpi->viewportCount; i++) {
-            get_viewport_xform(state, &vpi->pViewports[i], i);
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_VP_VIEWPORTS)) {
+         for (uint32_t i = 0; i < ps->vp->viewport_count; i++) {
+            get_viewport_xform(state, &ps->vp->viewports[i], i);
             set_viewport_depth_xform(state, i);
          }
          state->vp_dirty = true;
-      } else if (halfz_changed) {
-         /* handle dynamic state: convert from one transform to the other */
-         unsigned num_viewports = dynamic_states[VK_DYNAMIC_STATE_VIEWPORT] ? vpi->viewportCount : state->num_viewports;
-         for (i = 0; i < num_viewports; i++)
-            set_viewport_depth_xform(state, i);
-         state->vp_dirty = true;
       }
-      if (!dynamic_states[VK_DYNAMIC_STATE_SCISSOR] &&
-          !dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT)]) {
-         for (i = 0; i < vpi->scissorCount; i++) {
-            const VkRect2D *ss = &vpi->pScissors[i];
+      if (!BITSET_TEST(ps->dynamic, MESA_VK_DYNAMIC_VP_SCISSORS)) {
+         for (uint32_t i = 0; i < ps->vp->scissor_count; i++) {
+            const VkRect2D *ss = &ps->vp->scissors[i];
             state->scissors[i].minx = ss->offset.x;
             state->scissors[i].miny = ss->offset.y;
             state->scissors[i].maxx = ss->offset.x + ss->extent.width;
             state->scissors[i].maxy = ss->offset.y + ss->extent.height;
-            state->scissor_dirty = true;
          }
+         state->scissor_dirty = true;
+      }
 
+      if (state->rs_state.clip_halfz != !ps->vp->negative_one_to_one) {
+         state->rs_state.clip_halfz = !ps->vp->negative_one_to_one;
+         state->rs_dirty = true;
+         for (uint32_t i = 0; i < state->num_viewports; i++)
+            set_viewport_depth_xform(state, i);
+         state->vp_dirty = true;
       }
    }
 
index 4e20f51..aa3cf94 100644 (file)
@@ -67,6 +67,7 @@ lvp_pipeline_destroy(struct lvp_device *device, struct lvp_pipeline *pipeline)
       vk_pipeline_layout_unref(&device->vk, &pipeline->layout->vk);
 
    ralloc_free(pipeline->mem_ctx);
+   vk_free(&device->vk.alloc, pipeline->state_data);
    vk_object_base_finish(&pipeline->base);
    vk_free(&device->vk.alloc, pipeline);
 }
@@ -87,561 +88,6 @@ VKAPI_ATTR void VKAPI_CALL lvp_DestroyPipeline(
    simple_mtx_unlock(&device->queue.pipeline_lock);
 }
 
-static VkResult
-deep_copy_shader_stage(void *mem_ctx,
-                       struct VkPipelineShaderStageCreateInfo *dst,
-                       const struct VkPipelineShaderStageCreateInfo *src)
-{
-   dst->sType = src->sType;
-   dst->pNext = NULL;
-   dst->flags = src->flags;
-   dst->stage = src->stage;
-   dst->module = src->module;
-   dst->pName = src->pName;
-   dst->pSpecializationInfo = NULL;
-   if (src->pSpecializationInfo) {
-      const VkSpecializationInfo *src_spec = src->pSpecializationInfo;
-      VkSpecializationInfo *dst_spec = ralloc_size(mem_ctx, sizeof(VkSpecializationInfo) +
-                                                   src_spec->mapEntryCount * sizeof(VkSpecializationMapEntry) +
-                                                   src_spec->dataSize);
-      VkSpecializationMapEntry *maps = (VkSpecializationMapEntry *)(dst_spec + 1);
-      dst_spec->pMapEntries = maps;
-      void *pdata = (void *)(dst_spec->pMapEntries + src_spec->mapEntryCount);
-      dst_spec->pData = pdata;
-
-
-      dst_spec->mapEntryCount = src_spec->mapEntryCount;
-      dst_spec->dataSize = src_spec->dataSize;
-      memcpy(pdata, src_spec->pData, src->pSpecializationInfo->dataSize);
-      memcpy(maps, src_spec->pMapEntries, src_spec->mapEntryCount * sizeof(VkSpecializationMapEntry));
-      dst->pSpecializationInfo = dst_spec;
-   }
-   return VK_SUCCESS;
-}
-
-static VkResult
-deep_copy_vertex_input_state(void *mem_ctx,
-                             struct VkPipelineVertexInputStateCreateInfo *dst,
-                             const struct VkPipelineVertexInputStateCreateInfo *src)
-{
-   dst->sType = src->sType;
-   dst->pNext = NULL;
-   dst->flags = src->flags;
-   dst->vertexBindingDescriptionCount = src->vertexBindingDescriptionCount;
-
-   LVP_PIPELINE_DUP(dst->pVertexBindingDescriptions,
-                    src->pVertexBindingDescriptions,
-                    VkVertexInputBindingDescription,
-                    src->vertexBindingDescriptionCount);
-
-   dst->vertexAttributeDescriptionCount = src->vertexAttributeDescriptionCount;
-
-   LVP_PIPELINE_DUP(dst->pVertexAttributeDescriptions,
-                    src->pVertexAttributeDescriptions,
-                    VkVertexInputAttributeDescription,
-                    src->vertexAttributeDescriptionCount);
-
-   if (src->pNext) {
-      vk_foreach_struct_const(ext, src->pNext) {
-         switch (ext->sType) {
-         case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: {
-            const VkPipelineVertexInputDivisorStateCreateInfoEXT *ext_src = (VkPipelineVertexInputDivisorStateCreateInfoEXT *)ext;
-            unsigned n = ext_src->vertexBindingDivisorCount;
-            if (!n)
-               continue;
-            size_t offset = sizeof(VkPipelineVertexInputDivisorStateCreateInfoEXT);
-            char *p = (char *) ralloc_size(mem_ctx, offset + n * sizeof(VkVertexInputBindingDivisorDescriptionEXT));
-            if (!p)
-               return VK_ERROR_OUT_OF_HOST_MEMORY;
-            VkPipelineVertexInputDivisorStateCreateInfoEXT *ext_dst = (VkPipelineVertexInputDivisorStateCreateInfoEXT *)p;
-            VkVertexInputBindingDivisorDescriptionEXT *dst_divisors = (VkVertexInputBindingDivisorDescriptionEXT *)(p + offset);
-            ext_dst->sType = ext_src->sType;
-            ext_dst->pNext = NULL;
-            ext_dst->vertexBindingDivisorCount = n;
-            ext_dst->pVertexBindingDivisors = dst_divisors;
-            const VkVertexInputBindingDivisorDescriptionEXT *src_divisors = ext_src->pVertexBindingDivisors;
-            for (unsigned i = 0; i < n; ++i) {
-               uint32_t d = src_divisors[i].divisor;
-               dst_divisors[i].divisor = d ? d : UINT32_MAX;
-               dst_divisors[i].binding = src_divisors[i].binding;
-            }
-            dst->pNext = ext_dst;
-            break;
-         }
-         default:
-            break;
-         }
-      }
-   }
-   return VK_SUCCESS;
-}
-
-static bool
-dynamic_state_contains(const VkPipelineDynamicStateCreateInfo *src, VkDynamicState state)
-{
-   if (!src)
-      return false;
-
-   for (unsigned i = 0; i < src->dynamicStateCount; i++)
-      if (src->pDynamicStates[i] == state)
-         return true;
-   return false;
-}
-
-static VkResult
-deep_copy_viewport_state(void *mem_ctx,
-                         const VkPipelineDynamicStateCreateInfo *dyn_state,
-                         VkPipelineViewportStateCreateInfo *dst,
-                         const VkPipelineViewportStateCreateInfo *src)
-{
-   dst->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
-   dst->pNext = NULL;
-   dst->pViewports = NULL;
-   dst->pScissors = NULL;
-
-   if (!dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_VIEWPORT) &&
-       !dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT)) {
-      LVP_PIPELINE_DUP(dst->pViewports,
-                       src->pViewports,
-                       VkViewport,
-                       src->viewportCount);
-   }
-   if (!dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT))
-      dst->viewportCount = src->viewportCount;
-   else
-      dst->viewportCount = 0;
-
-   if (!dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_SCISSOR) &&
-       !dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT)) {
-      if (src->pScissors)
-         LVP_PIPELINE_DUP(dst->pScissors,
-                          src->pScissors,
-                          VkRect2D,
-                          src->scissorCount);
-   }
-   if (!dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT))
-      dst->scissorCount = src->scissorCount;
-   else
-      dst->scissorCount = 0;
-
-   if (src->pNext) {
-      vk_foreach_struct_const(ext, src->pNext) {
-         switch (ext->sType) {
-         case VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT: {
-            VkPipelineViewportDepthClipControlCreateInfoEXT *ext_src = (VkPipelineViewportDepthClipControlCreateInfoEXT *)ext;
-            VkPipelineViewportDepthClipControlCreateInfoEXT *ext_dst = ralloc(mem_ctx, VkPipelineViewportDepthClipControlCreateInfoEXT);
-            memcpy(ext_dst, ext_src, sizeof(*ext_dst));
-            ext_dst->pNext = dst->pNext;
-            dst->pNext = ext_dst;
-            break;
-         }
-         default:
-            break;
-         }
-      }
-   }
-
-   return VK_SUCCESS;
-}
-
-static VkResult
-deep_copy_color_blend_state(void *mem_ctx,
-                            VkPipelineColorBlendStateCreateInfo *dst,
-                            const VkPipelineColorBlendStateCreateInfo *src)
-{
-   dst->sType = src->sType;
-   dst->pNext = NULL;
-   dst->flags = src->flags;
-   dst->logicOpEnable = src->logicOpEnable;
-   dst->logicOp = src->logicOp;
-
-   LVP_PIPELINE_DUP(dst->pAttachments,
-                    src->pAttachments,
-                    VkPipelineColorBlendAttachmentState,
-                    src->attachmentCount);
-   dst->attachmentCount = src->attachmentCount;
-
-   memcpy(&dst->blendConstants, &src->blendConstants, sizeof(float) * 4);
-
-   return VK_SUCCESS;
-}
-
-static VkResult
-deep_copy_dynamic_state(void *mem_ctx,
-                        VkPipelineDynamicStateCreateInfo *dst,
-                        const VkPipelineDynamicStateCreateInfo *src,
-                        VkGraphicsPipelineLibraryFlagsEXT stages,
-                        bool has_depth, bool has_stencil)
-{
-   dst->sType = src->sType;
-   dst->pNext = NULL;
-   dst->flags = src->flags;
-   VkDynamicState *states = (void*)dst->pDynamicStates;
-   for (unsigned i = 0; i < src->dynamicStateCount; i++) {
-      switch (src->pDynamicStates[i]) {
-      case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE:
-      case VK_DYNAMIC_STATE_VERTEX_INPUT_EXT:
-      case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY:
-      case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE:
-         if (stages & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT)
-            states[dst->dynamicStateCount++] = src->pDynamicStates[i];
-         break;
-
-      case VK_DYNAMIC_STATE_VIEWPORT:
-      case VK_DYNAMIC_STATE_SCISSOR:
-      case VK_DYNAMIC_STATE_LINE_WIDTH:
-      case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT:
-      case VK_DYNAMIC_STATE_CULL_MODE:
-      case VK_DYNAMIC_STATE_FRONT_FACE:
-      case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT:
-      case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT:
-      case VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT:
-      case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE:
-         if (stages & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT)
-            states[dst->dynamicStateCount++] = src->pDynamicStates[i];
-         break;
-
-      case VK_DYNAMIC_STATE_DEPTH_BIAS:
-      case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
-      case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE:
-      case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE:
-      case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP:
-      case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE:
-      case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE:
-         if (has_depth && (stages & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT))
-            states[dst->dynamicStateCount++] = src->pDynamicStates[i];
-         break;
-
-      case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
-      case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
-      case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
-      case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE:
-      case VK_DYNAMIC_STATE_STENCIL_OP:
-         if (has_stencil && (stages & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT))
-            states[dst->dynamicStateCount++] = src->pDynamicStates[i];
-         break;
-
-      case VK_DYNAMIC_STATE_LOGIC_OP_EXT:
-      case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
-      case VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT:
-         if (stages & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT)
-            states[dst->dynamicStateCount++] = src->pDynamicStates[i];
-         break;
-      default:
-         unreachable("unknown dynamic state!");
-      }
-   }
-   assert(dst->dynamicStateCount <= 37);
-   return VK_SUCCESS;
-}
-
-
-static VkResult
-deep_copy_rasterization_state(void *mem_ctx,
-                              VkPipelineRasterizationStateCreateInfo *dst,
-                              const VkPipelineRasterizationStateCreateInfo *src)
-{
-   memcpy(dst, src, sizeof(VkPipelineRasterizationStateCreateInfo));
-   dst->pNext = NULL;
-
-   if (src->pNext) {
-      vk_foreach_struct_const(ext, src->pNext) {
-         switch (ext->sType) {
-         case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT: {
-            VkPipelineRasterizationDepthClipStateCreateInfoEXT *ext_src = (VkPipelineRasterizationDepthClipStateCreateInfoEXT *)ext;
-            VkPipelineRasterizationDepthClipStateCreateInfoEXT *ext_dst = ralloc(mem_ctx, VkPipelineRasterizationDepthClipStateCreateInfoEXT);
-            ext_dst->sType = ext_src->sType;
-            ext_dst->pNext = dst->pNext;
-            ext_dst->flags = ext_src->flags;
-            ext_dst->depthClipEnable = ext_src->depthClipEnable;
-            dst->pNext = ext_dst;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT: {
-            VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *ext_src = (VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *)ext;
-            VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *ext_dst = ralloc(mem_ctx, VkPipelineRasterizationProvokingVertexStateCreateInfoEXT);
-            memcpy(ext_dst, ext_src, sizeof(*ext_dst));
-            ext_dst->pNext = dst->pNext;
-            dst->pNext = ext_dst;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT: {
-            VkPipelineRasterizationLineStateCreateInfoEXT *ext_src = (VkPipelineRasterizationLineStateCreateInfoEXT *)ext;
-            VkPipelineRasterizationLineStateCreateInfoEXT *ext_dst = ralloc(mem_ctx, VkPipelineRasterizationLineStateCreateInfoEXT);
-            memcpy(ext_dst, ext_src, sizeof(*ext_dst));
-            ext_dst->pNext = dst->pNext;
-            dst->pNext = ext_dst;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT:
-            /* do nothing */
-            break;
-         default:
-            break;
-         }
-      }
-   }
-   return VK_SUCCESS;
-}
-
-static VkResult
-deep_copy_graphics_create_info(void *mem_ctx,
-                               VkGraphicsPipelineCreateInfo *dst,
-                               const VkGraphicsPipelineCreateInfo *src,
-                               VkGraphicsPipelineLibraryFlagsEXT shaders)
-{
-   int i;
-   VkResult result;
-   VkPipelineShaderStageCreateInfo *stages;
-   VkPipelineVertexInputStateCreateInfo *vertex_input;
-   VkPipelineRasterizationStateCreateInfo *rasterization_state;
-   const VkPipelineRenderingCreateInfo *rp_info = NULL;
-
-   dst->sType = src->sType;
-   dst->pNext = NULL;
-   dst->flags = src->flags;
-   dst->layout = src->layout;
-   if (shaders & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) {
-      assert(!dst->renderPass || !src->renderPass || dst->renderPass == src->renderPass);
-      assert(!dst->subpass || !src->subpass || dst->subpass == src->subpass);
-      dst->subpass = src->subpass;
-      dst->renderPass = src->renderPass;
-      rp_info = vk_get_pipeline_rendering_create_info(src);
-      if (rp_info && !src->renderPass) {
-         VkPipelineRenderingCreateInfo *r = ralloc(mem_ctx, VkPipelineRenderingCreateInfo);
-         memcpy(r, rp_info, sizeof(VkPipelineRenderingCreateInfo));
-         r->pNext = NULL;
-         dst->pNext = r;
-      }
-   }
-   bool has_depth = false;
-   bool has_stencil = false;
-   if (rp_info) {
-      has_depth = rp_info->depthAttachmentFormat != VK_FORMAT_UNDEFINED;
-      has_stencil = rp_info->stencilAttachmentFormat != VK_FORMAT_UNDEFINED;
-   } else if ((shaders & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) &&
-              (shaders ^ VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT)) {
-      /* if this is a fragment stage without a fragment output,
-       * assume both of these exist so the dynamic states are covered,
-       * then let them be naturally pruned in the final pipeline
-       */
-      has_depth = true;
-      has_stencil = true;
-   }
-   dst->basePipelineHandle = src->basePipelineHandle;
-   dst->basePipelineIndex = src->basePipelineIndex;
-
-   /* pStages */
-   VkShaderStageFlags stages_present = 0;
-   stages = (void*)dst->pStages;
-   if (!stages)
-      stages = ralloc_array(mem_ctx, VkPipelineShaderStageCreateInfo, 5 /* max number of gfx stages */);
-   for (i = 0 ; i < src->stageCount; i++) {
-      if (shaders & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) {
-         /* only vertex stages allowed */
-         if (!(src->pStages[i].stage & BITFIELD_MASK(VK_SHADER_STAGE_FRAGMENT_BIT)))
-            continue;
-      } else if (shaders & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) {
-         /* only fragment stages allowed */
-         if (src->pStages[i].stage != VK_SHADER_STAGE_FRAGMENT_BIT)
-            continue;
-      } else {
-          /* other partials don't consume shaders */
-          continue;
-      }
-      result = deep_copy_shader_stage(mem_ctx, &stages[dst->stageCount++], &src->pStages[i]);
-      if (result != VK_SUCCESS)
-         return result;
-      stages_present |= src->pStages[i].stage;
-   }
-   dst->pStages = stages;
-
-   if (shaders & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) {
-      /* pVertexInputState */
-      if (!dynamic_state_contains(src->pDynamicState, VK_DYNAMIC_STATE_VERTEX_INPUT_EXT)) {
-         vertex_input = ralloc(mem_ctx, VkPipelineVertexInputStateCreateInfo);
-         result = deep_copy_vertex_input_state(mem_ctx, vertex_input,
-                                               src->pVertexInputState);
-         if (result != VK_SUCCESS)
-            return result;
-         dst->pVertexInputState = vertex_input;
-      } else
-         dst->pVertexInputState = NULL;
-
-      /* pInputAssemblyState */
-      LVP_PIPELINE_DUP(dst->pInputAssemblyState,
-                       src->pInputAssemblyState,
-                       VkPipelineInputAssemblyStateCreateInfo,
-                       1);
-   }
-
-   bool rasterization_disabled = false;
-   if (shaders & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) {
-      /* pTessellationState */
-      if (src->pTessellationState &&
-         (stages_present & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) ==
-                           (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) {
-         LVP_PIPELINE_DUP(dst->pTessellationState,
-                          src->pTessellationState,
-                          VkPipelineTessellationStateCreateInfo,
-                          1);
-      }
-
-      /* pViewportState */
-      rasterization_disabled = !dynamic_state_contains(src->pDynamicState, VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE) &&
-                                    src->pRasterizationState->rasterizerDiscardEnable;
-      if (src->pViewportState && !rasterization_disabled) {
-         VkPipelineViewportStateCreateInfo *viewport_state;
-         viewport_state = ralloc(mem_ctx, VkPipelineViewportStateCreateInfo);
-         if (!viewport_state)
-            return VK_ERROR_OUT_OF_HOST_MEMORY;
-         deep_copy_viewport_state(mem_ctx, src->pDynamicState,
-             viewport_state, src->pViewportState);
-         dst->pViewportState = viewport_state;
-      } else
-         dst->pViewportState = NULL;
-
-      /* pRasterizationState */
-      rasterization_state = ralloc(mem_ctx, VkPipelineRasterizationStateCreateInfo);
-      if (!rasterization_state)
-         return VK_ERROR_OUT_OF_HOST_MEMORY;
-      deep_copy_rasterization_state(mem_ctx, rasterization_state, src->pRasterizationState);
-      dst->pRasterizationState = rasterization_state;
-   }
-
-   if (shaders & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) {
-      /* pDepthStencilState */
-      if (src->pDepthStencilState && !rasterization_disabled &&
-          /*
-             VUID-VkGraphicsPipelineCreateInfo-renderPass-06053
-             * If renderPass is VK_NULL_HANDLE, the pipeline is being created with fragment shader
-               state and fragment output interface state, and either of
-               VkPipelineRenderingCreateInfo::depthAttachmentFormat
-               or
-               VkPipelineRenderingCreateInfo::stencilAttachmentFormat
-               are not VK_FORMAT_UNDEFINED, pDepthStencilState must be a valid pointer to a valid
-               VkPipelineDepthStencilStateCreateInfo structure
-
-             VUID-VkGraphicsPipelineCreateInfo-renderPass-06590
-             * If renderPass is VK_NULL_HANDLE and the pipeline is being created with fragment shader
-               state but not fragment output interface state, pDepthStencilState must be a valid pointer
-               to a valid VkPipelineDepthStencilStateCreateInfo structure
-          */
-          (has_depth || has_stencil)) {
-         LVP_PIPELINE_DUP(dst->pDepthStencilState,
-                          src->pDepthStencilState,
-                          VkPipelineDepthStencilStateCreateInfo,
-                          1);
-         VkPipelineDepthStencilStateCreateInfo *pDepthStencilState = (void*)dst->pDepthStencilState;
-         if (!has_depth) {
-            pDepthStencilState->depthTestEnable = VK_FALSE;
-            pDepthStencilState->depthWriteEnable = VK_FALSE;
-            pDepthStencilState->depthCompareOp = VK_COMPARE_OP_ALWAYS;
-            pDepthStencilState->depthBoundsTestEnable = VK_FALSE;
-         }
-         if (!has_stencil) {
-            pDepthStencilState->stencilTestEnable = VK_FALSE;
-            memset(&pDepthStencilState->front, 0, sizeof(VkStencilOpState));
-            memset(&pDepthStencilState->back, 0, sizeof(VkStencilOpState));
-         }
-      } else
-         dst->pDepthStencilState = NULL;
-   }
-
-   if (shaders & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) {
-      assert(rp_info);
-      /* pMultisampleState */
-      if (src->pMultisampleState && !rasterization_disabled) {
-         VkPipelineMultisampleStateCreateInfo*   ms_state;
-         ms_state = ralloc_size(mem_ctx, sizeof(VkPipelineMultisampleStateCreateInfo) + sizeof(VkSampleMask));
-         if (!ms_state)
-            return VK_ERROR_OUT_OF_HOST_MEMORY;
-         /* does samplemask need deep copy? */
-         memcpy(ms_state, src->pMultisampleState, sizeof(VkPipelineMultisampleStateCreateInfo));
-         if (src->pMultisampleState->pSampleMask) {
-            VkSampleMask *sample_mask = (VkSampleMask *)(ms_state + 1);
-            sample_mask[0] = src->pMultisampleState->pSampleMask[0];
-            ms_state->pSampleMask = sample_mask;
-         }
-         dst->pMultisampleState = ms_state;
-      } else
-         dst->pMultisampleState = NULL;
-
-      bool uses_color_att = false;
-      for (unsigned i = 0; i < rp_info->colorAttachmentCount; i++) {
-         if (rp_info->pColorAttachmentFormats[i] != VK_FORMAT_UNDEFINED) {
-            uses_color_att = true;
-            break;
-         }
-      }
-
-      /* pColorBlendState */
-      if (src->pColorBlendState && !rasterization_disabled && uses_color_att) {
-         VkPipelineColorBlendStateCreateInfo*    cb_state;
-
-         cb_state = ralloc(mem_ctx, VkPipelineColorBlendStateCreateInfo);
-         if (!cb_state)
-            return VK_ERROR_OUT_OF_HOST_MEMORY;
-         deep_copy_color_blend_state(mem_ctx, cb_state, src->pColorBlendState);
-         dst->pColorBlendState = cb_state;
-
-         if (!dynamic_state_contains(src->pDynamicState, VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT)) {
-            const VkPipelineColorWriteCreateInfoEXT *cw_state =
-               vk_find_struct_const(src->pColorBlendState, PIPELINE_COLOR_WRITE_CREATE_INFO_EXT);
-            if (cw_state) {
-               assert(cw_state->attachmentCount <= src->pColorBlendState->attachmentCount);
-               for (unsigned i = 0; i < cw_state->attachmentCount; i++)
-                  if (!cw_state->pColorWriteEnables[i]) {
-                     VkPipelineColorBlendAttachmentState *att = (void*)&cb_state->pAttachments[i];
-                     att->colorWriteMask = 0;
-                  }
-            }
-         }
-      } else
-         dst->pColorBlendState = NULL;
-   }
-
-   if (src->pDynamicState) {
-      VkPipelineDynamicStateCreateInfo*       dyn_state;
-
-      /* pDynamicState */
-      if (dst->pDynamicState) {
-         dyn_state = (void*)dst->pDynamicState;
-      } else {
-         dyn_state = ralloc(mem_ctx, VkPipelineDynamicStateCreateInfo);
-         VkDynamicState *states = ralloc_array(mem_ctx, VkDynamicState, 37 /* current (1.3) number of dynamic states */);
-         dyn_state->pDynamicStates = states;
-         dyn_state->dynamicStateCount = 0;
-      }
-      if (!dyn_state || !dyn_state->pDynamicStates)
-         return VK_ERROR_OUT_OF_HOST_MEMORY;
-      deep_copy_dynamic_state(mem_ctx, dyn_state, src->pDynamicState, shaders, has_depth, has_stencil);
-      dst->pDynamicState = dyn_state;
-   } else
-      dst->pDynamicState = NULL;
-
-   return VK_SUCCESS;
-}
-
-static VkResult
-deep_copy_compute_create_info(void *mem_ctx,
-                              VkComputePipelineCreateInfo *dst,
-                              const VkComputePipelineCreateInfo *src)
-{
-   VkResult result;
-   dst->sType = src->sType;
-   dst->pNext = NULL;
-   dst->flags = src->flags;
-   dst->layout = src->layout;
-   dst->basePipelineHandle = src->basePipelineHandle;
-   dst->basePipelineIndex = src->basePipelineIndex;
-
-   result = deep_copy_shader_stage(mem_ctx, &dst->stage, &src->stage);
-   if (result != VK_SUCCESS)
-      return result;
-   return VK_SUCCESS;
-}
-
 static inline unsigned
 st_shader_stage_to_ptarget(gl_shader_stage stage)
 {
@@ -1333,22 +779,15 @@ lvp_graphics_pipeline_init(struct lvp_pipeline *pipeline,
       }
    }
 
-   /* recreate createinfo */
-   if (!libstate || libinfo)
-      deep_copy_graphics_create_info(pipeline->mem_ctx, &pipeline->graphics_create_info, pCreateInfo, pipeline->stages);
    if (libstate) {
       for (unsigned i = 0; i < libstate->libraryCount; i++) {
          LVP_FROM_HANDLE(lvp_pipeline, p, libstate->pLibraries[i]);
-         deep_copy_graphics_create_info(pipeline->mem_ctx, &pipeline->graphics_create_info, &p->graphics_create_info, p->stages);
+         vk_graphics_pipeline_state_merge(&pipeline->graphics_state,
+                                          &p->graphics_state);
          if (p->stages & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) {
-            pipeline->provoking_vertex_last = p->provoking_vertex_last;
-            pipeline->line_stipple_enable = p->line_stipple_enable;
             pipeline->line_smooth = p->line_smooth;
             pipeline->disable_multisample = p->disable_multisample;
             pipeline->line_rectangular = p->line_rectangular;
-            pipeline->line_stipple_factor = p->line_stipple_factor;
-            pipeline->line_stipple_pattern = p->line_stipple_pattern;
-            pipeline->negative_one_to_one = p->negative_one_to_one;
             pipeline->last_vertex = p->last_vertex;
             memcpy(&pipeline->stream_output, &p->stream_output, sizeof(p->stream_output));
          }
@@ -1362,6 +801,14 @@ lvp_graphics_pipeline_init(struct lvp_pipeline *pipeline,
       }
    }
 
+   result = vk_graphics_pipeline_state_fill(&device->vk,
+                                            &pipeline->graphics_state,
+                                            pCreateInfo, NULL, NULL, NULL,
+                                            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT,
+                                            &pipeline->state_data);
+   if (result != VK_SUCCESS)
+      return result;
+
    assert(pipeline->library || pipeline->stages == (VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
                                                     VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT |
                                                     VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
@@ -1398,10 +845,7 @@ lvp_graphics_pipeline_init(struct lvp_pipeline *pipeline,
    if (pCreateInfo->stageCount && pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]) {
       nir_lower_patch_vertices(pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL], pipeline->pipeline_nir[MESA_SHADER_TESS_CTRL]->info.tess.tcs_vertices_out, NULL);
       merge_tess_info(&pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info, &pipeline->pipeline_nir[MESA_SHADER_TESS_CTRL]->info);
-      const VkPipelineTessellationDomainOriginStateCreateInfo *domain_origin_state =
-         vk_find_struct_const(pCreateInfo->pTessellationState,
-                              PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO);
-      if (!domain_origin_state || domain_origin_state->domainOrigin == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)
+      if (pipeline->graphics_state.ts->domain_origin == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)
          pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info.tess.ccw = !pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info.tess.ccw;
    }
    if (libstate) {
@@ -1419,41 +863,13 @@ lvp_graphics_pipeline_init(struct lvp_pipeline *pipeline,
           }
        }
    } else if (pipeline->stages & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) {
-      /* composite pipelines should have these values set above */
-      if (pipeline->graphics_create_info.pViewportState) {
-         /* if pViewportState is null, it means rasterization is discarded,
-          * so this is ignored
-          */
-         const VkPipelineViewportDepthClipControlCreateInfoEXT *ccontrol = vk_find_struct_const(pCreateInfo->pViewportState,
-                                                                                                PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT);
-         if (ccontrol)
-            pipeline->negative_one_to_one = !!ccontrol->negativeOneToOne;
-      }
-
-      const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *pv_state =
-         vk_find_struct_const(pCreateInfo->pRasterizationState,
-                              PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT);
-      pipeline->provoking_vertex_last = pv_state && pv_state->provokingVertexMode == VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT;
-
-      const VkPipelineRasterizationLineStateCreateInfoEXT *line_state =
-         vk_find_struct_const(pCreateInfo->pRasterizationState,
-                              PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT);
-      if (line_state) {
+      const struct vk_rasterization_state *rs = pipeline->graphics_state.rs;
+      if (rs) {
          /* always draw bresenham if !smooth */
-         pipeline->line_stipple_enable = line_state->stippledLineEnable;
-         pipeline->line_smooth = line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
-         pipeline->disable_multisample = line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT ||
-                                         line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
-         pipeline->line_rectangular = line_state->lineRasterizationMode != VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
-         if (pipeline->line_stipple_enable) {
-            if (!dynamic_state_contains(pipeline->graphics_create_info.pDynamicState, VK_DYNAMIC_STATE_LINE_STIPPLE_EXT)) {
-               pipeline->line_stipple_factor = line_state->lineStippleFactor - 1;
-               pipeline->line_stipple_pattern = line_state->lineStipplePattern;
-            } else {
-               pipeline->line_stipple_factor = 0;
-               pipeline->line_stipple_pattern = UINT16_MAX;
-            }
-         }
+         pipeline->line_smooth = rs->line.mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
+         pipeline->disable_multisample = rs->line.mode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT ||
+                                         rs->line.mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
+         pipeline->line_rectangular = rs->line.mode != VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
       } else
          pipeline->line_rectangular = true;
       lvp_pipeline_xfb_init(pipeline);
@@ -1461,10 +877,12 @@ lvp_graphics_pipeline_init(struct lvp_pipeline *pipeline,
 
    if (!pipeline->library) {
       bool has_fragment_shader = false;
-      for (uint32_t i = 0; i < pipeline->graphics_create_info.stageCount; i++) {
-         const VkPipelineShaderStageCreateInfo *sinfo =
-            &pipeline->graphics_create_info.pStages[i];
-         gl_shader_stage stage = vk_to_mesa_shader_stage(sinfo->stage);
+      for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->pipeline_nir); i++) {
+         if (!pipeline->pipeline_nir[i])
+            continue;
+
+         gl_shader_stage stage = i;
+         assert(stage == pipeline->pipeline_nir[i]->info.stage);
          enum pipe_shader_type pstage = pipe_shader_type_from_mesa(stage);
          if (!pipeline->inlines[stage].can_inline)
             pipeline->shader_cso[pstage] = lvp_pipeline_compile(pipeline,
@@ -1492,6 +910,7 @@ fail:
       if (pipeline->pipeline_nir[i])
          ralloc_free(pipeline->pipeline_nir[i]);
    }
+   vk_free(&device->vk.alloc, pipeline->state_data);
 
    return result;
 }
@@ -1581,8 +1000,6 @@ lvp_compute_pipeline_init(struct lvp_pipeline *pipeline,
    pipeline->force_min_sample = false;
 
    pipeline->mem_ctx = ralloc_context(NULL);
-   deep_copy_compute_create_info(pipeline->mem_ctx,
-                                 &pipeline->compute_create_info, pCreateInfo);
    pipeline->is_compute_pipeline = true;
 
    VkResult result = lvp_shader_compile_to_ir(pipeline, &pCreateInfo->stage);
index 24f6df0..9f0ad0d 100644 (file)
@@ -68,6 +68,7 @@ typedef uint32_t xcb_window_t;
 #include "vk_command_buffer.h"
 #include "vk_command_pool.h"
 #include "vk_descriptor_set_layout.h"
+#include "vk_graphics_state.h"
 #include "vk_pipeline_layout.h"
 #include "vk_queue.h"
 #include "vk_sync.h"
@@ -431,6 +432,7 @@ struct lvp_pipeline {
    struct lvp_access_info access[MESA_SHADER_STAGES];
 
    void *mem_ctx;
+   void *state_data;
    bool is_compute_pipeline;
    bool force_min_sample;
    nir_shader *pipeline_nir[MESA_SHADER_STAGES];
@@ -443,18 +445,12 @@ struct lvp_pipeline {
    } inlines[MESA_SHADER_STAGES];
    gl_shader_stage last_vertex;
    struct pipe_stream_output_info stream_output;
-   VkGraphicsPipelineCreateInfo graphics_create_info;
-   VkComputePipelineCreateInfo compute_create_info;
+   struct vk_graphics_pipeline_state graphics_state;
    VkGraphicsPipelineLibraryFlagsEXT stages;
-   uint32_t line_stipple_factor;
-   uint16_t line_stipple_pattern;
-   bool line_stipple_enable;
    bool line_smooth;
    bool disable_multisample;
    bool line_rectangular;
    bool gs_output_lines;
-   bool provoking_vertex_last;
-   bool negative_one_to_one;
    bool library;
 };