From 80285db9efe16beefc59a470b7c53d7bd38dbdc4 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Tue, 6 Dec 2022 08:54:34 +0100 Subject: [PATCH] zink: lower smooth-lines if not supported This implements line-smoothing the same way as the draw-module does, except using a geometry shader instead of a CPU pass. Ideally, this should be enabled either by checking for the various smooth-line caps, or by a DRIconf setting. Unfortunately, RADV doesn't support he smooth-lines features, and we don't want to force it down a pessimistic shader-key code-path. So that plan is out the window for now. While DRIconf is also neat, it's a bit of work to wire up, and we don't really know of any real-world applications who would need this yet. So, for now, let's just unconditionally enable is on the IMG proprietary driver, which is going to need this for sure. Part-of: --- src/gallium/drivers/zink/zink_compiler.c | 13 +++++++++++++ src/gallium/drivers/zink/zink_draw.cpp | 19 +++++++++++++++++-- src/gallium/drivers/zink/zink_pipeline.c | 3 ++- src/gallium/drivers/zink/zink_program.c | 14 +++++++++++++- src/gallium/drivers/zink/zink_screen.c | 7 +++++++ src/gallium/drivers/zink/zink_shader_keys.h | 4 +++- src/gallium/drivers/zink/zink_state.c | 3 ++- src/gallium/drivers/zink/zink_types.h | 1 + 8 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index cd96cd1985a..9f895c2b03f 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -2801,6 +2801,13 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shad NIR_PASS_V(nir, nir_lower_var_copies); need_optimize = true; } + + if (zink_gs_key(key)->lower_line_smooth) { + NIR_PASS_V(nir, lower_line_smooth_gs); + NIR_PASS_V(nir, nir_lower_var_copies); + need_optimize = true; + } + if (zink_gs_key(key)->lower_gl_point) { NIR_PASS_V(nir, lower_gl_point_gs); need_optimize = true; @@ -2831,6 +2838,12 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shad case MESA_SHADER_FRAGMENT: if (zink_fs_key(key)->lower_line_stipple) NIR_PASS_V(nir, lower_line_stipple_fs); + + if (zink_fs_key(key)->lower_line_smooth) { + NIR_PASS_V(nir, lower_line_smooth_fs); + need_optimize = true; + } + if (!zink_fs_key(key)->samples && nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK)) { /* VK will always use gl_SampleMask[] values even if sample count is 0, diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp index 3caf7cd00f8..81a03aae9dd 100644 --- a/src/gallium/drivers/zink/zink_draw.cpp +++ b/src/gallium/drivers/zink/zink_draw.cpp @@ -803,8 +803,14 @@ zink_draw(struct pipe_context *pctx, &ctx->tess_levels[0]); } if (zink_get_fs_key(ctx)->lower_line_stipple || - zink_get_gs_key(ctx)->lower_gl_point) { - assert(zink_get_fs_key(ctx)->lower_line_stipple == zink_get_gs_key(ctx)->lower_line_stipple); + zink_get_gs_key(ctx)->lower_gl_point || + zink_get_fs_key(ctx)->lower_line_smooth) { + + assert(zink_get_gs_key(ctx)->lower_line_stipple == + zink_get_fs_key(ctx)->lower_line_stipple); + + assert(zink_get_gs_key(ctx)->lower_line_smooth == + zink_get_fs_key(ctx)->lower_line_smooth); float viewport_scale[2] = { ctx->vp_state.viewport_states[0].scale[0], @@ -823,6 +829,15 @@ zink_draw(struct pipe_context *pctx, VK_SHADER_STAGE_ALL_GRAPHICS, offsetof(struct zink_gfx_push_constant, line_stipple_pattern), sizeof(uint32_t), &stipple); + + if (ctx->gfx_pipeline_state.shader_keys.key[MESA_SHADER_FRAGMENT].key.fs.lower_line_smooth) { + float line_width = ctx->rast_state->base.line_width; + VKCTX(CmdPushConstants)(batch->state->cmdbuf, + ctx->curr_program->base.layout, + VK_SHADER_STAGE_ALL_GRAPHICS, + offsetof(struct zink_gfx_push_constant, line_width), + sizeof(uint32_t), &line_width); + } } if (have_streamout) { diff --git a/src/gallium/drivers/zink/zink_pipeline.c b/src/gallium/drivers/zink/zink_pipeline.c index 984a276ee69..1ce5291c730 100644 --- a/src/gallium/drivers/zink/zink_pipeline.c +++ b/src/gallium/drivers/zink/zink_pipeline.c @@ -268,7 +268,8 @@ zink_create_gfx_pipeline(struct zink_screen *screen, assert(state->rast_prim != PIPE_PRIM_MAX); VkPipelineRasterizationLineStateCreateInfoEXT rast_line_state; - if (screen->info.have_EXT_line_rasterization) { + if (screen->info.have_EXT_line_rasterization && + !state->shader_keys.key[MESA_SHADER_FRAGMENT].key.fs.lower_line_smooth) { rast_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT; rast_line_state.pNext = rast_state.pNext; rast_line_state.stippledLineEnable = VK_FALSE; diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index 93c8fa4d284..898ca6c617e 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -1851,7 +1851,19 @@ zink_set_primitive_emulation_keys(struct zink_context *ctx) zink_set_gs_key(ctx)->lower_line_stipple = lower_line_stipple; } - if (lower_line_stipple || zink_get_gs_key(ctx)->lower_gl_point) { + bool lower_line_smooth = screen->driver_workarounds.no_linesmooth && + ctx->rast_state->base.line_smooth && + !ctx->num_so_targets; + + if (zink_get_fs_key(ctx)->lower_line_smooth != lower_line_smooth) { + assert(zink_get_gs_key(ctx)->lower_line_smooth == + zink_get_fs_key(ctx)->lower_line_smooth); + zink_set_fs_key(ctx)->lower_line_smooth = lower_line_smooth; + zink_set_gs_key(ctx)->lower_line_smooth = lower_line_smooth; + } + + if (lower_line_stipple || lower_line_smooth || + zink_get_gs_key(ctx)->lower_gl_point) { enum pipe_shader_type prev_vertex_stage = ctx->gfx_stages[MESA_SHADER_TESS_EVAL] ? MESA_SHADER_TESS_EVAL : MESA_SHADER_VERTEX; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 8093891ae0c..a2af79c6954 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -2349,6 +2349,12 @@ init_driver_workarounds(struct zink_screen *screen) screen->driver_workarounds.no_linestipple = true; } + if (screen->info.driver_props.driverID == + VK_DRIVER_ID_IMAGINATION_PROPRIETARY) { + assert(screen->info.feats.features.geometryShader); + screen->driver_workarounds.no_linesmooth = true; + } + /* This is a workarround for the lack of * gl_PointSize + glPolygonMode(..., GL_LINE), in the imagination * proprietary driver. @@ -2731,6 +2737,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config) screen->info.have_EXT_non_seamless_cube_map && !screen->driconf.inline_uniforms && !screen->driver_workarounds.no_linestipple && + !screen->driver_workarounds.no_linesmooth && !screen->driver_workarounds.no_hw_gl_point; if (!screen->optimal_keys) screen->info.have_EXT_graphics_pipeline_library = false; diff --git a/src/gallium/drivers/zink/zink_shader_keys.h b/src/gallium/drivers/zink/zink_shader_keys.h index 93cfec503fc..01e6e23af81 100644 --- a/src/gallium/drivers/zink/zink_shader_keys.h +++ b/src/gallium/drivers/zink/zink_shader_keys.h @@ -60,6 +60,7 @@ struct zink_gs_key { struct zink_vs_key_base base; uint8_t pad; bool lower_line_stipple : 1; + bool lower_line_smooth : 1; bool lower_gl_point : 1; // not hashed unsigned size; @@ -72,7 +73,8 @@ struct zink_fs_key { bool force_persample_interp : 1; bool fbfetch_ms : 1; bool lower_line_stipple : 1; - uint8_t pad : 2; + bool lower_line_smooth : 1; + uint8_t pad : 1; uint8_t coord_replace_bits; }; diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c index f1d0351bb1c..f3aa4bfb9a7 100644 --- a/src/gallium/drivers/zink/zink_state.c +++ b/src/gallium/drivers/zink/zink_state.c @@ -617,7 +617,8 @@ zink_create_rasterizer_state(struct pipe_context *pctx, state->hw_state.line_mode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT; if (rs_state->line_rectangular) { - if (rs_state->line_smooth) + if (rs_state->line_smooth && + !screen->driver_workarounds.no_linesmooth) state->hw_state.line_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT; else state->hw_state.line_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT; diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 7f81b9d6186..902badf5436 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -1284,6 +1284,7 @@ struct zink_screen { bool needs_sanitised_layer; bool track_renderpasses; bool no_linestipple; + bool no_linesmooth; bool no_hw_gl_point; unsigned z16_unscaled_bias; unsigned z24_unscaled_bias;