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