From 55951ac28e7a30c2fae762990962a4410669c989 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tapani=20P=C3=A4lli?= Date: Tue, 15 Jun 2021 09:55:51 +0300 Subject: [PATCH] anv: fix emitting dynamic primitive topology MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Initial implementation missed various fields that derive from the primitive topology. This patch fixes 3DSTATE_RASTER/3DSTATE_SF, 3DSTATE_CLIP and 3DSTATE_WM (gen7.x) emission in the dynamic case. Fixes: f6fa4a80000 ("anv: add support for dynamic primitive topology change") Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4924 Signed-off-by: Tapani Pälli Reviewed-by: Lionel Landwerlin Part-of: --- src/intel/vulkan/anv_genX.h | 14 +++ src/intel/vulkan/anv_pipeline.c | 43 ++++++++- src/intel/vulkan/anv_private.h | 17 ++++ src/intel/vulkan/genX_cmd_buffer.c | 19 ++++ src/intel/vulkan/genX_pipeline.c | 179 +++++++++++++++++++------------------ src/intel/vulkan/gfx7_cmd_buffer.c | 87 +++++++++++++----- src/intel/vulkan/gfx8_cmd_buffer.c | 62 +++++++++---- 7 files changed, 295 insertions(+), 126 deletions(-) diff --git a/src/intel/vulkan/anv_genX.h b/src/intel/vulkan/anv_genX.h index 3f7aa7e..1a59502 100644 --- a/src/intel/vulkan/anv_genX.h +++ b/src/intel/vulkan/anv_genX.h @@ -126,3 +126,17 @@ void genX(blorp_exec)(struct blorp_batch *batch, void genX(cmd_emit_timestamp)(struct anv_batch *batch, struct anv_bo *bo, uint32_t offset); + +void +genX(rasterization_mode)(VkPolygonMode raster_mode, + VkLineRasterizationModeEXT line_mode, + uint32_t *api_mode, + bool *msaa_rasterization_enable); + +uint32_t +genX(ms_rasterization_mode)(struct anv_graphics_pipeline *pipeline, + VkPolygonMode raster_mode); + +VkPolygonMode +genX(raster_polygon_mode)(struct anv_graphics_pipeline *pipeline, + VkPrimitiveTopology primitive_topology); diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 3eee533..2855e36 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -2244,7 +2244,8 @@ copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline, ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE | ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE | ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE | - ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP); + ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP | + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY); } static void @@ -2321,6 +2322,25 @@ anv_pipeline_setup_l3_config(struct anv_pipeline *pipeline, bool needs_slm) pipeline->l3_config = intel_get_l3_config(devinfo, w); } +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; +} + VkResult anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline, struct anv_device *device, @@ -2461,6 +2481,27 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline, else pipeline->topology = vk_to_intel_primitive_type[ia_info->topology]; + /* If rasterization is not enabled, ms_info must be ignored. */ + const bool raster_enabled = + !pCreateInfo->pRasterizationState->rasterizerDiscardEnable || + (pipeline->dynamic_states & + ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE); + + const VkPipelineMultisampleStateCreateInfo *ms_info = + raster_enabled ? pCreateInfo->pMultisampleState : NULL; + + const VkPipelineRasterizationLineStateCreateInfoEXT *line_info = + vk_find_struct_const(pCreateInfo->pRasterizationState->pNext, + PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT); + + /* Store line mode, polygon mode and rasterization samples, these are used + * for dynamic primitive topology. + */ + pipeline->line_mode = vk_line_rasterization_mode(line_info, ms_info); + pipeline->polygon_mode = pCreateInfo->pRasterizationState->polygonMode; + pipeline->rasterization_samples = + ms_info ? ms_info->rasterizationSamples : 1; + return VK_SUCCESS; } diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index be2d7ff..4172b07 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -3529,6 +3529,13 @@ struct anv_graphics_pipeline { uint32_t topology; + /* These fields are required with dynamic primitive topology, + * rasterization_samples used only with gen < 8. + */ + VkLineRasterizationModeEXT line_mode; + VkPolygonMode polygon_mode; + uint32_t rasterization_samples; + struct anv_subpass * subpass; struct anv_shader_bin * shaders[MESA_SHADER_STAGES]; @@ -4441,6 +4448,16 @@ anv_sanitize_image_offset(const VkImageType imageType, } } +static inline uint32_t +anv_rasterization_aa_mode(VkPolygonMode raster_mode, + VkLineRasterizationModeEXT line_mode) +{ + if (raster_mode == VK_POLYGON_MODE_LINE && + line_mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT) + return true; + return false; +} + VkFormatFeatureFlags anv_get_image_format_features(const struct intel_device_info *devinfo, VkFormat vk_format, diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index 5e2b5b3..47aba61 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -3468,12 +3468,30 @@ cmd_buffer_emit_clip(struct anv_cmd_buffer *cmd_buffer) ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE | ANV_CMD_DIRTY_DYNAMIC_CULL_MODE | #endif + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY | ANV_CMD_DIRTY_DYNAMIC_VIEWPORT | ANV_CMD_DIRTY_PIPELINE; if ((cmd_buffer->state.gfx.dirty & clip_states) == 0) return; + /* Take dynamic primitive topology in to account with + * 3DSTATE_CLIP::ViewportXYClipTestEnable + */ + bool xy_clip_test_enable = 0; + + if (cmd_buffer->state.gfx.pipeline->dynamic_states & + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { + VkPrimitiveTopology primitive_topology = + cmd_buffer->state.gfx.dynamic.primitive_topology; + + VkPolygonMode dynamic_raster_mode = + genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline, + primitive_topology); + + xy_clip_test_enable = (dynamic_raster_mode == VK_POLYGON_MODE_FILL); + } + #if GFX_VER <= 7 const struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic; #endif @@ -3483,6 +3501,7 @@ cmd_buffer_emit_clip(struct anv_cmd_buffer *cmd_buffer) .FrontWinding = genX(vk_to_intel_front_face)[d->front_face], .CullMode = genX(vk_to_intel_cullmode)[d->cull_mode], #endif + .ViewportXYClipTestEnable = xy_clip_test_enable, }; uint32_t dwords[GENX(3DSTATE_CLIP_length)]; diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c index e7d79de..005782f 100644 --- a/src/intel/vulkan/genX_pipeline.c +++ b/src/intel/vulkan/genX_pipeline.c @@ -445,34 +445,14 @@ emit_3dstate_sbe(struct anv_graphics_pipeline *pipeline) #endif } -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 * different shader stages which might generate their own type of primitives. */ -static VkPolygonMode -anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline, - const VkPipelineInputAssemblyStateCreateInfo *ia_info, - const VkPipelineRasterizationStateCreateInfo *rs_info) +VkPolygonMode +genX(raster_polygon_mode)(struct anv_graphics_pipeline *pipeline, + VkPrimitiveTopology primitive_topology) { if (anv_pipeline_has_stage(pipeline, MESA_SHADER_GEOMETRY)) { switch (get_gs_prog_data(pipeline)->output_topology) { @@ -491,7 +471,7 @@ anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline, case _3DPRIM_QUADLIST: case _3DPRIM_QUADSTRIP: case _3DPRIM_POLYGON: - return rs_info->polygonMode; + return pipeline->polygon_mode; } unreachable("Unsupported GS output topology"); } else if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) { @@ -504,11 +484,11 @@ anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline, case BRW_TESS_OUTPUT_TOPOLOGY_TRI_CW: case BRW_TESS_OUTPUT_TOPOLOGY_TRI_CCW: - return rs_info->polygonMode; + return pipeline->polygon_mode; } unreachable("Unsupported TCS output topology"); } else { - switch (ia_info->topology) { + switch (primitive_topology) { case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return VK_POLYGON_MODE_POINT; @@ -523,7 +503,7 @@ anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline, case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: - return rs_info->polygonMode; + return pipeline->polygon_mode; default: unreachable("Unsupported primitive topology"); @@ -531,21 +511,13 @@ anv_raster_polygon_mode(struct anv_graphics_pipeline *pipeline, } } -#if GFX_VER <= 7 -static uint32_t -gfx7_ms_rast_mode(struct anv_graphics_pipeline *pipeline, - const VkPipelineInputAssemblyStateCreateInfo *ia_info, - const VkPipelineRasterizationStateCreateInfo *rs_info, - const VkPipelineMultisampleStateCreateInfo *ms_info) +uint32_t +genX(ms_rasterization_mode)(struct anv_graphics_pipeline *pipeline, + VkPolygonMode raster_mode) { - 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 GFX_VER <= 7 if (raster_mode == VK_POLYGON_MODE_LINE) { - switch (vk_line_rasterization_mode(line_info, ms_info)) { + switch (pipeline->line_mode) { case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT: return MSRASTMODE_ON_PATTERN; @@ -557,11 +529,13 @@ gfx7_ms_rast_mode(struct anv_graphics_pipeline *pipeline, unreachable("Unsupported line rasterization mode"); } } else { - return (ms_info && ms_info->rasterizationSamples > 1) ? - MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL; + return pipeline->rasterization_samples > 1 ? + MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL; } -} +#else + unreachable("Only on gen7"); #endif +} static VkProvokingVertexModeEXT vk_provoking_vertex_mode(const VkPipelineRasterizationStateCreateInfo *rs_info) @@ -603,6 +577,49 @@ vk_conservative_rasterization_mode(const VkPipelineRasterizationStateCreateInfo } #endif +void +genX(rasterization_mode)(VkPolygonMode raster_mode, + VkLineRasterizationModeEXT line_mode, + uint32_t *api_mode, + bool *msaa_rasterization_enable) +{ +#if GFX_VER >= 8 + if (raster_mode == VK_POLYGON_MODE_LINE) { + /* Unfortunately, configuring our line rasterization hardware on gfx8 + * and later is rather painful. Instead of giving us bits to tell the + * hardware what line mode to use like we had on gfx7, 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: + *api_mode = DX100; + *msaa_rasterization_enable = true; + break; + + case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT: + case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT: + *api_mode = DX9OGL; + *msaa_rasterization_enable = false; + break; + + default: + unreachable("Unsupported line rasterization mode"); + } + } else { + *api_mode = DX100; + *msaa_rasterization_enable = true; + } +#else + unreachable("Invalid call"); +#endif +} + static void emit_rs_state(struct anv_graphics_pipeline *pipeline, const VkPipelineInputAssemblyStateCreateInfo *ia_info, @@ -667,45 +684,18 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline, #endif VkPolygonMode raster_mode = - anv_raster_polygon_mode(pipeline, ia_info, rs_info); - VkLineRasterizationModeEXT line_mode = - vk_line_rasterization_mode(line_info, ms_info); + genX(raster_polygon_mode)(pipeline, ia_info->topology); + bool dynamic_primitive_topology = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; /* For details on 3DSTATE_RASTER multisample state, see the BSpec table * "Multisample Modes State". */ #if GFX_VER >= 8 - if (raster_mode == VK_POLYGON_MODE_LINE) { - /* Unfortunately, configuring our line rasterization hardware on gfx8 - * and later is rather painful. Instead of giving us bits to tell the - * hardware what line mode to use like we had on gfx7, 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; - } + if (!dynamic_primitive_topology) + genX(rasterization_mode)(raster_mode, pipeline->line_mode, + &raster.APIMode, + &raster.DXMultisampleRasterizationEnable); /* NOTE: 3DSTATE_RASTER::ForcedSampleCount affects the BDW and SKL PMA fix * computations. If we ever set this bit to a different value, they will @@ -714,13 +704,17 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline, raster.ForcedSampleCount = FSC_NUMRASTSAMPLES_0; raster.ForceMultisampling = false; #else - raster.MultisampleRasterizationMode = - gfx7_ms_rast_mode(pipeline, ia_info, rs_info, ms_info); + uint32_t ms_rast_mode = 0; + + if (!dynamic_primitive_topology) + ms_rast_mode = genX(ms_rasterization_mode)(pipeline, raster_mode); + + raster.MultisampleRasterizationMode = ms_rast_mode; #endif - if (raster_mode == VK_POLYGON_MODE_LINE && - line_mode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT) - raster.AntialiasingEnable = true; + raster.AntialiasingEnable = + dynamic_primitive_topology ? 0 : + anv_rasterization_aa_mode(raster_mode, pipeline->line_mode); raster.FrontWinding = dynamic_states & ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE ? @@ -1423,8 +1417,10 @@ emit_3dstate_clip(struct anv_graphics_pipeline *pipeline, * points and lines so we get "pop-free" clipping. */ VkPolygonMode raster_mode = - anv_raster_polygon_mode(pipeline, ia_info, rs_info); - clip.ViewportXYClipTestEnable = (raster_mode == VK_POLYGON_MODE_FILL); + genX(raster_polygon_mode)(pipeline, ia_info->topology); + clip.ViewportXYClipTestEnable = + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY ? + 0 : (raster_mode == VK_POLYGON_MODE_FILL); #if GFX_VER >= 8 clip.VertexSubPixelPrecisionSelect = _8Bit; @@ -2133,14 +2129,25 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline, struct anv_subpass *subp } else { wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE; } + + VkPolygonMode raster_mode = + genX(raster_polygon_mode)(pipeline, ia->topology); + wm.MultisampleRasterizationMode = - gfx7_ms_rast_mode(pipeline, ia, raster, multisample); + dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY ? 0 : + genX(ms_rasterization_mode)(pipeline, raster_mode); #endif wm.LineStippleEnable = line && line->stippledLineEnable; } - if (dynamic_states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) { + uint32_t dynamic_wm_states = ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE; + +#if GFX_VER < 8 + dynamic_wm_states |= ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; +#endif + + if (dynamic_states & dynamic_wm_states) { const struct intel_device_info *devinfo = &pipeline->base.device->info; uint32_t *dws = devinfo->ver >= 8 ? pipeline->gfx8.wm : pipeline->gfx7.wm; GENX(3DSTATE_WM_pack)(NULL, dws, &wm); diff --git a/src/intel/vulkan/gfx7_cmd_buffer.c b/src/intel/vulkan/gfx7_cmd_buffer.c index ff808f2..b092bd8 100644 --- a/src/intel/vulkan/gfx7_cmd_buffer.c +++ b/src/intel/vulkan/gfx7_cmd_buffer.c @@ -206,13 +206,42 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline; struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic; + if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { + uint32_t topology; + if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) + topology = pipeline->topology; + else + topology = genX(vk_to_intel_primitive_type)[d->primitive_topology]; + + cmd_buffer->state.gfx.primitive_topology = topology; + } + if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | ANV_CMD_DIRTY_RENDER_TARGETS | ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH | ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS | ANV_CMD_DIRTY_DYNAMIC_CULL_MODE | ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE | - ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE)) { + ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE | + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) { + /* Take dynamic primitive topology in to account with + * 3DSTATE_SF::MultisampleRasterizationMode + */ + uint32_t ms_rast_mode = 0; + + if (cmd_buffer->state.gfx.pipeline->dynamic_states & + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { + VkPrimitiveTopology primitive_topology = + cmd_buffer->state.gfx.dynamic.primitive_topology; + + VkPolygonMode dynamic_raster_mode = + genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline, + primitive_topology); + + ms_rast_mode = + genX(ms_rasterization_mode)(pipeline, dynamic_raster_mode); + } + uint32_t sf_dw[GENX(3DSTATE_SF_length)]; struct GENX(3DSTATE_SF) sf = { GENX(3DSTATE_SF_header), @@ -226,6 +255,7 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) .GlobalDepthOffsetEnableSolid = d->depth_bias_enable, .GlobalDepthOffsetEnableWireframe = d->depth_bias_enable, .GlobalDepthOffsetEnablePoint = d->depth_bias_enable, + .MultisampleRasterizationMode = ms_rast_mode, }; GENX(3DSTATE_SF_pack)(NULL, sf_dw, &sf); @@ -339,45 +369,56 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) } } - if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | - ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) { - uint32_t topology; - if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) - topology = pipeline->topology; - else - topology = genX(vk_to_intel_primitive_type)[d->primitive_topology]; - - cmd_buffer->state.gfx.primitive_topology = topology; - } - - if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) { - genX(emit_multisample)(&cmd_buffer->batch, - cmd_buffer->state.gfx.dynamic.sample_locations.samples, - cmd_buffer->state.gfx.dynamic.sample_locations.locations); - } - + /* 3DSTATE_WM in the hope we can avoid spawning fragment shaders + * threads or if we have dirty dynamic primitive topology state and + * need to toggle 3DSTATE_WM::MultisampleRasterizationMode dynamically. + */ if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE || - cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP) { + cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes; - /* 3DSTATE_WM in the hope we can avoid spawning fragment shaders - * threads. - */ + bool dirty_color_blend = cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE; - if (dirty_color_blend) { + bool dirty_primitive_topology = + cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; + + VkPolygonMode dynamic_raster_mode; + VkPrimitiveTopology primitive_topology = + cmd_buffer->state.gfx.dynamic.primitive_topology; + dynamic_raster_mode = + genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline, + primitive_topology); + + if (dirty_color_blend || dirty_primitive_topology) { uint32_t dwords[GENX(3DSTATE_WM_length)]; struct GENX(3DSTATE_WM) wm = { GENX(3DSTATE_WM_header), .ThreadDispatchEnable = pipeline->force_fragment_thread_dispatch || color_writes, + .MultisampleRasterizationMode = + genX(ms_rasterization_mode)(pipeline, dynamic_raster_mode), }; GENX(3DSTATE_WM_pack)(NULL, dwords, &wm); anv_batch_emit_merge(&cmd_buffer->batch, dwords, pipeline->gfx7.wm); } + } + + if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) { + genX(emit_multisample)(&cmd_buffer->batch, + cmd_buffer->state.gfx.dynamic.sample_locations.samples, + cmd_buffer->state.gfx.dynamic.sample_locations.locations); + } + + if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE || + cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP) { + const uint8_t color_writes = cmd_buffer->state.gfx.dynamic.color_writes; + bool dirty_color_blend = + cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE; + /* Blend states of each RT */ uint32_t surface_count = 0; struct anv_pipeline_bind_map *map; diff --git a/src/intel/vulkan/gfx8_cmd_buffer.c b/src/intel/vulkan/gfx8_cmd_buffer.c index f428c02..05092ca 100644 --- a/src/intel/vulkan/gfx8_cmd_buffer.c +++ b/src/intel/vulkan/gfx8_cmd_buffer.c @@ -420,6 +420,20 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline; struct anv_dynamic_state *d = &cmd_buffer->state.gfx.dynamic; + if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { + uint32_t topology; + if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) + topology = pipeline->topology; + else + topology = genX(vk_to_intel_primitive_type)[d->primitive_topology]; + + cmd_buffer->state.gfx.primitive_topology = topology; + + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF_TOPOLOGY), vft) { + vft.PrimitiveTopologyType = topology; + } + } + if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH)) { uint32_t sf_dw[GENX(3DSTATE_SF_length)]; @@ -443,10 +457,41 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS | ANV_CMD_DIRTY_DYNAMIC_CULL_MODE | ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE | - ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE)) { + ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE | + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) { + /* Take dynamic primitive topology in to account with + * 3DSTATE_RASTER::APIMode + * 3DSTATE_RASTER::DXMultisampleRasterizationEnable + * 3DSTATE_RASTER::AntialiasingEnable + */ + uint32_t api_mode = 0; + bool msaa_raster_enable = false; + bool aa_enable = 0; + + if (cmd_buffer->state.gfx.pipeline->dynamic_states & + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { + VkPrimitiveTopology primitive_topology = + cmd_buffer->state.gfx.dynamic.primitive_topology; + + VkPolygonMode dynamic_raster_mode = + genX(raster_polygon_mode)(cmd_buffer->state.gfx.pipeline, + primitive_topology); + + genX(rasterization_mode)( + dynamic_raster_mode, pipeline->line_mode, &api_mode, + &msaa_raster_enable); + + aa_enable = + anv_rasterization_aa_mode(dynamic_raster_mode, + pipeline->line_mode); + } + uint32_t raster_dw[GENX(3DSTATE_RASTER_length)]; struct GENX(3DSTATE_RASTER) raster = { GENX(3DSTATE_RASTER_header), + .APIMode = api_mode, + .DXMultisampleRasterizationEnable = msaa_raster_enable, + .AntialiasingEnable = aa_enable, .GlobalDepthOffsetConstant = d->depth_bias.bias, .GlobalDepthOffsetScale = d->depth_bias.slope, .GlobalDepthOffsetClamp = d->depth_bias.clamp, @@ -638,21 +683,6 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) } } - if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | - ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) { - uint32_t topology; - if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) - topology = pipeline->topology; - else - topology = genX(vk_to_intel_primitive_type)[d->primitive_topology]; - - cmd_buffer->state.gfx.primitive_topology = topology; - - anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF_TOPOLOGY), vft) { - vft.PrimitiveTopologyType = topology; - } - } - if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) { genX(emit_sample_pattern)(&cmd_buffer->batch, cmd_buffer->state.gfx.dynamic.sample_locations.samples, -- 2.7.4