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