radv: detect command buffers that do no work and drop them (v2)
authorDave Airlie <airlied@redhat.com>
Fri, 10 Feb 2017 00:20:44 +0000 (00:20 +0000)
committerDave Airlie <airlied@redhat.com>
Mon, 13 Feb 2017 20:00:28 +0000 (20:00 +0000)
If a buffer is just full of flushes we flush things on command
buffer submission, so don't bother submitting these.

This will reduce some CPU overhead on dota2, which submits a fair
few command streams that don't end up drawing anything.

v2: reorganise loop to count first then malloc,
rename some vars (Bas)

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/amd/vulkan/radv_cmd_buffer.c
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_meta_buffer.c
src/amd/vulkan/radv_private.h
src/amd/vulkan/si_cmd_buffer.c

index f281f33dc7363745c0ef11b483db211121156dee..25b1bd6a3e84c78b40ef78218c0361914dfe47e2 100644 (file)
@@ -1277,6 +1277,7 @@ radv_cmd_buffer_flush_state(struct radv_cmd_buffer *cmd_buffer)
        MAYBE_UNUSED unsigned cdw_max = radeon_check_space(cmd_buffer->device->ws,
                                                           cmd_buffer->cs, 4096);
 
+       cmd_buffer->no_draws = false;
        if ((cmd_buffer->state.vertex_descriptors_dirty || cmd_buffer->state.vb_dirty) &&
            cmd_buffer->state.pipeline->num_vertex_attribs) {
                unsigned vb_offset;
@@ -1592,6 +1593,7 @@ static void  radv_reset_cmd_buffer(struct radv_cmd_buffer *cmd_buffer)
        cmd_buffer->record_fail = false;
 
        cmd_buffer->ring_offsets_idx = -1;
+       cmd_buffer->no_draws = true;
 }
 
 VkResult radv_ResetCommandBuffer(
@@ -2423,6 +2425,7 @@ void radv_CmdDrawIndexedIndirectCountAMD(
 static void
 radv_flush_compute_state(struct radv_cmd_buffer *cmd_buffer)
 {
+       cmd_buffer->no_draws = false;
        radv_emit_compute_pipeline(cmd_buffer);
        radv_flush_descriptors(cmd_buffer, cmd_buffer->state.compute_pipeline,
                               VK_SHADER_STAGE_COMPUTE_BIT);
index fff31259028d91a27af5daefd0daa85ac77bceda..9be09af17954b16df0a7f6175313a98778ce9f51 100644 (file)
@@ -1452,8 +1452,18 @@ VkResult radv_QueueSubmit(
                struct radeon_winsys_cs **cs_array;
                bool can_patch = true;
                uint32_t advance;
+               int draw_cmd_buffers_count = 0;
 
-               if (!pSubmits[i].commandBufferCount) {
+               for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) {
+                       RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer,
+                                        pSubmits[i].pCommandBuffers[j]);
+                       assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+                       if (cmd_buffer->no_draws == true)
+                               continue;
+                       draw_cmd_buffers_count++;
+               }
+
+               if (!draw_cmd_buffers_count) {
                        if (pSubmits[i].waitSemaphoreCount || pSubmits[i].signalSemaphoreCount) {
                                ret = queue->device->ws->cs_submit(ctx, queue->queue_idx,
                                                                   &queue->device->empty_cs[queue->queue_family_index],
@@ -1472,24 +1482,27 @@ VkResult radv_QueueSubmit(
                        continue;
                }
 
-               cs_array = malloc(sizeof(struct radeon_winsys_cs *) *
-                                               pSubmits[i].commandBufferCount);
+               cs_array = malloc(sizeof(struct radeon_winsys_cs *) * draw_cmd_buffers_count);
 
+               int draw_cmd_buffer_idx = 0;
                for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) {
                        RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer,
                                         pSubmits[i].pCommandBuffers[j]);
                        assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+                       if (cmd_buffer->no_draws == true)
+                               continue;
 
-                       cs_array[j] = cmd_buffer->cs;
+                       cs_array[draw_cmd_buffer_idx] = cmd_buffer->cs;
+                       draw_cmd_buffer_idx++;
                        if ((cmd_buffer->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT))
                                can_patch = false;
                }
 
-               for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j += advance) {
+               for (uint32_t j = 0; j < draw_cmd_buffers_count; j += advance) {
                        advance = MIN2(max_cs_submission,
-                                      pSubmits[i].commandBufferCount - j);
+                                      draw_cmd_buffers_count - j);
                        bool b = j == 0;
-                       bool e = j + advance == pSubmits[i].commandBufferCount;
+                       bool e = j + advance == draw_cmd_buffers_count;
 
                        if (queue->device->trace_bo)
                                *queue->device->trace_id_ptr = 0;
index cd2973fa4a9fc015aed6dd4cb83d2c02175310b9..4857d3dc54f544b60c9aef4e6a6035568c172b88 100644 (file)
@@ -523,6 +523,7 @@ void radv_CmdUpdateBuffer(
        assert(!(dataSize & 3));
        assert(!(va & 3));
 
+       cmd_buffer->no_draws = false;
        if (dataSize < 4096) {
                cmd_buffer->device->ws->cs_add_buffer(cmd_buffer->cs, dst_buffer->bo, 8);
 
index 25ed5dec7cfa9e09e3ef674bb2435b4e4fa25bf9..9a88ce0d64df6c68321ca3e48693cc74618c6798 100644 (file)
@@ -750,6 +750,8 @@ struct radv_cmd_buffer {
        uint32_t gsvs_ring_size_needed;
 
        int ring_offsets_idx; /* just used for verification */
+
+       bool no_draws;
 };
 
 struct radv_image;
index 1c99b2282c673dae5680f5f12981630f037e72c0..b94c1f1079770e8c8d431a78e590c471b443c5c1 100644 (file)
@@ -828,7 +828,7 @@ static void si_emit_cp_dma_clear_buffer(struct radv_cmd_buffer *cmd_buffer,
 static void si_cp_dma_prepare(struct radv_cmd_buffer *cmd_buffer, uint64_t byte_count,
                              uint64_t remaining_size, unsigned *flags)
 {
-
+       cmd_buffer->no_draws = false;
        /* Flush the caches for the first copy only.
         * Also wait for the previous CP DMA operations.
         */