From a5b8466e4a8713974d0cd627d8656a0d8a7cb09e Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 14 Jun 2022 16:13:23 -0400 Subject: [PATCH] zink: use more dynamic state3 when available 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 Part-of: --- src/gallium/drivers/zink/zink_context.c | 14 +++- src/gallium/drivers/zink/zink_draw.cpp | 17 +++++ src/gallium/drivers/zink/zink_pipeline.c | 92 +++++++++++++++--------- src/gallium/drivers/zink/zink_screen.c | 9 +++ src/gallium/drivers/zink/zink_state.c | 11 ++- src/gallium/drivers/zink/zink_state.h | 1 + src/gallium/drivers/zink/zink_types.h | 8 +++ 7 files changed, 116 insertions(+), 36 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index f04542e3406..e284307ed16 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -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); diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp index dbdba63e32f..fad7673c12c 100644 --- a/src/gallium/drivers/zink/zink_draw.cpp +++ b/src/gallium/drivers/zink/zink_draw.cpp @@ -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; diff --git a/src/gallium/drivers/zink/zink_pipeline.c b/src/gallium/drivers/zink/zink_pipeline.c index 6d0919d75a0..e15ae75b527 100644 --- a/src/gallium/drivers/zink/zink_pipeline.c +++ b/src/gallium/drivers/zink/zink_pipeline.c @@ -35,16 +35,6 @@ #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}; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index c3af5e9bd42..25ef76540d6 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -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 && diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index 8b2559978b7..db5c17f374a 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -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) diff --git a/src/gallium/drivers/zink/zink_state.h b/src/gallium/drivers/zink/zink_state.h index 53a149635a0..6052bdf60b7 100644 --- a/src/gallium/drivers/zink/zink_state.h +++ b/src/gallium/drivers/zink/zink_state.h @@ -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 diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 4968ffa26cb..4fe2ee32f81 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -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;