Module: Mesa Branch: main Commit: 148ea7792f32d6a454c610fa8a49994ff954a61f URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=148ea7792f32d6a454c610fa8a49994ff954a61f
Author: Faith Ekstrand <faith.ekstr...@collabora.com> Date: Thu Jan 11 18:08:56 2024 -0600 nvk: Emit SET_ANTI_ALIAS at draw time when no render targets are bound Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27025> --- src/nouveau/vulkan/nvk_cmd_buffer.h | 1 + src/nouveau/vulkan/nvk_cmd_draw.c | 58 ++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.h b/src/nouveau/vulkan/nvk_cmd_buffer.h index 86ec031f21e..67a1dcdce3f 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.h +++ b/src/nouveau/vulkan/nvk_cmd_buffer.h @@ -91,6 +91,7 @@ struct nvk_rendering_state { VkRect2D area; uint32_t layer_count; uint32_t view_mask; + uint32_t samples; uint32_t color_att_count; struct nvk_attachment color_att[NVK_MAX_RTS]; diff --git a/src/nouveau/vulkan/nvk_cmd_draw.c b/src/nouveau/vulkan/nvk_cmd_draw.c index f0b2df87922..bde6429f597 100644 --- a/src/nouveau/vulkan/nvk_cmd_draw.c +++ b/src/nouveau/vulkan/nvk_cmd_draw.c @@ -455,6 +455,9 @@ nvk_cmd_buffer_dirty_render_pass(struct nvk_cmd_buffer *cmd) BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_WRITE_ENABLE); BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE); BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE); + + /* This may depend on render targets for ESO */ + BITSET_SET(dyn->dirty, MESA_VK_DYNAMIC_MS_RASTERIZATION_SAMPLES); } void @@ -496,6 +499,7 @@ nvk_cmd_buffer_begin_graphics(struct nvk_cmd_buffer *cmd, render->area = (VkRect2D) { }; render->layer_count = 0; render->view_mask = inheritance_info->viewMask; + render->samples = inheritance_info->rasterizationSamples; render->color_att_count = inheritance_info->colorAttachmentCount; for (uint32_t i = 0; i < render->color_att_count; i++) { @@ -592,6 +596,7 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer, render->area = pRenderingInfo->renderArea; render->view_mask = pRenderingInfo->viewMask; render->layer_count = pRenderingInfo->layerCount; + render->samples = 0; const uint32_t layer_count = render->view_mask ? util_last_bit(render->view_mask) : @@ -647,6 +652,7 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer, assert(sample_layout == NIL_SAMPLE_LAYOUT_INVALID || sample_layout == image->planes[ip].nil.sample_layout); sample_layout = image->planes[ip].nil.sample_layout; + render->samples = image->vk.samples; uint64_t addr = nvk_image_base_address(image, ip) + level->offset_B; @@ -767,6 +773,7 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer, assert(sample_layout == NIL_SAMPLE_LAYOUT_INVALID || sample_layout == nil_image.sample_layout); sample_layout = nil_image.sample_layout; + render->samples = image->vk.samples; P_MTHD(p, NV9097, SET_ZT_A); P_NV9097_SET_ZT_A(p, addr >> 32); @@ -807,10 +814,28 @@ nvk_CmdBeginRendering(VkCommandBuffer commandBuffer, P_IMMD(p, NV9097, SET_ZT_SELECT, 0 /* target_count */); } - if (sample_layout == NIL_SAMPLE_LAYOUT_INVALID) - sample_layout = NIL_SAMPLE_LAYOUT_1X1; - - P_IMMD(p, NV9097, SET_ANTI_ALIAS, nil_to_nv9097_samples_mode(sample_layout)); + /* From the Vulkan 1.3.275 spec: + * + * "It is legal for a subpass to use no color or depth/stencil + * attachments, either because it has no attachment references or + * because all of them are VK_ATTACHMENT_UNUSED. This kind of subpass + * can use shader side effects such as image stores and atomics to + * produce an output. In this case, the subpass continues to use the + * width, height, and layers of the framebuffer to define the dimensions + * of the rendering area, and the rasterizationSamples from each + * pipeline’s VkPipelineMultisampleStateCreateInfo to define the number + * of samples used in rasterization;" + * + * In the case where we have attachments, we emit SET_ANTI_ALIAS here + * because SET_COLOR_TARGET_* and SET_ZT_* don't have any other way of + * specifying the sample layout and we want to ensure it matches. When + * we don't have any attachments, we defer SET_ANTI_ALIAS to draw time + * where we base it on dynamic rasterizationSamples. + */ + if (sample_layout != NIL_SAMPLE_LAYOUT_INVALID) { + P_IMMD(p, NV9097, SET_ANTI_ALIAS, + nil_to_nv9097_samples_mode(sample_layout)); + } if (render->flags & VK_RENDERING_RESUMING_BIT) return; @@ -1398,9 +1423,34 @@ static void nvk_flush_ms_state(struct nvk_cmd_buffer *cmd) { struct nvk_descriptor_state *desc = &cmd->state.gfx.descriptors; + const struct nvk_rendering_state *render = &cmd->state.gfx.render; const struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state; + if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_MS_RASTERIZATION_SAMPLES)) { + /* When we don't have any attachments, we can't know the sample count + * from the render pass so we need to emit SET_ANTI_ALIAS here. See the + * comment in nvk_BeginRendering() for more details. + */ + if (render->samples == 0) { + struct nv_push *p = nvk_cmd_buffer_push(cmd, 2); + + /* Multisample information MAY be missing (rasterizationSamples == 0) + * if rasterizer discard is enabled. However, this isn't valid in + * the hardware so always use at least one sample. + */ + const uint32_t samples = MAX2(1, dyn->ms.rasterization_samples); + enum nil_sample_layout layout = nil_choose_sample_layout(samples); + P_IMMD(p, NV9097, SET_ANTI_ALIAS, nil_to_nv9097_samples_mode(layout)); + } else { + /* Multisample information MAY be missing (rasterizationSamples == 0) + * if rasterizer discard is enabled. + */ + assert(dyn->ms.rasterization_samples == 0 || + dyn->ms.rasterization_samples == render->samples); + } + } + if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_MS_ALPHA_TO_COVERAGE_ENABLE) || BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_MS_ALPHA_TO_ONE_ENABLE)) { struct nv_push *p = nvk_cmd_buffer_push(cmd, 2);