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
35 static inline void radeon_set_config_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
37 assert(reg
< SI_CONTEXT_REG_OFFSET
);
38 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
39 radeon_emit(cs
, PKT3(PKT3_SET_CONFIG_REG
, num
, 0));
40 radeon_emit(cs
, (reg
- SI_CONFIG_REG_OFFSET
) >> 2);
43 static inline void radeon_set_config_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
45 radeon_set_config_reg_seq(cs
, reg
, 1);
46 radeon_emit(cs
, value
);
49 static inline void radeon_set_context_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
51 assert(reg
>= SI_CONTEXT_REG_OFFSET
);
52 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
53 radeon_emit(cs
, PKT3(PKT3_SET_CONTEXT_REG
, num
, 0));
54 radeon_emit(cs
, (reg
- SI_CONTEXT_REG_OFFSET
) >> 2);
57 static inline void radeon_set_context_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
59 radeon_set_context_reg_seq(cs
, reg
, 1);
60 radeon_emit(cs
, value
);
63 static inline void radeon_set_context_reg_idx(struct radeon_cmdbuf
*cs
,
64 unsigned reg
, unsigned idx
,
67 assert(reg
>= SI_CONTEXT_REG_OFFSET
);
68 assert(cs
->current
.cdw
+ 3 <= cs
->current
.max_dw
);
69 radeon_emit(cs
, PKT3(PKT3_SET_CONTEXT_REG
, 1, 0));
70 radeon_emit(cs
, (reg
- SI_CONTEXT_REG_OFFSET
) >> 2 | (idx
<< 28));
71 radeon_emit(cs
, value
);
74 static inline void radeon_set_sh_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
76 assert(reg
>= SI_SH_REG_OFFSET
&& reg
< SI_SH_REG_END
);
77 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
78 radeon_emit(cs
, PKT3(PKT3_SET_SH_REG
, num
, 0));
79 radeon_emit(cs
, (reg
- SI_SH_REG_OFFSET
) >> 2);
82 static inline void radeon_set_sh_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
84 radeon_set_sh_reg_seq(cs
, reg
, 1);
85 radeon_emit(cs
, value
);
88 static inline void radeon_set_uconfig_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
90 assert(reg
>= CIK_UCONFIG_REG_OFFSET
&& reg
< CIK_UCONFIG_REG_END
);
91 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
92 radeon_emit(cs
, PKT3(PKT3_SET_UCONFIG_REG
, num
, 0));
93 radeon_emit(cs
, (reg
- CIK_UCONFIG_REG_OFFSET
) >> 2);
96 static inline void radeon_set_uconfig_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
98 radeon_set_uconfig_reg_seq(cs
, reg
, 1);
99 radeon_emit(cs
, value
);
102 static inline void radeon_set_uconfig_reg_idx(struct radeon_cmdbuf
*cs
,
103 unsigned reg
, unsigned idx
,
106 assert(reg
>= CIK_UCONFIG_REG_OFFSET
&& reg
< CIK_UCONFIG_REG_END
);
107 assert(cs
->current
.cdw
+ 3 <= cs
->current
.max_dw
);
108 radeon_emit(cs
, PKT3(PKT3_SET_UCONFIG_REG
, 1, 0));
109 radeon_emit(cs
, (reg
- CIK_UCONFIG_REG_OFFSET
) >> 2 | (idx
<< 28));
110 radeon_emit(cs
, value
);
113 /* Emit PKT3_SET_CONTEXT_REG if the register value is different. */
114 static inline void radeon_opt_set_context_reg(struct si_context
*sctx
, unsigned offset
,
115 enum si_tracked_reg reg
, unsigned value
)
117 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
119 if (!(sctx
->tracked_regs
.reg_saved
& (1 << reg
)) ||
120 sctx
->tracked_regs
.reg_value
[reg
] != value
) {
122 radeon_set_context_reg(cs
, offset
, value
);
124 sctx
->tracked_regs
.reg_saved
|= 1 << reg
;
125 sctx
->tracked_regs
.reg_value
[reg
] = value
;
130 * Set 2 consecutive registers if any registers value is different.
131 * @param offset starting register offset
132 * @param value1 is written to first register
133 * @param value2 is written to second register
135 static inline void radeon_opt_set_context_reg2(struct si_context
*sctx
, unsigned offset
,
136 enum si_tracked_reg reg
, unsigned value1
,
139 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
141 if (!(sctx
->tracked_regs
.reg_saved
& (1 << reg
)) ||
142 !(sctx
->tracked_regs
.reg_saved
& (1 << (reg
+ 1))) ||
143 sctx
->tracked_regs
.reg_value
[reg
] != value1
||
144 sctx
->tracked_regs
.reg_value
[reg
+1] != value2
) {
146 radeon_set_context_reg_seq(cs
, offset
, 2);
147 radeon_emit(cs
, value1
);
148 radeon_emit(cs
, value2
);
150 sctx
->tracked_regs
.reg_value
[reg
] = value1
;
151 sctx
->tracked_regs
.reg_value
[reg
+1] = value2
;
152 sctx
->tracked_regs
.reg_saved
|= 3 << reg
;
157 * Set 3 consecutive registers if any registers value is different.
159 static inline void radeon_opt_set_context_reg3(struct si_context
*sctx
, unsigned offset
,
160 enum si_tracked_reg reg
, unsigned value1
,
161 unsigned value2
, unsigned value3
)
163 struct radeon_cmdbuf
*cs
= sctx
->gfx_cs
;
165 if (!(sctx
->tracked_regs
.reg_saved
& (1 << reg
)) ||
166 !(sctx
->tracked_regs
.reg_saved
& (1 << (reg
+ 1))) ||
167 !(sctx
->tracked_regs
.reg_saved
& (1 << (reg
+ 2))) ||
168 sctx
->tracked_regs
.reg_value
[reg
] != value1
||
169 sctx
->tracked_regs
.reg_value
[reg
+1] != value2
||
170 sctx
->tracked_regs
.reg_value
[reg
+2] != value3
) {
172 radeon_set_context_reg_seq(cs
, offset
, 3);
173 radeon_emit(cs
, value1
);
174 radeon_emit(cs
, value2
);
175 radeon_emit(cs
, value3
);
177 sctx
->tracked_regs
.reg_value
[reg
] = value1
;
178 sctx
->tracked_regs
.reg_value
[reg
+1] = value2
;
179 sctx
->tracked_regs
.reg_value
[reg
+2] = value3
;
180 sctx
->tracked_regs
.reg_saved
|= 7 << reg
;