nvk: implement VK_EXT_discard_rectangles

Reviewed-by: Mel Henning <mhenning@darkrefraction.com>
Signed-off-by: Lorenzo Rossi <git@rossilorenzo.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33476>
This commit is contained in:
Lorenzo Rossi 2025-10-22 00:19:29 +02:00 committed by Marge Bot
parent 4c62e09505
commit dc0dcc993b
8 changed files with 128 additions and 4 deletions

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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,

View file

@ -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)