From 4fabd37a3c83f39957ac3e8cc5772cec48c8a048 Mon Sep 17 00:00:00 2001 From: Erik Faye-Lund Date: Thu, 27 Feb 2025 15:28:32 +0100 Subject: [PATCH] panvk: enable KHR_line_rasterization support This allows users to toggle between rectangular and bresenham style rasterization. The bresenham style rasterization is performed by disabling multisampling and changing the end-points to be axis-aligned. This is similar to what we already do in Gallium. Acked-by: Boris Brezillon Reviewed-by: Mary Guillemard Reviewed-by: Benjamin Lee Part-of: --- docs/features.txt | 2 +- docs/relnotes/new_features.txt | 1 + src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c | 32 ++++++++++++++++++--- src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c | 24 ++++++++++++++-- src/panfrost/vulkan/panvk_physical_device.c | 9 ++++++ 5 files changed, 61 insertions(+), 7 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index 460ddc48ba0..36a68620c6c 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -513,7 +513,7 @@ Vulkan 1.4 -- all DONE: anv, lvp, nvk, radv/gfx8+, tu/a7xx+, vn VK_KHR_dynamic_rendering_local_read DONE (anv, lvp, nvk, radv, tu, vn) VK_KHR_global_priority DONE (anv, lvp, nvk, panvk, radv, tu, vn) VK_KHR_index_type_uint8 DONE (anv, lvp, nvk, panvk, pvr, radv, tu, v3dv, vn) - VK_KHR_line_rasterization DONE (anv, lvp, nvk, radv, tu, v3dv, vn) + VK_KHR_line_rasterization DONE (anv, lvp, nvk, panvk, radv, tu, v3dv, vn) VK_KHR_load_store_op_none DONE (anv, lvp, nvk, radv, tu, v3dv, vn) VK_KHR_maintenance5 DONE (anv, lvp, nvk, radv, tu, v3dv, vn) VK_KHR_maintenance6 DONE (anv, lvp, nvk, radv, tu, vn) diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index e77298691aa..2e28911b971 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -25,3 +25,4 @@ EXT_shader_framebuffer_image_fetch_coherent on v3d KHR_blend_equation_advanced on v3d KHR_blend_equation_advanced_coherent on v3d KHR_partial_update on etnaviv +VK_KHR_line_rasterization on panvk diff --git a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c index db07997c0f1..9a77a88c6fd 100644 --- a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c @@ -1464,6 +1464,7 @@ prepare_dcd(struct panvk_cmd_buffer *cmdbuf) bool dcd0_dirty = dyn_gfx_state_dirty(cmdbuf, RS_RASTERIZER_DISCARD_ENABLE) || dyn_gfx_state_dirty(cmdbuf, RS_CULL_MODE) || + dyn_gfx_state_dirty(cmdbuf, RS_LINE_MODE) || dyn_gfx_state_dirty(cmdbuf, RS_FRONT_FACE) || dyn_gfx_state_dirty(cmdbuf, MS_RASTERIZATION_SAMPLES) || dyn_gfx_state_dirty(cmdbuf, MS_SAMPLE_MASK) || @@ -1477,10 +1478,15 @@ prepare_dcd(struct panvk_cmd_buffer *cmdbuf) dyn_gfx_state_dirty(cmdbuf, DS_STENCIL_TEST_ENABLE) || dyn_gfx_state_dirty(cmdbuf, DS_STENCIL_OP) || dyn_gfx_state_dirty(cmdbuf, DS_STENCIL_WRITE_MASK) || + /* line mode needs primitive topology */ + dyn_gfx_state_dirty(cmdbuf, IA_PRIMITIVE_TOPOLOGY) || fs_user_dirty(cmdbuf) || gfx_state_dirty(cmdbuf, RENDER_STATE) || gfx_state_dirty(cmdbuf, OQ); bool dcd1_dirty = dyn_gfx_state_dirty(cmdbuf, MS_RASTERIZATION_SAMPLES) || dyn_gfx_state_dirty(cmdbuf, MS_SAMPLE_MASK) || + /* line mode needs primitive topology */ + dyn_gfx_state_dirty(cmdbuf, RS_LINE_MODE) || + dyn_gfx_state_dirty(cmdbuf, IA_PRIMITIVE_TOPOLOGY) || fs_user_dirty(cmdbuf) || gfx_state_dirty(cmdbuf, RENDER_STATE); @@ -1488,10 +1494,27 @@ prepare_dcd(struct panvk_cmd_buffer *cmdbuf) &cmdbuf->vk.dynamic_graphics_state; const struct vk_rasterization_state *rs = &cmdbuf->vk.dynamic_graphics_state.rs; + const struct vk_input_assembly_state *ia = + &cmdbuf->vk.dynamic_graphics_state.ia; + bool alpha_to_coverage = dyns->ms.alpha_to_coverage_enable; bool writes_z = writes_depth(cmdbuf); bool writes_s = writes_stencil(cmdbuf); + bool msaa = dyns->ms.rasterization_samples > 1; + if ((ia->primitive_topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST || + ia->primitive_topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) && + rs->line.mode == VK_LINE_RASTERIZATION_MODE_BRESENHAM) { + /* we need to disable MSAA when rendering bresenham lines. + * + * From the Vulkan spec: + * "When Bresenham lines are being rasterized, sample locations may + * all be treated as being at the pixel center (this may affect + * attribute and depth interpolation)."" + */ + msaa = false; + } + if (dcd0_dirty) { struct mali_dcd_flags_0_packed dcd0; pan_pack(&dcd0, DCD_FLAGS_0, cfg) { @@ -1530,11 +1553,14 @@ prepare_dcd(struct panvk_cmd_buffer *cmdbuf) cfg.overdraw_alpha1 = true; } + if (rs->line.mode == VK_LINE_RASTERIZATION_MODE_BRESENHAM) + cfg.aligned_line_ends = true; + cfg.front_face_ccw = rs->front_face == VK_FRONT_FACE_COUNTER_CLOCKWISE; cfg.cull_front_face = (rs->cull_mode & VK_CULL_MODE_FRONT_BIT) != 0; cfg.cull_back_face = (rs->cull_mode & VK_CULL_MODE_BACK_BIT) != 0; - cfg.multisample_enable = dyns->ms.rasterization_samples > 1; + cfg.multisample_enable = msaa; cfg.occlusion_query = cmdbuf->state.gfx.occlusion_query.mode; cfg.alpha_to_coverage = alpha_to_coverage; } @@ -1546,9 +1572,7 @@ prepare_dcd(struct panvk_cmd_buffer *cmdbuf) if (dcd1_dirty) { struct mali_dcd_flags_1_packed dcd1; pan_pack(&dcd1, DCD_FLAGS_1, cfg) { - cfg.sample_mask = dyns->ms.rasterization_samples > 1 - ? dyns->ms.sample_mask - : UINT16_MAX; + cfg.sample_mask = msaa ? dyns->ms.sample_mask : UINT16_MAX; if (fs) { cfg.render_target_mask = diff --git a/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c index e17c24c08c8..873684c3e82 100644 --- a/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c @@ -185,6 +185,9 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, dyn_gfx_state_dirty(cmdbuf, RS_DEPTH_CLIP_ENABLE) || dyn_gfx_state_dirty(cmdbuf, RS_DEPTH_BIAS_ENABLE) || dyn_gfx_state_dirty(cmdbuf, RS_DEPTH_BIAS_FACTORS) || + dyn_gfx_state_dirty(cmdbuf, RS_LINE_MODE) || + /* line mode needs primitive topology */ + dyn_gfx_state_dirty(cmdbuf, IA_PRIMITIVE_TOPOLOGY) || dyn_gfx_state_dirty(cmdbuf, CB_LOGIC_OP_ENABLE) || dyn_gfx_state_dirty(cmdbuf, CB_LOGIC_OP) || dyn_gfx_state_dirty(cmdbuf, CB_ATTACHMENT_COUNT) || @@ -219,6 +222,7 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, const struct vk_rasterization_state *rs = &dyns->rs; const struct vk_color_blend_state *cb = &dyns->cb; const struct vk_depth_stencil_state *ds = &dyns->ds; + const struct vk_input_assembly_state *ia = &dyns->ia; const struct panvk_shader *fs = get_fs(cmdbuf); const struct pan_shader_info *fs_info = fs ? &fs->info : NULL; unsigned bd_count = MAX2(cb->attachment_count, 1); @@ -227,6 +231,20 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, bool writes_z = writes_depth(cmdbuf); bool writes_s = writes_stencil(cmdbuf); + bool msaa = dyns->ms.rasterization_samples > 1; + if ((ia->primitive_topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST || + ia->primitive_topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) && + rs->line.mode == VK_LINE_RASTERIZATION_MODE_BRESENHAM) { + /* we need to disable MSAA when rendering bresenham lines. + * + * From the Vulkan spec: + * "When Bresenham lines are being rasterized, sample locations may + * all be treated as being at the pixel center (this may affect + * attribute and depth interpolation)."" + */ + msaa = false; + } + struct panfrost_ptr ptr = panvk_cmd_alloc_desc_aggregate( cmdbuf, PAN_DESC(RENDERER_STATE), PAN_DESC_ARRAY(bd_count, BLEND)); if (!ptr.gpu) @@ -251,7 +269,6 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, pan_pack(rsd, RENDERER_STATE, cfg) { bool alpha_to_coverage = dyns->ms.alpha_to_coverage_enable; - bool msaa = dyns->ms.rasterization_samples > 1; if (fs) { pan_shader_prepare_rsd(fs_info, fs_code, &cfg); @@ -284,7 +301,7 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, cfg.properties.pixel_kill_operation = earlyzs.kill; cfg.properties.zs_update_operation = earlyzs.update; cfg.multisample_misc.evaluate_per_sample = - (fs->info.fs.sample_shading && msaa); + (fs->info.fs.sample_shading && dyns->ms.rasterization_samples > 1); } else { cfg.properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION; cfg.properties.allow_forward_pixel_to_kill = true; @@ -314,6 +331,9 @@ panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, cfg.stencil_mask_misc.front_facing_depth_bias = rs->depth_bias.enable; cfg.stencil_mask_misc.back_facing_depth_bias = rs->depth_bias.enable; + if (rs->line.mode == VK_LINE_RASTERIZATION_MODE_BRESENHAM) + cfg.stencil_mask_misc.aligned_line_ends = true; + cfg.depth_units = rs->depth_bias.constant_factor; cfg.depth_factor = rs->depth_bias.slope_factor; cfg.depth_bias_clamp = rs->depth_bias.clamp; diff --git a/src/panfrost/vulkan/panvk_physical_device.c b/src/panfrost/vulkan/panvk_physical_device.c index 73ddab5a45e..4aeef693007 100644 --- a/src/panfrost/vulkan/panvk_physical_device.c +++ b/src/panfrost/vulkan/panvk_physical_device.c @@ -202,6 +202,7 @@ get_device_extensions(const struct panvk_physical_device *device, .KHR_image_format_list = true, .KHR_imageless_framebuffer = true, .KHR_index_type_uint8 = true, + .KHR_line_rasterization = true, .KHR_maintenance1 = true, .KHR_maintenance2 = true, .KHR_maintenance3 = true, @@ -251,6 +252,7 @@ get_device_extensions(const struct panvk_physical_device *device, .EXT_image_drm_format_modifier = true, .EXT_image_robustness = true, .EXT_index_type_uint8 = true, + .EXT_line_rasterization = true, .EXT_physical_device_drm = true, .EXT_pipeline_creation_cache_control = true, .EXT_pipeline_creation_feedback = true, @@ -390,6 +392,10 @@ get_features(const struct panvk_physical_device *device, .shaderSubgroupRotate = true, .shaderSubgroupRotateClustered = true, + /* VK_KHR_line_rasterization */ + .rectangularLines = true, + .bresenhamLines = true, + /* VK_EXT_graphics_pipeline_library */ .graphicsPipelineLibrary = true, @@ -854,6 +860,9 @@ get_device_properties(const struct panvk_instance *instance, /* XXX: VK_KHR_maintenance4 */ .maxBufferSize = 1 << 30, + /* VK_KHR_line_rasterization */ + .lineSubPixelPrecisionBits = 8, + /* VK_EXT_custom_border_color */ .maxCustomBorderColorSamplers = 32768,