diff --git a/docs/features.txt b/docs/features.txt index 35e0774c4df..b40b3c15b02 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -613,7 +613,7 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_device_generated_commands DONE (lvp, nvk/Turing+, radv/gfx8+) VK_EXT_device_memory_report DONE (anv, radv, vn) VK_EXT_direct_mode_display DONE (anv, hk, lvp, nvk, panvk, radv, tu, v3dv, vn) - VK_EXT_discard_rectangles DONE (radv) + VK_EXT_discard_rectangles DONE (nvk, radv) VK_EXT_display_control DONE (anv, hasvk, nvk, panvk, radv, tu) VK_EXT_display_surface_counter DONE (anv, lvp, nvk, panvk, radv, tu, vn) VK_EXT_dynamic_rendering_unused_attachments DONE (anv, hk, lvp, nvk, radv, tu, vn) diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index 2bc78b29002..e40e0aa7c03 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -1,3 +1,4 @@ VK_KHR_relaxed_block_layout on pvr VK_KHR_storage_buffer_storage_class on pvr VK_EXT_external_memory_acquire_unmodified on panvk +VK_EXT_discard_rectangles on NVK diff --git a/src/nouveau/vulkan/nvk_cmd_clear.c b/src/nouveau/vulkan/nvk_cmd_clear.c index b0c95b3ba5d..2f55b8686a7 100644 --- a/src/nouveau/vulkan/nvk_cmd_clear.c +++ b/src/nouveau/vulkan/nvk_cmd_clear.c @@ -84,6 +84,21 @@ const struct nvk_mme_test_case nvk_mme_clear_tests[] = {{ }, }, {}}; +void +nvk_mme_update_window_clip(struct mme_builder *b) +{ + struct mme_value is_drawing = mme_load(b); + struct mme_value window_clip_enabled = nvk_mme_load_scratch(b, WINDOW_CLIP_ENABLED); + + struct mme_value new_value = mme_and(b, window_clip_enabled, is_drawing); + mme_mthd(b, NV9097_SET_WINDOW_CLIP_ENABLE); + mme_emit(b, new_value); + + mme_free_reg(b, new_value); + mme_free_reg(b, window_clip_enabled); + mme_free_reg(b, is_drawing); +} + static void emit_clear_rects(struct nvk_cmd_buffer *cmd, int color_att, @@ -135,7 +150,9 @@ nvk_CmdClearAttachments(VkCommandBuffer commandBuffer, const VkClearRect *pRects) { VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); - struct nv_push *p = nvk_cmd_buffer_push(cmd, 2 + attachmentCount * 4); + const struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state; + + struct nv_push *p = nvk_cmd_buffer_push(cmd, 4 + attachmentCount * 4); P_IMMD(p, NV9097, SET_CLEAR_SURFACE_CONTROL, { .respect_stencil_mask = RESPECT_STENCIL_MASK_FALSE, @@ -144,6 +161,15 @@ nvk_CmdClearAttachments(VkCommandBuffer commandBuffer, .use_viewport_clip0 = USE_VIEWPORT_CLIP0_FALSE, }); + /* VK_EXT_discard_rects doesn't influence clears */ + const bool stash_window_clip = + BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DR_ENABLE) || dyn->dr.enable; + if (stash_window_clip) { + /* Disable WINDOW_CLIP while we clear */ + P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_UPDATE_WINDOW_CLIP)); + P_INLINE_DATA(p, 0); + } + bool clear_depth = false, clear_stencil = false; for (uint32_t i = 0; i < attachmentCount; i++) { if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) { @@ -185,6 +211,13 @@ nvk_CmdClearAttachments(VkCommandBuffer commandBuffer, /* No color clears */ if (clear_depth || clear_stencil) emit_clear_rects(cmd, -1, clear_depth, clear_stencil, rectCount, pRects); + + if (stash_window_clip) { + p = nvk_cmd_buffer_push(cmd, 2); + /* Restore stashed WINDOW_CLIP value */ + P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_UPDATE_WINDOW_CLIP)); + P_INLINE_DATA(p, 1); + } } static VkImageViewType diff --git a/src/nouveau/vulkan/nvk_cmd_draw.c b/src/nouveau/vulkan/nvk_cmd_draw.c index 3d058a4d7f6..6314ba2f2fd 100644 --- a/src/nouveau/vulkan/nvk_cmd_draw.c +++ b/src/nouveau/vulkan/nvk_cmd_draw.c @@ -467,7 +467,9 @@ nvk_push_draw_state_init(struct nvk_queue *queue, struct nv_push *p) P_NV9097_SET_WINDOW_OFFSET_Y(p, 0); P_IMMD(p, NV9097, SET_ACTIVE_ZCULL_REGION, 0x3f); - P_IMMD(p, NV9097, SET_WINDOW_CLIP_ENABLE, V_FALSE); + P_IMMD(p, NV9097, SET_MME_SHADOW_SCRATCH(NVK_MME_SCRATCH_WINDOW_CLIP_ENABLED), 0); + P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_UPDATE_WINDOW_CLIP)); + P_INLINE_DATA(p, 1); P_IMMD(p, NV9097, SET_CLIP_ID_TEST, ENABLE_FALSE); // P_IMMD(p, NV9097, X_X_X_SET_CLEAR_CONTROL, { @@ -690,8 +692,9 @@ void nvk_cmd_buffer_begin_graphics(struct nvk_cmd_buffer *cmd, const VkCommandBufferBeginInfo *pBeginInfo) { + const struct nvk_device *dev = nvk_cmd_buffer_device(cmd); if (cmd->vk.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) { - struct nv_push *p = nvk_cmd_buffer_push(cmd, 5); + struct nv_push *p = nvk_cmd_buffer_push(cmd, 9); P_MTHD(p, NV9097, INVALIDATE_SAMPLER_CACHE_NO_WFI); P_NV9097_INVALIDATE_SAMPLER_CACHE_NO_WFI(p, { .lines = LINES_ALL, @@ -703,6 +706,13 @@ nvk_cmd_buffer_begin_graphics(struct nvk_cmd_buffer *cmd, P_IMMD(p, NVA097, INVALIDATE_SHADER_CACHES_NO_WFI, { .constant = CONSTANT_TRUE, }); + if (dev->vk.enabled_extensions.EXT_discard_rectangles) { + P_IMMD(p, NV9097, + SET_MME_SHADOW_SCRATCH(NVK_MME_SCRATCH_WINDOW_CLIP_ENABLED), + 0); + P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_UPDATE_WINDOW_CLIP)); + P_INLINE_DATA(p, 1); + } } cmd->state.gfx.descriptors.flush_root = nvk_cmd_flush_gfx_root_desc; @@ -2075,6 +2085,74 @@ nvk_flush_vp_state(struct nvk_cmd_buffer *cmd) } } +static uint32_t +vk_to_nv9097_dr_mode(VkDiscardRectangleModeEXT vk_mode) +{ + STATIC_ASSERT(VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT == + NV9097_SET_WINDOW_CLIP_TYPE_V_INCLUSIVE); + STATIC_ASSERT(VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT == + NV9097_SET_WINDOW_CLIP_TYPE_V_EXCLUSIVE); + assert(vk_mode <= NV9097_SET_WINDOW_CLIP_TYPE_V_EXCLUSIVE); + return vk_mode; +} + +static void +nvk_flush_dr_state(struct nvk_cmd_buffer *cmd) +{ + struct nvk_device *dev = nvk_cmd_buffer_device(cmd); + const struct nvk_physical_device *pdev = nvk_device_physical(dev); + + const struct vk_dynamic_graphics_state *dyn = + &cmd->vk.dynamic_graphics_state; + + /* VK_EXT_discard_rectangles */ + if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DR_ENABLE)) { + struct nv_push *p = nvk_cmd_buffer_push(cmd, 4); + P_IMMD(p, NV9097, SET_MME_SHADOW_SCRATCH(NVK_MME_SCRATCH_WINDOW_CLIP_ENABLED), + dyn->dr.enable); + P_1INC(p, NV9097, CALL_MME_MACRO(NVK_MME_UPDATE_WINDOW_CLIP)); + P_INLINE_DATA(p, 1); + } + if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DR_MODE)) { + struct nv_push *p = nvk_cmd_buffer_push(cmd, 2); + P_IMMD(p, NV9097, SET_WINDOW_CLIP_TYPE, vk_to_nv9097_dr_mode(dyn->dr.mode)); + } + if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_DR_RECTANGLES)) { + const uint32_t sr_max = + nvk_image_max_dimension(&pdev->info, VK_IMAGE_TYPE_2D); + + struct nv_push *p = + nvk_cmd_buffer_push(cmd, 1 + 2 * NVK_MAX_DISCARD_RECTANGLES); + + P_MTHD(p, NV9097, SET_WINDOW_CLIP_HORIZONTAL(0)); + for (unsigned i = 0; i < NVK_MAX_DISCARD_RECTANGLES; i++) { + const bool is_rect_enabled = i < dyn->dr.rectangle_count; + uint32_t xmin = 0; + uint32_t xmax = 0; + uint32_t ymin = 0; + uint32_t ymax = 0; + + if (is_rect_enabled) { + const VkRect2D *r = &dyn->dr.rectangles[i]; + + xmin = MIN2(sr_max, r->offset.x); + xmax = MIN2(sr_max, r->offset.x + r->extent.width); + ymin = MIN2(sr_max, r->offset.y); + ymax = MIN2(sr_max, r->offset.y + r->extent.height); + } + + P_NV9097_SET_WINDOW_CLIP_HORIZONTAL(p, i, { + .xmin = xmin, + .xmax = xmax, + }); + P_NV9097_SET_WINDOW_CLIP_VERTICAL(p, i, { + .ymin = ymin, + .ymax = ymax, + }); + } + } +} + static uint32_t vk_to_nv9097_polygon_mode(VkPolygonMode vk_mode) { @@ -3413,6 +3491,7 @@ nvk_cmd_flush_gfx_dynamic_state(struct nvk_cmd_buffer *cmd) nvk_flush_ia_state(cmd); nvk_flush_ts_state(cmd); nvk_flush_vp_state(cmd); + nvk_flush_dr_state(cmd); nvk_flush_rs_state(cmd); nvk_flush_fsr_state(cmd); nvk_flush_ms_state(cmd); diff --git a/src/nouveau/vulkan/nvk_mme.c b/src/nouveau/vulkan/nvk_mme.c index 7d1b05ac108..bbec8760987 100644 --- a/src/nouveau/vulkan/nvk_mme.c +++ b/src/nouveau/vulkan/nvk_mme.c @@ -12,6 +12,7 @@ static const nvk_mme_builder_func mme_builders[NVK_MME_COUNT] = { [NVK_MME_SELECT_CB0] = nvk_mme_select_cb0, [NVK_MME_BIND_CBUF_DESC] = nvk_mme_bind_cbuf_desc, [NVK_MME_CLEAR] = nvk_mme_clear, + [NVK_MME_UPDATE_WINDOW_CLIP] = nvk_mme_update_window_clip, [NVK_MME_BIND_IB] = nvk_mme_bind_ib, [NVK_MME_BIND_VB] = nvk_mme_bind_vb, [NVK_MME_SET_VB_ENABLES] = nvk_mme_set_vb_enables, diff --git a/src/nouveau/vulkan/nvk_mme.h b/src/nouveau/vulkan/nvk_mme.h index 06e1d4294ff..6773eb52204 100644 --- a/src/nouveau/vulkan/nvk_mme.h +++ b/src/nouveau/vulkan/nvk_mme.h @@ -16,6 +16,7 @@ enum nvk_mme { NVK_MME_SELECT_CB0, NVK_MME_BIND_CBUF_DESC, NVK_MME_CLEAR, + NVK_MME_UPDATE_WINDOW_CLIP, NVK_MME_BIND_IB, NVK_MME_BIND_VB, NVK_MME_SET_VB_ENABLES, @@ -68,6 +69,9 @@ enum nvk_mme_scratch { NVK_MME_SCRATCH_WRITE_MASK_PIPELINE, NVK_MME_SCRATCH_CONSERVATIVE_RASTER_STATE, + /* Copy of SET_WINDOW_CLIP_ENABLE */ + NVK_MME_SCRATCH_WINDOW_CLIP_ENABLED, /* TODO: can we use shadow-ram? */ + /* Bitfield of enabled vertex buffer bindings */ NVK_MME_SCRATCH_VB_ENABLES, @@ -218,6 +222,7 @@ uint32_t *nvk_build_mme(const struct nv_device_info *devinfo, void nvk_mme_select_cb0(struct mme_builder *b); void nvk_mme_bind_cbuf_desc(struct mme_builder *b); void nvk_mme_clear(struct mme_builder *b); +void nvk_mme_update_window_clip(struct mme_builder *b); void nvk_mme_bind_ib(struct mme_builder *b); void nvk_mme_bind_vb(struct mme_builder *b); void nvk_mme_set_vb_enables(struct mme_builder *b); diff --git a/src/nouveau/vulkan/nvk_physical_device.c b/src/nouveau/vulkan/nvk_physical_device.c index 2ce531ca001..c3675b7f526 100644 --- a/src/nouveau/vulkan/nvk_physical_device.c +++ b/src/nouveau/vulkan/nvk_physical_device.c @@ -214,6 +214,7 @@ nvk_get_device_extensions(const struct nvk_instance *instance, .EXT_descriptor_buffer = info->cls_eng3d >= MAXWELL_A, .EXT_descriptor_indexing = true, .EXT_device_generated_commands = info->cls_eng3d >= MAXWELL_B, + .EXT_discard_rectangles = true, #ifdef VK_USE_PLATFORM_DISPLAY_KHR .EXT_display_control = true, #endif @@ -1018,6 +1019,9 @@ nvk_get_device_properties(const struct nvk_instance *instance, /* VK_KHR_cooperative_matrix */ .cooperativeMatrixSupportedStages = VK_SHADER_STAGE_COMPUTE_BIT, + /* VK_KHR_discard_rectangles */ + .maxDiscardRectangles = NVK_MAX_DISCARD_RECTANGLES, + /* VK_KHR_compute_shader_derivatives */ .meshAndTaskShaderDerivatives = false, diff --git a/src/nouveau/vulkan/nvk_private.h b/src/nouveau/vulkan/nvk_private.h index d67d9e91b8d..8a8acebb672 100644 --- a/src/nouveau/vulkan/nvk_private.h +++ b/src/nouveau/vulkan/nvk_private.h @@ -30,6 +30,7 @@ (NVK_MAX_PUSH_DESCRIPTORS * NVK_MAX_DESCRIPTOR_SIZE) #define NVK_SSBO_BOUNDS_CHECK_ALIGNMENT 4 #define NVK_MAX_MULTIVIEW_VIEW_COUNT 32 +#define NVK_MAX_DISCARD_RECTANGLES 8 #define NVK_SPARSE_ADDR_SPACE_SIZE (1ull << 39) #define NVK_MAX_BUFFER_SIZE (1ull << 31)