gallium/radeon: Only print a message for LLVM diagnostic errors
[mesa.git] / src / gallium / drivers / ilo / ilo_cp.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 LunarG, Inc.
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "genhw/genhw.h"
29 #include "intel_winsys.h"
30
31 #include "ilo_cp.h"
32
33 #define MI_NOOP GEN_MI_CMD(MI_NOOP)
34 #define MI_BATCH_BUFFER_END GEN_MI_CMD(MI_BATCH_BUFFER_END)
35
36 /* the size of the private space */
37 static const int ilo_cp_private = 2;
38
39 /**
40 * Dump the contents of the parser bo. This can only be called in the flush
41 * callback.
42 */
43 void
44 ilo_cp_dump(struct ilo_cp *cp)
45 {
46 ilo_printf("dumping %d bytes\n", cp->used * 4);
47 if (cp->used)
48 intel_winsys_decode_bo(cp->winsys, cp->bo, cp->used * 4);
49 }
50
51 /**
52 * Save the command parser state for rewind.
53 *
54 * Note that this cannot rewind a flush, and the caller must make sure
55 * that does not happend.
56 */
57 void
58 ilo_cp_setjmp(struct ilo_cp *cp, struct ilo_cp_jmp_buf *jmp)
59 {
60 jmp->id = pointer_to_intptr(cp->bo);
61
62 jmp->size = cp->size;
63 jmp->used = cp->used;
64 jmp->stolen = cp->stolen;
65 /* save reloc count to rewind ilo_cp_write_bo() */
66 jmp->reloc_count = intel_bo_get_reloc_count(cp->bo);
67 }
68
69 /**
70 * Rewind to the saved state.
71 */
72 void
73 ilo_cp_longjmp(struct ilo_cp *cp, const struct ilo_cp_jmp_buf *jmp)
74 {
75 if (jmp->id != pointer_to_intptr(cp->bo)) {
76 assert(!"invalid use of CP longjmp");
77 return;
78 }
79
80 cp->size = jmp->size;
81 cp->used = jmp->used;
82 cp->stolen = jmp->stolen;
83 intel_bo_truncate_relocs(cp->bo, jmp->reloc_count);
84 }
85
86 /**
87 * Clear the parser buffer.
88 */
89 static void
90 ilo_cp_clear_buffer(struct ilo_cp *cp)
91 {
92 cp->cmd_cur = 0;
93 cp->cmd_end = 0;
94
95 cp->used = 0;
96 cp->stolen = 0;
97
98 /*
99 * Recalculate cp->size. This is needed not only because cp->stolen is
100 * reset above, but also that ilo_cp_private are added to cp->size in
101 * ilo_cp_end_buffer().
102 */
103 cp->size = cp->bo_size - ilo_cp_private;
104 }
105
106 /**
107 * Add MI_BATCH_BUFFER_END to the private space of the parser buffer.
108 */
109 static void
110 ilo_cp_end_buffer(struct ilo_cp *cp)
111 {
112 /* make the private space available */
113 cp->size += ilo_cp_private;
114
115 assert(cp->used + 2 <= cp->size);
116
117 cp->ptr[cp->used++] = MI_BATCH_BUFFER_END;
118
119 /*
120 * From the Sandy Bridge PRM, volume 1 part 1, page 107:
121 *
122 * "The batch buffer must be QWord aligned and a multiple of QWords in
123 * length."
124 */
125 if (cp->used & 1)
126 cp->ptr[cp->used++] = MI_NOOP;
127 }
128
129 /**
130 * Upload the parser buffer to the bo.
131 */
132 static int
133 ilo_cp_upload_buffer(struct ilo_cp *cp)
134 {
135 int err;
136
137 if (!cp->sys) {
138 intel_bo_unmap(cp->bo);
139 return 0;
140 }
141
142 err = intel_bo_pwrite(cp->bo, 0, cp->used * 4, cp->ptr);
143 if (likely(!err && cp->stolen)) {
144 const int offset = cp->bo_size - cp->stolen;
145
146 err = intel_bo_pwrite(cp->bo, offset * 4,
147 cp->stolen * 4, &cp->ptr[offset]);
148 }
149
150 return err;
151 }
152
153 /**
154 * Reallocate the parser bo.
155 */
156 static void
157 ilo_cp_realloc_bo(struct ilo_cp *cp)
158 {
159 struct intel_bo *bo;
160
161 /*
162 * allocate the new bo before unreferencing the old one so that they
163 * won't point at the same address, which is needed for jmpbuf
164 */
165 bo = intel_winsys_alloc_buffer(cp->winsys,
166 "batch buffer", cp->bo_size * 4, INTEL_DOMAIN_CPU);
167 if (unlikely(!bo)) {
168 /* reuse the old one */
169 bo = cp->bo;
170 intel_bo_reference(bo);
171 }
172
173 if (cp->bo)
174 intel_bo_unreference(cp->bo);
175 cp->bo = bo;
176
177 if (!cp->sys)
178 cp->ptr = intel_bo_map(cp->bo, true);
179 }
180
181 /**
182 * Execute the parser bo.
183 */
184 static int
185 ilo_cp_exec_bo(struct ilo_cp *cp)
186 {
187 const bool do_exec = !(ilo_debug & ILO_DEBUG_NOHW);
188 int err;
189
190 if (likely(do_exec)) {
191 err = intel_winsys_submit_bo(cp->winsys, cp->ring,
192 cp->bo, cp->used * 4, cp->render_ctx, cp->one_off_flags);
193 }
194 else {
195 err = 0;
196 }
197
198 cp->one_off_flags = 0;
199
200 return err;
201 }
202
203 /**
204 * Flush the command parser and execute the commands. When the parser buffer
205 * is empty, the callback is not invoked.
206 */
207 void
208 ilo_cp_flush_internal(struct ilo_cp *cp)
209 {
210 int err;
211
212 ilo_cp_set_owner(cp, NULL, 0);
213
214 /* sanity check */
215 assert(cp->bo_size == cp->size + cp->stolen + ilo_cp_private);
216
217 if (!cp->used) {
218 /* return the space stolen and etc. */
219 ilo_cp_clear_buffer(cp);
220
221 return;
222 }
223
224 ilo_cp_end_buffer(cp);
225
226 /* upload and execute */
227 err = ilo_cp_upload_buffer(cp);
228 if (likely(!err))
229 err = ilo_cp_exec_bo(cp);
230
231 if (likely(!err && cp->flush_callback))
232 cp->flush_callback(cp, cp->flush_callback_data);
233
234 ilo_cp_clear_buffer(cp);
235 ilo_cp_realloc_bo(cp);
236 }
237
238 /**
239 * Destroy the command parser.
240 */
241 void
242 ilo_cp_destroy(struct ilo_cp *cp)
243 {
244 if (cp->bo) {
245 if (!cp->sys)
246 intel_bo_unmap(cp->bo);
247
248 intel_bo_unreference(cp->bo);
249 }
250
251 intel_winsys_destroy_context(cp->winsys, cp->render_ctx);
252
253 FREE(cp->sys);
254 FREE(cp);
255 }
256
257 /**
258 * Create a command parser.
259 */
260 struct ilo_cp *
261 ilo_cp_create(struct intel_winsys *winsys, int size, bool direct_map)
262 {
263 struct ilo_cp *cp;
264
265 cp = CALLOC_STRUCT(ilo_cp);
266 if (!cp)
267 return NULL;
268
269 cp->winsys = winsys;
270 cp->render_ctx = intel_winsys_create_context(winsys);
271 if (!cp->render_ctx) {
272 FREE(cp);
273 return NULL;
274 }
275
276 cp->ring = INTEL_RING_RENDER;
277 cp->no_implicit_flush = false;
278
279 cp->bo_size = size;
280
281 if (!direct_map) {
282 cp->sys = MALLOC(cp->bo_size * 4);
283 if (!cp->sys) {
284 FREE(cp);
285 return NULL;
286 }
287
288 cp->ptr = cp->sys;
289 }
290
291 ilo_cp_realloc_bo(cp);
292 if (!cp->bo) {
293 FREE(cp->sys);
294 FREE(cp);
295 return NULL;
296 }
297
298 ilo_cp_clear_buffer(cp);
299
300 return cp;
301 }