radv: implement VK_EXT_line_rasterization
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Fri, 13 Sep 2019 11:40:44 +0000 (13:40 +0200)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Thu, 13 Feb 2020 07:14:01 +0000 (08:14 +0100)
Only Bresenham lines are supported. GFX9 is currently disabled
because there is some CTS failures for some weird reasons.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2982>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2982>

src/amd/vulkan/radv_cmd_buffer.c
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_extensions.py
src/amd/vulkan/radv_pipeline.c
src/amd/vulkan/radv_private.h

index d516c26d96c604706a6402c89c9e96d454a6be4f..66c7d0721ba9dc58984b54c3bdfacac9b81f46ac 100644 (file)
@@ -92,6 +92,10 @@ const struct radv_dynamic_state default_dynamic_state = {
                .front = 0u,
                .back = 0u,
        },
+       .line_stipple = {
+               .factor = 0u,
+               .pattern = 0u,
+       },
 };
 
 static void
@@ -212,6 +216,14 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer,
                }
        }
 
+       if (copy_mask & RADV_DYNAMIC_LINE_STIPPLE) {
+               if (memcmp(&dest->line_stipple, &src->line_stipple,
+                          sizeof(src->line_stipple))) {
+                       dest->line_stipple = src->line_stipple;
+                       dest_mask |= RADV_DYNAMIC_LINE_STIPPLE;
+               }
+       }
+
        cmd_buffer->state.dirty |= dest_mask;
 }
 
@@ -1317,6 +1329,22 @@ radv_emit_depth_bias(struct radv_cmd_buffer *cmd_buffer)
        radeon_emit(cmd_buffer->cs, bias); /* BACK OFFSET */
 }
 
+static void
+radv_emit_line_stipple(struct radv_cmd_buffer *cmd_buffer)
+{
+       struct radv_dynamic_state *d = &cmd_buffer->state.dynamic;
+       struct radv_pipeline *pipeline = cmd_buffer->state.pipeline;
+       uint32_t auto_reset_cntl = 1;
+
+       if (pipeline->graphics.topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP)
+               auto_reset_cntl = 2;
+
+       radeon_set_context_reg(cmd_buffer->cs, R_028A0C_PA_SC_LINE_STIPPLE,
+                              S_028A0C_LINE_PATTERN(d->line_stipple.pattern) |
+                              S_028A0C_REPEAT_COUNT(d->line_stipple.factor - 1) |
+                              S_028A0C_AUTO_RESET_CNTL(auto_reset_cntl));
+}
+
 static void
 radv_emit_fb_color_state(struct radv_cmd_buffer *cmd_buffer,
                         int index,
@@ -2202,6 +2230,9 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer)
        if (states & RADV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS)
                radv_emit_sample_locations(cmd_buffer);
 
+       if (states & RADV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE)
+               radv_emit_line_stipple(cmd_buffer);
+
        cmd_buffer->state.dirty &= ~states;
 }
 
@@ -4107,6 +4138,20 @@ void radv_CmdSetSampleLocationsEXT(
        state->dirty |= RADV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS;
 }
 
+void radv_CmdSetLineStippleEXT(
+       VkCommandBuffer                             commandBuffer,
+       uint32_t                                    lineStippleFactor,
+       uint16_t                                    lineStipplePattern)
+{
+       RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
+       struct radv_cmd_state *state = &cmd_buffer->state;
+
+       state->dynamic.line_stipple.factor = lineStippleFactor;
+       state->dynamic.line_stipple.pattern = lineStipplePattern;
+
+       state->dirty |= RADV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE;
+}
+
 void radv_CmdExecuteCommands(
        VkCommandBuffer                             commandBuffer,
        uint32_t                                    commandBufferCount,
index a016ff3886d098ec90adf8b16c085c865b84c8f5..ca0909ff73deaabeba2d9551206fa9e083ab4e2c 100644 (file)
@@ -1270,6 +1270,17 @@ void radv_GetPhysicalDeviceFeatures2(
                        features->subgroupBroadcastDynamicId = true;
                        break;
                }
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
+                       VkPhysicalDeviceLineRasterizationFeaturesEXT *features =
+                               (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext;
+                       features->rectangularLines = false;
+                       features->bresenhamLines = true;
+                       features->smoothLines = false;
+                       features->stippledRectangularLines = false;
+                       features->stippledBresenhamLines = true;
+                       features->stippledSmoothLines = false;
+                       break;
+               }
                default:
                        break;
                }
