1 /*
2 * Copyright 2013 Advanced Micro Devices, Inc.
3 * Authors: Marek Olšák <[email protected]>
4 * SPDX-License-Identifier: MIT
5 */
6
7 /**
8 * This file contains helpers for writing commands to commands streams.
9 */
10
11 #ifndef R600_CS_H
12 #define R600_CS_H
13
14 #include "r600_pipe_common.h"
15 #include "r600d_common.h"
16
17 /**
18 * Return true if there is enough memory in VRAM and GTT for the buffers
19 * added so far.
20 *
21 * \param vram VRAM memory size not added to the buffer list yet
22 * \param gtt GTT memory size not added to the buffer list yet
23 */
24 static inline bool
radeon_cs_memory_below_limit(struct r600_common_screen * screen,struct radeon_cmdbuf * cs,uint64_t vram,uint64_t gtt)25 radeon_cs_memory_below_limit(struct r600_common_screen *screen,
26 struct radeon_cmdbuf *cs,
27 uint64_t vram, uint64_t gtt)
28 {
29 vram += (uint64_t)cs->used_vram_kb * 1024;
30 gtt += (uint64_t)cs->used_gart_kb * 1024;
31
32 /* Anything that goes above the VRAM size should go to GTT. */
33 if (vram > (uint64_t)screen->info.vram_size_kb * 1024)
34 gtt += vram - (uint64_t)screen->info.vram_size_kb * 1024;
35
36 /* Now we just need to check if we have enough GTT. */
37 return gtt < (uint64_t)screen->info.gart_size_kb * 1024 * 0.7;
38 }
39
40 /**
41 * Add a buffer to the buffer list for the given command stream (CS).
42 *
43 * All buffers used by a CS must be added to the list. This tells the kernel
44 * driver which buffers are used by GPU commands. Other buffers can
45 * be swapped out (not accessible) during execution.
46 *
47 * The buffer list becomes empty after every context flush and must be
48 * rebuilt.
49 */
radeon_add_to_buffer_list(struct r600_common_context * rctx,struct r600_ring * ring,struct r600_resource * rbo,unsigned usage)50 static inline unsigned radeon_add_to_buffer_list(struct r600_common_context *rctx,
51 struct r600_ring *ring,
52 struct r600_resource *rbo,
53 unsigned usage)
54 {
55 assert(usage);
56 return rctx->ws->cs_add_buffer(
57 &ring->cs, rbo->buf,
58 usage | RADEON_USAGE_SYNCHRONIZED,
59 rbo->domains) * 4;
60 }
61
62 /**
63 * Same as above, but also checks memory usage and flushes the context
64 * accordingly.
65 *
66 * When this SHOULD NOT be used:
67 *
68 * - if r600_context_add_resource_size has been called for the buffer
69 * followed by *_need_cs_space for checking the memory usage
70 *
71 * - if r600_need_dma_space has been called for the buffer
72 *
73 * - when emitting state packets and draw packets (because preceding packets
74 * can't be re-emitted at that point)
75 *
76 * - if shader resource "enabled_mask" is not up-to-date or there is
77 * a different constraint disallowing a context flush
78 */
79 static inline unsigned
radeon_add_to_buffer_list_check_mem(struct r600_common_context * rctx,struct r600_ring * ring,struct r600_resource * rbo,unsigned usage,bool check_mem)80 radeon_add_to_buffer_list_check_mem(struct r600_common_context *rctx,
81 struct r600_ring *ring,
82 struct r600_resource *rbo,
83 unsigned usage,
84 bool check_mem)
85 {
86 if (check_mem &&
87 !radeon_cs_memory_below_limit(rctx->screen, &ring->cs,
88 rctx->vram + rbo->vram_usage,
89 rctx->gtt + rbo->gart_usage))
90 ring->flush(rctx, PIPE_FLUSH_ASYNC, NULL);
91
92 return radeon_add_to_buffer_list(rctx, ring, rbo, usage);
93 }
94
r600_emit_reloc(struct r600_common_context * rctx,struct r600_ring * ring,struct r600_resource * rbo,unsigned usage)95 static inline void r600_emit_reloc(struct r600_common_context *rctx,
96 struct r600_ring *ring, struct r600_resource *rbo,
97 unsigned usage)
98 {
99 struct radeon_cmdbuf *cs = &ring->cs;
100 bool has_vm = ((struct r600_common_screen*)rctx->b.screen)->info.r600_has_virtual_memory;
101 unsigned reloc = radeon_add_to_buffer_list(rctx, ring, rbo, usage);
102
103 if (!has_vm) {
104 radeon_emit(cs, PKT3(PKT3_NOP, 0, 0));
105 radeon_emit(cs, reloc);
106 }
107 }
108
radeon_set_config_reg_seq(struct radeon_cmdbuf * cs,unsigned reg,unsigned num)109 static inline void radeon_set_config_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num)
110 {
111 assert(reg < R600_CONTEXT_REG_OFFSET);
112 assert(cs->current.cdw + 2 + num <= cs->current.max_dw);
113 radeon_emit(cs, PKT3(PKT3_SET_CONFIG_REG, num, 0));
114 radeon_emit(cs, (reg - R600_CONFIG_REG_OFFSET) >> 2);
115 }
116
radeon_set_config_reg(struct radeon_cmdbuf * cs,unsigned reg,unsigned value)117 static inline void radeon_set_config_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value)
118 {
119 radeon_set_config_reg_seq(cs, reg, 1);
120 radeon_emit(cs, value);
121 }
122
radeon_set_context_reg_seq(struct radeon_cmdbuf * cs,unsigned reg,unsigned num)123 static inline void radeon_set_context_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num)
124 {
125 assert(reg >= R600_CONTEXT_REG_OFFSET);
126 assert(cs->current.cdw + 2 + num <= cs->current.max_dw);
127 radeon_emit(cs, PKT3(PKT3_SET_CONTEXT_REG, num, 0));
128 radeon_emit(cs, (reg - R600_CONTEXT_REG_OFFSET) >> 2);
129 }
130
radeon_set_context_reg(struct radeon_cmdbuf * cs,unsigned reg,unsigned value)131 static inline void radeon_set_context_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value)
132 {
133 radeon_set_context_reg_seq(cs, reg, 1);
134 radeon_emit(cs, value);
135 }
136
radeon_set_context_reg_idx(struct radeon_cmdbuf * cs,unsigned reg,unsigned idx,unsigned value)137 static inline void radeon_set_context_reg_idx(struct radeon_cmdbuf *cs,
138 unsigned reg, unsigned idx,
139 unsigned value)
140 {
141 assert(reg >= R600_CONTEXT_REG_OFFSET);
142 assert(cs->current.cdw + 3 <= cs->current.max_dw);
143 radeon_emit(cs, PKT3(PKT3_SET_CONTEXT_REG, 1, 0));
144 radeon_emit(cs, (reg - R600_CONTEXT_REG_OFFSET) >> 2 | (idx << 28));
145 radeon_emit(cs, value);
146 }
147
radeon_set_sh_reg_seq(struct radeon_cmdbuf * cs,unsigned reg,unsigned num)148 static inline void radeon_set_sh_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num)
149 {
150 assert(reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END);
151 assert(cs->current.cdw + 2 + num <= cs->current.max_dw);
152 radeon_emit(cs, PKT3(PKT3_SET_SH_REG, num, 0));
153 radeon_emit(cs, (reg - SI_SH_REG_OFFSET) >> 2);
154 }
155
radeon_set_sh_reg(struct radeon_cmdbuf * cs,unsigned reg,unsigned value)156 static inline void radeon_set_sh_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value)
157 {
158 radeon_set_sh_reg_seq(cs, reg, 1);
159 radeon_emit(cs, value);
160 }
161
radeon_set_uconfig_reg_seq(struct radeon_cmdbuf * cs,unsigned reg,unsigned num)162 static inline void radeon_set_uconfig_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num)
163 {
164 assert(reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END);
165 assert(cs->current.cdw + 2 + num <= cs->current.max_dw);
166 radeon_emit(cs, PKT3(PKT3_SET_UCONFIG_REG, num, 0));
167 radeon_emit(cs, (reg - CIK_UCONFIG_REG_OFFSET) >> 2);
168 }
169
radeon_set_uconfig_reg(struct radeon_cmdbuf * cs,unsigned reg,unsigned value)170 static inline void radeon_set_uconfig_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value)
171 {
172 radeon_set_uconfig_reg_seq(cs, reg, 1);
173 radeon_emit(cs, value);
174 }
175
radeon_set_uconfig_reg_idx(struct radeon_cmdbuf * cs,unsigned reg,unsigned idx,unsigned value)176 static inline void radeon_set_uconfig_reg_idx(struct radeon_cmdbuf *cs,
177 unsigned reg, unsigned idx,
178 unsigned value)
179 {
180 assert(reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END);
181 assert(cs->current.cdw + 3 <= cs->current.max_dw);
182 radeon_emit(cs, PKT3(PKT3_SET_UCONFIG_REG, 1, 0));
183 radeon_emit(cs, (reg - CIK_UCONFIG_REG_OFFSET) >> 2 | (idx << 28));
184 radeon_emit(cs, value);
185 }
186
187 #endif
188