radv: store the dispatch initiator into the device
[mesa.git] / src / amd / vulkan / radv_cmd_buffer.c
index 3cdcc069385425eba2fd2a0e48eb370a3127e991..eae5d40e1986945146dd02727e502c37d717a809 100644 (file)
@@ -198,12 +198,11 @@ static VkResult radv_create_cmd_buffer(
 {
        struct radv_cmd_buffer *cmd_buffer;
        unsigned ring;
-       cmd_buffer = vk_alloc(&pool->alloc, sizeof(*cmd_buffer), 8,
-                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       cmd_buffer = vk_zalloc(&pool->alloc, sizeof(*cmd_buffer), 8,
+                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
        if (cmd_buffer == NULL)
                return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-       memset(cmd_buffer, 0, sizeof(*cmd_buffer));
        cmd_buffer->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
        cmd_buffer->device = device;
        cmd_buffer->pool = pool;
@@ -231,8 +230,6 @@ static VkResult radv_create_cmd_buffer(
 
        *pCommandBuffer = radv_cmd_buffer_to_handle(cmd_buffer);
 
-       cmd_buffer->upload.offset = 0;
-       cmd_buffer->upload.size = 0;
        list_inithead(&cmd_buffer->upload.list);
 
        return VK_SUCCESS;
@@ -295,6 +292,8 @@ radv_reset_cmd_buffer(struct radv_cmd_buffer *cmd_buffer)
                cmd_buffer->gfx9_fence_bo = cmd_buffer->upload.upload_bo;
        }
 
+       cmd_buffer->status = RADV_CMD_BUFFER_STATUS_INITIAL;
+
        return cmd_buffer->record_result;
 }
 
@@ -405,9 +404,6 @@ void radv_cmd_buffer_trace_emit(struct radv_cmd_buffer *cmd_buffer)
        struct radeon_winsys_cs *cs = cmd_buffer->cs;
        uint64_t va;
 
-       if (!device->trace_bo)
-               return;
-
        va = radv_buffer_get_va(device->trace_bo);
        if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)
                va += 4;
@@ -438,7 +434,8 @@ radv_cmd_buffer_after_draw(struct radv_cmd_buffer *cmd_buffer)
                                       flags);
        }
 
-       radv_cmd_buffer_trace_emit(cmd_buffer);
+       if (unlikely(cmd_buffer->device->trace_bo))
+               radv_cmd_buffer_trace_emit(cmd_buffer);
 }
 
 static void
