From f6e7de41d7b15185b746b79f7ef601c9405adc95 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 22 May 2019 22:44:59 -0500 Subject: [PATCH] anv: Implement VK_EXT_line_rasterization Reviewed-by: Lionel Landwerlin --- src/intel/vulkan/anv_cmd_buffer.c | 20 +++++ src/intel/vulkan/anv_device.c | 32 ++++++- src/intel/vulkan/anv_extensions.py | 1 + src/intel/vulkan/anv_pipeline.c | 10 +++ src/intel/vulkan/anv_private.h | 11 ++- src/intel/vulkan/gen7_cmd_buffer.c | 9 ++ src/intel/vulkan/gen8_cmd_buffer.c | 9 ++ src/intel/vulkan/genX_pipeline.c | 131 ++++++++++++++++++++++++++--- 8 files changed, 211 insertions(+), 12 deletions(-) diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c index d3887ae1ec6..96c75e06ae8 100644 --- a/src/intel/vulkan/anv_cmd_buffer.c +++ b/src/intel/vulkan/anv_cmd_buffer.c @@ -72,6 +72,10 @@ const struct anv_dynamic_state default_dynamic_state = { .front = 0u, .back = 0u, }, + .line_stipple = { + .factor = 0u, + .pattern = 0u, + }, }; void @@ -111,6 +115,9 @@ anv_dynamic_state_copy(struct anv_dynamic_state *dest, if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE) dest->stencil_reference = src->stencil_reference; + + if (copy_mask & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) + dest->line_stipple = src->line_stipple; } static void @@ -514,6 +521,19 @@ void anv_CmdSetStencilReference( cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE; } +void anv_CmdSetLineStippleEXT( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern) +{ + ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + + cmd_buffer->state.gfx.dynamic.line_stipple.factor = lineStippleFactor; + cmd_buffer->state.gfx.dynamic.line_stipple.pattern = lineStipplePattern; + + cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE; +} + static void anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer, VkPipelineBindPoint bind_point, diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index d46883398b2..9a5dba040cc 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -1098,6 +1098,17 @@ void anv_GetPhysicalDeviceFeatures2( break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: { + VkPhysicalDeviceLineRasterizationFeaturesEXT *features = + (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext; + features->rectangularLines = true; + features->bresenhamLines = true; + features->smoothLines = true; + features->stippledRectangularLines = false; + features->stippledBresenhamLines = true; + features->stippledSmoothLines = false; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: { VkPhysicalDeviceMultiviewFeatures *features = (VkPhysicalDeviceMultiviewFeatures *)ext; @@ -1353,7 +1364,7 @@ void anv_GetPhysicalDeviceProperties( }, .pointSizeGranularity = (1.0 / 8.0), .lineWidthGranularity = (1.0 / 128.0), - .strictLines = false, /* FINISHME */ + .strictLines = false, .standardSampleLocations = true, .optimalBufferCopyOffsetAlignment = 128, .optimalBufferCopyRowPitchAlignment = 128, @@ -1510,6 +1521,25 @@ void anv_GetPhysicalDeviceProperties2( break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: { + VkPhysicalDeviceLineRasterizationPropertiesEXT *props = + (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext; + /* In the Skylake PRM Vol. 7, subsection titled "GIQ (Diamond) + * Sampling Rules - Legacy Mode", it says the following: + * + * "Note that the device divides a pixel into a 16x16 array of + * subpixels, referenced by their upper left corners." + * + * This is the only known reference in the PRMs to the subpixel + * precision of line rasterization and a "16x16 array of subpixels" + * implies 4 subpixel precision bits. Empirical testing has shown + * that 4 subpixel precision bits applies to all line rasterization + * types. + */ + props->lineSubPixelPrecisionBits = 4; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: { VkPhysicalDeviceMaintenance3Properties *props = (VkPhysicalDeviceMaintenance3Properties *)ext; diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py index d40aa08863c..f90e6f31a65 100644 --- a/src/intel/vulkan/anv_extensions.py +++ b/src/intel/vulkan/anv_extensions.py @@ -137,6 +137,7 @@ EXTENSIONS = [ Extension('VK_EXT_host_query_reset', 1, True), Extension('VK_EXT_index_type_uint8', 1, True), Extension('VK_EXT_inline_uniform_block', 1, True), + Extension('VK_EXT_line_rasterization', 1, True), Extension('VK_EXT_memory_budget', 1, 'device->has_mem_available'), Extension('VK_EXT_pci_bus_info', 2, True), Extension('VK_EXT_pipeline_creation_feedback', 1, True), diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 002ff00d538..38b05380c1b 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -1619,6 +1619,16 @@ copy_non_dynamic_state(struct anv_pipeline *pipeline, } } + const VkPipelineRasterizationLineStateCreateInfoEXT *line_state = + vk_find_struct_const(pCreateInfo->pRasterizationState->pNext, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT); + if (line_state) { + if (states & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) { + dynamic->line_stipple.factor = line_state->lineStippleFactor; + dynamic->line_stipple.pattern = line_state->lineStipplePattern; + } + } + pipeline->dynamic_state_mask = states; } diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index f46a87e8e7c..2465f264354 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1951,6 +1951,7 @@ enum anv_cmd_dirty_bits { ANV_CMD_DIRTY_INDEX_BUFFER = 1 << 10, ANV_CMD_DIRTY_RENDER_TARGETS = 1 << 11, ANV_CMD_DIRTY_XFB_ENABLE = 1 << 12, + ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE = 1 << 13, /* VK_DYNAMIC_STATE_LINE_STIPPLE_EXT */ }; typedef uint32_t anv_cmd_dirty_mask_t; @@ -1963,7 +1964,8 @@ typedef uint32_t anv_cmd_dirty_mask_t; ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS | \ ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK | \ ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK | \ - ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE) + ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE | \ + ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) static inline enum anv_cmd_dirty_bits anv_cmd_dirty_bit_for_vk_dynamic_state(VkDynamicState vk_state) @@ -1987,6 +1989,8 @@ anv_cmd_dirty_bit_for_vk_dynamic_state(VkDynamicState vk_state) return ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK; case VK_DYNAMIC_STATE_STENCIL_REFERENCE: return ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE; + case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT: + return ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE; default: assert(!"Unsupported dynamic state"); return 0; @@ -2256,6 +2260,11 @@ struct anv_dynamic_state { uint32_t front; uint32_t back; } stencil_reference; + + struct { + uint32_t factor; + uint16_t pattern; + } line_stipple; }; extern const struct anv_dynamic_state default_dynamic_state; diff --git a/src/intel/vulkan/gen7_cmd_buffer.c b/src/intel/vulkan/gen7_cmd_buffer.c index bfbbb7793f5..c5281e527ef 100644 --- a/src/intel/vulkan/gen7_cmd_buffer.c +++ b/src/intel/vulkan/gen7_cmd_buffer.c @@ -237,6 +237,15 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) } } + if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) { + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_LINE_STIPPLE), ls) { + ls.LineStipplePattern = d->line_stipple.pattern; + ls.LineStippleInverseRepeatCount = + 1.0f / MAX2(1, d->line_stipple.factor); + ls.LineStippleRepeatCount = d->line_stipple.factor; + } + } + if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | ANV_CMD_DIRTY_RENDER_TARGETS | ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK | diff --git a/src/intel/vulkan/gen8_cmd_buffer.c b/src/intel/vulkan/gen8_cmd_buffer.c index a4ef3d95db8..e4f0c1410fb 100644 --- a/src/intel/vulkan/gen8_cmd_buffer.c +++ b/src/intel/vulkan/gen8_cmd_buffer.c @@ -542,6 +542,15 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) } #endif + if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) { + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_LINE_STIPPLE), ls) { + ls.LineStipplePattern = d->line_stipple.pattern; + ls.LineStippleInverseRepeatCount = + 1.0f / MAX2(1, d->line_stipple.factor); + ls.LineStippleRepeatCount = d->line_stipple.factor; + } + } + if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | ANV_CMD_DIRTY_INDEX_BUFFER)) { anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF), vf) { diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index 9c47c486e0d..efe18cc3ae1 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -448,6 +448,25 @@ static const uint32_t vk_to_gen_front_face[] = { [VK_FRONT_FACE_CLOCKWISE] = 0 }; +static VkLineRasterizationModeEXT +vk_line_rasterization_mode(const VkPipelineRasterizationLineStateCreateInfoEXT *line_info, + const VkPipelineMultisampleStateCreateInfo *ms_info) +{ + VkLineRasterizationModeEXT line_mode = + line_info ? line_info->lineRasterizationMode : + VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT; + + if (line_mode == VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT) { + if (ms_info && ms_info->rasterizationSamples > 1) { + return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT; + } else { + return VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT; + } + } + + return line_mode; +} + /** Returns the final polygon mode for rasterization * * This function takes into account polygon mode, primitive topology and the @@ -521,10 +540,44 @@ anv_raster_polygon_mode(struct anv_pipeline *pipeline, } } +#if GEN_GEN <= 7 +static uint32_t +gen7_ms_rast_mode(struct anv_pipeline *pipeline, + const VkPipelineInputAssemblyStateCreateInfo *ia_info, + const VkPipelineRasterizationStateCreateInfo *rs_info, + const VkPipelineMultisampleStateCreateInfo *ms_info) +{ + const VkPipelineRasterizationLineStateCreateInfoEXT *line_info = + vk_find_struct_const(rs_info->pNext, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT); + + VkPolygonMode raster_mode = + anv_raster_polygon_mode(pipeline, ia_info, rs_info); + if (raster_mode == VK_POLYGON_MODE_LINE) { + switch (vk_line_rasterization_mode(line_info, ms_info)) { + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT: + return MSRASTMODE_ON_PATTERN; + + case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT: + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT: + return MSRASTMODE_OFF_PIXEL; + + default: + unreachable("Unsupported line rasterization mode"); + } + } else { + return (ms_info && ms_info->rasterizationSamples > 1) ? + MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL; + } +} +#endif + static void emit_rs_state(struct anv_pipeline *pipeline, + const VkPipelineInputAssemblyStateCreateInfo *ia_info, const VkPipelineRasterizationStateCreateInfo *rs_info, const VkPipelineMultisampleStateCreateInfo *ms_info, + const VkPipelineRasterizationLineStateCreateInfoEXT *line_info, const struct anv_render_pass *pass, const struct anv_subpass *subpass) { @@ -538,6 +591,11 @@ emit_rs_state(struct anv_pipeline *pipeline, sf.LineStripListProvokingVertexSelect = 0; sf.TriangleFanProvokingVertexSelect = 1; sf.VertexSubPixelPrecisionSelect = _8Bit; + sf.AALineDistanceMode = true; + +#if GEN_IS_HASWELL + sf.LineStippleEnable = line_info && line_info->stippledLineEnable; +#endif const struct brw_vue_prog_data *last_vue_prog_data = anv_pipeline_get_last_vue_prog_data(pipeline); @@ -557,11 +615,47 @@ emit_rs_state(struct anv_pipeline *pipeline, # define raster sf #endif + VkPolygonMode raster_mode = + anv_raster_polygon_mode(pipeline, ia_info, rs_info); + VkLineRasterizationModeEXT line_mode = + vk_line_rasterization_mode(line_info, ms_info); + /* For details on 3DSTATE_RASTER multisample state, see the BSpec table * "Multisample Modes State". */ #if GEN_GEN >= 8 - raster.DXMultisampleRasterizationEnable = true; + if (raster_mode == VK_POLYGON_MODE_LINE) { + /* Unfortunately, configuring our line rasterization hardware on gen8 + * and later is rather painful. Instead of giving us bits to tell the + * hardware what line mode to use like we had on gen7, we now have an + * arcane combination of API Mode and MSAA enable bits which do things + * in a table which are expected to magically put the hardware into the + * right mode for your API. Sadly, Vulkan isn't any of the APIs the + * hardware people thought of so nothing works the way you want it to. + * + * Look at the table titled "Multisample Rasterization Modes" in Vol 7 + * of the Skylake PRM for more details. + */ + switch (line_mode) { + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT: + raster.APIMode = DX100; + raster.DXMultisampleRasterizationEnable = true; + break; + + case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT: + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT: + raster.APIMode = DX9OGL; + raster.DXMultisampleRasterizationEnable = false; + break; + + default: + unreachable("Unsupported line rasterization mode"); + } + } else { + raster.APIMode = DX100; + raster.DXMultisampleRasterizationEnable = true; + } + /* NOTE: 3DSTATE_RASTER::ForcedSampleCount affects the BDW and SKL PMA fix * computations. If we ever set this bit to a different value, they will * need to be updated accordingly. @@ -570,10 +664,13 @@ emit_rs_state(struct anv_pipeline *pipeline, raster.ForceMultisampling = false; #else raster.MultisampleRasterizationMode = - (ms_info && ms_info->rasterizationSamples > 1) ? - MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL; + gen7_ms_rast_mode(pipeline, ia_info, rs_info, ms_info); #endif + if (raster_mode == VK_POLYGON_MODE_LINE && + line_mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT) + raster.AntialiasingEnable = true; + raster.FrontWinding = vk_to_gen_front_face[rs_info->frontFace]; raster.CullMode = vk_to_gen_cullmode[rs_info->cullMode]; raster.FrontFaceFillMode = vk_to_gen_fillmode[rs_info->polygonMode]; @@ -1690,8 +1787,11 @@ has_color_buffer_write_enabled(const struct anv_pipeline *pipeline, static void emit_3dstate_wm(struct anv_pipeline *pipeline, struct anv_subpass *subpass, + const VkPipelineInputAssemblyStateCreateInfo *ia, + const VkPipelineRasterizationStateCreateInfo *raster, const VkPipelineColorBlendStateCreateInfo *blend, - const VkPipelineMultisampleStateCreateInfo *multisample) + const VkPipelineMultisampleStateCreateInfo *multisample, + const VkPipelineRasterizationLineStateCreateInfoEXT *line) { const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline); @@ -1758,17 +1858,19 @@ emit_3dstate_wm(struct anv_pipeline *pipeline, struct anv_subpass *subpass, wm.ThreadDispatchEnable = true; if (multisample && multisample->rasterizationSamples > 1) { - wm.MultisampleRasterizationMode = MSRASTMODE_ON_PATTERN; if (wm_prog_data->persample_dispatch) { wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE; } else { wm.MultisampleDispatchMode = MSDISPMODE_PERPIXEL; } } else { - wm.MultisampleRasterizationMode = MSRASTMODE_OFF_PIXEL; wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE; } + wm.MultisampleRasterizationMode = + gen7_ms_rast_mode(pipeline, ia, raster, multisample); #endif + + wm.LineStippleEnable = line && line->stippledLineEnable; } } } @@ -2017,11 +2119,17 @@ genX(graphics_pipeline_create)( return result; } + const VkPipelineRasterizationLineStateCreateInfoEXT *line_info = + vk_find_struct_const(pCreateInfo->pRasterizationState->pNext, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT); + assert(pCreateInfo->pVertexInputState); emit_vertex_input(pipeline, pCreateInfo->pVertexInputState); assert(pCreateInfo->pRasterizationState); - emit_rs_state(pipeline, pCreateInfo->pRasterizationState, - pCreateInfo->pMultisampleState, pass, subpass); + emit_rs_state(pipeline, pCreateInfo->pInputAssemblyState, + pCreateInfo->pRasterizationState, + pCreateInfo->pMultisampleState, + line_info, pass, subpass); emit_ms_state(pipeline, pCreateInfo->pMultisampleState); emit_ds_state(pipeline, pCreateInfo->pDepthStencilState, pass, subpass); emit_cb_state(pipeline, pCreateInfo->pColorBlendState, @@ -2059,8 +2167,11 @@ genX(graphics_pipeline_create)( emit_3dstate_hs_te_ds(pipeline, pCreateInfo->pTessellationState); emit_3dstate_gs(pipeline); emit_3dstate_sbe(pipeline); - emit_3dstate_wm(pipeline, subpass, pCreateInfo->pColorBlendState, - pCreateInfo->pMultisampleState); + emit_3dstate_wm(pipeline, subpass, + pCreateInfo->pInputAssemblyState, + pCreateInfo->pRasterizationState, + pCreateInfo->pColorBlendState, + pCreateInfo->pMultisampleState, line_info); emit_3dstate_ps(pipeline, pCreateInfo->pColorBlendState, pCreateInfo->pMultisampleState); #if GEN_GEN >= 8 -- 2.30.2