2 * Copyright 2013 Advanced Micro Devices, Inc.
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:
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
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.
26 * This file contains helpers for writing commands to commands streams.
29 #ifndef SI_BUILD_PM4_H
30 #define SI_BUILD_PM4_H
36 #include "ac_shadowed_regs.h"
37 #define SI_CHECK_SHADOWED_REGS(reg_offset, count) ac_check_shadowed_regs(GFX10, CHIP_NAVI14, reg_offset, count)
39 #define SI_CHECK_SHADOWED_REGS(reg_offset, count)
42 static inline void radeon_set_config_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
44 SI_CHECK_SHADOWED_REGS(reg
, num
);
45 assert(reg
< SI_CONTEXT_REG_OFFSET
);
46 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
47 radeon_emit(cs
, PKT3(PKT3_SET_CONFIG_REG
, num
, 0));
48 radeon_emit(cs
, (reg
- SI_CONFIG_REG_OFFSET
) >> 2);
51 static inline void radeon_set_config_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
53 radeon_set_config_reg_seq(cs
, reg
, 1);
54 radeon_emit(cs
, value
);
57 static inline void radeon_set_context_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
59 SI_CHECK_SHADOWED_REGS(reg
, num
);
60 assert(reg
>= SI_CONTEXT_REG_OFFSET
);
61 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
62 radeon_emit(cs
, PKT3(PKT3_SET_CONTEXT_REG
, num
, 0));
63 radeon_emit(cs
, (reg
- SI_CONTEXT_REG_OFFSET
) >> 2);
66 static inline void radeon_set_context_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
68 radeon_set_context_reg_seq(cs
, reg
, 1);
69 radeon_emit(cs
, value
);
72 static inline void radeon_set_context_reg_seq_array(struct radeon_cmdbuf
*cs
, unsigned reg
,
73 unsigned num
, const uint32_t *values
)
75 radeon_set_context_reg_seq(cs
, reg
, num
);
76 radeon_emit_array(cs
, values
, num
);
79 static inline void radeon_set_context_reg_idx(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned idx
,
82 SI_CHECK_SHADOWED_REGS(reg
, 1);
83 assert(reg
>= SI_CONTEXT_REG_OFFSET
);
84 assert(cs
->current
.cdw
+ 3 <= cs
->current
.max_dw
);
85 radeon_emit(cs
, PKT3(PKT3_SET_CONTEXT_REG
, 1, 0));
86 radeon_emit(cs
, (reg
- SI_CONTEXT_REG_OFFSET
) >> 2 | (idx
<< 28));
87 radeon_emit(cs
, value
);
90 static inline void radeon_set_sh_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
92 SI_CHECK_SHADOWED_REGS(reg
, num
);
93 assert(reg
>= SI_SH_REG_OFFSET
&& reg
< SI_SH_REG_END
);
94 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
95 radeon_emit(cs
, PKT3(PKT3_SET_SH_REG
, num
, 0));
96 radeon_emit(cs
, (reg
- SI_SH_REG_OFFSET
) >> 2);
99 static inline void radeon_set_sh_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
101 radeon_set_sh_reg_seq(cs
, reg
, 1);
102 radeon_emit(cs
, value
);
105 static inline void radeon_set_uconfig_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
107 SI_CHECK_SHADOWED_REGS(reg
, num
);
108 assert(reg
>= CIK_UCONFIG_REG_OFFSET
&& reg
< CIK_UCONFIG_REG_END
);
109 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
110 radeon_emit(cs
, PKT3(PKT3_SET_UCONFIG_REG
, num
, 0));
111 radeon_emit(cs
, (reg
- CIK_UCONFIG_REG_OFFSET
) >> 2);
114 static inline void radeon_set_uconfig_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
116 radeon_set_uconfig_reg_seq(cs
, reg
, 1);
117 radeon_emit(cs
, value
);
120 static inline void radeon_set_uconfig_reg_idx(struct radeon_cmdbuf
*cs
, struct si_screen
*screen
,
121 unsigned reg
, unsigned idx
, unsigned value
)
123 SI_CHECK_SHADOWED_REGS(reg
, 1);
124 assert(reg
>= CIK_UCONFIG_REG_OFFSET
&& reg
< CIK_UCONFIG_REG_END
);
125 assert(cs
->current
.cdw
+ 3 <= cs
->current
.max_dw
);
127 unsigned opcode
= PKT3_SET_UCONFIG_REG_INDEX
;
128 if (screen
->info
.chip_class
< GFX9
||
129 (screen
->info
.chip_class
== GFX9
&& screen
->info
.me_fw_version
< 26))
130 opcode
= PKT3_SET_UCONFIG_REG
;
131 radeon_emit(cs
, PKT3(opcode
, 1, 0));
132 radeon_emit(cs
, (reg
- CIK_UCONFIG_REG_OFFSET
) >> 2 | (idx
<< 28));
133 radeon_emit(cs
, value
);
136 static inline void radeon_set_context_reg_rmw(struct radeon_cmdbuf
*cs
, unsigned reg
,
137 unsigned value
, unsigned mask
)
139 SI_CHECK_SHADOWED_REGS(reg
, 1);
140 assert(reg
>= SI_CONTEXT_REG_OFFSET
);
141 assert(cs
->current
.cdw
+ 4 <= cs
->current
.max_dw
);
142 radeon_emit(cs
, PKT3(PKT3_CONTEXT_REG_RMW
, 2, 0));
143 radeon_emit(cs
, (reg
- SI_CONTEXT_REG_OFFSET
) >> 2);
144 radeon_emit(cs
, mask
);
145 radeon_emit(cs
, value
);
148 /* Emit PKT3_CONTEXT_REG_RMW if the register value is different. */
149 static inline void radeon_opt_set_context_reg_rmw(struct si_context
*sctx
, unsigned offset
,
150 enum si_tracked_reg reg
, unsigned value
,
153 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
155 assert((value
& ~mask
) == 0);
158 if (((sctx
->tracked_regs
.reg_saved
>> reg
) & 0x1) != 0x1 ||
159 sctx
->tracked_regs
.reg_value
[reg
] != value
) {
160 radeon_set_context_reg_rmw(cs
, offset
, value
, mask
);
162 sctx
->tracked_regs
.reg_saved
|= 0x1ull
<< reg
;
163 sctx
->tracked_regs
.reg_value
[reg
] = value
;
167 /* Emit PKT3_SET_CONTEXT_REG if the register value is different. */
168 static inline void radeon_opt_set_context_reg(struct si_context
*sctx
, unsigned offset
,
169 enum si_tracked_reg reg
, unsigned value
)
171 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
173 if (((sctx
->tracked_regs
.reg_saved
>> reg
) & 0x1) != 0x1 ||
174 sctx
->tracked_regs
.reg_value
[reg
] != value
) {
175 radeon_set_context_reg(cs
, offset
, value
);
177 sctx
->tracked_regs
.reg_saved
|= 0x1ull
<< reg
;
178 sctx
->tracked_regs
.reg_value
[reg
] = value
;
183 * Set 2 consecutive registers if any registers value is different.
184 * @param offset starting register offset
185 * @param value1 is written to first register
186 * @param value2 is written to second register
188 static inline void radeon_opt_set_context_reg2(struct si_context
*sctx
, unsigned offset
,
189 enum si_tracked_reg reg
, unsigned value1
,
192 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
194 if (((sctx
->tracked_regs
.reg_saved
>> reg
) & 0x3) != 0x3 ||
195 sctx
->tracked_regs
.reg_value
[reg
] != value1
||
196 sctx
->tracked_regs
.reg_value
[reg
+ 1] != value2
) {
197 radeon_set_context_reg_seq(cs
, offset
, 2);
198 radeon_emit(cs
, value1
);
199 radeon_emit(cs
, value2
);
201 sctx
->tracked_regs
.reg_value
[reg
] = value1
;
202 sctx
->tracked_regs
.reg_value
[reg
+ 1] = value2
;
203 sctx
->tracked_regs
.reg_saved
|= 0x3ull
<< reg
;
208 * Set 3 consecutive registers if any registers value is different.
210 static inline void radeon_opt_set_context_reg3(struct si_context
*sctx
, unsigned offset
,
211 enum si_tracked_reg reg
, unsigned value1
,
212 unsigned value2
, unsigned value3
)
214 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
216 if (((sctx
->tracked_regs
.reg_saved
>> reg
) & 0x7) != 0x7 ||
217 sctx
->tracked_regs
.reg_value
[reg
] != value1
||
218 sctx
->tracked_regs
.reg_value
[reg
+ 1] != value2
||
219 sctx
->tracked_regs
.reg_value
[reg
+ 2] != value3
) {
220 radeon_set_context_reg_seq(cs
, offset
, 3);
221 radeon_emit(cs
, value1
);
222 radeon_emit(cs
, value2
);
223 radeon_emit(cs
, value3
);
225 sctx
->tracked_regs
.reg_value
[reg
] = value1
;
226 sctx
->tracked_regs
.reg_value
[reg
+ 1] = value2
;
227 sctx
->tracked_regs
.reg_value
[reg
+ 2] = value3
;
228 sctx
->tracked_regs
.reg_saved
|= 0x7ull
<< reg
;
233 * Set 4 consecutive registers if any registers value is different.
235 static inline void radeon_opt_set_context_reg4(struct si_context
*sctx
, unsigned offset
,
236 enum si_tracked_reg reg
, unsigned value1
,
237 unsigned value2
, unsigned value3
, unsigned value4
)
239 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
241 if (((sctx
->tracked_regs
.reg_saved
>> reg
) & 0xf) != 0xf ||
242 sctx
->tracked_regs
.reg_value
[reg
] != value1
||
243 sctx
->tracked_regs
.reg_value
[reg
+ 1] != value2
||
244 sctx
->tracked_regs
.reg_value
[reg
+ 2] != value3
||
245 sctx
->tracked_regs
.reg_value
[reg
+ 3] != value4
) {
246 radeon_set_context_reg_seq(cs
, offset
, 4);
247 radeon_emit(cs
, value1
);
248 radeon_emit(cs
, value2
);
249 radeon_emit(cs
, value3
);
250 radeon_emit(cs
, value4
);
252 sctx
->tracked_regs
.reg_value
[reg
] = value1
;
253 sctx
->tracked_regs
.reg_value
[reg
+ 1] = value2
;
254 sctx
->tracked_regs
.reg_value
[reg
+ 2] = value3
;
255 sctx
->tracked_regs
.reg_value
[reg
+ 3] = value4
;
256 sctx
->tracked_regs
.reg_saved
|= 0xfull
<< reg
;
261 * Set consecutive registers if any registers value is different.
263 static inline void radeon_opt_set_context_regn(struct si_context
*sctx
, unsigned offset
,
264 unsigned *value
, unsigned *saved_val
, unsigned num
)
266 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
269 for (i
= 0; i
< num
; i
++) {
270 if (saved_val
[i
] != value
[i
]) {
271 radeon_set_context_reg_seq(cs
, offset
, num
);
272 for (j
= 0; j
< num
; j
++)
273 radeon_emit(cs
, value
[j
]);
275 memcpy(saved_val
, value
, sizeof(uint32_t) * num
);