zink: use more dynamic state3 when available
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Tue, 14 Jun 2022 20:13:23 +0000 (16:13 -0400)
committerMarge Bot <emma+marge@anholt.net>
Fri, 30 Sep 2022 23:17:25 +0000 (23:17 +0000)
this is an all-or-nothing type of thing, where either all the blend/ms
states are available or they aren't

Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18890>

src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_draw.cpp
src/gallium/drivers/zink/zink_pipeline.c
src/gallium/drivers/zink/zink_screen.c
src/gallium/drivers/zink/zink_state.c
src/gallium/drivers/zink/zink_state.h
src/gallium/drivers/zink/zink_types.h

index f04542e..e284307 100644 (file)
@@ -2879,6 +2879,7 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
                            const struct pipe_framebuffer_state *state)
 {
    struct zink_context *ctx = zink_context(pctx);
+   struct zink_screen *screen = zink_screen(pctx->screen);
    unsigned samples = state->nr_cbufs || state->zsbuf ? 0 : state->samples;
    unsigned w = ctx->fb_state.width;
    unsigned h = ctx->fb_state.height;
@@ -2932,6 +2933,8 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
    /* renderpass changes if the number or types of attachments change */
    ctx->rp_changed |= ctx->fb_state.nr_cbufs != state->nr_cbufs;
    ctx->rp_changed |= !!ctx->fb_state.zsbuf != !!state->zsbuf;
+   if (ctx->fb_state.nr_cbufs != state->nr_cbufs)
+      ctx->blend_state_changed |= screen->have_full_ds3;
 
    util_copy_framebuffer_state(&ctx->fb_state, state);
    zink_update_fbfetch(ctx);
@@ -3030,7 +3033,10 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
       zink_update_fs_key_samples(ctx);
    if (ctx->gfx_pipeline_state.rast_samples != rast_samples) {
       ctx->sample_locations_changed |= ctx->gfx_pipeline_state.sample_locations_enabled;
-      ctx->gfx_pipeline_state.dirty = true;
+      if (screen->have_full_ds3)
+         ctx->sample_mask_changed = true;
+      else
+         ctx->gfx_pipeline_state.dirty = true;
    }
    ctx->gfx_pipeline_state.rast_samples = rast_samples;
 
@@ -3054,7 +3060,10 @@ zink_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
 {
    struct zink_context *ctx = zink_context(pctx);
    ctx->gfx_pipeline_state.sample_mask = sample_mask;
-   ctx->gfx_pipeline_state.dirty = true;
+   if (zink_screen(pctx->screen)->have_full_ds3)
+      ctx->sample_mask_changed = true;
+   else
+      ctx->gfx_pipeline_state.dirty = true;
 }
 
 static void
@@ -4631,6 +4640,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
                                                  screen->info.have_EXT_vertex_input_dynamic_state;
    ctx->compute_pipeline_state.dirty = true;
    ctx->fb_changed = ctx->rp_changed = true;
+   ctx->sample_mask_changed = true;
    ctx->gfx_pipeline_state.gfx_prim_mode = PIPE_PRIM_MAX;
 
    zink_init_draw_functions(ctx, screen);
index dbdba63..fad7673 100644 (file)
@@ -647,6 +647,23 @@ zink_draw(struct pipe_context *pctx,
       VKCTX(CmdSetLineRasterizationModeEXT)(batch->state->cmdbuf, (VkLineRasterizationModeEXT)rast_state->hw_state.line_mode);
       VKCTX(CmdSetLineStippleEnableEXT)(batch->state->cmdbuf, rast_state->hw_state.line_stipple_enable);
    }
+   if ((BATCH_CHANGED || ctx->sample_mask_changed) && screen->have_full_ds3) {
+      VKCTX(CmdSetRasterizationSamplesEXT)(batch->state->cmdbuf, (VkSampleCountFlagBits)(ctx->gfx_pipeline_state.rast_samples + 1));
+      VKCTX(CmdSetSampleMaskEXT)(batch->state->cmdbuf, (VkSampleCountFlagBits)(ctx->gfx_pipeline_state.rast_samples + 1), &ctx->gfx_pipeline_state.sample_mask);
+      ctx->sample_mask_changed = false;
+   }
+   if ((BATCH_CHANGED || ctx->blend_state_changed) && screen->have_full_ds3) {
+      if (ctx->gfx_pipeline_state.blend_state) {
+         VKCTX(CmdSetAlphaToCoverageEnableEXT)(batch->state->cmdbuf, ctx->gfx_pipeline_state.blend_state->alpha_to_coverage);
+         if (screen->info.feats.features.alphaToOne)
+            VKCTX(CmdSetAlphaToOneEnableEXT)(batch->state->cmdbuf, ctx->gfx_pipeline_state.blend_state->alpha_to_one);
+         VKCTX(CmdSetColorBlendEnableEXT)(batch->state->cmdbuf, 0, ctx->fb_state.nr_cbufs, ctx->gfx_pipeline_state.blend_state->ds3.enables);
+         VKCTX(CmdSetColorWriteMaskEXT)(batch->state->cmdbuf, 0, ctx->fb_state.nr_cbufs, ctx->gfx_pipeline_state.blend_state->ds3.wrmask);
+         VKCTX(CmdSetColorBlendEquationEXT)(batch->state->cmdbuf, 0, ctx->fb_state.nr_cbufs, ctx->gfx_pipeline_state.blend_state->ds3.eq);
+         VKCTX(CmdSetLogicOpEnableEXT)(batch->state->cmdbuf, ctx->gfx_pipeline_state.blend_state->logicop_enable);
+         VKCTX(CmdSetLogicOpEXT)(batch->state->cmdbuf, ctx->gfx_pipeline_state.blend_state->logicop_func);
+      }
+   }
 
    if (BATCH_CHANGED || rast_state_changed) {
       enum pipe_prim_type reduced_prim = ctx->last_vertex_stage->reduced_prim;
index 6d0919d..e15ae75 100644 (file)
 #include "util/u_debug.h"
 #include "util/u_prim.h"
 
-static VkBlendFactor
-clamp_void_blend_factor(VkBlendFactor f)
-{
-   if (f == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA)
-      return VK_BLEND_FACTOR_ZERO;
-   if (f == VK_BLEND_FACTOR_DST_ALPHA)
-      return VK_BLEND_FACTOR_ONE;
-   return f;
-}
-
 VkPipeline
 zink_create_gfx_pipeline(struct zink_screen *screen,
                          struct zink_gfx_program *prog,
@@ -210,7 +200,7 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
    depth_stencil_state.back = state->dyn_state1.depth_stencil_alpha_state->stencil_back;
    depth_stencil_state.depthWriteEnable = state->dyn_state1.depth_stencil_alpha_state->depth_write;
 
-   VkDynamicState dynamicStateEnables[64] = {
+   VkDynamicState dynamicStateEnables[80] = {
       VK_DYNAMIC_STATE_LINE_WIDTH,
       VK_DYNAMIC_STATE_DEPTH_BIAS,
       VK_DYNAMIC_STATE_BLEND_CONSTANTS,
@@ -257,6 +247,20 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT;
       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT;
       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
+      if (screen->have_full_ds3) {
+         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SAMPLE_MASK_EXT;
+         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT;
+         if (state->blend_state) {
+            dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LOGIC_OP_EXT;
+            dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT;
+            dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT;
+            if (screen->info.feats.features.alphaToOne)
+               dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT;
+            dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT;
+            dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT;
+            dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT;
+         }
+      }
    }
    if (screen->info.have_EXT_color_write_enable)
       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
@@ -454,32 +458,12 @@ zink_create_gfx_pipeline_output(struct zink_screen *screen, struct zink_gfx_pipe
 
    VkPipelineColorBlendStateCreateInfo blend_state = {0};
    blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
-   if (state->blend_state) {
-      unsigned num_attachments = state->rendering_info.colorAttachmentCount;
-      blend_state.pAttachments = state->blend_state->attachments;
-      blend_state.attachmentCount = num_attachments;
-      blend_state.logicOpEnable = state->blend_state->logicop_enable;
+   blend_state.attachmentCount = state->rendering_info.colorAttachmentCount;
+   if (state->blend_state)
       blend_state.logicOp = state->blend_state->logicop_func;
-   }
 
    VkPipelineMultisampleStateCreateInfo ms_state = {0};
    ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
-   ms_state.rasterizationSamples = state->rast_samples + 1;
-   if (state->blend_state) {
-      ms_state.alphaToCoverageEnable = state->blend_state->alpha_to_coverage;
-      if (state->blend_state->alpha_to_one && !screen->info.feats.features.alphaToOne) {
-         static bool warned = false;
-         warn_missing_feature(warned, "alphaToOne");
-      }
-      ms_state.alphaToOneEnable = state->blend_state->alpha_to_one;
-   }
-   /* "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
-    * - Chapter 27. Rasterization
-    * 
-    * thus it never makes sense to leave this as NULL since gallium will provide correct
-    * data here as long as sample_mask is initialized on context creation
-    */
-   ms_state.pSampleMask = &state->sample_mask;
    if (state->force_persample_interp) {
       ms_state.sampleShadingEnable = VK_TRUE;
       ms_state.minSampleShading = 1.0;
@@ -498,6 +482,48 @@ zink_create_gfx_pipeline_output(struct zink_screen *screen, struct zink_gfx_pipe
    }
    if (screen->info.have_EXT_color_write_enable)
       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
+
+   if (screen->have_full_ds3) {
+      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SAMPLE_MASK_EXT;
+      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT;
+      if (state->blend_state) {
+         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LOGIC_OP_EXT;
+         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT;
+         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT;
+         if (screen->info.feats.features.alphaToOne)
+            dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT;
+         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT;
+         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT;
+         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT;
+      }
+   } else {
+      if (state->blend_state) {
+         unsigned num_attachments = state->render_pass ?
+                                    state->render_pass->state.num_rts :
+                                    state->rendering_info.colorAttachmentCount;
+         if (state->render_pass && state->render_pass->state.have_zsbuf)
+            num_attachments--;
+         blend_state.pAttachments = state->blend_state->attachments;
+         blend_state.attachmentCount = num_attachments;
+         blend_state.logicOpEnable = state->blend_state->logicop_enable;
+         blend_state.logicOp = state->blend_state->logicop_func;
+
+         ms_state.alphaToCoverageEnable = state->blend_state->alpha_to_coverage;
+         if (state->blend_state->alpha_to_one && !screen->info.feats.features.alphaToOne) {
+            static bool warned = false;
+            warn_missing_feature(warned, "alphaToOne");
+         }
+         ms_state.alphaToOneEnable = state->blend_state->alpha_to_one;
+      }
+      ms_state.rasterizationSamples = state->rast_samples + 1;
+      /* "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
+       * - Chapter 27. Rasterization
+       * 
+       * thus it never makes sense to leave this as NULL since gallium will provide correct
+       * data here as long as sample_mask is initialized on context creation
+       */
+      ms_state.pSampleMask = &state->sample_mask;
+   }
    assert(state_count < ARRAY_SIZE(dynamicStateEnables));
 
    VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0};
index c3af5e9..25ef765 100644 (file)
@@ -2250,6 +2250,15 @@ init_driver_workarounds(struct zink_screen *screen)
        !screen->info.dynamic_state3_feats.extendedDynamicState3ProvokingVertexMode ||
        !screen->info.dynamic_state3_feats.extendedDynamicState3LineRasterizationMode)
       screen->info.have_EXT_extended_dynamic_state3 = false;
+   else if (screen->info.dynamic_state3_feats.extendedDynamicState3SampleMask &&
+            screen->info.dynamic_state3_feats.extendedDynamicState3AlphaToCoverageEnable &&
+            (!screen->info.feats.features.alphaToOne || screen->info.dynamic_state3_feats.extendedDynamicState3AlphaToOneEnable) &&
+            screen->info.dynamic_state3_feats.extendedDynamicState3ColorBlendEnable &&
+            screen->info.dynamic_state3_feats.extendedDynamicState3RasterizationSamples &&
+            screen->info.dynamic_state3_feats.extendedDynamicState3ColorWriteMask &&
+            screen->info.dynamic_state3_feats.extendedDynamicState3LogicOpEnable &&
+            screen->info.dynamic_state2_feats.extendedDynamicState2LogicOp)
+      screen->have_full_ds3 = true;
    if (screen->info.have_EXT_graphics_pipeline_library)
       screen->info.have_EXT_graphics_pipeline_library = screen->info.have_EXT_extended_dynamic_state &&
                                                         screen->info.have_EXT_extended_dynamic_state2 &&
index 8b25599..db5c17f 100644 (file)
@@ -406,6 +406,15 @@ zink_create_blend_state(struct pipe_context *pctx,
          att.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
 
       cso->attachments[i] = att;
+
+      cso->ds3.enables[i] = att.blendEnable;
+      cso->ds3.eq[i].alphaBlendOp = att.alphaBlendOp;
+      cso->ds3.eq[i].dstAlphaBlendFactor = att.dstAlphaBlendFactor;
+      cso->ds3.eq[i].srcAlphaBlendFactor = att.srcAlphaBlendFactor;
+      cso->ds3.eq[i].colorBlendOp = att.colorBlendOp;
+      cso->ds3.eq[i].dstColorBlendFactor = att.dstColorBlendFactor;
+      cso->ds3.eq[i].srcColorBlendFactor = att.srcColorBlendFactor;
+      cso->ds3.wrmask[i] = att.colorWriteMask;
    }
    cso->dual_src_blend = util_blend_state_is_dual(blend_state, 0);
 
@@ -422,7 +431,7 @@ zink_bind_blend_state(struct pipe_context *pctx, void *cso)
    if (state->blend_state != cso) {
       state->blend_state = cso;
       state->blend_id = blend ? blend->hash : 0;
-      state->dirty = true;
+      state->dirty |= !zink_screen(pctx->screen)->have_full_ds3;
       bool force_dual_color_blend = zink_screen(pctx->screen)->driconf.dual_color_blend_by_location &&
                                     blend && blend->dual_src_blend && state->blend_state->attachments[0].blendEnable;
       if (force_dual_color_blend != zink_get_fs_key(ctx)->force_dual_color_blend)
index 53a1496..6052bdf 100644 (file)
@@ -56,6 +56,7 @@ zink_cache_vertex_state_destroy(struct pipe_screen *pscreen, struct pipe_vertex_
 const struct zink_vertex_elements_hw_state *
 zink_vertex_state_mask(struct pipe_vertex_state *vstate, uint32_t partial_velem_mask, bool have_EXT_vertex_input_dynamic_state);
 
+
 #ifdef __cplusplus
 }
 #endif
index 4968ffa..4fe2ee3 100644 (file)
@@ -274,6 +274,12 @@ struct zink_blend_state {
    uint32_t hash;
    VkPipelineColorBlendAttachmentState attachments[PIPE_MAX_COLOR_BUFS];
 
+   struct {
+      VkBool32 enables[PIPE_MAX_COLOR_BUFS];
+      VkColorBlendEquationEXT eq[PIPE_MAX_COLOR_BUFS];
+      VkColorComponentFlags wrmask[PIPE_MAX_COLOR_BUFS];
+   } ds3;
+
    VkBool32 logicop_enable;
    VkLogicOp logicop_func;
 
@@ -1134,6 +1140,7 @@ struct zink_screen {
    struct nir_shader_compiler_options nir_options;
 
    bool optimal_keys;
+   bool have_full_ds3;
    bool have_X8_D24_UNORM_PACK32;
    bool have_D24_UNORM_S8_UINT;
    bool have_D32_SFLOAT_S8_UINT;
@@ -1573,6 +1580,7 @@ struct zink_context {
    bool primitive_restart;
    bool vertex_state_changed : 1;
    bool blend_state_changed : 1;
+   bool sample_mask_changed : 1;
    bool rast_state_changed : 1;
    bool dsa_state_changed : 1;
    bool stencil_ref_changed : 1;