1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2017 Advanced Micro Devices, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 10bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 11bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 14bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 15bf215546Sopenharmony_ci * Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 21bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 24bf215546Sopenharmony_ci * 25bf215546Sopenharmony_ci **************************************************************************/ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "util/u_threaded_context.h" 28bf215546Sopenharmony_ci#include "util/u_cpu_detect.h" 29bf215546Sopenharmony_ci#include "util/format/u_format.h" 30bf215546Sopenharmony_ci#include "util/u_inlines.h" 31bf215546Sopenharmony_ci#include "util/u_memory.h" 32bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 33bf215546Sopenharmony_ci#include "driver_trace/tr_context.h" 34bf215546Sopenharmony_ci#include "util/log.h" 35bf215546Sopenharmony_ci#include "compiler/shader_info.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#if TC_DEBUG >= 1 38bf215546Sopenharmony_ci#define tc_assert assert 39bf215546Sopenharmony_ci#else 40bf215546Sopenharmony_ci#define tc_assert(x) 41bf215546Sopenharmony_ci#endif 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci#if TC_DEBUG >= 2 44bf215546Sopenharmony_ci#define tc_printf mesa_logi 45bf215546Sopenharmony_ci#define tc_asprintf asprintf 46bf215546Sopenharmony_ci#define tc_strcmp strcmp 47bf215546Sopenharmony_ci#else 48bf215546Sopenharmony_ci#define tc_printf(...) 49bf215546Sopenharmony_ci#define tc_asprintf(...) 0 50bf215546Sopenharmony_ci#define tc_strcmp(...) 0 51bf215546Sopenharmony_ci#endif 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci#define TC_SENTINEL 0x5ca1ab1e 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cienum tc_call_id { 56bf215546Sopenharmony_ci#define CALL(name) TC_CALL_##name, 57bf215546Sopenharmony_ci#include "u_threaded_context_calls.h" 58bf215546Sopenharmony_ci#undef CALL 59bf215546Sopenharmony_ci TC_NUM_CALLS, 60bf215546Sopenharmony_ci}; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci#if TC_DEBUG >= 3 63bf215546Sopenharmony_cistatic const char *tc_call_names[] = { 64bf215546Sopenharmony_ci#define CALL(name) #name, 65bf215546Sopenharmony_ci#include "u_threaded_context_calls.h" 66bf215546Sopenharmony_ci#undef CALL 67bf215546Sopenharmony_ci}; 68bf215546Sopenharmony_ci#endif 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_citypedef uint16_t (*tc_execute)(struct pipe_context *pipe, void *call, uint64_t *last); 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_cistatic const tc_execute execute_func[TC_NUM_CALLS]; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_cistatic void 75bf215546Sopenharmony_citc_buffer_subdata(struct pipe_context *_pipe, 76bf215546Sopenharmony_ci struct pipe_resource *resource, 77bf215546Sopenharmony_ci unsigned usage, unsigned offset, 78bf215546Sopenharmony_ci unsigned size, const void *data); 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_cistatic void 81bf215546Sopenharmony_citc_batch_check(UNUSED struct tc_batch *batch) 82bf215546Sopenharmony_ci{ 83bf215546Sopenharmony_ci tc_assert(batch->sentinel == TC_SENTINEL); 84bf215546Sopenharmony_ci tc_assert(batch->num_total_slots <= TC_SLOTS_PER_BATCH); 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cistatic void 88bf215546Sopenharmony_citc_debug_check(struct threaded_context *tc) 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci for (unsigned i = 0; i < TC_MAX_BATCHES; i++) { 91bf215546Sopenharmony_ci tc_batch_check(&tc->batch_slots[i]); 92bf215546Sopenharmony_ci tc_assert(tc->batch_slots[i].tc == tc); 93bf215546Sopenharmony_ci } 94bf215546Sopenharmony_ci} 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_cistatic void 97bf215546Sopenharmony_citc_set_driver_thread(struct threaded_context *tc) 98bf215546Sopenharmony_ci{ 99bf215546Sopenharmony_ci#ifndef NDEBUG 100bf215546Sopenharmony_ci tc->driver_thread = util_get_thread_id(); 101bf215546Sopenharmony_ci#endif 102bf215546Sopenharmony_ci} 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_cistatic void 105bf215546Sopenharmony_citc_clear_driver_thread(struct threaded_context *tc) 106bf215546Sopenharmony_ci{ 107bf215546Sopenharmony_ci#ifndef NDEBUG 108bf215546Sopenharmony_ci memset(&tc->driver_thread, 0, sizeof(tc->driver_thread)); 109bf215546Sopenharmony_ci#endif 110bf215546Sopenharmony_ci} 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_cistatic void * 113bf215546Sopenharmony_cito_call_check(void *ptr, unsigned num_slots) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci#if TC_DEBUG >= 1 116bf215546Sopenharmony_ci struct tc_call_base *call = ptr; 117bf215546Sopenharmony_ci tc_assert(call->num_slots == num_slots); 118bf215546Sopenharmony_ci#endif 119bf215546Sopenharmony_ci return ptr; 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci#define to_call(ptr, type) ((struct type *)to_call_check((void *)(ptr), call_size(type))) 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci#define size_to_slots(size) DIV_ROUND_UP(size, 8) 124bf215546Sopenharmony_ci#define call_size(type) size_to_slots(sizeof(struct type)) 125bf215546Sopenharmony_ci#define call_size_with_slots(type, num_slots) size_to_slots( \ 126bf215546Sopenharmony_ci sizeof(struct type) + sizeof(((struct type*)NULL)->slot[0]) * (num_slots)) 127bf215546Sopenharmony_ci#define get_next_call(ptr, type) ((struct type*)((uint64_t*)ptr + call_size(type))) 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci/* Assign src to dst while dst is uninitialized. */ 130bf215546Sopenharmony_cistatic inline void 131bf215546Sopenharmony_citc_set_resource_reference(struct pipe_resource **dst, struct pipe_resource *src) 132bf215546Sopenharmony_ci{ 133bf215546Sopenharmony_ci *dst = src; 134bf215546Sopenharmony_ci pipe_reference(NULL, &src->reference); /* only increment refcount */ 135bf215546Sopenharmony_ci} 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci/* Assign src to dst while dst is uninitialized. */ 138bf215546Sopenharmony_cistatic inline void 139bf215546Sopenharmony_citc_set_vertex_state_reference(struct pipe_vertex_state **dst, 140bf215546Sopenharmony_ci struct pipe_vertex_state *src) 141bf215546Sopenharmony_ci{ 142bf215546Sopenharmony_ci *dst = src; 143bf215546Sopenharmony_ci pipe_reference(NULL, &src->reference); /* only increment refcount */ 144bf215546Sopenharmony_ci} 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci/* Unreference dst but don't touch the dst pointer. */ 147bf215546Sopenharmony_cistatic inline void 148bf215546Sopenharmony_citc_drop_resource_reference(struct pipe_resource *dst) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci if (pipe_reference(&dst->reference, NULL)) /* only decrement refcount */ 151bf215546Sopenharmony_ci pipe_resource_destroy(dst); 152bf215546Sopenharmony_ci} 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci/* Unreference dst but don't touch the dst pointer. */ 155bf215546Sopenharmony_cistatic inline void 156bf215546Sopenharmony_citc_drop_surface_reference(struct pipe_surface *dst) 157bf215546Sopenharmony_ci{ 158bf215546Sopenharmony_ci if (pipe_reference(&dst->reference, NULL)) /* only decrement refcount */ 159bf215546Sopenharmony_ci dst->context->surface_destroy(dst->context, dst); 160bf215546Sopenharmony_ci} 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci/* Unreference dst but don't touch the dst pointer. */ 163bf215546Sopenharmony_cistatic inline void 164bf215546Sopenharmony_citc_drop_so_target_reference(struct pipe_stream_output_target *dst) 165bf215546Sopenharmony_ci{ 166bf215546Sopenharmony_ci if (pipe_reference(&dst->reference, NULL)) /* only decrement refcount */ 167bf215546Sopenharmony_ci dst->context->stream_output_target_destroy(dst->context, dst); 168bf215546Sopenharmony_ci} 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci/** 171bf215546Sopenharmony_ci * Subtract the given number of references. 172bf215546Sopenharmony_ci */ 173bf215546Sopenharmony_cistatic inline void 174bf215546Sopenharmony_citc_drop_vertex_state_references(struct pipe_vertex_state *dst, int num_refs) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci int count = p_atomic_add_return(&dst->reference.count, -num_refs); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci assert(count >= 0); 179bf215546Sopenharmony_ci /* Underflows shouldn't happen, but let's be safe. */ 180bf215546Sopenharmony_ci if (count <= 0) 181bf215546Sopenharmony_ci dst->screen->vertex_state_destroy(dst->screen, dst); 182bf215546Sopenharmony_ci} 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci/* We don't want to read or write min_index and max_index, because 185bf215546Sopenharmony_ci * it shouldn't be needed by drivers at this point. 186bf215546Sopenharmony_ci */ 187bf215546Sopenharmony_ci#define DRAW_INFO_SIZE_WITHOUT_MIN_MAX_INDEX \ 188bf215546Sopenharmony_ci offsetof(struct pipe_draw_info, min_index) 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic void 191bf215546Sopenharmony_citc_batch_execute(void *job, UNUSED void *gdata, int thread_index) 192bf215546Sopenharmony_ci{ 193bf215546Sopenharmony_ci struct tc_batch *batch = job; 194bf215546Sopenharmony_ci struct pipe_context *pipe = batch->tc->pipe; 195bf215546Sopenharmony_ci uint64_t *last = &batch->slots[batch->num_total_slots]; 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci tc_batch_check(batch); 198bf215546Sopenharmony_ci tc_set_driver_thread(batch->tc); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci assert(!batch->token); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci for (uint64_t *iter = batch->slots; iter != last;) { 203bf215546Sopenharmony_ci struct tc_call_base *call = (struct tc_call_base *)iter; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci tc_assert(call->sentinel == TC_SENTINEL); 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci#if TC_DEBUG >= 3 208bf215546Sopenharmony_ci tc_printf("CALL: %s", tc_call_names[call->call_id]); 209bf215546Sopenharmony_ci#endif 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci iter += execute_func[call->call_id](pipe, call, last); 212bf215546Sopenharmony_ci } 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci /* Add the fence to the list of fences for the driver to signal at the next 215bf215546Sopenharmony_ci * flush, which we use for tracking which buffers are referenced by 216bf215546Sopenharmony_ci * an unflushed command buffer. 217bf215546Sopenharmony_ci */ 218bf215546Sopenharmony_ci struct threaded_context *tc = batch->tc; 219bf215546Sopenharmony_ci struct util_queue_fence *fence = 220bf215546Sopenharmony_ci &tc->buffer_lists[batch->buffer_list_index].driver_flushed_fence; 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci if (tc->options.driver_calls_flush_notify) { 223bf215546Sopenharmony_ci tc->signal_fences_next_flush[tc->num_signal_fences_next_flush++] = fence; 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci /* Since our buffer lists are chained as a ring, we need to flush 226bf215546Sopenharmony_ci * the context twice as we go around the ring to make the driver signal 227bf215546Sopenharmony_ci * the buffer list fences, so that the producer thread can reuse the buffer 228bf215546Sopenharmony_ci * list structures for the next batches without waiting. 229bf215546Sopenharmony_ci */ 230bf215546Sopenharmony_ci unsigned half_ring = TC_MAX_BUFFER_LISTS / 2; 231bf215546Sopenharmony_ci if (batch->buffer_list_index % half_ring == half_ring - 1) 232bf215546Sopenharmony_ci pipe->flush(pipe, NULL, PIPE_FLUSH_ASYNC); 233bf215546Sopenharmony_ci } else { 234bf215546Sopenharmony_ci util_queue_fence_signal(fence); 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci tc_clear_driver_thread(batch->tc); 238bf215546Sopenharmony_ci tc_batch_check(batch); 239bf215546Sopenharmony_ci batch->num_total_slots = 0; 240bf215546Sopenharmony_ci} 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_cistatic void 243bf215546Sopenharmony_citc_begin_next_buffer_list(struct threaded_context *tc) 244bf215546Sopenharmony_ci{ 245bf215546Sopenharmony_ci tc->next_buf_list = (tc->next_buf_list + 1) % TC_MAX_BUFFER_LISTS; 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci tc->batch_slots[tc->next].buffer_list_index = tc->next_buf_list; 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci /* Clear the buffer list in the new empty batch. */ 250bf215546Sopenharmony_ci struct tc_buffer_list *buf_list = &tc->buffer_lists[tc->next_buf_list]; 251bf215546Sopenharmony_ci assert(util_queue_fence_is_signalled(&buf_list->driver_flushed_fence)); 252bf215546Sopenharmony_ci util_queue_fence_reset(&buf_list->driver_flushed_fence); /* set to unsignalled */ 253bf215546Sopenharmony_ci BITSET_ZERO(buf_list->buffer_list); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci tc->add_all_gfx_bindings_to_buffer_list = true; 256bf215546Sopenharmony_ci tc->add_all_compute_bindings_to_buffer_list = true; 257bf215546Sopenharmony_ci} 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_cistatic void 260bf215546Sopenharmony_citc_batch_flush(struct threaded_context *tc) 261bf215546Sopenharmony_ci{ 262bf215546Sopenharmony_ci struct tc_batch *next = &tc->batch_slots[tc->next]; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci tc_assert(next->num_total_slots != 0); 265bf215546Sopenharmony_ci tc_batch_check(next); 266bf215546Sopenharmony_ci tc_debug_check(tc); 267bf215546Sopenharmony_ci tc->bytes_mapped_estimate = 0; 268bf215546Sopenharmony_ci p_atomic_add(&tc->num_offloaded_slots, next->num_total_slots); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci if (next->token) { 271bf215546Sopenharmony_ci next->token->tc = NULL; 272bf215546Sopenharmony_ci tc_unflushed_batch_token_reference(&next->token, NULL); 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci util_queue_add_job(&tc->queue, next, &next->fence, tc_batch_execute, 276bf215546Sopenharmony_ci NULL, 0); 277bf215546Sopenharmony_ci tc->last = tc->next; 278bf215546Sopenharmony_ci tc->next = (tc->next + 1) % TC_MAX_BATCHES; 279bf215546Sopenharmony_ci tc_begin_next_buffer_list(tc); 280bf215546Sopenharmony_ci} 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci/* This is the function that adds variable-sized calls into the current 283bf215546Sopenharmony_ci * batch. It also flushes the batch if there is not enough space there. 284bf215546Sopenharmony_ci * All other higher-level "add" functions use it. 285bf215546Sopenharmony_ci */ 286bf215546Sopenharmony_cistatic void * 287bf215546Sopenharmony_citc_add_sized_call(struct threaded_context *tc, enum tc_call_id id, 288bf215546Sopenharmony_ci unsigned num_slots) 289bf215546Sopenharmony_ci{ 290bf215546Sopenharmony_ci struct tc_batch *next = &tc->batch_slots[tc->next]; 291bf215546Sopenharmony_ci assert(num_slots <= TC_SLOTS_PER_BATCH); 292bf215546Sopenharmony_ci tc_debug_check(tc); 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci if (unlikely(next->num_total_slots + num_slots > TC_SLOTS_PER_BATCH)) { 295bf215546Sopenharmony_ci tc_batch_flush(tc); 296bf215546Sopenharmony_ci next = &tc->batch_slots[tc->next]; 297bf215546Sopenharmony_ci tc_assert(next->num_total_slots == 0); 298bf215546Sopenharmony_ci } 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci tc_assert(util_queue_fence_is_signalled(&next->fence)); 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci struct tc_call_base *call = (struct tc_call_base*)&next->slots[next->num_total_slots]; 303bf215546Sopenharmony_ci next->num_total_slots += num_slots; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci#if !defined(NDEBUG) && TC_DEBUG >= 1 306bf215546Sopenharmony_ci call->sentinel = TC_SENTINEL; 307bf215546Sopenharmony_ci#endif 308bf215546Sopenharmony_ci call->call_id = id; 309bf215546Sopenharmony_ci call->num_slots = num_slots; 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci#if TC_DEBUG >= 3 312bf215546Sopenharmony_ci tc_printf("ENQUEUE: %s", tc_call_names[id]); 313bf215546Sopenharmony_ci#endif 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci tc_debug_check(tc); 316bf215546Sopenharmony_ci return call; 317bf215546Sopenharmony_ci} 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci#define tc_add_call(tc, execute, type) \ 320bf215546Sopenharmony_ci ((struct type*)tc_add_sized_call(tc, execute, call_size(type))) 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci#define tc_add_slot_based_call(tc, execute, type, num_slots) \ 323bf215546Sopenharmony_ci ((struct type*)tc_add_sized_call(tc, execute, \ 324bf215546Sopenharmony_ci call_size_with_slots(type, num_slots))) 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_cistatic bool 327bf215546Sopenharmony_citc_is_sync(struct threaded_context *tc) 328bf215546Sopenharmony_ci{ 329bf215546Sopenharmony_ci struct tc_batch *last = &tc->batch_slots[tc->last]; 330bf215546Sopenharmony_ci struct tc_batch *next = &tc->batch_slots[tc->next]; 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci return util_queue_fence_is_signalled(&last->fence) && 333bf215546Sopenharmony_ci !next->num_total_slots; 334bf215546Sopenharmony_ci} 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_cistatic void 337bf215546Sopenharmony_ci_tc_sync(struct threaded_context *tc, UNUSED const char *info, UNUSED const char *func) 338bf215546Sopenharmony_ci{ 339bf215546Sopenharmony_ci struct tc_batch *last = &tc->batch_slots[tc->last]; 340bf215546Sopenharmony_ci struct tc_batch *next = &tc->batch_slots[tc->next]; 341bf215546Sopenharmony_ci bool synced = false; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci tc_debug_check(tc); 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci /* Only wait for queued calls... */ 346bf215546Sopenharmony_ci if (!util_queue_fence_is_signalled(&last->fence)) { 347bf215546Sopenharmony_ci util_queue_fence_wait(&last->fence); 348bf215546Sopenharmony_ci synced = true; 349bf215546Sopenharmony_ci } 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci tc_debug_check(tc); 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci if (next->token) { 354bf215546Sopenharmony_ci next->token->tc = NULL; 355bf215546Sopenharmony_ci tc_unflushed_batch_token_reference(&next->token, NULL); 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci /* .. and execute unflushed calls directly. */ 359bf215546Sopenharmony_ci if (next->num_total_slots) { 360bf215546Sopenharmony_ci p_atomic_add(&tc->num_direct_slots, next->num_total_slots); 361bf215546Sopenharmony_ci tc->bytes_mapped_estimate = 0; 362bf215546Sopenharmony_ci tc_batch_execute(next, NULL, 0); 363bf215546Sopenharmony_ci tc_begin_next_buffer_list(tc); 364bf215546Sopenharmony_ci synced = true; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci if (synced) { 368bf215546Sopenharmony_ci p_atomic_inc(&tc->num_syncs); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci if (tc_strcmp(func, "tc_destroy") != 0) { 371bf215546Sopenharmony_ci tc_printf("sync %s %s", func, info); 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci } 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci tc_debug_check(tc); 376bf215546Sopenharmony_ci} 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci#define tc_sync(tc) _tc_sync(tc, "", __func__) 379bf215546Sopenharmony_ci#define tc_sync_msg(tc, info) _tc_sync(tc, info, __func__) 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci/** 382bf215546Sopenharmony_ci * Call this from fence_finish for same-context fence waits of deferred fences 383bf215546Sopenharmony_ci * that haven't been flushed yet. 384bf215546Sopenharmony_ci * 385bf215546Sopenharmony_ci * The passed pipe_context must be the one passed to pipe_screen::fence_finish, 386bf215546Sopenharmony_ci * i.e., the wrapped one. 387bf215546Sopenharmony_ci */ 388bf215546Sopenharmony_civoid 389bf215546Sopenharmony_cithreaded_context_flush(struct pipe_context *_pipe, 390bf215546Sopenharmony_ci struct tc_unflushed_batch_token *token, 391bf215546Sopenharmony_ci bool prefer_async) 392bf215546Sopenharmony_ci{ 393bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci /* This is called from the gallium frontend / application thread. */ 396bf215546Sopenharmony_ci if (token->tc && token->tc == tc) { 397bf215546Sopenharmony_ci struct tc_batch *last = &tc->batch_slots[tc->last]; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci /* Prefer to do the flush in the driver thread if it is already 400bf215546Sopenharmony_ci * running. That should be better for cache locality. 401bf215546Sopenharmony_ci */ 402bf215546Sopenharmony_ci if (prefer_async || !util_queue_fence_is_signalled(&last->fence)) 403bf215546Sopenharmony_ci tc_batch_flush(tc); 404bf215546Sopenharmony_ci else 405bf215546Sopenharmony_ci tc_sync(token->tc); 406bf215546Sopenharmony_ci } 407bf215546Sopenharmony_ci} 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci/* Must be called before TC binds, maps, invalidates, or adds a buffer to a buffer list. */ 410bf215546Sopenharmony_cistatic void tc_touch_buffer(struct threaded_context *tc, struct threaded_resource *buf) 411bf215546Sopenharmony_ci{ 412bf215546Sopenharmony_ci const struct threaded_context *first_user = buf->first_user; 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci /* Fast path exit to avoid additional branches */ 415bf215546Sopenharmony_ci if (likely(first_user == tc)) 416bf215546Sopenharmony_ci return; 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci if (!first_user) 419bf215546Sopenharmony_ci first_user = p_atomic_cmpxchg_ptr(&buf->first_user, NULL, tc); 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci /* The NULL check might seem unnecessary here but it's actually critical: 422bf215546Sopenharmony_ci * p_atomic_cmpxchg will return NULL if it succeeds, meaning that NULL is 423bf215546Sopenharmony_ci * equivalent to "we're the first user" here. (It's equally important not 424bf215546Sopenharmony_ci * to ignore the result of the cmpxchg above, since it might fail.) 425bf215546Sopenharmony_ci * Without the NULL check, we'd set the flag unconditionally, which is bad. 426bf215546Sopenharmony_ci */ 427bf215546Sopenharmony_ci if (first_user && first_user != tc && !buf->used_by_multiple_contexts) 428bf215546Sopenharmony_ci buf->used_by_multiple_contexts = true; 429bf215546Sopenharmony_ci} 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_cistatic bool tc_is_buffer_shared(struct threaded_resource *buf) 432bf215546Sopenharmony_ci{ 433bf215546Sopenharmony_ci return buf->is_shared || buf->used_by_multiple_contexts; 434bf215546Sopenharmony_ci} 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_cistatic void 437bf215546Sopenharmony_citc_add_to_buffer_list(struct threaded_context *tc, struct tc_buffer_list *next, struct pipe_resource *buf) 438bf215546Sopenharmony_ci{ 439bf215546Sopenharmony_ci struct threaded_resource *tbuf = threaded_resource(buf); 440bf215546Sopenharmony_ci tc_touch_buffer(tc, tbuf); 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci uint32_t id = tbuf->buffer_id_unique; 443bf215546Sopenharmony_ci BITSET_SET(next->buffer_list, id & TC_BUFFER_ID_MASK); 444bf215546Sopenharmony_ci} 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci/* Set a buffer binding and add it to the buffer list. */ 447bf215546Sopenharmony_cistatic void 448bf215546Sopenharmony_citc_bind_buffer(struct threaded_context *tc, uint32_t *binding, struct tc_buffer_list *next, struct pipe_resource *buf) 449bf215546Sopenharmony_ci{ 450bf215546Sopenharmony_ci struct threaded_resource *tbuf = threaded_resource(buf); 451bf215546Sopenharmony_ci tc_touch_buffer(tc, tbuf); 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci uint32_t id = tbuf->buffer_id_unique; 454bf215546Sopenharmony_ci *binding = id; 455bf215546Sopenharmony_ci BITSET_SET(next->buffer_list, id & TC_BUFFER_ID_MASK); 456bf215546Sopenharmony_ci} 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci/* Reset a buffer binding. */ 459bf215546Sopenharmony_cistatic void 460bf215546Sopenharmony_citc_unbind_buffer(uint32_t *binding) 461bf215546Sopenharmony_ci{ 462bf215546Sopenharmony_ci *binding = 0; 463bf215546Sopenharmony_ci} 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci/* Reset a range of buffer binding slots. */ 466bf215546Sopenharmony_cistatic void 467bf215546Sopenharmony_citc_unbind_buffers(uint32_t *binding, unsigned count) 468bf215546Sopenharmony_ci{ 469bf215546Sopenharmony_ci if (count) 470bf215546Sopenharmony_ci memset(binding, 0, sizeof(*binding) * count); 471bf215546Sopenharmony_ci} 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_cistatic void 474bf215546Sopenharmony_citc_add_bindings_to_buffer_list(BITSET_WORD *buffer_list, const uint32_t *bindings, 475bf215546Sopenharmony_ci unsigned count) 476bf215546Sopenharmony_ci{ 477bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 478bf215546Sopenharmony_ci if (bindings[i]) 479bf215546Sopenharmony_ci BITSET_SET(buffer_list, bindings[i] & TC_BUFFER_ID_MASK); 480bf215546Sopenharmony_ci } 481bf215546Sopenharmony_ci} 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_cistatic bool 484bf215546Sopenharmony_citc_rebind_bindings(uint32_t old_id, uint32_t new_id, uint32_t *bindings, 485bf215546Sopenharmony_ci unsigned count) 486bf215546Sopenharmony_ci{ 487bf215546Sopenharmony_ci unsigned rebind_count = 0; 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 490bf215546Sopenharmony_ci if (bindings[i] == old_id) { 491bf215546Sopenharmony_ci bindings[i] = new_id; 492bf215546Sopenharmony_ci rebind_count++; 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci } 495bf215546Sopenharmony_ci return rebind_count; 496bf215546Sopenharmony_ci} 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_cistatic void 499bf215546Sopenharmony_citc_add_shader_bindings_to_buffer_list(struct threaded_context *tc, 500bf215546Sopenharmony_ci BITSET_WORD *buffer_list, 501bf215546Sopenharmony_ci enum pipe_shader_type shader) 502bf215546Sopenharmony_ci{ 503bf215546Sopenharmony_ci tc_add_bindings_to_buffer_list(buffer_list, tc->const_buffers[shader], 504bf215546Sopenharmony_ci tc->max_const_buffers); 505bf215546Sopenharmony_ci if (tc->seen_shader_buffers[shader]) { 506bf215546Sopenharmony_ci tc_add_bindings_to_buffer_list(buffer_list, tc->shader_buffers[shader], 507bf215546Sopenharmony_ci tc->max_shader_buffers); 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci if (tc->seen_image_buffers[shader]) { 510bf215546Sopenharmony_ci tc_add_bindings_to_buffer_list(buffer_list, tc->image_buffers[shader], 511bf215546Sopenharmony_ci tc->max_images); 512bf215546Sopenharmony_ci } 513bf215546Sopenharmony_ci if (tc->seen_sampler_buffers[shader]) { 514bf215546Sopenharmony_ci tc_add_bindings_to_buffer_list(buffer_list, tc->sampler_buffers[shader], 515bf215546Sopenharmony_ci tc->max_samplers); 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci} 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_cistatic unsigned 520bf215546Sopenharmony_citc_rebind_shader_bindings(struct threaded_context *tc, uint32_t old_id, 521bf215546Sopenharmony_ci uint32_t new_id, enum pipe_shader_type shader, uint32_t *rebind_mask) 522bf215546Sopenharmony_ci{ 523bf215546Sopenharmony_ci unsigned ubo = 0, ssbo = 0, img = 0, sampler = 0; 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci ubo = tc_rebind_bindings(old_id, new_id, tc->const_buffers[shader], 526bf215546Sopenharmony_ci tc->max_const_buffers); 527bf215546Sopenharmony_ci if (ubo) 528bf215546Sopenharmony_ci *rebind_mask |= BITFIELD_BIT(TC_BINDING_UBO_VS) << shader; 529bf215546Sopenharmony_ci if (tc->seen_shader_buffers[shader]) { 530bf215546Sopenharmony_ci ssbo = tc_rebind_bindings(old_id, new_id, tc->shader_buffers[shader], 531bf215546Sopenharmony_ci tc->max_shader_buffers); 532bf215546Sopenharmony_ci if (ssbo) 533bf215546Sopenharmony_ci *rebind_mask |= BITFIELD_BIT(TC_BINDING_SSBO_VS) << shader; 534bf215546Sopenharmony_ci } 535bf215546Sopenharmony_ci if (tc->seen_image_buffers[shader]) { 536bf215546Sopenharmony_ci img = tc_rebind_bindings(old_id, new_id, tc->image_buffers[shader], 537bf215546Sopenharmony_ci tc->max_images); 538bf215546Sopenharmony_ci if (img) 539bf215546Sopenharmony_ci *rebind_mask |= BITFIELD_BIT(TC_BINDING_IMAGE_VS) << shader; 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci if (tc->seen_sampler_buffers[shader]) { 542bf215546Sopenharmony_ci sampler = tc_rebind_bindings(old_id, new_id, tc->sampler_buffers[shader], 543bf215546Sopenharmony_ci tc->max_samplers); 544bf215546Sopenharmony_ci if (sampler) 545bf215546Sopenharmony_ci *rebind_mask |= BITFIELD_BIT(TC_BINDING_SAMPLERVIEW_VS) << shader; 546bf215546Sopenharmony_ci } 547bf215546Sopenharmony_ci return ubo + ssbo + img + sampler; 548bf215546Sopenharmony_ci} 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci/* Add all bound buffers used by VS/TCS/TES/GS/FS to the buffer list. 551bf215546Sopenharmony_ci * This is called by the first draw call in a batch when we want to inherit 552bf215546Sopenharmony_ci * all bindings set by the previous batch. 553bf215546Sopenharmony_ci */ 554bf215546Sopenharmony_cistatic void 555bf215546Sopenharmony_citc_add_all_gfx_bindings_to_buffer_list(struct threaded_context *tc) 556bf215546Sopenharmony_ci{ 557bf215546Sopenharmony_ci BITSET_WORD *buffer_list = tc->buffer_lists[tc->next_buf_list].buffer_list; 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci tc_add_bindings_to_buffer_list(buffer_list, tc->vertex_buffers, tc->max_vertex_buffers); 560bf215546Sopenharmony_ci if (tc->seen_streamout_buffers) 561bf215546Sopenharmony_ci tc_add_bindings_to_buffer_list(buffer_list, tc->streamout_buffers, PIPE_MAX_SO_BUFFERS); 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci tc_add_shader_bindings_to_buffer_list(tc, buffer_list, PIPE_SHADER_VERTEX); 564bf215546Sopenharmony_ci tc_add_shader_bindings_to_buffer_list(tc, buffer_list, PIPE_SHADER_FRAGMENT); 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci if (tc->seen_tcs) 567bf215546Sopenharmony_ci tc_add_shader_bindings_to_buffer_list(tc, buffer_list, PIPE_SHADER_TESS_CTRL); 568bf215546Sopenharmony_ci if (tc->seen_tes) 569bf215546Sopenharmony_ci tc_add_shader_bindings_to_buffer_list(tc, buffer_list, PIPE_SHADER_TESS_EVAL); 570bf215546Sopenharmony_ci if (tc->seen_gs) 571bf215546Sopenharmony_ci tc_add_shader_bindings_to_buffer_list(tc, buffer_list, PIPE_SHADER_GEOMETRY); 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_ci tc->add_all_gfx_bindings_to_buffer_list = false; 574bf215546Sopenharmony_ci} 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci/* Add all bound buffers used by compute to the buffer list. 577bf215546Sopenharmony_ci * This is called by the first compute call in a batch when we want to inherit 578bf215546Sopenharmony_ci * all bindings set by the previous batch. 579bf215546Sopenharmony_ci */ 580bf215546Sopenharmony_cistatic void 581bf215546Sopenharmony_citc_add_all_compute_bindings_to_buffer_list(struct threaded_context *tc) 582bf215546Sopenharmony_ci{ 583bf215546Sopenharmony_ci BITSET_WORD *buffer_list = tc->buffer_lists[tc->next_buf_list].buffer_list; 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci tc_add_shader_bindings_to_buffer_list(tc, buffer_list, PIPE_SHADER_COMPUTE); 586bf215546Sopenharmony_ci tc->add_all_compute_bindings_to_buffer_list = false; 587bf215546Sopenharmony_ci} 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_cistatic unsigned 590bf215546Sopenharmony_citc_rebind_buffer(struct threaded_context *tc, uint32_t old_id, uint32_t new_id, uint32_t *rebind_mask) 591bf215546Sopenharmony_ci{ 592bf215546Sopenharmony_ci unsigned vbo = 0, so = 0; 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci vbo = tc_rebind_bindings(old_id, new_id, tc->vertex_buffers, 595bf215546Sopenharmony_ci tc->max_vertex_buffers); 596bf215546Sopenharmony_ci if (vbo) 597bf215546Sopenharmony_ci *rebind_mask |= BITFIELD_BIT(TC_BINDING_VERTEX_BUFFER); 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci if (tc->seen_streamout_buffers) { 600bf215546Sopenharmony_ci so = tc_rebind_bindings(old_id, new_id, tc->streamout_buffers, 601bf215546Sopenharmony_ci PIPE_MAX_SO_BUFFERS); 602bf215546Sopenharmony_ci if (so) 603bf215546Sopenharmony_ci *rebind_mask |= BITFIELD_BIT(TC_BINDING_STREAMOUT_BUFFER); 604bf215546Sopenharmony_ci } 605bf215546Sopenharmony_ci unsigned rebound = vbo + so; 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci rebound += tc_rebind_shader_bindings(tc, old_id, new_id, PIPE_SHADER_VERTEX, rebind_mask); 608bf215546Sopenharmony_ci rebound += tc_rebind_shader_bindings(tc, old_id, new_id, PIPE_SHADER_FRAGMENT, rebind_mask); 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_ci if (tc->seen_tcs) 611bf215546Sopenharmony_ci rebound += tc_rebind_shader_bindings(tc, old_id, new_id, PIPE_SHADER_TESS_CTRL, rebind_mask); 612bf215546Sopenharmony_ci if (tc->seen_tes) 613bf215546Sopenharmony_ci rebound += tc_rebind_shader_bindings(tc, old_id, new_id, PIPE_SHADER_TESS_EVAL, rebind_mask); 614bf215546Sopenharmony_ci if (tc->seen_gs) 615bf215546Sopenharmony_ci rebound += tc_rebind_shader_bindings(tc, old_id, new_id, PIPE_SHADER_GEOMETRY, rebind_mask); 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci rebound += tc_rebind_shader_bindings(tc, old_id, new_id, PIPE_SHADER_COMPUTE, rebind_mask); 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci if (rebound) 620bf215546Sopenharmony_ci BITSET_SET(tc->buffer_lists[tc->next_buf_list].buffer_list, new_id & TC_BUFFER_ID_MASK); 621bf215546Sopenharmony_ci return rebound; 622bf215546Sopenharmony_ci} 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_cistatic bool 625bf215546Sopenharmony_citc_is_buffer_bound_with_mask(uint32_t id, uint32_t *bindings, unsigned binding_mask) 626bf215546Sopenharmony_ci{ 627bf215546Sopenharmony_ci while (binding_mask) { 628bf215546Sopenharmony_ci if (bindings[u_bit_scan(&binding_mask)] == id) 629bf215546Sopenharmony_ci return true; 630bf215546Sopenharmony_ci } 631bf215546Sopenharmony_ci return false; 632bf215546Sopenharmony_ci} 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_cistatic bool 635bf215546Sopenharmony_citc_is_buffer_shader_bound_for_write(struct threaded_context *tc, uint32_t id, 636bf215546Sopenharmony_ci enum pipe_shader_type shader) 637bf215546Sopenharmony_ci{ 638bf215546Sopenharmony_ci if (tc->seen_shader_buffers[shader] && 639bf215546Sopenharmony_ci tc_is_buffer_bound_with_mask(id, tc->shader_buffers[shader], 640bf215546Sopenharmony_ci tc->shader_buffers_writeable_mask[shader])) 641bf215546Sopenharmony_ci return true; 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci if (tc->seen_image_buffers[shader] && 644bf215546Sopenharmony_ci tc_is_buffer_bound_with_mask(id, tc->image_buffers[shader], 645bf215546Sopenharmony_ci tc->image_buffers_writeable_mask[shader])) 646bf215546Sopenharmony_ci return true; 647bf215546Sopenharmony_ci 648bf215546Sopenharmony_ci return false; 649bf215546Sopenharmony_ci} 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_cistatic bool 652bf215546Sopenharmony_citc_is_buffer_bound_for_write(struct threaded_context *tc, uint32_t id) 653bf215546Sopenharmony_ci{ 654bf215546Sopenharmony_ci if (tc->seen_streamout_buffers && 655bf215546Sopenharmony_ci tc_is_buffer_bound_with_mask(id, tc->streamout_buffers, 656bf215546Sopenharmony_ci BITFIELD_MASK(PIPE_MAX_SO_BUFFERS))) 657bf215546Sopenharmony_ci return true; 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ci if (tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_VERTEX) || 660bf215546Sopenharmony_ci tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_FRAGMENT) || 661bf215546Sopenharmony_ci tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_COMPUTE)) 662bf215546Sopenharmony_ci return true; 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci if (tc->seen_tcs && 665bf215546Sopenharmony_ci tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_TESS_CTRL)) 666bf215546Sopenharmony_ci return true; 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci if (tc->seen_tes && 669bf215546Sopenharmony_ci tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_TESS_EVAL)) 670bf215546Sopenharmony_ci return true; 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci if (tc->seen_gs && 673bf215546Sopenharmony_ci tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_GEOMETRY)) 674bf215546Sopenharmony_ci return true; 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ci return false; 677bf215546Sopenharmony_ci} 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_cistatic bool 680bf215546Sopenharmony_citc_is_buffer_busy(struct threaded_context *tc, struct threaded_resource *tbuf, 681bf215546Sopenharmony_ci unsigned map_usage) 682bf215546Sopenharmony_ci{ 683bf215546Sopenharmony_ci if (!tc->options.is_resource_busy) 684bf215546Sopenharmony_ci return true; 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_ci uint32_t id_hash = tbuf->buffer_id_unique & TC_BUFFER_ID_MASK; 687bf215546Sopenharmony_ci 688bf215546Sopenharmony_ci for (unsigned i = 0; i < TC_MAX_BUFFER_LISTS; i++) { 689bf215546Sopenharmony_ci struct tc_buffer_list *buf_list = &tc->buffer_lists[i]; 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci /* If the buffer is referenced by a batch that hasn't been flushed (by tc or the driver), 692bf215546Sopenharmony_ci * then the buffer is considered busy. */ 693bf215546Sopenharmony_ci if (!util_queue_fence_is_signalled(&buf_list->driver_flushed_fence) && 694bf215546Sopenharmony_ci BITSET_TEST(buf_list->buffer_list, id_hash)) 695bf215546Sopenharmony_ci return true; 696bf215546Sopenharmony_ci } 697bf215546Sopenharmony_ci 698bf215546Sopenharmony_ci /* The buffer isn't referenced by any unflushed batch: we can safely ask to the driver whether 699bf215546Sopenharmony_ci * this buffer is busy or not. */ 700bf215546Sopenharmony_ci return tc->options.is_resource_busy(tc->pipe->screen, tbuf->latest, map_usage); 701bf215546Sopenharmony_ci} 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci/** 704bf215546Sopenharmony_ci * allow_cpu_storage should be false for user memory and imported buffers. 705bf215546Sopenharmony_ci */ 706bf215546Sopenharmony_civoid 707bf215546Sopenharmony_cithreaded_resource_init(struct pipe_resource *res, bool allow_cpu_storage) 708bf215546Sopenharmony_ci{ 709bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(res); 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci tres->first_user = NULL; 712bf215546Sopenharmony_ci tres->used_by_multiple_contexts = false; 713bf215546Sopenharmony_ci tres->latest = &tres->b; 714bf215546Sopenharmony_ci tres->cpu_storage = NULL; 715bf215546Sopenharmony_ci util_range_init(&tres->valid_buffer_range); 716bf215546Sopenharmony_ci tres->is_shared = false; 717bf215546Sopenharmony_ci tres->is_user_ptr = false; 718bf215546Sopenharmony_ci tres->buffer_id_unique = 0; 719bf215546Sopenharmony_ci tres->pending_staging_uploads = 0; 720bf215546Sopenharmony_ci util_range_init(&tres->pending_staging_uploads_range); 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_ci if (allow_cpu_storage && 723bf215546Sopenharmony_ci !(res->flags & (PIPE_RESOURCE_FLAG_MAP_PERSISTENT | 724bf215546Sopenharmony_ci PIPE_RESOURCE_FLAG_SPARSE | 725bf215546Sopenharmony_ci PIPE_RESOURCE_FLAG_ENCRYPTED)) && 726bf215546Sopenharmony_ci /* We need buffer invalidation and buffer busyness tracking for the CPU 727bf215546Sopenharmony_ci * storage, which aren't supported with pipe_vertex_state. */ 728bf215546Sopenharmony_ci !(res->bind & PIPE_BIND_VERTEX_STATE)) 729bf215546Sopenharmony_ci tres->allow_cpu_storage = true; 730bf215546Sopenharmony_ci else 731bf215546Sopenharmony_ci tres->allow_cpu_storage = false; 732bf215546Sopenharmony_ci} 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_civoid 735bf215546Sopenharmony_cithreaded_resource_deinit(struct pipe_resource *res) 736bf215546Sopenharmony_ci{ 737bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(res); 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci if (tres->latest != &tres->b) 740bf215546Sopenharmony_ci pipe_resource_reference(&tres->latest, NULL); 741bf215546Sopenharmony_ci util_range_destroy(&tres->valid_buffer_range); 742bf215546Sopenharmony_ci util_range_destroy(&tres->pending_staging_uploads_range); 743bf215546Sopenharmony_ci align_free(tres->cpu_storage); 744bf215546Sopenharmony_ci} 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_cistruct pipe_context * 747bf215546Sopenharmony_cithreaded_context_unwrap_sync(struct pipe_context *pipe) 748bf215546Sopenharmony_ci{ 749bf215546Sopenharmony_ci if (!pipe || !pipe->priv) 750bf215546Sopenharmony_ci return pipe; 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci tc_sync(threaded_context(pipe)); 753bf215546Sopenharmony_ci return (struct pipe_context*)pipe->priv; 754bf215546Sopenharmony_ci} 755bf215546Sopenharmony_ci 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci/******************************************************************** 758bf215546Sopenharmony_ci * simple functions 759bf215546Sopenharmony_ci */ 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci#define TC_FUNC1(func, qualifier, type, deref, addr, ...) \ 762bf215546Sopenharmony_ci struct tc_call_##func { \ 763bf215546Sopenharmony_ci struct tc_call_base base; \ 764bf215546Sopenharmony_ci type state; \ 765bf215546Sopenharmony_ci }; \ 766bf215546Sopenharmony_ci \ 767bf215546Sopenharmony_ci static uint16_t \ 768bf215546Sopenharmony_ci tc_call_##func(struct pipe_context *pipe, void *call, uint64_t *last) \ 769bf215546Sopenharmony_ci { \ 770bf215546Sopenharmony_ci pipe->func(pipe, addr(to_call(call, tc_call_##func)->state)); \ 771bf215546Sopenharmony_ci return call_size(tc_call_##func); \ 772bf215546Sopenharmony_ci } \ 773bf215546Sopenharmony_ci \ 774bf215546Sopenharmony_ci static void \ 775bf215546Sopenharmony_ci tc_##func(struct pipe_context *_pipe, qualifier type deref param) \ 776bf215546Sopenharmony_ci { \ 777bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); \ 778bf215546Sopenharmony_ci struct tc_call_##func *p = (struct tc_call_##func*) \ 779bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_##func, tc_call_##func); \ 780bf215546Sopenharmony_ci p->state = deref(param); \ 781bf215546Sopenharmony_ci __VA_ARGS__; \ 782bf215546Sopenharmony_ci } 783bf215546Sopenharmony_ci 784bf215546Sopenharmony_ciTC_FUNC1(set_active_query_state, , bool, , ) 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ciTC_FUNC1(set_blend_color, const, struct pipe_blend_color, *, &) 787bf215546Sopenharmony_ciTC_FUNC1(set_stencil_ref, const, struct pipe_stencil_ref, , ) 788bf215546Sopenharmony_ciTC_FUNC1(set_clip_state, const, struct pipe_clip_state, *, &) 789bf215546Sopenharmony_ciTC_FUNC1(set_sample_mask, , unsigned, , ) 790bf215546Sopenharmony_ciTC_FUNC1(set_min_samples, , unsigned, , ) 791bf215546Sopenharmony_ciTC_FUNC1(set_polygon_stipple, const, struct pipe_poly_stipple, *, &) 792bf215546Sopenharmony_ci 793bf215546Sopenharmony_ciTC_FUNC1(texture_barrier, , unsigned, , ) 794bf215546Sopenharmony_ciTC_FUNC1(memory_barrier, , unsigned, , ) 795bf215546Sopenharmony_ciTC_FUNC1(delete_texture_handle, , uint64_t, , ) 796bf215546Sopenharmony_ciTC_FUNC1(delete_image_handle, , uint64_t, , ) 797bf215546Sopenharmony_ciTC_FUNC1(set_frontend_noop, , bool, , ) 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci 800bf215546Sopenharmony_ci/******************************************************************** 801bf215546Sopenharmony_ci * queries 802bf215546Sopenharmony_ci */ 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_cistatic struct pipe_query * 805bf215546Sopenharmony_citc_create_query(struct pipe_context *_pipe, unsigned query_type, 806bf215546Sopenharmony_ci unsigned index) 807bf215546Sopenharmony_ci{ 808bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 809bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci return pipe->create_query(pipe, query_type, index); 812bf215546Sopenharmony_ci} 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_cistatic struct pipe_query * 815bf215546Sopenharmony_citc_create_batch_query(struct pipe_context *_pipe, unsigned num_queries, 816bf215546Sopenharmony_ci unsigned *query_types) 817bf215546Sopenharmony_ci{ 818bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 819bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 820bf215546Sopenharmony_ci 821bf215546Sopenharmony_ci return pipe->create_batch_query(pipe, num_queries, query_types); 822bf215546Sopenharmony_ci} 823bf215546Sopenharmony_ci 824bf215546Sopenharmony_cistruct tc_query_call { 825bf215546Sopenharmony_ci struct tc_call_base base; 826bf215546Sopenharmony_ci struct pipe_query *query; 827bf215546Sopenharmony_ci}; 828bf215546Sopenharmony_ci 829bf215546Sopenharmony_cistatic uint16_t 830bf215546Sopenharmony_citc_call_destroy_query(struct pipe_context *pipe, void *call, uint64_t *last) 831bf215546Sopenharmony_ci{ 832bf215546Sopenharmony_ci struct pipe_query *query = to_call(call, tc_query_call)->query; 833bf215546Sopenharmony_ci struct threaded_query *tq = threaded_query(query); 834bf215546Sopenharmony_ci 835bf215546Sopenharmony_ci if (list_is_linked(&tq->head_unflushed)) 836bf215546Sopenharmony_ci list_del(&tq->head_unflushed); 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci pipe->destroy_query(pipe, query); 839bf215546Sopenharmony_ci return call_size(tc_query_call); 840bf215546Sopenharmony_ci} 841bf215546Sopenharmony_ci 842bf215546Sopenharmony_cistatic void 843bf215546Sopenharmony_citc_destroy_query(struct pipe_context *_pipe, struct pipe_query *query) 844bf215546Sopenharmony_ci{ 845bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 846bf215546Sopenharmony_ci 847bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_destroy_query, tc_query_call)->query = query; 848bf215546Sopenharmony_ci} 849bf215546Sopenharmony_ci 850bf215546Sopenharmony_cistatic uint16_t 851bf215546Sopenharmony_citc_call_begin_query(struct pipe_context *pipe, void *call, uint64_t *last) 852bf215546Sopenharmony_ci{ 853bf215546Sopenharmony_ci pipe->begin_query(pipe, to_call(call, tc_query_call)->query); 854bf215546Sopenharmony_ci return call_size(tc_query_call); 855bf215546Sopenharmony_ci} 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_cistatic bool 858bf215546Sopenharmony_citc_begin_query(struct pipe_context *_pipe, struct pipe_query *query) 859bf215546Sopenharmony_ci{ 860bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 861bf215546Sopenharmony_ci 862bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_begin_query, tc_query_call)->query = query; 863bf215546Sopenharmony_ci return true; /* we don't care about the return value for this call */ 864bf215546Sopenharmony_ci} 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_cistruct tc_end_query_call { 867bf215546Sopenharmony_ci struct tc_call_base base; 868bf215546Sopenharmony_ci struct threaded_context *tc; 869bf215546Sopenharmony_ci struct pipe_query *query; 870bf215546Sopenharmony_ci}; 871bf215546Sopenharmony_ci 872bf215546Sopenharmony_cistatic uint16_t 873bf215546Sopenharmony_citc_call_end_query(struct pipe_context *pipe, void *call, uint64_t *last) 874bf215546Sopenharmony_ci{ 875bf215546Sopenharmony_ci struct tc_end_query_call *p = to_call(call, tc_end_query_call); 876bf215546Sopenharmony_ci struct threaded_query *tq = threaded_query(p->query); 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci if (!list_is_linked(&tq->head_unflushed)) 879bf215546Sopenharmony_ci list_add(&tq->head_unflushed, &p->tc->unflushed_queries); 880bf215546Sopenharmony_ci 881bf215546Sopenharmony_ci pipe->end_query(pipe, p->query); 882bf215546Sopenharmony_ci return call_size(tc_end_query_call); 883bf215546Sopenharmony_ci} 884bf215546Sopenharmony_ci 885bf215546Sopenharmony_cistatic bool 886bf215546Sopenharmony_citc_end_query(struct pipe_context *_pipe, struct pipe_query *query) 887bf215546Sopenharmony_ci{ 888bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 889bf215546Sopenharmony_ci struct threaded_query *tq = threaded_query(query); 890bf215546Sopenharmony_ci struct tc_end_query_call *call = 891bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_end_query, tc_end_query_call); 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_ci call->tc = tc; 894bf215546Sopenharmony_ci call->query = query; 895bf215546Sopenharmony_ci 896bf215546Sopenharmony_ci tq->flushed = false; 897bf215546Sopenharmony_ci 898bf215546Sopenharmony_ci return true; /* we don't care about the return value for this call */ 899bf215546Sopenharmony_ci} 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_cistatic bool 902bf215546Sopenharmony_citc_get_query_result(struct pipe_context *_pipe, 903bf215546Sopenharmony_ci struct pipe_query *query, bool wait, 904bf215546Sopenharmony_ci union pipe_query_result *result) 905bf215546Sopenharmony_ci{ 906bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 907bf215546Sopenharmony_ci struct threaded_query *tq = threaded_query(query); 908bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 909bf215546Sopenharmony_ci bool flushed = tq->flushed; 910bf215546Sopenharmony_ci 911bf215546Sopenharmony_ci if (!flushed) { 912bf215546Sopenharmony_ci tc_sync_msg(tc, wait ? "wait" : "nowait"); 913bf215546Sopenharmony_ci tc_set_driver_thread(tc); 914bf215546Sopenharmony_ci } 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci bool success = pipe->get_query_result(pipe, query, wait, result); 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci if (!flushed) 919bf215546Sopenharmony_ci tc_clear_driver_thread(tc); 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci if (success) { 922bf215546Sopenharmony_ci tq->flushed = true; 923bf215546Sopenharmony_ci if (list_is_linked(&tq->head_unflushed)) { 924bf215546Sopenharmony_ci /* This is safe because it can only happen after we sync'd. */ 925bf215546Sopenharmony_ci list_del(&tq->head_unflushed); 926bf215546Sopenharmony_ci } 927bf215546Sopenharmony_ci } 928bf215546Sopenharmony_ci return success; 929bf215546Sopenharmony_ci} 930bf215546Sopenharmony_ci 931bf215546Sopenharmony_cistruct tc_query_result_resource { 932bf215546Sopenharmony_ci struct tc_call_base base; 933bf215546Sopenharmony_ci enum pipe_query_flags flags:8; 934bf215546Sopenharmony_ci enum pipe_query_value_type result_type:8; 935bf215546Sopenharmony_ci int8_t index; /* it can be -1 */ 936bf215546Sopenharmony_ci unsigned offset; 937bf215546Sopenharmony_ci struct pipe_query *query; 938bf215546Sopenharmony_ci struct pipe_resource *resource; 939bf215546Sopenharmony_ci}; 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_cistatic uint16_t 942bf215546Sopenharmony_citc_call_get_query_result_resource(struct pipe_context *pipe, void *call, uint64_t *last) 943bf215546Sopenharmony_ci{ 944bf215546Sopenharmony_ci struct tc_query_result_resource *p = to_call(call, tc_query_result_resource); 945bf215546Sopenharmony_ci 946bf215546Sopenharmony_ci pipe->get_query_result_resource(pipe, p->query, p->flags, p->result_type, 947bf215546Sopenharmony_ci p->index, p->resource, p->offset); 948bf215546Sopenharmony_ci tc_drop_resource_reference(p->resource); 949bf215546Sopenharmony_ci return call_size(tc_query_result_resource); 950bf215546Sopenharmony_ci} 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_cistatic void 953bf215546Sopenharmony_citc_get_query_result_resource(struct pipe_context *_pipe, 954bf215546Sopenharmony_ci struct pipe_query *query, 955bf215546Sopenharmony_ci enum pipe_query_flags flags, 956bf215546Sopenharmony_ci enum pipe_query_value_type result_type, int index, 957bf215546Sopenharmony_ci struct pipe_resource *resource, unsigned offset) 958bf215546Sopenharmony_ci{ 959bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 960bf215546Sopenharmony_ci 961bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(resource); 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ci struct tc_query_result_resource *p = 964bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_get_query_result_resource, 965bf215546Sopenharmony_ci tc_query_result_resource); 966bf215546Sopenharmony_ci p->query = query; 967bf215546Sopenharmony_ci p->flags = flags; 968bf215546Sopenharmony_ci p->result_type = result_type; 969bf215546Sopenharmony_ci p->index = index; 970bf215546Sopenharmony_ci tc_set_resource_reference(&p->resource, resource); 971bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, &tc->buffer_lists[tc->next_buf_list], resource); 972bf215546Sopenharmony_ci p->offset = offset; 973bf215546Sopenharmony_ci} 974bf215546Sopenharmony_ci 975bf215546Sopenharmony_cistruct tc_render_condition { 976bf215546Sopenharmony_ci struct tc_call_base base; 977bf215546Sopenharmony_ci bool condition; 978bf215546Sopenharmony_ci unsigned mode; 979bf215546Sopenharmony_ci struct pipe_query *query; 980bf215546Sopenharmony_ci}; 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_cistatic uint16_t 983bf215546Sopenharmony_citc_call_render_condition(struct pipe_context *pipe, void *call, uint64_t *last) 984bf215546Sopenharmony_ci{ 985bf215546Sopenharmony_ci struct tc_render_condition *p = to_call(call, tc_render_condition); 986bf215546Sopenharmony_ci pipe->render_condition(pipe, p->query, p->condition, p->mode); 987bf215546Sopenharmony_ci return call_size(tc_render_condition); 988bf215546Sopenharmony_ci} 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_cistatic void 991bf215546Sopenharmony_citc_render_condition(struct pipe_context *_pipe, 992bf215546Sopenharmony_ci struct pipe_query *query, bool condition, 993bf215546Sopenharmony_ci enum pipe_render_cond_flag mode) 994bf215546Sopenharmony_ci{ 995bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 996bf215546Sopenharmony_ci struct tc_render_condition *p = 997bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_render_condition, tc_render_condition); 998bf215546Sopenharmony_ci 999bf215546Sopenharmony_ci p->query = query; 1000bf215546Sopenharmony_ci p->condition = condition; 1001bf215546Sopenharmony_ci p->mode = mode; 1002bf215546Sopenharmony_ci} 1003bf215546Sopenharmony_ci 1004bf215546Sopenharmony_ci 1005bf215546Sopenharmony_ci/******************************************************************** 1006bf215546Sopenharmony_ci * constant (immutable) states 1007bf215546Sopenharmony_ci */ 1008bf215546Sopenharmony_ci 1009bf215546Sopenharmony_ci#define TC_CSO_CREATE(name, sname) \ 1010bf215546Sopenharmony_ci static void * \ 1011bf215546Sopenharmony_ci tc_create_##name##_state(struct pipe_context *_pipe, \ 1012bf215546Sopenharmony_ci const struct pipe_##sname##_state *state) \ 1013bf215546Sopenharmony_ci { \ 1014bf215546Sopenharmony_ci struct pipe_context *pipe = threaded_context(_pipe)->pipe; \ 1015bf215546Sopenharmony_ci return pipe->create_##name##_state(pipe, state); \ 1016bf215546Sopenharmony_ci } 1017bf215546Sopenharmony_ci 1018bf215546Sopenharmony_ci#define TC_CSO_BIND(name, ...) TC_FUNC1(bind_##name##_state, , void *, , , ##__VA_ARGS__) 1019bf215546Sopenharmony_ci#define TC_CSO_DELETE(name) TC_FUNC1(delete_##name##_state, , void *, , ) 1020bf215546Sopenharmony_ci 1021bf215546Sopenharmony_ci#define TC_CSO(name, sname, ...) \ 1022bf215546Sopenharmony_ci TC_CSO_CREATE(name, sname) \ 1023bf215546Sopenharmony_ci TC_CSO_BIND(name, ##__VA_ARGS__) \ 1024bf215546Sopenharmony_ci TC_CSO_DELETE(name) 1025bf215546Sopenharmony_ci 1026bf215546Sopenharmony_ci#define TC_CSO_WHOLE(name) TC_CSO(name, name) 1027bf215546Sopenharmony_ci#define TC_CSO_SHADER(name) TC_CSO(name, shader) 1028bf215546Sopenharmony_ci#define TC_CSO_SHADER_TRACK(name) TC_CSO(name, shader, tc->seen_##name = true;) 1029bf215546Sopenharmony_ci 1030bf215546Sopenharmony_ciTC_CSO_WHOLE(blend) 1031bf215546Sopenharmony_ciTC_CSO_WHOLE(rasterizer) 1032bf215546Sopenharmony_ciTC_CSO_WHOLE(depth_stencil_alpha) 1033bf215546Sopenharmony_ciTC_CSO_WHOLE(compute) 1034bf215546Sopenharmony_ciTC_CSO_SHADER(fs) 1035bf215546Sopenharmony_ciTC_CSO_SHADER(vs) 1036bf215546Sopenharmony_ciTC_CSO_SHADER_TRACK(gs) 1037bf215546Sopenharmony_ciTC_CSO_SHADER_TRACK(tcs) 1038bf215546Sopenharmony_ciTC_CSO_SHADER_TRACK(tes) 1039bf215546Sopenharmony_ciTC_CSO_CREATE(sampler, sampler) 1040bf215546Sopenharmony_ciTC_CSO_DELETE(sampler) 1041bf215546Sopenharmony_ciTC_CSO_BIND(vertex_elements) 1042bf215546Sopenharmony_ciTC_CSO_DELETE(vertex_elements) 1043bf215546Sopenharmony_ci 1044bf215546Sopenharmony_cistatic void * 1045bf215546Sopenharmony_citc_create_vertex_elements_state(struct pipe_context *_pipe, unsigned count, 1046bf215546Sopenharmony_ci const struct pipe_vertex_element *elems) 1047bf215546Sopenharmony_ci{ 1048bf215546Sopenharmony_ci struct pipe_context *pipe = threaded_context(_pipe)->pipe; 1049bf215546Sopenharmony_ci 1050bf215546Sopenharmony_ci return pipe->create_vertex_elements_state(pipe, count, elems); 1051bf215546Sopenharmony_ci} 1052bf215546Sopenharmony_ci 1053bf215546Sopenharmony_cistruct tc_sampler_states { 1054bf215546Sopenharmony_ci struct tc_call_base base; 1055bf215546Sopenharmony_ci ubyte shader, start, count; 1056bf215546Sopenharmony_ci void *slot[0]; /* more will be allocated if needed */ 1057bf215546Sopenharmony_ci}; 1058bf215546Sopenharmony_ci 1059bf215546Sopenharmony_cistatic uint16_t 1060bf215546Sopenharmony_citc_call_bind_sampler_states(struct pipe_context *pipe, void *call, uint64_t *last) 1061bf215546Sopenharmony_ci{ 1062bf215546Sopenharmony_ci struct tc_sampler_states *p = (struct tc_sampler_states *)call; 1063bf215546Sopenharmony_ci 1064bf215546Sopenharmony_ci pipe->bind_sampler_states(pipe, p->shader, p->start, p->count, p->slot); 1065bf215546Sopenharmony_ci return p->base.num_slots; 1066bf215546Sopenharmony_ci} 1067bf215546Sopenharmony_ci 1068bf215546Sopenharmony_cistatic void 1069bf215546Sopenharmony_citc_bind_sampler_states(struct pipe_context *_pipe, 1070bf215546Sopenharmony_ci enum pipe_shader_type shader, 1071bf215546Sopenharmony_ci unsigned start, unsigned count, void **states) 1072bf215546Sopenharmony_ci{ 1073bf215546Sopenharmony_ci if (!count) 1074bf215546Sopenharmony_ci return; 1075bf215546Sopenharmony_ci 1076bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1077bf215546Sopenharmony_ci struct tc_sampler_states *p = 1078bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_bind_sampler_states, tc_sampler_states, count); 1079bf215546Sopenharmony_ci 1080bf215546Sopenharmony_ci p->shader = shader; 1081bf215546Sopenharmony_ci p->start = start; 1082bf215546Sopenharmony_ci p->count = count; 1083bf215546Sopenharmony_ci memcpy(p->slot, states, count * sizeof(states[0])); 1084bf215546Sopenharmony_ci} 1085bf215546Sopenharmony_ci 1086bf215546Sopenharmony_cistatic void 1087bf215546Sopenharmony_citc_link_shader(struct pipe_context *_pipe, void **shaders) 1088bf215546Sopenharmony_ci{ 1089bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1090bf215546Sopenharmony_ci tc->pipe->link_shader(tc->pipe, shaders); 1091bf215546Sopenharmony_ci} 1092bf215546Sopenharmony_ci/******************************************************************** 1093bf215546Sopenharmony_ci * immediate states 1094bf215546Sopenharmony_ci */ 1095bf215546Sopenharmony_ci 1096bf215546Sopenharmony_cistruct tc_framebuffer { 1097bf215546Sopenharmony_ci struct tc_call_base base; 1098bf215546Sopenharmony_ci struct pipe_framebuffer_state state; 1099bf215546Sopenharmony_ci}; 1100bf215546Sopenharmony_ci 1101bf215546Sopenharmony_cistatic uint16_t 1102bf215546Sopenharmony_citc_call_set_framebuffer_state(struct pipe_context *pipe, void *call, uint64_t *last) 1103bf215546Sopenharmony_ci{ 1104bf215546Sopenharmony_ci struct pipe_framebuffer_state *p = &to_call(call, tc_framebuffer)->state; 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_ci pipe->set_framebuffer_state(pipe, p); 1107bf215546Sopenharmony_ci 1108bf215546Sopenharmony_ci unsigned nr_cbufs = p->nr_cbufs; 1109bf215546Sopenharmony_ci for (unsigned i = 0; i < nr_cbufs; i++) 1110bf215546Sopenharmony_ci tc_drop_surface_reference(p->cbufs[i]); 1111bf215546Sopenharmony_ci tc_drop_surface_reference(p->zsbuf); 1112bf215546Sopenharmony_ci return call_size(tc_framebuffer); 1113bf215546Sopenharmony_ci} 1114bf215546Sopenharmony_ci 1115bf215546Sopenharmony_cistatic void 1116bf215546Sopenharmony_citc_set_framebuffer_state(struct pipe_context *_pipe, 1117bf215546Sopenharmony_ci const struct pipe_framebuffer_state *fb) 1118bf215546Sopenharmony_ci{ 1119bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1120bf215546Sopenharmony_ci struct tc_framebuffer *p = 1121bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_set_framebuffer_state, tc_framebuffer); 1122bf215546Sopenharmony_ci unsigned nr_cbufs = fb->nr_cbufs; 1123bf215546Sopenharmony_ci 1124bf215546Sopenharmony_ci p->state.width = fb->width; 1125bf215546Sopenharmony_ci p->state.height = fb->height; 1126bf215546Sopenharmony_ci p->state.samples = fb->samples; 1127bf215546Sopenharmony_ci p->state.layers = fb->layers; 1128bf215546Sopenharmony_ci p->state.nr_cbufs = nr_cbufs; 1129bf215546Sopenharmony_ci 1130bf215546Sopenharmony_ci for (unsigned i = 0; i < nr_cbufs; i++) { 1131bf215546Sopenharmony_ci p->state.cbufs[i] = NULL; 1132bf215546Sopenharmony_ci pipe_surface_reference(&p->state.cbufs[i], fb->cbufs[i]); 1133bf215546Sopenharmony_ci } 1134bf215546Sopenharmony_ci p->state.zsbuf = NULL; 1135bf215546Sopenharmony_ci pipe_surface_reference(&p->state.zsbuf, fb->zsbuf); 1136bf215546Sopenharmony_ci} 1137bf215546Sopenharmony_ci 1138bf215546Sopenharmony_cistruct tc_tess_state { 1139bf215546Sopenharmony_ci struct tc_call_base base; 1140bf215546Sopenharmony_ci float state[6]; 1141bf215546Sopenharmony_ci}; 1142bf215546Sopenharmony_ci 1143bf215546Sopenharmony_cistatic uint16_t 1144bf215546Sopenharmony_citc_call_set_tess_state(struct pipe_context *pipe, void *call, uint64_t *last) 1145bf215546Sopenharmony_ci{ 1146bf215546Sopenharmony_ci float *p = to_call(call, tc_tess_state)->state; 1147bf215546Sopenharmony_ci 1148bf215546Sopenharmony_ci pipe->set_tess_state(pipe, p, p + 4); 1149bf215546Sopenharmony_ci return call_size(tc_tess_state); 1150bf215546Sopenharmony_ci} 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_cistatic void 1153bf215546Sopenharmony_citc_set_tess_state(struct pipe_context *_pipe, 1154bf215546Sopenharmony_ci const float default_outer_level[4], 1155bf215546Sopenharmony_ci const float default_inner_level[2]) 1156bf215546Sopenharmony_ci{ 1157bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1158bf215546Sopenharmony_ci float *p = tc_add_call(tc, TC_CALL_set_tess_state, tc_tess_state)->state; 1159bf215546Sopenharmony_ci 1160bf215546Sopenharmony_ci memcpy(p, default_outer_level, 4 * sizeof(float)); 1161bf215546Sopenharmony_ci memcpy(p + 4, default_inner_level, 2 * sizeof(float)); 1162bf215546Sopenharmony_ci} 1163bf215546Sopenharmony_ci 1164bf215546Sopenharmony_cistruct tc_patch_vertices { 1165bf215546Sopenharmony_ci struct tc_call_base base; 1166bf215546Sopenharmony_ci ubyte patch_vertices; 1167bf215546Sopenharmony_ci}; 1168bf215546Sopenharmony_ci 1169bf215546Sopenharmony_cistatic uint16_t 1170bf215546Sopenharmony_citc_call_set_patch_vertices(struct pipe_context *pipe, void *call, uint64_t *last) 1171bf215546Sopenharmony_ci{ 1172bf215546Sopenharmony_ci uint8_t patch_vertices = to_call(call, tc_patch_vertices)->patch_vertices; 1173bf215546Sopenharmony_ci 1174bf215546Sopenharmony_ci pipe->set_patch_vertices(pipe, patch_vertices); 1175bf215546Sopenharmony_ci return call_size(tc_patch_vertices); 1176bf215546Sopenharmony_ci} 1177bf215546Sopenharmony_ci 1178bf215546Sopenharmony_cistatic void 1179bf215546Sopenharmony_citc_set_patch_vertices(struct pipe_context *_pipe, uint8_t patch_vertices) 1180bf215546Sopenharmony_ci{ 1181bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1182bf215546Sopenharmony_ci 1183bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_set_patch_vertices, 1184bf215546Sopenharmony_ci tc_patch_vertices)->patch_vertices = patch_vertices; 1185bf215546Sopenharmony_ci} 1186bf215546Sopenharmony_ci 1187bf215546Sopenharmony_cistruct tc_constant_buffer_base { 1188bf215546Sopenharmony_ci struct tc_call_base base; 1189bf215546Sopenharmony_ci ubyte shader, index; 1190bf215546Sopenharmony_ci bool is_null; 1191bf215546Sopenharmony_ci}; 1192bf215546Sopenharmony_ci 1193bf215546Sopenharmony_cistruct tc_constant_buffer { 1194bf215546Sopenharmony_ci struct tc_constant_buffer_base base; 1195bf215546Sopenharmony_ci struct pipe_constant_buffer cb; 1196bf215546Sopenharmony_ci}; 1197bf215546Sopenharmony_ci 1198bf215546Sopenharmony_cistatic uint16_t 1199bf215546Sopenharmony_citc_call_set_constant_buffer(struct pipe_context *pipe, void *call, uint64_t *last) 1200bf215546Sopenharmony_ci{ 1201bf215546Sopenharmony_ci struct tc_constant_buffer *p = (struct tc_constant_buffer *)call; 1202bf215546Sopenharmony_ci 1203bf215546Sopenharmony_ci if (unlikely(p->base.is_null)) { 1204bf215546Sopenharmony_ci pipe->set_constant_buffer(pipe, p->base.shader, p->base.index, false, NULL); 1205bf215546Sopenharmony_ci return call_size(tc_constant_buffer_base); 1206bf215546Sopenharmony_ci } 1207bf215546Sopenharmony_ci 1208bf215546Sopenharmony_ci pipe->set_constant_buffer(pipe, p->base.shader, p->base.index, true, &p->cb); 1209bf215546Sopenharmony_ci return call_size(tc_constant_buffer); 1210bf215546Sopenharmony_ci} 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_cistatic void 1213bf215546Sopenharmony_citc_set_constant_buffer(struct pipe_context *_pipe, 1214bf215546Sopenharmony_ci enum pipe_shader_type shader, uint index, 1215bf215546Sopenharmony_ci bool take_ownership, 1216bf215546Sopenharmony_ci const struct pipe_constant_buffer *cb) 1217bf215546Sopenharmony_ci{ 1218bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci if (unlikely(!cb || (!cb->buffer && !cb->user_buffer))) { 1221bf215546Sopenharmony_ci struct tc_constant_buffer_base *p = 1222bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_set_constant_buffer, tc_constant_buffer_base); 1223bf215546Sopenharmony_ci p->shader = shader; 1224bf215546Sopenharmony_ci p->index = index; 1225bf215546Sopenharmony_ci p->is_null = true; 1226bf215546Sopenharmony_ci tc_unbind_buffer(&tc->const_buffers[shader][index]); 1227bf215546Sopenharmony_ci return; 1228bf215546Sopenharmony_ci } 1229bf215546Sopenharmony_ci 1230bf215546Sopenharmony_ci struct pipe_resource *buffer; 1231bf215546Sopenharmony_ci unsigned offset; 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_ci if (cb->user_buffer) { 1234bf215546Sopenharmony_ci /* This must be done before adding set_constant_buffer, because it could 1235bf215546Sopenharmony_ci * generate e.g. transfer_unmap and flush partially-uninitialized 1236bf215546Sopenharmony_ci * set_constant_buffer to the driver if it was done afterwards. 1237bf215546Sopenharmony_ci */ 1238bf215546Sopenharmony_ci buffer = NULL; 1239bf215546Sopenharmony_ci u_upload_data(tc->base.const_uploader, 0, cb->buffer_size, 1240bf215546Sopenharmony_ci tc->ubo_alignment, cb->user_buffer, &offset, &buffer); 1241bf215546Sopenharmony_ci u_upload_unmap(tc->base.const_uploader); 1242bf215546Sopenharmony_ci take_ownership = true; 1243bf215546Sopenharmony_ci } else { 1244bf215546Sopenharmony_ci buffer = cb->buffer; 1245bf215546Sopenharmony_ci offset = cb->buffer_offset; 1246bf215546Sopenharmony_ci } 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ci struct tc_constant_buffer *p = 1249bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_set_constant_buffer, tc_constant_buffer); 1250bf215546Sopenharmony_ci p->base.shader = shader; 1251bf215546Sopenharmony_ci p->base.index = index; 1252bf215546Sopenharmony_ci p->base.is_null = false; 1253bf215546Sopenharmony_ci p->cb.user_buffer = NULL; 1254bf215546Sopenharmony_ci p->cb.buffer_offset = offset; 1255bf215546Sopenharmony_ci p->cb.buffer_size = cb->buffer_size; 1256bf215546Sopenharmony_ci 1257bf215546Sopenharmony_ci if (take_ownership) 1258bf215546Sopenharmony_ci p->cb.buffer = buffer; 1259bf215546Sopenharmony_ci else 1260bf215546Sopenharmony_ci tc_set_resource_reference(&p->cb.buffer, buffer); 1261bf215546Sopenharmony_ci 1262bf215546Sopenharmony_ci if (buffer) { 1263bf215546Sopenharmony_ci tc_bind_buffer(tc, &tc->const_buffers[shader][index], 1264bf215546Sopenharmony_ci &tc->buffer_lists[tc->next_buf_list], buffer); 1265bf215546Sopenharmony_ci } else { 1266bf215546Sopenharmony_ci tc_unbind_buffer(&tc->const_buffers[shader][index]); 1267bf215546Sopenharmony_ci } 1268bf215546Sopenharmony_ci} 1269bf215546Sopenharmony_ci 1270bf215546Sopenharmony_cistruct tc_inlinable_constants { 1271bf215546Sopenharmony_ci struct tc_call_base base; 1272bf215546Sopenharmony_ci ubyte shader; 1273bf215546Sopenharmony_ci ubyte num_values; 1274bf215546Sopenharmony_ci uint32_t values[MAX_INLINABLE_UNIFORMS]; 1275bf215546Sopenharmony_ci}; 1276bf215546Sopenharmony_ci 1277bf215546Sopenharmony_cistatic uint16_t 1278bf215546Sopenharmony_citc_call_set_inlinable_constants(struct pipe_context *pipe, void *call, uint64_t *last) 1279bf215546Sopenharmony_ci{ 1280bf215546Sopenharmony_ci struct tc_inlinable_constants *p = to_call(call, tc_inlinable_constants); 1281bf215546Sopenharmony_ci 1282bf215546Sopenharmony_ci pipe->set_inlinable_constants(pipe, p->shader, p->num_values, p->values); 1283bf215546Sopenharmony_ci return call_size(tc_inlinable_constants); 1284bf215546Sopenharmony_ci} 1285bf215546Sopenharmony_ci 1286bf215546Sopenharmony_cistatic void 1287bf215546Sopenharmony_citc_set_inlinable_constants(struct pipe_context *_pipe, 1288bf215546Sopenharmony_ci enum pipe_shader_type shader, 1289bf215546Sopenharmony_ci uint num_values, uint32_t *values) 1290bf215546Sopenharmony_ci{ 1291bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1292bf215546Sopenharmony_ci struct tc_inlinable_constants *p = 1293bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_set_inlinable_constants, tc_inlinable_constants); 1294bf215546Sopenharmony_ci p->shader = shader; 1295bf215546Sopenharmony_ci p->num_values = num_values; 1296bf215546Sopenharmony_ci memcpy(p->values, values, num_values * 4); 1297bf215546Sopenharmony_ci} 1298bf215546Sopenharmony_ci 1299bf215546Sopenharmony_cistruct tc_sample_locations { 1300bf215546Sopenharmony_ci struct tc_call_base base; 1301bf215546Sopenharmony_ci uint16_t size; 1302bf215546Sopenharmony_ci uint8_t slot[0]; 1303bf215546Sopenharmony_ci}; 1304bf215546Sopenharmony_ci 1305bf215546Sopenharmony_ci 1306bf215546Sopenharmony_cistatic uint16_t 1307bf215546Sopenharmony_citc_call_set_sample_locations(struct pipe_context *pipe, void *call, uint64_t *last) 1308bf215546Sopenharmony_ci{ 1309bf215546Sopenharmony_ci struct tc_sample_locations *p = (struct tc_sample_locations *)call; 1310bf215546Sopenharmony_ci 1311bf215546Sopenharmony_ci pipe->set_sample_locations(pipe, p->size, p->slot); 1312bf215546Sopenharmony_ci return p->base.num_slots; 1313bf215546Sopenharmony_ci} 1314bf215546Sopenharmony_ci 1315bf215546Sopenharmony_cistatic void 1316bf215546Sopenharmony_citc_set_sample_locations(struct pipe_context *_pipe, size_t size, const uint8_t *locations) 1317bf215546Sopenharmony_ci{ 1318bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1319bf215546Sopenharmony_ci struct tc_sample_locations *p = 1320bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_sample_locations, 1321bf215546Sopenharmony_ci tc_sample_locations, size); 1322bf215546Sopenharmony_ci 1323bf215546Sopenharmony_ci p->size = size; 1324bf215546Sopenharmony_ci memcpy(p->slot, locations, size); 1325bf215546Sopenharmony_ci} 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_cistruct tc_scissors { 1328bf215546Sopenharmony_ci struct tc_call_base base; 1329bf215546Sopenharmony_ci ubyte start, count; 1330bf215546Sopenharmony_ci struct pipe_scissor_state slot[0]; /* more will be allocated if needed */ 1331bf215546Sopenharmony_ci}; 1332bf215546Sopenharmony_ci 1333bf215546Sopenharmony_cistatic uint16_t 1334bf215546Sopenharmony_citc_call_set_scissor_states(struct pipe_context *pipe, void *call, uint64_t *last) 1335bf215546Sopenharmony_ci{ 1336bf215546Sopenharmony_ci struct tc_scissors *p = (struct tc_scissors *)call; 1337bf215546Sopenharmony_ci 1338bf215546Sopenharmony_ci pipe->set_scissor_states(pipe, p->start, p->count, p->slot); 1339bf215546Sopenharmony_ci return p->base.num_slots; 1340bf215546Sopenharmony_ci} 1341bf215546Sopenharmony_ci 1342bf215546Sopenharmony_cistatic void 1343bf215546Sopenharmony_citc_set_scissor_states(struct pipe_context *_pipe, 1344bf215546Sopenharmony_ci unsigned start, unsigned count, 1345bf215546Sopenharmony_ci const struct pipe_scissor_state *states) 1346bf215546Sopenharmony_ci{ 1347bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1348bf215546Sopenharmony_ci struct tc_scissors *p = 1349bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_scissor_states, tc_scissors, count); 1350bf215546Sopenharmony_ci 1351bf215546Sopenharmony_ci p->start = start; 1352bf215546Sopenharmony_ci p->count = count; 1353bf215546Sopenharmony_ci memcpy(&p->slot, states, count * sizeof(states[0])); 1354bf215546Sopenharmony_ci} 1355bf215546Sopenharmony_ci 1356bf215546Sopenharmony_cistruct tc_viewports { 1357bf215546Sopenharmony_ci struct tc_call_base base; 1358bf215546Sopenharmony_ci ubyte start, count; 1359bf215546Sopenharmony_ci struct pipe_viewport_state slot[0]; /* more will be allocated if needed */ 1360bf215546Sopenharmony_ci}; 1361bf215546Sopenharmony_ci 1362bf215546Sopenharmony_cistatic uint16_t 1363bf215546Sopenharmony_citc_call_set_viewport_states(struct pipe_context *pipe, void *call, uint64_t *last) 1364bf215546Sopenharmony_ci{ 1365bf215546Sopenharmony_ci struct tc_viewports *p = (struct tc_viewports *)call; 1366bf215546Sopenharmony_ci 1367bf215546Sopenharmony_ci pipe->set_viewport_states(pipe, p->start, p->count, p->slot); 1368bf215546Sopenharmony_ci return p->base.num_slots; 1369bf215546Sopenharmony_ci} 1370bf215546Sopenharmony_ci 1371bf215546Sopenharmony_cistatic void 1372bf215546Sopenharmony_citc_set_viewport_states(struct pipe_context *_pipe, 1373bf215546Sopenharmony_ci unsigned start, unsigned count, 1374bf215546Sopenharmony_ci const struct pipe_viewport_state *states) 1375bf215546Sopenharmony_ci{ 1376bf215546Sopenharmony_ci if (!count) 1377bf215546Sopenharmony_ci return; 1378bf215546Sopenharmony_ci 1379bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1380bf215546Sopenharmony_ci struct tc_viewports *p = 1381bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_viewport_states, tc_viewports, count); 1382bf215546Sopenharmony_ci 1383bf215546Sopenharmony_ci p->start = start; 1384bf215546Sopenharmony_ci p->count = count; 1385bf215546Sopenharmony_ci memcpy(&p->slot, states, count * sizeof(states[0])); 1386bf215546Sopenharmony_ci} 1387bf215546Sopenharmony_ci 1388bf215546Sopenharmony_cistruct tc_window_rects { 1389bf215546Sopenharmony_ci struct tc_call_base base; 1390bf215546Sopenharmony_ci bool include; 1391bf215546Sopenharmony_ci ubyte count; 1392bf215546Sopenharmony_ci struct pipe_scissor_state slot[0]; /* more will be allocated if needed */ 1393bf215546Sopenharmony_ci}; 1394bf215546Sopenharmony_ci 1395bf215546Sopenharmony_cistatic uint16_t 1396bf215546Sopenharmony_citc_call_set_window_rectangles(struct pipe_context *pipe, void *call, uint64_t *last) 1397bf215546Sopenharmony_ci{ 1398bf215546Sopenharmony_ci struct tc_window_rects *p = (struct tc_window_rects *)call; 1399bf215546Sopenharmony_ci 1400bf215546Sopenharmony_ci pipe->set_window_rectangles(pipe, p->include, p->count, p->slot); 1401bf215546Sopenharmony_ci return p->base.num_slots; 1402bf215546Sopenharmony_ci} 1403bf215546Sopenharmony_ci 1404bf215546Sopenharmony_cistatic void 1405bf215546Sopenharmony_citc_set_window_rectangles(struct pipe_context *_pipe, bool include, 1406bf215546Sopenharmony_ci unsigned count, 1407bf215546Sopenharmony_ci const struct pipe_scissor_state *rects) 1408bf215546Sopenharmony_ci{ 1409bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1410bf215546Sopenharmony_ci struct tc_window_rects *p = 1411bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_window_rectangles, tc_window_rects, count); 1412bf215546Sopenharmony_ci 1413bf215546Sopenharmony_ci p->include = include; 1414bf215546Sopenharmony_ci p->count = count; 1415bf215546Sopenharmony_ci memcpy(p->slot, rects, count * sizeof(rects[0])); 1416bf215546Sopenharmony_ci} 1417bf215546Sopenharmony_ci 1418bf215546Sopenharmony_cistruct tc_sampler_views { 1419bf215546Sopenharmony_ci struct tc_call_base base; 1420bf215546Sopenharmony_ci ubyte shader, start, count, unbind_num_trailing_slots; 1421bf215546Sopenharmony_ci struct pipe_sampler_view *slot[0]; /* more will be allocated if needed */ 1422bf215546Sopenharmony_ci}; 1423bf215546Sopenharmony_ci 1424bf215546Sopenharmony_cistatic uint16_t 1425bf215546Sopenharmony_citc_call_set_sampler_views(struct pipe_context *pipe, void *call, uint64_t *last) 1426bf215546Sopenharmony_ci{ 1427bf215546Sopenharmony_ci struct tc_sampler_views *p = (struct tc_sampler_views *)call; 1428bf215546Sopenharmony_ci 1429bf215546Sopenharmony_ci pipe->set_sampler_views(pipe, p->shader, p->start, p->count, 1430bf215546Sopenharmony_ci p->unbind_num_trailing_slots, true, p->slot); 1431bf215546Sopenharmony_ci return p->base.num_slots; 1432bf215546Sopenharmony_ci} 1433bf215546Sopenharmony_ci 1434bf215546Sopenharmony_cistatic void 1435bf215546Sopenharmony_citc_set_sampler_views(struct pipe_context *_pipe, 1436bf215546Sopenharmony_ci enum pipe_shader_type shader, 1437bf215546Sopenharmony_ci unsigned start, unsigned count, 1438bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, bool take_ownership, 1439bf215546Sopenharmony_ci struct pipe_sampler_view **views) 1440bf215546Sopenharmony_ci{ 1441bf215546Sopenharmony_ci if (!count && !unbind_num_trailing_slots) 1442bf215546Sopenharmony_ci return; 1443bf215546Sopenharmony_ci 1444bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1445bf215546Sopenharmony_ci struct tc_sampler_views *p = 1446bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_sampler_views, tc_sampler_views, 1447bf215546Sopenharmony_ci views ? count : 0); 1448bf215546Sopenharmony_ci 1449bf215546Sopenharmony_ci p->shader = shader; 1450bf215546Sopenharmony_ci p->start = start; 1451bf215546Sopenharmony_ci 1452bf215546Sopenharmony_ci if (views) { 1453bf215546Sopenharmony_ci struct tc_buffer_list *next = &tc->buffer_lists[tc->next_buf_list]; 1454bf215546Sopenharmony_ci 1455bf215546Sopenharmony_ci p->count = count; 1456bf215546Sopenharmony_ci p->unbind_num_trailing_slots = unbind_num_trailing_slots; 1457bf215546Sopenharmony_ci 1458bf215546Sopenharmony_ci if (take_ownership) { 1459bf215546Sopenharmony_ci memcpy(p->slot, views, sizeof(*views) * count); 1460bf215546Sopenharmony_ci 1461bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 1462bf215546Sopenharmony_ci if (views[i] && views[i]->target == PIPE_BUFFER) { 1463bf215546Sopenharmony_ci tc_bind_buffer(tc, &tc->sampler_buffers[shader][start + i], next, 1464bf215546Sopenharmony_ci views[i]->texture); 1465bf215546Sopenharmony_ci } else { 1466bf215546Sopenharmony_ci tc_unbind_buffer(&tc->sampler_buffers[shader][start + i]); 1467bf215546Sopenharmony_ci } 1468bf215546Sopenharmony_ci } 1469bf215546Sopenharmony_ci } else { 1470bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 1471bf215546Sopenharmony_ci p->slot[i] = NULL; 1472bf215546Sopenharmony_ci pipe_sampler_view_reference(&p->slot[i], views[i]); 1473bf215546Sopenharmony_ci 1474bf215546Sopenharmony_ci if (views[i] && views[i]->target == PIPE_BUFFER) { 1475bf215546Sopenharmony_ci tc_bind_buffer(tc, &tc->sampler_buffers[shader][start + i], next, 1476bf215546Sopenharmony_ci views[i]->texture); 1477bf215546Sopenharmony_ci } else { 1478bf215546Sopenharmony_ci tc_unbind_buffer(&tc->sampler_buffers[shader][start + i]); 1479bf215546Sopenharmony_ci } 1480bf215546Sopenharmony_ci } 1481bf215546Sopenharmony_ci } 1482bf215546Sopenharmony_ci 1483bf215546Sopenharmony_ci tc_unbind_buffers(&tc->sampler_buffers[shader][start + count], 1484bf215546Sopenharmony_ci unbind_num_trailing_slots); 1485bf215546Sopenharmony_ci tc->seen_sampler_buffers[shader] = true; 1486bf215546Sopenharmony_ci } else { 1487bf215546Sopenharmony_ci p->count = 0; 1488bf215546Sopenharmony_ci p->unbind_num_trailing_slots = count + unbind_num_trailing_slots; 1489bf215546Sopenharmony_ci 1490bf215546Sopenharmony_ci tc_unbind_buffers(&tc->sampler_buffers[shader][start], 1491bf215546Sopenharmony_ci count + unbind_num_trailing_slots); 1492bf215546Sopenharmony_ci } 1493bf215546Sopenharmony_ci} 1494bf215546Sopenharmony_ci 1495bf215546Sopenharmony_cistruct tc_shader_images { 1496bf215546Sopenharmony_ci struct tc_call_base base; 1497bf215546Sopenharmony_ci ubyte shader, start, count; 1498bf215546Sopenharmony_ci ubyte unbind_num_trailing_slots; 1499bf215546Sopenharmony_ci struct pipe_image_view slot[0]; /* more will be allocated if needed */ 1500bf215546Sopenharmony_ci}; 1501bf215546Sopenharmony_ci 1502bf215546Sopenharmony_cistatic uint16_t 1503bf215546Sopenharmony_citc_call_set_shader_images(struct pipe_context *pipe, void *call, uint64_t *last) 1504bf215546Sopenharmony_ci{ 1505bf215546Sopenharmony_ci struct tc_shader_images *p = (struct tc_shader_images *)call; 1506bf215546Sopenharmony_ci unsigned count = p->count; 1507bf215546Sopenharmony_ci 1508bf215546Sopenharmony_ci if (!p->count) { 1509bf215546Sopenharmony_ci pipe->set_shader_images(pipe, p->shader, p->start, 0, 1510bf215546Sopenharmony_ci p->unbind_num_trailing_slots, NULL); 1511bf215546Sopenharmony_ci return call_size(tc_shader_images); 1512bf215546Sopenharmony_ci } 1513bf215546Sopenharmony_ci 1514bf215546Sopenharmony_ci pipe->set_shader_images(pipe, p->shader, p->start, p->count, 1515bf215546Sopenharmony_ci p->unbind_num_trailing_slots, p->slot); 1516bf215546Sopenharmony_ci 1517bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) 1518bf215546Sopenharmony_ci tc_drop_resource_reference(p->slot[i].resource); 1519bf215546Sopenharmony_ci 1520bf215546Sopenharmony_ci return p->base.num_slots; 1521bf215546Sopenharmony_ci} 1522bf215546Sopenharmony_ci 1523bf215546Sopenharmony_cistatic void 1524bf215546Sopenharmony_citc_set_shader_images(struct pipe_context *_pipe, 1525bf215546Sopenharmony_ci enum pipe_shader_type shader, 1526bf215546Sopenharmony_ci unsigned start, unsigned count, 1527bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, 1528bf215546Sopenharmony_ci const struct pipe_image_view *images) 1529bf215546Sopenharmony_ci{ 1530bf215546Sopenharmony_ci if (!count && !unbind_num_trailing_slots) 1531bf215546Sopenharmony_ci return; 1532bf215546Sopenharmony_ci 1533bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1534bf215546Sopenharmony_ci struct tc_shader_images *p = 1535bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_shader_images, tc_shader_images, 1536bf215546Sopenharmony_ci images ? count : 0); 1537bf215546Sopenharmony_ci unsigned writable_buffers = 0; 1538bf215546Sopenharmony_ci 1539bf215546Sopenharmony_ci p->shader = shader; 1540bf215546Sopenharmony_ci p->start = start; 1541bf215546Sopenharmony_ci 1542bf215546Sopenharmony_ci if (images) { 1543bf215546Sopenharmony_ci p->count = count; 1544bf215546Sopenharmony_ci p->unbind_num_trailing_slots = unbind_num_trailing_slots; 1545bf215546Sopenharmony_ci 1546bf215546Sopenharmony_ci struct tc_buffer_list *next = &tc->buffer_lists[tc->next_buf_list]; 1547bf215546Sopenharmony_ci 1548bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 1549bf215546Sopenharmony_ci struct pipe_resource *resource = images[i].resource; 1550bf215546Sopenharmony_ci 1551bf215546Sopenharmony_ci tc_set_resource_reference(&p->slot[i].resource, resource); 1552bf215546Sopenharmony_ci 1553bf215546Sopenharmony_ci if (resource && resource->target == PIPE_BUFFER) { 1554bf215546Sopenharmony_ci tc_bind_buffer(tc, &tc->image_buffers[shader][start + i], next, resource); 1555bf215546Sopenharmony_ci 1556bf215546Sopenharmony_ci if (images[i].access & PIPE_IMAGE_ACCESS_WRITE) { 1557bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(resource); 1558bf215546Sopenharmony_ci 1559bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(resource); 1560bf215546Sopenharmony_ci util_range_add(&tres->b, &tres->valid_buffer_range, 1561bf215546Sopenharmony_ci images[i].u.buf.offset, 1562bf215546Sopenharmony_ci images[i].u.buf.offset + images[i].u.buf.size); 1563bf215546Sopenharmony_ci writable_buffers |= BITFIELD_BIT(start + i); 1564bf215546Sopenharmony_ci } 1565bf215546Sopenharmony_ci } else { 1566bf215546Sopenharmony_ci tc_unbind_buffer(&tc->image_buffers[shader][start + i]); 1567bf215546Sopenharmony_ci } 1568bf215546Sopenharmony_ci } 1569bf215546Sopenharmony_ci memcpy(p->slot, images, count * sizeof(images[0])); 1570bf215546Sopenharmony_ci 1571bf215546Sopenharmony_ci tc_unbind_buffers(&tc->image_buffers[shader][start + count], 1572bf215546Sopenharmony_ci unbind_num_trailing_slots); 1573bf215546Sopenharmony_ci tc->seen_image_buffers[shader] = true; 1574bf215546Sopenharmony_ci } else { 1575bf215546Sopenharmony_ci p->count = 0; 1576bf215546Sopenharmony_ci p->unbind_num_trailing_slots = count + unbind_num_trailing_slots; 1577bf215546Sopenharmony_ci 1578bf215546Sopenharmony_ci tc_unbind_buffers(&tc->image_buffers[shader][start], 1579bf215546Sopenharmony_ci count + unbind_num_trailing_slots); 1580bf215546Sopenharmony_ci } 1581bf215546Sopenharmony_ci 1582bf215546Sopenharmony_ci tc->image_buffers_writeable_mask[shader] &= ~BITFIELD_RANGE(start, count); 1583bf215546Sopenharmony_ci tc->image_buffers_writeable_mask[shader] |= writable_buffers; 1584bf215546Sopenharmony_ci} 1585bf215546Sopenharmony_ci 1586bf215546Sopenharmony_cistruct tc_shader_buffers { 1587bf215546Sopenharmony_ci struct tc_call_base base; 1588bf215546Sopenharmony_ci ubyte shader, start, count; 1589bf215546Sopenharmony_ci bool unbind; 1590bf215546Sopenharmony_ci unsigned writable_bitmask; 1591bf215546Sopenharmony_ci struct pipe_shader_buffer slot[0]; /* more will be allocated if needed */ 1592bf215546Sopenharmony_ci}; 1593bf215546Sopenharmony_ci 1594bf215546Sopenharmony_cistatic uint16_t 1595bf215546Sopenharmony_citc_call_set_shader_buffers(struct pipe_context *pipe, void *call, uint64_t *last) 1596bf215546Sopenharmony_ci{ 1597bf215546Sopenharmony_ci struct tc_shader_buffers *p = (struct tc_shader_buffers *)call; 1598bf215546Sopenharmony_ci unsigned count = p->count; 1599bf215546Sopenharmony_ci 1600bf215546Sopenharmony_ci if (p->unbind) { 1601bf215546Sopenharmony_ci pipe->set_shader_buffers(pipe, p->shader, p->start, p->count, NULL, 0); 1602bf215546Sopenharmony_ci return call_size(tc_shader_buffers); 1603bf215546Sopenharmony_ci } 1604bf215546Sopenharmony_ci 1605bf215546Sopenharmony_ci pipe->set_shader_buffers(pipe, p->shader, p->start, p->count, p->slot, 1606bf215546Sopenharmony_ci p->writable_bitmask); 1607bf215546Sopenharmony_ci 1608bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) 1609bf215546Sopenharmony_ci tc_drop_resource_reference(p->slot[i].buffer); 1610bf215546Sopenharmony_ci 1611bf215546Sopenharmony_ci return p->base.num_slots; 1612bf215546Sopenharmony_ci} 1613bf215546Sopenharmony_ci 1614bf215546Sopenharmony_cistatic void 1615bf215546Sopenharmony_citc_set_shader_buffers(struct pipe_context *_pipe, 1616bf215546Sopenharmony_ci enum pipe_shader_type shader, 1617bf215546Sopenharmony_ci unsigned start, unsigned count, 1618bf215546Sopenharmony_ci const struct pipe_shader_buffer *buffers, 1619bf215546Sopenharmony_ci unsigned writable_bitmask) 1620bf215546Sopenharmony_ci{ 1621bf215546Sopenharmony_ci if (!count) 1622bf215546Sopenharmony_ci return; 1623bf215546Sopenharmony_ci 1624bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1625bf215546Sopenharmony_ci struct tc_shader_buffers *p = 1626bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_shader_buffers, tc_shader_buffers, 1627bf215546Sopenharmony_ci buffers ? count : 0); 1628bf215546Sopenharmony_ci 1629bf215546Sopenharmony_ci p->shader = shader; 1630bf215546Sopenharmony_ci p->start = start; 1631bf215546Sopenharmony_ci p->count = count; 1632bf215546Sopenharmony_ci p->unbind = buffers == NULL; 1633bf215546Sopenharmony_ci p->writable_bitmask = writable_bitmask; 1634bf215546Sopenharmony_ci 1635bf215546Sopenharmony_ci if (buffers) { 1636bf215546Sopenharmony_ci struct tc_buffer_list *next = &tc->buffer_lists[tc->next_buf_list]; 1637bf215546Sopenharmony_ci 1638bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 1639bf215546Sopenharmony_ci struct pipe_shader_buffer *dst = &p->slot[i]; 1640bf215546Sopenharmony_ci const struct pipe_shader_buffer *src = buffers + i; 1641bf215546Sopenharmony_ci 1642bf215546Sopenharmony_ci tc_set_resource_reference(&dst->buffer, src->buffer); 1643bf215546Sopenharmony_ci dst->buffer_offset = src->buffer_offset; 1644bf215546Sopenharmony_ci dst->buffer_size = src->buffer_size; 1645bf215546Sopenharmony_ci 1646bf215546Sopenharmony_ci if (src->buffer) { 1647bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(src->buffer); 1648bf215546Sopenharmony_ci 1649bf215546Sopenharmony_ci tc_bind_buffer(tc, &tc->shader_buffers[shader][start + i], next, &tres->b); 1650bf215546Sopenharmony_ci 1651bf215546Sopenharmony_ci if (writable_bitmask & BITFIELD_BIT(i)) { 1652bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(src->buffer); 1653bf215546Sopenharmony_ci util_range_add(&tres->b, &tres->valid_buffer_range, 1654bf215546Sopenharmony_ci src->buffer_offset, 1655bf215546Sopenharmony_ci src->buffer_offset + src->buffer_size); 1656bf215546Sopenharmony_ci } 1657bf215546Sopenharmony_ci } else { 1658bf215546Sopenharmony_ci tc_unbind_buffer(&tc->shader_buffers[shader][start + i]); 1659bf215546Sopenharmony_ci } 1660bf215546Sopenharmony_ci } 1661bf215546Sopenharmony_ci tc->seen_shader_buffers[shader] = true; 1662bf215546Sopenharmony_ci } else { 1663bf215546Sopenharmony_ci tc_unbind_buffers(&tc->shader_buffers[shader][start], count); 1664bf215546Sopenharmony_ci } 1665bf215546Sopenharmony_ci 1666bf215546Sopenharmony_ci tc->shader_buffers_writeable_mask[shader] &= ~BITFIELD_RANGE(start, count); 1667bf215546Sopenharmony_ci tc->shader_buffers_writeable_mask[shader] |= writable_bitmask << start; 1668bf215546Sopenharmony_ci} 1669bf215546Sopenharmony_ci 1670bf215546Sopenharmony_cistruct tc_vertex_buffers { 1671bf215546Sopenharmony_ci struct tc_call_base base; 1672bf215546Sopenharmony_ci ubyte start, count; 1673bf215546Sopenharmony_ci ubyte unbind_num_trailing_slots; 1674bf215546Sopenharmony_ci struct pipe_vertex_buffer slot[0]; /* more will be allocated if needed */ 1675bf215546Sopenharmony_ci}; 1676bf215546Sopenharmony_ci 1677bf215546Sopenharmony_cistatic uint16_t 1678bf215546Sopenharmony_citc_call_set_vertex_buffers(struct pipe_context *pipe, void *call, uint64_t *last) 1679bf215546Sopenharmony_ci{ 1680bf215546Sopenharmony_ci struct tc_vertex_buffers *p = (struct tc_vertex_buffers *)call; 1681bf215546Sopenharmony_ci unsigned count = p->count; 1682bf215546Sopenharmony_ci 1683bf215546Sopenharmony_ci if (!count) { 1684bf215546Sopenharmony_ci pipe->set_vertex_buffers(pipe, p->start, 0, 1685bf215546Sopenharmony_ci p->unbind_num_trailing_slots, false, NULL); 1686bf215546Sopenharmony_ci return call_size(tc_vertex_buffers); 1687bf215546Sopenharmony_ci } 1688bf215546Sopenharmony_ci 1689bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) 1690bf215546Sopenharmony_ci tc_assert(!p->slot[i].is_user_buffer); 1691bf215546Sopenharmony_ci 1692bf215546Sopenharmony_ci pipe->set_vertex_buffers(pipe, p->start, count, 1693bf215546Sopenharmony_ci p->unbind_num_trailing_slots, true, p->slot); 1694bf215546Sopenharmony_ci return p->base.num_slots; 1695bf215546Sopenharmony_ci} 1696bf215546Sopenharmony_ci 1697bf215546Sopenharmony_cistatic void 1698bf215546Sopenharmony_citc_set_vertex_buffers(struct pipe_context *_pipe, 1699bf215546Sopenharmony_ci unsigned start, unsigned count, 1700bf215546Sopenharmony_ci unsigned unbind_num_trailing_slots, 1701bf215546Sopenharmony_ci bool take_ownership, 1702bf215546Sopenharmony_ci const struct pipe_vertex_buffer *buffers) 1703bf215546Sopenharmony_ci{ 1704bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1705bf215546Sopenharmony_ci 1706bf215546Sopenharmony_ci if (!count && !unbind_num_trailing_slots) 1707bf215546Sopenharmony_ci return; 1708bf215546Sopenharmony_ci 1709bf215546Sopenharmony_ci if (count && buffers) { 1710bf215546Sopenharmony_ci struct tc_vertex_buffers *p = 1711bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_vertex_buffers, tc_vertex_buffers, count); 1712bf215546Sopenharmony_ci p->start = start; 1713bf215546Sopenharmony_ci p->count = count; 1714bf215546Sopenharmony_ci p->unbind_num_trailing_slots = unbind_num_trailing_slots; 1715bf215546Sopenharmony_ci 1716bf215546Sopenharmony_ci struct tc_buffer_list *next = &tc->buffer_lists[tc->next_buf_list]; 1717bf215546Sopenharmony_ci 1718bf215546Sopenharmony_ci if (take_ownership) { 1719bf215546Sopenharmony_ci memcpy(p->slot, buffers, count * sizeof(struct pipe_vertex_buffer)); 1720bf215546Sopenharmony_ci 1721bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 1722bf215546Sopenharmony_ci struct pipe_resource *buf = buffers[i].buffer.resource; 1723bf215546Sopenharmony_ci 1724bf215546Sopenharmony_ci if (buf) { 1725bf215546Sopenharmony_ci tc_bind_buffer(tc, &tc->vertex_buffers[start + i], next, buf); 1726bf215546Sopenharmony_ci } else { 1727bf215546Sopenharmony_ci tc_unbind_buffer(&tc->vertex_buffers[start + i]); 1728bf215546Sopenharmony_ci } 1729bf215546Sopenharmony_ci } 1730bf215546Sopenharmony_ci } else { 1731bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 1732bf215546Sopenharmony_ci struct pipe_vertex_buffer *dst = &p->slot[i]; 1733bf215546Sopenharmony_ci const struct pipe_vertex_buffer *src = buffers + i; 1734bf215546Sopenharmony_ci struct pipe_resource *buf = src->buffer.resource; 1735bf215546Sopenharmony_ci 1736bf215546Sopenharmony_ci tc_assert(!src->is_user_buffer); 1737bf215546Sopenharmony_ci dst->stride = src->stride; 1738bf215546Sopenharmony_ci dst->is_user_buffer = false; 1739bf215546Sopenharmony_ci tc_set_resource_reference(&dst->buffer.resource, buf); 1740bf215546Sopenharmony_ci dst->buffer_offset = src->buffer_offset; 1741bf215546Sopenharmony_ci 1742bf215546Sopenharmony_ci if (buf) { 1743bf215546Sopenharmony_ci tc_bind_buffer(tc, &tc->vertex_buffers[start + i], next, buf); 1744bf215546Sopenharmony_ci } else { 1745bf215546Sopenharmony_ci tc_unbind_buffer(&tc->vertex_buffers[start + i]); 1746bf215546Sopenharmony_ci } 1747bf215546Sopenharmony_ci } 1748bf215546Sopenharmony_ci } 1749bf215546Sopenharmony_ci 1750bf215546Sopenharmony_ci tc_unbind_buffers(&tc->vertex_buffers[start + count], 1751bf215546Sopenharmony_ci unbind_num_trailing_slots); 1752bf215546Sopenharmony_ci } else { 1753bf215546Sopenharmony_ci struct tc_vertex_buffers *p = 1754bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_set_vertex_buffers, tc_vertex_buffers, 0); 1755bf215546Sopenharmony_ci p->start = start; 1756bf215546Sopenharmony_ci p->count = 0; 1757bf215546Sopenharmony_ci p->unbind_num_trailing_slots = count + unbind_num_trailing_slots; 1758bf215546Sopenharmony_ci 1759bf215546Sopenharmony_ci tc_unbind_buffers(&tc->vertex_buffers[start], 1760bf215546Sopenharmony_ci count + unbind_num_trailing_slots); 1761bf215546Sopenharmony_ci } 1762bf215546Sopenharmony_ci} 1763bf215546Sopenharmony_ci 1764bf215546Sopenharmony_cistruct tc_stream_outputs { 1765bf215546Sopenharmony_ci struct tc_call_base base; 1766bf215546Sopenharmony_ci unsigned count; 1767bf215546Sopenharmony_ci struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS]; 1768bf215546Sopenharmony_ci unsigned offsets[PIPE_MAX_SO_BUFFERS]; 1769bf215546Sopenharmony_ci}; 1770bf215546Sopenharmony_ci 1771bf215546Sopenharmony_cistatic uint16_t 1772bf215546Sopenharmony_citc_call_set_stream_output_targets(struct pipe_context *pipe, void *call, uint64_t *last) 1773bf215546Sopenharmony_ci{ 1774bf215546Sopenharmony_ci struct tc_stream_outputs *p = to_call(call, tc_stream_outputs); 1775bf215546Sopenharmony_ci unsigned count = p->count; 1776bf215546Sopenharmony_ci 1777bf215546Sopenharmony_ci pipe->set_stream_output_targets(pipe, count, p->targets, p->offsets); 1778bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) 1779bf215546Sopenharmony_ci tc_drop_so_target_reference(p->targets[i]); 1780bf215546Sopenharmony_ci 1781bf215546Sopenharmony_ci return call_size(tc_stream_outputs); 1782bf215546Sopenharmony_ci} 1783bf215546Sopenharmony_ci 1784bf215546Sopenharmony_cistatic void 1785bf215546Sopenharmony_citc_set_stream_output_targets(struct pipe_context *_pipe, 1786bf215546Sopenharmony_ci unsigned count, 1787bf215546Sopenharmony_ci struct pipe_stream_output_target **tgs, 1788bf215546Sopenharmony_ci const unsigned *offsets) 1789bf215546Sopenharmony_ci{ 1790bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1791bf215546Sopenharmony_ci struct tc_stream_outputs *p = 1792bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_set_stream_output_targets, tc_stream_outputs); 1793bf215546Sopenharmony_ci struct tc_buffer_list *next = &tc->buffer_lists[tc->next_buf_list]; 1794bf215546Sopenharmony_ci 1795bf215546Sopenharmony_ci for (unsigned i = 0; i < count; i++) { 1796bf215546Sopenharmony_ci p->targets[i] = NULL; 1797bf215546Sopenharmony_ci pipe_so_target_reference(&p->targets[i], tgs[i]); 1798bf215546Sopenharmony_ci if (tgs[i]) { 1799bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(tgs[i]->buffer); 1800bf215546Sopenharmony_ci tc_bind_buffer(tc, &tc->streamout_buffers[i], next, tgs[i]->buffer); 1801bf215546Sopenharmony_ci } else { 1802bf215546Sopenharmony_ci tc_unbind_buffer(&tc->streamout_buffers[i]); 1803bf215546Sopenharmony_ci } 1804bf215546Sopenharmony_ci } 1805bf215546Sopenharmony_ci p->count = count; 1806bf215546Sopenharmony_ci memcpy(p->offsets, offsets, count * sizeof(unsigned)); 1807bf215546Sopenharmony_ci 1808bf215546Sopenharmony_ci tc_unbind_buffers(&tc->streamout_buffers[count], PIPE_MAX_SO_BUFFERS - count); 1809bf215546Sopenharmony_ci if (count) 1810bf215546Sopenharmony_ci tc->seen_streamout_buffers = true; 1811bf215546Sopenharmony_ci} 1812bf215546Sopenharmony_ci 1813bf215546Sopenharmony_cistatic void 1814bf215546Sopenharmony_citc_set_compute_resources(struct pipe_context *_pipe, unsigned start, 1815bf215546Sopenharmony_ci unsigned count, struct pipe_surface **resources) 1816bf215546Sopenharmony_ci{ 1817bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1818bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 1819bf215546Sopenharmony_ci 1820bf215546Sopenharmony_ci tc_sync(tc); 1821bf215546Sopenharmony_ci pipe->set_compute_resources(pipe, start, count, resources); 1822bf215546Sopenharmony_ci} 1823bf215546Sopenharmony_ci 1824bf215546Sopenharmony_cistatic void 1825bf215546Sopenharmony_citc_set_global_binding(struct pipe_context *_pipe, unsigned first, 1826bf215546Sopenharmony_ci unsigned count, struct pipe_resource **resources, 1827bf215546Sopenharmony_ci uint32_t **handles) 1828bf215546Sopenharmony_ci{ 1829bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1830bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 1831bf215546Sopenharmony_ci 1832bf215546Sopenharmony_ci tc_sync(tc); 1833bf215546Sopenharmony_ci pipe->set_global_binding(pipe, first, count, resources, handles); 1834bf215546Sopenharmony_ci} 1835bf215546Sopenharmony_ci 1836bf215546Sopenharmony_ci 1837bf215546Sopenharmony_ci/******************************************************************** 1838bf215546Sopenharmony_ci * views 1839bf215546Sopenharmony_ci */ 1840bf215546Sopenharmony_ci 1841bf215546Sopenharmony_cistatic struct pipe_surface * 1842bf215546Sopenharmony_citc_create_surface(struct pipe_context *_pipe, 1843bf215546Sopenharmony_ci struct pipe_resource *resource, 1844bf215546Sopenharmony_ci const struct pipe_surface *surf_tmpl) 1845bf215546Sopenharmony_ci{ 1846bf215546Sopenharmony_ci struct pipe_context *pipe = threaded_context(_pipe)->pipe; 1847bf215546Sopenharmony_ci struct pipe_surface *view = 1848bf215546Sopenharmony_ci pipe->create_surface(pipe, resource, surf_tmpl); 1849bf215546Sopenharmony_ci 1850bf215546Sopenharmony_ci if (view) 1851bf215546Sopenharmony_ci view->context = _pipe; 1852bf215546Sopenharmony_ci return view; 1853bf215546Sopenharmony_ci} 1854bf215546Sopenharmony_ci 1855bf215546Sopenharmony_cistatic void 1856bf215546Sopenharmony_citc_surface_destroy(struct pipe_context *_pipe, 1857bf215546Sopenharmony_ci struct pipe_surface *surf) 1858bf215546Sopenharmony_ci{ 1859bf215546Sopenharmony_ci struct pipe_context *pipe = threaded_context(_pipe)->pipe; 1860bf215546Sopenharmony_ci 1861bf215546Sopenharmony_ci pipe->surface_destroy(pipe, surf); 1862bf215546Sopenharmony_ci} 1863bf215546Sopenharmony_ci 1864bf215546Sopenharmony_cistatic struct pipe_sampler_view * 1865bf215546Sopenharmony_citc_create_sampler_view(struct pipe_context *_pipe, 1866bf215546Sopenharmony_ci struct pipe_resource *resource, 1867bf215546Sopenharmony_ci const struct pipe_sampler_view *templ) 1868bf215546Sopenharmony_ci{ 1869bf215546Sopenharmony_ci struct pipe_context *pipe = threaded_context(_pipe)->pipe; 1870bf215546Sopenharmony_ci struct pipe_sampler_view *view = 1871bf215546Sopenharmony_ci pipe->create_sampler_view(pipe, resource, templ); 1872bf215546Sopenharmony_ci 1873bf215546Sopenharmony_ci if (view) 1874bf215546Sopenharmony_ci view->context = _pipe; 1875bf215546Sopenharmony_ci return view; 1876bf215546Sopenharmony_ci} 1877bf215546Sopenharmony_ci 1878bf215546Sopenharmony_cistatic void 1879bf215546Sopenharmony_citc_sampler_view_destroy(struct pipe_context *_pipe, 1880bf215546Sopenharmony_ci struct pipe_sampler_view *view) 1881bf215546Sopenharmony_ci{ 1882bf215546Sopenharmony_ci struct pipe_context *pipe = threaded_context(_pipe)->pipe; 1883bf215546Sopenharmony_ci 1884bf215546Sopenharmony_ci pipe->sampler_view_destroy(pipe, view); 1885bf215546Sopenharmony_ci} 1886bf215546Sopenharmony_ci 1887bf215546Sopenharmony_cistatic struct pipe_stream_output_target * 1888bf215546Sopenharmony_citc_create_stream_output_target(struct pipe_context *_pipe, 1889bf215546Sopenharmony_ci struct pipe_resource *res, 1890bf215546Sopenharmony_ci unsigned buffer_offset, 1891bf215546Sopenharmony_ci unsigned buffer_size) 1892bf215546Sopenharmony_ci{ 1893bf215546Sopenharmony_ci struct pipe_context *pipe = threaded_context(_pipe)->pipe; 1894bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(res); 1895bf215546Sopenharmony_ci struct pipe_stream_output_target *view; 1896bf215546Sopenharmony_ci 1897bf215546Sopenharmony_ci util_range_add(&tres->b, &tres->valid_buffer_range, buffer_offset, 1898bf215546Sopenharmony_ci buffer_offset + buffer_size); 1899bf215546Sopenharmony_ci 1900bf215546Sopenharmony_ci view = pipe->create_stream_output_target(pipe, res, buffer_offset, 1901bf215546Sopenharmony_ci buffer_size); 1902bf215546Sopenharmony_ci if (view) 1903bf215546Sopenharmony_ci view->context = _pipe; 1904bf215546Sopenharmony_ci return view; 1905bf215546Sopenharmony_ci} 1906bf215546Sopenharmony_ci 1907bf215546Sopenharmony_cistatic void 1908bf215546Sopenharmony_citc_stream_output_target_destroy(struct pipe_context *_pipe, 1909bf215546Sopenharmony_ci struct pipe_stream_output_target *target) 1910bf215546Sopenharmony_ci{ 1911bf215546Sopenharmony_ci struct pipe_context *pipe = threaded_context(_pipe)->pipe; 1912bf215546Sopenharmony_ci 1913bf215546Sopenharmony_ci pipe->stream_output_target_destroy(pipe, target); 1914bf215546Sopenharmony_ci} 1915bf215546Sopenharmony_ci 1916bf215546Sopenharmony_ci 1917bf215546Sopenharmony_ci/******************************************************************** 1918bf215546Sopenharmony_ci * bindless 1919bf215546Sopenharmony_ci */ 1920bf215546Sopenharmony_ci 1921bf215546Sopenharmony_cistatic uint64_t 1922bf215546Sopenharmony_citc_create_texture_handle(struct pipe_context *_pipe, 1923bf215546Sopenharmony_ci struct pipe_sampler_view *view, 1924bf215546Sopenharmony_ci const struct pipe_sampler_state *state) 1925bf215546Sopenharmony_ci{ 1926bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1927bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 1928bf215546Sopenharmony_ci 1929bf215546Sopenharmony_ci tc_sync(tc); 1930bf215546Sopenharmony_ci return pipe->create_texture_handle(pipe, view, state); 1931bf215546Sopenharmony_ci} 1932bf215546Sopenharmony_ci 1933bf215546Sopenharmony_cistruct tc_make_texture_handle_resident { 1934bf215546Sopenharmony_ci struct tc_call_base base; 1935bf215546Sopenharmony_ci bool resident; 1936bf215546Sopenharmony_ci uint64_t handle; 1937bf215546Sopenharmony_ci}; 1938bf215546Sopenharmony_ci 1939bf215546Sopenharmony_cistatic uint16_t 1940bf215546Sopenharmony_citc_call_make_texture_handle_resident(struct pipe_context *pipe, void *call, uint64_t *last) 1941bf215546Sopenharmony_ci{ 1942bf215546Sopenharmony_ci struct tc_make_texture_handle_resident *p = 1943bf215546Sopenharmony_ci to_call(call, tc_make_texture_handle_resident); 1944bf215546Sopenharmony_ci 1945bf215546Sopenharmony_ci pipe->make_texture_handle_resident(pipe, p->handle, p->resident); 1946bf215546Sopenharmony_ci return call_size(tc_make_texture_handle_resident); 1947bf215546Sopenharmony_ci} 1948bf215546Sopenharmony_ci 1949bf215546Sopenharmony_cistatic void 1950bf215546Sopenharmony_citc_make_texture_handle_resident(struct pipe_context *_pipe, uint64_t handle, 1951bf215546Sopenharmony_ci bool resident) 1952bf215546Sopenharmony_ci{ 1953bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1954bf215546Sopenharmony_ci struct tc_make_texture_handle_resident *p = 1955bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_make_texture_handle_resident, 1956bf215546Sopenharmony_ci tc_make_texture_handle_resident); 1957bf215546Sopenharmony_ci 1958bf215546Sopenharmony_ci p->handle = handle; 1959bf215546Sopenharmony_ci p->resident = resident; 1960bf215546Sopenharmony_ci} 1961bf215546Sopenharmony_ci 1962bf215546Sopenharmony_cistatic uint64_t 1963bf215546Sopenharmony_citc_create_image_handle(struct pipe_context *_pipe, 1964bf215546Sopenharmony_ci const struct pipe_image_view *image) 1965bf215546Sopenharmony_ci{ 1966bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1967bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 1968bf215546Sopenharmony_ci 1969bf215546Sopenharmony_ci if (image->resource->target == PIPE_BUFFER) 1970bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(image->resource); 1971bf215546Sopenharmony_ci 1972bf215546Sopenharmony_ci tc_sync(tc); 1973bf215546Sopenharmony_ci return pipe->create_image_handle(pipe, image); 1974bf215546Sopenharmony_ci} 1975bf215546Sopenharmony_ci 1976bf215546Sopenharmony_cistruct tc_make_image_handle_resident { 1977bf215546Sopenharmony_ci struct tc_call_base base; 1978bf215546Sopenharmony_ci bool resident; 1979bf215546Sopenharmony_ci unsigned access; 1980bf215546Sopenharmony_ci uint64_t handle; 1981bf215546Sopenharmony_ci}; 1982bf215546Sopenharmony_ci 1983bf215546Sopenharmony_cistatic uint16_t 1984bf215546Sopenharmony_citc_call_make_image_handle_resident(struct pipe_context *pipe, void *call, uint64_t *last) 1985bf215546Sopenharmony_ci{ 1986bf215546Sopenharmony_ci struct tc_make_image_handle_resident *p = 1987bf215546Sopenharmony_ci to_call(call, tc_make_image_handle_resident); 1988bf215546Sopenharmony_ci 1989bf215546Sopenharmony_ci pipe->make_image_handle_resident(pipe, p->handle, p->access, p->resident); 1990bf215546Sopenharmony_ci return call_size(tc_make_image_handle_resident); 1991bf215546Sopenharmony_ci} 1992bf215546Sopenharmony_ci 1993bf215546Sopenharmony_cistatic void 1994bf215546Sopenharmony_citc_make_image_handle_resident(struct pipe_context *_pipe, uint64_t handle, 1995bf215546Sopenharmony_ci unsigned access, bool resident) 1996bf215546Sopenharmony_ci{ 1997bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 1998bf215546Sopenharmony_ci struct tc_make_image_handle_resident *p = 1999bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_make_image_handle_resident, 2000bf215546Sopenharmony_ci tc_make_image_handle_resident); 2001bf215546Sopenharmony_ci 2002bf215546Sopenharmony_ci p->handle = handle; 2003bf215546Sopenharmony_ci p->access = access; 2004bf215546Sopenharmony_ci p->resident = resident; 2005bf215546Sopenharmony_ci} 2006bf215546Sopenharmony_ci 2007bf215546Sopenharmony_ci 2008bf215546Sopenharmony_ci/******************************************************************** 2009bf215546Sopenharmony_ci * transfer 2010bf215546Sopenharmony_ci */ 2011bf215546Sopenharmony_ci 2012bf215546Sopenharmony_cistruct tc_replace_buffer_storage { 2013bf215546Sopenharmony_ci struct tc_call_base base; 2014bf215546Sopenharmony_ci uint16_t num_rebinds; 2015bf215546Sopenharmony_ci uint32_t rebind_mask; 2016bf215546Sopenharmony_ci uint32_t delete_buffer_id; 2017bf215546Sopenharmony_ci struct pipe_resource *dst; 2018bf215546Sopenharmony_ci struct pipe_resource *src; 2019bf215546Sopenharmony_ci tc_replace_buffer_storage_func func; 2020bf215546Sopenharmony_ci}; 2021bf215546Sopenharmony_ci 2022bf215546Sopenharmony_cistatic uint16_t 2023bf215546Sopenharmony_citc_call_replace_buffer_storage(struct pipe_context *pipe, void *call, uint64_t *last) 2024bf215546Sopenharmony_ci{ 2025bf215546Sopenharmony_ci struct tc_replace_buffer_storage *p = to_call(call, tc_replace_buffer_storage); 2026bf215546Sopenharmony_ci 2027bf215546Sopenharmony_ci p->func(pipe, p->dst, p->src, p->num_rebinds, p->rebind_mask, p->delete_buffer_id); 2028bf215546Sopenharmony_ci 2029bf215546Sopenharmony_ci tc_drop_resource_reference(p->dst); 2030bf215546Sopenharmony_ci tc_drop_resource_reference(p->src); 2031bf215546Sopenharmony_ci return call_size(tc_replace_buffer_storage); 2032bf215546Sopenharmony_ci} 2033bf215546Sopenharmony_ci 2034bf215546Sopenharmony_ci/* Return true if the buffer has been invalidated or is idle. 2035bf215546Sopenharmony_ci * Note that callers must've called tc_touch_buffer before calling 2036bf215546Sopenharmony_ci * this function. */ 2037bf215546Sopenharmony_cistatic bool 2038bf215546Sopenharmony_citc_invalidate_buffer(struct threaded_context *tc, 2039bf215546Sopenharmony_ci struct threaded_resource *tbuf) 2040bf215546Sopenharmony_ci{ 2041bf215546Sopenharmony_ci if (!tc_is_buffer_busy(tc, tbuf, PIPE_MAP_READ_WRITE)) { 2042bf215546Sopenharmony_ci /* It's idle, so invalidation would be a no-op, but we can still clear 2043bf215546Sopenharmony_ci * the valid range because we are technically doing invalidation, but 2044bf215546Sopenharmony_ci * skipping it because it's useless. 2045bf215546Sopenharmony_ci * 2046bf215546Sopenharmony_ci * If the buffer is bound for write, we can't invalidate the range. 2047bf215546Sopenharmony_ci */ 2048bf215546Sopenharmony_ci if (!tc_is_buffer_bound_for_write(tc, tbuf->buffer_id_unique)) 2049bf215546Sopenharmony_ci util_range_set_empty(&tbuf->valid_buffer_range); 2050bf215546Sopenharmony_ci return true; 2051bf215546Sopenharmony_ci } 2052bf215546Sopenharmony_ci 2053bf215546Sopenharmony_ci struct pipe_screen *screen = tc->base.screen; 2054bf215546Sopenharmony_ci struct pipe_resource *new_buf; 2055bf215546Sopenharmony_ci 2056bf215546Sopenharmony_ci /* Shared, pinned, and sparse buffers can't be reallocated. */ 2057bf215546Sopenharmony_ci if (tc_is_buffer_shared(tbuf) || 2058bf215546Sopenharmony_ci tbuf->is_user_ptr || 2059bf215546Sopenharmony_ci tbuf->b.flags & (PIPE_RESOURCE_FLAG_SPARSE | PIPE_RESOURCE_FLAG_UNMAPPABLE)) 2060bf215546Sopenharmony_ci return false; 2061bf215546Sopenharmony_ci 2062bf215546Sopenharmony_ci /* Allocate a new one. */ 2063bf215546Sopenharmony_ci new_buf = screen->resource_create(screen, &tbuf->b); 2064bf215546Sopenharmony_ci if (!new_buf) 2065bf215546Sopenharmony_ci return false; 2066bf215546Sopenharmony_ci 2067bf215546Sopenharmony_ci /* Replace the "latest" pointer. */ 2068bf215546Sopenharmony_ci if (tbuf->latest != &tbuf->b) 2069bf215546Sopenharmony_ci pipe_resource_reference(&tbuf->latest, NULL); 2070bf215546Sopenharmony_ci 2071bf215546Sopenharmony_ci tbuf->latest = new_buf; 2072bf215546Sopenharmony_ci 2073bf215546Sopenharmony_ci uint32_t delete_buffer_id = tbuf->buffer_id_unique; 2074bf215546Sopenharmony_ci 2075bf215546Sopenharmony_ci /* Enqueue storage replacement of the original buffer. */ 2076bf215546Sopenharmony_ci struct tc_replace_buffer_storage *p = 2077bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_replace_buffer_storage, 2078bf215546Sopenharmony_ci tc_replace_buffer_storage); 2079bf215546Sopenharmony_ci 2080bf215546Sopenharmony_ci p->func = tc->replace_buffer_storage; 2081bf215546Sopenharmony_ci tc_set_resource_reference(&p->dst, &tbuf->b); 2082bf215546Sopenharmony_ci tc_set_resource_reference(&p->src, new_buf); 2083bf215546Sopenharmony_ci p->delete_buffer_id = delete_buffer_id; 2084bf215546Sopenharmony_ci p->rebind_mask = 0; 2085bf215546Sopenharmony_ci 2086bf215546Sopenharmony_ci /* Treat the current buffer as the new buffer. */ 2087bf215546Sopenharmony_ci bool bound_for_write = tc_is_buffer_bound_for_write(tc, tbuf->buffer_id_unique); 2088bf215546Sopenharmony_ci p->num_rebinds = tc_rebind_buffer(tc, tbuf->buffer_id_unique, 2089bf215546Sopenharmony_ci threaded_resource(new_buf)->buffer_id_unique, 2090bf215546Sopenharmony_ci &p->rebind_mask); 2091bf215546Sopenharmony_ci 2092bf215546Sopenharmony_ci /* If the buffer is not bound for write, clear the valid range. */ 2093bf215546Sopenharmony_ci if (!bound_for_write) 2094bf215546Sopenharmony_ci util_range_set_empty(&tbuf->valid_buffer_range); 2095bf215546Sopenharmony_ci 2096bf215546Sopenharmony_ci tbuf->buffer_id_unique = threaded_resource(new_buf)->buffer_id_unique; 2097bf215546Sopenharmony_ci threaded_resource(new_buf)->buffer_id_unique = 0; 2098bf215546Sopenharmony_ci 2099bf215546Sopenharmony_ci return true; 2100bf215546Sopenharmony_ci} 2101bf215546Sopenharmony_ci 2102bf215546Sopenharmony_ci/* Note that callers must've called tc_touch_buffer first before 2103bf215546Sopenharmony_ci * calling tc_improve_map_buffer_flags. */ 2104bf215546Sopenharmony_cistatic unsigned 2105bf215546Sopenharmony_citc_improve_map_buffer_flags(struct threaded_context *tc, 2106bf215546Sopenharmony_ci struct threaded_resource *tres, unsigned usage, 2107bf215546Sopenharmony_ci unsigned offset, unsigned size) 2108bf215546Sopenharmony_ci{ 2109bf215546Sopenharmony_ci /* Never invalidate inside the driver and never infer "unsynchronized". */ 2110bf215546Sopenharmony_ci unsigned tc_flags = TC_TRANSFER_MAP_NO_INVALIDATE | 2111bf215546Sopenharmony_ci TC_TRANSFER_MAP_NO_INFER_UNSYNCHRONIZED; 2112bf215546Sopenharmony_ci 2113bf215546Sopenharmony_ci /* Prevent a reentry. */ 2114bf215546Sopenharmony_ci if (usage & tc_flags) 2115bf215546Sopenharmony_ci return usage; 2116bf215546Sopenharmony_ci 2117bf215546Sopenharmony_ci /* Use the staging upload if it's preferred. */ 2118bf215546Sopenharmony_ci if (usage & (PIPE_MAP_DISCARD_RANGE | 2119bf215546Sopenharmony_ci PIPE_MAP_DISCARD_WHOLE_RESOURCE) && 2120bf215546Sopenharmony_ci !(usage & PIPE_MAP_PERSISTENT) && 2121bf215546Sopenharmony_ci tres->b.flags & PIPE_RESOURCE_FLAG_DONT_MAP_DIRECTLY && 2122bf215546Sopenharmony_ci tc->use_forced_staging_uploads) { 2123bf215546Sopenharmony_ci usage &= ~(PIPE_MAP_DISCARD_WHOLE_RESOURCE | 2124bf215546Sopenharmony_ci PIPE_MAP_UNSYNCHRONIZED); 2125bf215546Sopenharmony_ci 2126bf215546Sopenharmony_ci return usage | tc_flags | PIPE_MAP_DISCARD_RANGE; 2127bf215546Sopenharmony_ci } 2128bf215546Sopenharmony_ci 2129bf215546Sopenharmony_ci /* Sparse buffers can't be mapped directly and can't be reallocated 2130bf215546Sopenharmony_ci * (fully invalidated). That may just be a radeonsi limitation, but 2131bf215546Sopenharmony_ci * the threaded context must obey it with radeonsi. 2132bf215546Sopenharmony_ci */ 2133bf215546Sopenharmony_ci if (tres->b.flags & (PIPE_RESOURCE_FLAG_SPARSE | PIPE_RESOURCE_FLAG_UNMAPPABLE)) { 2134bf215546Sopenharmony_ci /* We can use DISCARD_RANGE instead of full discard. This is the only 2135bf215546Sopenharmony_ci * fast path for sparse buffers that doesn't need thread synchronization. 2136bf215546Sopenharmony_ci */ 2137bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) 2138bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_RANGE; 2139bf215546Sopenharmony_ci 2140bf215546Sopenharmony_ci /* Allow DISCARD_WHOLE_RESOURCE and infering UNSYNCHRONIZED in drivers. 2141bf215546Sopenharmony_ci * The threaded context doesn't do unsychronized mappings and invalida- 2142bf215546Sopenharmony_ci * tions of sparse buffers, therefore a correct driver behavior won't 2143bf215546Sopenharmony_ci * result in an incorrect behavior with the threaded context. 2144bf215546Sopenharmony_ci */ 2145bf215546Sopenharmony_ci return usage; 2146bf215546Sopenharmony_ci } 2147bf215546Sopenharmony_ci 2148bf215546Sopenharmony_ci usage |= tc_flags; 2149bf215546Sopenharmony_ci 2150bf215546Sopenharmony_ci /* Handle CPU reads trivially. */ 2151bf215546Sopenharmony_ci if (usage & PIPE_MAP_READ) { 2152bf215546Sopenharmony_ci if (usage & PIPE_MAP_UNSYNCHRONIZED) 2153bf215546Sopenharmony_ci usage |= TC_TRANSFER_MAP_THREADED_UNSYNC; /* don't sync */ 2154bf215546Sopenharmony_ci 2155bf215546Sopenharmony_ci /* Drivers aren't allowed to do buffer invalidations. */ 2156bf215546Sopenharmony_ci return usage & ~PIPE_MAP_DISCARD_WHOLE_RESOURCE; 2157bf215546Sopenharmony_ci } 2158bf215546Sopenharmony_ci 2159bf215546Sopenharmony_ci /* See if the buffer range being mapped has never been initialized or 2160bf215546Sopenharmony_ci * the buffer is idle, in which case it can be mapped unsynchronized. */ 2161bf215546Sopenharmony_ci if (!(usage & PIPE_MAP_UNSYNCHRONIZED) && 2162bf215546Sopenharmony_ci ((!tres->is_shared && 2163bf215546Sopenharmony_ci !util_ranges_intersect(&tres->valid_buffer_range, offset, offset + size)) || 2164bf215546Sopenharmony_ci !tc_is_buffer_busy(tc, tres, usage))) 2165bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 2166bf215546Sopenharmony_ci 2167bf215546Sopenharmony_ci if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) { 2168bf215546Sopenharmony_ci /* If discarding the entire range, discard the whole resource instead. */ 2169bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_RANGE && 2170bf215546Sopenharmony_ci offset == 0 && size == tres->b.width0) 2171bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE; 2172bf215546Sopenharmony_ci 2173bf215546Sopenharmony_ci /* Discard the whole resource if needed. */ 2174bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) { 2175bf215546Sopenharmony_ci if (tc_invalidate_buffer(tc, tres)) 2176bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 2177bf215546Sopenharmony_ci else 2178bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_RANGE; /* fallback */ 2179bf215546Sopenharmony_ci } 2180bf215546Sopenharmony_ci } 2181bf215546Sopenharmony_ci 2182bf215546Sopenharmony_ci /* We won't need this flag anymore. */ 2183bf215546Sopenharmony_ci /* TODO: We might not need TC_TRANSFER_MAP_NO_INVALIDATE with this. */ 2184bf215546Sopenharmony_ci usage &= ~PIPE_MAP_DISCARD_WHOLE_RESOURCE; 2185bf215546Sopenharmony_ci 2186bf215546Sopenharmony_ci /* GL_AMD_pinned_memory and persistent mappings can't use staging 2187bf215546Sopenharmony_ci * buffers. */ 2188bf215546Sopenharmony_ci if (usage & (PIPE_MAP_UNSYNCHRONIZED | 2189bf215546Sopenharmony_ci PIPE_MAP_PERSISTENT) || 2190bf215546Sopenharmony_ci tres->is_user_ptr) 2191bf215546Sopenharmony_ci usage &= ~PIPE_MAP_DISCARD_RANGE; 2192bf215546Sopenharmony_ci 2193bf215546Sopenharmony_ci /* Unsychronized buffer mappings don't have to synchronize the thread. */ 2194bf215546Sopenharmony_ci if (usage & PIPE_MAP_UNSYNCHRONIZED) { 2195bf215546Sopenharmony_ci usage &= ~PIPE_MAP_DISCARD_RANGE; 2196bf215546Sopenharmony_ci usage |= TC_TRANSFER_MAP_THREADED_UNSYNC; /* notify the driver */ 2197bf215546Sopenharmony_ci } 2198bf215546Sopenharmony_ci 2199bf215546Sopenharmony_ci return usage; 2200bf215546Sopenharmony_ci} 2201bf215546Sopenharmony_ci 2202bf215546Sopenharmony_cistatic void * 2203bf215546Sopenharmony_citc_buffer_map(struct pipe_context *_pipe, 2204bf215546Sopenharmony_ci struct pipe_resource *resource, unsigned level, 2205bf215546Sopenharmony_ci unsigned usage, const struct pipe_box *box, 2206bf215546Sopenharmony_ci struct pipe_transfer **transfer) 2207bf215546Sopenharmony_ci{ 2208bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2209bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(resource); 2210bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2211bf215546Sopenharmony_ci 2212bf215546Sopenharmony_ci /* PIPE_MAP_THREAD_SAFE is for glthread, which shouldn't use the CPU storage and 2213bf215546Sopenharmony_ci * this shouldn't normally be necessary because glthread only uses large buffers. 2214bf215546Sopenharmony_ci */ 2215bf215546Sopenharmony_ci if (usage & PIPE_MAP_THREAD_SAFE) 2216bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(resource); 2217bf215546Sopenharmony_ci 2218bf215546Sopenharmony_ci tc_touch_buffer(tc, tres); 2219bf215546Sopenharmony_ci 2220bf215546Sopenharmony_ci /* CPU storage relies on buffer invalidation never failing. With shared buffers, 2221bf215546Sopenharmony_ci * invalidation might not always be possible, so CPU storage can't be used. 2222bf215546Sopenharmony_ci */ 2223bf215546Sopenharmony_ci if (tc_is_buffer_shared(tres)) 2224bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(resource); 2225bf215546Sopenharmony_ci 2226bf215546Sopenharmony_ci usage = tc_improve_map_buffer_flags(tc, tres, usage, box->x, box->width); 2227bf215546Sopenharmony_ci 2228bf215546Sopenharmony_ci /* If the CPU storage is enabled, return it directly. */ 2229bf215546Sopenharmony_ci if (tres->allow_cpu_storage && !(usage & TC_TRANSFER_MAP_UPLOAD_CPU_STORAGE)) { 2230bf215546Sopenharmony_ci /* We can't let resource_copy_region disable the CPU storage. */ 2231bf215546Sopenharmony_ci assert(!(tres->b.flags & PIPE_RESOURCE_FLAG_DONT_MAP_DIRECTLY)); 2232bf215546Sopenharmony_ci 2233bf215546Sopenharmony_ci if (!tres->cpu_storage) { 2234bf215546Sopenharmony_ci tres->cpu_storage = align_malloc(resource->width0, tc->map_buffer_alignment); 2235bf215546Sopenharmony_ci 2236bf215546Sopenharmony_ci if (tres->cpu_storage && tres->valid_buffer_range.end) { 2237bf215546Sopenharmony_ci /* The GPU buffer contains valid data. Copy them to the CPU storage. */ 2238bf215546Sopenharmony_ci struct pipe_box box2; 2239bf215546Sopenharmony_ci struct pipe_transfer *transfer2; 2240bf215546Sopenharmony_ci 2241bf215546Sopenharmony_ci unsigned valid_range_len = tres->valid_buffer_range.end - tres->valid_buffer_range.start; 2242bf215546Sopenharmony_ci u_box_1d(tres->valid_buffer_range.start, valid_range_len, &box2); 2243bf215546Sopenharmony_ci 2244bf215546Sopenharmony_ci tc_sync_msg(tc, "cpu storage GPU -> CPU copy"); 2245bf215546Sopenharmony_ci tc_set_driver_thread(tc); 2246bf215546Sopenharmony_ci 2247bf215546Sopenharmony_ci void *ret = pipe->buffer_map(pipe, tres->latest ? tres->latest : resource, 2248bf215546Sopenharmony_ci 0, PIPE_MAP_READ, &box2, &transfer2); 2249bf215546Sopenharmony_ci memcpy(&((uint8_t*)tres->cpu_storage)[tres->valid_buffer_range.start], 2250bf215546Sopenharmony_ci ret, 2251bf215546Sopenharmony_ci valid_range_len); 2252bf215546Sopenharmony_ci pipe->buffer_unmap(pipe, transfer2); 2253bf215546Sopenharmony_ci 2254bf215546Sopenharmony_ci tc_clear_driver_thread(tc); 2255bf215546Sopenharmony_ci } 2256bf215546Sopenharmony_ci } 2257bf215546Sopenharmony_ci 2258bf215546Sopenharmony_ci if (tres->cpu_storage) { 2259bf215546Sopenharmony_ci struct threaded_transfer *ttrans = slab_zalloc(&tc->pool_transfers); 2260bf215546Sopenharmony_ci ttrans->b.resource = resource; 2261bf215546Sopenharmony_ci ttrans->b.usage = usage; 2262bf215546Sopenharmony_ci ttrans->b.box = *box; 2263bf215546Sopenharmony_ci ttrans->valid_buffer_range = &tres->valid_buffer_range; 2264bf215546Sopenharmony_ci ttrans->cpu_storage_mapped = true; 2265bf215546Sopenharmony_ci *transfer = &ttrans->b; 2266bf215546Sopenharmony_ci 2267bf215546Sopenharmony_ci return (uint8_t*)tres->cpu_storage + box->x; 2268bf215546Sopenharmony_ci } else { 2269bf215546Sopenharmony_ci tres->allow_cpu_storage = false; 2270bf215546Sopenharmony_ci } 2271bf215546Sopenharmony_ci } 2272bf215546Sopenharmony_ci 2273bf215546Sopenharmony_ci /* Do a staging transfer within the threaded context. The driver should 2274bf215546Sopenharmony_ci * only get resource_copy_region. 2275bf215546Sopenharmony_ci */ 2276bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_RANGE) { 2277bf215546Sopenharmony_ci struct threaded_transfer *ttrans = slab_zalloc(&tc->pool_transfers); 2278bf215546Sopenharmony_ci uint8_t *map; 2279bf215546Sopenharmony_ci 2280bf215546Sopenharmony_ci u_upload_alloc(tc->base.stream_uploader, 0, 2281bf215546Sopenharmony_ci box->width + (box->x % tc->map_buffer_alignment), 2282bf215546Sopenharmony_ci tc->map_buffer_alignment, &ttrans->b.offset, 2283bf215546Sopenharmony_ci &ttrans->staging, (void**)&map); 2284bf215546Sopenharmony_ci if (!map) { 2285bf215546Sopenharmony_ci slab_free(&tc->pool_transfers, ttrans); 2286bf215546Sopenharmony_ci return NULL; 2287bf215546Sopenharmony_ci } 2288bf215546Sopenharmony_ci 2289bf215546Sopenharmony_ci ttrans->b.resource = resource; 2290bf215546Sopenharmony_ci ttrans->b.level = 0; 2291bf215546Sopenharmony_ci ttrans->b.usage = usage; 2292bf215546Sopenharmony_ci ttrans->b.box = *box; 2293bf215546Sopenharmony_ci ttrans->b.stride = 0; 2294bf215546Sopenharmony_ci ttrans->b.layer_stride = 0; 2295bf215546Sopenharmony_ci ttrans->valid_buffer_range = &tres->valid_buffer_range; 2296bf215546Sopenharmony_ci ttrans->cpu_storage_mapped = false; 2297bf215546Sopenharmony_ci *transfer = &ttrans->b; 2298bf215546Sopenharmony_ci 2299bf215546Sopenharmony_ci p_atomic_inc(&tres->pending_staging_uploads); 2300bf215546Sopenharmony_ci util_range_add(resource, &tres->pending_staging_uploads_range, 2301bf215546Sopenharmony_ci box->x, box->x + box->width); 2302bf215546Sopenharmony_ci 2303bf215546Sopenharmony_ci return map + (box->x % tc->map_buffer_alignment); 2304bf215546Sopenharmony_ci } 2305bf215546Sopenharmony_ci 2306bf215546Sopenharmony_ci if (usage & PIPE_MAP_UNSYNCHRONIZED && 2307bf215546Sopenharmony_ci p_atomic_read(&tres->pending_staging_uploads) && 2308bf215546Sopenharmony_ci util_ranges_intersect(&tres->pending_staging_uploads_range, box->x, box->x + box->width)) { 2309bf215546Sopenharmony_ci /* Write conflict detected between a staging transfer and the direct mapping we're 2310bf215546Sopenharmony_ci * going to do. Resolve the conflict by ignoring UNSYNCHRONIZED so the direct mapping 2311bf215546Sopenharmony_ci * will have to wait for the staging transfer completion. 2312bf215546Sopenharmony_ci * Note: The conflict detection is only based on the mapped range, not on the actual 2313bf215546Sopenharmony_ci * written range(s). 2314bf215546Sopenharmony_ci */ 2315bf215546Sopenharmony_ci usage &= ~PIPE_MAP_UNSYNCHRONIZED & ~TC_TRANSFER_MAP_THREADED_UNSYNC; 2316bf215546Sopenharmony_ci tc->use_forced_staging_uploads = false; 2317bf215546Sopenharmony_ci } 2318bf215546Sopenharmony_ci 2319bf215546Sopenharmony_ci /* Unsychronized buffer mappings don't have to synchronize the thread. */ 2320bf215546Sopenharmony_ci if (!(usage & TC_TRANSFER_MAP_THREADED_UNSYNC)) { 2321bf215546Sopenharmony_ci tc_sync_msg(tc, usage & PIPE_MAP_DISCARD_RANGE ? " discard_range" : 2322bf215546Sopenharmony_ci usage & PIPE_MAP_READ ? " read" : " staging conflict"); 2323bf215546Sopenharmony_ci tc_set_driver_thread(tc); 2324bf215546Sopenharmony_ci } 2325bf215546Sopenharmony_ci 2326bf215546Sopenharmony_ci tc->bytes_mapped_estimate += box->width; 2327bf215546Sopenharmony_ci 2328bf215546Sopenharmony_ci void *ret = pipe->buffer_map(pipe, tres->latest ? tres->latest : resource, 2329bf215546Sopenharmony_ci level, usage, box, transfer); 2330bf215546Sopenharmony_ci threaded_transfer(*transfer)->valid_buffer_range = &tres->valid_buffer_range; 2331bf215546Sopenharmony_ci threaded_transfer(*transfer)->cpu_storage_mapped = false; 2332bf215546Sopenharmony_ci 2333bf215546Sopenharmony_ci if (!(usage & TC_TRANSFER_MAP_THREADED_UNSYNC)) 2334bf215546Sopenharmony_ci tc_clear_driver_thread(tc); 2335bf215546Sopenharmony_ci 2336bf215546Sopenharmony_ci return ret; 2337bf215546Sopenharmony_ci} 2338bf215546Sopenharmony_ci 2339bf215546Sopenharmony_cistatic void * 2340bf215546Sopenharmony_citc_texture_map(struct pipe_context *_pipe, 2341bf215546Sopenharmony_ci struct pipe_resource *resource, unsigned level, 2342bf215546Sopenharmony_ci unsigned usage, const struct pipe_box *box, 2343bf215546Sopenharmony_ci struct pipe_transfer **transfer) 2344bf215546Sopenharmony_ci{ 2345bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2346bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(resource); 2347bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2348bf215546Sopenharmony_ci 2349bf215546Sopenharmony_ci tc_sync_msg(tc, "texture"); 2350bf215546Sopenharmony_ci tc_set_driver_thread(tc); 2351bf215546Sopenharmony_ci 2352bf215546Sopenharmony_ci tc->bytes_mapped_estimate += box->width; 2353bf215546Sopenharmony_ci 2354bf215546Sopenharmony_ci void *ret = pipe->texture_map(pipe, tres->latest ? tres->latest : resource, 2355bf215546Sopenharmony_ci level, usage, box, transfer); 2356bf215546Sopenharmony_ci 2357bf215546Sopenharmony_ci if (!(usage & TC_TRANSFER_MAP_THREADED_UNSYNC)) 2358bf215546Sopenharmony_ci tc_clear_driver_thread(tc); 2359bf215546Sopenharmony_ci 2360bf215546Sopenharmony_ci return ret; 2361bf215546Sopenharmony_ci} 2362bf215546Sopenharmony_ci 2363bf215546Sopenharmony_cistruct tc_transfer_flush_region { 2364bf215546Sopenharmony_ci struct tc_call_base base; 2365bf215546Sopenharmony_ci struct pipe_box box; 2366bf215546Sopenharmony_ci struct pipe_transfer *transfer; 2367bf215546Sopenharmony_ci}; 2368bf215546Sopenharmony_ci 2369bf215546Sopenharmony_cistatic uint16_t 2370bf215546Sopenharmony_citc_call_transfer_flush_region(struct pipe_context *pipe, void *call, uint64_t *last) 2371bf215546Sopenharmony_ci{ 2372bf215546Sopenharmony_ci struct tc_transfer_flush_region *p = to_call(call, tc_transfer_flush_region); 2373bf215546Sopenharmony_ci 2374bf215546Sopenharmony_ci pipe->transfer_flush_region(pipe, p->transfer, &p->box); 2375bf215546Sopenharmony_ci return call_size(tc_transfer_flush_region); 2376bf215546Sopenharmony_ci} 2377bf215546Sopenharmony_ci 2378bf215546Sopenharmony_cistruct tc_resource_copy_region { 2379bf215546Sopenharmony_ci struct tc_call_base base; 2380bf215546Sopenharmony_ci unsigned dst_level; 2381bf215546Sopenharmony_ci unsigned dstx, dsty, dstz; 2382bf215546Sopenharmony_ci unsigned src_level; 2383bf215546Sopenharmony_ci struct pipe_box src_box; 2384bf215546Sopenharmony_ci struct pipe_resource *dst; 2385bf215546Sopenharmony_ci struct pipe_resource *src; 2386bf215546Sopenharmony_ci}; 2387bf215546Sopenharmony_ci 2388bf215546Sopenharmony_cistatic void 2389bf215546Sopenharmony_citc_resource_copy_region(struct pipe_context *_pipe, 2390bf215546Sopenharmony_ci struct pipe_resource *dst, unsigned dst_level, 2391bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 2392bf215546Sopenharmony_ci struct pipe_resource *src, unsigned src_level, 2393bf215546Sopenharmony_ci const struct pipe_box *src_box); 2394bf215546Sopenharmony_ci 2395bf215546Sopenharmony_cistatic void 2396bf215546Sopenharmony_citc_buffer_do_flush_region(struct threaded_context *tc, 2397bf215546Sopenharmony_ci struct threaded_transfer *ttrans, 2398bf215546Sopenharmony_ci const struct pipe_box *box) 2399bf215546Sopenharmony_ci{ 2400bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(ttrans->b.resource); 2401bf215546Sopenharmony_ci 2402bf215546Sopenharmony_ci if (ttrans->staging) { 2403bf215546Sopenharmony_ci struct pipe_box src_box; 2404bf215546Sopenharmony_ci 2405bf215546Sopenharmony_ci u_box_1d(ttrans->b.offset + ttrans->b.box.x % tc->map_buffer_alignment + 2406bf215546Sopenharmony_ci (box->x - ttrans->b.box.x), 2407bf215546Sopenharmony_ci box->width, &src_box); 2408bf215546Sopenharmony_ci 2409bf215546Sopenharmony_ci /* Copy the staging buffer into the original one. */ 2410bf215546Sopenharmony_ci tc_resource_copy_region(&tc->base, ttrans->b.resource, 0, box->x, 0, 0, 2411bf215546Sopenharmony_ci ttrans->staging, 0, &src_box); 2412bf215546Sopenharmony_ci } 2413bf215546Sopenharmony_ci 2414bf215546Sopenharmony_ci /* Don't update the valid range when we're uploading the CPU storage 2415bf215546Sopenharmony_ci * because it includes the uninitialized range too. 2416bf215546Sopenharmony_ci */ 2417bf215546Sopenharmony_ci if (!(ttrans->b.usage & TC_TRANSFER_MAP_UPLOAD_CPU_STORAGE)) { 2418bf215546Sopenharmony_ci util_range_add(&tres->b, ttrans->valid_buffer_range, 2419bf215546Sopenharmony_ci box->x, box->x + box->width); 2420bf215546Sopenharmony_ci } 2421bf215546Sopenharmony_ci} 2422bf215546Sopenharmony_ci 2423bf215546Sopenharmony_cistatic void 2424bf215546Sopenharmony_citc_transfer_flush_region(struct pipe_context *_pipe, 2425bf215546Sopenharmony_ci struct pipe_transfer *transfer, 2426bf215546Sopenharmony_ci const struct pipe_box *rel_box) 2427bf215546Sopenharmony_ci{ 2428bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2429bf215546Sopenharmony_ci struct threaded_transfer *ttrans = threaded_transfer(transfer); 2430bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(transfer->resource); 2431bf215546Sopenharmony_ci unsigned required_usage = PIPE_MAP_WRITE | 2432bf215546Sopenharmony_ci PIPE_MAP_FLUSH_EXPLICIT; 2433bf215546Sopenharmony_ci 2434bf215546Sopenharmony_ci if (tres->b.target == PIPE_BUFFER) { 2435bf215546Sopenharmony_ci if ((transfer->usage & required_usage) == required_usage) { 2436bf215546Sopenharmony_ci struct pipe_box box; 2437bf215546Sopenharmony_ci 2438bf215546Sopenharmony_ci u_box_1d(transfer->box.x + rel_box->x, rel_box->width, &box); 2439bf215546Sopenharmony_ci tc_buffer_do_flush_region(tc, ttrans, &box); 2440bf215546Sopenharmony_ci } 2441bf215546Sopenharmony_ci 2442bf215546Sopenharmony_ci /* Staging transfers don't send the call to the driver. 2443bf215546Sopenharmony_ci * 2444bf215546Sopenharmony_ci * Transfers using the CPU storage shouldn't call transfer_flush_region 2445bf215546Sopenharmony_ci * in the driver because the buffer is not really mapped on the driver 2446bf215546Sopenharmony_ci * side and the CPU storage always re-uploads everything (flush_region 2447bf215546Sopenharmony_ci * makes no difference). 2448bf215546Sopenharmony_ci */ 2449bf215546Sopenharmony_ci if (ttrans->staging || ttrans->cpu_storage_mapped) 2450bf215546Sopenharmony_ci return; 2451bf215546Sopenharmony_ci } 2452bf215546Sopenharmony_ci 2453bf215546Sopenharmony_ci struct tc_transfer_flush_region *p = 2454bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_transfer_flush_region, tc_transfer_flush_region); 2455bf215546Sopenharmony_ci p->transfer = transfer; 2456bf215546Sopenharmony_ci p->box = *rel_box; 2457bf215546Sopenharmony_ci} 2458bf215546Sopenharmony_ci 2459bf215546Sopenharmony_cistatic void 2460bf215546Sopenharmony_citc_flush(struct pipe_context *_pipe, struct pipe_fence_handle **fence, 2461bf215546Sopenharmony_ci unsigned flags); 2462bf215546Sopenharmony_ci 2463bf215546Sopenharmony_cistruct tc_buffer_unmap { 2464bf215546Sopenharmony_ci struct tc_call_base base; 2465bf215546Sopenharmony_ci bool was_staging_transfer; 2466bf215546Sopenharmony_ci union { 2467bf215546Sopenharmony_ci struct pipe_transfer *transfer; 2468bf215546Sopenharmony_ci struct pipe_resource *resource; 2469bf215546Sopenharmony_ci }; 2470bf215546Sopenharmony_ci}; 2471bf215546Sopenharmony_ci 2472bf215546Sopenharmony_cistatic uint16_t 2473bf215546Sopenharmony_citc_call_buffer_unmap(struct pipe_context *pipe, void *call, uint64_t *last) 2474bf215546Sopenharmony_ci{ 2475bf215546Sopenharmony_ci struct tc_buffer_unmap *p = to_call(call, tc_buffer_unmap); 2476bf215546Sopenharmony_ci 2477bf215546Sopenharmony_ci if (p->was_staging_transfer) { 2478bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(p->resource); 2479bf215546Sopenharmony_ci /* Nothing to do except keeping track of staging uploads */ 2480bf215546Sopenharmony_ci assert(tres->pending_staging_uploads > 0); 2481bf215546Sopenharmony_ci p_atomic_dec(&tres->pending_staging_uploads); 2482bf215546Sopenharmony_ci tc_drop_resource_reference(p->resource); 2483bf215546Sopenharmony_ci } else { 2484bf215546Sopenharmony_ci pipe->buffer_unmap(pipe, p->transfer); 2485bf215546Sopenharmony_ci } 2486bf215546Sopenharmony_ci 2487bf215546Sopenharmony_ci return call_size(tc_buffer_unmap); 2488bf215546Sopenharmony_ci} 2489bf215546Sopenharmony_ci 2490bf215546Sopenharmony_cistatic void 2491bf215546Sopenharmony_citc_buffer_unmap(struct pipe_context *_pipe, struct pipe_transfer *transfer) 2492bf215546Sopenharmony_ci{ 2493bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2494bf215546Sopenharmony_ci struct threaded_transfer *ttrans = threaded_transfer(transfer); 2495bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(transfer->resource); 2496bf215546Sopenharmony_ci 2497bf215546Sopenharmony_ci /* PIPE_MAP_THREAD_SAFE is only valid with UNSYNCHRONIZED. It can be 2498bf215546Sopenharmony_ci * called from any thread and bypasses all multithreaded queues. 2499bf215546Sopenharmony_ci */ 2500bf215546Sopenharmony_ci if (transfer->usage & PIPE_MAP_THREAD_SAFE) { 2501bf215546Sopenharmony_ci assert(transfer->usage & PIPE_MAP_UNSYNCHRONIZED); 2502bf215546Sopenharmony_ci assert(!(transfer->usage & (PIPE_MAP_FLUSH_EXPLICIT | 2503bf215546Sopenharmony_ci PIPE_MAP_DISCARD_RANGE))); 2504bf215546Sopenharmony_ci 2505bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2506bf215546Sopenharmony_ci util_range_add(&tres->b, ttrans->valid_buffer_range, 2507bf215546Sopenharmony_ci transfer->box.x, transfer->box.x + transfer->box.width); 2508bf215546Sopenharmony_ci 2509bf215546Sopenharmony_ci pipe->buffer_unmap(pipe, transfer); 2510bf215546Sopenharmony_ci return; 2511bf215546Sopenharmony_ci } 2512bf215546Sopenharmony_ci 2513bf215546Sopenharmony_ci if (transfer->usage & PIPE_MAP_WRITE && 2514bf215546Sopenharmony_ci !(transfer->usage & PIPE_MAP_FLUSH_EXPLICIT)) 2515bf215546Sopenharmony_ci tc_buffer_do_flush_region(tc, ttrans, &transfer->box); 2516bf215546Sopenharmony_ci 2517bf215546Sopenharmony_ci if (ttrans->cpu_storage_mapped) { 2518bf215546Sopenharmony_ci /* GL allows simultaneous GPU stores with mapped buffers as long as GPU stores don't 2519bf215546Sopenharmony_ci * touch the mapped range. That's a problem because GPU stores free the CPU storage. 2520bf215546Sopenharmony_ci * If that happens, we just ignore the unmap call and don't upload anything to prevent 2521bf215546Sopenharmony_ci * a crash. 2522bf215546Sopenharmony_ci * 2523bf215546Sopenharmony_ci * Disallow the CPU storage in the driver to work around this. 2524bf215546Sopenharmony_ci */ 2525bf215546Sopenharmony_ci assert(tres->cpu_storage); 2526bf215546Sopenharmony_ci 2527bf215546Sopenharmony_ci if (tres->cpu_storage) { 2528bf215546Sopenharmony_ci /* Invalidations shouldn't fail as long as CPU storage is allowed. */ 2529bf215546Sopenharmony_ci ASSERTED bool invalidated = tc_invalidate_buffer(tc, tres); 2530bf215546Sopenharmony_ci assert(invalidated); 2531bf215546Sopenharmony_ci 2532bf215546Sopenharmony_ci tc_buffer_subdata(&tc->base, &tres->b, 2533bf215546Sopenharmony_ci PIPE_MAP_UNSYNCHRONIZED | 2534bf215546Sopenharmony_ci TC_TRANSFER_MAP_UPLOAD_CPU_STORAGE, 2535bf215546Sopenharmony_ci 0, tres->b.width0, tres->cpu_storage); 2536bf215546Sopenharmony_ci /* This shouldn't have been freed by buffer_subdata. */ 2537bf215546Sopenharmony_ci assert(tres->cpu_storage); 2538bf215546Sopenharmony_ci } else { 2539bf215546Sopenharmony_ci static bool warned_once = false; 2540bf215546Sopenharmony_ci if (!warned_once) { 2541bf215546Sopenharmony_ci fprintf(stderr, "This application is incompatible with cpu_storage.\n"); 2542bf215546Sopenharmony_ci fprintf(stderr, "Use tc_max_cpu_storage_size=0 to disable it and report this issue to Mesa.\n"); 2543bf215546Sopenharmony_ci warned_once = true; 2544bf215546Sopenharmony_ci } 2545bf215546Sopenharmony_ci } 2546bf215546Sopenharmony_ci 2547bf215546Sopenharmony_ci tc_drop_resource_reference(ttrans->staging); 2548bf215546Sopenharmony_ci slab_free(&tc->pool_transfers, ttrans); 2549bf215546Sopenharmony_ci return; 2550bf215546Sopenharmony_ci } 2551bf215546Sopenharmony_ci 2552bf215546Sopenharmony_ci bool was_staging_transfer = false; 2553bf215546Sopenharmony_ci 2554bf215546Sopenharmony_ci if (ttrans->staging) { 2555bf215546Sopenharmony_ci was_staging_transfer = true; 2556bf215546Sopenharmony_ci 2557bf215546Sopenharmony_ci tc_drop_resource_reference(ttrans->staging); 2558bf215546Sopenharmony_ci slab_free(&tc->pool_transfers, ttrans); 2559bf215546Sopenharmony_ci } 2560bf215546Sopenharmony_ci 2561bf215546Sopenharmony_ci struct tc_buffer_unmap *p = tc_add_call(tc, TC_CALL_buffer_unmap, 2562bf215546Sopenharmony_ci tc_buffer_unmap); 2563bf215546Sopenharmony_ci if (was_staging_transfer) { 2564bf215546Sopenharmony_ci tc_set_resource_reference(&p->resource, &tres->b); 2565bf215546Sopenharmony_ci p->was_staging_transfer = true; 2566bf215546Sopenharmony_ci } else { 2567bf215546Sopenharmony_ci p->transfer = transfer; 2568bf215546Sopenharmony_ci p->was_staging_transfer = false; 2569bf215546Sopenharmony_ci } 2570bf215546Sopenharmony_ci 2571bf215546Sopenharmony_ci /* tc_buffer_map directly maps the buffers, but tc_buffer_unmap 2572bf215546Sopenharmony_ci * defers the unmap operation to the batch execution. 2573bf215546Sopenharmony_ci * bytes_mapped_estimate is an estimation of the map/unmap bytes delta 2574bf215546Sopenharmony_ci * and if it goes over an optional limit the current batch is flushed, 2575bf215546Sopenharmony_ci * to reclaim some RAM. */ 2576bf215546Sopenharmony_ci if (!ttrans->staging && tc->bytes_mapped_limit && 2577bf215546Sopenharmony_ci tc->bytes_mapped_estimate > tc->bytes_mapped_limit) { 2578bf215546Sopenharmony_ci tc_flush(_pipe, NULL, PIPE_FLUSH_ASYNC); 2579bf215546Sopenharmony_ci } 2580bf215546Sopenharmony_ci} 2581bf215546Sopenharmony_ci 2582bf215546Sopenharmony_cistruct tc_texture_unmap { 2583bf215546Sopenharmony_ci struct tc_call_base base; 2584bf215546Sopenharmony_ci struct pipe_transfer *transfer; 2585bf215546Sopenharmony_ci}; 2586bf215546Sopenharmony_ci 2587bf215546Sopenharmony_cistatic uint16_t 2588bf215546Sopenharmony_citc_call_texture_unmap(struct pipe_context *pipe, void *call, uint64_t *last) 2589bf215546Sopenharmony_ci{ 2590bf215546Sopenharmony_ci struct tc_texture_unmap *p = (struct tc_texture_unmap *) call; 2591bf215546Sopenharmony_ci 2592bf215546Sopenharmony_ci pipe->texture_unmap(pipe, p->transfer); 2593bf215546Sopenharmony_ci return call_size(tc_texture_unmap); 2594bf215546Sopenharmony_ci} 2595bf215546Sopenharmony_ci 2596bf215546Sopenharmony_cistatic void 2597bf215546Sopenharmony_citc_texture_unmap(struct pipe_context *_pipe, struct pipe_transfer *transfer) 2598bf215546Sopenharmony_ci{ 2599bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2600bf215546Sopenharmony_ci struct threaded_transfer *ttrans = threaded_transfer(transfer); 2601bf215546Sopenharmony_ci 2602bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_texture_unmap, tc_texture_unmap)->transfer = transfer; 2603bf215546Sopenharmony_ci 2604bf215546Sopenharmony_ci /* tc_texture_map directly maps the textures, but tc_texture_unmap 2605bf215546Sopenharmony_ci * defers the unmap operation to the batch execution. 2606bf215546Sopenharmony_ci * bytes_mapped_estimate is an estimation of the map/unmap bytes delta 2607bf215546Sopenharmony_ci * and if it goes over an optional limit the current batch is flushed, 2608bf215546Sopenharmony_ci * to reclaim some RAM. */ 2609bf215546Sopenharmony_ci if (!ttrans->staging && tc->bytes_mapped_limit && 2610bf215546Sopenharmony_ci tc->bytes_mapped_estimate > tc->bytes_mapped_limit) { 2611bf215546Sopenharmony_ci tc_flush(_pipe, NULL, PIPE_FLUSH_ASYNC); 2612bf215546Sopenharmony_ci } 2613bf215546Sopenharmony_ci} 2614bf215546Sopenharmony_ci 2615bf215546Sopenharmony_cistruct tc_buffer_subdata { 2616bf215546Sopenharmony_ci struct tc_call_base base; 2617bf215546Sopenharmony_ci unsigned usage, offset, size; 2618bf215546Sopenharmony_ci struct pipe_resource *resource; 2619bf215546Sopenharmony_ci char slot[0]; /* more will be allocated if needed */ 2620bf215546Sopenharmony_ci}; 2621bf215546Sopenharmony_ci 2622bf215546Sopenharmony_cistatic uint16_t 2623bf215546Sopenharmony_citc_call_buffer_subdata(struct pipe_context *pipe, void *call, uint64_t *last) 2624bf215546Sopenharmony_ci{ 2625bf215546Sopenharmony_ci struct tc_buffer_subdata *p = (struct tc_buffer_subdata *)call; 2626bf215546Sopenharmony_ci 2627bf215546Sopenharmony_ci pipe->buffer_subdata(pipe, p->resource, p->usage, p->offset, p->size, 2628bf215546Sopenharmony_ci p->slot); 2629bf215546Sopenharmony_ci tc_drop_resource_reference(p->resource); 2630bf215546Sopenharmony_ci return p->base.num_slots; 2631bf215546Sopenharmony_ci} 2632bf215546Sopenharmony_ci 2633bf215546Sopenharmony_cistatic void 2634bf215546Sopenharmony_citc_buffer_subdata(struct pipe_context *_pipe, 2635bf215546Sopenharmony_ci struct pipe_resource *resource, 2636bf215546Sopenharmony_ci unsigned usage, unsigned offset, 2637bf215546Sopenharmony_ci unsigned size, const void *data) 2638bf215546Sopenharmony_ci{ 2639bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2640bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(resource); 2641bf215546Sopenharmony_ci 2642bf215546Sopenharmony_ci if (!size) 2643bf215546Sopenharmony_ci return; 2644bf215546Sopenharmony_ci 2645bf215546Sopenharmony_ci tc_touch_buffer(tc, tres); 2646bf215546Sopenharmony_ci 2647bf215546Sopenharmony_ci usage |= PIPE_MAP_WRITE; 2648bf215546Sopenharmony_ci 2649bf215546Sopenharmony_ci /* PIPE_MAP_DIRECTLY supresses implicit DISCARD_RANGE. */ 2650bf215546Sopenharmony_ci if (!(usage & PIPE_MAP_DIRECTLY)) 2651bf215546Sopenharmony_ci usage |= PIPE_MAP_DISCARD_RANGE; 2652bf215546Sopenharmony_ci 2653bf215546Sopenharmony_ci usage = tc_improve_map_buffer_flags(tc, tres, usage, offset, size); 2654bf215546Sopenharmony_ci 2655bf215546Sopenharmony_ci /* Unsychronized and big transfers should use transfer_map. Also handle 2656bf215546Sopenharmony_ci * full invalidations, because drivers aren't allowed to do them. 2657bf215546Sopenharmony_ci */ 2658bf215546Sopenharmony_ci if (usage & (PIPE_MAP_UNSYNCHRONIZED | 2659bf215546Sopenharmony_ci PIPE_MAP_DISCARD_WHOLE_RESOURCE) || 2660bf215546Sopenharmony_ci size > TC_MAX_SUBDATA_BYTES || 2661bf215546Sopenharmony_ci tres->cpu_storage) { 2662bf215546Sopenharmony_ci struct pipe_transfer *transfer; 2663bf215546Sopenharmony_ci struct pipe_box box; 2664bf215546Sopenharmony_ci uint8_t *map = NULL; 2665bf215546Sopenharmony_ci 2666bf215546Sopenharmony_ci u_box_1d(offset, size, &box); 2667bf215546Sopenharmony_ci 2668bf215546Sopenharmony_ci /* CPU storage is only useful for partial updates. It can add overhead 2669bf215546Sopenharmony_ci * on glBufferData calls so avoid using it. 2670bf215546Sopenharmony_ci */ 2671bf215546Sopenharmony_ci if (!tres->cpu_storage && offset == 0 && size == resource->width0) 2672bf215546Sopenharmony_ci usage |= TC_TRANSFER_MAP_UPLOAD_CPU_STORAGE; 2673bf215546Sopenharmony_ci 2674bf215546Sopenharmony_ci map = tc_buffer_map(_pipe, resource, 0, usage, &box, &transfer); 2675bf215546Sopenharmony_ci if (map) { 2676bf215546Sopenharmony_ci memcpy(map, data, size); 2677bf215546Sopenharmony_ci tc_buffer_unmap(_pipe, transfer); 2678bf215546Sopenharmony_ci } 2679bf215546Sopenharmony_ci return; 2680bf215546Sopenharmony_ci } 2681bf215546Sopenharmony_ci 2682bf215546Sopenharmony_ci util_range_add(&tres->b, &tres->valid_buffer_range, offset, offset + size); 2683bf215546Sopenharmony_ci 2684bf215546Sopenharmony_ci /* The upload is small. Enqueue it. */ 2685bf215546Sopenharmony_ci struct tc_buffer_subdata *p = 2686bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_buffer_subdata, tc_buffer_subdata, size); 2687bf215546Sopenharmony_ci 2688bf215546Sopenharmony_ci tc_set_resource_reference(&p->resource, resource); 2689bf215546Sopenharmony_ci /* This is will always be busy because if it wasn't, tc_improve_map_buffer- 2690bf215546Sopenharmony_ci * _flags would set UNSYNCHRONIZED and we wouldn't get here. 2691bf215546Sopenharmony_ci */ 2692bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, &tc->buffer_lists[tc->next_buf_list], resource); 2693bf215546Sopenharmony_ci p->usage = usage; 2694bf215546Sopenharmony_ci p->offset = offset; 2695bf215546Sopenharmony_ci p->size = size; 2696bf215546Sopenharmony_ci memcpy(p->slot, data, size); 2697bf215546Sopenharmony_ci} 2698bf215546Sopenharmony_ci 2699bf215546Sopenharmony_cistruct tc_texture_subdata { 2700bf215546Sopenharmony_ci struct tc_call_base base; 2701bf215546Sopenharmony_ci unsigned level, usage, stride, layer_stride; 2702bf215546Sopenharmony_ci struct pipe_box box; 2703bf215546Sopenharmony_ci struct pipe_resource *resource; 2704bf215546Sopenharmony_ci char slot[0]; /* more will be allocated if needed */ 2705bf215546Sopenharmony_ci}; 2706bf215546Sopenharmony_ci 2707bf215546Sopenharmony_cistatic uint16_t 2708bf215546Sopenharmony_citc_call_texture_subdata(struct pipe_context *pipe, void *call, uint64_t *last) 2709bf215546Sopenharmony_ci{ 2710bf215546Sopenharmony_ci struct tc_texture_subdata *p = (struct tc_texture_subdata *)call; 2711bf215546Sopenharmony_ci 2712bf215546Sopenharmony_ci pipe->texture_subdata(pipe, p->resource, p->level, p->usage, &p->box, 2713bf215546Sopenharmony_ci p->slot, p->stride, p->layer_stride); 2714bf215546Sopenharmony_ci tc_drop_resource_reference(p->resource); 2715bf215546Sopenharmony_ci return p->base.num_slots; 2716bf215546Sopenharmony_ci} 2717bf215546Sopenharmony_ci 2718bf215546Sopenharmony_cistatic void 2719bf215546Sopenharmony_citc_texture_subdata(struct pipe_context *_pipe, 2720bf215546Sopenharmony_ci struct pipe_resource *resource, 2721bf215546Sopenharmony_ci unsigned level, unsigned usage, 2722bf215546Sopenharmony_ci const struct pipe_box *box, 2723bf215546Sopenharmony_ci const void *data, unsigned stride, 2724bf215546Sopenharmony_ci unsigned layer_stride) 2725bf215546Sopenharmony_ci{ 2726bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2727bf215546Sopenharmony_ci unsigned size; 2728bf215546Sopenharmony_ci 2729bf215546Sopenharmony_ci assert(box->height >= 1); 2730bf215546Sopenharmony_ci assert(box->depth >= 1); 2731bf215546Sopenharmony_ci 2732bf215546Sopenharmony_ci size = (box->depth - 1) * layer_stride + 2733bf215546Sopenharmony_ci (box->height - 1) * stride + 2734bf215546Sopenharmony_ci box->width * util_format_get_blocksize(resource->format); 2735bf215546Sopenharmony_ci if (!size) 2736bf215546Sopenharmony_ci return; 2737bf215546Sopenharmony_ci 2738bf215546Sopenharmony_ci /* Small uploads can be enqueued, big uploads must sync. */ 2739bf215546Sopenharmony_ci if (size <= TC_MAX_SUBDATA_BYTES) { 2740bf215546Sopenharmony_ci struct tc_texture_subdata *p = 2741bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_texture_subdata, tc_texture_subdata, size); 2742bf215546Sopenharmony_ci 2743bf215546Sopenharmony_ci tc_set_resource_reference(&p->resource, resource); 2744bf215546Sopenharmony_ci p->level = level; 2745bf215546Sopenharmony_ci p->usage = usage; 2746bf215546Sopenharmony_ci p->box = *box; 2747bf215546Sopenharmony_ci p->stride = stride; 2748bf215546Sopenharmony_ci p->layer_stride = layer_stride; 2749bf215546Sopenharmony_ci memcpy(p->slot, data, size); 2750bf215546Sopenharmony_ci } else { 2751bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2752bf215546Sopenharmony_ci 2753bf215546Sopenharmony_ci tc_sync(tc); 2754bf215546Sopenharmony_ci tc_set_driver_thread(tc); 2755bf215546Sopenharmony_ci pipe->texture_subdata(pipe, resource, level, usage, box, data, 2756bf215546Sopenharmony_ci stride, layer_stride); 2757bf215546Sopenharmony_ci tc_clear_driver_thread(tc); 2758bf215546Sopenharmony_ci } 2759bf215546Sopenharmony_ci} 2760bf215546Sopenharmony_ci 2761bf215546Sopenharmony_ci 2762bf215546Sopenharmony_ci/******************************************************************** 2763bf215546Sopenharmony_ci * miscellaneous 2764bf215546Sopenharmony_ci */ 2765bf215546Sopenharmony_ci 2766bf215546Sopenharmony_ci#define TC_FUNC_SYNC_RET0(ret_type, func) \ 2767bf215546Sopenharmony_ci static ret_type \ 2768bf215546Sopenharmony_ci tc_##func(struct pipe_context *_pipe) \ 2769bf215546Sopenharmony_ci { \ 2770bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); \ 2771bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; \ 2772bf215546Sopenharmony_ci tc_sync(tc); \ 2773bf215546Sopenharmony_ci return pipe->func(pipe); \ 2774bf215546Sopenharmony_ci } 2775bf215546Sopenharmony_ci 2776bf215546Sopenharmony_ciTC_FUNC_SYNC_RET0(uint64_t, get_timestamp) 2777bf215546Sopenharmony_ci 2778bf215546Sopenharmony_cistatic void 2779bf215546Sopenharmony_citc_get_sample_position(struct pipe_context *_pipe, 2780bf215546Sopenharmony_ci unsigned sample_count, unsigned sample_index, 2781bf215546Sopenharmony_ci float *out_value) 2782bf215546Sopenharmony_ci{ 2783bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2784bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2785bf215546Sopenharmony_ci 2786bf215546Sopenharmony_ci tc_sync(tc); 2787bf215546Sopenharmony_ci pipe->get_sample_position(pipe, sample_count, sample_index, 2788bf215546Sopenharmony_ci out_value); 2789bf215546Sopenharmony_ci} 2790bf215546Sopenharmony_ci 2791bf215546Sopenharmony_cistatic enum pipe_reset_status 2792bf215546Sopenharmony_citc_get_device_reset_status(struct pipe_context *_pipe) 2793bf215546Sopenharmony_ci{ 2794bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2795bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2796bf215546Sopenharmony_ci 2797bf215546Sopenharmony_ci if (!tc->options.unsynchronized_get_device_reset_status) 2798bf215546Sopenharmony_ci tc_sync(tc); 2799bf215546Sopenharmony_ci 2800bf215546Sopenharmony_ci return pipe->get_device_reset_status(pipe); 2801bf215546Sopenharmony_ci} 2802bf215546Sopenharmony_ci 2803bf215546Sopenharmony_cistatic void 2804bf215546Sopenharmony_citc_set_device_reset_callback(struct pipe_context *_pipe, 2805bf215546Sopenharmony_ci const struct pipe_device_reset_callback *cb) 2806bf215546Sopenharmony_ci{ 2807bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2808bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2809bf215546Sopenharmony_ci 2810bf215546Sopenharmony_ci tc_sync(tc); 2811bf215546Sopenharmony_ci pipe->set_device_reset_callback(pipe, cb); 2812bf215546Sopenharmony_ci} 2813bf215546Sopenharmony_ci 2814bf215546Sopenharmony_cistruct tc_string_marker { 2815bf215546Sopenharmony_ci struct tc_call_base base; 2816bf215546Sopenharmony_ci int len; 2817bf215546Sopenharmony_ci char slot[0]; /* more will be allocated if needed */ 2818bf215546Sopenharmony_ci}; 2819bf215546Sopenharmony_ci 2820bf215546Sopenharmony_cistatic uint16_t 2821bf215546Sopenharmony_citc_call_emit_string_marker(struct pipe_context *pipe, void *call, uint64_t *last) 2822bf215546Sopenharmony_ci{ 2823bf215546Sopenharmony_ci struct tc_string_marker *p = (struct tc_string_marker *)call; 2824bf215546Sopenharmony_ci pipe->emit_string_marker(pipe, p->slot, p->len); 2825bf215546Sopenharmony_ci return p->base.num_slots; 2826bf215546Sopenharmony_ci} 2827bf215546Sopenharmony_ci 2828bf215546Sopenharmony_cistatic void 2829bf215546Sopenharmony_citc_emit_string_marker(struct pipe_context *_pipe, 2830bf215546Sopenharmony_ci const char *string, int len) 2831bf215546Sopenharmony_ci{ 2832bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2833bf215546Sopenharmony_ci 2834bf215546Sopenharmony_ci if (len <= TC_MAX_STRING_MARKER_BYTES) { 2835bf215546Sopenharmony_ci struct tc_string_marker *p = 2836bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_emit_string_marker, tc_string_marker, len); 2837bf215546Sopenharmony_ci 2838bf215546Sopenharmony_ci memcpy(p->slot, string, len); 2839bf215546Sopenharmony_ci p->len = len; 2840bf215546Sopenharmony_ci } else { 2841bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2842bf215546Sopenharmony_ci 2843bf215546Sopenharmony_ci tc_sync(tc); 2844bf215546Sopenharmony_ci tc_set_driver_thread(tc); 2845bf215546Sopenharmony_ci pipe->emit_string_marker(pipe, string, len); 2846bf215546Sopenharmony_ci tc_clear_driver_thread(tc); 2847bf215546Sopenharmony_ci } 2848bf215546Sopenharmony_ci} 2849bf215546Sopenharmony_ci 2850bf215546Sopenharmony_cistatic void 2851bf215546Sopenharmony_citc_dump_debug_state(struct pipe_context *_pipe, FILE *stream, 2852bf215546Sopenharmony_ci unsigned flags) 2853bf215546Sopenharmony_ci{ 2854bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2855bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2856bf215546Sopenharmony_ci 2857bf215546Sopenharmony_ci tc_sync(tc); 2858bf215546Sopenharmony_ci pipe->dump_debug_state(pipe, stream, flags); 2859bf215546Sopenharmony_ci} 2860bf215546Sopenharmony_ci 2861bf215546Sopenharmony_cistatic void 2862bf215546Sopenharmony_citc_set_debug_callback(struct pipe_context *_pipe, 2863bf215546Sopenharmony_ci const struct util_debug_callback *cb) 2864bf215546Sopenharmony_ci{ 2865bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2866bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2867bf215546Sopenharmony_ci 2868bf215546Sopenharmony_ci tc_sync(tc); 2869bf215546Sopenharmony_ci 2870bf215546Sopenharmony_ci /* Drop all synchronous debug callbacks. Drivers are expected to be OK 2871bf215546Sopenharmony_ci * with this. shader-db will use an environment variable to disable 2872bf215546Sopenharmony_ci * the threaded context. 2873bf215546Sopenharmony_ci */ 2874bf215546Sopenharmony_ci if (cb && !cb->async) 2875bf215546Sopenharmony_ci pipe->set_debug_callback(pipe, NULL); 2876bf215546Sopenharmony_ci else 2877bf215546Sopenharmony_ci pipe->set_debug_callback(pipe, cb); 2878bf215546Sopenharmony_ci} 2879bf215546Sopenharmony_ci 2880bf215546Sopenharmony_cistatic void 2881bf215546Sopenharmony_citc_set_log_context(struct pipe_context *_pipe, struct u_log_context *log) 2882bf215546Sopenharmony_ci{ 2883bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2884bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2885bf215546Sopenharmony_ci 2886bf215546Sopenharmony_ci tc_sync(tc); 2887bf215546Sopenharmony_ci pipe->set_log_context(pipe, log); 2888bf215546Sopenharmony_ci} 2889bf215546Sopenharmony_ci 2890bf215546Sopenharmony_cistatic void 2891bf215546Sopenharmony_citc_create_fence_fd(struct pipe_context *_pipe, 2892bf215546Sopenharmony_ci struct pipe_fence_handle **fence, int fd, 2893bf215546Sopenharmony_ci enum pipe_fd_type type) 2894bf215546Sopenharmony_ci{ 2895bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2896bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2897bf215546Sopenharmony_ci 2898bf215546Sopenharmony_ci tc_sync(tc); 2899bf215546Sopenharmony_ci pipe->create_fence_fd(pipe, fence, fd, type); 2900bf215546Sopenharmony_ci} 2901bf215546Sopenharmony_ci 2902bf215546Sopenharmony_cistruct tc_fence_call { 2903bf215546Sopenharmony_ci struct tc_call_base base; 2904bf215546Sopenharmony_ci struct pipe_fence_handle *fence; 2905bf215546Sopenharmony_ci}; 2906bf215546Sopenharmony_ci 2907bf215546Sopenharmony_cistatic uint16_t 2908bf215546Sopenharmony_citc_call_fence_server_sync(struct pipe_context *pipe, void *call, uint64_t *last) 2909bf215546Sopenharmony_ci{ 2910bf215546Sopenharmony_ci struct pipe_fence_handle *fence = to_call(call, tc_fence_call)->fence; 2911bf215546Sopenharmony_ci 2912bf215546Sopenharmony_ci pipe->fence_server_sync(pipe, fence); 2913bf215546Sopenharmony_ci pipe->screen->fence_reference(pipe->screen, &fence, NULL); 2914bf215546Sopenharmony_ci return call_size(tc_fence_call); 2915bf215546Sopenharmony_ci} 2916bf215546Sopenharmony_ci 2917bf215546Sopenharmony_cistatic void 2918bf215546Sopenharmony_citc_fence_server_sync(struct pipe_context *_pipe, 2919bf215546Sopenharmony_ci struct pipe_fence_handle *fence) 2920bf215546Sopenharmony_ci{ 2921bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2922bf215546Sopenharmony_ci struct pipe_screen *screen = tc->pipe->screen; 2923bf215546Sopenharmony_ci struct tc_fence_call *call = tc_add_call(tc, TC_CALL_fence_server_sync, 2924bf215546Sopenharmony_ci tc_fence_call); 2925bf215546Sopenharmony_ci 2926bf215546Sopenharmony_ci call->fence = NULL; 2927bf215546Sopenharmony_ci screen->fence_reference(screen, &call->fence, fence); 2928bf215546Sopenharmony_ci} 2929bf215546Sopenharmony_ci 2930bf215546Sopenharmony_cistatic void 2931bf215546Sopenharmony_citc_fence_server_signal(struct pipe_context *_pipe, 2932bf215546Sopenharmony_ci struct pipe_fence_handle *fence) 2933bf215546Sopenharmony_ci{ 2934bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2935bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2936bf215546Sopenharmony_ci tc_sync(tc); 2937bf215546Sopenharmony_ci pipe->fence_server_signal(pipe, fence); 2938bf215546Sopenharmony_ci} 2939bf215546Sopenharmony_ci 2940bf215546Sopenharmony_cistatic struct pipe_video_codec * 2941bf215546Sopenharmony_citc_create_video_codec(UNUSED struct pipe_context *_pipe, 2942bf215546Sopenharmony_ci UNUSED const struct pipe_video_codec *templ) 2943bf215546Sopenharmony_ci{ 2944bf215546Sopenharmony_ci unreachable("Threaded context should not be enabled for video APIs"); 2945bf215546Sopenharmony_ci return NULL; 2946bf215546Sopenharmony_ci} 2947bf215546Sopenharmony_ci 2948bf215546Sopenharmony_cistatic struct pipe_video_buffer * 2949bf215546Sopenharmony_citc_create_video_buffer(UNUSED struct pipe_context *_pipe, 2950bf215546Sopenharmony_ci UNUSED const struct pipe_video_buffer *templ) 2951bf215546Sopenharmony_ci{ 2952bf215546Sopenharmony_ci unreachable("Threaded context should not be enabled for video APIs"); 2953bf215546Sopenharmony_ci return NULL; 2954bf215546Sopenharmony_ci} 2955bf215546Sopenharmony_ci 2956bf215546Sopenharmony_cistruct tc_context_param { 2957bf215546Sopenharmony_ci struct tc_call_base base; 2958bf215546Sopenharmony_ci enum pipe_context_param param; 2959bf215546Sopenharmony_ci unsigned value; 2960bf215546Sopenharmony_ci}; 2961bf215546Sopenharmony_ci 2962bf215546Sopenharmony_cistatic uint16_t 2963bf215546Sopenharmony_citc_call_set_context_param(struct pipe_context *pipe, void *call, uint64_t *last) 2964bf215546Sopenharmony_ci{ 2965bf215546Sopenharmony_ci struct tc_context_param *p = to_call(call, tc_context_param); 2966bf215546Sopenharmony_ci 2967bf215546Sopenharmony_ci if (pipe->set_context_param) 2968bf215546Sopenharmony_ci pipe->set_context_param(pipe, p->param, p->value); 2969bf215546Sopenharmony_ci 2970bf215546Sopenharmony_ci return call_size(tc_context_param); 2971bf215546Sopenharmony_ci} 2972bf215546Sopenharmony_ci 2973bf215546Sopenharmony_cistatic void 2974bf215546Sopenharmony_citc_set_context_param(struct pipe_context *_pipe, 2975bf215546Sopenharmony_ci enum pipe_context_param param, 2976bf215546Sopenharmony_ci unsigned value) 2977bf215546Sopenharmony_ci{ 2978bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 2979bf215546Sopenharmony_ci 2980bf215546Sopenharmony_ci if (param == PIPE_CONTEXT_PARAM_PIN_THREADS_TO_L3_CACHE) { 2981bf215546Sopenharmony_ci /* Pin the gallium thread as requested. */ 2982bf215546Sopenharmony_ci util_set_thread_affinity(tc->queue.threads[0], 2983bf215546Sopenharmony_ci util_get_cpu_caps()->L3_affinity_mask[value], 2984bf215546Sopenharmony_ci NULL, util_get_cpu_caps()->num_cpu_mask_bits); 2985bf215546Sopenharmony_ci 2986bf215546Sopenharmony_ci /* Execute this immediately (without enqueuing). 2987bf215546Sopenharmony_ci * It's required to be thread-safe. 2988bf215546Sopenharmony_ci */ 2989bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 2990bf215546Sopenharmony_ci if (pipe->set_context_param) 2991bf215546Sopenharmony_ci pipe->set_context_param(pipe, param, value); 2992bf215546Sopenharmony_ci return; 2993bf215546Sopenharmony_ci } 2994bf215546Sopenharmony_ci 2995bf215546Sopenharmony_ci if (tc->pipe->set_context_param) { 2996bf215546Sopenharmony_ci struct tc_context_param *call = 2997bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_set_context_param, tc_context_param); 2998bf215546Sopenharmony_ci 2999bf215546Sopenharmony_ci call->param = param; 3000bf215546Sopenharmony_ci call->value = value; 3001bf215546Sopenharmony_ci } 3002bf215546Sopenharmony_ci} 3003bf215546Sopenharmony_ci 3004bf215546Sopenharmony_ci 3005bf215546Sopenharmony_ci/******************************************************************** 3006bf215546Sopenharmony_ci * draw, launch, clear, blit, copy, flush 3007bf215546Sopenharmony_ci */ 3008bf215546Sopenharmony_ci 3009bf215546Sopenharmony_cistruct tc_flush_call { 3010bf215546Sopenharmony_ci struct tc_call_base base; 3011bf215546Sopenharmony_ci unsigned flags; 3012bf215546Sopenharmony_ci struct threaded_context *tc; 3013bf215546Sopenharmony_ci struct pipe_fence_handle *fence; 3014bf215546Sopenharmony_ci}; 3015bf215546Sopenharmony_ci 3016bf215546Sopenharmony_cistatic void 3017bf215546Sopenharmony_citc_flush_queries(struct threaded_context *tc) 3018bf215546Sopenharmony_ci{ 3019bf215546Sopenharmony_ci struct threaded_query *tq, *tmp; 3020bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE(tq, tmp, &tc->unflushed_queries, head_unflushed) { 3021bf215546Sopenharmony_ci list_del(&tq->head_unflushed); 3022bf215546Sopenharmony_ci 3023bf215546Sopenharmony_ci /* Memory release semantics: due to a possible race with 3024bf215546Sopenharmony_ci * tc_get_query_result, we must ensure that the linked list changes 3025bf215546Sopenharmony_ci * are visible before setting tq->flushed. 3026bf215546Sopenharmony_ci */ 3027bf215546Sopenharmony_ci p_atomic_set(&tq->flushed, true); 3028bf215546Sopenharmony_ci } 3029bf215546Sopenharmony_ci} 3030bf215546Sopenharmony_ci 3031bf215546Sopenharmony_cistatic uint16_t 3032bf215546Sopenharmony_citc_call_flush(struct pipe_context *pipe, void *call, uint64_t *last) 3033bf215546Sopenharmony_ci{ 3034bf215546Sopenharmony_ci struct tc_flush_call *p = to_call(call, tc_flush_call); 3035bf215546Sopenharmony_ci struct pipe_screen *screen = pipe->screen; 3036bf215546Sopenharmony_ci 3037bf215546Sopenharmony_ci pipe->flush(pipe, p->fence ? &p->fence : NULL, p->flags); 3038bf215546Sopenharmony_ci screen->fence_reference(screen, &p->fence, NULL); 3039bf215546Sopenharmony_ci 3040bf215546Sopenharmony_ci if (!(p->flags & PIPE_FLUSH_DEFERRED)) 3041bf215546Sopenharmony_ci tc_flush_queries(p->tc); 3042bf215546Sopenharmony_ci 3043bf215546Sopenharmony_ci return call_size(tc_flush_call); 3044bf215546Sopenharmony_ci} 3045bf215546Sopenharmony_ci 3046bf215546Sopenharmony_cistatic void 3047bf215546Sopenharmony_citc_flush(struct pipe_context *_pipe, struct pipe_fence_handle **fence, 3048bf215546Sopenharmony_ci unsigned flags) 3049bf215546Sopenharmony_ci{ 3050bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3051bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 3052bf215546Sopenharmony_ci struct pipe_screen *screen = pipe->screen; 3053bf215546Sopenharmony_ci bool async = flags & (PIPE_FLUSH_DEFERRED | PIPE_FLUSH_ASYNC); 3054bf215546Sopenharmony_ci 3055bf215546Sopenharmony_ci if (async && tc->options.create_fence) { 3056bf215546Sopenharmony_ci if (fence) { 3057bf215546Sopenharmony_ci struct tc_batch *next = &tc->batch_slots[tc->next]; 3058bf215546Sopenharmony_ci 3059bf215546Sopenharmony_ci if (!next->token) { 3060bf215546Sopenharmony_ci next->token = malloc(sizeof(*next->token)); 3061bf215546Sopenharmony_ci if (!next->token) 3062bf215546Sopenharmony_ci goto out_of_memory; 3063bf215546Sopenharmony_ci 3064bf215546Sopenharmony_ci pipe_reference_init(&next->token->ref, 1); 3065bf215546Sopenharmony_ci next->token->tc = tc; 3066bf215546Sopenharmony_ci } 3067bf215546Sopenharmony_ci 3068bf215546Sopenharmony_ci screen->fence_reference(screen, fence, 3069bf215546Sopenharmony_ci tc->options.create_fence(pipe, next->token)); 3070bf215546Sopenharmony_ci if (!*fence) 3071bf215546Sopenharmony_ci goto out_of_memory; 3072bf215546Sopenharmony_ci } 3073bf215546Sopenharmony_ci 3074bf215546Sopenharmony_ci struct tc_flush_call *p = tc_add_call(tc, TC_CALL_flush, tc_flush_call); 3075bf215546Sopenharmony_ci p->tc = tc; 3076bf215546Sopenharmony_ci p->fence = fence ? *fence : NULL; 3077bf215546Sopenharmony_ci p->flags = flags | TC_FLUSH_ASYNC; 3078bf215546Sopenharmony_ci 3079bf215546Sopenharmony_ci if (!(flags & PIPE_FLUSH_DEFERRED)) 3080bf215546Sopenharmony_ci tc_batch_flush(tc); 3081bf215546Sopenharmony_ci return; 3082bf215546Sopenharmony_ci } 3083bf215546Sopenharmony_ci 3084bf215546Sopenharmony_ciout_of_memory: 3085bf215546Sopenharmony_ci tc_sync_msg(tc, flags & PIPE_FLUSH_END_OF_FRAME ? "end of frame" : 3086bf215546Sopenharmony_ci flags & PIPE_FLUSH_DEFERRED ? "deferred fence" : "normal"); 3087bf215546Sopenharmony_ci 3088bf215546Sopenharmony_ci if (!(flags & PIPE_FLUSH_DEFERRED)) 3089bf215546Sopenharmony_ci tc_flush_queries(tc); 3090bf215546Sopenharmony_ci tc_set_driver_thread(tc); 3091bf215546Sopenharmony_ci pipe->flush(pipe, fence, flags); 3092bf215546Sopenharmony_ci tc_clear_driver_thread(tc); 3093bf215546Sopenharmony_ci} 3094bf215546Sopenharmony_ci 3095bf215546Sopenharmony_cistruct tc_draw_single { 3096bf215546Sopenharmony_ci struct tc_call_base base; 3097bf215546Sopenharmony_ci unsigned index_bias; 3098bf215546Sopenharmony_ci struct pipe_draw_info info; 3099bf215546Sopenharmony_ci}; 3100bf215546Sopenharmony_ci 3101bf215546Sopenharmony_cistruct tc_draw_single_drawid { 3102bf215546Sopenharmony_ci struct tc_draw_single base; 3103bf215546Sopenharmony_ci unsigned drawid_offset; 3104bf215546Sopenharmony_ci}; 3105bf215546Sopenharmony_ci 3106bf215546Sopenharmony_cistatic uint16_t 3107bf215546Sopenharmony_citc_call_draw_single_drawid(struct pipe_context *pipe, void *call, uint64_t *last) 3108bf215546Sopenharmony_ci{ 3109bf215546Sopenharmony_ci struct tc_draw_single_drawid *info_drawid = to_call(call, tc_draw_single_drawid); 3110bf215546Sopenharmony_ci struct tc_draw_single *info = &info_drawid->base; 3111bf215546Sopenharmony_ci 3112bf215546Sopenharmony_ci /* u_threaded_context stores start/count in min/max_index for single draws. */ 3113bf215546Sopenharmony_ci /* Drivers using u_threaded_context shouldn't use min/max_index. */ 3114bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 3115bf215546Sopenharmony_ci 3116bf215546Sopenharmony_ci draw.start = info->info.min_index; 3117bf215546Sopenharmony_ci draw.count = info->info.max_index; 3118bf215546Sopenharmony_ci draw.index_bias = info->index_bias; 3119bf215546Sopenharmony_ci 3120bf215546Sopenharmony_ci info->info.index_bounds_valid = false; 3121bf215546Sopenharmony_ci info->info.has_user_indices = false; 3122bf215546Sopenharmony_ci info->info.take_index_buffer_ownership = false; 3123bf215546Sopenharmony_ci 3124bf215546Sopenharmony_ci pipe->draw_vbo(pipe, &info->info, info_drawid->drawid_offset, NULL, &draw, 1); 3125bf215546Sopenharmony_ci if (info->info.index_size) 3126bf215546Sopenharmony_ci tc_drop_resource_reference(info->info.index.resource); 3127bf215546Sopenharmony_ci 3128bf215546Sopenharmony_ci return call_size(tc_draw_single_drawid); 3129bf215546Sopenharmony_ci} 3130bf215546Sopenharmony_ci 3131bf215546Sopenharmony_cistatic void 3132bf215546Sopenharmony_cisimplify_draw_info(struct pipe_draw_info *info) 3133bf215546Sopenharmony_ci{ 3134bf215546Sopenharmony_ci /* Clear these fields to facilitate draw merging. 3135bf215546Sopenharmony_ci * Drivers shouldn't use them. 3136bf215546Sopenharmony_ci */ 3137bf215546Sopenharmony_ci info->has_user_indices = false; 3138bf215546Sopenharmony_ci info->index_bounds_valid = false; 3139bf215546Sopenharmony_ci info->take_index_buffer_ownership = false; 3140bf215546Sopenharmony_ci info->index_bias_varies = false; 3141bf215546Sopenharmony_ci info->_pad = 0; 3142bf215546Sopenharmony_ci 3143bf215546Sopenharmony_ci /* This shouldn't be set when merging single draws. */ 3144bf215546Sopenharmony_ci info->increment_draw_id = false; 3145bf215546Sopenharmony_ci 3146bf215546Sopenharmony_ci if (info->index_size) { 3147bf215546Sopenharmony_ci if (!info->primitive_restart) 3148bf215546Sopenharmony_ci info->restart_index = 0; 3149bf215546Sopenharmony_ci } else { 3150bf215546Sopenharmony_ci assert(!info->primitive_restart); 3151bf215546Sopenharmony_ci info->primitive_restart = false; 3152bf215546Sopenharmony_ci info->restart_index = 0; 3153bf215546Sopenharmony_ci info->index.resource = NULL; 3154bf215546Sopenharmony_ci } 3155bf215546Sopenharmony_ci} 3156bf215546Sopenharmony_ci 3157bf215546Sopenharmony_cistatic bool 3158bf215546Sopenharmony_ciis_next_call_a_mergeable_draw(struct tc_draw_single *first, 3159bf215546Sopenharmony_ci struct tc_draw_single *next) 3160bf215546Sopenharmony_ci{ 3161bf215546Sopenharmony_ci if (next->base.call_id != TC_CALL_draw_single) 3162bf215546Sopenharmony_ci return false; 3163bf215546Sopenharmony_ci 3164bf215546Sopenharmony_ci simplify_draw_info(&next->info); 3165bf215546Sopenharmony_ci 3166bf215546Sopenharmony_ci STATIC_ASSERT(offsetof(struct pipe_draw_info, min_index) == 3167bf215546Sopenharmony_ci sizeof(struct pipe_draw_info) - 8); 3168bf215546Sopenharmony_ci STATIC_ASSERT(offsetof(struct pipe_draw_info, max_index) == 3169bf215546Sopenharmony_ci sizeof(struct pipe_draw_info) - 4); 3170bf215546Sopenharmony_ci /* All fields must be the same except start and count. */ 3171bf215546Sopenharmony_ci /* u_threaded_context stores start/count in min/max_index for single draws. */ 3172bf215546Sopenharmony_ci return memcmp((uint32_t*)&first->info, (uint32_t*)&next->info, 3173bf215546Sopenharmony_ci DRAW_INFO_SIZE_WITHOUT_MIN_MAX_INDEX) == 0; 3174bf215546Sopenharmony_ci} 3175bf215546Sopenharmony_ci 3176bf215546Sopenharmony_cistatic uint16_t 3177bf215546Sopenharmony_citc_call_draw_single(struct pipe_context *pipe, void *call, uint64_t *last_ptr) 3178bf215546Sopenharmony_ci{ 3179bf215546Sopenharmony_ci /* Draw call merging. */ 3180bf215546Sopenharmony_ci struct tc_draw_single *first = to_call(call, tc_draw_single); 3181bf215546Sopenharmony_ci struct tc_draw_single *last = (struct tc_draw_single *)last_ptr; 3182bf215546Sopenharmony_ci struct tc_draw_single *next = get_next_call(first, tc_draw_single); 3183bf215546Sopenharmony_ci 3184bf215546Sopenharmony_ci /* If at least 2 consecutive draw calls can be merged... */ 3185bf215546Sopenharmony_ci if (next != last && 3186bf215546Sopenharmony_ci next->base.call_id == TC_CALL_draw_single) { 3187bf215546Sopenharmony_ci simplify_draw_info(&first->info); 3188bf215546Sopenharmony_ci 3189bf215546Sopenharmony_ci if (is_next_call_a_mergeable_draw(first, next)) { 3190bf215546Sopenharmony_ci /* The maximum number of merged draws is given by the batch size. */ 3191bf215546Sopenharmony_ci struct pipe_draw_start_count_bias multi[TC_SLOTS_PER_BATCH / call_size(tc_draw_single)]; 3192bf215546Sopenharmony_ci unsigned num_draws = 2; 3193bf215546Sopenharmony_ci bool index_bias_varies = first->index_bias != next->index_bias; 3194bf215546Sopenharmony_ci 3195bf215546Sopenharmony_ci /* u_threaded_context stores start/count in min/max_index for single draws. */ 3196bf215546Sopenharmony_ci multi[0].start = first->info.min_index; 3197bf215546Sopenharmony_ci multi[0].count = first->info.max_index; 3198bf215546Sopenharmony_ci multi[0].index_bias = first->index_bias; 3199bf215546Sopenharmony_ci multi[1].start = next->info.min_index; 3200bf215546Sopenharmony_ci multi[1].count = next->info.max_index; 3201bf215546Sopenharmony_ci multi[1].index_bias = next->index_bias; 3202bf215546Sopenharmony_ci 3203bf215546Sopenharmony_ci /* Find how many other draws can be merged. */ 3204bf215546Sopenharmony_ci next = get_next_call(next, tc_draw_single); 3205bf215546Sopenharmony_ci for (; next != last && is_next_call_a_mergeable_draw(first, next); 3206bf215546Sopenharmony_ci next = get_next_call(next, tc_draw_single), num_draws++) { 3207bf215546Sopenharmony_ci /* u_threaded_context stores start/count in min/max_index for single draws. */ 3208bf215546Sopenharmony_ci multi[num_draws].start = next->info.min_index; 3209bf215546Sopenharmony_ci multi[num_draws].count = next->info.max_index; 3210bf215546Sopenharmony_ci multi[num_draws].index_bias = next->index_bias; 3211bf215546Sopenharmony_ci index_bias_varies |= first->index_bias != next->index_bias; 3212bf215546Sopenharmony_ci } 3213bf215546Sopenharmony_ci 3214bf215546Sopenharmony_ci first->info.index_bias_varies = index_bias_varies; 3215bf215546Sopenharmony_ci pipe->draw_vbo(pipe, &first->info, 0, NULL, multi, num_draws); 3216bf215546Sopenharmony_ci 3217bf215546Sopenharmony_ci /* Since all draws use the same index buffer, drop all references at once. */ 3218bf215546Sopenharmony_ci if (first->info.index_size) 3219bf215546Sopenharmony_ci pipe_drop_resource_references(first->info.index.resource, num_draws); 3220bf215546Sopenharmony_ci 3221bf215546Sopenharmony_ci return call_size(tc_draw_single) * num_draws; 3222bf215546Sopenharmony_ci } 3223bf215546Sopenharmony_ci } 3224bf215546Sopenharmony_ci 3225bf215546Sopenharmony_ci /* u_threaded_context stores start/count in min/max_index for single draws. */ 3226bf215546Sopenharmony_ci /* Drivers using u_threaded_context shouldn't use min/max_index. */ 3227bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 3228bf215546Sopenharmony_ci 3229bf215546Sopenharmony_ci draw.start = first->info.min_index; 3230bf215546Sopenharmony_ci draw.count = first->info.max_index; 3231bf215546Sopenharmony_ci draw.index_bias = first->index_bias; 3232bf215546Sopenharmony_ci 3233bf215546Sopenharmony_ci first->info.index_bounds_valid = false; 3234bf215546Sopenharmony_ci first->info.has_user_indices = false; 3235bf215546Sopenharmony_ci first->info.take_index_buffer_ownership = false; 3236bf215546Sopenharmony_ci 3237bf215546Sopenharmony_ci pipe->draw_vbo(pipe, &first->info, 0, NULL, &draw, 1); 3238bf215546Sopenharmony_ci if (first->info.index_size) 3239bf215546Sopenharmony_ci tc_drop_resource_reference(first->info.index.resource); 3240bf215546Sopenharmony_ci 3241bf215546Sopenharmony_ci return call_size(tc_draw_single); 3242bf215546Sopenharmony_ci} 3243bf215546Sopenharmony_ci 3244bf215546Sopenharmony_cistruct tc_draw_indirect { 3245bf215546Sopenharmony_ci struct tc_call_base base; 3246bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 3247bf215546Sopenharmony_ci struct pipe_draw_info info; 3248bf215546Sopenharmony_ci struct pipe_draw_indirect_info indirect; 3249bf215546Sopenharmony_ci}; 3250bf215546Sopenharmony_ci 3251bf215546Sopenharmony_cistatic uint16_t 3252bf215546Sopenharmony_citc_call_draw_indirect(struct pipe_context *pipe, void *call, uint64_t *last) 3253bf215546Sopenharmony_ci{ 3254bf215546Sopenharmony_ci struct tc_draw_indirect *info = to_call(call, tc_draw_indirect); 3255bf215546Sopenharmony_ci 3256bf215546Sopenharmony_ci info->info.index_bounds_valid = false; 3257bf215546Sopenharmony_ci info->info.take_index_buffer_ownership = false; 3258bf215546Sopenharmony_ci 3259bf215546Sopenharmony_ci pipe->draw_vbo(pipe, &info->info, 0, &info->indirect, &info->draw, 1); 3260bf215546Sopenharmony_ci if (info->info.index_size) 3261bf215546Sopenharmony_ci tc_drop_resource_reference(info->info.index.resource); 3262bf215546Sopenharmony_ci 3263bf215546Sopenharmony_ci tc_drop_resource_reference(info->indirect.buffer); 3264bf215546Sopenharmony_ci tc_drop_resource_reference(info->indirect.indirect_draw_count); 3265bf215546Sopenharmony_ci tc_drop_so_target_reference(info->indirect.count_from_stream_output); 3266bf215546Sopenharmony_ci return call_size(tc_draw_indirect); 3267bf215546Sopenharmony_ci} 3268bf215546Sopenharmony_ci 3269bf215546Sopenharmony_cistruct tc_draw_multi { 3270bf215546Sopenharmony_ci struct tc_call_base base; 3271bf215546Sopenharmony_ci unsigned num_draws; 3272bf215546Sopenharmony_ci struct pipe_draw_info info; 3273bf215546Sopenharmony_ci struct pipe_draw_start_count_bias slot[]; /* variable-sized array */ 3274bf215546Sopenharmony_ci}; 3275bf215546Sopenharmony_ci 3276bf215546Sopenharmony_cistatic uint16_t 3277bf215546Sopenharmony_citc_call_draw_multi(struct pipe_context *pipe, void *call, uint64_t *last) 3278bf215546Sopenharmony_ci{ 3279bf215546Sopenharmony_ci struct tc_draw_multi *info = (struct tc_draw_multi*)call; 3280bf215546Sopenharmony_ci 3281bf215546Sopenharmony_ci info->info.has_user_indices = false; 3282bf215546Sopenharmony_ci info->info.index_bounds_valid = false; 3283bf215546Sopenharmony_ci info->info.take_index_buffer_ownership = false; 3284bf215546Sopenharmony_ci 3285bf215546Sopenharmony_ci pipe->draw_vbo(pipe, &info->info, 0, NULL, info->slot, info->num_draws); 3286bf215546Sopenharmony_ci if (info->info.index_size) 3287bf215546Sopenharmony_ci tc_drop_resource_reference(info->info.index.resource); 3288bf215546Sopenharmony_ci 3289bf215546Sopenharmony_ci return info->base.num_slots; 3290bf215546Sopenharmony_ci} 3291bf215546Sopenharmony_ci 3292bf215546Sopenharmony_ci#define DRAW_INFO_SIZE_WITHOUT_INDEXBUF_AND_MIN_MAX_INDEX \ 3293bf215546Sopenharmony_ci offsetof(struct pipe_draw_info, index) 3294bf215546Sopenharmony_ci 3295bf215546Sopenharmony_civoid 3296bf215546Sopenharmony_citc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, 3297bf215546Sopenharmony_ci unsigned drawid_offset, 3298bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 3299bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 3300bf215546Sopenharmony_ci unsigned num_draws) 3301bf215546Sopenharmony_ci{ 3302bf215546Sopenharmony_ci STATIC_ASSERT(DRAW_INFO_SIZE_WITHOUT_INDEXBUF_AND_MIN_MAX_INDEX + 3303bf215546Sopenharmony_ci sizeof(intptr_t) == offsetof(struct pipe_draw_info, min_index)); 3304bf215546Sopenharmony_ci 3305bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3306bf215546Sopenharmony_ci unsigned index_size = info->index_size; 3307bf215546Sopenharmony_ci bool has_user_indices = info->has_user_indices; 3308bf215546Sopenharmony_ci 3309bf215546Sopenharmony_ci if (unlikely(indirect)) { 3310bf215546Sopenharmony_ci assert(!has_user_indices); 3311bf215546Sopenharmony_ci assert(num_draws == 1); 3312bf215546Sopenharmony_ci 3313bf215546Sopenharmony_ci struct tc_draw_indirect *p = 3314bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_draw_indirect, tc_draw_indirect); 3315bf215546Sopenharmony_ci struct tc_buffer_list *next = &tc->buffer_lists[tc->next_buf_list]; 3316bf215546Sopenharmony_ci 3317bf215546Sopenharmony_ci if (index_size) { 3318bf215546Sopenharmony_ci if (!info->take_index_buffer_ownership) { 3319bf215546Sopenharmony_ci tc_set_resource_reference(&p->info.index.resource, 3320bf215546Sopenharmony_ci info->index.resource); 3321bf215546Sopenharmony_ci } 3322bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, next, info->index.resource); 3323bf215546Sopenharmony_ci } 3324bf215546Sopenharmony_ci memcpy(&p->info, info, DRAW_INFO_SIZE_WITHOUT_MIN_MAX_INDEX); 3325bf215546Sopenharmony_ci 3326bf215546Sopenharmony_ci tc_set_resource_reference(&p->indirect.buffer, indirect->buffer); 3327bf215546Sopenharmony_ci tc_set_resource_reference(&p->indirect.indirect_draw_count, 3328bf215546Sopenharmony_ci indirect->indirect_draw_count); 3329bf215546Sopenharmony_ci p->indirect.count_from_stream_output = NULL; 3330bf215546Sopenharmony_ci pipe_so_target_reference(&p->indirect.count_from_stream_output, 3331bf215546Sopenharmony_ci indirect->count_from_stream_output); 3332bf215546Sopenharmony_ci 3333bf215546Sopenharmony_ci if (indirect->buffer) 3334bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, next, indirect->buffer); 3335bf215546Sopenharmony_ci if (indirect->indirect_draw_count) 3336bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, next, indirect->indirect_draw_count); 3337bf215546Sopenharmony_ci if (indirect->count_from_stream_output) 3338bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, next, indirect->count_from_stream_output->buffer); 3339bf215546Sopenharmony_ci 3340bf215546Sopenharmony_ci memcpy(&p->indirect, indirect, sizeof(*indirect)); 3341bf215546Sopenharmony_ci p->draw.start = draws[0].start; 3342bf215546Sopenharmony_ci 3343bf215546Sopenharmony_ci /* This must be after tc_add_call, which can flush the batch. */ 3344bf215546Sopenharmony_ci if (unlikely(tc->add_all_gfx_bindings_to_buffer_list)) 3345bf215546Sopenharmony_ci tc_add_all_gfx_bindings_to_buffer_list(tc); 3346bf215546Sopenharmony_ci return; 3347bf215546Sopenharmony_ci } 3348bf215546Sopenharmony_ci 3349bf215546Sopenharmony_ci if (num_draws == 1) { 3350bf215546Sopenharmony_ci /* Single draw. */ 3351bf215546Sopenharmony_ci if (index_size && has_user_indices) { 3352bf215546Sopenharmony_ci unsigned size = draws[0].count * index_size; 3353bf215546Sopenharmony_ci struct pipe_resource *buffer = NULL; 3354bf215546Sopenharmony_ci unsigned offset; 3355bf215546Sopenharmony_ci 3356bf215546Sopenharmony_ci if (!size) 3357bf215546Sopenharmony_ci return; 3358bf215546Sopenharmony_ci 3359bf215546Sopenharmony_ci /* This must be done before adding draw_vbo, because it could generate 3360bf215546Sopenharmony_ci * e.g. transfer_unmap and flush partially-uninitialized draw_vbo 3361bf215546Sopenharmony_ci * to the driver if it was done afterwards. 3362bf215546Sopenharmony_ci */ 3363bf215546Sopenharmony_ci u_upload_data(tc->base.stream_uploader, 0, size, 4, 3364bf215546Sopenharmony_ci (uint8_t*)info->index.user + draws[0].start * index_size, 3365bf215546Sopenharmony_ci &offset, &buffer); 3366bf215546Sopenharmony_ci if (unlikely(!buffer)) 3367bf215546Sopenharmony_ci return; 3368bf215546Sopenharmony_ci 3369bf215546Sopenharmony_ci struct tc_draw_single *p = drawid_offset > 0 ? 3370bf215546Sopenharmony_ci &tc_add_call(tc, TC_CALL_draw_single_drawid, tc_draw_single_drawid)->base : 3371bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_draw_single, tc_draw_single); 3372bf215546Sopenharmony_ci memcpy(&p->info, info, DRAW_INFO_SIZE_WITHOUT_INDEXBUF_AND_MIN_MAX_INDEX); 3373bf215546Sopenharmony_ci p->info.index.resource = buffer; 3374bf215546Sopenharmony_ci if (drawid_offset > 0) 3375bf215546Sopenharmony_ci ((struct tc_draw_single_drawid*)p)->drawid_offset = drawid_offset; 3376bf215546Sopenharmony_ci /* u_threaded_context stores start/count in min/max_index for single draws. */ 3377bf215546Sopenharmony_ci p->info.min_index = offset >> util_logbase2(index_size); 3378bf215546Sopenharmony_ci p->info.max_index = draws[0].count; 3379bf215546Sopenharmony_ci p->index_bias = draws[0].index_bias; 3380bf215546Sopenharmony_ci } else { 3381bf215546Sopenharmony_ci /* Non-indexed call or indexed with a real index buffer. */ 3382bf215546Sopenharmony_ci struct tc_draw_single *p = drawid_offset > 0 ? 3383bf215546Sopenharmony_ci &tc_add_call(tc, TC_CALL_draw_single_drawid, tc_draw_single_drawid)->base : 3384bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_draw_single, tc_draw_single); 3385bf215546Sopenharmony_ci if (index_size) { 3386bf215546Sopenharmony_ci if (!info->take_index_buffer_ownership) { 3387bf215546Sopenharmony_ci tc_set_resource_reference(&p->info.index.resource, 3388bf215546Sopenharmony_ci info->index.resource); 3389bf215546Sopenharmony_ci } 3390bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, &tc->buffer_lists[tc->next_buf_list], info->index.resource); 3391bf215546Sopenharmony_ci } 3392bf215546Sopenharmony_ci if (drawid_offset > 0) 3393bf215546Sopenharmony_ci ((struct tc_draw_single_drawid*)p)->drawid_offset = drawid_offset; 3394bf215546Sopenharmony_ci memcpy(&p->info, info, DRAW_INFO_SIZE_WITHOUT_MIN_MAX_INDEX); 3395bf215546Sopenharmony_ci /* u_threaded_context stores start/count in min/max_index for single draws. */ 3396bf215546Sopenharmony_ci p->info.min_index = draws[0].start; 3397bf215546Sopenharmony_ci p->info.max_index = draws[0].count; 3398bf215546Sopenharmony_ci p->index_bias = draws[0].index_bias; 3399bf215546Sopenharmony_ci } 3400bf215546Sopenharmony_ci 3401bf215546Sopenharmony_ci /* This must be after tc_add_call, which can flush the batch. */ 3402bf215546Sopenharmony_ci if (unlikely(tc->add_all_gfx_bindings_to_buffer_list)) 3403bf215546Sopenharmony_ci tc_add_all_gfx_bindings_to_buffer_list(tc); 3404bf215546Sopenharmony_ci return; 3405bf215546Sopenharmony_ci } 3406bf215546Sopenharmony_ci 3407bf215546Sopenharmony_ci const int draw_overhead_bytes = sizeof(struct tc_draw_multi); 3408bf215546Sopenharmony_ci const int one_draw_slot_bytes = sizeof(((struct tc_draw_multi*)NULL)->slot[0]); 3409bf215546Sopenharmony_ci const int slots_for_one_draw = DIV_ROUND_UP(draw_overhead_bytes + one_draw_slot_bytes, 3410bf215546Sopenharmony_ci sizeof(struct tc_call_base)); 3411bf215546Sopenharmony_ci /* Multi draw. */ 3412bf215546Sopenharmony_ci if (index_size && has_user_indices) { 3413bf215546Sopenharmony_ci struct pipe_resource *buffer = NULL; 3414bf215546Sopenharmony_ci unsigned buffer_offset, total_count = 0; 3415bf215546Sopenharmony_ci unsigned index_size_shift = util_logbase2(index_size); 3416bf215546Sopenharmony_ci uint8_t *ptr = NULL; 3417bf215546Sopenharmony_ci 3418bf215546Sopenharmony_ci /* Get the total count. */ 3419bf215546Sopenharmony_ci for (unsigned i = 0; i < num_draws; i++) 3420bf215546Sopenharmony_ci total_count += draws[i].count; 3421bf215546Sopenharmony_ci 3422bf215546Sopenharmony_ci if (!total_count) 3423bf215546Sopenharmony_ci return; 3424bf215546Sopenharmony_ci 3425bf215546Sopenharmony_ci /* Allocate space for all index buffers. 3426bf215546Sopenharmony_ci * 3427bf215546Sopenharmony_ci * This must be done before adding draw_vbo, because it could generate 3428bf215546Sopenharmony_ci * e.g. transfer_unmap and flush partially-uninitialized draw_vbo 3429bf215546Sopenharmony_ci * to the driver if it was done afterwards. 3430bf215546Sopenharmony_ci */ 3431bf215546Sopenharmony_ci u_upload_alloc(tc->base.stream_uploader, 0, 3432bf215546Sopenharmony_ci total_count << index_size_shift, 4, 3433bf215546Sopenharmony_ci &buffer_offset, &buffer, (void**)&ptr); 3434bf215546Sopenharmony_ci if (unlikely(!buffer)) 3435bf215546Sopenharmony_ci return; 3436bf215546Sopenharmony_ci 3437bf215546Sopenharmony_ci int total_offset = 0; 3438bf215546Sopenharmony_ci unsigned offset = 0; 3439bf215546Sopenharmony_ci while (num_draws) { 3440bf215546Sopenharmony_ci struct tc_batch *next = &tc->batch_slots[tc->next]; 3441bf215546Sopenharmony_ci 3442bf215546Sopenharmony_ci int nb_slots_left = TC_SLOTS_PER_BATCH - next->num_total_slots; 3443bf215546Sopenharmony_ci /* If there isn't enough place for one draw, try to fill the next one */ 3444bf215546Sopenharmony_ci if (nb_slots_left < slots_for_one_draw) 3445bf215546Sopenharmony_ci nb_slots_left = TC_SLOTS_PER_BATCH; 3446bf215546Sopenharmony_ci const int size_left_bytes = nb_slots_left * sizeof(struct tc_call_base); 3447bf215546Sopenharmony_ci 3448bf215546Sopenharmony_ci /* How many draws can we fit in the current batch */ 3449bf215546Sopenharmony_ci const int dr = MIN2(num_draws, (size_left_bytes - draw_overhead_bytes) / one_draw_slot_bytes); 3450bf215546Sopenharmony_ci 3451bf215546Sopenharmony_ci struct tc_draw_multi *p = 3452bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_draw_multi, tc_draw_multi, 3453bf215546Sopenharmony_ci dr); 3454bf215546Sopenharmony_ci memcpy(&p->info, info, DRAW_INFO_SIZE_WITHOUT_INDEXBUF_AND_MIN_MAX_INDEX); 3455bf215546Sopenharmony_ci 3456bf215546Sopenharmony_ci if (total_offset == 0) 3457bf215546Sopenharmony_ci /* the first slot inherits the reference from u_upload_alloc() */ 3458bf215546Sopenharmony_ci p->info.index.resource = buffer; 3459bf215546Sopenharmony_ci else 3460bf215546Sopenharmony_ci /* all following slots need a new reference */ 3461bf215546Sopenharmony_ci tc_set_resource_reference(&p->info.index.resource, buffer); 3462bf215546Sopenharmony_ci 3463bf215546Sopenharmony_ci p->num_draws = dr; 3464bf215546Sopenharmony_ci 3465bf215546Sopenharmony_ci /* Upload index buffers. */ 3466bf215546Sopenharmony_ci for (unsigned i = 0; i < dr; i++) { 3467bf215546Sopenharmony_ci unsigned count = draws[i + total_offset].count; 3468bf215546Sopenharmony_ci 3469bf215546Sopenharmony_ci if (!count) { 3470bf215546Sopenharmony_ci p->slot[i].start = 0; 3471bf215546Sopenharmony_ci p->slot[i].count = 0; 3472bf215546Sopenharmony_ci p->slot[i].index_bias = 0; 3473bf215546Sopenharmony_ci continue; 3474bf215546Sopenharmony_ci } 3475bf215546Sopenharmony_ci 3476bf215546Sopenharmony_ci unsigned size = count << index_size_shift; 3477bf215546Sopenharmony_ci memcpy(ptr + offset, 3478bf215546Sopenharmony_ci (uint8_t*)info->index.user + 3479bf215546Sopenharmony_ci (draws[i + total_offset].start << index_size_shift), size); 3480bf215546Sopenharmony_ci p->slot[i].start = (buffer_offset + offset) >> index_size_shift; 3481bf215546Sopenharmony_ci p->slot[i].count = count; 3482bf215546Sopenharmony_ci p->slot[i].index_bias = draws[i + total_offset].index_bias; 3483bf215546Sopenharmony_ci offset += size; 3484bf215546Sopenharmony_ci } 3485bf215546Sopenharmony_ci 3486bf215546Sopenharmony_ci total_offset += dr; 3487bf215546Sopenharmony_ci num_draws -= dr; 3488bf215546Sopenharmony_ci } 3489bf215546Sopenharmony_ci } else { 3490bf215546Sopenharmony_ci int total_offset = 0; 3491bf215546Sopenharmony_ci bool take_index_buffer_ownership = info->take_index_buffer_ownership; 3492bf215546Sopenharmony_ci while (num_draws) { 3493bf215546Sopenharmony_ci struct tc_batch *next = &tc->batch_slots[tc->next]; 3494bf215546Sopenharmony_ci 3495bf215546Sopenharmony_ci int nb_slots_left = TC_SLOTS_PER_BATCH - next->num_total_slots; 3496bf215546Sopenharmony_ci /* If there isn't enough place for one draw, try to fill the next one */ 3497bf215546Sopenharmony_ci if (nb_slots_left < slots_for_one_draw) 3498bf215546Sopenharmony_ci nb_slots_left = TC_SLOTS_PER_BATCH; 3499bf215546Sopenharmony_ci const int size_left_bytes = nb_slots_left * sizeof(struct tc_call_base); 3500bf215546Sopenharmony_ci 3501bf215546Sopenharmony_ci /* How many draws can we fit in the current batch */ 3502bf215546Sopenharmony_ci const int dr = MIN2(num_draws, (size_left_bytes - draw_overhead_bytes) / one_draw_slot_bytes); 3503bf215546Sopenharmony_ci 3504bf215546Sopenharmony_ci /* Non-indexed call or indexed with a real index buffer. */ 3505bf215546Sopenharmony_ci struct tc_draw_multi *p = 3506bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_draw_multi, tc_draw_multi, 3507bf215546Sopenharmony_ci dr); 3508bf215546Sopenharmony_ci if (index_size) { 3509bf215546Sopenharmony_ci if (!take_index_buffer_ownership) { 3510bf215546Sopenharmony_ci tc_set_resource_reference(&p->info.index.resource, 3511bf215546Sopenharmony_ci info->index.resource); 3512bf215546Sopenharmony_ci } 3513bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, &tc->buffer_lists[tc->next_buf_list], info->index.resource); 3514bf215546Sopenharmony_ci } 3515bf215546Sopenharmony_ci take_index_buffer_ownership = false; 3516bf215546Sopenharmony_ci memcpy(&p->info, info, DRAW_INFO_SIZE_WITHOUT_MIN_MAX_INDEX); 3517bf215546Sopenharmony_ci p->num_draws = dr; 3518bf215546Sopenharmony_ci memcpy(p->slot, &draws[total_offset], sizeof(draws[0]) * dr); 3519bf215546Sopenharmony_ci num_draws -= dr; 3520bf215546Sopenharmony_ci 3521bf215546Sopenharmony_ci total_offset += dr; 3522bf215546Sopenharmony_ci } 3523bf215546Sopenharmony_ci } 3524bf215546Sopenharmony_ci 3525bf215546Sopenharmony_ci /* This must be after tc_add_*call, which can flush the batch. */ 3526bf215546Sopenharmony_ci if (unlikely(tc->add_all_gfx_bindings_to_buffer_list)) 3527bf215546Sopenharmony_ci tc_add_all_gfx_bindings_to_buffer_list(tc); 3528bf215546Sopenharmony_ci} 3529bf215546Sopenharmony_ci 3530bf215546Sopenharmony_cistruct tc_draw_vstate_single { 3531bf215546Sopenharmony_ci struct tc_call_base base; 3532bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 3533bf215546Sopenharmony_ci 3534bf215546Sopenharmony_ci /* The following states must be together without holes because they are 3535bf215546Sopenharmony_ci * compared by draw merging. 3536bf215546Sopenharmony_ci */ 3537bf215546Sopenharmony_ci struct pipe_vertex_state *state; 3538bf215546Sopenharmony_ci uint32_t partial_velem_mask; 3539bf215546Sopenharmony_ci struct pipe_draw_vertex_state_info info; 3540bf215546Sopenharmony_ci}; 3541bf215546Sopenharmony_ci 3542bf215546Sopenharmony_cistatic bool 3543bf215546Sopenharmony_ciis_next_call_a_mergeable_draw_vstate(struct tc_draw_vstate_single *first, 3544bf215546Sopenharmony_ci struct tc_draw_vstate_single *next) 3545bf215546Sopenharmony_ci{ 3546bf215546Sopenharmony_ci if (next->base.call_id != TC_CALL_draw_vstate_single) 3547bf215546Sopenharmony_ci return false; 3548bf215546Sopenharmony_ci 3549bf215546Sopenharmony_ci return !memcmp(&first->state, &next->state, 3550bf215546Sopenharmony_ci offsetof(struct tc_draw_vstate_single, info) + 3551bf215546Sopenharmony_ci sizeof(struct pipe_draw_vertex_state_info) - 3552bf215546Sopenharmony_ci offsetof(struct tc_draw_vstate_single, state)); 3553bf215546Sopenharmony_ci} 3554bf215546Sopenharmony_ci 3555bf215546Sopenharmony_cistatic uint16_t 3556bf215546Sopenharmony_citc_call_draw_vstate_single(struct pipe_context *pipe, void *call, uint64_t *last_ptr) 3557bf215546Sopenharmony_ci{ 3558bf215546Sopenharmony_ci /* Draw call merging. */ 3559bf215546Sopenharmony_ci struct tc_draw_vstate_single *first = to_call(call, tc_draw_vstate_single); 3560bf215546Sopenharmony_ci struct tc_draw_vstate_single *last = (struct tc_draw_vstate_single *)last_ptr; 3561bf215546Sopenharmony_ci struct tc_draw_vstate_single *next = get_next_call(first, tc_draw_vstate_single); 3562bf215546Sopenharmony_ci 3563bf215546Sopenharmony_ci /* If at least 2 consecutive draw calls can be merged... */ 3564bf215546Sopenharmony_ci if (next != last && 3565bf215546Sopenharmony_ci is_next_call_a_mergeable_draw_vstate(first, next)) { 3566bf215546Sopenharmony_ci /* The maximum number of merged draws is given by the batch size. */ 3567bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draws[TC_SLOTS_PER_BATCH / 3568bf215546Sopenharmony_ci call_size(tc_draw_vstate_single)]; 3569bf215546Sopenharmony_ci unsigned num_draws = 2; 3570bf215546Sopenharmony_ci 3571bf215546Sopenharmony_ci draws[0] = first->draw; 3572bf215546Sopenharmony_ci draws[1] = next->draw; 3573bf215546Sopenharmony_ci 3574bf215546Sopenharmony_ci /* Find how many other draws can be merged. */ 3575bf215546Sopenharmony_ci next = get_next_call(next, tc_draw_vstate_single); 3576bf215546Sopenharmony_ci for (; next != last && 3577bf215546Sopenharmony_ci is_next_call_a_mergeable_draw_vstate(first, next); 3578bf215546Sopenharmony_ci next = get_next_call(next, tc_draw_vstate_single), 3579bf215546Sopenharmony_ci num_draws++) 3580bf215546Sopenharmony_ci draws[num_draws] = next->draw; 3581bf215546Sopenharmony_ci 3582bf215546Sopenharmony_ci pipe->draw_vertex_state(pipe, first->state, first->partial_velem_mask, 3583bf215546Sopenharmony_ci first->info, draws, num_draws); 3584bf215546Sopenharmony_ci /* Since all draws use the same state, drop all references at once. */ 3585bf215546Sopenharmony_ci tc_drop_vertex_state_references(first->state, num_draws); 3586bf215546Sopenharmony_ci 3587bf215546Sopenharmony_ci return call_size(tc_draw_vstate_single) * num_draws; 3588bf215546Sopenharmony_ci } 3589bf215546Sopenharmony_ci 3590bf215546Sopenharmony_ci pipe->draw_vertex_state(pipe, first->state, first->partial_velem_mask, 3591bf215546Sopenharmony_ci first->info, &first->draw, 1); 3592bf215546Sopenharmony_ci tc_drop_vertex_state_references(first->state, 1); 3593bf215546Sopenharmony_ci return call_size(tc_draw_vstate_single); 3594bf215546Sopenharmony_ci} 3595bf215546Sopenharmony_ci 3596bf215546Sopenharmony_cistruct tc_draw_vstate_multi { 3597bf215546Sopenharmony_ci struct tc_call_base base; 3598bf215546Sopenharmony_ci uint32_t partial_velem_mask; 3599bf215546Sopenharmony_ci struct pipe_draw_vertex_state_info info; 3600bf215546Sopenharmony_ci unsigned num_draws; 3601bf215546Sopenharmony_ci struct pipe_vertex_state *state; 3602bf215546Sopenharmony_ci struct pipe_draw_start_count_bias slot[0]; 3603bf215546Sopenharmony_ci}; 3604bf215546Sopenharmony_ci 3605bf215546Sopenharmony_cistatic uint16_t 3606bf215546Sopenharmony_citc_call_draw_vstate_multi(struct pipe_context *pipe, void *call, uint64_t *last) 3607bf215546Sopenharmony_ci{ 3608bf215546Sopenharmony_ci struct tc_draw_vstate_multi *info = (struct tc_draw_vstate_multi*)call; 3609bf215546Sopenharmony_ci 3610bf215546Sopenharmony_ci pipe->draw_vertex_state(pipe, info->state, info->partial_velem_mask, 3611bf215546Sopenharmony_ci info->info, info->slot, info->num_draws); 3612bf215546Sopenharmony_ci tc_drop_vertex_state_references(info->state, 1); 3613bf215546Sopenharmony_ci return info->base.num_slots; 3614bf215546Sopenharmony_ci} 3615bf215546Sopenharmony_ci 3616bf215546Sopenharmony_cistatic void 3617bf215546Sopenharmony_citc_draw_vertex_state(struct pipe_context *_pipe, 3618bf215546Sopenharmony_ci struct pipe_vertex_state *state, 3619bf215546Sopenharmony_ci uint32_t partial_velem_mask, 3620bf215546Sopenharmony_ci struct pipe_draw_vertex_state_info info, 3621bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 3622bf215546Sopenharmony_ci unsigned num_draws) 3623bf215546Sopenharmony_ci{ 3624bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3625bf215546Sopenharmony_ci 3626bf215546Sopenharmony_ci if (num_draws == 1) { 3627bf215546Sopenharmony_ci /* Single draw. */ 3628bf215546Sopenharmony_ci struct tc_draw_vstate_single *p = 3629bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_draw_vstate_single, tc_draw_vstate_single); 3630bf215546Sopenharmony_ci p->partial_velem_mask = partial_velem_mask; 3631bf215546Sopenharmony_ci p->draw = draws[0]; 3632bf215546Sopenharmony_ci p->info.mode = info.mode; 3633bf215546Sopenharmony_ci p->info.take_vertex_state_ownership = false; 3634bf215546Sopenharmony_ci 3635bf215546Sopenharmony_ci /* This should be always 0 for simplicity because we assume that 3636bf215546Sopenharmony_ci * index_bias doesn't vary. 3637bf215546Sopenharmony_ci */ 3638bf215546Sopenharmony_ci assert(draws[0].index_bias == 0); 3639bf215546Sopenharmony_ci 3640bf215546Sopenharmony_ci if (!info.take_vertex_state_ownership) 3641bf215546Sopenharmony_ci tc_set_vertex_state_reference(&p->state, state); 3642bf215546Sopenharmony_ci else 3643bf215546Sopenharmony_ci p->state = state; 3644bf215546Sopenharmony_ci 3645bf215546Sopenharmony_ci 3646bf215546Sopenharmony_ci /* This must be after tc_add_*call, which can flush the batch. */ 3647bf215546Sopenharmony_ci if (unlikely(tc->add_all_gfx_bindings_to_buffer_list)) 3648bf215546Sopenharmony_ci tc_add_all_gfx_bindings_to_buffer_list(tc); 3649bf215546Sopenharmony_ci return; 3650bf215546Sopenharmony_ci } 3651bf215546Sopenharmony_ci 3652bf215546Sopenharmony_ci const int draw_overhead_bytes = sizeof(struct tc_draw_vstate_multi); 3653bf215546Sopenharmony_ci const int one_draw_slot_bytes = sizeof(((struct tc_draw_vstate_multi*)NULL)->slot[0]); 3654bf215546Sopenharmony_ci const int slots_for_one_draw = DIV_ROUND_UP(draw_overhead_bytes + one_draw_slot_bytes, 3655bf215546Sopenharmony_ci sizeof(struct tc_call_base)); 3656bf215546Sopenharmony_ci /* Multi draw. */ 3657bf215546Sopenharmony_ci int total_offset = 0; 3658bf215546Sopenharmony_ci bool take_vertex_state_ownership = info.take_vertex_state_ownership; 3659bf215546Sopenharmony_ci while (num_draws) { 3660bf215546Sopenharmony_ci struct tc_batch *next = &tc->batch_slots[tc->next]; 3661bf215546Sopenharmony_ci 3662bf215546Sopenharmony_ci int nb_slots_left = TC_SLOTS_PER_BATCH - next->num_total_slots; 3663bf215546Sopenharmony_ci /* If there isn't enough place for one draw, try to fill the next one */ 3664bf215546Sopenharmony_ci if (nb_slots_left < slots_for_one_draw) 3665bf215546Sopenharmony_ci nb_slots_left = TC_SLOTS_PER_BATCH; 3666bf215546Sopenharmony_ci const int size_left_bytes = nb_slots_left * sizeof(struct tc_call_base); 3667bf215546Sopenharmony_ci 3668bf215546Sopenharmony_ci /* How many draws can we fit in the current batch */ 3669bf215546Sopenharmony_ci const int dr = MIN2(num_draws, (size_left_bytes - draw_overhead_bytes) / one_draw_slot_bytes); 3670bf215546Sopenharmony_ci 3671bf215546Sopenharmony_ci /* Non-indexed call or indexed with a real index buffer. */ 3672bf215546Sopenharmony_ci struct tc_draw_vstate_multi *p = 3673bf215546Sopenharmony_ci tc_add_slot_based_call(tc, TC_CALL_draw_vstate_multi, tc_draw_vstate_multi, dr); 3674bf215546Sopenharmony_ci 3675bf215546Sopenharmony_ci if (!take_vertex_state_ownership) 3676bf215546Sopenharmony_ci tc_set_vertex_state_reference(&p->state, state); 3677bf215546Sopenharmony_ci else 3678bf215546Sopenharmony_ci p->state = state; 3679bf215546Sopenharmony_ci 3680bf215546Sopenharmony_ci take_vertex_state_ownership = false; 3681bf215546Sopenharmony_ci p->partial_velem_mask = partial_velem_mask; 3682bf215546Sopenharmony_ci p->info.mode = info.mode; 3683bf215546Sopenharmony_ci p->info.take_vertex_state_ownership = false; 3684bf215546Sopenharmony_ci p->num_draws = dr; 3685bf215546Sopenharmony_ci memcpy(p->slot, &draws[total_offset], sizeof(draws[0]) * dr); 3686bf215546Sopenharmony_ci num_draws -= dr; 3687bf215546Sopenharmony_ci 3688bf215546Sopenharmony_ci total_offset += dr; 3689bf215546Sopenharmony_ci } 3690bf215546Sopenharmony_ci 3691bf215546Sopenharmony_ci 3692bf215546Sopenharmony_ci /* This must be after tc_add_*call, which can flush the batch. */ 3693bf215546Sopenharmony_ci if (unlikely(tc->add_all_gfx_bindings_to_buffer_list)) 3694bf215546Sopenharmony_ci tc_add_all_gfx_bindings_to_buffer_list(tc); 3695bf215546Sopenharmony_ci} 3696bf215546Sopenharmony_ci 3697bf215546Sopenharmony_cistruct tc_launch_grid_call { 3698bf215546Sopenharmony_ci struct tc_call_base base; 3699bf215546Sopenharmony_ci struct pipe_grid_info info; 3700bf215546Sopenharmony_ci}; 3701bf215546Sopenharmony_ci 3702bf215546Sopenharmony_cistatic uint16_t 3703bf215546Sopenharmony_citc_call_launch_grid(struct pipe_context *pipe, void *call, uint64_t *last) 3704bf215546Sopenharmony_ci{ 3705bf215546Sopenharmony_ci struct pipe_grid_info *p = &to_call(call, tc_launch_grid_call)->info; 3706bf215546Sopenharmony_ci 3707bf215546Sopenharmony_ci pipe->launch_grid(pipe, p); 3708bf215546Sopenharmony_ci tc_drop_resource_reference(p->indirect); 3709bf215546Sopenharmony_ci return call_size(tc_launch_grid_call); 3710bf215546Sopenharmony_ci} 3711bf215546Sopenharmony_ci 3712bf215546Sopenharmony_cistatic void 3713bf215546Sopenharmony_citc_launch_grid(struct pipe_context *_pipe, 3714bf215546Sopenharmony_ci const struct pipe_grid_info *info) 3715bf215546Sopenharmony_ci{ 3716bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3717bf215546Sopenharmony_ci struct tc_launch_grid_call *p = tc_add_call(tc, TC_CALL_launch_grid, 3718bf215546Sopenharmony_ci tc_launch_grid_call); 3719bf215546Sopenharmony_ci assert(info->input == NULL); 3720bf215546Sopenharmony_ci 3721bf215546Sopenharmony_ci tc_set_resource_reference(&p->info.indirect, info->indirect); 3722bf215546Sopenharmony_ci memcpy(&p->info, info, sizeof(*info)); 3723bf215546Sopenharmony_ci 3724bf215546Sopenharmony_ci if (info->indirect) 3725bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, &tc->buffer_lists[tc->next_buf_list], info->indirect); 3726bf215546Sopenharmony_ci 3727bf215546Sopenharmony_ci /* This must be after tc_add_*call, which can flush the batch. */ 3728bf215546Sopenharmony_ci if (unlikely(tc->add_all_compute_bindings_to_buffer_list)) 3729bf215546Sopenharmony_ci tc_add_all_compute_bindings_to_buffer_list(tc); 3730bf215546Sopenharmony_ci} 3731bf215546Sopenharmony_ci 3732bf215546Sopenharmony_cistatic uint16_t 3733bf215546Sopenharmony_citc_call_resource_copy_region(struct pipe_context *pipe, void *call, uint64_t *last) 3734bf215546Sopenharmony_ci{ 3735bf215546Sopenharmony_ci struct tc_resource_copy_region *p = to_call(call, tc_resource_copy_region); 3736bf215546Sopenharmony_ci 3737bf215546Sopenharmony_ci pipe->resource_copy_region(pipe, p->dst, p->dst_level, p->dstx, p->dsty, 3738bf215546Sopenharmony_ci p->dstz, p->src, p->src_level, &p->src_box); 3739bf215546Sopenharmony_ci tc_drop_resource_reference(p->dst); 3740bf215546Sopenharmony_ci tc_drop_resource_reference(p->src); 3741bf215546Sopenharmony_ci return call_size(tc_resource_copy_region); 3742bf215546Sopenharmony_ci} 3743bf215546Sopenharmony_ci 3744bf215546Sopenharmony_cistatic void 3745bf215546Sopenharmony_citc_resource_copy_region(struct pipe_context *_pipe, 3746bf215546Sopenharmony_ci struct pipe_resource *dst, unsigned dst_level, 3747bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 3748bf215546Sopenharmony_ci struct pipe_resource *src, unsigned src_level, 3749bf215546Sopenharmony_ci const struct pipe_box *src_box) 3750bf215546Sopenharmony_ci{ 3751bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3752bf215546Sopenharmony_ci struct threaded_resource *tdst = threaded_resource(dst); 3753bf215546Sopenharmony_ci struct tc_resource_copy_region *p = 3754bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_resource_copy_region, 3755bf215546Sopenharmony_ci tc_resource_copy_region); 3756bf215546Sopenharmony_ci 3757bf215546Sopenharmony_ci if (dst->target == PIPE_BUFFER) 3758bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(dst); 3759bf215546Sopenharmony_ci 3760bf215546Sopenharmony_ci tc_set_resource_reference(&p->dst, dst); 3761bf215546Sopenharmony_ci p->dst_level = dst_level; 3762bf215546Sopenharmony_ci p->dstx = dstx; 3763bf215546Sopenharmony_ci p->dsty = dsty; 3764bf215546Sopenharmony_ci p->dstz = dstz; 3765bf215546Sopenharmony_ci tc_set_resource_reference(&p->src, src); 3766bf215546Sopenharmony_ci p->src_level = src_level; 3767bf215546Sopenharmony_ci p->src_box = *src_box; 3768bf215546Sopenharmony_ci 3769bf215546Sopenharmony_ci if (dst->target == PIPE_BUFFER) { 3770bf215546Sopenharmony_ci struct tc_buffer_list *next = &tc->buffer_lists[tc->next_buf_list]; 3771bf215546Sopenharmony_ci 3772bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, next, src); 3773bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, next, dst); 3774bf215546Sopenharmony_ci 3775bf215546Sopenharmony_ci util_range_add(&tdst->b, &tdst->valid_buffer_range, 3776bf215546Sopenharmony_ci dstx, dstx + src_box->width); 3777bf215546Sopenharmony_ci } 3778bf215546Sopenharmony_ci} 3779bf215546Sopenharmony_ci 3780bf215546Sopenharmony_cistruct tc_blit_call { 3781bf215546Sopenharmony_ci struct tc_call_base base; 3782bf215546Sopenharmony_ci struct pipe_blit_info info; 3783bf215546Sopenharmony_ci}; 3784bf215546Sopenharmony_ci 3785bf215546Sopenharmony_cistatic uint16_t 3786bf215546Sopenharmony_citc_call_blit(struct pipe_context *pipe, void *call, uint64_t *last) 3787bf215546Sopenharmony_ci{ 3788bf215546Sopenharmony_ci struct pipe_blit_info *blit = &to_call(call, tc_blit_call)->info; 3789bf215546Sopenharmony_ci 3790bf215546Sopenharmony_ci pipe->blit(pipe, blit); 3791bf215546Sopenharmony_ci tc_drop_resource_reference(blit->dst.resource); 3792bf215546Sopenharmony_ci tc_drop_resource_reference(blit->src.resource); 3793bf215546Sopenharmony_ci return call_size(tc_blit_call); 3794bf215546Sopenharmony_ci} 3795bf215546Sopenharmony_ci 3796bf215546Sopenharmony_cistatic void 3797bf215546Sopenharmony_citc_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info) 3798bf215546Sopenharmony_ci{ 3799bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3800bf215546Sopenharmony_ci struct tc_blit_call *blit = tc_add_call(tc, TC_CALL_blit, tc_blit_call); 3801bf215546Sopenharmony_ci 3802bf215546Sopenharmony_ci tc_set_resource_reference(&blit->info.dst.resource, info->dst.resource); 3803bf215546Sopenharmony_ci tc_set_resource_reference(&blit->info.src.resource, info->src.resource); 3804bf215546Sopenharmony_ci memcpy(&blit->info, info, sizeof(*info)); 3805bf215546Sopenharmony_ci} 3806bf215546Sopenharmony_ci 3807bf215546Sopenharmony_cistruct tc_generate_mipmap { 3808bf215546Sopenharmony_ci struct tc_call_base base; 3809bf215546Sopenharmony_ci enum pipe_format format; 3810bf215546Sopenharmony_ci unsigned base_level; 3811bf215546Sopenharmony_ci unsigned last_level; 3812bf215546Sopenharmony_ci unsigned first_layer; 3813bf215546Sopenharmony_ci unsigned last_layer; 3814bf215546Sopenharmony_ci struct pipe_resource *res; 3815bf215546Sopenharmony_ci}; 3816bf215546Sopenharmony_ci 3817bf215546Sopenharmony_cistatic uint16_t 3818bf215546Sopenharmony_citc_call_generate_mipmap(struct pipe_context *pipe, void *call, uint64_t *last) 3819bf215546Sopenharmony_ci{ 3820bf215546Sopenharmony_ci struct tc_generate_mipmap *p = to_call(call, tc_generate_mipmap); 3821bf215546Sopenharmony_ci ASSERTED bool result = pipe->generate_mipmap(pipe, p->res, p->format, 3822bf215546Sopenharmony_ci p->base_level, 3823bf215546Sopenharmony_ci p->last_level, 3824bf215546Sopenharmony_ci p->first_layer, 3825bf215546Sopenharmony_ci p->last_layer); 3826bf215546Sopenharmony_ci assert(result); 3827bf215546Sopenharmony_ci tc_drop_resource_reference(p->res); 3828bf215546Sopenharmony_ci return call_size(tc_generate_mipmap); 3829bf215546Sopenharmony_ci} 3830bf215546Sopenharmony_ci 3831bf215546Sopenharmony_cistatic bool 3832bf215546Sopenharmony_citc_generate_mipmap(struct pipe_context *_pipe, 3833bf215546Sopenharmony_ci struct pipe_resource *res, 3834bf215546Sopenharmony_ci enum pipe_format format, 3835bf215546Sopenharmony_ci unsigned base_level, 3836bf215546Sopenharmony_ci unsigned last_level, 3837bf215546Sopenharmony_ci unsigned first_layer, 3838bf215546Sopenharmony_ci unsigned last_layer) 3839bf215546Sopenharmony_ci{ 3840bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3841bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 3842bf215546Sopenharmony_ci struct pipe_screen *screen = pipe->screen; 3843bf215546Sopenharmony_ci unsigned bind = PIPE_BIND_SAMPLER_VIEW; 3844bf215546Sopenharmony_ci 3845bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(format)) 3846bf215546Sopenharmony_ci bind = PIPE_BIND_DEPTH_STENCIL; 3847bf215546Sopenharmony_ci else 3848bf215546Sopenharmony_ci bind = PIPE_BIND_RENDER_TARGET; 3849bf215546Sopenharmony_ci 3850bf215546Sopenharmony_ci if (!screen->is_format_supported(screen, format, res->target, 3851bf215546Sopenharmony_ci res->nr_samples, res->nr_storage_samples, 3852bf215546Sopenharmony_ci bind)) 3853bf215546Sopenharmony_ci return false; 3854bf215546Sopenharmony_ci 3855bf215546Sopenharmony_ci struct tc_generate_mipmap *p = 3856bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_generate_mipmap, tc_generate_mipmap); 3857bf215546Sopenharmony_ci 3858bf215546Sopenharmony_ci tc_set_resource_reference(&p->res, res); 3859bf215546Sopenharmony_ci p->format = format; 3860bf215546Sopenharmony_ci p->base_level = base_level; 3861bf215546Sopenharmony_ci p->last_level = last_level; 3862bf215546Sopenharmony_ci p->first_layer = first_layer; 3863bf215546Sopenharmony_ci p->last_layer = last_layer; 3864bf215546Sopenharmony_ci return true; 3865bf215546Sopenharmony_ci} 3866bf215546Sopenharmony_ci 3867bf215546Sopenharmony_cistruct tc_resource_call { 3868bf215546Sopenharmony_ci struct tc_call_base base; 3869bf215546Sopenharmony_ci struct pipe_resource *resource; 3870bf215546Sopenharmony_ci}; 3871bf215546Sopenharmony_ci 3872bf215546Sopenharmony_cistatic uint16_t 3873bf215546Sopenharmony_citc_call_flush_resource(struct pipe_context *pipe, void *call, uint64_t *last) 3874bf215546Sopenharmony_ci{ 3875bf215546Sopenharmony_ci struct pipe_resource *resource = to_call(call, tc_resource_call)->resource; 3876bf215546Sopenharmony_ci 3877bf215546Sopenharmony_ci pipe->flush_resource(pipe, resource); 3878bf215546Sopenharmony_ci tc_drop_resource_reference(resource); 3879bf215546Sopenharmony_ci return call_size(tc_resource_call); 3880bf215546Sopenharmony_ci} 3881bf215546Sopenharmony_ci 3882bf215546Sopenharmony_cistatic void 3883bf215546Sopenharmony_citc_flush_resource(struct pipe_context *_pipe, struct pipe_resource *resource) 3884bf215546Sopenharmony_ci{ 3885bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3886bf215546Sopenharmony_ci struct tc_resource_call *call = tc_add_call(tc, TC_CALL_flush_resource, 3887bf215546Sopenharmony_ci tc_resource_call); 3888bf215546Sopenharmony_ci 3889bf215546Sopenharmony_ci tc_set_resource_reference(&call->resource, resource); 3890bf215546Sopenharmony_ci} 3891bf215546Sopenharmony_ci 3892bf215546Sopenharmony_cistatic uint16_t 3893bf215546Sopenharmony_citc_call_invalidate_resource(struct pipe_context *pipe, void *call, uint64_t *last) 3894bf215546Sopenharmony_ci{ 3895bf215546Sopenharmony_ci struct pipe_resource *resource = to_call(call, tc_resource_call)->resource; 3896bf215546Sopenharmony_ci 3897bf215546Sopenharmony_ci pipe->invalidate_resource(pipe, resource); 3898bf215546Sopenharmony_ci tc_drop_resource_reference(resource); 3899bf215546Sopenharmony_ci return call_size(tc_resource_call); 3900bf215546Sopenharmony_ci} 3901bf215546Sopenharmony_ci 3902bf215546Sopenharmony_cistatic void 3903bf215546Sopenharmony_citc_invalidate_resource(struct pipe_context *_pipe, 3904bf215546Sopenharmony_ci struct pipe_resource *resource) 3905bf215546Sopenharmony_ci{ 3906bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3907bf215546Sopenharmony_ci 3908bf215546Sopenharmony_ci if (resource->target == PIPE_BUFFER) { 3909bf215546Sopenharmony_ci /* This can fail, in which case we simply ignore the invalidation request. */ 3910bf215546Sopenharmony_ci struct threaded_resource *tbuf = threaded_resource(resource); 3911bf215546Sopenharmony_ci tc_touch_buffer(tc, tbuf); 3912bf215546Sopenharmony_ci tc_invalidate_buffer(tc, tbuf); 3913bf215546Sopenharmony_ci return; 3914bf215546Sopenharmony_ci } 3915bf215546Sopenharmony_ci 3916bf215546Sopenharmony_ci struct tc_resource_call *call = tc_add_call(tc, TC_CALL_invalidate_resource, 3917bf215546Sopenharmony_ci tc_resource_call); 3918bf215546Sopenharmony_ci tc_set_resource_reference(&call->resource, resource); 3919bf215546Sopenharmony_ci} 3920bf215546Sopenharmony_ci 3921bf215546Sopenharmony_cistruct tc_clear { 3922bf215546Sopenharmony_ci struct tc_call_base base; 3923bf215546Sopenharmony_ci bool scissor_state_set; 3924bf215546Sopenharmony_ci uint8_t stencil; 3925bf215546Sopenharmony_ci uint16_t buffers; 3926bf215546Sopenharmony_ci float depth; 3927bf215546Sopenharmony_ci struct pipe_scissor_state scissor_state; 3928bf215546Sopenharmony_ci union pipe_color_union color; 3929bf215546Sopenharmony_ci}; 3930bf215546Sopenharmony_ci 3931bf215546Sopenharmony_cistatic uint16_t 3932bf215546Sopenharmony_citc_call_clear(struct pipe_context *pipe, void *call, uint64_t *last) 3933bf215546Sopenharmony_ci{ 3934bf215546Sopenharmony_ci struct tc_clear *p = to_call(call, tc_clear); 3935bf215546Sopenharmony_ci 3936bf215546Sopenharmony_ci pipe->clear(pipe, p->buffers, p->scissor_state_set ? &p->scissor_state : NULL, &p->color, p->depth, p->stencil); 3937bf215546Sopenharmony_ci return call_size(tc_clear); 3938bf215546Sopenharmony_ci} 3939bf215546Sopenharmony_ci 3940bf215546Sopenharmony_cistatic void 3941bf215546Sopenharmony_citc_clear(struct pipe_context *_pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state, 3942bf215546Sopenharmony_ci const union pipe_color_union *color, double depth, 3943bf215546Sopenharmony_ci unsigned stencil) 3944bf215546Sopenharmony_ci{ 3945bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3946bf215546Sopenharmony_ci struct tc_clear *p = tc_add_call(tc, TC_CALL_clear, tc_clear); 3947bf215546Sopenharmony_ci 3948bf215546Sopenharmony_ci p->buffers = buffers; 3949bf215546Sopenharmony_ci if (scissor_state) 3950bf215546Sopenharmony_ci p->scissor_state = *scissor_state; 3951bf215546Sopenharmony_ci p->scissor_state_set = !!scissor_state; 3952bf215546Sopenharmony_ci p->color = *color; 3953bf215546Sopenharmony_ci p->depth = depth; 3954bf215546Sopenharmony_ci p->stencil = stencil; 3955bf215546Sopenharmony_ci} 3956bf215546Sopenharmony_ci 3957bf215546Sopenharmony_cistruct tc_clear_render_target { 3958bf215546Sopenharmony_ci struct tc_call_base base; 3959bf215546Sopenharmony_ci bool render_condition_enabled; 3960bf215546Sopenharmony_ci unsigned dstx; 3961bf215546Sopenharmony_ci unsigned dsty; 3962bf215546Sopenharmony_ci unsigned width; 3963bf215546Sopenharmony_ci unsigned height; 3964bf215546Sopenharmony_ci union pipe_color_union color; 3965bf215546Sopenharmony_ci struct pipe_surface *dst; 3966bf215546Sopenharmony_ci}; 3967bf215546Sopenharmony_ci 3968bf215546Sopenharmony_cistatic uint16_t 3969bf215546Sopenharmony_citc_call_clear_render_target(struct pipe_context *pipe, void *call, uint64_t *last) 3970bf215546Sopenharmony_ci{ 3971bf215546Sopenharmony_ci struct tc_clear_render_target *p = to_call(call, tc_clear_render_target); 3972bf215546Sopenharmony_ci 3973bf215546Sopenharmony_ci pipe->clear_render_target(pipe, p->dst, &p->color, p->dstx, p->dsty, p->width, p->height, 3974bf215546Sopenharmony_ci p->render_condition_enabled); 3975bf215546Sopenharmony_ci tc_drop_surface_reference(p->dst); 3976bf215546Sopenharmony_ci return call_size(tc_clear_render_target); 3977bf215546Sopenharmony_ci} 3978bf215546Sopenharmony_ci 3979bf215546Sopenharmony_cistatic void 3980bf215546Sopenharmony_citc_clear_render_target(struct pipe_context *_pipe, 3981bf215546Sopenharmony_ci struct pipe_surface *dst, 3982bf215546Sopenharmony_ci const union pipe_color_union *color, 3983bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, 3984bf215546Sopenharmony_ci unsigned width, unsigned height, 3985bf215546Sopenharmony_ci bool render_condition_enabled) 3986bf215546Sopenharmony_ci{ 3987bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 3988bf215546Sopenharmony_ci struct tc_clear_render_target *p = tc_add_call(tc, TC_CALL_clear_render_target, tc_clear_render_target); 3989bf215546Sopenharmony_ci p->dst = NULL; 3990bf215546Sopenharmony_ci pipe_surface_reference(&p->dst, dst); 3991bf215546Sopenharmony_ci p->color = *color; 3992bf215546Sopenharmony_ci p->dstx = dstx; 3993bf215546Sopenharmony_ci p->dsty = dsty; 3994bf215546Sopenharmony_ci p->width = width; 3995bf215546Sopenharmony_ci p->height = height; 3996bf215546Sopenharmony_ci p->render_condition_enabled = render_condition_enabled; 3997bf215546Sopenharmony_ci} 3998bf215546Sopenharmony_ci 3999bf215546Sopenharmony_ci 4000bf215546Sopenharmony_cistruct tc_clear_depth_stencil { 4001bf215546Sopenharmony_ci struct tc_call_base base; 4002bf215546Sopenharmony_ci bool render_condition_enabled; 4003bf215546Sopenharmony_ci float depth; 4004bf215546Sopenharmony_ci unsigned clear_flags; 4005bf215546Sopenharmony_ci unsigned stencil; 4006bf215546Sopenharmony_ci unsigned dstx; 4007bf215546Sopenharmony_ci unsigned dsty; 4008bf215546Sopenharmony_ci unsigned width; 4009bf215546Sopenharmony_ci unsigned height; 4010bf215546Sopenharmony_ci struct pipe_surface *dst; 4011bf215546Sopenharmony_ci}; 4012bf215546Sopenharmony_ci 4013bf215546Sopenharmony_ci 4014bf215546Sopenharmony_cistatic uint16_t 4015bf215546Sopenharmony_citc_call_clear_depth_stencil(struct pipe_context *pipe, void *call, uint64_t *last) 4016bf215546Sopenharmony_ci{ 4017bf215546Sopenharmony_ci struct tc_clear_depth_stencil *p = to_call(call, tc_clear_depth_stencil); 4018bf215546Sopenharmony_ci 4019bf215546Sopenharmony_ci pipe->clear_depth_stencil(pipe, p->dst, p->clear_flags, p->depth, p->stencil, 4020bf215546Sopenharmony_ci p->dstx, p->dsty, p->width, p->height, 4021bf215546Sopenharmony_ci p->render_condition_enabled); 4022bf215546Sopenharmony_ci tc_drop_surface_reference(p->dst); 4023bf215546Sopenharmony_ci return call_size(tc_clear_depth_stencil); 4024bf215546Sopenharmony_ci} 4025bf215546Sopenharmony_ci 4026bf215546Sopenharmony_cistatic void 4027bf215546Sopenharmony_citc_clear_depth_stencil(struct pipe_context *_pipe, 4028bf215546Sopenharmony_ci struct pipe_surface *dst, unsigned clear_flags, 4029bf215546Sopenharmony_ci double depth, unsigned stencil, unsigned dstx, 4030bf215546Sopenharmony_ci unsigned dsty, unsigned width, unsigned height, 4031bf215546Sopenharmony_ci bool render_condition_enabled) 4032bf215546Sopenharmony_ci{ 4033bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4034bf215546Sopenharmony_ci struct tc_clear_depth_stencil *p = tc_add_call(tc, TC_CALL_clear_depth_stencil, tc_clear_depth_stencil); 4035bf215546Sopenharmony_ci p->dst = NULL; 4036bf215546Sopenharmony_ci pipe_surface_reference(&p->dst, dst); 4037bf215546Sopenharmony_ci p->clear_flags = clear_flags; 4038bf215546Sopenharmony_ci p->depth = depth; 4039bf215546Sopenharmony_ci p->stencil = stencil; 4040bf215546Sopenharmony_ci p->dstx = dstx; 4041bf215546Sopenharmony_ci p->dsty = dsty; 4042bf215546Sopenharmony_ci p->width = width; 4043bf215546Sopenharmony_ci p->height = height; 4044bf215546Sopenharmony_ci p->render_condition_enabled = render_condition_enabled; 4045bf215546Sopenharmony_ci} 4046bf215546Sopenharmony_ci 4047bf215546Sopenharmony_cistruct tc_clear_buffer { 4048bf215546Sopenharmony_ci struct tc_call_base base; 4049bf215546Sopenharmony_ci uint8_t clear_value_size; 4050bf215546Sopenharmony_ci unsigned offset; 4051bf215546Sopenharmony_ci unsigned size; 4052bf215546Sopenharmony_ci char clear_value[16]; 4053bf215546Sopenharmony_ci struct pipe_resource *res; 4054bf215546Sopenharmony_ci}; 4055bf215546Sopenharmony_ci 4056bf215546Sopenharmony_cistatic uint16_t 4057bf215546Sopenharmony_citc_call_clear_buffer(struct pipe_context *pipe, void *call, uint64_t *last) 4058bf215546Sopenharmony_ci{ 4059bf215546Sopenharmony_ci struct tc_clear_buffer *p = to_call(call, tc_clear_buffer); 4060bf215546Sopenharmony_ci 4061bf215546Sopenharmony_ci pipe->clear_buffer(pipe, p->res, p->offset, p->size, p->clear_value, 4062bf215546Sopenharmony_ci p->clear_value_size); 4063bf215546Sopenharmony_ci tc_drop_resource_reference(p->res); 4064bf215546Sopenharmony_ci return call_size(tc_clear_buffer); 4065bf215546Sopenharmony_ci} 4066bf215546Sopenharmony_ci 4067bf215546Sopenharmony_cistatic void 4068bf215546Sopenharmony_citc_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res, 4069bf215546Sopenharmony_ci unsigned offset, unsigned size, 4070bf215546Sopenharmony_ci const void *clear_value, int clear_value_size) 4071bf215546Sopenharmony_ci{ 4072bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4073bf215546Sopenharmony_ci struct threaded_resource *tres = threaded_resource(res); 4074bf215546Sopenharmony_ci struct tc_clear_buffer *p = 4075bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_clear_buffer, tc_clear_buffer); 4076bf215546Sopenharmony_ci 4077bf215546Sopenharmony_ci tc_buffer_disable_cpu_storage(res); 4078bf215546Sopenharmony_ci 4079bf215546Sopenharmony_ci tc_set_resource_reference(&p->res, res); 4080bf215546Sopenharmony_ci tc_add_to_buffer_list(tc, &tc->buffer_lists[tc->next_buf_list], res); 4081bf215546Sopenharmony_ci p->offset = offset; 4082bf215546Sopenharmony_ci p->size = size; 4083bf215546Sopenharmony_ci memcpy(p->clear_value, clear_value, clear_value_size); 4084bf215546Sopenharmony_ci p->clear_value_size = clear_value_size; 4085bf215546Sopenharmony_ci 4086bf215546Sopenharmony_ci util_range_add(&tres->b, &tres->valid_buffer_range, offset, offset + size); 4087bf215546Sopenharmony_ci} 4088bf215546Sopenharmony_ci 4089bf215546Sopenharmony_cistruct tc_clear_texture { 4090bf215546Sopenharmony_ci struct tc_call_base base; 4091bf215546Sopenharmony_ci unsigned level; 4092bf215546Sopenharmony_ci struct pipe_box box; 4093bf215546Sopenharmony_ci char data[16]; 4094bf215546Sopenharmony_ci struct pipe_resource *res; 4095bf215546Sopenharmony_ci}; 4096bf215546Sopenharmony_ci 4097bf215546Sopenharmony_cistatic uint16_t 4098bf215546Sopenharmony_citc_call_clear_texture(struct pipe_context *pipe, void *call, uint64_t *last) 4099bf215546Sopenharmony_ci{ 4100bf215546Sopenharmony_ci struct tc_clear_texture *p = to_call(call, tc_clear_texture); 4101bf215546Sopenharmony_ci 4102bf215546Sopenharmony_ci pipe->clear_texture(pipe, p->res, p->level, &p->box, p->data); 4103bf215546Sopenharmony_ci tc_drop_resource_reference(p->res); 4104bf215546Sopenharmony_ci return call_size(tc_clear_texture); 4105bf215546Sopenharmony_ci} 4106bf215546Sopenharmony_ci 4107bf215546Sopenharmony_cistatic void 4108bf215546Sopenharmony_citc_clear_texture(struct pipe_context *_pipe, struct pipe_resource *res, 4109bf215546Sopenharmony_ci unsigned level, const struct pipe_box *box, const void *data) 4110bf215546Sopenharmony_ci{ 4111bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4112bf215546Sopenharmony_ci struct tc_clear_texture *p = 4113bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_clear_texture, tc_clear_texture); 4114bf215546Sopenharmony_ci 4115bf215546Sopenharmony_ci tc_set_resource_reference(&p->res, res); 4116bf215546Sopenharmony_ci p->level = level; 4117bf215546Sopenharmony_ci p->box = *box; 4118bf215546Sopenharmony_ci memcpy(p->data, data, 4119bf215546Sopenharmony_ci util_format_get_blocksize(res->format)); 4120bf215546Sopenharmony_ci} 4121bf215546Sopenharmony_ci 4122bf215546Sopenharmony_cistruct tc_resource_commit { 4123bf215546Sopenharmony_ci struct tc_call_base base; 4124bf215546Sopenharmony_ci bool commit; 4125bf215546Sopenharmony_ci unsigned level; 4126bf215546Sopenharmony_ci struct pipe_box box; 4127bf215546Sopenharmony_ci struct pipe_resource *res; 4128bf215546Sopenharmony_ci}; 4129bf215546Sopenharmony_ci 4130bf215546Sopenharmony_cistatic uint16_t 4131bf215546Sopenharmony_citc_call_resource_commit(struct pipe_context *pipe, void *call, uint64_t *last) 4132bf215546Sopenharmony_ci{ 4133bf215546Sopenharmony_ci struct tc_resource_commit *p = to_call(call, tc_resource_commit); 4134bf215546Sopenharmony_ci 4135bf215546Sopenharmony_ci pipe->resource_commit(pipe, p->res, p->level, &p->box, p->commit); 4136bf215546Sopenharmony_ci tc_drop_resource_reference(p->res); 4137bf215546Sopenharmony_ci return call_size(tc_resource_commit); 4138bf215546Sopenharmony_ci} 4139bf215546Sopenharmony_ci 4140bf215546Sopenharmony_cistatic bool 4141bf215546Sopenharmony_citc_resource_commit(struct pipe_context *_pipe, struct pipe_resource *res, 4142bf215546Sopenharmony_ci unsigned level, struct pipe_box *box, bool commit) 4143bf215546Sopenharmony_ci{ 4144bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4145bf215546Sopenharmony_ci struct tc_resource_commit *p = 4146bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_resource_commit, tc_resource_commit); 4147bf215546Sopenharmony_ci 4148bf215546Sopenharmony_ci tc_set_resource_reference(&p->res, res); 4149bf215546Sopenharmony_ci p->level = level; 4150bf215546Sopenharmony_ci p->box = *box; 4151bf215546Sopenharmony_ci p->commit = commit; 4152bf215546Sopenharmony_ci return true; /* we don't care about the return value for this call */ 4153bf215546Sopenharmony_ci} 4154bf215546Sopenharmony_ci 4155bf215546Sopenharmony_cistatic unsigned 4156bf215546Sopenharmony_citc_init_intel_perf_query_info(struct pipe_context *_pipe) 4157bf215546Sopenharmony_ci{ 4158bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4159bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4160bf215546Sopenharmony_ci 4161bf215546Sopenharmony_ci return pipe->init_intel_perf_query_info(pipe); 4162bf215546Sopenharmony_ci} 4163bf215546Sopenharmony_ci 4164bf215546Sopenharmony_cistatic void 4165bf215546Sopenharmony_citc_get_intel_perf_query_info(struct pipe_context *_pipe, 4166bf215546Sopenharmony_ci unsigned query_index, 4167bf215546Sopenharmony_ci const char **name, 4168bf215546Sopenharmony_ci uint32_t *data_size, 4169bf215546Sopenharmony_ci uint32_t *n_counters, 4170bf215546Sopenharmony_ci uint32_t *n_active) 4171bf215546Sopenharmony_ci{ 4172bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4173bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4174bf215546Sopenharmony_ci 4175bf215546Sopenharmony_ci tc_sync(tc); /* n_active vs begin/end_intel_perf_query */ 4176bf215546Sopenharmony_ci pipe->get_intel_perf_query_info(pipe, query_index, name, data_size, 4177bf215546Sopenharmony_ci n_counters, n_active); 4178bf215546Sopenharmony_ci} 4179bf215546Sopenharmony_ci 4180bf215546Sopenharmony_cistatic void 4181bf215546Sopenharmony_citc_get_intel_perf_query_counter_info(struct pipe_context *_pipe, 4182bf215546Sopenharmony_ci unsigned query_index, 4183bf215546Sopenharmony_ci unsigned counter_index, 4184bf215546Sopenharmony_ci const char **name, 4185bf215546Sopenharmony_ci const char **desc, 4186bf215546Sopenharmony_ci uint32_t *offset, 4187bf215546Sopenharmony_ci uint32_t *data_size, 4188bf215546Sopenharmony_ci uint32_t *type_enum, 4189bf215546Sopenharmony_ci uint32_t *data_type_enum, 4190bf215546Sopenharmony_ci uint64_t *raw_max) 4191bf215546Sopenharmony_ci{ 4192bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4193bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4194bf215546Sopenharmony_ci 4195bf215546Sopenharmony_ci pipe->get_intel_perf_query_counter_info(pipe, query_index, counter_index, 4196bf215546Sopenharmony_ci name, desc, offset, data_size, type_enum, data_type_enum, raw_max); 4197bf215546Sopenharmony_ci} 4198bf215546Sopenharmony_ci 4199bf215546Sopenharmony_cistatic struct pipe_query * 4200bf215546Sopenharmony_citc_new_intel_perf_query_obj(struct pipe_context *_pipe, unsigned query_index) 4201bf215546Sopenharmony_ci{ 4202bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4203bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4204bf215546Sopenharmony_ci 4205bf215546Sopenharmony_ci return pipe->new_intel_perf_query_obj(pipe, query_index); 4206bf215546Sopenharmony_ci} 4207bf215546Sopenharmony_ci 4208bf215546Sopenharmony_cistatic uint16_t 4209bf215546Sopenharmony_citc_call_begin_intel_perf_query(struct pipe_context *pipe, void *call, uint64_t *last) 4210bf215546Sopenharmony_ci{ 4211bf215546Sopenharmony_ci (void)pipe->begin_intel_perf_query(pipe, to_call(call, tc_query_call)->query); 4212bf215546Sopenharmony_ci return call_size(tc_query_call); 4213bf215546Sopenharmony_ci} 4214bf215546Sopenharmony_ci 4215bf215546Sopenharmony_cistatic bool 4216bf215546Sopenharmony_citc_begin_intel_perf_query(struct pipe_context *_pipe, struct pipe_query *q) 4217bf215546Sopenharmony_ci{ 4218bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4219bf215546Sopenharmony_ci 4220bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_begin_intel_perf_query, tc_query_call)->query = q; 4221bf215546Sopenharmony_ci 4222bf215546Sopenharmony_ci /* assume success, begin failure can be signaled from get_intel_perf_query_data */ 4223bf215546Sopenharmony_ci return true; 4224bf215546Sopenharmony_ci} 4225bf215546Sopenharmony_ci 4226bf215546Sopenharmony_cistatic uint16_t 4227bf215546Sopenharmony_citc_call_end_intel_perf_query(struct pipe_context *pipe, void *call, uint64_t *last) 4228bf215546Sopenharmony_ci{ 4229bf215546Sopenharmony_ci pipe->end_intel_perf_query(pipe, to_call(call, tc_query_call)->query); 4230bf215546Sopenharmony_ci return call_size(tc_query_call); 4231bf215546Sopenharmony_ci} 4232bf215546Sopenharmony_ci 4233bf215546Sopenharmony_cistatic void 4234bf215546Sopenharmony_citc_end_intel_perf_query(struct pipe_context *_pipe, struct pipe_query *q) 4235bf215546Sopenharmony_ci{ 4236bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4237bf215546Sopenharmony_ci 4238bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_end_intel_perf_query, tc_query_call)->query = q; 4239bf215546Sopenharmony_ci} 4240bf215546Sopenharmony_ci 4241bf215546Sopenharmony_cistatic void 4242bf215546Sopenharmony_citc_delete_intel_perf_query(struct pipe_context *_pipe, struct pipe_query *q) 4243bf215546Sopenharmony_ci{ 4244bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4245bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4246bf215546Sopenharmony_ci 4247bf215546Sopenharmony_ci tc_sync(tc); /* flush potentially pending begin/end_intel_perf_queries */ 4248bf215546Sopenharmony_ci pipe->delete_intel_perf_query(pipe, q); 4249bf215546Sopenharmony_ci} 4250bf215546Sopenharmony_ci 4251bf215546Sopenharmony_cistatic void 4252bf215546Sopenharmony_citc_wait_intel_perf_query(struct pipe_context *_pipe, struct pipe_query *q) 4253bf215546Sopenharmony_ci{ 4254bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4255bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4256bf215546Sopenharmony_ci 4257bf215546Sopenharmony_ci tc_sync(tc); /* flush potentially pending begin/end_intel_perf_queries */ 4258bf215546Sopenharmony_ci pipe->wait_intel_perf_query(pipe, q); 4259bf215546Sopenharmony_ci} 4260bf215546Sopenharmony_ci 4261bf215546Sopenharmony_cistatic bool 4262bf215546Sopenharmony_citc_is_intel_perf_query_ready(struct pipe_context *_pipe, struct pipe_query *q) 4263bf215546Sopenharmony_ci{ 4264bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4265bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4266bf215546Sopenharmony_ci 4267bf215546Sopenharmony_ci tc_sync(tc); /* flush potentially pending begin/end_intel_perf_queries */ 4268bf215546Sopenharmony_ci return pipe->is_intel_perf_query_ready(pipe, q); 4269bf215546Sopenharmony_ci} 4270bf215546Sopenharmony_ci 4271bf215546Sopenharmony_cistatic bool 4272bf215546Sopenharmony_citc_get_intel_perf_query_data(struct pipe_context *_pipe, 4273bf215546Sopenharmony_ci struct pipe_query *q, 4274bf215546Sopenharmony_ci size_t data_size, 4275bf215546Sopenharmony_ci uint32_t *data, 4276bf215546Sopenharmony_ci uint32_t *bytes_written) 4277bf215546Sopenharmony_ci{ 4278bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4279bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4280bf215546Sopenharmony_ci 4281bf215546Sopenharmony_ci tc_sync(tc); /* flush potentially pending begin/end_intel_perf_queries */ 4282bf215546Sopenharmony_ci return pipe->get_intel_perf_query_data(pipe, q, data_size, data, bytes_written); 4283bf215546Sopenharmony_ci} 4284bf215546Sopenharmony_ci 4285bf215546Sopenharmony_ci/******************************************************************** 4286bf215546Sopenharmony_ci * callback 4287bf215546Sopenharmony_ci */ 4288bf215546Sopenharmony_ci 4289bf215546Sopenharmony_cistruct tc_callback_call { 4290bf215546Sopenharmony_ci struct tc_call_base base; 4291bf215546Sopenharmony_ci void (*fn)(void *data); 4292bf215546Sopenharmony_ci void *data; 4293bf215546Sopenharmony_ci}; 4294bf215546Sopenharmony_ci 4295bf215546Sopenharmony_cistatic uint16_t 4296bf215546Sopenharmony_citc_call_callback(UNUSED struct pipe_context *pipe, void *call, uint64_t *last) 4297bf215546Sopenharmony_ci{ 4298bf215546Sopenharmony_ci struct tc_callback_call *p = to_call(call, tc_callback_call); 4299bf215546Sopenharmony_ci 4300bf215546Sopenharmony_ci p->fn(p->data); 4301bf215546Sopenharmony_ci return call_size(tc_callback_call); 4302bf215546Sopenharmony_ci} 4303bf215546Sopenharmony_ci 4304bf215546Sopenharmony_cistatic void 4305bf215546Sopenharmony_citc_callback(struct pipe_context *_pipe, void (*fn)(void *), void *data, 4306bf215546Sopenharmony_ci bool asap) 4307bf215546Sopenharmony_ci{ 4308bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4309bf215546Sopenharmony_ci 4310bf215546Sopenharmony_ci if (asap && tc_is_sync(tc)) { 4311bf215546Sopenharmony_ci fn(data); 4312bf215546Sopenharmony_ci return; 4313bf215546Sopenharmony_ci } 4314bf215546Sopenharmony_ci 4315bf215546Sopenharmony_ci struct tc_callback_call *p = 4316bf215546Sopenharmony_ci tc_add_call(tc, TC_CALL_callback, tc_callback_call); 4317bf215546Sopenharmony_ci p->fn = fn; 4318bf215546Sopenharmony_ci p->data = data; 4319bf215546Sopenharmony_ci} 4320bf215546Sopenharmony_ci 4321bf215546Sopenharmony_ci 4322bf215546Sopenharmony_ci/******************************************************************** 4323bf215546Sopenharmony_ci * create & destroy 4324bf215546Sopenharmony_ci */ 4325bf215546Sopenharmony_ci 4326bf215546Sopenharmony_cistatic void 4327bf215546Sopenharmony_citc_destroy(struct pipe_context *_pipe) 4328bf215546Sopenharmony_ci{ 4329bf215546Sopenharmony_ci struct threaded_context *tc = threaded_context(_pipe); 4330bf215546Sopenharmony_ci struct pipe_context *pipe = tc->pipe; 4331bf215546Sopenharmony_ci 4332bf215546Sopenharmony_ci if (tc->base.const_uploader && 4333bf215546Sopenharmony_ci tc->base.stream_uploader != tc->base.const_uploader) 4334bf215546Sopenharmony_ci u_upload_destroy(tc->base.const_uploader); 4335bf215546Sopenharmony_ci 4336bf215546Sopenharmony_ci if (tc->base.stream_uploader) 4337bf215546Sopenharmony_ci u_upload_destroy(tc->base.stream_uploader); 4338bf215546Sopenharmony_ci 4339bf215546Sopenharmony_ci tc_sync(tc); 4340bf215546Sopenharmony_ci 4341bf215546Sopenharmony_ci if (util_queue_is_initialized(&tc->queue)) { 4342bf215546Sopenharmony_ci util_queue_destroy(&tc->queue); 4343bf215546Sopenharmony_ci 4344bf215546Sopenharmony_ci for (unsigned i = 0; i < TC_MAX_BATCHES; i++) { 4345bf215546Sopenharmony_ci util_queue_fence_destroy(&tc->batch_slots[i].fence); 4346bf215546Sopenharmony_ci assert(!tc->batch_slots[i].token); 4347bf215546Sopenharmony_ci } 4348bf215546Sopenharmony_ci } 4349bf215546Sopenharmony_ci 4350bf215546Sopenharmony_ci slab_destroy_child(&tc->pool_transfers); 4351bf215546Sopenharmony_ci assert(tc->batch_slots[tc->next].num_total_slots == 0); 4352bf215546Sopenharmony_ci pipe->destroy(pipe); 4353bf215546Sopenharmony_ci 4354bf215546Sopenharmony_ci for (unsigned i = 0; i < TC_MAX_BUFFER_LISTS; i++) { 4355bf215546Sopenharmony_ci if (!util_queue_fence_is_signalled(&tc->buffer_lists[i].driver_flushed_fence)) 4356bf215546Sopenharmony_ci util_queue_fence_signal(&tc->buffer_lists[i].driver_flushed_fence); 4357bf215546Sopenharmony_ci util_queue_fence_destroy(&tc->buffer_lists[i].driver_flushed_fence); 4358bf215546Sopenharmony_ci } 4359bf215546Sopenharmony_ci 4360bf215546Sopenharmony_ci FREE(tc); 4361bf215546Sopenharmony_ci} 4362bf215546Sopenharmony_ci 4363bf215546Sopenharmony_cistatic const tc_execute execute_func[TC_NUM_CALLS] = { 4364bf215546Sopenharmony_ci#define CALL(name) tc_call_##name, 4365bf215546Sopenharmony_ci#include "u_threaded_context_calls.h" 4366bf215546Sopenharmony_ci#undef CALL 4367bf215546Sopenharmony_ci}; 4368bf215546Sopenharmony_ci 4369bf215546Sopenharmony_civoid tc_driver_internal_flush_notify(struct threaded_context *tc) 4370bf215546Sopenharmony_ci{ 4371bf215546Sopenharmony_ci /* Allow drivers to call this function even for internal contexts that 4372bf215546Sopenharmony_ci * don't have tc. It simplifies drivers. 4373bf215546Sopenharmony_ci */ 4374bf215546Sopenharmony_ci if (!tc) 4375bf215546Sopenharmony_ci return; 4376bf215546Sopenharmony_ci 4377bf215546Sopenharmony_ci /* Signal fences set by tc_batch_execute. */ 4378bf215546Sopenharmony_ci for (unsigned i = 0; i < tc->num_signal_fences_next_flush; i++) 4379bf215546Sopenharmony_ci util_queue_fence_signal(tc->signal_fences_next_flush[i]); 4380bf215546Sopenharmony_ci 4381bf215546Sopenharmony_ci tc->num_signal_fences_next_flush = 0; 4382bf215546Sopenharmony_ci} 4383bf215546Sopenharmony_ci 4384bf215546Sopenharmony_ci/** 4385bf215546Sopenharmony_ci * Wrap an existing pipe_context into a threaded_context. 4386bf215546Sopenharmony_ci * 4387bf215546Sopenharmony_ci * \param pipe pipe_context to wrap 4388bf215546Sopenharmony_ci * \param parent_transfer_pool parent slab pool set up for creating pipe_- 4389bf215546Sopenharmony_ci * transfer objects; the driver should have one 4390bf215546Sopenharmony_ci * in pipe_screen. 4391bf215546Sopenharmony_ci * \param replace_buffer callback for replacing a pipe_resource's storage 4392bf215546Sopenharmony_ci * with another pipe_resource's storage. 4393bf215546Sopenharmony_ci * \param options optional TC options/callbacks 4394bf215546Sopenharmony_ci * \param out if successful, the threaded_context will be returned here in 4395bf215546Sopenharmony_ci * addition to the return value if "out" != NULL 4396bf215546Sopenharmony_ci */ 4397bf215546Sopenharmony_cistruct pipe_context * 4398bf215546Sopenharmony_cithreaded_context_create(struct pipe_context *pipe, 4399bf215546Sopenharmony_ci struct slab_parent_pool *parent_transfer_pool, 4400bf215546Sopenharmony_ci tc_replace_buffer_storage_func replace_buffer, 4401bf215546Sopenharmony_ci const struct threaded_context_options *options, 4402bf215546Sopenharmony_ci struct threaded_context **out) 4403bf215546Sopenharmony_ci{ 4404bf215546Sopenharmony_ci struct threaded_context *tc; 4405bf215546Sopenharmony_ci 4406bf215546Sopenharmony_ci if (!pipe) 4407bf215546Sopenharmony_ci return NULL; 4408bf215546Sopenharmony_ci 4409bf215546Sopenharmony_ci if (!debug_get_bool_option("GALLIUM_THREAD", util_get_cpu_caps()->nr_cpus > 1)) 4410bf215546Sopenharmony_ci return pipe; 4411bf215546Sopenharmony_ci 4412bf215546Sopenharmony_ci tc = CALLOC_STRUCT(threaded_context); 4413bf215546Sopenharmony_ci if (!tc) { 4414bf215546Sopenharmony_ci pipe->destroy(pipe); 4415bf215546Sopenharmony_ci return NULL; 4416bf215546Sopenharmony_ci } 4417bf215546Sopenharmony_ci 4418bf215546Sopenharmony_ci if (options) 4419bf215546Sopenharmony_ci tc->options = *options; 4420bf215546Sopenharmony_ci 4421bf215546Sopenharmony_ci pipe = trace_context_create_threaded(pipe->screen, pipe, &replace_buffer, &tc->options); 4422bf215546Sopenharmony_ci 4423bf215546Sopenharmony_ci /* The driver context isn't wrapped, so set its "priv" to NULL. */ 4424bf215546Sopenharmony_ci pipe->priv = NULL; 4425bf215546Sopenharmony_ci 4426bf215546Sopenharmony_ci tc->pipe = pipe; 4427bf215546Sopenharmony_ci tc->replace_buffer_storage = replace_buffer; 4428bf215546Sopenharmony_ci tc->map_buffer_alignment = 4429bf215546Sopenharmony_ci pipe->screen->get_param(pipe->screen, PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT); 4430bf215546Sopenharmony_ci tc->ubo_alignment = 4431bf215546Sopenharmony_ci MAX2(pipe->screen->get_param(pipe->screen, PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT), 64); 4432bf215546Sopenharmony_ci tc->base.priv = pipe; /* priv points to the wrapped driver context */ 4433bf215546Sopenharmony_ci tc->base.screen = pipe->screen; 4434bf215546Sopenharmony_ci tc->base.destroy = tc_destroy; 4435bf215546Sopenharmony_ci tc->base.callback = tc_callback; 4436bf215546Sopenharmony_ci 4437bf215546Sopenharmony_ci tc->base.stream_uploader = u_upload_clone(&tc->base, pipe->stream_uploader); 4438bf215546Sopenharmony_ci if (pipe->stream_uploader == pipe->const_uploader) 4439bf215546Sopenharmony_ci tc->base.const_uploader = tc->base.stream_uploader; 4440bf215546Sopenharmony_ci else 4441bf215546Sopenharmony_ci tc->base.const_uploader = u_upload_clone(&tc->base, pipe->const_uploader); 4442bf215546Sopenharmony_ci 4443bf215546Sopenharmony_ci if (!tc->base.stream_uploader || !tc->base.const_uploader) 4444bf215546Sopenharmony_ci goto fail; 4445bf215546Sopenharmony_ci 4446bf215546Sopenharmony_ci tc->use_forced_staging_uploads = true; 4447bf215546Sopenharmony_ci 4448bf215546Sopenharmony_ci /* The queue size is the number of batches "waiting". Batches are removed 4449bf215546Sopenharmony_ci * from the queue before being executed, so keep one tc_batch slot for that 4450bf215546Sopenharmony_ci * execution. Also, keep one unused slot for an unflushed batch. 4451bf215546Sopenharmony_ci */ 4452bf215546Sopenharmony_ci if (!util_queue_init(&tc->queue, "gdrv", TC_MAX_BATCHES - 2, 1, 0, NULL)) 4453bf215546Sopenharmony_ci goto fail; 4454bf215546Sopenharmony_ci 4455bf215546Sopenharmony_ci for (unsigned i = 0; i < TC_MAX_BATCHES; i++) { 4456bf215546Sopenharmony_ci#if !defined(NDEBUG) && TC_DEBUG >= 1 4457bf215546Sopenharmony_ci tc->batch_slots[i].sentinel = TC_SENTINEL; 4458bf215546Sopenharmony_ci#endif 4459bf215546Sopenharmony_ci tc->batch_slots[i].tc = tc; 4460bf215546Sopenharmony_ci util_queue_fence_init(&tc->batch_slots[i].fence); 4461bf215546Sopenharmony_ci } 4462bf215546Sopenharmony_ci for (unsigned i = 0; i < TC_MAX_BUFFER_LISTS; i++) 4463bf215546Sopenharmony_ci util_queue_fence_init(&tc->buffer_lists[i].driver_flushed_fence); 4464bf215546Sopenharmony_ci 4465bf215546Sopenharmony_ci list_inithead(&tc->unflushed_queries); 4466bf215546Sopenharmony_ci 4467bf215546Sopenharmony_ci slab_create_child(&tc->pool_transfers, parent_transfer_pool); 4468bf215546Sopenharmony_ci 4469bf215546Sopenharmony_ci /* If you have different limits in each shader stage, set the maximum. */ 4470bf215546Sopenharmony_ci struct pipe_screen *screen = pipe->screen;; 4471bf215546Sopenharmony_ci tc->max_vertex_buffers = 4472bf215546Sopenharmony_ci screen->get_param(screen, PIPE_CAP_MAX_VERTEX_BUFFERS); 4473bf215546Sopenharmony_ci tc->max_const_buffers = 4474bf215546Sopenharmony_ci screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, 4475bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_CONST_BUFFERS); 4476bf215546Sopenharmony_ci tc->max_shader_buffers = 4477bf215546Sopenharmony_ci screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, 4478bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_SHADER_BUFFERS); 4479bf215546Sopenharmony_ci tc->max_images = 4480bf215546Sopenharmony_ci screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, 4481bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_SHADER_IMAGES); 4482bf215546Sopenharmony_ci tc->max_samplers = 4483bf215546Sopenharmony_ci screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, 4484bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); 4485bf215546Sopenharmony_ci 4486bf215546Sopenharmony_ci tc->base.set_context_param = tc_set_context_param; /* always set this */ 4487bf215546Sopenharmony_ci 4488bf215546Sopenharmony_ci#define CTX_INIT(_member) \ 4489bf215546Sopenharmony_ci tc->base._member = tc->pipe->_member ? tc_##_member : NULL 4490bf215546Sopenharmony_ci 4491bf215546Sopenharmony_ci CTX_INIT(flush); 4492bf215546Sopenharmony_ci CTX_INIT(draw_vbo); 4493bf215546Sopenharmony_ci CTX_INIT(draw_vertex_state); 4494bf215546Sopenharmony_ci CTX_INIT(launch_grid); 4495bf215546Sopenharmony_ci CTX_INIT(resource_copy_region); 4496bf215546Sopenharmony_ci CTX_INIT(blit); 4497bf215546Sopenharmony_ci CTX_INIT(clear); 4498bf215546Sopenharmony_ci CTX_INIT(clear_render_target); 4499bf215546Sopenharmony_ci CTX_INIT(clear_depth_stencil); 4500bf215546Sopenharmony_ci CTX_INIT(clear_buffer); 4501bf215546Sopenharmony_ci CTX_INIT(clear_texture); 4502bf215546Sopenharmony_ci CTX_INIT(flush_resource); 4503bf215546Sopenharmony_ci CTX_INIT(generate_mipmap); 4504bf215546Sopenharmony_ci CTX_INIT(render_condition); 4505bf215546Sopenharmony_ci CTX_INIT(create_query); 4506bf215546Sopenharmony_ci CTX_INIT(create_batch_query); 4507bf215546Sopenharmony_ci CTX_INIT(destroy_query); 4508bf215546Sopenharmony_ci CTX_INIT(begin_query); 4509bf215546Sopenharmony_ci CTX_INIT(end_query); 4510bf215546Sopenharmony_ci CTX_INIT(get_query_result); 4511bf215546Sopenharmony_ci CTX_INIT(get_query_result_resource); 4512bf215546Sopenharmony_ci CTX_INIT(set_active_query_state); 4513bf215546Sopenharmony_ci CTX_INIT(create_blend_state); 4514bf215546Sopenharmony_ci CTX_INIT(bind_blend_state); 4515bf215546Sopenharmony_ci CTX_INIT(delete_blend_state); 4516bf215546Sopenharmony_ci CTX_INIT(create_sampler_state); 4517bf215546Sopenharmony_ci CTX_INIT(bind_sampler_states); 4518bf215546Sopenharmony_ci CTX_INIT(delete_sampler_state); 4519bf215546Sopenharmony_ci CTX_INIT(create_rasterizer_state); 4520bf215546Sopenharmony_ci CTX_INIT(bind_rasterizer_state); 4521bf215546Sopenharmony_ci CTX_INIT(delete_rasterizer_state); 4522bf215546Sopenharmony_ci CTX_INIT(create_depth_stencil_alpha_state); 4523bf215546Sopenharmony_ci CTX_INIT(bind_depth_stencil_alpha_state); 4524bf215546Sopenharmony_ci CTX_INIT(delete_depth_stencil_alpha_state); 4525bf215546Sopenharmony_ci CTX_INIT(link_shader); 4526bf215546Sopenharmony_ci CTX_INIT(create_fs_state); 4527bf215546Sopenharmony_ci CTX_INIT(bind_fs_state); 4528bf215546Sopenharmony_ci CTX_INIT(delete_fs_state); 4529bf215546Sopenharmony_ci CTX_INIT(create_vs_state); 4530bf215546Sopenharmony_ci CTX_INIT(bind_vs_state); 4531bf215546Sopenharmony_ci CTX_INIT(delete_vs_state); 4532bf215546Sopenharmony_ci CTX_INIT(create_gs_state); 4533bf215546Sopenharmony_ci CTX_INIT(bind_gs_state); 4534bf215546Sopenharmony_ci CTX_INIT(delete_gs_state); 4535bf215546Sopenharmony_ci CTX_INIT(create_tcs_state); 4536bf215546Sopenharmony_ci CTX_INIT(bind_tcs_state); 4537bf215546Sopenharmony_ci CTX_INIT(delete_tcs_state); 4538bf215546Sopenharmony_ci CTX_INIT(create_tes_state); 4539bf215546Sopenharmony_ci CTX_INIT(bind_tes_state); 4540bf215546Sopenharmony_ci CTX_INIT(delete_tes_state); 4541bf215546Sopenharmony_ci CTX_INIT(create_compute_state); 4542bf215546Sopenharmony_ci CTX_INIT(bind_compute_state); 4543bf215546Sopenharmony_ci CTX_INIT(delete_compute_state); 4544bf215546Sopenharmony_ci CTX_INIT(create_vertex_elements_state); 4545bf215546Sopenharmony_ci CTX_INIT(bind_vertex_elements_state); 4546bf215546Sopenharmony_ci CTX_INIT(delete_vertex_elements_state); 4547bf215546Sopenharmony_ci CTX_INIT(set_blend_color); 4548bf215546Sopenharmony_ci CTX_INIT(set_stencil_ref); 4549bf215546Sopenharmony_ci CTX_INIT(set_sample_mask); 4550bf215546Sopenharmony_ci CTX_INIT(set_min_samples); 4551bf215546Sopenharmony_ci CTX_INIT(set_clip_state); 4552bf215546Sopenharmony_ci CTX_INIT(set_constant_buffer); 4553bf215546Sopenharmony_ci CTX_INIT(set_inlinable_constants); 4554bf215546Sopenharmony_ci CTX_INIT(set_framebuffer_state); 4555bf215546Sopenharmony_ci CTX_INIT(set_polygon_stipple); 4556bf215546Sopenharmony_ci CTX_INIT(set_sample_locations); 4557bf215546Sopenharmony_ci CTX_INIT(set_scissor_states); 4558bf215546Sopenharmony_ci CTX_INIT(set_viewport_states); 4559bf215546Sopenharmony_ci CTX_INIT(set_window_rectangles); 4560bf215546Sopenharmony_ci CTX_INIT(set_sampler_views); 4561bf215546Sopenharmony_ci CTX_INIT(set_tess_state); 4562bf215546Sopenharmony_ci CTX_INIT(set_patch_vertices); 4563bf215546Sopenharmony_ci CTX_INIT(set_shader_buffers); 4564bf215546Sopenharmony_ci CTX_INIT(set_shader_images); 4565bf215546Sopenharmony_ci CTX_INIT(set_vertex_buffers); 4566bf215546Sopenharmony_ci CTX_INIT(create_stream_output_target); 4567bf215546Sopenharmony_ci CTX_INIT(stream_output_target_destroy); 4568bf215546Sopenharmony_ci CTX_INIT(set_stream_output_targets); 4569bf215546Sopenharmony_ci CTX_INIT(create_sampler_view); 4570bf215546Sopenharmony_ci CTX_INIT(sampler_view_destroy); 4571bf215546Sopenharmony_ci CTX_INIT(create_surface); 4572bf215546Sopenharmony_ci CTX_INIT(surface_destroy); 4573bf215546Sopenharmony_ci CTX_INIT(buffer_map); 4574bf215546Sopenharmony_ci CTX_INIT(texture_map); 4575bf215546Sopenharmony_ci CTX_INIT(transfer_flush_region); 4576bf215546Sopenharmony_ci CTX_INIT(buffer_unmap); 4577bf215546Sopenharmony_ci CTX_INIT(texture_unmap); 4578bf215546Sopenharmony_ci CTX_INIT(buffer_subdata); 4579bf215546Sopenharmony_ci CTX_INIT(texture_subdata); 4580bf215546Sopenharmony_ci CTX_INIT(texture_barrier); 4581bf215546Sopenharmony_ci CTX_INIT(memory_barrier); 4582bf215546Sopenharmony_ci CTX_INIT(resource_commit); 4583bf215546Sopenharmony_ci CTX_INIT(create_video_codec); 4584bf215546Sopenharmony_ci CTX_INIT(create_video_buffer); 4585bf215546Sopenharmony_ci CTX_INIT(set_compute_resources); 4586bf215546Sopenharmony_ci CTX_INIT(set_global_binding); 4587bf215546Sopenharmony_ci CTX_INIT(get_sample_position); 4588bf215546Sopenharmony_ci CTX_INIT(invalidate_resource); 4589bf215546Sopenharmony_ci CTX_INIT(get_device_reset_status); 4590bf215546Sopenharmony_ci CTX_INIT(set_device_reset_callback); 4591bf215546Sopenharmony_ci CTX_INIT(dump_debug_state); 4592bf215546Sopenharmony_ci CTX_INIT(set_log_context); 4593bf215546Sopenharmony_ci CTX_INIT(emit_string_marker); 4594bf215546Sopenharmony_ci CTX_INIT(set_debug_callback); 4595bf215546Sopenharmony_ci CTX_INIT(create_fence_fd); 4596bf215546Sopenharmony_ci CTX_INIT(fence_server_sync); 4597bf215546Sopenharmony_ci CTX_INIT(fence_server_signal); 4598bf215546Sopenharmony_ci CTX_INIT(get_timestamp); 4599bf215546Sopenharmony_ci CTX_INIT(create_texture_handle); 4600bf215546Sopenharmony_ci CTX_INIT(delete_texture_handle); 4601bf215546Sopenharmony_ci CTX_INIT(make_texture_handle_resident); 4602bf215546Sopenharmony_ci CTX_INIT(create_image_handle); 4603bf215546Sopenharmony_ci CTX_INIT(delete_image_handle); 4604bf215546Sopenharmony_ci CTX_INIT(make_image_handle_resident); 4605bf215546Sopenharmony_ci CTX_INIT(set_frontend_noop); 4606bf215546Sopenharmony_ci CTX_INIT(init_intel_perf_query_info); 4607bf215546Sopenharmony_ci CTX_INIT(get_intel_perf_query_info); 4608bf215546Sopenharmony_ci CTX_INIT(get_intel_perf_query_counter_info); 4609bf215546Sopenharmony_ci CTX_INIT(new_intel_perf_query_obj); 4610bf215546Sopenharmony_ci CTX_INIT(begin_intel_perf_query); 4611bf215546Sopenharmony_ci CTX_INIT(end_intel_perf_query); 4612bf215546Sopenharmony_ci CTX_INIT(delete_intel_perf_query); 4613bf215546Sopenharmony_ci CTX_INIT(wait_intel_perf_query); 4614bf215546Sopenharmony_ci CTX_INIT(is_intel_perf_query_ready); 4615bf215546Sopenharmony_ci CTX_INIT(get_intel_perf_query_data); 4616bf215546Sopenharmony_ci#undef CTX_INIT 4617bf215546Sopenharmony_ci 4618bf215546Sopenharmony_ci if (out) 4619bf215546Sopenharmony_ci *out = tc; 4620bf215546Sopenharmony_ci 4621bf215546Sopenharmony_ci tc_begin_next_buffer_list(tc); 4622bf215546Sopenharmony_ci return &tc->base; 4623bf215546Sopenharmony_ci 4624bf215546Sopenharmony_cifail: 4625bf215546Sopenharmony_ci tc_destroy(&tc->base); 4626bf215546Sopenharmony_ci return NULL; 4627bf215546Sopenharmony_ci} 4628bf215546Sopenharmony_ci 4629bf215546Sopenharmony_civoid 4630bf215546Sopenharmony_cithreaded_context_init_bytes_mapped_limit(struct threaded_context *tc, unsigned divisor) 4631bf215546Sopenharmony_ci{ 4632bf215546Sopenharmony_ci uint64_t total_ram; 4633bf215546Sopenharmony_ci if (os_get_total_physical_memory(&total_ram)) { 4634bf215546Sopenharmony_ci tc->bytes_mapped_limit = total_ram / divisor; 4635bf215546Sopenharmony_ci if (sizeof(void*) == 4) 4636bf215546Sopenharmony_ci tc->bytes_mapped_limit = MIN2(tc->bytes_mapped_limit, 512*1024*1024UL); 4637bf215546Sopenharmony_ci } 4638bf215546Sopenharmony_ci} 4639