From 9fbf6b2abff19dc4c3e942569737ac3e67302e1d Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 2 Jul 2021 10:37:47 -0400 Subject: [PATCH] lavapipe: implement VK_EXT_line_rasterization rectangular and strict lines aren't supported in this, and multisampling must be disabled for correct line rasterization Reviewed-by: Dave Airlie Part-of: --- .../frontends/lavapipe/lvp_cmd_buffer.c | 17 +++++++++++ src/gallium/frontends/lavapipe/lvp_device.c | 18 ++++++++++++ src/gallium/frontends/lavapipe/lvp_execute.c | 28 +++++++++++++++++-- src/gallium/frontends/lavapipe/lvp_pipeline.c | 14 ++++++++++ src/gallium/frontends/lavapipe/lvp_private.h | 8 ++++++ 5 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c b/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c index 7230b5ae660..446502bc010 100644 --- a/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c +++ b/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c @@ -1963,6 +1963,23 @@ VKAPI_ATTR void VKAPI_CALL lvp_CmdSetFrontFaceEXT( cmd_buf_queue(cmd_buffer, cmd); } +VKAPI_ATTR void VKAPI_CALL lvp_CmdSetLineStippleEXT( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern) +{ + LVP_FROM_HANDLE(lvp_cmd_buffer, cmd_buffer, commandBuffer); + struct lvp_cmd_buffer_entry *cmd; + + cmd = cmd_buf_entry_alloc(cmd_buffer, LVP_CMD_SET_LINE_STIPPLE); + if (!cmd) + return; + + cmd->u.set_line_stipple.line_stipple_factor = lineStippleFactor; + cmd->u.set_line_stipple.line_stipple_pattern = lineStipplePattern; + cmd_buf_queue(cmd_buffer, cmd); +} + VKAPI_ATTR void VKAPI_CALL lvp_CmdSetPrimitiveTopologyEXT( VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology) diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index 4cf903f8687..bd2dbe74344 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -140,6 +140,7 @@ static const struct vk_device_extension_table lvp_device_extensions_supported = .EXT_vertex_input_dynamic_state = true, .EXT_custom_border_color = true, .EXT_provoking_vertex = true, + .EXT_line_rasterization = true, .GOOGLE_decorate_string = true, .GOOGLE_hlsl_functionality1 = true, }; @@ -512,6 +513,17 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures2( features->privateData = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: { + VkPhysicalDeviceLineRasterizationFeaturesEXT *features = + (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext; + features->rectangularLines = false; + features->bresenhamLines = true; + features->smoothLines = true; + features->stippledRectangularLines = false; + features->stippledBresenhamLines = true; + features->stippledSmoothLines = true; + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: { VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext; @@ -927,6 +939,12 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceProperties2( properties->filterMinmaxSingleComponentFormats = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: { + VkPhysicalDeviceLineRasterizationPropertiesEXT *properties = + (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext; + properties->lineSubPixelPrecisionBits = 4; + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: { VkPhysicalDeviceSubgroupProperties *properties = (VkPhysicalDeviceSubgroupProperties*)ext; diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index c88b9dca738..020c6394d99 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -38,6 +38,7 @@ #include "util/u_sampler.h" #include "util/u_box.h" #include "util/u_inlines.h" +#include "util/u_prim.h" #include "util/u_prim_restart.h" #include "util/format/u_format_zs.h" @@ -116,6 +117,7 @@ struct rendering_state { int num_shader_buffers[PIPE_SHADER_TYPES]; bool iv_dirty[PIPE_SHADER_TYPES]; bool sb_dirty[PIPE_SHADER_TYPES]; + bool disable_multisample; enum gs_output gs_output_lines : 2; void *ss_cso[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS]; void *velems_cso; @@ -214,8 +216,14 @@ static void emit_state(struct rendering_state *state) } if (state->rs_dirty) { + bool ms = state->rs_state.multisample; + if (state->disable_multisample && + (state->gs_output_lines == GS_OUTPUT_LINES || + (state->gs_output_lines == GS_OUTPUT_NONE && u_reduced_prim(state->info.mode) == PIPE_PRIM_LINES))) + state->rs_state.multisample = false; cso_set_rasterizer(state->cso, &state->rs_state); state->rs_dirty = false; + state->rs_state.multisample = ms; } if (state->dsa_dirty) { @@ -438,7 +446,8 @@ static void handle_graphics_pipeline(struct lvp_cmd_buffer_entry *cmd, state->rs_state.depth_clip_near = state->rs_state.depth_clip_far = !rsc->depthClampEnable; state->rs_state.rasterizer_discard = rsc->rasterizerDiscardEnable; - + 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.point_size_per_vertex = true; @@ -470,6 +479,7 @@ static void handle_graphics_pipeline(struct lvp_cmd_buffer_entry *cmd, state->rs_dirty = true; } + 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; @@ -658,8 +668,10 @@ static void handle_graphics_pipeline(struct lvp_cmd_buffer_entry *cmd, { const VkPipelineInputAssemblyStateCreateInfo *ia = pipeline->graphics_create_info.pInputAssemblyState; - if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT)]) + if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT)]) { state->info.mode = vk_conv_topology(ia->topology); + state->rs_dirty = true; + } state->info.primitive_restart = ia->primitiveRestartEnable; } @@ -2886,6 +2898,7 @@ static void handle_set_primitive_topology(struct lvp_cmd_buffer_entry *cmd, struct rendering_state *state) { state->info.mode = vk_conv_topology(cmd->u.set_primitive_topology.prim); + state->rs_dirty = true; } @@ -2945,6 +2958,14 @@ static void handle_set_stencil_op(struct lvp_cmd_buffer_entry *cmd, state->dsa_dirty = true; } +static void handle_set_line_stipple(struct lvp_cmd_buffer_entry *cmd, + struct rendering_state *state) +{ + state->rs_state.line_stipple_factor = cmd->u.set_line_stipple.line_stipple_factor - 1; + state->rs_state.line_stipple_pattern = cmd->u.set_line_stipple.line_stipple_pattern; + state->rs_dirty = true; +} + static void lvp_execute_cmd_buffer(struct lvp_cmd_buffer *cmd_buffer, struct rendering_state *state) { @@ -3157,6 +3178,9 @@ static void lvp_execute_cmd_buffer(struct lvp_cmd_buffer *cmd_buffer, case LVP_CMD_SET_STENCIL_OP: handle_set_stencil_op(cmd, state); break; + case LVP_CMD_SET_LINE_STIPPLE: + handle_set_line_stipple(cmd, state); + break; } first = false; did_flush = false; diff --git a/src/gallium/frontends/lavapipe/lvp_pipeline.c b/src/gallium/frontends/lavapipe/lvp_pipeline.c index f01f7b00bd2..63b8041f43f 100644 --- a/src/gallium/frontends/lavapipe/lvp_pipeline.c +++ b/src/gallium/frontends/lavapipe/lvp_pipeline.c @@ -806,6 +806,20 @@ lvp_graphics_pipeline_init(struct lvp_pipeline *pipeline, 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) { + /* 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_RECTANGULAR_EXT; + 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; + } + } + for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { VK_FROM_HANDLE(vk_shader_module, module, diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index 35f2f07a71b..d2dee50cd72 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -483,6 +483,7 @@ struct lvp_pipeline { uint16_t line_stipple_pattern; bool line_stipple_enable; bool line_smooth; + bool disable_multisample; bool gs_output_lines; bool provoking_vertex_last; }; @@ -681,6 +682,7 @@ enum lvp_cmds { LVP_CMD_SET_DEPTH_BOUNDS_TEST_ENABLE, LVP_CMD_SET_STENCIL_TEST_ENABLE, LVP_CMD_SET_STENCIL_OP, + LVP_CMD_SET_LINE_STIPPLE, }; struct lvp_cmd_bind_pipeline { @@ -1062,6 +1064,11 @@ struct lvp_cmd_set_stencil_op { VkCompareOp compare_op; }; +struct lvp_cmd_set_line_stipple { + uint32_t line_stipple_factor; + uint16_t line_stipple_pattern; +}; + struct lvp_cmd_buffer_entry { struct list_head cmd_link; uint32_t cmd_type; @@ -1119,6 +1126,7 @@ struct lvp_cmd_buffer_entry { struct lvp_cmd_set_depth_bounds_test_enable set_depth_bounds_test_enable; struct lvp_cmd_set_stencil_test_enable set_stencil_test_enable; struct lvp_cmd_set_stencil_op set_stencil_op; + struct lvp_cmd_set_line_stipple set_line_stipple; } u; };