• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Advanced Micro Devices, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * on the rights to use, copy, modify, merge, publish, distribute, sub
9  * license, and/or sell copies of the Software, and to permit persons to whom
10  * the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include "ac_shadowed_regs.h"
26 #include "radv_cs.h"
27 #include "radv_debug.h"
28 #include "radv_private.h"
29 #include "sid.h"
30 
31 static void
radv_set_context_reg_array(struct radeon_cmdbuf * cs,unsigned reg,unsigned num,const uint32_t * values)32 radv_set_context_reg_array(struct radeon_cmdbuf *cs, unsigned reg, unsigned num, const uint32_t *values)
33 {
34    radeon_set_context_reg_seq(cs, reg, num);
35    radeon_emit_array(cs, values, num);
36 }
37 
38 VkResult
radv_create_shadow_regs_preamble(const struct radv_device * device,struct radv_queue_state * queue_state)39 radv_create_shadow_regs_preamble(const struct radv_device *device, struct radv_queue_state *queue_state)
40 {
41    struct radeon_winsys *ws = device->ws;
42    const struct radeon_info *info = &device->physical_device->rad_info;
43    VkResult result;
44 
45    struct radeon_cmdbuf *cs = ws->cs_create(ws, AMD_IP_GFX, false);
46    if (!cs)
47       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
48 
49    radeon_check_space(ws, cs, 256);
50 
51    /* allocate memory for queue_state->shadowed_regs where register states are saved */
52    result = ws->buffer_create(ws, SI_SHADOWED_REG_BUFFER_SIZE, 4096, RADEON_DOMAIN_VRAM,
53                               RADEON_FLAG_ZERO_VRAM | RADEON_FLAG_NO_INTERPROCESS_SHARING, RADV_BO_PRIORITY_SCRATCH, 0,
54                               &queue_state->shadowed_regs);
55    if (result != VK_SUCCESS)
56       goto fail;
57 
58    /* fill the cs for shadow regs preamble ib that starts the register shadowing */
59    ac_create_shadowing_ib_preamble(info, (pm4_cmd_add_fn)&radeon_emit, cs, queue_state->shadowed_regs->va,
60                                    device->pbb_allowed);
61 
62    while (cs->cdw & 7) {
63       if (info->gfx_ib_pad_with_type2)
64          radeon_emit(cs, PKT2_NOP_PAD);
65       else
66          radeon_emit(cs, PKT3_NOP_PAD);
67    }
68 
69    result = ws->buffer_create(
70       ws, cs->cdw * 4, 4096, ws->cs_domain(ws),
71       RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_READ_ONLY | RADEON_FLAG_GTT_WC,
72       RADV_BO_PRIORITY_CS, 0, &queue_state->shadow_regs_ib);
73    if (result != VK_SUCCESS)
74       goto fail_ib_buffer;
75 
76    /* copy the cs to queue_state->shadow_regs_ib. This will be the first preamble ib
77     * added in radv_update_preamble_cs.
78     */
79    void *map = ws->buffer_map(queue_state->shadow_regs_ib);
80    if (!map) {
81       result = VK_ERROR_MEMORY_MAP_FAILED;
82       goto fail_map;
83    }
84    memcpy(map, cs->buf, cs->cdw * 4);
85    queue_state->shadow_regs_ib_size_dw = cs->cdw;
86 
87    ws->buffer_unmap(queue_state->shadow_regs_ib);
88    ws->cs_destroy(cs);
89    return VK_SUCCESS;
90 fail_map:
91    ws->buffer_destroy(ws, queue_state->shadow_regs_ib);
92    queue_state->shadow_regs_ib = NULL;
93 fail_ib_buffer:
94    ws->buffer_destroy(ws, queue_state->shadowed_regs);
95    queue_state->shadowed_regs = NULL;
96 fail:
97    ws->cs_destroy(cs);
98    return result;
99 }
100 
101 void
radv_destroy_shadow_regs_preamble(struct radv_queue_state * queue_state,struct radeon_winsys * ws)102 radv_destroy_shadow_regs_preamble(struct radv_queue_state *queue_state, struct radeon_winsys *ws)
103 {
104    if (queue_state->shadow_regs_ib)
105       ws->buffer_destroy(ws, queue_state->shadow_regs_ib);
106    if (queue_state->shadowed_regs)
107       ws->buffer_destroy(ws, queue_state->shadowed_regs);
108 }
109 
110 void
radv_emit_shadow_regs_preamble(struct radeon_cmdbuf * cs,const struct radv_device * device,struct radv_queue_state * queue_state)111 radv_emit_shadow_regs_preamble(struct radeon_cmdbuf *cs, const struct radv_device *device,
112                                struct radv_queue_state *queue_state)
113 {
114    struct radeon_winsys *ws = device->ws;
115 
116    ws->cs_execute_ib(cs, queue_state->shadow_regs_ib, 0, queue_state->shadow_regs_ib_size_dw & 0xffff, false);
117 
118    radv_cs_add_buffer(device->ws, cs, queue_state->shadowed_regs);
119    radv_cs_add_buffer(device->ws, cs, queue_state->shadow_regs_ib);
120 }
121 
122 /* radv_init_shadowed_regs_buffer_state() will be called once from radv_queue_init(). This
123  * initializes the shadowed_regs buffer to good state */
124 VkResult
radv_init_shadowed_regs_buffer_state(const struct radv_device * device,struct radv_queue * queue)125 radv_init_shadowed_regs_buffer_state(const struct radv_device *device, struct radv_queue *queue)
126 {
127    const struct radeon_info *info = &device->physical_device->rad_info;
128    struct radeon_winsys *ws = device->ws;
129    struct radeon_cmdbuf *cs;
130    VkResult result;
131 
132    cs = ws->cs_create(ws, AMD_IP_GFX, false);
133    if (!cs)
134       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
135 
136    radeon_check_space(ws, cs, 768);
137 
138    radv_emit_shadow_regs_preamble(cs, device, &queue->state);
139    ac_emulate_clear_state(info, cs, radv_set_context_reg_array);
140 
141    result = ws->cs_finalize(cs);
142    if (result == VK_SUCCESS) {
143       if (!radv_queue_internal_submit(queue, cs))
144          result = VK_ERROR_UNKNOWN;
145    }
146 
147    ws->cs_destroy(cs);
148    return result;
149 }
150