xref: /aosp_15_r20/external/mesa3d/src/amd/vulkan/radv_cp_reg_shadowing.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2023 Advanced Micro Devices, Inc.
3  * All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "radv_cp_reg_shadowing.h"
9 #include "ac_shadowed_regs.h"
10 #include "radv_buffer.h"
11 #include "radv_cs.h"
12 #include "radv_debug.h"
13 #include "sid.h"
14 
15 static void
radv_set_context_reg_array(struct radeon_cmdbuf * cs,unsigned reg,unsigned num,const uint32_t * values)16 radv_set_context_reg_array(struct radeon_cmdbuf *cs, unsigned reg, unsigned num, const uint32_t *values)
17 {
18    radeon_set_context_reg_seq(cs, reg, num);
19    radeon_emit_array(cs, values, num);
20 }
21 
22 VkResult
radv_create_shadow_regs_preamble(struct radv_device * device,struct radv_queue_state * queue_state)23 radv_create_shadow_regs_preamble(struct radv_device *device, struct radv_queue_state *queue_state)
24 {
25    const struct radv_physical_device *pdev = radv_device_physical(device);
26    struct radeon_winsys *ws = device->ws;
27    const struct radeon_info *gpu_info = &pdev->info;
28    VkResult result;
29 
30    struct radeon_cmdbuf *cs = ws->cs_create(ws, AMD_IP_GFX, false);
31    if (!cs)
32       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
33 
34    radeon_check_space(ws, cs, 256);
35 
36    /* allocate memory for queue_state->shadowed_regs where register states are saved */
37    result = radv_bo_create(device, NULL, SI_SHADOWED_REG_BUFFER_SIZE, 4096, RADEON_DOMAIN_VRAM,
38                            RADEON_FLAG_ZERO_VRAM | RADEON_FLAG_NO_INTERPROCESS_SHARING, RADV_BO_PRIORITY_SCRATCH, 0,
39                            true, &queue_state->shadowed_regs);
40    if (result != VK_SUCCESS)
41       goto fail;
42 
43    /* fill the cs for shadow regs preamble ib that starts the register shadowing */
44    ac_create_shadowing_ib_preamble(gpu_info, (pm4_cmd_add_fn)&radeon_emit, cs, queue_state->shadowed_regs->va,
45                                    device->pbb_allowed);
46 
47    ws->cs_pad(cs, 0);
48 
49    result = radv_bo_create(
50       device, NULL, cs->cdw * 4, 4096, ws->cs_domain(ws),
51       RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_READ_ONLY | RADEON_FLAG_GTT_WC,
52       RADV_BO_PRIORITY_CS, 0, true, &queue_state->shadow_regs_ib);
53    if (result != VK_SUCCESS)
54       goto fail_ib_buffer;
55 
56    /* copy the cs to queue_state->shadow_regs_ib. This will be the first preamble ib
57     * added in radv_update_preamble_cs.
58     */
59    void *map = radv_buffer_map(ws, queue_state->shadow_regs_ib);
60    if (!map) {
61       result = VK_ERROR_MEMORY_MAP_FAILED;
62       goto fail_map;
63    }
64    memcpy(map, cs->buf, cs->cdw * 4);
65    queue_state->shadow_regs_ib_size_dw = cs->cdw;
66 
67    ws->buffer_unmap(ws, queue_state->shadow_regs_ib, false);
68    ws->cs_destroy(cs);
69    return VK_SUCCESS;
70 fail_map:
71    radv_bo_destroy(device, NULL, queue_state->shadow_regs_ib);
72    queue_state->shadow_regs_ib = NULL;
73 fail_ib_buffer:
74    radv_bo_destroy(device, NULL, queue_state->shadowed_regs);
75    queue_state->shadowed_regs = NULL;
76 fail:
77    ws->cs_destroy(cs);
78    return result;
79 }
80 
81 void
radv_destroy_shadow_regs_preamble(struct radv_device * device,struct radv_queue_state * queue_state,struct radeon_winsys * ws)82 radv_destroy_shadow_regs_preamble(struct radv_device *device, struct radv_queue_state *queue_state,
83                                   struct radeon_winsys *ws)
84 {
85    if (queue_state->shadow_regs_ib)
86       radv_bo_destroy(device, NULL, queue_state->shadow_regs_ib);
87    if (queue_state->shadowed_regs)
88       radv_bo_destroy(device, NULL, queue_state->shadowed_regs);
89 }
90 
91 void
radv_emit_shadow_regs_preamble(struct radeon_cmdbuf * cs,const struct radv_device * device,struct radv_queue_state * queue_state)92 radv_emit_shadow_regs_preamble(struct radeon_cmdbuf *cs, const struct radv_device *device,
93                                struct radv_queue_state *queue_state)
94 {
95    struct radeon_winsys *ws = device->ws;
96 
97    ws->cs_execute_ib(cs, queue_state->shadow_regs_ib, 0, queue_state->shadow_regs_ib_size_dw & 0xffff, false);
98 
99    radv_cs_add_buffer(device->ws, cs, queue_state->shadowed_regs);
100    radv_cs_add_buffer(device->ws, cs, queue_state->shadow_regs_ib);
101 }
102 
103 /* radv_init_shadowed_regs_buffer_state() will be called once from radv_queue_init(). This
104  * initializes the shadowed_regs buffer to good state */
105 VkResult
radv_init_shadowed_regs_buffer_state(const struct radv_device * device,struct radv_queue * queue)106 radv_init_shadowed_regs_buffer_state(const struct radv_device *device, struct radv_queue *queue)
107 {
108    const struct radv_physical_device *pdev = radv_device_physical(device);
109    const struct radeon_info *gpu_info = &pdev->info;
110    struct radeon_winsys *ws = device->ws;
111    struct radeon_cmdbuf *cs;
112    VkResult result;
113 
114    cs = ws->cs_create(ws, AMD_IP_GFX, false);
115    if (!cs)
116       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
117 
118    radeon_check_space(ws, cs, 768);
119 
120    radv_emit_shadow_regs_preamble(cs, device, &queue->state);
121 
122    if (pdev->info.gfx_level < GFX12)
123       ac_emulate_clear_state(gpu_info, cs, radv_set_context_reg_array);
124 
125    result = ws->cs_finalize(cs);
126    if (result == VK_SUCCESS) {
127       if (!radv_queue_internal_submit(queue, cs))
128          result = VK_ERROR_UNKNOWN;
129    }
130 
131    ws->cs_destroy(cs);
132    return result;
133 }
134