From 5db0bf99944ff2d3e83ef27d2aebe8f074d93d59 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Wed, 10 Jan 2018 02:41:30 +0100 Subject: [PATCH] radv: Implement VK_EXT_discard_rectangles. Tested with a modified deferred demo and no regressions in a 1.0.2 mustpass run. Reviewed-by: Samuel Pitoiset Reviewed-by: Dave Airlie --- src/amd/vulkan/radv_cmd_buffer.c | 51 +++++++++++++++++++++++++++++++++++++++ src/amd/vulkan/radv_device.c | 6 +++++ src/amd/vulkan/radv_extensions.py | 1 + src/amd/vulkan/radv_pipeline.c | 35 +++++++++++++++++++++++++++ src/amd/vulkan/radv_private.h | 23 +++++++++++++----- 5 files changed, 110 insertions(+), 6 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 3114ae9..4b5556b 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -91,6 +91,7 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, */ dest->viewport.count = src->viewport.count; dest->scissor.count = src->scissor.count; + dest->discard_rectangle.count = src->discard_rectangle.count; if (copy_mask & RADV_DYNAMIC_VIEWPORT) { if (memcmp(&dest->viewport.viewports, &src->viewport.viewports, @@ -168,6 +169,16 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, } } + if (copy_mask & RADV_DYNAMIC_DISCARD_RECTANGLE) { + if (memcmp(&dest->discard_rectangle.rectangles, &src->discard_rectangle.rectangles, + src->discard_rectangle.count * sizeof(VkRect2D))) { + typed_memcpy(dest->discard_rectangle.rectangles, + src->discard_rectangle.rectangles, + src->discard_rectangle.count); + dest_mask |= RADV_DYNAMIC_DISCARD_RECTANGLE; + } + } + cmd_buffer->state.dirty |= dest_mask; } @@ -1098,6 +1109,8 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer) } radeon_set_context_reg(cmd_buffer->cs, R_028A6C_VGT_GS_OUT_PRIM_TYPE, pipeline->graphics.gs_out); + radeon_set_context_reg(cmd_buffer->cs, R_02820C_PA_SC_CLIPRECT_RULE, pipeline->graphics.pa_sc_cliprect_rule); + if (unlikely(cmd_buffer->device->trace_bo)) radv_save_pipeline(cmd_buffer, pipeline, RING_GFX); @@ -1135,6 +1148,22 @@ radv_emit_scissor(struct radv_cmd_buffer *cmd_buffer) } static void +radv_emit_discard_rectangle(struct radv_cmd_buffer *cmd_buffer) +{ + if (!cmd_buffer->state.dynamic.discard_rectangle.count) + return; + + radeon_set_context_reg_seq(cmd_buffer->cs, R_028210_PA_SC_CLIPRECT_0_TL, + cmd_buffer->state.dynamic.discard_rectangle.count * 2); + for (unsigned i = 0; i < cmd_buffer->state.dynamic.discard_rectangle.count; ++i) { + VkRect2D rect = cmd_buffer->state.dynamic.discard_rectangle.rectangles[i]; + radeon_emit(cmd_buffer->cs, S_028210_TL_X(rect.offset.x) | S_028210_TL_Y(rect.offset.y)); + radeon_emit(cmd_buffer->cs, S_028214_BR_X(rect.offset.x + rect.extent.width) | + S_028214_BR_Y(rect.offset.y + rect.extent.height)); + } +} + +static void radv_emit_line_width(struct radv_cmd_buffer *cmd_buffer) { unsigned width = cmd_buffer->state.dynamic.line_width * 8; @@ -1627,6 +1656,9 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer) RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS)) radv_emit_depth_biais(cmd_buffer); + if (cmd_buffer->state.dirty & RADV_CMD_DIRTY_DYNAMIC_DISCARD_RECTANGLE) + radv_emit_discard_rectangle(cmd_buffer); + cmd_buffer->state.dirty &= ~RADV_CMD_DIRTY_DYNAMIC_ALL; } @@ -2882,6 +2914,25 @@ void radv_CmdSetStencilReference( cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE; } +void radv_CmdSetDiscardRectangleEXT( + VkCommandBuffer commandBuffer, + uint32_t firstDiscardRectangle, + uint32_t discardRectangleCount, + const VkRect2D* pDiscardRectangles) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + MAYBE_UNUSED const uint32_t total_count = firstDiscardRectangle + discardRectangleCount; + + assert(firstDiscardRectangle < MAX_DISCARD_RECTANGLES); + assert(total_count >= 1 && total_count <= MAX_DISCARD_RECTANGLES); + + typed_memcpy(&state->dynamic.discard_rectangle.rectangles[firstDiscardRectangle], + pDiscardRectangles, discardRectangleCount); + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_DISCARD_RECTANGLE; +} + void radv_CmdExecuteCommands( VkCommandBuffer commandBuffer, uint32_t commandBufferCount, diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 4270e6a..baffa41 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -794,6 +794,12 @@ void radv_GetPhysicalDeviceProperties2KHR( properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT: { + VkPhysicalDeviceDiscardRectanglePropertiesEXT *properties = + (VkPhysicalDeviceDiscardRectanglePropertiesEXT*)ext; + properties->maxDiscardRectangles = MAX_DISCARD_RECTANGLES; + break; + } default: break; } diff --git a/src/amd/vulkan/radv_extensions.py b/src/amd/vulkan/radv_extensions.py index 6bdb011..9980cfc 100644 --- a/src/amd/vulkan/radv_extensions.py +++ b/src/amd/vulkan/radv_extensions.py @@ -81,6 +81,7 @@ EXTENSIONS = [ Extension('VK_KHR_xcb_surface', 6, 'VK_USE_PLATFORM_XCB_KHR'), Extension('VK_KHR_xlib_surface', 6, 'VK_USE_PLATFORM_XLIB_KHR'), Extension('VK_KHX_multiview', 1, True), + Extension('VK_EXT_discard_rectangles', 1, True), Extension('VK_EXT_external_memory_dma_buf', 1, True), Extension('VK_EXT_global_priority', 1, 'device->rad_info.has_ctx_priority'), Extension('VK_AMD_draw_indirect_count', 1, True), diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 9ece79e..c3c17af 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -1006,6 +1006,8 @@ static unsigned radv_dynamic_state_mask(VkDynamicState state) return RADV_DYNAMIC_STENCIL_WRITE_MASK; case VK_DYNAMIC_STATE_STENCIL_REFERENCE: return RADV_DYNAMIC_STENCIL_REFERENCE; + case VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT: + return RADV_DYNAMIC_DISCARD_RECTANGLE; default: unreachable("Unhandled dynamic state"); } @@ -1133,6 +1135,39 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline, } } + const VkPipelineDiscardRectangleStateCreateInfoEXT *discard_rectangle_info = + vk_find_struct_const(pCreateInfo->pNext, PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT); + if (discard_rectangle_info) { + dynamic->discard_rectangle.count = discard_rectangle_info->discardRectangleCount; + typed_memcpy(dynamic->discard_rectangle.rectangles, + discard_rectangle_info->pDiscardRectangles, + discard_rectangle_info->discardRectangleCount); + + unsigned mask = 0; + + for (unsigned i = 0; i < (1u << MAX_DISCARD_RECTANGLES); ++i) { + /* Interpret i as a bitmask, and then set the bit in the mask if + * that combination of rectangles in which the pixel is contained + * should pass the cliprect test. */ + unsigned relevant_subset = i & ((1u << discard_rectangle_info->discardRectangleCount) - 1); + + if (discard_rectangle_info->discardRectangleMode == VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT && + !relevant_subset) + continue; + + if (discard_rectangle_info->discardRectangleMode == VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT && + relevant_subset) + continue; + + mask |= 1u << i; + } + pipeline->graphics.pa_sc_cliprect_rule = mask; + } else { + states &= ~RADV_DYNAMIC_DISCARD_RECTANGLE; + + /* Allow from all rectangle combinations */ + pipeline->graphics.pa_sc_cliprect_rule = 0xffff; + } pipeline->dynamic_state.mask = states; } diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index b7c53d0..7330dc6 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -81,6 +81,7 @@ typedef uint32_t xcb_window_t; #define MAX_RTS 8 #define MAX_VIEWPORTS 16 #define MAX_SCISSORS 16 +#define MAX_DISCARD_RECTANGLES 4 #define MAX_PUSH_CONSTANTS_SIZE 128 #define MAX_PUSH_DESCRIPTORS 32 #define MAX_DYNAMIC_BUFFERS 16 @@ -739,7 +740,8 @@ enum radv_dynamic_state_bits { RADV_DYNAMIC_STENCIL_COMPARE_MASK = 1 << 6, RADV_DYNAMIC_STENCIL_WRITE_MASK = 1 << 7, RADV_DYNAMIC_STENCIL_REFERENCE = 1 << 8, - RADV_DYNAMIC_ALL = (1 << 9) - 1, + RADV_DYNAMIC_DISCARD_RECTANGLE = 1 << 9, + RADV_DYNAMIC_ALL = (1 << 10) - 1, }; enum radv_cmd_dirty_bits { @@ -754,11 +756,12 @@ enum radv_cmd_dirty_bits { RADV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK = 1 << 6, RADV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK = 1 << 7, RADV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE = 1 << 8, - RADV_CMD_DIRTY_DYNAMIC_ALL = (1 << 9) - 1, - RADV_CMD_DIRTY_PIPELINE = 1 << 9, - RADV_CMD_DIRTY_INDEX_BUFFER = 1 << 10, - RADV_CMD_DIRTY_FRAMEBUFFER = 1 << 11, - RADV_CMD_DIRTY_VERTEX_BUFFER = 1 << 12, + RADV_CMD_DIRTY_DYNAMIC_DISCARD_RECTANGLE = 1 << 9, + RADV_CMD_DIRTY_DYNAMIC_ALL = (1 << 10) - 1, + RADV_CMD_DIRTY_PIPELINE = 1 << 10, + RADV_CMD_DIRTY_INDEX_BUFFER = 1 << 11, + RADV_CMD_DIRTY_FRAMEBUFFER = 1 << 12, + RADV_CMD_DIRTY_VERTEX_BUFFER = 1 << 13, }; enum radv_cmd_flush_bits { @@ -803,6 +806,11 @@ struct radv_scissor_state { VkRect2D scissors[MAX_SCISSORS]; }; +struct radv_discard_rectangle_state { + uint32_t count; + VkRect2D rectangles[MAX_DISCARD_RECTANGLES]; +}; + struct radv_dynamic_state { /** * Bitmask of (1 << VK_DYNAMIC_STATE_*). @@ -843,6 +851,8 @@ struct radv_dynamic_state { uint32_t front; uint32_t back; } stencil_reference; + + struct radv_discard_rectangle_state discard_rectangle; }; extern const struct radv_dynamic_state default_dynamic_state; @@ -1239,6 +1249,7 @@ struct radv_pipeline { uint32_t vtx_reuse_depth; struct radv_prim_vertex_count prim_vertex_count; bool can_use_guardband; + uint32_t pa_sc_cliprect_rule; } graphics; }; -- 2.7.4