@@ -450,9 +447,6 @@ radv_save_pipeline(struct radv_cmd_buffer *cmd_buffer,
        uint32_t data[2];
        uint64_t va;
 
-       if (!device->trace_bo)
-               return;
-
        va = radv_buffer_get_va(device->trace_bo);
 
        switch (ring) {
@@ -1087,7 +1081,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);
 
-       radv_save_pipeline(cmd_buffer, pipeline, RING_GFX);
+       if (unlikely(cmd_buffer->device->trace_bo))
+               radv_save_pipeline(cmd_buffer, pipeline, RING_GFX);
 
        cmd_buffer->state.emitted_pipeline = pipeline;
 
@@ -1188,9 +1183,10 @@ radv_emit_depth_biais(struct radv_cmd_buffer *cmd_buffer)
 static void
 radv_emit_fb_color_state(struct radv_cmd_buffer *cmd_buffer,
                         int index,
-                        struct radv_color_buffer_info *cb)
+                        struct radv_attachment_info *att)
 {
        bool is_vi = cmd_buffer->device->physical_device->rad_info.chip_class >= VI;
+       struct radv_color_buffer_info *cb = &att->cb;
 
        if (cmd_buffer->device->physical_device->rad_info.chip_class >= GFX9) {
                radeon_set_context_reg_seq(cmd_buffer->cs, R_028C60_CB_COLOR0_BASE + index * 0x3c, 11);
@@ -1211,7 +1207,7 @@ radv_emit_fb_color_state(struct radv_cmd_buffer *cmd_buffer,
                radeon_emit(cmd_buffer->cs, cb->cb_dcc_base >> 32);
                
                radeon_set_context_reg(cmd_buffer->cs, R_0287A0_CB_MRT0_EPITCH + index * 4,
-                                      cb->gfx9_epitch);
+                                      S_0287A0_EPITCH(att->attachment->image->surface.u.gfx9.surf.epitch));
        } else {
                radeon_set_context_reg_seq(cmd_buffer->cs, R_028C60_CB_COLOR0_BASE + index * 0x3c, 11);
                radeon_emit(cmd_buffer->cs, cb->cb_color_base);
@@ -1304,8 +1300,7 @@ radv_set_depth_clear_regs(struct radv_cmd_buffer *cmd_buffer,
        va += image->offset + image->clear_value_offset;
        unsigned reg_offset = 0, reg_count = 0;
 
-       if (!image->surface.htile_size || !aspects)
-               return;
+       assert(image->surface.htile_size);
 
        if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
                ++reg_count;
@@ -1316,8 +1311,6 @@ radv_set_depth_clear_regs(struct radv_cmd_buffer *cmd_buffer,
        if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
                ++reg_count;
 
-       radv_cs_add_buffer(cmd_buffer->device->ws, cmd_buffer->cs, image->bo, 8);
-
        radeon_emit(cmd_buffer->cs, PKT3(PKT3_WRITE_DATA, 2 + reg_count, 0));
        radeon_emit(cmd_buffer->cs, S_370_DST_SEL(V_370_MEM_ASYNC) |
                                    S_370_WR_CONFIRM(1) |
@@ -1340,20 +1333,30 @@ static void
 radv_load_depth_clear_regs(struct radv_cmd_buffer *cmd_buffer,
                           struct radv_image *image)
 {
+       VkImageAspectFlags aspects = vk_format_aspects(image->vk_format);
        uint64_t va = radv_buffer_get_va(image->bo);
        va += image->offset + image->clear_value_offset;
+       unsigned reg_offset = 0, reg_count = 0;
 
        if (!image->surface.htile_size)
                return;
 
+       if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
+               ++reg_count;
+       } else {
+               ++reg_offset;
+               va += 4;
+       }
+       if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
+               ++reg_count;
 
        radeon_emit(cmd_buffer->cs, PKT3(PKT3_COPY_DATA, 4, 0));
        radeon_emit(cmd_buffer->cs, COPY_DATA_SRC_SEL(COPY_DATA_MEM) |
                                    COPY_DATA_DST_SEL(COPY_DATA_REG) |
-                                   COPY_DATA_COUNT_SEL);
+                                   (reg_count == 2 ? COPY_DATA_COUNT_SEL : 0));
        radeon_emit(cmd_buffer->cs, va);
        radeon_emit(cmd_buffer->cs, va >> 32);
-       radeon_emit(cmd_buffer->cs, R_028028_DB_STENCIL_CLEAR >> 2);
+       radeon_emit(cmd_buffer->cs, (R_028028_DB_STENCIL_CLEAR + 4 * reg_offset) >> 2);
        radeon_emit(cmd_buffer->cs, 0);
 
        radeon_emit(cmd_buffer->cs, PKT3(PKT3_PFP_SYNC_ME, 0, 0));
@@ -1374,10 +1377,7 @@ radv_set_dcc_need_cmask_elim_pred(struct radv_cmd_buffer *cmd_buffer,
        uint64_t va = radv_buffer_get_va(image->bo);
        va += image->offset + image->dcc_pred_offset;
 
-       if (!image->surface.dcc_size)
-               return;
-
-       radv_cs_add_buffer(cmd_buffer->device->ws, cmd_buffer->cs, image->bo, 8);
+       assert(image->surface.dcc_size);
 
        radeon_emit(cmd_buffer->cs, PKT3(PKT3_WRITE_DATA, 4, 0));
        radeon_emit(cmd_buffer->cs, S_370_DST_SEL(V_370_MEM_ASYNC) |
@@ -1398,10 +1398,7 @@ radv_set_color_clear_regs(struct radv_cmd_buffer *cmd_buffer,
        uint64_t va = radv_buffer_get_va(image->bo);
        va += image->offset + image->clear_value_offset;
 
-       if (!image->cmask.size && !image->surface.dcc_size)
-               return;
-
-       radv_cs_add_buffer(cmd_buffer->device->ws, cmd_buffer->cs, image->bo, 8);
+       assert(image->cmask.size || image->surface.dcc_size);
 
        radeon_emit(cmd_buffer->cs, PKT3(PKT3_WRITE_DATA, 4, 0));
        radeon_emit(cmd_buffer->cs, S_370_DST_SEL(V_370_MEM_ASYNC) |
@@ -1467,7 +1464,7 @@ radv_emit_framebuffer_state(struct radv_cmd_buffer *cmd_buffer)
                radv_cs_add_buffer(cmd_buffer->device->ws, cmd_buffer->cs, att->attachment->bo, 8);
 
                assert(att->attachment->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT);
-               radv_emit_fb_color_state(cmd_buffer, i, &att->cb);
+               radv_emit_fb_color_state(cmd_buffer, i, att);
 
                radv_load_color_clear_regs(cmd_buffer, att->attachment->image, i);
        }
@@ -1517,21 +1514,26 @@ static void
 radv_emit_index_buffer(struct radv_cmd_buffer *cmd_buffer)
 {
        struct radeon_winsys_cs *cs = cmd_buffer->cs;
+       struct radv_cmd_state *state = &cmd_buffer->state;
 
-       if (cmd_buffer->device->physical_device->rad_info.chip_class >= GFX9) {
-               radeon_set_uconfig_reg_idx(cs, R_03090C_VGT_INDEX_TYPE,
-                                          2, cmd_buffer->state.index_type);
-       } else {
-               radeon_emit(cs, PKT3(PKT3_INDEX_TYPE, 0, 0));
-               radeon_emit(cs, cmd_buffer->state.index_type);
+       if (state->index_type != state->last_index_type) {
+               if (cmd_buffer->device->physical_device->rad_info.chip_class >= GFX9) {
+                       radeon_set_uconfig_reg_idx(cs, R_03090C_VGT_INDEX_TYPE,
+                                                  2, state->index_type);
+               } else {
+                       radeon_emit(cs, PKT3(PKT3_INDEX_TYPE, 0, 0));
+                       radeon_emit(cs, state->index_type);
+               }
+
+               state->last_index_type = state->index_type;
        }
 
        radeon_emit(cs, PKT3(PKT3_INDEX_BASE, 1, 0));
-       radeon_emit(cs, cmd_buffer->state.index_va);
-       radeon_emit(cs, cmd_buffer->state.index_va >> 32);
+       radeon_emit(cs, state->index_va);
+       radeon_emit(cs, state->index_va >> 32);
 
        radeon_emit(cs, PKT3(PKT3_INDEX_BUFFER_SIZE, 0, 0));
-       radeon_emit(cs, cmd_buffer->state.max_index_count);
+       radeon_emit(cs, state->max_index_count);
 
        cmd_buffer->state.dirty &= ~RADV_CMD_DIRTY_INDEX_BUFFER;
 }
@@ -1734,7 +1736,7 @@ radv_flush_descriptors(struct radv_cmd_buffer *cmd_buffer,
        cmd_buffer->state.descriptors_dirty = 0;
        cmd_buffer->state.push_descriptors_dirty = false;
 
-       if (cmd_buffer->device->trace_bo)
+       if (unlikely(cmd_buffer->device->trace_bo))
                radv_save_descriptors(cmd_buffer);
 
        assert(cmd_buffer->cs->cdw <= cdw_max);
@@ -1783,9 +1785,8 @@ radv_flush_constants(struct radv_cmd_buffer *cmd_buffer,
 static bool
 radv_cmd_buffer_update_vertex_descriptors(struct radv_cmd_buffer *cmd_buffer, bool pipeline_is_dirty)
 {
-       struct radv_device *device = cmd_buffer->device;
-
-       if ((pipeline_is_dirty || cmd_buffer->state.vb_dirty) &&
+       if ((pipeline_is_dirty ||
+           (cmd_buffer->state.dirty & RADV_CMD_DIRTY_VERTEX_BUFFER)) &&
            cmd_buffer->state.pipeline->vertex_elements.count &&
            radv_get_vertex_shader(cmd_buffer->state.pipeline)->info.info.vs.has_vertex_buffers) {
                struct radv_vertex_elements_info *velems = &cmd_buffer->state.pipeline->vertex_elements;
@@ -1807,7 +1808,6 @@ radv_cmd_buffer_update_vertex_descriptors(struct radv_cmd_buffer *cmd_buffer, bo
                        struct radv_buffer *buffer = cmd_buffer->vertex_bindings[vb].buffer;
                        uint32_t stride = cmd_buffer->state.pipeline->binding_stride[vb];
 
-                       radv_cs_add_buffer(device->ws, cmd_buffer->cs, buffer->bo, 8);
                        va = radv_buffer_get_va(buffer->bo);
 
                        offset = cmd_buffer->vertex_bindings[vb].offset + velems->offset[i];
@@ -1831,7 +1831,7 @@ radv_cmd_buffer_update_vertex_descriptors(struct radv_cmd_buffer *cmd_buffer, bo
                cmd_buffer->state.vb_size = count * 16;
                cmd_buffer->state.vb_prefetch_dirty = true;
        }
-       cmd_buffer->state.vb_dirty = false;
+       cmd_buffer->state.dirty &= ~RADV_CMD_DIRTY_VERTEX_BUFFER;
 
        return true;
 }
@@ -2144,9 +2144,6 @@ VkResult radv_AllocateCommandBuffers(
        VkResult result = VK_SUCCESS;
        uint32_t i;
 
-       memset(pCommandBuffers, 0,
-                       sizeof(*pCommandBuffers)*pAllocateInfo->commandBufferCount);
-
        for (i = 0; i < pAllocateInfo->commandBufferCount; i++) {
 
                if (!list_empty(&pool->free_cmd_buffers)) {
@@ -2168,10 +2165,23 @@ VkResult radv_AllocateCommandBuffers(
                        break;
        }
 
-       if (result != VK_SUCCESS)
+       if (result != VK_SUCCESS) {
                radv_FreeCommandBuffers(_device, pAllocateInfo->commandPool,
                                        i, pCommandBuffers);
 
+               /* From the Vulkan 1.0.66 spec:
+                *
+                * "vkAllocateCommandBuffers can be used to create multiple
+                *  command buffers. If the creation of any of those command
+                *  buffers fails, the implementation must destroy all
+                *  successfully created command buffer objects from this
+                *  command, set all entries of the pCommandBuffers array to
+                *  NULL and return the error."
+                */
+               memset(pCommandBuffers, 0,
+                      sizeof(*pCommandBuffers) * pAllocateInfo->commandBufferCount);
+       }
+
        return result;
 }
 
@@ -2222,14 +2232,20 @@ VkResult radv_BeginCommandBuffer(
        const VkCommandBufferBeginInfo *pBeginInfo)
 {
        RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
-       VkResult result;
+       VkResult result = VK_SUCCESS;
 
-       result = radv_reset_cmd_buffer(cmd_buffer);
-       if (result != VK_SUCCESS)
-               return result;
+       if (cmd_buffer->status != RADV_CMD_BUFFER_STATUS_INITIAL) {
+               /* If the command buffer has already been resetted with
+                * vkResetCommandBuffer, no need to do it again.
+                */
+               result = radv_reset_cmd_buffer(cmd_buffer);
+               if (result != VK_SUCCESS)
+                       return result;
+       }
 
        memset(&cmd_buffer->state, 0, sizeof(cmd_buffer->state));
        cmd_buffer->state.last_primitive_reset_en = -1;
+       cmd_buffer->state.last_index_type = -1;
        cmd_buffer->usage_flags = pBeginInfo->flags;
 
        /* setup initial configuration into command buffer */
@@ -2262,7 +2278,11 @@ VkResult radv_BeginCommandBuffer(
                radv_cmd_buffer_set_subpass(cmd_buffer, subpass, false);
        }
 
-       radv_cmd_buffer_trace_emit(cmd_buffer);
+       if (unlikely(cmd_buffer->device->trace_bo))
+               radv_cmd_buffer_trace_emit(cmd_buffer);
+
+       cmd_buffer->status = RADV_CMD_BUFFER_STATUS_RECORDING;
+
        return result;
 }
 
@@ -2292,6 +2312,9 @@ void radv_CmdBindVertexBuffers(
 
                vb[idx].buffer = radv_buffer_from_handle(pBuffers[i]);
                vb[idx].offset = pOffsets[i];
+
+               radv_cs_add_buffer(cmd_buffer->device->ws, cmd_buffer->cs,
+                                  vb[idx].buffer->bo, 8);
        }
 
        if (!changed) {
@@ -2299,7 +2322,7 @@ void radv_CmdBindVertexBuffers(
                return;
        }
 
-       cmd_buffer->state.vb_dirty = true;
+       cmd_buffer->state.dirty |= RADV_CMD_DIRTY_VERTEX_BUFFER;
 }
 
 void radv_CmdBindIndexBuffer(
@@ -2526,7 +2549,9 @@ VkResult radv_EndCommandBuffer(
        vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.attachments);
 
        if (!cmd_buffer->device->ws->cs_finalize(cmd_buffer->cs))
-               return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+               return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
+
+       cmd_buffer->status = RADV_CMD_BUFFER_STATUS_EXECUTABLE;
 
        return cmd_buffer->record_result;
 }
@@ -2576,7 +2601,9 @@ radv_emit_compute_pipeline(struct radv_cmd_buffer *cmd_buffer)
                    S_00B81C_NUM_THREAD_FULL(compute_shader->info.cs.block_size[2]));
 
        assert(cmd_buffer->cs->cdw <= cdw_max);
-       radv_save_pipeline(cmd_buffer, pipeline, RING_COMPUTE);
+
+       if (unlikely(cmd_buffer->device->trace_bo))
+               radv_save_pipeline(cmd_buffer, pipeline, RING_COMPUTE);
 }
 
 static void radv_mark_descriptor_sets_dirty(struct radv_cmd_buffer *cmd_buffer)
@@ -2836,6 +2863,11 @@ void radv_CmdExecuteCommands(
                        primary->state.last_ia_multi_vgt_param =
                                secondary->state.last_ia_multi_vgt_param;
                }
+
+               if (secondary->state.last_index_type != -1) {
+                       primary->state.last_index_type =
+                               secondary->state.last_index_type;
+               }
        }
 
        /* After executing commands from secondary buffers we have to dirty
@@ -3220,8 +3252,10 @@ radv_emit_all_graphics_states(struct radv_cmd_buffer *cmd_buffer,
                 * so the state must be re-emitted before the next indexed
                 * draw.
                 */
-               if (cmd_buffer->device->physical_device->rad_info.chip_class >= CIK)
+               if (cmd_buffer->device->physical_device->rad_info.chip_class >= CIK) {
+                       cmd_buffer->state.last_index_type = -1;
                        cmd_buffer->state.dirty |= RADV_CMD_DIRTY_INDEX_BUFFER;
+               }
        }
 
        radv_cmd_buffer_flush_dynamic_state(cmd_buffer);
@@ -3449,29 +3483,16 @@ radv_emit_dispatch_packets(struct radv_cmd_buffer *cmd_buffer,
 {
        struct radv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
        struct radv_shader_variant *compute_shader = pipeline->shaders[MESA_SHADER_COMPUTE];
+       unsigned dispatch_initiator = cmd_buffer->device->dispatch_initiator;
        struct radeon_winsys *ws = cmd_buffer->device->ws;
        struct radeon_winsys_cs *cs = cmd_buffer->cs;
        struct ac_userdata_info *loc;
-       unsigned dispatch_initiator;
-       uint8_t grid_used;
-
-       grid_used = compute_shader->info.info.cs.grid_components_used;
 
        loc = radv_lookup_user_sgpr(pipeline, MESA_SHADER_COMPUTE,
                                    AC_UD_CS_GRID_SIZE);
 
        MAYBE_UNUSED unsigned cdw_max = radeon_check_space(ws, cs, 25);
 
-       dispatch_initiator = S_00B800_COMPUTE_SHADER_EN(1) |
-                            S_00B800_FORCE_START_AT_000(1);
-
-       if (cmd_buffer->device->physical_device->rad_info.chip_class >= CIK) {
-               /* If the KMD allows it (there is a KMD hw register for it),
-                * allow launching waves out-of-order.
-                */
-               dispatch_initiator |= S_00B800_ORDER_MODE(1);
-       }
-
        if (info->indirect) {
                uint64_t va = radv_buffer_get_va(info->indirect->bo);
 
@@ -3480,7 +3501,7 @@ radv_emit_dispatch_packets(struct radv_cmd_buffer *cmd_buffer,
                radv_cs_add_buffer(ws, cs, info->indirect->bo, 8);
 
                if (loc->sgpr_idx != -1) {
-                       for (unsigned i = 0; i < grid_used; ++i) {
+                       for (unsigned i = 0; i < 3; ++i) {
                                radeon_emit(cs, PKT3(PKT3_COPY_DATA, 4, 0));
                                radeon_emit(cs, COPY_DATA_SRC_SEL(COPY_DATA_MEM) |
                                                COPY_DATA_DST_SEL(COPY_DATA_REG));
@@ -3547,15 +3568,13 @@ radv_emit_dispatch_packets(struct radv_cmd_buffer *cmd_buffer,
 
                if (loc->sgpr_idx != -1) {
                        assert(!loc->indirect);
-                       assert(loc->num_sgprs == grid_used);
+                       assert(loc->num_sgprs == 3);
 
                        radeon_set_sh_reg_seq(cs, R_00B900_COMPUTE_USER_DATA_0 +
-                                                 loc->sgpr_idx * 4, grid_used);
+                                                 loc->sgpr_idx * 4, 3);
                        radeon_emit(cs, blocks[0]);
-                       if (grid_used > 1)
-                               radeon_emit(cs, blocks[1]);
-                       if (grid_used > 2)
-                               radeon_emit(cs, blocks[2]);
+                       radeon_emit(cs, blocks[1]);
+                       radeon_emit(cs, blocks[2]);
                }
 
                radeon_emit(cs, PKT3(PKT3_DISPATCH_DIRECT, 3, 0) |