1 /*
2 * Copyright 2020 Advanced Micro Devices, Inc.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "si_build_pm4.h"
8 #include "ac_debug.h"
9 #include "ac_shadowed_regs.h"
10 #include "util/u_memory.h"
11
si_set_context_reg_array(struct radeon_cmdbuf * cs,unsigned reg,unsigned num,const uint32_t * values)12 static void si_set_context_reg_array(struct radeon_cmdbuf *cs, unsigned reg, unsigned num,
13 const uint32_t *values)
14 {
15 radeon_begin(cs);
16 radeon_set_context_reg_seq(reg, num);
17 radeon_emit_array(values, num);
18 radeon_end();
19 }
20
si_init_cp_reg_shadowing(struct si_context * sctx)21 void si_init_cp_reg_shadowing(struct si_context *sctx)
22 {
23 if (sctx->has_graphics &&
24 sctx->screen->info.register_shadowing_required) {
25 if (sctx->screen->info.has_fw_based_shadowing) {
26 sctx->shadowing.registers =
27 si_aligned_buffer_create(sctx->b.screen,
28 PIPE_RESOURCE_FLAG_UNMAPPABLE | SI_RESOURCE_FLAG_DRIVER_INTERNAL,
29 PIPE_USAGE_DEFAULT,
30 sctx->screen->info.fw_based_mcbp.shadow_size,
31 sctx->screen->info.fw_based_mcbp.shadow_alignment);
32 sctx->shadowing.csa =
33 si_aligned_buffer_create(sctx->b.screen,
34 PIPE_RESOURCE_FLAG_UNMAPPABLE | SI_RESOURCE_FLAG_DRIVER_INTERNAL,
35 PIPE_USAGE_DEFAULT,
36 sctx->screen->info.fw_based_mcbp.csa_size,
37 sctx->screen->info.fw_based_mcbp.csa_alignment);
38 if (!sctx->shadowing.registers || !sctx->shadowing.csa)
39 fprintf(stderr, "radeonsi: cannot create register shadowing buffer(s)\n");
40 else
41 sctx->ws->cs_set_mcbp_reg_shadowing_va(&sctx->gfx_cs,
42 sctx->shadowing.registers->gpu_address,
43 sctx->shadowing.csa->gpu_address);
44 } else {
45 sctx->shadowing.registers =
46 si_aligned_buffer_create(sctx->b.screen,
47 PIPE_RESOURCE_FLAG_UNMAPPABLE | SI_RESOURCE_FLAG_DRIVER_INTERNAL,
48 PIPE_USAGE_DEFAULT,
49 SI_SHADOWED_REG_BUFFER_SIZE,
50 4096);
51 if (!sctx->shadowing.registers)
52 fprintf(stderr, "radeonsi: cannot create a shadowed_regs buffer\n");
53 }
54 }
55
56 si_init_gfx_preamble_state(sctx);
57
58 if (sctx->shadowing.registers) {
59 /* We need to clear the shadowed reg buffer. */
60 si_cp_dma_clear_buffer(sctx, &sctx->gfx_cs, &sctx->shadowing.registers->b.b,
61 0, sctx->shadowing.registers->bo_size, 0);
62 si_barrier_after_simple_buffer_op(sctx, 0, &sctx->shadowing.registers->b.b, NULL);
63
64 /* Create the shadowing preamble. (allocate enough dwords because the preamble is large) */
65 struct si_pm4_state *shadowing_preamble = si_pm4_create_sized(sctx->screen, 256, false);
66
67 ac_create_shadowing_ib_preamble(&sctx->screen->info,
68 (pm4_cmd_add_fn)ac_pm4_cmd_add, &shadowing_preamble->base,
69 sctx->shadowing.registers->gpu_address, sctx->screen->dpbb_allowed);
70
71 /* Initialize shadowed registers as follows. */
72 radeon_add_to_buffer_list(sctx, &sctx->gfx_cs, sctx->shadowing.registers,
73 RADEON_USAGE_READWRITE | RADEON_PRIO_DESCRIPTORS);
74 if (sctx->shadowing.csa)
75 radeon_add_to_buffer_list(sctx, &sctx->gfx_cs, sctx->shadowing.csa,
76 RADEON_USAGE_READWRITE | RADEON_PRIO_DESCRIPTORS);
77 si_pm4_emit_commands(sctx, shadowing_preamble);
78
79 if (sctx->gfx_level < GFX12)
80 ac_emulate_clear_state(&sctx->screen->info, &sctx->gfx_cs, si_set_context_reg_array);
81
82 /* TODO: Gfx11 fails GLCTS if we don't re-emit the preamble at the beginning of every IB. */
83 /* TODO: Skipping this may have made register shadowing slower on Gfx11. */
84 if (sctx->gfx_level < GFX11) {
85 si_pm4_emit_commands(sctx, sctx->cs_preamble_state);
86
87 /* The register values are shadowed, so we won't need to set them again. */
88 si_pm4_free_state(sctx, sctx->cs_preamble_state, ~0);
89 sctx->cs_preamble_state = NULL;
90 }
91
92 if (sctx->gfx_level < GFX12)
93 si_set_tracked_regs_to_clear_state(sctx);
94
95 /* Setup preemption. The shadowing preamble will be executed as a preamble IB,
96 * which will load register values from memory on a context switch.
97 */
98 sctx->ws->cs_setup_preemption(&sctx->gfx_cs, shadowing_preamble->base.pm4,
99 shadowing_preamble->base.ndw);
100 si_pm4_free_state(sctx, shadowing_preamble, ~0);
101 }
102 }
103