@@ -1889,6 +1900,12 @@ void radv_GetPhysicalDeviceProperties2(
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES:
                        radv_get_physical_device_properties_1_2(pdevice, (void *)ext);
                        break;
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: {
+                       VkPhysicalDeviceLineRasterizationPropertiesEXT *props =
+                               (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext;
+                       props->lineSubPixelPrecisionBits = 4;
+                       break;
+               }
                default:
                        break;
                }
index 57aa67be616d411f4b5b741b827e88dad91ef360..32e14a640e2f9bfcdf50ab514a106440faa37643 100644 (file)
@@ -128,6 +128,8 @@ EXTENSIONS = [
     Extension('VK_EXT_host_query_reset',                  1, True),
     Extension('VK_EXT_index_type_uint8',                  1, 'device->rad_info.chip_class >= GFX8'),
     Extension('VK_EXT_inline_uniform_block',              1, True),
+    # Disable line rasterization on GFX9 until the CTS failures have been resolved.
+    Extension('VK_EXT_line_rasterization',                1, 'device->rad_info.chip_class != GFX9'),
     Extension('VK_EXT_memory_budget',                     1, True),
     Extension('VK_EXT_memory_priority',                   1, True),
     Extension('VK_EXT_pci_bus_info',                      2, True),
index b065ca4258ce50e34ddaa5d09f1167d15d137877..c3c69b34015d6f27274118407d1de7f06e70374d 100644 (file)
@@ -1242,6 +1242,23 @@ radv_pipeline_init_multisample_state(struct radv_pipeline *pipeline,
        ms->pa_sc_mode_cntl_0 = S_028A48_ALTERNATE_RBS_PER_TILE(pipeline->device->physical_device->rad_info.chip_class >= GFX9) |
                                S_028A48_VPORT_SCISSOR_ENABLE(1);
 
+       const VkPipelineRasterizationLineStateCreateInfoEXT *rast_line =
+               vk_find_struct_const(pCreateInfo->pRasterizationState->pNext,
+                                    PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT);
+       if (rast_line) {
+               ms->pa_sc_mode_cntl_0 |= S_028A48_LINE_STIPPLE_ENABLE(rast_line->stippledLineEnable);
+               if (rast_line->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT) {
+                       /* From the Vulkan spec 1.1.129:
+                        *
+                        * "When VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT lines
+                        *  are being rasterized, sample locations may all be
+                        *  treated as being at the pixel center (this may
+                        *  affect attribute and depth interpolation)."
+                        */
+                       ms->num_samples = 1;
+               }
+       }
+
        if (ms->num_samples > 1) {
                RADV_FROM_HANDLE(radv_render_pass, pass, pCreateInfo->renderPass);
                struct radv_subpass *subpass = &pass->subpasses[pCreateInfo->subpass];
@@ -1397,6 +1414,8 @@ static unsigned radv_dynamic_state_mask(VkDynamicState state)
                return RADV_DYNAMIC_DISCARD_RECTANGLE;
        case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT:
                return RADV_DYNAMIC_SAMPLE_LOCATIONS;
+       case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT:
+               return RADV_DYNAMIC_LINE_STIPPLE;
        default:
                unreachable("Unhandled dynamic state");
        }
@@ -1432,6 +1451,11 @@ static uint32_t radv_pipeline_needed_dynamic_state(const VkGraphicsPipelineCreat
                                  PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT))
                states &= ~RADV_DYNAMIC_SAMPLE_LOCATIONS;
 
+       if (!pCreateInfo->pRasterizationState ||
+           !vk_find_struct_const(pCreateInfo->pRasterizationState->pNext,
+                                 PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT))
+               states &= ~RADV_DYNAMIC_LINE_STIPPLE;
+
        /* TODO: blend constants & line width. */
 
        return states;
@@ -1584,6 +1608,14 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline,
                }
        }
 
