gallium/u_threaded: properly initialize fence unflushed tokens
[mesa.git] / src / gallium / auxiliary / util / u_threaded_context.c
1 /**************************************************************************
2 *
3 * Copyright 2017 Advanced Micro Devices, Inc.
4 * All Rights Reserved.
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
10 * license, and/or sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27 #include "util/u_threaded_context.h"
28 #include "util/u_cpu_detect.h"
29 #include "util/u_format.h"
30 #include "util/u_inlines.h"
31 #include "util/u_memory.h"
32 #include "util/u_upload_mgr.h"
33
34 /* 0 = disabled, 1 = assertions, 2 = printfs */
35 #define TC_DEBUG 0
36
37 #if TC_DEBUG >= 1
38 #define tc_assert assert
39 #else
40 #define tc_assert(x)
41 #endif
42
43 #if TC_DEBUG >= 2
44 #define tc_printf printf
45 #define tc_asprintf asprintf
46 #define tc_strcmp strcmp
47 #else
48 #define tc_printf(...)
49 #define tc_asprintf(...) 0
50 #define tc_strcmp(...) 0
51 #endif
52
53 #define TC_SENTINEL 0x5ca1ab1e
54
55 enum tc_call_id {
56 #define CALL(name) TC_CALL_##name,
57 #include "u_threaded_context_calls.h"
58 #undef CALL
59 TC_NUM_CALLS,
60 };
61
62 typedef void (*tc_execute)(struct pipe_context *pipe, union tc_payload *payload);
63
64 static const tc_execute execute_func[TC_NUM_CALLS];
65
66 static void
67 tc_batch_check(MAYBE_UNUSED struct tc_batch *batch)
68 {
69 tc_assert(batch->sentinel == TC_SENTINEL);
70 tc_assert(batch->num_total_call_slots <= TC_CALLS_PER_BATCH);
71 }
72
73 static void
74 tc_debug_check(struct threaded_context *tc)
75 {
76 for (unsigned i = 0; i < TC_MAX_BATCHES; i++) {
77 tc_batch_check(&tc->batch_slots[i]);
78 tc_assert(tc->batch_slots[i].pipe == tc->pipe);
79 }
80 }
81
82 static void
83 tc_batch_execute(void *job, UNUSED int thread_index)
84 {
85 struct tc_batch *batch = job;
86 struct pipe_context *pipe = batch->pipe;
87 struct tc_call *last = &batch->call[batch->num_total_call_slots];
88
89 tc_batch_check(batch);
90
91 assert(!batch->token);
92
93 for (struct tc_call *iter = batch->call; iter != last;
94 iter += iter->num_call_slots) {
95 tc_assert(iter->sentinel == TC_SENTINEL);
96 execute_func[iter->call_id](pipe, &iter->payload);
97 }
98
99 tc_batch_check(batch);
100 batch->num_total_call_slots = 0;
101 }
102
103 static void
104 tc_batch_flush(struct threaded_context *tc)
105 {
106 struct tc_batch *next = &tc->batch_slots[tc->next];
107
108 tc_assert(next->num_total_call_slots != 0);
109 tc_batch_check(next);
110 tc_debug_check(tc);
111 p_atomic_add(&tc->num_offloaded_slots, next->num_total_call_slots);
112
113 if (next->token) {
114 next->token->tc = NULL;
115 tc_unflushed_batch_token_reference(&next->token, NULL);
116 }
117
118 util_queue_add_job(&tc->queue, next, &next->fence, tc_batch_execute,
119 NULL);
120 tc->last = tc->next;
121 tc->next = (tc->next + 1) % TC_MAX_BATCHES;
122 }
123
124 /* This is the function that adds variable-sized calls into the current
125 * batch. It also flushes the batch if there is not enough space there.
126 * All other higher-level "add" functions use it.
127 */
128 static union tc_payload *
129 tc_add_sized_call(struct threaded_context *tc, enum tc_call_id id,
130 unsigned payload_size)
131 {
132 struct tc_batch *next = &tc->batch_slots[tc->next];
133 unsigned total_size = offsetof(struct tc_call, payload) + payload_size;
134 unsigned num_call_slots = DIV_ROUND_UP(total_size, sizeof(struct tc_call));
135
136 tc_debug_check(tc);
137
138 if (unlikely(next->num_total_call_slots + num_call_slots > TC_CALLS_PER_BATCH)) {
139 tc_batch_flush(tc);
140 next = &tc->batch_slots[tc->next];
141 tc_assert(next->num_total_call_slots == 0);
142 }
143
144 tc_assert(util_queue_fence_is_signalled(&next->fence));
145
146 struct tc_call *call = &next->call[next->num_total_call_slots];
147 next->num_total_call_slots += num_call_slots;
148
149 call->sentinel = TC_SENTINEL;
150 call->call_id = id;
151 call->num_call_slots = num_call_slots;
152
153 tc_debug_check(tc);
154 return &call->payload;
155 }
156
157 #define tc_add_struct_typed_call(tc, execute, type) \
158 ((struct type*)tc_add_sized_call(tc, execute, sizeof(struct type)))
159
160 #define tc_add_slot_based_call(tc, execute, type, num_slots) \
161 ((struct type*)tc_add_sized_call(tc, execute, \
162 sizeof(struct type) + \
163 sizeof(((struct type*)NULL)->slot[0]) * \
164 (num_slots)))
165
166 static union tc_payload *
167 tc_add_small_call(struct threaded_context *tc, enum tc_call_id id)
168 {
169 return tc_add_sized_call(tc, id, 0);
170 }
171
172 static bool
173 tc_is_sync(struct threaded_context *tc)
174 {
175 struct tc_batch *last = &tc->batch_slots[tc->last];
176 struct tc_batch *next = &tc->batch_slots[tc->next];
177
178 return util_queue_fence_is_signalled(&last->fence) &&
179 !next->num_total_call_slots;
180 }
181
182 static void
183 _tc_sync(struct threaded_context *tc, MAYBE_UNUSED const char *info, MAYBE_UNUSED const char *func)
184 {
185 struct tc_batch *last = &tc->batch_slots[tc->last];
186 struct tc_batch *next = &tc->batch_slots[tc->next];
187 bool synced = false;
188
189 tc_debug_check(tc);
190
191 /* Only wait for queued calls... */
192 if (!util_queue_fence_is_signalled(&last->fence)) {
193 util_queue_fence_wait(&last->fence);
194 synced = true;
195 }
196
197 tc_debug_check(tc);
198
199 if (next->token) {
200 next->token->tc = NULL;
201 tc_unflushed_batch_token_reference(&next->token, NULL);
202 }
203
204 /* .. and execute unflushed calls directly. */
205 if (next->num_total_call_slots) {
206 p_atomic_add(&tc->num_direct_slots, next->num_total_call_slots);
207 tc_batch_execute(next, 0);
208 synced = true;
209 }
210
211 if (synced) {
212 p_atomic_inc(&tc->num_syncs);
213
214 if (tc_strcmp(func, "tc_destroy") != 0) {
215 tc_printf("sync %s %s\n", func, info);
216 }
217 }
218
219 tc_debug_check(tc);
220 }
221
222 #define tc_sync(tc) _tc_sync(tc, "", __func__)
223 #define tc_sync_msg(tc, info) _tc_sync(tc, info, __func__)
224
225 /**
226 * Call this from fence_finish for same-context fence waits of deferred fences
227 * that haven't been flushed yet.
228 *
229 * The passed pipe_context must be the one passed to pipe_screen::fence_finish,
230 * i.e., the wrapped one.
231 */
232 void
233 threaded_context_flush(struct pipe_context *_pipe,
234 struct tc_unflushed_batch_token *token)
235 {
236 struct threaded_context *tc = threaded_context(_pipe);
237
238 /* This is called from the state-tracker / application thread. */
239 if (token->tc && token->tc == tc)
240 tc_sync(token->tc);
241 }
242
243 static void
244 tc_set_resource_reference(struct pipe_resource **dst, struct pipe_resource *src)
245 {
246 *dst = NULL;
247 pipe_resource_reference(dst, src);
248 }
249
250 void
251 threaded_resource_init(struct pipe_resource *res)
252 {
253 struct threaded_resource *tres = threaded_resource(res);
254
255 tres->latest = &tres->b;
256 util_range_init(&tres->valid_buffer_range);
257 tres->base_valid_buffer_range = &tres->valid_buffer_range;
258 tres->is_shared = false;
259 tres->is_user_ptr = false;
260 }
261
262 void
263 threaded_resource_deinit(struct pipe_resource *res)
264 {
265 struct threaded_resource *tres = threaded_resource(res);
266
267 if (tres->latest != &tres->b)
268 pipe_resource_reference(&tres->latest, NULL);
269 util_range_destroy(&tres->valid_buffer_range);
270 }
271
272 struct pipe_context *
273 threaded_context_unwrap_sync(struct pipe_context *pipe)
274 {
275 if (!pipe || !pipe->priv)
276 return pipe;
277
278 tc_sync(threaded_context(pipe));
279 return (struct pipe_context*)pipe->priv;
280 }
281
282
283 /********************************************************************
284 * simple functions
285 */
286
287 #define TC_FUNC1(func, m_payload, qualifier, type, deref, deref2) \
288 static void \
289 tc_call_##func(struct pipe_context *pipe, union tc_payload *payload) \
290 { \
291 pipe->func(pipe, deref2((type*)payload)); \
292 } \
293 \
294 static void \
295 tc_##func(struct pipe_context *_pipe, qualifier type deref param) \
296 { \
297 struct threaded_context *tc = threaded_context(_pipe); \
298 type *p = (type*)tc_add_sized_call(tc, TC_CALL_##func, sizeof(type)); \
299 *p = deref(param); \
300 }
301
302 TC_FUNC1(set_active_query_state, flags, , boolean, , *)
303
304 TC_FUNC1(set_blend_color, blend_color, const, struct pipe_blend_color, *, )
305 TC_FUNC1(set_stencil_ref, stencil_ref, const, struct pipe_stencil_ref, *, )
306 TC_FUNC1(set_clip_state, clip_state, const, struct pipe_clip_state, *, )
307 TC_FUNC1(set_sample_mask, sample_mask, , unsigned, , *)
308 TC_FUNC1(set_min_samples, min_samples, , unsigned, , *)
309 TC_FUNC1(set_polygon_stipple, polygon_stipple, const, struct pipe_poly_stipple, *, )
310
311 TC_FUNC1(texture_barrier, flags, , unsigned, , *)
312 TC_FUNC1(memory_barrier, flags, , unsigned, , *)
313
314
315 /********************************************************************
316 * queries
317 */
318
319 static struct pipe_query *
320 tc_create_query(struct pipe_context *_pipe, unsigned query_type,
321 unsigned index)
322 {
323 struct threaded_context *tc = threaded_context(_pipe);
324 struct pipe_context *pipe = tc->pipe;
325
326 return pipe->create_query(pipe, query_type, index);
327 }
328
329 static struct pipe_query *
330 tc_create_batch_query(struct pipe_context *_pipe, unsigned num_queries,
331 unsigned *query_types)
332 {
333 struct threaded_context *tc = threaded_context(_pipe);
334 struct pipe_context *pipe = tc->pipe;
335
336 return pipe->create_batch_query(pipe, num_queries, query_types);
337 }
338
339 static void
340 tc_call_destroy_query(struct pipe_context *pipe, union tc_payload *payload)
341 {
342 struct threaded_query *tq = threaded_query(payload->query);
343
344 if (tq->head_unflushed.next)
345 LIST_DEL(&tq->head_unflushed);
346
347 pipe->destroy_query(pipe, payload->query);
348 }
349
350 static void
351 tc_destroy_query(struct pipe_context *_pipe, struct pipe_query *query)
352 {
353 struct threaded_context *tc = threaded_context(_pipe);
354
355 tc_add_small_call(tc, TC_CALL_destroy_query)->query = query;
356 }
357
358 static void
359 tc_call_begin_query(struct pipe_context *pipe, union tc_payload *payload)
360 {
361 pipe->begin_query(pipe, payload->query);
362 }
363
364 static boolean
365 tc_begin_query(struct pipe_context *_pipe, struct pipe_query *query)
366 {
367 struct threaded_context *tc = threaded_context(_pipe);
368 union tc_payload *payload = tc_add_small_call(tc, TC_CALL_begin_query);
369
370 payload->query = query;
371 return true; /* we don't care about the return value for this call */
372 }
373
374 struct tc_end_query_payload {
375 struct threaded_context *tc;
376 struct pipe_query *query;
377 };
378
379 static void
380 tc_call_end_query(struct pipe_context *pipe, union tc_payload *payload)
381 {
382 struct tc_end_query_payload *p = (struct tc_end_query_payload *)payload;
383 struct threaded_query *tq = threaded_query(p->query);
384
385 if (!tq->head_unflushed.next)
386 LIST_ADD(&tq->head_unflushed, &p->tc->unflushed_queries);
387
388 pipe->end_query(pipe, p->query);
389 }
390
391 static bool
392 tc_end_query(struct pipe_context *_pipe, struct pipe_query *query)
393 {
394 struct threaded_context *tc = threaded_context(_pipe);
395 struct threaded_query *tq = threaded_query(query);
396 struct tc_end_query_payload *payload =
397 tc_add_struct_typed_call(tc, TC_CALL_end_query, tc_end_query_payload);
398
399 payload->tc = tc;
400 payload->query = query;
401
402 tq->flushed = false;
403
404 return true; /* we don't care about the return value for this call */
405 }
406
407 static boolean
408 tc_get_query_result(struct pipe_context *_pipe,
409 struct pipe_query *query, boolean wait,
410 union pipe_query_result *result)
411 {
412 struct threaded_context *tc = threaded_context(_pipe);
413 struct threaded_query *tq = threaded_query(query);
414 struct pipe_context *pipe = tc->pipe;
415
416 if (!tq->flushed)
417 tc_sync_msg(tc, wait ? "wait" : "nowait");
418
419 bool success = pipe->get_query_result(pipe, query, wait, result);
420
421 if (success) {
422 tq->flushed = true;
423 if (tq->head_unflushed.next) {
424 /* This is safe because it can only happen after we sync'd. */
425 LIST_DEL(&tq->head_unflushed);
426 }
427 }
428 return success;
429 }
430
431 struct tc_query_result_resource {
432 struct pipe_query *query;
433 boolean wait;
434 enum pipe_query_value_type result_type;
435 int index;
436 struct pipe_resource *resource;
437 unsigned offset;
438 };
439
440 static void
441 tc_call_get_query_result_resource(struct pipe_context *pipe,
442 union tc_payload *payload)
443 {
444 struct tc_query_result_resource *p = (struct tc_query_result_resource *)payload;
445
446 pipe->get_query_result_resource(pipe, p->query, p->wait, p->result_type,
447 p->index, p->resource, p->offset);
448 pipe_resource_reference(&p->resource, NULL);
449 }
450
451 static void
452 tc_get_query_result_resource(struct pipe_context *_pipe,
453 struct pipe_query *query, boolean wait,
454 enum pipe_query_value_type result_type, int index,
455 struct pipe_resource *resource, unsigned offset)
456 {
457 struct threaded_context *tc = threaded_context(_pipe);
458 struct tc_query_result_resource *p =
459 tc_add_struct_typed_call(tc, TC_CALL_get_query_result_resource,
460 tc_query_result_resource);
461
462 p->query = query;
463 p->wait = wait;
464 p->result_type = result_type;
465 p->index = index;
466 tc_set_resource_reference(&p->resource, resource);
467 p->offset = offset;
468 }
469
470 struct tc_render_condition {
471 struct pipe_query *query;
472 bool condition;
473 unsigned mode;
474 };
475
476 static void
477 tc_call_render_condition(struct pipe_context *pipe, union tc_payload *payload)
478 {
479 struct tc_render_condition *p = (struct tc_render_condition *)payload;
480 pipe->render_condition(pipe, p->query, p->condition, p->mode);
481 }
482
483 static void
484 tc_render_condition(struct pipe_context *_pipe,
485 struct pipe_query *query, boolean condition,
486 enum pipe_render_cond_flag mode)
487 {
488 struct threaded_context *tc = threaded_context(_pipe);
489 struct tc_render_condition *p =
490 tc_add_struct_typed_call(tc, TC_CALL_render_condition, tc_render_condition);
491
492 p->query = query;
493 p->condition = condition;
494 p->mode = mode;
495 }
496
497
498 /********************************************************************
499 * constant (immutable) states
500 */
501
502 #define TC_CSO_CREATE(name, sname) \
503 static void * \
504 tc_create_##name##_state(struct pipe_context *_pipe, \
505 const struct pipe_##sname##_state *state) \
506 { \
507 struct pipe_context *pipe = threaded_context(_pipe)->pipe; \
508 return pipe->create_##name##_state(pipe, state); \
509 }
510
511 #define TC_CSO_BIND(name) TC_FUNC1(bind_##name##_state, cso, , void *, , *)
512 #define TC_CSO_DELETE(name) TC_FUNC1(delete_##name##_state, cso, , void *, , *)
513
514 #define TC_CSO_WHOLE2(name, sname) \
515 TC_CSO_CREATE(name, sname) \
516 TC_CSO_BIND(name) \
517 TC_CSO_DELETE(name)
518
519 #define TC_CSO_WHOLE(name) TC_CSO_WHOLE2(name, name)
520
521 TC_CSO_WHOLE(blend)
522 TC_CSO_WHOLE(rasterizer)
523 TC_CSO_WHOLE(depth_stencil_alpha)
524 TC_CSO_WHOLE(compute)
525 TC_CSO_WHOLE2(fs, shader)
526 TC_CSO_WHOLE2(vs, shader)
527 TC_CSO_WHOLE2(gs, shader)
528 TC_CSO_WHOLE2(tcs, shader)
529 TC_CSO_WHOLE2(tes, shader)
530 TC_CSO_CREATE(sampler, sampler)
531 TC_CSO_DELETE(sampler)
532 TC_CSO_BIND(vertex_elements)
533 TC_CSO_DELETE(vertex_elements)
534
535 static void *
536 tc_create_vertex_elements_state(struct pipe_context *_pipe, unsigned count,
537 const struct pipe_vertex_element *elems)
538 {
539 struct pipe_context *pipe = threaded_context(_pipe)->pipe;
540
541 return pipe->create_vertex_elements_state(pipe, count, elems);
542 }
543
544 struct tc_sampler_states {
545 ubyte shader, start, count;
546 void *slot[0]; /* more will be allocated if needed */
547 };
548
549 static void
550 tc_call_bind_sampler_states(struct pipe_context *pipe, union tc_payload *payload)
551 {
552 struct tc_sampler_states *p = (struct tc_sampler_states *)payload;
553 pipe->bind_sampler_states(pipe, p->shader, p->start, p->count, p->slot);
554 }
555
556 static void
557 tc_bind_sampler_states(struct pipe_context *_pipe,
558 enum pipe_shader_type shader,
559 unsigned start, unsigned count, void **states)
560 {
561 if (!count)
562 return;
563
564 struct threaded_context *tc = threaded_context(_pipe);
565 struct tc_sampler_states *p =
566 tc_add_slot_based_call(tc, TC_CALL_bind_sampler_states, tc_sampler_states, count);
567
568 p->shader = shader;
569 p->start = start;
570 p->count = count;
571 memcpy(p->slot, states, count * sizeof(states[0]));
572 }
573
574
575 /********************************************************************
576 * immediate states
577 */
578
579 static void
580 tc_call_set_framebuffer_state(struct pipe_context *pipe, union tc_payload *payload)
581 {
582 struct pipe_framebuffer_state *p = (struct pipe_framebuffer_state *)payload;
583
584 pipe->set_framebuffer_state(pipe, p);
585
586 unsigned nr_cbufs = p->nr_cbufs;
587 for (unsigned i = 0; i < nr_cbufs; i++)
588 pipe_surface_reference(&p->cbufs[i], NULL);
589 pipe_surface_reference(&p->zsbuf, NULL);
590 }
591
592 static void
593 tc_set_framebuffer_state(struct pipe_context *_pipe,
594 const struct pipe_framebuffer_state *fb)
595 {
596 struct threaded_context *tc = threaded_context(_pipe);
597 struct pipe_framebuffer_state *p =
598 tc_add_struct_typed_call(tc, TC_CALL_set_framebuffer_state,
599 pipe_framebuffer_state);
600 unsigned nr_cbufs = fb->nr_cbufs;
601
602 p->width = fb->width;
603 p->height = fb->height;
604 p->samples = fb->samples;
605 p->layers = fb->layers;
606 p->nr_cbufs = nr_cbufs;
607
608 for (unsigned i = 0; i < nr_cbufs; i++) {
609 p->cbufs[i] = NULL;
610 pipe_surface_reference(&p->cbufs[i], fb->cbufs[i]);
611 }
612 p->zsbuf = NULL;
613 pipe_surface_reference(&p->zsbuf, fb->zsbuf);
614 }
615
616 static void
617 tc_call_set_tess_state(struct pipe_context *pipe, union tc_payload *payload)
618 {
619 float *p = (float*)payload;
620 pipe->set_tess_state(pipe, p, p + 4);
621 }
622
623 static void
624 tc_set_tess_state(struct pipe_context *_pipe,
625 const float default_outer_level[4],
626 const float default_inner_level[2])
627 {
628 struct threaded_context *tc = threaded_context(_pipe);
629 float *p = (float*)tc_add_sized_call(tc, TC_CALL_set_tess_state,
630 sizeof(float) * 6);
631
632 memcpy(p, default_outer_level, 4 * sizeof(float));
633 memcpy(p + 4, default_inner_level, 2 * sizeof(float));
634 }
635
636 struct tc_constant_buffer {
637 ubyte shader, index;
638 struct pipe_constant_buffer cb;
639 };
640
641 static void
642 tc_call_set_constant_buffer(struct pipe_context *pipe, union tc_payload *payload)
643 {
644 struct tc_constant_buffer *p = (struct tc_constant_buffer *)payload;
645
646 pipe->set_constant_buffer(pipe,
647 p->shader,
648 p->index,
649 &p->cb);
650 pipe_resource_reference(&p->cb.buffer, NULL);
651 }
652
653 static void
654 tc_set_constant_buffer(struct pipe_context *_pipe,
655 enum pipe_shader_type shader, uint index,
656 const struct pipe_constant_buffer *cb)
657 {
658 struct threaded_context *tc = threaded_context(_pipe);
659 struct pipe_resource *buffer = NULL;
660 unsigned offset;
661
662 /* This must be done before adding set_constant_buffer, because it could
663 * generate e.g. transfer_unmap and flush partially-uninitialized
664 * set_constant_buffer to the driver if it was done afterwards.
665 */
666 if (cb && cb->user_buffer) {
667 u_upload_data(tc->base.const_uploader, 0, cb->buffer_size, 64,
668 cb->user_buffer, &offset, &buffer);
669 }
670
671 struct tc_constant_buffer *p =
672 tc_add_struct_typed_call(tc, TC_CALL_set_constant_buffer,
673 tc_constant_buffer);
674 p->shader = shader;
675 p->index = index;
676
677 if (cb) {
678 if (cb->user_buffer) {
679 p->cb.buffer_size = cb->buffer_size;
680 p->cb.user_buffer = NULL;
681 p->cb.buffer_offset = offset;
682 p->cb.buffer = buffer;
683 } else {
684 tc_set_resource_reference(&p->cb.buffer,
685 cb->buffer);
686 memcpy(&p->cb, cb, sizeof(*cb));
687 }
688 } else {
689 memset(&p->cb, 0, sizeof(*cb));
690 }
691 }
692
693 struct tc_scissors {
694 ubyte start, count;
695 struct pipe_scissor_state slot[0]; /* more will be allocated if needed */
696 };
697
698 static void
699 tc_call_set_scissor_states(struct pipe_context *pipe, union tc_payload *payload)
700 {
701 struct tc_scissors *p = (struct tc_scissors *)payload;
702 pipe->set_scissor_states(pipe, p->start, p->count, p->slot);
703 }
704
705 static void
706 tc_set_scissor_states(struct pipe_context *_pipe,
707 unsigned start, unsigned count,
708 const struct pipe_scissor_state *states)
709 {
710 struct threaded_context *tc = threaded_context(_pipe);
711 struct tc_scissors *p =
712 tc_add_slot_based_call(tc, TC_CALL_set_scissor_states, tc_scissors, count);
713
714 p->start = start;
715 p->count = count;
716 memcpy(&p->slot, states, count * sizeof(states[0]));
717 }
718
719 struct tc_viewports {
720 ubyte start, count;
721 struct pipe_viewport_state slot[0]; /* more will be allocated if needed */
722 };
723
724 static void
725 tc_call_set_viewport_states(struct pipe_context *pipe, union tc_payload *payload)
726 {
727 struct tc_viewports *p = (struct tc_viewports *)payload;
728 pipe->set_viewport_states(pipe, p->start, p->count, p->slot);
729 }
730
731 static void
732 tc_set_viewport_states(struct pipe_context *_pipe,
733 unsigned start, unsigned count,
734 const struct pipe_viewport_state *states)
735 {
736 if (!count)
737 return;
738
739 struct threaded_context *tc = threaded_context(_pipe);
740 struct tc_viewports *p =
741 tc_add_slot_based_call(tc, TC_CALL_set_viewport_states, tc_viewports, count);
742
743 p->start = start;
744 p->count = count;
745 memcpy(&p->slot, states, count * sizeof(states[0]));
746 }
747
748 struct tc_window_rects {
749 bool include;
750 ubyte count;
751 struct pipe_scissor_state slot[0]; /* more will be allocated if needed */
752 };
753
754 static void
755 tc_call_set_window_rectangles(struct pipe_context *pipe,
756 union tc_payload *payload)
757 {
758 struct tc_window_rects *p = (struct tc_window_rects *)payload;
759 pipe->set_window_rectangles(pipe, p->include, p->count, p->slot);
760 }
761
762 static void
763 tc_set_window_rectangles(struct pipe_context *_pipe, boolean include,
764 unsigned count,
765 const struct pipe_scissor_state *rects)
766 {
767 struct threaded_context *tc = threaded_context(_pipe);
768 struct tc_window_rects *p =
769 tc_add_slot_based_call(tc, TC_CALL_set_window_rectangles, tc_window_rects, count);
770
771 p->include = include;
772 p->count = count;
773 memcpy(p->slot, rects, count * sizeof(rects[0]));
774 }
775
776 struct tc_sampler_views {
777 ubyte shader, start, count;
778 struct pipe_sampler_view *slot[0]; /* more will be allocated if needed */
779 };
780
781 static void
782 tc_call_set_sampler_views(struct pipe_context *pipe, union tc_payload *payload)
783 {
784 struct tc_sampler_views *p = (struct tc_sampler_views *)payload;
785 unsigned count = p->count;
786
787 pipe->set_sampler_views(pipe, p->shader, p->start, p->count, p->slot);
788 for (unsigned i = 0; i < count; i++)
789 pipe_sampler_view_reference(&p->slot[i], NULL);
790 }
791
792 static void
793 tc_set_sampler_views(struct pipe_context *_pipe,
794 enum pipe_shader_type shader,
795 unsigned start, unsigned count,
796 struct pipe_sampler_view **views)
797 {
798 if (!count)
799 return;
800
801 struct threaded_context *tc = threaded_context(_pipe);
802 struct tc_sampler_views *p =
803 tc_add_slot_based_call(tc, TC_CALL_set_sampler_views, tc_sampler_views, count);
804
805 p->shader = shader;
806 p->start = start;
807 p->count = count;
808
809 if (views) {
810 for (unsigned i = 0; i < count; i++) {
811 p->slot[i] = NULL;
812 pipe_sampler_view_reference(&p->slot[i], views[i]);
813 }
814 } else {
815 memset(p->slot, 0, count * sizeof(views[0]));
816 }
817 }
818
819 struct tc_shader_images {
820 ubyte shader, start, count;
821 bool unbind;
822 struct pipe_image_view slot[0]; /* more will be allocated if needed */
823 };
824
825 static void
826 tc_call_set_shader_images(struct pipe_context *pipe, union tc_payload *payload)
827 {
828 struct tc_shader_images *p = (struct tc_shader_images *)payload;
829 unsigned count = p->count;
830
831 if (p->unbind) {
832 pipe->set_shader_images(pipe, p->shader, p->start, p->count, NULL);
833 return;
834 }
835
836 pipe->set_shader_images(pipe, p->shader, p->start, p->count, p->slot);
837
838 for (unsigned i = 0; i < count; i++)
839 pipe_resource_reference(&p->slot[i].resource, NULL);
840 }
841
842 static void
843 tc_set_shader_images(struct pipe_context *_pipe,
844 enum pipe_shader_type shader,
845 unsigned start, unsigned count,
846 const struct pipe_image_view *images)
847 {
848 if (!count)
849 return;
850
851 struct threaded_context *tc = threaded_context(_pipe);
852 struct tc_shader_images *p =
853 tc_add_slot_based_call(tc, TC_CALL_set_shader_images, tc_shader_images,
854 images ? count : 0);
855
856 p->shader = shader;
857 p->start = start;
858 p->count = count;
859 p->unbind = images == NULL;
860
861 if (images) {
862 for (unsigned i = 0; i < count; i++) {
863 tc_set_resource_reference(&p->slot[i].resource, images[i].resource);
864
865 if (images[i].access & PIPE_IMAGE_ACCESS_WRITE &&
866 images[i].resource &&
867 images[i].resource->target == PIPE_BUFFER) {
868 struct threaded_resource *tres =
869 threaded_resource(images[i].resource);
870
871 util_range_add(&tres->valid_buffer_range, images[i].u.buf.offset,
872 images[i].u.buf.offset + images[i].u.buf.size);
873 }
874 }
875 memcpy(p->slot, images, count * sizeof(images[0]));
876 }
877 }
878
879 struct tc_shader_buffers {
880 ubyte shader, start, count;
881 bool unbind;
882 struct pipe_shader_buffer slot[0]; /* more will be allocated if needed */
883 };
884
885 static void
886 tc_call_set_shader_buffers(struct pipe_context *pipe, union tc_payload *payload)
887 {
888 struct tc_shader_buffers *p = (struct tc_shader_buffers *)payload;
889 unsigned count = p->count;
890
891 if (p->unbind) {
892 pipe->set_shader_buffers(pipe, p->shader, p->start, p->count, NULL);
893 return;
894 }
895
896 pipe->set_shader_buffers(pipe, p->shader, p->start, p->count, p->slot);
897
898 for (unsigned i = 0; i < count; i++)
899 pipe_resource_reference(&p->slot[i].buffer, NULL);
900 }
901
902 static void
903 tc_set_shader_buffers(struct pipe_context *_pipe,
904 enum pipe_shader_type shader,
905 unsigned start, unsigned count,
906 const struct pipe_shader_buffer *buffers)
907 {
908 if (!count)
909 return;
910
911 struct threaded_context *tc = threaded_context(_pipe);
912 struct tc_shader_buffers *p =
913 tc_add_slot_based_call(tc, TC_CALL_set_shader_buffers, tc_shader_buffers,
914 buffers ? count : 0);
915
916 p->shader = shader;
917 p->start = start;
918 p->count = count;
919 p->unbind = buffers == NULL;
920
921 if (buffers) {
922 for (unsigned i = 0; i < count; i++) {
923 struct pipe_shader_buffer *dst = &p->slot[i];
924 const struct pipe_shader_buffer *src = buffers + i;
925
926 tc_set_resource_reference(&dst->buffer, src->buffer);
927 dst->buffer_offset = src->buffer_offset;
928 dst->buffer_size = src->buffer_size;
929
930 if (src->buffer) {
931 struct threaded_resource *tres = threaded_resource(src->buffer);
932
933 util_range_add(&tres->valid_buffer_range, src->buffer_offset,
934 src->buffer_offset + src->buffer_size);
935 }
936 }
937 }
938 }
939
940 struct tc_vertex_buffers {
941 ubyte start, count;
942 bool unbind;
943 struct pipe_vertex_buffer slot[0]; /* more will be allocated if needed */
944 };
945
946 static void
947 tc_call_set_vertex_buffers(struct pipe_context *pipe, union tc_payload *payload)
948 {
949 struct tc_vertex_buffers *p = (struct tc_vertex_buffers *)payload;
950 unsigned count = p->count;
951
952 if (p->unbind) {
953 pipe->set_vertex_buffers(pipe, p->start, count, NULL);
954 return;
955 }
956
957 for (unsigned i = 0; i < count; i++)
958 tc_assert(!p->slot[i].is_user_buffer);
959
960 pipe->set_vertex_buffers(pipe, p->start, count, p->slot);
961 for (unsigned i = 0; i < count; i++)
962 pipe_resource_reference(&p->slot[i].buffer.resource, NULL);
963 }
964
965 static void
966 tc_set_vertex_buffers(struct pipe_context *_pipe,
967 unsigned start, unsigned count,
968 const struct pipe_vertex_buffer *buffers)
969 {
970 struct threaded_context *tc = threaded_context(_pipe);
971
972 if (!count)
973 return;
974
975 if (buffers) {
976 struct tc_vertex_buffers *p =
977 tc_add_slot_based_call(tc, TC_CALL_set_vertex_buffers, tc_vertex_buffers, count);
978 p->start = start;
979 p->count = count;
980 p->unbind = false;
981
982 for (unsigned i = 0; i < count; i++) {
983 struct pipe_vertex_buffer *dst = &p->slot[i];
984 const struct pipe_vertex_buffer *src = buffers + i;
985
986 tc_assert(!src->is_user_buffer);
987 dst->stride = src->stride;
988 dst->is_user_buffer = false;
989 tc_set_resource_reference(&dst->buffer.resource,
990 src->buffer.resource);
991 dst->buffer_offset = src->buffer_offset;
992 }
993 } else {
994 struct tc_vertex_buffers *p =
995 tc_add_slot_based_call(tc, TC_CALL_set_vertex_buffers, tc_vertex_buffers, 0);
996 p->start = start;
997 p->count = count;
998 p->unbind = true;
999 }
1000 }
1001
1002 struct tc_stream_outputs {
1003 unsigned count;
1004 struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS];
1005 unsigned offsets[PIPE_MAX_SO_BUFFERS];
1006 };
1007
1008 static void
1009 tc_call_set_stream_output_targets(struct pipe_context *pipe, union tc_payload *payload)
1010 {
1011 struct tc_stream_outputs *p = (struct tc_stream_outputs *)payload;
1012 unsigned count = p->count;
1013
1014 pipe->set_stream_output_targets(pipe, count, p->targets, p->offsets);
1015 for (unsigned i = 0; i < count; i++)
1016 pipe_so_target_reference(&p->targets[i], NULL);
1017 }
1018
1019 static void
1020 tc_set_stream_output_targets(struct pipe_context *_pipe,
1021 unsigned count,
1022 struct pipe_stream_output_target **tgs,
1023 const unsigned *offsets)
1024 {
1025 struct threaded_context *tc = threaded_context(_pipe);
1026 struct tc_stream_outputs *p =
1027 tc_add_struct_typed_call(tc, TC_CALL_set_stream_output_targets,
1028 tc_stream_outputs);
1029
1030 for (unsigned i = 0; i < count; i++) {
1031 p->targets[i] = NULL;
1032 pipe_so_target_reference(&p->targets[i], tgs[i]);
1033 }
1034 p->count = count;
1035 memcpy(p->offsets, offsets, count * sizeof(unsigned));
1036 }
1037
1038 static void
1039 tc_set_compute_resources(struct pipe_context *_pipe, unsigned start,
1040 unsigned count, struct pipe_surface **resources)
1041 {
1042 struct threaded_context *tc = threaded_context(_pipe);
1043 struct pipe_context *pipe = tc->pipe;
1044
1045 tc_sync(tc);
1046 pipe->set_compute_resources(pipe, start, count, resources);
1047 }
1048
1049 static void
1050 tc_set_global_binding(struct pipe_context *_pipe, unsigned first,
1051 unsigned count, struct pipe_resource **resources,
1052 uint32_t **handles)
1053 {
1054 struct threaded_context *tc = threaded_context(_pipe);
1055 struct pipe_context *pipe = tc->pipe;
1056
1057 tc_sync(tc);
1058 pipe->set_global_binding(pipe, first, count, resources, handles);
1059 }
1060
1061
1062 /********************************************************************
1063 * views
1064 */
1065
1066 static struct pipe_surface *
1067 tc_create_surface(struct pipe_context *_pipe,
1068 struct pipe_resource *resource,
1069 const struct pipe_surface *surf_tmpl)
1070 {
1071 struct pipe_context *pipe = threaded_context(_pipe)->pipe;
1072 struct pipe_surface *view =
1073 pipe->create_surface(pipe, resource, surf_tmpl);
1074
1075 if (view)
1076 view->context = _pipe;
1077 return view;
1078 }
1079
1080 static void
1081 tc_surface_destroy(struct pipe_context *_pipe,
1082 struct pipe_surface *surf)
1083 {
1084 struct pipe_context *pipe = threaded_context(_pipe)->pipe;
1085
1086 pipe->surface_destroy(pipe, surf);
1087 }
1088
1089 static struct pipe_sampler_view *
1090 tc_create_sampler_view(struct pipe_context *_pipe,
1091 struct pipe_resource *resource,
1092 const struct pipe_sampler_view *templ)
1093 {
1094 struct pipe_context *pipe = threaded_context(_pipe)->pipe;
1095 struct pipe_sampler_view *view =
1096 pipe->create_sampler_view(pipe, resource, templ);
1097
1098 if (view)
1099 view->context = _pipe;
1100 return view;
1101 }
1102
1103 static void
1104 tc_sampler_view_destroy(struct pipe_context *_pipe,
1105 struct pipe_sampler_view *view)
1106 {
1107 struct pipe_context *pipe = threaded_context(_pipe)->pipe;
1108
1109 pipe->sampler_view_destroy(pipe, view);
1110 }
1111
1112 static struct pipe_stream_output_target *
1113 tc_create_stream_output_target(struct pipe_context *_pipe,
1114 struct pipe_resource *res,
1115 unsigned buffer_offset,
1116 unsigned buffer_size)
1117 {
1118 struct pipe_context *pipe = threaded_context(_pipe)->pipe;
1119 struct threaded_resource *tres = threaded_resource(res);
1120 struct pipe_stream_output_target *view;
1121
1122 tc_sync(threaded_context(_pipe));
1123 util_range_add(&tres->valid_buffer_range, buffer_offset,
1124 buffer_offset + buffer_size);
1125
1126 view = pipe->create_stream_output_target(pipe, res, buffer_offset,
1127 buffer_size);
1128 if (view)
1129 view->context = _pipe;
1130 return view;
1131 }
1132
1133 static void
1134 tc_stream_output_target_destroy(struct pipe_context *_pipe,
1135 struct pipe_stream_output_target *target)
1136 {
1137 struct pipe_context *pipe = threaded_context(_pipe)->pipe;
1138
1139 pipe->stream_output_target_destroy(pipe, target);
1140 }
1141
1142
1143 /********************************************************************
1144 * bindless
1145 */
1146
1147 static uint64_t
1148 tc_create_texture_handle(struct pipe_context *_pipe,
1149 struct pipe_sampler_view *view,
1150 const struct pipe_sampler_state *state)
1151 {
1152 struct threaded_context *tc = threaded_context(_pipe);
1153 struct pipe_context *pipe = tc->pipe;
1154
1155 tc_sync(tc);
1156 return pipe->create_texture_handle(pipe, view, state);
1157 }
1158
1159 static void
1160 tc_call_delete_texture_handle(struct pipe_context *pipe,
1161 union tc_payload *payload)
1162 {
1163 pipe->delete_texture_handle(pipe, payload->handle);
1164 }
1165
1166 static void
1167 tc_delete_texture_handle(struct pipe_context *_pipe, uint64_t handle)
1168 {
1169 struct threaded_context *tc = threaded_context(_pipe);
1170 union tc_payload *payload =
1171 tc_add_small_call(tc, TC_CALL_delete_texture_handle);
1172
1173 payload->handle = handle;
1174 }
1175
1176 struct tc_make_texture_handle_resident
1177 {
1178 uint64_t handle;
1179 bool resident;
1180 };
1181
1182 static void
1183 tc_call_make_texture_handle_resident(struct pipe_context *pipe,
1184 union tc_payload *payload)
1185 {
1186 struct tc_make_texture_handle_resident *p =
1187 (struct tc_make_texture_handle_resident *)payload;
1188
1189 pipe->make_texture_handle_resident(pipe, p->handle, p->resident);
1190 }
1191
1192 static void
1193 tc_make_texture_handle_resident(struct pipe_context *_pipe, uint64_t handle,
1194 bool resident)
1195 {
1196 struct threaded_context *tc = threaded_context(_pipe);
1197 struct tc_make_texture_handle_resident *p =
1198 tc_add_struct_typed_call(tc, TC_CALL_make_texture_handle_resident,
1199 tc_make_texture_handle_resident);
1200
1201 p->handle = handle;
1202 p->resident = resident;
1203 }
1204
1205 static uint64_t
1206 tc_create_image_handle(struct pipe_context *_pipe,
1207 const struct pipe_image_view *image)
1208 {
1209 struct threaded_context *tc = threaded_context(_pipe);
1210 struct pipe_context *pipe = tc->pipe;
1211
1212 tc_sync(tc);
1213 return pipe->create_image_handle(pipe, image);
1214 }
1215
1216 static void
1217 tc_call_delete_image_handle(struct pipe_context *pipe,
1218 union tc_payload *payload)
1219 {
1220 pipe->delete_image_handle(pipe, payload->handle);
1221 }
1222
1223 static void
1224 tc_delete_image_handle(struct pipe_context *_pipe, uint64_t handle)
1225 {
1226 struct threaded_context *tc = threaded_context(_pipe);
1227 union tc_payload *payload =
1228 tc_add_small_call(tc, TC_CALL_delete_image_handle);
1229
1230 payload->handle = handle;
1231 }
1232
1233 struct tc_make_image_handle_resident
1234 {
1235 uint64_t handle;
1236 unsigned access;
1237 bool resident;
1238 };
1239
1240 static void
1241 tc_call_make_image_handle_resident(struct pipe_context *pipe,
1242 union tc_payload *payload)
1243 {
1244 struct tc_make_image_handle_resident *p =
1245 (struct tc_make_image_handle_resident *)payload;
1246
1247 pipe->make_image_handle_resident(pipe, p->handle, p->access, p->resident);
1248 }
1249
1250 static void
1251 tc_make_image_handle_resident(struct pipe_context *_pipe, uint64_t handle,
1252 unsigned access, bool resident)
1253 {
1254 struct threaded_context *tc = threaded_context(_pipe);
1255 struct tc_make_image_handle_resident *p =
1256 tc_add_struct_typed_call(tc, TC_CALL_make_image_handle_resident,
1257 tc_make_image_handle_resident);
1258
1259 p->handle = handle;
1260 p->access = access;
1261 p->resident = resident;
1262 }
1263
1264
1265 /********************************************************************
1266 * transfer
1267 */
1268
1269 struct tc_replace_buffer_storage {
1270 struct pipe_resource *dst;
1271 struct pipe_resource *src;
1272 tc_replace_buffer_storage_func func;
1273 };
1274
1275 static void
1276 tc_call_replace_buffer_storage(struct pipe_context *pipe,
1277 union tc_payload *payload)
1278 {
1279 struct tc_replace_buffer_storage *p =
1280 (struct tc_replace_buffer_storage *)payload;
1281
1282 p->func(pipe, p->dst, p->src);
1283 pipe_resource_reference(&p->dst, NULL);
1284 pipe_resource_reference(&p->src, NULL);
1285 }
1286
1287 static bool
1288 tc_invalidate_buffer(struct threaded_context *tc,
1289 struct threaded_resource *tbuf)
1290 {
1291 /* We can't check if the buffer is idle, so we invalidate it
1292 * unconditionally. */
1293 struct pipe_screen *screen = tc->base.screen;
1294 struct pipe_resource *new_buf;
1295
1296 /* Shared, pinned, and sparse buffers can't be reallocated. */
1297 if (tbuf->is_shared ||
1298 tbuf->is_user_ptr ||
1299 tbuf->b.flags & PIPE_RESOURCE_FLAG_SPARSE)
1300 return false;
1301
1302 /* Allocate a new one. */
1303 new_buf = screen->resource_create(screen, &tbuf->b);
1304 if (!new_buf)
1305 return false;
1306
1307 /* Replace the "latest" pointer. */
1308 if (tbuf->latest != &tbuf->b)
1309 pipe_resource_reference(&tbuf->latest, NULL);
1310
1311 tbuf->latest = new_buf;
1312 util_range_set_empty(&tbuf->valid_buffer_range);
1313
1314 /* The valid range should point to the original buffer. */
1315 threaded_resource(new_buf)->base_valid_buffer_range =
1316 &tbuf->valid_buffer_range;
1317
1318 /* Enqueue storage replacement of the original buffer. */
1319 struct tc_replace_buffer_storage *p =
1320 tc_add_struct_typed_call(tc, TC_CALL_replace_buffer_storage,
1321 tc_replace_buffer_storage);
1322
1323 p->func = tc->replace_buffer_storage;
1324 tc_set_resource_reference(&p->dst, &tbuf->b);
1325 tc_set_resource_reference(&p->src, new_buf);
1326 return true;
1327 }
1328
1329 static unsigned
1330 tc_improve_map_buffer_flags(struct threaded_context *tc,
1331 struct threaded_resource *tres, unsigned usage,
1332 unsigned offset, unsigned size)
1333 {
1334 /* Never invalidate inside the driver and never infer "unsynchronized". */
1335 unsigned tc_flags = TC_TRANSFER_MAP_NO_INVALIDATE |
1336 TC_TRANSFER_MAP_NO_INFER_UNSYNCHRONIZED;
1337
1338 /* Prevent a reentry. */
1339 if (usage & tc_flags)
1340 return usage;
1341
1342 /* Use the staging upload if it's preferred. */
1343 if (usage & (PIPE_TRANSFER_DISCARD_RANGE |
1344 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) &&
1345 !(usage & PIPE_TRANSFER_PERSISTENT) &&
1346 /* Try not to decrement the counter if it's not positive. Still racy,
1347 * but it makes it harder to wrap the counter from INT_MIN to INT_MAX. */
1348 tres->max_forced_staging_uploads > 0 &&
1349 p_atomic_dec_return(&tres->max_forced_staging_uploads) >= 0) {
1350 usage &= ~(PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE |
1351 PIPE_TRANSFER_UNSYNCHRONIZED);
1352
1353 return usage | tc_flags | PIPE_TRANSFER_DISCARD_RANGE;
1354 }
1355
1356 /* Sparse buffers can't be mapped directly and can't be reallocated
1357 * (fully invalidated). That may just be a radeonsi limitation, but
1358 * the threaded context must obey it with radeonsi.
1359 */
1360 if (tres->b.flags & PIPE_RESOURCE_FLAG_SPARSE) {
1361 /* We can use DISCARD_RANGE instead of full discard. This is the only
1362 * fast path for sparse buffers that doesn't need thread synchronization.
1363 */
1364 if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE)
1365 usage |= PIPE_TRANSFER_DISCARD_RANGE;
1366
1367 /* Allow DISCARD_WHOLE_RESOURCE and infering UNSYNCHRONIZED in drivers.
1368 * The threaded context doesn't do unsychronized mappings and invalida-
1369 * tions of sparse buffers, therefore a correct driver behavior won't
1370 * result in an incorrect behavior with the threaded context.
1371 */
1372 return usage;
1373 }
1374
1375 usage |= tc_flags;
1376
1377 /* Handle CPU reads trivially. */
1378 if (usage & PIPE_TRANSFER_READ) {
1379 /* Drivers aren't allowed to do buffer invalidations. */
1380 return usage & ~PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
1381 }
1382
1383 /* See if the buffer range being mapped has never been initialized,
1384 * in which case it can be mapped unsynchronized. */
1385 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED) &&
1386 !tres->is_shared &&
1387 !util_ranges_intersect(&tres->valid_buffer_range, offset, offset + size))
1388 usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
1389
1390 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
1391 /* If discarding the entire range, discard the whole resource instead. */
1392 if (usage & PIPE_TRANSFER_DISCARD_RANGE &&
1393 offset == 0 && size == tres->b.width0)
1394 usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
1395
1396 /* Discard the whole resource if needed. */
1397 if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
1398 if (tc_invalidate_buffer(tc, tres))
1399 usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
1400 else
1401 usage |= PIPE_TRANSFER_DISCARD_RANGE; /* fallback */
1402 }
1403 }
1404
1405 /* We won't need this flag anymore. */
1406 /* TODO: We might not need TC_TRANSFER_MAP_NO_INVALIDATE with this. */
1407 usage &= ~PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
1408
1409 /* GL_AMD_pinned_memory and persistent mappings can't use staging
1410 * buffers. */
1411 if (usage & (PIPE_TRANSFER_UNSYNCHRONIZED |
1412 PIPE_TRANSFER_PERSISTENT) ||
1413 tres->is_user_ptr)
1414 usage &= ~PIPE_TRANSFER_DISCARD_RANGE;
1415
1416 /* Unsychronized buffer mappings don't have to synchronize the thread. */
1417 if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) {
1418 usage &= ~PIPE_TRANSFER_DISCARD_RANGE;
1419 usage |= TC_TRANSFER_MAP_THREADED_UNSYNC; /* notify the driver */
1420 }
1421
1422 return usage;
1423 }
1424
1425 static void *
1426 tc_transfer_map(struct pipe_context *_pipe,
1427 struct pipe_resource *resource, unsigned level,
1428 unsigned usage, const struct pipe_box *box,
1429 struct pipe_transfer **transfer)
1430 {
1431 struct threaded_context *tc = threaded_context(_pipe);
1432 struct threaded_resource *tres = threaded_resource(resource);
1433 struct pipe_context *pipe = tc->pipe;
1434
1435 if (resource->target == PIPE_BUFFER) {
1436 usage = tc_improve_map_buffer_flags(tc, tres, usage, box->x, box->width);
1437
1438 /* Do a staging transfer within the threaded context. The driver should
1439 * only get resource_copy_region.
1440 */
1441 if (usage & PIPE_TRANSFER_DISCARD_RANGE) {
1442 struct threaded_transfer *ttrans = slab_alloc(&tc->pool_transfers);
1443 uint8_t *map;
1444
1445 ttrans->staging = NULL;
1446
1447 u_upload_alloc(tc->base.stream_uploader, 0,
1448 box->width + (box->x % tc->map_buffer_alignment),
1449 64, &ttrans->offset, &ttrans->staging, (void**)&map);
1450 if (!map) {
1451 slab_free(&tc->pool_transfers, ttrans);
1452 return NULL;
1453 }
1454
1455 tc_set_resource_reference(&ttrans->b.resource, resource);
1456 ttrans->b.level = 0;
1457 ttrans->b.usage = usage;
1458 ttrans->b.box = *box;
1459 ttrans->b.stride = 0;
1460 ttrans->b.layer_stride = 0;
1461 *transfer = &ttrans->b;
1462 return map + (box->x % tc->map_buffer_alignment);
1463 }
1464 }
1465
1466 /* Unsychronized buffer mappings don't have to synchronize the thread. */
1467 if (!(usage & TC_TRANSFER_MAP_THREADED_UNSYNC))
1468 tc_sync_msg(tc, resource->target != PIPE_BUFFER ? " texture" :
1469 usage & PIPE_TRANSFER_DISCARD_RANGE ? " discard_range" :
1470 usage & PIPE_TRANSFER_READ ? " read" : " ??");
1471
1472 return pipe->transfer_map(pipe, tres->latest ? tres->latest : resource,
1473 level, usage, box, transfer);
1474 }
1475
1476 struct tc_transfer_flush_region {
1477 struct pipe_transfer *transfer;
1478 struct pipe_box box;
1479 };
1480
1481 static void
1482 tc_call_transfer_flush_region(struct pipe_context *pipe,
1483 union tc_payload *payload)
1484 {
1485 struct tc_transfer_flush_region *p =
1486 (struct tc_transfer_flush_region *)payload;
1487
1488 pipe->transfer_flush_region(pipe, p->transfer, &p->box);
1489 }
1490
1491 struct tc_resource_copy_region {
1492 struct pipe_resource *dst;
1493 unsigned dst_level;
1494 unsigned dstx, dsty, dstz;
1495 struct pipe_resource *src;
1496 unsigned src_level;
1497 struct pipe_box src_box;
1498 };
1499
1500 static void
1501 tc_resource_copy_region(struct pipe_context *_pipe,
1502 struct pipe_resource *dst, unsigned dst_level,
1503 unsigned dstx, unsigned dsty, unsigned dstz,
1504 struct pipe_resource *src, unsigned src_level,
1505 const struct pipe_box *src_box);
1506
1507 static void
1508 tc_buffer_do_flush_region(struct threaded_context *tc,
1509 struct threaded_transfer *ttrans,
1510 const struct pipe_box *box)
1511 {
1512 struct threaded_resource *tres = threaded_resource(ttrans->b.resource);
1513
1514 if (ttrans->staging) {
1515 struct pipe_box src_box;
1516
1517 u_box_1d(ttrans->offset + box->x % tc->map_buffer_alignment,
1518 box->width, &src_box);
1519
1520 /* Copy the staging buffer into the original one. */
1521 tc_resource_copy_region(&tc->base, ttrans->b.resource, 0, box->x, 0, 0,
1522 ttrans->staging, 0, &src_box);
1523 }
1524
1525 util_range_add(tres->base_valid_buffer_range, box->x, box->x + box->width);
1526 }
1527
1528 static void
1529 tc_transfer_flush_region(struct pipe_context *_pipe,
1530 struct pipe_transfer *transfer,
1531 const struct pipe_box *rel_box)
1532 {
1533 struct threaded_context *tc = threaded_context(_pipe);
1534 struct threaded_transfer *ttrans = threaded_transfer(transfer);
1535 struct threaded_resource *tres = threaded_resource(transfer->resource);
1536 unsigned required_usage = PIPE_TRANSFER_WRITE |
1537 PIPE_TRANSFER_FLUSH_EXPLICIT;
1538
1539 if (tres->b.target == PIPE_BUFFER) {
1540 if ((transfer->usage & required_usage) == required_usage) {
1541 struct pipe_box box;
1542
1543 u_box_1d(transfer->box.x + rel_box->x, rel_box->width, &box);
1544 tc_buffer_do_flush_region(tc, ttrans, &box);
1545 }
1546
1547 /* Staging transfers don't send the call to the driver. */
1548 if (ttrans->staging)
1549 return;
1550 }
1551
1552 struct tc_transfer_flush_region *p =
1553 tc_add_struct_typed_call(tc, TC_CALL_transfer_flush_region,
1554 tc_transfer_flush_region);
1555 p->transfer = transfer;
1556 p->box = *rel_box;
1557 }
1558
1559 static void
1560 tc_call_transfer_unmap(struct pipe_context *pipe, union tc_payload *payload)
1561 {
1562 pipe->transfer_unmap(pipe, payload->transfer);
1563 }
1564
1565 static void
1566 tc_transfer_unmap(struct pipe_context *_pipe, struct pipe_transfer *transfer)
1567 {
1568 struct threaded_context *tc = threaded_context(_pipe);
1569 struct threaded_transfer *ttrans = threaded_transfer(transfer);
1570 struct threaded_resource *tres = threaded_resource(transfer->resource);
1571
1572 if (tres->b.target == PIPE_BUFFER) {
1573 if (transfer->usage & PIPE_TRANSFER_WRITE &&
1574 !(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT))
1575 tc_buffer_do_flush_region(tc, ttrans, &transfer->box);
1576
1577 /* Staging transfers don't send the call to the driver. */
1578 if (ttrans->staging) {
1579 pipe_resource_reference(&ttrans->staging, NULL);
1580 pipe_resource_reference(&ttrans->b.resource, NULL);
1581 slab_free(&tc->pool_transfers, ttrans);
1582 return;
1583 }
1584 }
1585
1586 tc_add_small_call(tc, TC_CALL_transfer_unmap)->transfer = transfer;
1587 }
1588
1589 struct tc_buffer_subdata {
1590 struct pipe_resource *resource;
1591 unsigned usage, offset, size;
1592 char slot[0]; /* more will be allocated if needed */
1593 };
1594
1595 static void
1596 tc_call_buffer_subdata(struct pipe_context *pipe, union tc_payload *payload)
1597 {
1598 struct tc_buffer_subdata *p = (struct tc_buffer_subdata *)payload;
1599
1600 pipe->buffer_subdata(pipe, p->resource, p->usage, p->offset, p->size,
1601 p->slot);
1602 pipe_resource_reference(&p->resource, NULL);
1603 }
1604
1605 static void
1606 tc_buffer_subdata(struct pipe_context *_pipe,
1607 struct pipe_resource *resource,
1608 unsigned usage, unsigned offset,
1609 unsigned size, const void *data)
1610 {
1611 struct threaded_context *tc = threaded_context(_pipe);
1612 struct threaded_resource *tres = threaded_resource(resource);
1613
1614 if (!size)
1615 return;
1616
1617 usage |= PIPE_TRANSFER_WRITE |
1618 PIPE_TRANSFER_DISCARD_RANGE;
1619
1620 usage = tc_improve_map_buffer_flags(tc, tres, usage, offset, size);
1621
1622 /* Unsychronized and big transfers should use transfer_map. Also handle
1623 * full invalidations, because drivers aren't allowed to do them.
1624 */
1625 if (usage & (PIPE_TRANSFER_UNSYNCHRONIZED |
1626 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) ||
1627 size > TC_MAX_SUBDATA_BYTES) {
1628 struct pipe_transfer *transfer;
1629 struct pipe_box box;
1630 uint8_t *map = NULL;
1631
1632 u_box_1d(offset, size, &box);
1633
1634 map = tc_transfer_map(_pipe, resource, 0, usage, &box, &transfer);
1635 if (map) {
1636 memcpy(map, data, size);
1637 tc_transfer_unmap(_pipe, transfer);
1638 }
1639 return;
1640 }
1641
1642 util_range_add(&tres->valid_buffer_range, offset, offset + size);
1643
1644 /* The upload is small. Enqueue it. */
1645 struct tc_buffer_subdata *p =
1646 tc_add_slot_based_call(tc, TC_CALL_buffer_subdata, tc_buffer_subdata, size);
1647
1648 tc_set_resource_reference(&p->resource, resource);
1649 p->usage = usage;
1650 p->offset = offset;
1651 p->size = size;
1652 memcpy(p->slot, data, size);
1653 }
1654
1655 struct tc_texture_subdata {
1656 struct pipe_resource *resource;
1657 unsigned level, usage, stride, layer_stride;
1658 struct pipe_box box;
1659 char slot[0]; /* more will be allocated if needed */
1660 };
1661
1662 static void
1663 tc_call_texture_subdata(struct pipe_context *pipe, union tc_payload *payload)
1664 {
1665 struct tc_texture_subdata *p = (struct tc_texture_subdata *)payload;
1666
1667 pipe->texture_subdata(pipe, p->resource, p->level, p->usage, &p->box,
1668 p->slot, p->stride, p->layer_stride);
1669 pipe_resource_reference(&p->resource, NULL);
1670 }
1671
1672 static void
1673 tc_texture_subdata(struct pipe_context *_pipe,
1674 struct pipe_resource *resource,
1675 unsigned level, unsigned usage,
1676 const struct pipe_box *box,
1677 const void *data, unsigned stride,
1678 unsigned layer_stride)
1679 {
1680 struct threaded_context *tc = threaded_context(_pipe);
1681 unsigned size;
1682
1683 assert(box->height >= 1);
1684 assert(box->depth >= 1);
1685
1686 size = (box->depth - 1) * layer_stride +
1687 (box->height - 1) * stride +
1688 box->width * util_format_get_blocksize(resource->format);
1689 if (!size)
1690 return;
1691
1692 /* Small uploads can be enqueued, big uploads must sync. */
1693 if (size <= TC_MAX_SUBDATA_BYTES) {
1694 struct tc_texture_subdata *p =
1695 tc_add_slot_based_call(tc, TC_CALL_texture_subdata, tc_texture_subdata, size);
1696
1697 tc_set_resource_reference(&p->resource, resource);
1698 p->level = level;
1699 p->usage = usage;
1700 p->box = *box;
1701 p->stride = stride;
1702 p->layer_stride = layer_stride;
1703 memcpy(p->slot, data, size);
1704 } else {
1705 struct pipe_context *pipe = tc->pipe;
1706
1707 tc_sync(tc);
1708 pipe->texture_subdata(pipe, resource, level, usage, box, data,
1709 stride, layer_stride);
1710 }
1711 }
1712
1713
1714 /********************************************************************
1715 * miscellaneous
1716 */
1717
1718 #define TC_FUNC_SYNC_RET0(ret_type, func) \
1719 static ret_type \
1720 tc_##func(struct pipe_context *_pipe) \
1721 { \
1722 struct threaded_context *tc = threaded_context(_pipe); \
1723 struct pipe_context *pipe = tc->pipe; \
1724 tc_sync(tc); \
1725 return pipe->func(pipe); \
1726 }
1727
1728 TC_FUNC_SYNC_RET0(enum pipe_reset_status, get_device_reset_status)
1729 TC_FUNC_SYNC_RET0(uint64_t, get_timestamp)
1730
1731 static void
1732 tc_get_sample_position(struct pipe_context *_pipe,
1733 unsigned sample_count, unsigned sample_index,
1734 float *out_value)
1735 {
1736 struct threaded_context *tc = threaded_context(_pipe);
1737 struct pipe_context *pipe = tc->pipe;
1738
1739 tc_sync(tc);
1740 pipe->get_sample_position(pipe, sample_count, sample_index,
1741 out_value);
1742 }
1743
1744 static void
1745 tc_set_device_reset_callback(struct pipe_context *_pipe,
1746 const struct pipe_device_reset_callback *cb)
1747 {
1748 struct threaded_context *tc = threaded_context(_pipe);
1749 struct pipe_context *pipe = tc->pipe;
1750
1751 tc_sync(tc);
1752 pipe->set_device_reset_callback(pipe, cb);
1753 }
1754
1755 struct tc_string_marker {
1756 int len;
1757 char slot[0]; /* more will be allocated if needed */
1758 };
1759
1760 static void
1761 tc_call_emit_string_marker(struct pipe_context *pipe, union tc_payload *payload)
1762 {
1763 struct tc_string_marker *p = (struct tc_string_marker *)payload;
1764 pipe->emit_string_marker(pipe, p->slot, p->len);
1765 }
1766
1767 static void
1768 tc_emit_string_marker(struct pipe_context *_pipe,
1769 const char *string, int len)
1770 {
1771 struct threaded_context *tc = threaded_context(_pipe);
1772
1773 if (len <= TC_MAX_STRING_MARKER_BYTES) {
1774 struct tc_string_marker *p =
1775 tc_add_slot_based_call(tc, TC_CALL_emit_string_marker, tc_string_marker, len);
1776
1777 memcpy(p->slot, string, len);
1778 p->len = len;
1779 } else {
1780 struct pipe_context *pipe = tc->pipe;
1781
1782 tc_sync(tc);
1783 pipe->emit_string_marker(pipe, string, len);
1784 }
1785 }
1786
1787 static void
1788 tc_dump_debug_state(struct pipe_context *_pipe, FILE *stream,
1789 unsigned flags)
1790 {
1791 struct threaded_context *tc = threaded_context(_pipe);
1792 struct pipe_context *pipe = tc->pipe;
1793
1794 tc_sync(tc);
1795 pipe->dump_debug_state(pipe, stream, flags);
1796 }
1797
1798 static void
1799 tc_set_debug_callback(struct pipe_context *_pipe,
1800 const struct pipe_debug_callback *cb)
1801 {
1802 struct threaded_context *tc = threaded_context(_pipe);
1803 struct pipe_context *pipe = tc->pipe;
1804
1805 /* Drop all synchronous debug callbacks. Drivers are expected to be OK
1806 * with this. shader-db will use an environment variable to disable
1807 * the threaded context.
1808 */
1809 if (cb && cb->debug_message && !cb->async)
1810 return;
1811
1812 tc_sync(tc);
1813 pipe->set_debug_callback(pipe, cb);
1814 }
1815
1816 static void
1817 tc_set_log_context(struct pipe_context *_pipe, struct u_log_context *log)
1818 {
1819 struct threaded_context *tc = threaded_context(_pipe);
1820 struct pipe_context *pipe = tc->pipe;
1821
1822 tc_sync(tc);
1823 pipe->set_log_context(pipe, log);
1824 }
1825
1826 static void
1827 tc_create_fence_fd(struct pipe_context *_pipe,
1828 struct pipe_fence_handle **fence, int fd)
1829 {
1830 struct threaded_context *tc = threaded_context(_pipe);
1831 struct pipe_context *pipe = tc->pipe;
1832
1833 tc_sync(tc);
1834 pipe->create_fence_fd(pipe, fence, fd);
1835 }
1836
1837 static void
1838 tc_call_fence_server_sync(struct pipe_context *pipe, union tc_payload *payload)
1839 {
1840 pipe->fence_server_sync(pipe, payload->fence);
1841 pipe->screen->fence_reference(pipe->screen, &payload->fence, NULL);
1842 }
1843
1844 static void
1845 tc_fence_server_sync(struct pipe_context *_pipe,
1846 struct pipe_fence_handle *fence)
1847 {
1848 struct threaded_context *tc = threaded_context(_pipe);
1849 struct pipe_screen *screen = tc->pipe->screen;
1850 union tc_payload *payload = tc_add_small_call(tc, TC_CALL_fence_server_sync);
1851
1852 payload->fence = NULL;
1853 screen->fence_reference(screen, &payload->fence, fence);
1854 }
1855
1856 static struct pipe_video_codec *
1857 tc_create_video_codec(UNUSED struct pipe_context *_pipe,
1858 UNUSED const struct pipe_video_codec *templ)
1859 {
1860 unreachable("Threaded context should not be enabled for video APIs");
1861 return NULL;
1862 }
1863
1864 static struct pipe_video_buffer *
1865 tc_create_video_buffer(UNUSED struct pipe_context *_pipe,
1866 UNUSED const struct pipe_video_buffer *templ)
1867 {
1868 unreachable("Threaded context should not be enabled for video APIs");
1869 return NULL;
1870 }
1871
1872
1873 /********************************************************************
1874 * draw, launch, clear, blit, copy, flush
1875 */
1876
1877 struct tc_flush_payload {
1878 struct threaded_context *tc;
1879 struct pipe_fence_handle *fence;
1880 unsigned flags;
1881 };
1882
1883 static void
1884 tc_flush_queries(struct threaded_context *tc)
1885 {
1886 struct threaded_query *tq, *tmp;
1887 LIST_FOR_EACH_ENTRY_SAFE(tq, tmp, &tc->unflushed_queries, head_unflushed) {
1888 LIST_DEL(&tq->head_unflushed);
1889
1890 /* Memory release semantics: due to a possible race with
1891 * tc_get_query_result, we must ensure that the linked list changes
1892 * are visible before setting tq->flushed.
1893 */
1894 p_atomic_set(&tq->flushed, true);
1895 }
1896 }
1897
1898 static void
1899 tc_call_flush(struct pipe_context *pipe, union tc_payload *payload)
1900 {
1901 struct tc_flush_payload *p = (struct tc_flush_payload *)payload;
1902 struct pipe_screen *screen = pipe->screen;
1903
1904 pipe->flush(pipe, p->fence ? &p->fence : NULL, p->flags);
1905 screen->fence_reference(screen, &p->fence, NULL);
1906
1907 if (!(p->flags & PIPE_FLUSH_DEFERRED))
1908 tc_flush_queries(p->tc);
1909 }
1910
1911 static void
1912 tc_flush(struct pipe_context *_pipe, struct pipe_fence_handle **fence,
1913 unsigned flags)
1914 {
1915 struct threaded_context *tc = threaded_context(_pipe);
1916 struct pipe_context *pipe = tc->pipe;
1917 struct pipe_screen *screen = pipe->screen;
1918 bool async = flags & PIPE_FLUSH_DEFERRED;
1919
1920 if (flags & PIPE_FLUSH_ASYNC) {
1921 struct tc_batch *last = &tc->batch_slots[tc->last];
1922
1923 /* Prefer to do the flush in the driver thread, but avoid the inter-thread
1924 * communication overhead if the driver thread is currently idle and the
1925 * caller is going to wait for the fence immediately anyway.
1926 */
1927 if (!(util_queue_fence_is_signalled(&last->fence) &&
1928 (flags & PIPE_FLUSH_HINT_FINISH)))
1929 async = true;
1930 }
1931
1932 if (async && tc->create_fence) {
1933 if (fence) {
1934 struct tc_batch *next = &tc->batch_slots[tc->next];
1935
1936 if (!next->token) {
1937 next->token = malloc(sizeof(*next->token));
1938 if (!next->token)
1939 goto out_of_memory;
1940
1941 pipe_reference_init(&next->token->ref, 1);
1942 next->token->tc = tc;
1943 }
1944
1945 screen->fence_reference(screen, fence, tc->create_fence(pipe, next->token));
1946 if (!*fence)
1947 goto out_of_memory;
1948 }
1949
1950 struct tc_flush_payload *p =
1951 tc_add_struct_typed_call(tc, TC_CALL_flush, tc_flush_payload);
1952 p->tc = tc;
1953 p->fence = fence ? *fence : NULL;
1954 p->flags = flags | TC_FLUSH_ASYNC;
1955
1956 if (!(flags & PIPE_FLUSH_DEFERRED))
1957 tc_batch_flush(tc);
1958 return;
1959 }
1960
1961 out_of_memory:
1962 tc_sync_msg(tc, flags & PIPE_FLUSH_END_OF_FRAME ? "end of frame" :
1963 flags & PIPE_FLUSH_DEFERRED ? "deferred fence" : "normal");
1964
1965 if (!(flags & PIPE_FLUSH_DEFERRED))
1966 tc_flush_queries(tc);
1967 pipe->flush(pipe, fence, flags);
1968 }
1969
1970 /* This is actually variable-sized, because indirect isn't allocated if it's
1971 * not needed. */
1972 struct tc_full_draw_info {
1973 struct pipe_draw_info draw;
1974 struct pipe_draw_indirect_info indirect;
1975 };
1976
1977 static void
1978 tc_call_draw_vbo(struct pipe_context *pipe, union tc_payload *payload)
1979 {
1980 struct tc_full_draw_info *info = (struct tc_full_draw_info*)payload;
1981
1982 pipe->draw_vbo(pipe, &info->draw);
1983 pipe_so_target_reference(&info->draw.count_from_stream_output, NULL);
1984 if (info->draw.index_size)
1985 pipe_resource_reference(&info->draw.index.resource, NULL);
1986 if (info->draw.indirect) {
1987 pipe_resource_reference(&info->indirect.buffer, NULL);
1988 pipe_resource_reference(&info->indirect.indirect_draw_count, NULL);
1989 }
1990 }
1991
1992 static struct tc_full_draw_info *
1993 tc_add_draw_vbo(struct pipe_context *_pipe, bool indirect)
1994 {
1995 return (struct tc_full_draw_info*)
1996 tc_add_sized_call(threaded_context(_pipe), TC_CALL_draw_vbo,
1997 indirect ? sizeof(struct tc_full_draw_info) :
1998 sizeof(struct pipe_draw_info));
1999 }
2000
2001 static void
2002 tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info)
2003 {
2004 struct threaded_context *tc = threaded_context(_pipe);
2005 struct pipe_draw_indirect_info *indirect = info->indirect;
2006 unsigned index_size = info->index_size;
2007 bool has_user_indices = info->has_user_indices;
2008
2009 if (index_size && has_user_indices) {
2010 unsigned size = info->count * index_size;
2011 struct pipe_resource *buffer = NULL;
2012 unsigned offset;
2013
2014 tc_assert(!indirect);
2015
2016 /* This must be done before adding draw_vbo, because it could generate
2017 * e.g. transfer_unmap and flush partially-uninitialized draw_vbo
2018 * to the driver if it was done afterwards.
2019 */
2020 u_upload_data(tc->base.stream_uploader, 0, size, 4, info->index.user,
2021 &offset, &buffer);
2022 if (unlikely(!buffer))
2023 return;
2024
2025 struct tc_full_draw_info *p = tc_add_draw_vbo(_pipe, false);
2026 p->draw.count_from_stream_output = NULL;
2027 pipe_so_target_reference(&p->draw.count_from_stream_output,
2028 info->count_from_stream_output);
2029 memcpy(&p->draw, info, sizeof(*info));
2030 p->draw.has_user_indices = false;
2031 p->draw.index.resource = buffer;
2032 p->draw.start = offset / index_size;
2033 } else {
2034 /* Non-indexed call or indexed with a real index buffer. */
2035 struct tc_full_draw_info *p = tc_add_draw_vbo(_pipe, indirect != NULL);
2036 p->draw.count_from_stream_output = NULL;
2037 pipe_so_target_reference(&p->draw.count_from_stream_output,
2038 info->count_from_stream_output);
2039 if (index_size) {
2040 tc_set_resource_reference(&p->draw.index.resource,
2041 info->index.resource);
2042 }
2043 memcpy(&p->draw, info, sizeof(*info));
2044
2045 if (indirect) {
2046 tc_set_resource_reference(&p->draw.indirect->buffer, indirect->buffer);
2047 tc_set_resource_reference(&p->indirect.indirect_draw_count,
2048 indirect->indirect_draw_count);
2049 memcpy(&p->indirect, indirect, sizeof(*indirect));
2050 p->draw.indirect = &p->indirect;
2051 }
2052 }
2053 }
2054
2055 static void
2056 tc_call_launch_grid(struct pipe_context *pipe, union tc_payload *payload)
2057 {
2058 struct pipe_grid_info *p = (struct pipe_grid_info *)payload;
2059
2060 pipe->launch_grid(pipe, p);
2061 pipe_resource_reference(&p->indirect, NULL);
2062 }
2063
2064 static void
2065 tc_launch_grid(struct pipe_context *_pipe,
2066 const struct pipe_grid_info *info)
2067 {
2068 struct threaded_context *tc = threaded_context(_pipe);
2069 struct pipe_grid_info *p = tc_add_struct_typed_call(tc, TC_CALL_launch_grid,
2070 pipe_grid_info);
2071 assert(info->input == NULL);
2072
2073 tc_set_resource_reference(&p->indirect, info->indirect);
2074 memcpy(p, info, sizeof(*info));
2075 }
2076
2077 static void
2078 tc_call_resource_copy_region(struct pipe_context *pipe, union tc_payload *payload)
2079 {
2080 struct tc_resource_copy_region *p = (struct tc_resource_copy_region *)payload;
2081
2082 pipe->resource_copy_region(pipe, p->dst, p->dst_level, p->dstx, p->dsty,
2083 p->dstz, p->src, p->src_level, &p->src_box);
2084 pipe_resource_reference(&p->dst, NULL);
2085 pipe_resource_reference(&p->src, NULL);
2086 }
2087
2088 static void
2089 tc_resource_copy_region(struct pipe_context *_pipe,
2090 struct pipe_resource *dst, unsigned dst_level,
2091 unsigned dstx, unsigned dsty, unsigned dstz,
2092 struct pipe_resource *src, unsigned src_level,
2093 const struct pipe_box *src_box)
2094 {
2095 struct threaded_context *tc = threaded_context(_pipe);
2096 struct threaded_resource *tdst = threaded_resource(dst);
2097 struct tc_resource_copy_region *p =
2098 tc_add_struct_typed_call(tc, TC_CALL_resource_copy_region,
2099 tc_resource_copy_region);
2100
2101 tc_set_resource_reference(&p->dst, dst);
2102 p->dst_level = dst_level;
2103 p->dstx = dstx;
2104 p->dsty = dsty;
2105 p->dstz = dstz;
2106 tc_set_resource_reference(&p->src, src);
2107 p->src_level = src_level;
2108 p->src_box = *src_box;
2109
2110 if (dst->target == PIPE_BUFFER)
2111 util_range_add(&tdst->valid_buffer_range, dstx, dstx + src_box->width);
2112 }
2113
2114 static void
2115 tc_call_blit(struct pipe_context *pipe, union tc_payload *payload)
2116 {
2117 struct pipe_blit_info *blit = (struct pipe_blit_info*)payload;
2118
2119 pipe->blit(pipe, blit);
2120 pipe_resource_reference(&blit->dst.resource, NULL);
2121 pipe_resource_reference(&blit->src.resource, NULL);
2122 }
2123
2124 static void
2125 tc_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
2126 {
2127 struct threaded_context *tc = threaded_context(_pipe);
2128 struct pipe_blit_info *blit =
2129 tc_add_struct_typed_call(tc, TC_CALL_blit, pipe_blit_info);
2130
2131 tc_set_resource_reference(&blit->dst.resource, info->dst.resource);
2132 tc_set_resource_reference(&blit->src.resource, info->src.resource);
2133 memcpy(blit, info, sizeof(*info));
2134 }
2135
2136 struct tc_generate_mipmap {
2137 struct pipe_resource *res;
2138 enum pipe_format format;
2139 unsigned base_level;
2140 unsigned last_level;
2141 unsigned first_layer;
2142 unsigned last_layer;
2143 };
2144
2145 static void
2146 tc_call_generate_mipmap(struct pipe_context *pipe, union tc_payload *payload)
2147 {
2148 struct tc_generate_mipmap *p = (struct tc_generate_mipmap *)payload;
2149 MAYBE_UNUSED bool result = pipe->generate_mipmap(pipe, p->res, p->format,
2150 p->base_level,
2151 p->last_level,
2152 p->first_layer,
2153 p->last_layer);
2154 assert(result);
2155 pipe_resource_reference(&p->res, NULL);
2156 }
2157
2158 static boolean
2159 tc_generate_mipmap(struct pipe_context *_pipe,
2160 struct pipe_resource *res,
2161 enum pipe_format format,
2162 unsigned base_level,
2163 unsigned last_level,
2164 unsigned first_layer,
2165 unsigned last_layer)
2166 {
2167 struct threaded_context *tc = threaded_context(_pipe);
2168 struct pipe_context *pipe = tc->pipe;
2169 struct pipe_screen *screen = pipe->screen;
2170 unsigned bind = PIPE_BIND_SAMPLER_VIEW;
2171
2172 if (util_format_is_depth_or_stencil(format))
2173 bind = PIPE_BIND_DEPTH_STENCIL;
2174 else
2175 bind = PIPE_BIND_RENDER_TARGET;
2176
2177 if (!screen->is_format_supported(screen, format, res->target,
2178 res->nr_samples, bind))
2179 return false;
2180
2181 struct tc_generate_mipmap *p =
2182 tc_add_struct_typed_call(tc, TC_CALL_generate_mipmap, tc_generate_mipmap);
2183
2184 tc_set_resource_reference(&p->res, res);
2185 p->format = format;
2186 p->base_level = base_level;
2187 p->last_level = last_level;
2188 p->first_layer = first_layer;
2189 p->last_layer = last_layer;
2190 return true;
2191 }
2192
2193 static void
2194 tc_call_flush_resource(struct pipe_context *pipe, union tc_payload *payload)
2195 {
2196 pipe->flush_resource(pipe, payload->resource);
2197 pipe_resource_reference(&payload->resource, NULL);
2198 }
2199
2200 static void
2201 tc_flush_resource(struct pipe_context *_pipe,
2202 struct pipe_resource *resource)
2203 {
2204 struct threaded_context *tc = threaded_context(_pipe);
2205 union tc_payload *payload = tc_add_small_call(tc, TC_CALL_flush_resource);
2206
2207 tc_set_resource_reference(&payload->resource, resource);
2208 }
2209
2210 static void
2211 tc_call_invalidate_resource(struct pipe_context *pipe, union tc_payload *payload)
2212 {
2213 pipe->invalidate_resource(pipe, payload->resource);
2214 pipe_resource_reference(&payload->resource, NULL);
2215 }
2216
2217 static void
2218 tc_invalidate_resource(struct pipe_context *_pipe,
2219 struct pipe_resource *resource)
2220 {
2221 struct threaded_context *tc = threaded_context(_pipe);
2222
2223 if (resource->target == PIPE_BUFFER) {
2224 tc_invalidate_buffer(tc, threaded_resource(resource));
2225 return;
2226 }
2227
2228 union tc_payload *payload = tc_add_small_call(tc, TC_CALL_invalidate_resource);
2229 tc_set_resource_reference(&payload->resource, resource);
2230 }
2231
2232 struct tc_clear {
2233 unsigned buffers;
2234 union pipe_color_union color;
2235 double depth;
2236 unsigned stencil;
2237 };
2238
2239 static void
2240 tc_call_clear(struct pipe_context *pipe, union tc_payload *payload)
2241 {
2242 struct tc_clear *p = (struct tc_clear *)payload;
2243 pipe->clear(pipe, p->buffers, &p->color, p->depth, p->stencil);
2244 }
2245
2246 static void
2247 tc_clear(struct pipe_context *_pipe, unsigned buffers,
2248 const union pipe_color_union *color, double depth,
2249 unsigned stencil)
2250 {
2251 struct threaded_context *tc = threaded_context(_pipe);
2252 struct tc_clear *p = tc_add_struct_typed_call(tc, TC_CALL_clear, tc_clear);
2253
2254 p->buffers = buffers;
2255 p->color = *color;
2256 p->depth = depth;
2257 p->stencil = stencil;
2258 }
2259
2260 static void
2261 tc_clear_render_target(struct pipe_context *_pipe,
2262 struct pipe_surface *dst,
2263 const union pipe_color_union *color,
2264 unsigned dstx, unsigned dsty,
2265 unsigned width, unsigned height,
2266 bool render_condition_enabled)
2267 {
2268 struct threaded_context *tc = threaded_context(_pipe);
2269 struct pipe_context *pipe = tc->pipe;
2270
2271 tc_sync(tc);
2272 pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height,
2273 render_condition_enabled);
2274 }
2275
2276 static void
2277 tc_clear_depth_stencil(struct pipe_context *_pipe,
2278 struct pipe_surface *dst, unsigned clear_flags,
2279 double depth, unsigned stencil, unsigned dstx,
2280 unsigned dsty, unsigned width, unsigned height,
2281 bool render_condition_enabled)
2282 {
2283 struct threaded_context *tc = threaded_context(_pipe);
2284 struct pipe_context *pipe = tc->pipe;
2285
2286 tc_sync(tc);
2287 pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil,
2288 dstx, dsty, width, height,
2289 render_condition_enabled);
2290 }
2291
2292 struct tc_clear_buffer {
2293 struct pipe_resource *res;
2294 unsigned offset;
2295 unsigned size;
2296 char clear_value[16];
2297 int clear_value_size;
2298 };
2299
2300 static void
2301 tc_call_clear_buffer(struct pipe_context *pipe, union tc_payload *payload)
2302 {
2303 struct tc_clear_buffer *p = (struct tc_clear_buffer *)payload;
2304
2305 pipe->clear_buffer(pipe, p->res, p->offset, p->size, p->clear_value,
2306 p->clear_value_size);
2307 pipe_resource_reference(&p->res, NULL);
2308 }
2309
2310 static void
2311 tc_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res,
2312 unsigned offset, unsigned size,
2313 const void *clear_value, int clear_value_size)
2314 {
2315 struct threaded_context *tc = threaded_context(_pipe);
2316 struct threaded_resource *tres = threaded_resource(res);
2317 struct tc_clear_buffer *p =
2318 tc_add_struct_typed_call(tc, TC_CALL_clear_buffer, tc_clear_buffer);
2319
2320 tc_set_resource_reference(&p->res, res);
2321 p->offset = offset;
2322 p->size = size;
2323 memcpy(p->clear_value, clear_value, clear_value_size);
2324 p->clear_value_size = clear_value_size;
2325
2326 util_range_add(&tres->valid_buffer_range, offset, offset + size);
2327 }
2328
2329 struct tc_clear_texture {
2330 struct pipe_resource *res;
2331 unsigned level;
2332 struct pipe_box box;
2333 char data[16];
2334 };
2335
2336 static void
2337 tc_call_clear_texture(struct pipe_context *pipe, union tc_payload *payload)
2338 {
2339 struct tc_clear_texture *p = (struct tc_clear_texture *)payload;
2340
2341 pipe->clear_texture(pipe, p->res, p->level, &p->box, p->data);
2342 pipe_resource_reference(&p->res, NULL);
2343 }
2344
2345 static void
2346 tc_clear_texture(struct pipe_context *_pipe, struct pipe_resource *res,
2347 unsigned level, const struct pipe_box *box, const void *data)
2348 {
2349 struct threaded_context *tc = threaded_context(_pipe);
2350 struct tc_clear_texture *p =
2351 tc_add_struct_typed_call(tc, TC_CALL_clear_texture, tc_clear_texture);
2352
2353 tc_set_resource_reference(&p->res, res);
2354 p->level = level;
2355 p->box = *box;
2356 memcpy(p->data, data,
2357 util_format_get_blocksize(res->format));
2358 }
2359
2360 struct tc_resource_commit {
2361 struct pipe_resource *res;
2362 unsigned level;
2363 struct pipe_box box;
2364 bool commit;
2365 };
2366
2367 static void
2368 tc_call_resource_commit(struct pipe_context *pipe, union tc_payload *payload)
2369 {
2370 struct tc_resource_commit *p = (struct tc_resource_commit *)payload;
2371
2372 pipe->resource_commit(pipe, p->res, p->level, &p->box, p->commit);
2373 pipe_resource_reference(&p->res, NULL);
2374 }
2375
2376 static bool
2377 tc_resource_commit(struct pipe_context *_pipe, struct pipe_resource *res,
2378 unsigned level, struct pipe_box *box, bool commit)
2379 {
2380 struct threaded_context *tc = threaded_context(_pipe);
2381 struct tc_resource_commit *p =
2382 tc_add_struct_typed_call(tc, TC_CALL_resource_commit, tc_resource_commit);
2383
2384 tc_set_resource_reference(&p->res, res);
2385 p->level = level;
2386 p->box = *box;
2387 p->commit = commit;
2388 return true; /* we don't care about the return value for this call */
2389 }
2390
2391
2392 /********************************************************************
2393 * callback
2394 */
2395
2396 struct tc_callback_payload {
2397 void (*fn)(void *data);
2398 void *data;
2399 };
2400
2401 static void
2402 tc_call_callback(UNUSED struct pipe_context *pipe, union tc_payload *payload)
2403 {
2404 struct tc_callback_payload *p = (struct tc_callback_payload *)payload;
2405
2406 p->fn(p->data);
2407 }
2408
2409 static void
2410 tc_callback(struct pipe_context *_pipe, void (*fn)(void *), void *data,
2411 bool asap)
2412 {
2413 struct threaded_context *tc = threaded_context(_pipe);
2414
2415 if (asap && tc_is_sync(tc)) {
2416 fn(data);
2417 return;
2418 }
2419
2420 struct tc_callback_payload *p =
2421 tc_add_struct_typed_call(tc, TC_CALL_callback, tc_callback_payload);
2422 p->fn = fn;
2423 p->data = data;
2424 }
2425
2426
2427 /********************************************************************
2428 * create & destroy
2429 */
2430
2431 static void
2432 tc_destroy(struct pipe_context *_pipe)
2433 {
2434 struct threaded_context *tc = threaded_context(_pipe);
2435 struct pipe_context *pipe = tc->pipe;
2436
2437 if (tc->base.const_uploader &&
2438 tc->base.stream_uploader != tc->base.const_uploader)
2439 u_upload_destroy(tc->base.const_uploader);
2440
2441 if (tc->base.stream_uploader)
2442 u_upload_destroy(tc->base.stream_uploader);
2443
2444 tc_sync(tc);
2445
2446 if (util_queue_is_initialized(&tc->queue)) {
2447 util_queue_destroy(&tc->queue);
2448
2449 for (unsigned i = 0; i < TC_MAX_BATCHES; i++) {
2450 util_queue_fence_destroy(&tc->batch_slots[i].fence);
2451 assert(!tc->batch_slots[i].token);
2452 }
2453 }
2454
2455 slab_destroy_child(&tc->pool_transfers);
2456 assert(tc->batch_slots[tc->next].num_total_call_slots == 0);
2457 pipe->destroy(pipe);
2458 os_free_aligned(tc);
2459 }
2460
2461 static const tc_execute execute_func[TC_NUM_CALLS] = {
2462 #define CALL(name) tc_call_##name,
2463 #include "u_threaded_context_calls.h"
2464 #undef CALL
2465 };
2466
2467 /**
2468 * Wrap an existing pipe_context into a threaded_context.
2469 *
2470 * \param pipe pipe_context to wrap
2471 * \param parent_transfer_pool parent slab pool set up for creating pipe_-
2472 * transfer objects; the driver should have one
2473 * in pipe_screen.
2474 * \param replace_buffer callback for replacing a pipe_resource's storage
2475 * with another pipe_resource's storage.
2476 * \param out if successful, the threaded_context will be returned here in
2477 * addition to the return value if "out" != NULL
2478 */
2479 struct pipe_context *
2480 threaded_context_create(struct pipe_context *pipe,
2481 struct slab_parent_pool *parent_transfer_pool,
2482 tc_replace_buffer_storage_func replace_buffer,
2483 tc_create_fence_func create_fence,
2484 struct threaded_context **out)
2485 {
2486 struct threaded_context *tc;
2487
2488 STATIC_ASSERT(sizeof(union tc_payload) <= 8);
2489 STATIC_ASSERT(sizeof(struct tc_call) <= 16);
2490
2491 if (!pipe)
2492 return NULL;
2493
2494 util_cpu_detect();
2495
2496 if (!debug_get_bool_option("GALLIUM_THREAD", util_cpu_caps.nr_cpus > 1))
2497 return pipe;
2498
2499 tc = os_malloc_aligned(sizeof(struct threaded_context), 16);
2500 if (!tc) {
2501 pipe->destroy(pipe);
2502 return NULL;
2503 }
2504 memset(tc, 0, sizeof(*tc));
2505
2506 assert((uintptr_t)tc % 16 == 0);
2507 /* These should be static asserts, but they don't work with MSVC */
2508 assert(offsetof(struct threaded_context, batch_slots) % 16 == 0);
2509 assert(offsetof(struct threaded_context, batch_slots[0].call) % 16 == 0);
2510 assert(offsetof(struct threaded_context, batch_slots[0].call[1]) % 16 == 0);
2511 assert(offsetof(struct threaded_context, batch_slots[1].call) % 16 == 0);
2512
2513 /* The driver context isn't wrapped, so set its "priv" to NULL. */
2514 pipe->priv = NULL;
2515
2516 tc->pipe = pipe;
2517 tc->replace_buffer_storage = replace_buffer;
2518 tc->create_fence = create_fence;
2519 tc->map_buffer_alignment =
2520 pipe->screen->get_param(pipe->screen, PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT);
2521 tc->base.priv = pipe; /* priv points to the wrapped driver context */
2522 tc->base.screen = pipe->screen;
2523 tc->base.destroy = tc_destroy;
2524 tc->base.callback = tc_callback;
2525
2526 tc->base.stream_uploader = u_upload_clone(&tc->base, pipe->stream_uploader);
2527 if (pipe->stream_uploader == pipe->const_uploader)
2528 tc->base.const_uploader = tc->base.stream_uploader;
2529 else
2530 tc->base.const_uploader = u_upload_clone(&tc->base, pipe->const_uploader);
2531
2532 if (!tc->base.stream_uploader || !tc->base.const_uploader)
2533 goto fail;
2534
2535 /* The queue size is the number of batches "waiting". Batches are removed
2536 * from the queue before being executed, so keep one tc_batch slot for that
2537 * execution. Also, keep one unused slot for an unflushed batch.
2538 */
2539 if (!util_queue_init(&tc->queue, "gallium_drv", TC_MAX_BATCHES - 2, 1, 0))
2540 goto fail;
2541
2542 for (unsigned i = 0; i < TC_MAX_BATCHES; i++) {
2543 tc->batch_slots[i].sentinel = TC_SENTINEL;
2544 tc->batch_slots[i].pipe = pipe;
2545 util_queue_fence_init(&tc->batch_slots[i].fence);
2546 }
2547
2548 LIST_INITHEAD(&tc->unflushed_queries);
2549
2550 slab_create_child(&tc->pool_transfers, parent_transfer_pool);
2551
2552 #define CTX_INIT(_member) \
2553 tc->base._member = tc->pipe->_member ? tc_##_member : NULL
2554
2555 CTX_INIT(flush);
2556 CTX_INIT(draw_vbo);
2557 CTX_INIT(launch_grid);
2558 CTX_INIT(resource_copy_region);
2559 CTX_INIT(blit);
2560 CTX_INIT(clear);
2561 CTX_INIT(clear_render_target);
2562 CTX_INIT(clear_depth_stencil);
2563 CTX_INIT(clear_buffer);
2564 CTX_INIT(clear_texture);
2565 CTX_INIT(flush_resource);
2566 CTX_INIT(generate_mipmap);
2567 CTX_INIT(render_condition);
2568 CTX_INIT(create_query);
2569 CTX_INIT(create_batch_query);
2570 CTX_INIT(destroy_query);
2571 CTX_INIT(begin_query);
2572 CTX_INIT(end_query);
2573 CTX_INIT(get_query_result);
2574 CTX_INIT(get_query_result_resource);
2575 CTX_INIT(set_active_query_state);
2576 CTX_INIT(create_blend_state);
2577 CTX_INIT(bind_blend_state);
2578 CTX_INIT(delete_blend_state);
2579 CTX_INIT(create_sampler_state);
2580 CTX_INIT(bind_sampler_states);
2581 CTX_INIT(delete_sampler_state);
2582 CTX_INIT(create_rasterizer_state);
2583 CTX_INIT(bind_rasterizer_state);
2584 CTX_INIT(delete_rasterizer_state);
2585 CTX_INIT(create_depth_stencil_alpha_state);
2586 CTX_INIT(bind_depth_stencil_alpha_state);
2587 CTX_INIT(delete_depth_stencil_alpha_state);
2588 CTX_INIT(create_fs_state);
2589 CTX_INIT(bind_fs_state);
2590 CTX_INIT(delete_fs_state);
2591 CTX_INIT(create_vs_state);
2592 CTX_INIT(bind_vs_state);
2593 CTX_INIT(delete_vs_state);
2594 CTX_INIT(create_gs_state);
2595 CTX_INIT(bind_gs_state);
2596 CTX_INIT(delete_gs_state);
2597 CTX_INIT(create_tcs_state);
2598 CTX_INIT(bind_tcs_state);
2599 CTX_INIT(delete_tcs_state);
2600 CTX_INIT(create_tes_state);
2601 CTX_INIT(bind_tes_state);
2602 CTX_INIT(delete_tes_state);
2603 CTX_INIT(create_compute_state);
2604 CTX_INIT(bind_compute_state);
2605 CTX_INIT(delete_compute_state);
2606 CTX_INIT(create_vertex_elements_state);
2607 CTX_INIT(bind_vertex_elements_state);
2608 CTX_INIT(delete_vertex_elements_state);
2609 CTX_INIT(set_blend_color);
2610 CTX_INIT(set_stencil_ref);
2611 CTX_INIT(set_sample_mask);
2612 CTX_INIT(set_min_samples);
2613 CTX_INIT(set_clip_state);
2614 CTX_INIT(set_constant_buffer);
2615 CTX_INIT(set_framebuffer_state);
2616 CTX_INIT(set_polygon_stipple);
2617 CTX_INIT(set_scissor_states);
2618 CTX_INIT(set_viewport_states);
2619 CTX_INIT(set_window_rectangles);
2620 CTX_INIT(set_sampler_views);
2621 CTX_INIT(set_tess_state);
2622 CTX_INIT(set_shader_buffers);
2623 CTX_INIT(set_shader_images);
2624 CTX_INIT(set_vertex_buffers);
2625 CTX_INIT(create_stream_output_target);
2626 CTX_INIT(stream_output_target_destroy);
2627 CTX_INIT(set_stream_output_targets);
2628 CTX_INIT(create_sampler_view);
2629 CTX_INIT(sampler_view_destroy);
2630 CTX_INIT(create_surface);
2631 CTX_INIT(surface_destroy);
2632 CTX_INIT(transfer_map);
2633 CTX_INIT(transfer_flush_region);
2634 CTX_INIT(transfer_unmap);
2635 CTX_INIT(buffer_subdata);
2636 CTX_INIT(texture_subdata);
2637 CTX_INIT(texture_barrier);
2638 CTX_INIT(memory_barrier);
2639 CTX_INIT(resource_commit);
2640 CTX_INIT(create_video_codec);
2641 CTX_INIT(create_video_buffer);
2642 CTX_INIT(set_compute_resources);
2643 CTX_INIT(set_global_binding);
2644 CTX_INIT(get_sample_position);
2645 CTX_INIT(invalidate_resource);
2646 CTX_INIT(get_device_reset_status);
2647 CTX_INIT(set_device_reset_callback);
2648 CTX_INIT(dump_debug_state);
2649 CTX_INIT(set_log_context);
2650 CTX_INIT(emit_string_marker);
2651 CTX_INIT(set_debug_callback);
2652 CTX_INIT(create_fence_fd);
2653 CTX_INIT(fence_server_sync);
2654 CTX_INIT(get_timestamp);
2655 CTX_INIT(create_texture_handle);
2656 CTX_INIT(delete_texture_handle);
2657 CTX_INIT(make_texture_handle_resident);
2658 CTX_INIT(create_image_handle);
2659 CTX_INIT(delete_image_handle);
2660 CTX_INIT(make_image_handle_resident);
2661 #undef CTX_INIT
2662
2663 if (out)
2664 *out = tc;
2665
2666 return &tc->base;
2667
2668 fail:
2669 tc_destroy(&tc->base);
2670 return NULL;
2671 }