From 542211676c58b0410662e1a959e259487c103e71 Mon Sep 17 00:00:00 2001 From: Hyunjun Ko Date: Mon, 4 Oct 2021 01:24:58 +0000 Subject: [PATCH] turnip: enable VK_EXT_line_rasterization By default line mode is VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT, when lineRasterizationMode is VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT and primtype is line - we enable bresenham line mode. We have to disable MSAA when bresenham lines are used, this is a hardware limitation and spec allows it: "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)." This forces us to re-emit msaa state when line mode is changed. Signed-off-by: Hyunjun Ko Signed-off-by: Danylo Piliaiev Part-of: --- docs/features.txt | 2 +- src/freedreno/vulkan/tu_clear_blit.c | 3 ++- src/freedreno/vulkan/tu_cmd_buffer.c | 33 ++++++++++++++++++++++++---- src/freedreno/vulkan/tu_device.c | 18 +++++++++++++++ src/freedreno/vulkan/tu_pipeline.c | 22 ++++++++++++++----- src/freedreno/vulkan/tu_private.h | 6 ++++- src/freedreno/vulkan/tu_util.h | 14 ++++++++++++ 7 files changed, 86 insertions(+), 12 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index 8b2125b5e42..06d3e52e056 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -529,7 +529,7 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_image_robustness DONE (anv, radv) VK_EXT_index_type_uint8 DONE (anv, lvp, radv/gfx8+, v3dv, tu) VK_EXT_inline_uniform_block DONE (anv, radv) - VK_EXT_line_rasterization DONE (anv, lvp, radv) + VK_EXT_line_rasterization DONE (anv, lvp, radv, tu) VK_EXT_memory_budget DONE (anv, radv, tu) VK_EXT_memory_priority DONE (radv) VK_EXT_multi_draw DONE (anv, lvp, radv) diff --git a/src/freedreno/vulkan/tu_clear_blit.c b/src/freedreno/vulkan/tu_clear_blit.c index aa77f0d7076..8d38a8fd0da 100644 --- a/src/freedreno/vulkan/tu_clear_blit.c +++ b/src/freedreno/vulkan/tu_clear_blit.c @@ -696,7 +696,8 @@ r3d_common(struct tu_cmd_buffer *cmd, struct tu_cs *cs, bool blit, } } - tu6_emit_msaa(cs, samples); + cmd->state.line_mode = RECTANGULAR; + tu6_emit_msaa(cs, samples, cmd->state.line_mode); } static void diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index 6e1288fc97d..c7d38decb4b 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -304,10 +304,11 @@ tu6_emit_mrt(struct tu_cmd_buffer *cmd, } void -tu6_emit_msaa(struct tu_cs *cs, VkSampleCountFlagBits vk_samples) +tu6_emit_msaa(struct tu_cs *cs, VkSampleCountFlagBits vk_samples, + enum a5xx_line_mode line_mode) { const enum a3xx_msaa_samples samples = tu_msaa_samples(vk_samples); - bool msaa_disable = samples == MSAA_ONE; + bool msaa_disable = (samples == MSAA_ONE) || (line_mode == BRESENHAM); tu_cs_emit_regs(cs, A6XX_SP_TP_RAS_MSAA_CNTL(samples), @@ -1589,6 +1590,7 @@ tu_BeginCommandBuffer(VkCommandBuffer commandBuffer, memset(&cmd_buffer->state, 0, sizeof(cmd_buffer->state)); cmd_buffer->state.index_size = 0xff; /* dirty restart index */ + cmd_buffer->state.line_mode = RECTANGULAR; tu_cache_init(&cmd_buffer->state.cache); tu_cache_init(&cmd_buffer->state.renderpass_cache); @@ -2206,6 +2208,21 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer, tu_cs_emit_draw_state(cs, TU_DRAW_STATE_DYNAMIC + i, pipeline->dynamic_state[i]); } + if (cmd->state.line_mode != pipeline->line_mode) { + cmd->state.line_mode = pipeline->line_mode; + + /* We have to disable MSAA when bresenham lines are used, this is + * a hardware limitation and spec allows it: + * + * 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). + */ + if (cmd->state.subpass && cmd->state.subpass->samples) { + tu6_emit_msaa(&cmd->draw_cs, cmd->state.subpass->samples, cmd->state.line_mode); + } + } + /* the vertex_buffers draw state always contains all the currently * bound vertex buffers. update its size to only emit the vbs which * are actually used by the pipeline @@ -2617,6 +2634,14 @@ tu_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer, tu_stub(); } +VKAPI_ATTR void VKAPI_CALL +tu_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern) +{ + tu_stub(); +} + static void tu_flush_for_access(struct tu_cache_state *cache, enum tu_cmd_access_mask src_mask, @@ -3186,7 +3211,7 @@ tu_CmdBeginRenderPass2(VkCommandBuffer commandBuffer, tu6_emit_zs(cmd, cmd->state.subpass, &cmd->draw_cs); tu6_emit_mrt(cmd, cmd->state.subpass, &cmd->draw_cs); if (cmd->state.subpass->samples) - tu6_emit_msaa(&cmd->draw_cs, cmd->state.subpass->samples); + tu6_emit_msaa(&cmd->draw_cs, cmd->state.subpass->samples, cmd->state.line_mode); tu6_emit_render_cntl(cmd, cmd->state.subpass, &cmd->draw_cs, false); tu_set_input_attachments(cmd, cmd->state.subpass); @@ -3255,7 +3280,7 @@ tu_CmdNextSubpass2(VkCommandBuffer commandBuffer, tu6_emit_zs(cmd, cmd->state.subpass, cs); tu6_emit_mrt(cmd, cmd->state.subpass, cs); if (cmd->state.subpass->samples) - tu6_emit_msaa(cs, cmd->state.subpass->samples); + tu6_emit_msaa(cs, cmd->state.subpass->samples, cmd->state.line_mode); tu6_emit_render_cntl(cmd, cmd->state.subpass, cs, false); tu_set_input_attachments(cmd, cmd->state.subpass); diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index aff36984487..1d41260e93c 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -190,6 +190,7 @@ get_device_extensions(const struct tu_physical_device *device, .EXT_shader_viewport_index_layer = true, .EXT_vertex_attribute_divisor = true, .EXT_provoking_vertex = true, + .EXT_line_rasterization = true, #ifdef ANDROID .ANDROID_native_buffer = true, #endif @@ -735,6 +736,17 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, features->mutableDescriptorType = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: { + VkPhysicalDeviceLineRasterizationFeaturesEXT *features = + (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext; + features->rectangularLines = true; + features->bresenhamLines = true; + features->smoothLines = false; + features->stippledRectangularLines = false; + features->stippledBresenhamLines = false; + features->stippledSmoothLines = false; + break; + } default: break; @@ -1084,6 +1096,12 @@ tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, properties->transformFeedbackPreservesTriangleFanProvokingVertex = false; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: { + VkPhysicalDeviceLineRasterizationPropertiesEXT *props = + (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext; + props->lineSubPixelPrecisionBits = 8; + break; + } default: break; diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index bbc4dd87276..7543e4503c0 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -1970,7 +1970,7 @@ tu6_emit_sample_locations(struct tu_cs *cs, const VkSampleLocationsInfoEXT *samp static uint32_t tu6_gras_su_cntl(const VkPipelineRasterizationStateCreateInfo *rast_info, - VkSampleCountFlagBits samples, + enum a5xx_line_mode line_mode, bool multiview) { uint32_t gras_su_cntl = 0; @@ -1989,8 +1989,7 @@ tu6_gras_su_cntl(const VkPipelineRasterizationStateCreateInfo *rast_info, if (rast_info->depthBiasEnable) gras_su_cntl |= A6XX_GRAS_SU_CNTL_POLY_OFFSET; - if (samples > VK_SAMPLE_COUNT_1_BIT) - gras_su_cntl |= A6XX_GRAS_SU_CNTL_LINE_MODE(RECTANGULAR); + gras_su_cntl |= A6XX_GRAS_SU_CNTL_LINE_MODE(line_mode); if (multiview) { gras_su_cntl |= @@ -2763,6 +2762,19 @@ tu_pipeline_builder_parse_rasterization(struct tu_pipeline_builder *builder, if (depth_clip_state) depth_clip_disable = !depth_clip_state->depthClipEnable; + pipeline->line_mode = RECTANGULAR; + + if (tu6_primtype_line(pipeline->ia.primtype)) { + const VkPipelineRasterizationLineStateCreateInfoEXT *rast_line_state = + vk_find_struct_const(rast_info->pNext, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT); + + if (rast_line_state && rast_line_state->lineRasterizationMode == + VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT) { + pipeline->line_mode = BRESENHAM; + } + } + struct tu_cs cs; uint32_t cs_size = 9 + (builder->emit_msaa_state ? 11 : 0); pipeline->rast_state = tu_cs_draw_state(&pipeline->cs, &cs, cs_size); @@ -2798,7 +2810,7 @@ tu_pipeline_builder_parse_rasterization(struct tu_pipeline_builder *builder, * It happens when subpass doesn't use any color/depth attachment. */ if (builder->emit_msaa_state) - tu6_emit_msaa(&cs, builder->samples); + tu6_emit_msaa(&cs, builder->samples, pipeline->line_mode); const VkPipelineRasterizationStateStreamCreateInfoEXT *stream_info = vk_find_struct_const(rast_info->pNext, @@ -2818,7 +2830,7 @@ tu_pipeline_builder_parse_rasterization(struct tu_pipeline_builder *builder, } pipeline->gras_su_cntl = - tu6_gras_su_cntl(rast_info, builder->samples, builder->multiview_mask != 0); + tu6_gras_su_cntl(rast_info, pipeline->line_mode, builder->multiview_mask != 0); if (tu_pipeline_static_state(pipeline, &cs, TU_DYNAMIC_STATE_GRAS_SU_CNTL, 2)) tu_cs_emit_regs(&cs, A6XX_GRAS_SU_CNTL(.dword = pipeline->gras_su_cntl)); diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index fcd79e6f054..cd45a6bc9e4 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -1022,6 +1022,7 @@ struct tu_cmd_state bool has_subpass_predication; bool predication_active; bool disable_gmem; + enum a5xx_line_mode line_mode; struct tu_lrz_state lrz; @@ -1213,6 +1214,8 @@ struct tu_pipeline bool rb_depth_cntl_disable; + enum a5xx_line_mode line_mode; + /* draw states for the pipeline */ struct tu_draw_state load_state, rast_state, blend_state; @@ -1282,7 +1285,8 @@ tu6_emit_depth_bias(struct tu_cs *cs, float clamp, float slope_factor); -void tu6_emit_msaa(struct tu_cs *cs, VkSampleCountFlagBits samples); +void tu6_emit_msaa(struct tu_cs *cs, VkSampleCountFlagBits samples, + enum a5xx_line_mode line_mode); void tu6_emit_window_scissor(struct tu_cs *cs, uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2); diff --git a/src/freedreno/vulkan/tu_util.h b/src/freedreno/vulkan/tu_util.h index 9c42cfdbad6..2ad7f86e36e 100644 --- a/src/freedreno/vulkan/tu_util.h +++ b/src/freedreno/vulkan/tu_util.h @@ -85,6 +85,20 @@ tu6_rop(VkLogicOp op) return lookup[op]; } +static inline bool +tu6_primtype_line(enum pc_di_primtype type) +{ + switch(type) { + case DI_PT_LINELIST: + case DI_PT_LINESTRIP: + case DI_PT_LINE_ADJ: + case DI_PT_LINESTRIP_ADJ: + return true; + default: + return false; + } +} + static inline enum pc_di_primtype tu6_primtype(VkPrimitiveTopology topology) {