2 * Mesa 3-D graphics library
4 * Copyright (C) 2012-2013 LunarG, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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 NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Chia-I Wu <olv@lunarg.com>
31 #include "intel_winsys.h"
33 #include "ilo_builder.h"
34 #include "ilo_common.h"
37 struct ilo_shader_cache
;
39 typedef void (*ilo_cp_callback
)(struct ilo_cp
*cp
, void *data
);
42 ilo_cp_callback release_callback
;
50 struct intel_winsys
*winsys
;
51 struct ilo_shader_cache
*shader_cache
;
52 struct intel_context
*render_ctx
;
54 ilo_cp_callback flush_callback
;
55 void *flush_callback_data
;
57 const struct ilo_cp_owner
*owner
;
60 enum intel_ring_type ring
;
61 bool no_implicit_flush
;
62 unsigned one_off_flags
;
64 struct ilo_builder builder
;
65 struct intel_bo
*last_submitted_bo
;
73 ilo_cp_create(const struct ilo_dev_info
*dev
,
74 struct intel_winsys
*winsys
,
75 struct ilo_shader_cache
*shc
);
78 ilo_cp_destroy(struct ilo_cp
*cp
);
81 ilo_cp_flush_internal(struct ilo_cp
*cp
);
84 ilo_cp_flush(struct ilo_cp
*cp
, const char *reason
)
86 if (ilo_debug
& ILO_DEBUG_FLUSH
) {
87 ilo_printf("cp flushed for %s because of %s: ",
88 (cp
->ring
== INTEL_RING_RENDER
) ? "render" : "other", reason
);
89 ilo_builder_batch_print_stats(&cp
->builder
);
92 ilo_cp_flush_internal(cp
);
96 * Return true if the parser buffer is empty.
99 ilo_cp_empty(struct ilo_cp
*cp
)
101 return !ilo_builder_batch_used(&cp
->builder
);
105 * Return the remaining space (in dwords) in the parser buffer.
108 ilo_cp_space(struct ilo_cp
*cp
)
110 const int space
= ilo_builder_batch_space(&cp
->builder
);
111 const int mi_batch_buffer_end_space
= 2;
113 assert(space
>= cp
->owner_reserve
+ mi_batch_buffer_end_space
);
115 return space
- cp
->owner_reserve
- mi_batch_buffer_end_space
;
119 * Internal function called by functions that flush implicitly.
122 ilo_cp_implicit_flush(struct ilo_cp
*cp
)
124 if (cp
->no_implicit_flush
) {
125 assert(!"unexpected command parser flush");
126 ilo_builder_batch_discard(&cp
->builder
);
129 ilo_cp_flush(cp
, "out of space (implicit)");
133 * Set the ring buffer.
136 ilo_cp_set_ring(struct ilo_cp
*cp
, enum intel_ring_type ring
)
138 if (cp
->ring
!= ring
) {
139 ilo_cp_implicit_flush(cp
);
145 * Assert that no function should flush implicitly.
148 ilo_cp_assert_no_implicit_flush(struct ilo_cp
*cp
, bool enable
)
150 cp
->no_implicit_flush
= enable
;
154 * Set one-off flags. They will be cleared after flushing.
157 ilo_cp_set_one_off_flags(struct ilo_cp
*cp
, unsigned flags
)
159 cp
->one_off_flags
|= flags
;
163 * Set flush callback. The callback is invoked after the bo has been
164 * successfully executed, and before the bo is reallocated.
167 ilo_cp_set_flush_callback(struct ilo_cp
*cp
, ilo_cp_callback callback
,
170 cp
->flush_callback
= callback
;
171 cp
->flush_callback_data
= data
;
175 * Set the parser owner. If this is a new owner, the previous owner is
176 * notified and the space it reserved is reclaimed.
178 * \return true if this is a new owner
181 ilo_cp_set_owner(struct ilo_cp
*cp
, const struct ilo_cp_owner
*owner
,
184 const bool new_owner
= (cp
->owner
!= owner
);
186 /* release current owner */
187 if (new_owner
&& cp
->owner
) {
188 const bool no_implicit_flush
= cp
->no_implicit_flush
;
190 /* reclaim the reserved space */
191 cp
->owner_reserve
= 0;
193 /* invoke the release callback */
194 cp
->no_implicit_flush
= true;
195 cp
->owner
->release_callback(cp
, cp
->owner
->release_data
);
196 cp
->no_implicit_flush
= no_implicit_flush
;
201 if (cp
->owner_reserve
!= reserve
) {
202 const int extra
= reserve
- cp
->owner_reserve
;
204 if (ilo_cp_space(cp
) < extra
) {
205 ilo_cp_implicit_flush(cp
);
207 assert(ilo_cp_space(cp
) >= reserve
);
208 cp
->owner_reserve
= reserve
;
211 cp
->owner_reserve
+= extra
;
215 /* set owner last because of the possible flush above */
222 * Begin writing a command.
225 ilo_cp_begin(struct ilo_cp
*cp
, int cmd_size
)
227 if (ilo_cp_space(cp
) < cmd_size
) {
228 ilo_cp_implicit_flush(cp
);
229 assert(ilo_cp_space(cp
) >= cmd_size
);
232 cp
->pos
= ilo_builder_batch_pointer(&cp
->builder
, cmd_size
, &cp
->ptr
);
235 cp
->cmd_end
= cmd_size
;
239 * Begin writing data to a space stolen from the top of the parser buffer.
241 * \param item builder item type
242 * \param data_size in dwords
243 * \param align in dwords
244 * \param bo_offset in bytes to the stolen space
247 ilo_cp_steal(struct ilo_cp
*cp
, enum ilo_builder_item_type item
,
248 int data_size
, int align
, uint32_t *bo_offset
)
253 /* flush if there is not enough space after stealing */
254 if (ilo_cp_space(cp
) < data_size
+ align
- 1) {
255 ilo_cp_implicit_flush(cp
);
256 assert(ilo_cp_space(cp
) >= data_size
+ align
- 1);
259 cp
->pos
= ilo_builder_state_pointer(&cp
->builder
,
260 item
, align
<< 2, data_size
, &cp
->ptr
) >> 2;
263 cp
->cmd_end
= data_size
;
265 /* offset in cp->bo */
267 *bo_offset
= cp
->pos
<< 2;
271 * Write a dword to the parser buffer. This function must be enclosed by
272 * ilo_cp_begin()/ilo_cp_steal() and ilo_cp_end().
275 ilo_cp_write(struct ilo_cp
*cp
, uint32_t val
)
277 assert(cp
->cmd_cur
< cp
->cmd_end
);
278 cp
->ptr
[cp
->cmd_cur
++] = val
;
282 * Write multiple dwords to the parser buffer.
285 ilo_cp_write_multi(struct ilo_cp
*cp
, const void *vals
, int num_vals
)
287 assert(cp
->cmd_cur
+ num_vals
<= cp
->cmd_end
);
288 memcpy(cp
->ptr
+ cp
->cmd_cur
, vals
, num_vals
* 4);
289 cp
->cmd_cur
+= num_vals
;
293 * Write a bo to the parser buffer. In addition to writing the offset of the
294 * bo to the buffer, it also emits a relocation.
297 ilo_cp_write_bo(struct ilo_cp
*cp
, uint32_t val
,
298 struct intel_bo
*bo
, uint32_t flags
)
301 ilo_builder_batch_reloc(&cp
->builder
, cp
->pos
+ cp
->cmd_cur
,
311 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
312 * matching ilo_cp_end().
315 ilo_cp_end(struct ilo_cp
*cp
)
317 assert(cp
->cmd_cur
== cp
->cmd_end
);
321 * A variant of ilo_cp_steal() where the data are written via the returned
324 * \return ptr pointer where the data are written to. It is valid until any
325 * change is made to the parser.
328 ilo_cp_steal_ptr(struct ilo_cp
*cp
, enum ilo_builder_item_type item
,
329 int data_size
, int align
, uint32_t *bo_offset
)
333 ilo_cp_steal(cp
, item
, data_size
, align
, bo_offset
);
335 ptr
= &cp
->ptr
[cp
->cmd_cur
];
336 cp
->cmd_cur
= cp
->cmd_end
;
343 #endif /* ILO_CP_H */