2 * Copyright 2013 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 * Authors: Marek Olšák <maraeo@gmail.com>
27 * This file contains helpers for writing commands to commands streams.
33 #include "r600_pipe_common.h"
34 #include "r600d_common.h"
37 * Return true if there is enough memory in VRAM and GTT for the buffers
40 * \param vram VRAM memory size not added to the buffer list yet
41 * \param gtt GTT memory size not added to the buffer list yet
44 radeon_cs_memory_below_limit(struct r600_common_screen
*screen
,
45 struct radeon_cmdbuf
*cs
,
46 uint64_t vram
, uint64_t gtt
)
48 vram
+= cs
->used_vram
;
51 /* Anything that goes above the VRAM size should go to GTT. */
52 if (vram
> screen
->info
.vram_size
)
53 gtt
+= vram
- screen
->info
.vram_size
;
55 /* Now we just need to check if we have enough GTT. */
56 return gtt
< screen
->info
.gart_size
* 0.7;
60 * Add a buffer to the buffer list for the given command stream (CS).
62 * All buffers used by a CS must be added to the list. This tells the kernel
63 * driver which buffers are used by GPU commands. Other buffers can
64 * be swapped out (not accessible) during execution.
66 * The buffer list becomes empty after every context flush and must be
69 static inline unsigned radeon_add_to_buffer_list(struct r600_common_context
*rctx
,
70 struct r600_ring
*ring
,
71 struct r600_resource
*rbo
,
72 enum radeon_bo_usage usage
,
73 enum radeon_bo_priority priority
)
76 return rctx
->ws
->cs_add_buffer(
78 (enum radeon_bo_usage
)(usage
| RADEON_USAGE_SYNCHRONIZED
),
79 rbo
->domains
, priority
) * 4;
83 * Same as above, but also checks memory usage and flushes the context
86 * When this SHOULD NOT be used:
88 * - if r600_context_add_resource_size has been called for the buffer
89 * followed by *_need_cs_space for checking the memory usage
91 * - if r600_need_dma_space has been called for the buffer
93 * - when emitting state packets and draw packets (because preceding packets
94 * can't be re-emitted at that point)
96 * - if shader resource "enabled_mask" is not up-to-date or there is
97 * a different constraint disallowing a context flush
99 static inline unsigned
100 radeon_add_to_buffer_list_check_mem(struct r600_common_context
*rctx
,
101 struct r600_ring
*ring
,
102 struct r600_resource
*rbo
,
103 enum radeon_bo_usage usage
,
104 enum radeon_bo_priority priority
,
108 !radeon_cs_memory_below_limit(rctx
->screen
, ring
->cs
,
109 rctx
->vram
+ rbo
->vram_usage
,
110 rctx
->gtt
+ rbo
->gart_usage
))
111 ring
->flush(rctx
, PIPE_FLUSH_ASYNC
, NULL
);
113 return radeon_add_to_buffer_list(rctx
, ring
, rbo
, usage
, priority
);
116 static inline void r600_emit_reloc(struct r600_common_context
*rctx
,
117 struct r600_ring
*ring
, struct r600_resource
*rbo
,
118 enum radeon_bo_usage usage
,
119 enum radeon_bo_priority priority
)
121 struct radeon_cmdbuf
*cs
= ring
->cs
;
122 bool has_vm
= ((struct r600_common_screen
*)rctx
->b
.screen
)->info
.r600_has_virtual_memory
;
123 unsigned reloc
= radeon_add_to_buffer_list(rctx
, ring
, rbo
, usage
, priority
);
126 radeon_emit(cs
, PKT3(PKT3_NOP
, 0, 0));
127 radeon_emit(cs
, reloc
);
131 static inline void radeon_set_config_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
133 assert(reg
< R600_CONTEXT_REG_OFFSET
);
134 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
135 radeon_emit(cs
, PKT3(PKT3_SET_CONFIG_REG
, num
, 0));
136 radeon_emit(cs
, (reg
- R600_CONFIG_REG_OFFSET
) >> 2);
139 static inline void radeon_set_config_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
141 radeon_set_config_reg_seq(cs
, reg
, 1);
142 radeon_emit(cs
, value
);
145 static inline void radeon_set_context_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
147 assert(reg
>= R600_CONTEXT_REG_OFFSET
);
148 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
149 radeon_emit(cs
, PKT3(PKT3_SET_CONTEXT_REG
, num
, 0));
150 radeon_emit(cs
, (reg
- R600_CONTEXT_REG_OFFSET
) >> 2);
153 static inline void radeon_set_context_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
155 radeon_set_context_reg_seq(cs
, reg
, 1);
156 radeon_emit(cs
, value
);
159 static inline void radeon_set_context_reg_idx(struct radeon_cmdbuf
*cs
,
160 unsigned reg
, unsigned idx
,
163 assert(reg
>= R600_CONTEXT_REG_OFFSET
);
164 assert(cs
->current
.cdw
+ 3 <= cs
->current
.max_dw
);
165 radeon_emit(cs
, PKT3(PKT3_SET_CONTEXT_REG
, 1, 0));
166 radeon_emit(cs
, (reg
- R600_CONTEXT_REG_OFFSET
) >> 2 | (idx
<< 28));
167 radeon_emit(cs
, value
);
170 static inline void radeon_set_sh_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
172 assert(reg
>= SI_SH_REG_OFFSET
&& reg
< SI_SH_REG_END
);
173 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
174 radeon_emit(cs
, PKT3(PKT3_SET_SH_REG
, num
, 0));
175 radeon_emit(cs
, (reg
- SI_SH_REG_OFFSET
) >> 2);
178 static inline void radeon_set_sh_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
180 radeon_set_sh_reg_seq(cs
, reg
, 1);
181 radeon_emit(cs
, value
);
184 static inline void radeon_set_uconfig_reg_seq(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned num
)
186 assert(reg
>= CIK_UCONFIG_REG_OFFSET
&& reg
< CIK_UCONFIG_REG_END
);
187 assert(cs
->current
.cdw
+ 2 + num
<= cs
->current
.max_dw
);
188 radeon_emit(cs
, PKT3(PKT3_SET_UCONFIG_REG
, num
, 0));
189 radeon_emit(cs
, (reg
- CIK_UCONFIG_REG_OFFSET
) >> 2);
192 static inline void radeon_set_uconfig_reg(struct radeon_cmdbuf
*cs
, unsigned reg
, unsigned value
)
194 radeon_set_uconfig_reg_seq(cs
, reg
, 1);
195 radeon_emit(cs
, value
);
198 static inline void radeon_set_uconfig_reg_idx(struct radeon_cmdbuf
*cs
,
199 unsigned reg
, unsigned idx
,
202 assert(reg
>= CIK_UCONFIG_REG_OFFSET
&& reg
< CIK_UCONFIG_REG_END
);
203 assert(cs
->current
.cdw
+ 3 <= cs
->current
.max_dw
);
204 radeon_emit(cs
, PKT3(PKT3_SET_UCONFIG_REG
, 1, 0));
205 radeon_emit(cs
, (reg
- CIK_UCONFIG_REG_OFFSET
) >> 2 | (idx
<< 28));
206 radeon_emit(cs
, value
);