+       const VkPipelineRasterizationLineStateCreateInfoEXT *rast_line_info =
+               vk_find_struct_const(pCreateInfo->pRasterizationState->pNext,
+                                    PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT);
+       if (needed_states & RADV_DYNAMIC_LINE_STIPPLE) {
+               dynamic->line_stipple.factor = rast_line_info->lineStippleFactor;
+               dynamic->line_stipple.pattern = rast_line_info->lineStipplePattern;
+       }
+
        pipeline->dynamic_state.mask = states;
 }
 
@@ -5019,6 +5051,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline,
        uint32_t gs_out;
        uint32_t prim = si_translate_prim(pCreateInfo->pInputAssemblyState->topology);
 
+       pipeline->graphics.topology = pCreateInfo->pInputAssemblyState->topology;
        pipeline->graphics.can_use_guardband = radv_prim_can_use_guardband(pCreateInfo->pInputAssemblyState->topology);
 
        if (radv_pipeline_has_gs(pipeline)) {
index 537355f6c9a62026e906d30e7aea1f043ba42d2c..af2f05859a171a20a02cf2b537429d9fe549b20a 100644 (file)
@@ -971,7 +971,8 @@ enum radv_dynamic_state_bits {
        RADV_DYNAMIC_STENCIL_REFERENCE    = 1 << 8,
        RADV_DYNAMIC_DISCARD_RECTANGLE    = 1 << 9,
        RADV_DYNAMIC_SAMPLE_LOCATIONS     = 1 << 10,
-       RADV_DYNAMIC_ALL                  = (1 << 11) - 1,
+       RADV_DYNAMIC_LINE_STIPPLE         = 1 << 11,
+       RADV_DYNAMIC_ALL                  = (1 << 12) - 1,
 };
 
 enum radv_cmd_dirty_bits {
@@ -988,12 +989,13 @@ enum radv_cmd_dirty_bits {
        RADV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE         = 1 << 8,
        RADV_CMD_DIRTY_DYNAMIC_DISCARD_RECTANGLE         = 1 << 9,
        RADV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS          = 1 << 10,
-       RADV_CMD_DIRTY_DYNAMIC_ALL                       = (1 << 11) - 1,
-       RADV_CMD_DIRTY_PIPELINE                          = 1 << 11,
-       RADV_CMD_DIRTY_INDEX_BUFFER                      = 1 << 12,
-       RADV_CMD_DIRTY_FRAMEBUFFER                       = 1 << 13,
-       RADV_CMD_DIRTY_VERTEX_BUFFER                     = 1 << 14,
-       RADV_CMD_DIRTY_STREAMOUT_BUFFER                  = 1 << 15,
+       RADV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE              = 1 << 11,
+       RADV_CMD_DIRTY_DYNAMIC_ALL                       = (1 << 12) - 1,
+       RADV_CMD_DIRTY_PIPELINE                          = 1 << 12,
+       RADV_CMD_DIRTY_INDEX_BUFFER                      = 1 << 13,
+       RADV_CMD_DIRTY_FRAMEBUFFER                       = 1 << 14,
+       RADV_CMD_DIRTY_VERTEX_BUFFER                     = 1 << 15,
+       RADV_CMD_DIRTY_STREAMOUT_BUFFER                  = 1 << 16,
 };
 
 enum radv_cmd_flush_bits {
@@ -1125,6 +1127,11 @@ struct radv_dynamic_state {
        struct radv_discard_rectangle_state               discard_rectangle;
 
        struct radv_sample_locations_state                sample_location;
+
+       struct {
+               uint32_t factor;
+               uint16_t pattern;
+       } line_stipple;
 };
 
 extern const struct radv_dynamic_state default_dynamic_state;
@@ -1640,6 +1647,7 @@ struct radv_pipeline {
                        bool can_use_guardband;
                        uint32_t needed_dynamic_state;
                        bool disable_out_of_order_rast_for_occlusion;
+                       uint8_t topology;
 
                        /* Used for rbplus */
                        uint32_t col_format;