1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "d3d12_batch.h" 25bf215546Sopenharmony_ci#include "d3d12_context.h" 26bf215546Sopenharmony_ci#include "d3d12_fence.h" 27bf215546Sopenharmony_ci#include "d3d12_query.h" 28bf215546Sopenharmony_ci#include "d3d12_residency.h" 29bf215546Sopenharmony_ci#include "d3d12_resource.h" 30bf215546Sopenharmony_ci#include "d3d12_resource_state.h" 31bf215546Sopenharmony_ci#include "d3d12_screen.h" 32bf215546Sopenharmony_ci#include "d3d12_surface.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "util/hash_table.h" 35bf215546Sopenharmony_ci#include "util/set.h" 36bf215546Sopenharmony_ci#include "util/u_inlines.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include <dxguids/dxguids.h> 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_cibool 41bf215546Sopenharmony_cid3d12_init_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) 42bf215546Sopenharmony_ci{ 43bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci batch->bos = _mesa_hash_table_create(NULL, _mesa_hash_pointer, 46bf215546Sopenharmony_ci _mesa_key_pointer_equal); 47bf215546Sopenharmony_ci batch->sampler_views = _mesa_set_create(NULL, _mesa_hash_pointer, 48bf215546Sopenharmony_ci _mesa_key_pointer_equal); 49bf215546Sopenharmony_ci batch->surfaces = _mesa_set_create(NULL, _mesa_hash_pointer, 50bf215546Sopenharmony_ci _mesa_key_pointer_equal); 51bf215546Sopenharmony_ci batch->objects = _mesa_set_create(NULL, 52bf215546Sopenharmony_ci _mesa_hash_pointer, 53bf215546Sopenharmony_ci _mesa_key_pointer_equal); 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci if (!batch->bos || !batch->sampler_views || !batch->surfaces || !batch->objects) 56bf215546Sopenharmony_ci return false; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci util_dynarray_init(&batch->zombie_samplers, NULL); 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci if (FAILED(screen->dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, 61bf215546Sopenharmony_ci IID_PPV_ARGS(&batch->cmdalloc)))) 62bf215546Sopenharmony_ci return false; 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci batch->sampler_heap = 66bf215546Sopenharmony_ci d3d12_descriptor_heap_new(screen->dev, 67bf215546Sopenharmony_ci D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 68bf215546Sopenharmony_ci D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 69bf215546Sopenharmony_ci 128); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci batch->view_heap = 72bf215546Sopenharmony_ci d3d12_descriptor_heap_new(screen->dev, 73bf215546Sopenharmony_ci D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 74bf215546Sopenharmony_ci D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 75bf215546Sopenharmony_ci 1024); 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci if (!batch->sampler_heap && !batch->view_heap) 78bf215546Sopenharmony_ci return false; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci return true; 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_cistatic void 84bf215546Sopenharmony_cidelete_bo(hash_entry *entry) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci struct d3d12_bo *bo = (struct d3d12_bo *)entry->key; 87bf215546Sopenharmony_ci d3d12_bo_unreference(bo); 88bf215546Sopenharmony_ci} 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_cistatic void 91bf215546Sopenharmony_cidelete_sampler_view(set_entry *entry) 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci struct pipe_sampler_view *pres = (struct pipe_sampler_view *)entry->key; 94bf215546Sopenharmony_ci pipe_sampler_view_reference(&pres, NULL); 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_cistatic void 98bf215546Sopenharmony_cidelete_surface(set_entry *entry) 99bf215546Sopenharmony_ci{ 100bf215546Sopenharmony_ci struct pipe_surface *surf = (struct pipe_surface *)entry->key; 101bf215546Sopenharmony_ci pipe_surface_reference(&surf, NULL); 102bf215546Sopenharmony_ci} 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_cistatic void 105bf215546Sopenharmony_cidelete_object(set_entry *entry) 106bf215546Sopenharmony_ci{ 107bf215546Sopenharmony_ci ID3D12Object *object = (ID3D12Object *)entry->key; 108bf215546Sopenharmony_ci object->Release(); 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_cibool 112bf215546Sopenharmony_cid3d12_reset_batch(struct d3d12_context *ctx, struct d3d12_batch *batch, uint64_t timeout_ns) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci // batch hasn't been submitted before 115bf215546Sopenharmony_ci if (!batch->fence && !batch->has_errors) 116bf215546Sopenharmony_ci return true; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci if (batch->fence) { 119bf215546Sopenharmony_ci if (!d3d12_fence_finish(batch->fence, timeout_ns)) 120bf215546Sopenharmony_ci return false; 121bf215546Sopenharmony_ci d3d12_fence_reference(&batch->fence, NULL); 122bf215546Sopenharmony_ci } 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci _mesa_hash_table_clear(batch->bos, delete_bo); 125bf215546Sopenharmony_ci _mesa_set_clear(batch->sampler_views, delete_sampler_view); 126bf215546Sopenharmony_ci _mesa_set_clear(batch->surfaces, delete_surface); 127bf215546Sopenharmony_ci _mesa_set_clear(batch->objects, delete_object); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci util_dynarray_foreach(&batch->zombie_samplers, d3d12_descriptor_handle, handle) 130bf215546Sopenharmony_ci d3d12_descriptor_handle_free(handle); 131bf215546Sopenharmony_ci util_dynarray_clear(&batch->zombie_samplers); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci d3d12_descriptor_heap_clear(batch->view_heap); 134bf215546Sopenharmony_ci d3d12_descriptor_heap_clear(batch->sampler_heap); 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci if (FAILED(batch->cmdalloc->Reset())) { 137bf215546Sopenharmony_ci debug_printf("D3D12: resetting ID3D12CommandAllocator failed\n"); 138bf215546Sopenharmony_ci return false; 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci batch->has_errors = false; 141bf215546Sopenharmony_ci batch->pending_memory_barrier = false; 142bf215546Sopenharmony_ci return true; 143bf215546Sopenharmony_ci} 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_civoid 146bf215546Sopenharmony_cid3d12_destroy_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) 147bf215546Sopenharmony_ci{ 148bf215546Sopenharmony_ci d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE); 149bf215546Sopenharmony_ci batch->cmdalloc->Release(); 150bf215546Sopenharmony_ci d3d12_descriptor_heap_free(batch->sampler_heap); 151bf215546Sopenharmony_ci d3d12_descriptor_heap_free(batch->view_heap); 152bf215546Sopenharmony_ci _mesa_hash_table_destroy(batch->bos, NULL); 153bf215546Sopenharmony_ci _mesa_set_destroy(batch->sampler_views, NULL); 154bf215546Sopenharmony_ci _mesa_set_destroy(batch->surfaces, NULL); 155bf215546Sopenharmony_ci _mesa_set_destroy(batch->objects, NULL); 156bf215546Sopenharmony_ci util_dynarray_fini(&batch->zombie_samplers); 157bf215546Sopenharmony_ci} 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_civoid 160bf215546Sopenharmony_cid3d12_start_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) 161bf215546Sopenharmony_ci{ 162bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 163bf215546Sopenharmony_ci ID3D12DescriptorHeap* heaps[2] = { d3d12_descriptor_heap_get(batch->view_heap), 164bf215546Sopenharmony_ci d3d12_descriptor_heap_get(batch->sampler_heap) }; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci d3d12_reset_batch(ctx, batch, PIPE_TIMEOUT_INFINITE); 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci /* Create or reset global command list */ 169bf215546Sopenharmony_ci if (ctx->cmdlist) { 170bf215546Sopenharmony_ci if (FAILED(ctx->cmdlist->Reset(batch->cmdalloc, NULL))) { 171bf215546Sopenharmony_ci debug_printf("D3D12: resetting ID3D12GraphicsCommandList failed\n"); 172bf215546Sopenharmony_ci batch->has_errors = true; 173bf215546Sopenharmony_ci return; 174bf215546Sopenharmony_ci } 175bf215546Sopenharmony_ci } else { 176bf215546Sopenharmony_ci if (FAILED(screen->dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, 177bf215546Sopenharmony_ci batch->cmdalloc, NULL, 178bf215546Sopenharmony_ci IID_PPV_ARGS(&ctx->cmdlist)))) { 179bf215546Sopenharmony_ci debug_printf("D3D12: creating ID3D12GraphicsCommandList failed\n"); 180bf215546Sopenharmony_ci batch->has_errors = true; 181bf215546Sopenharmony_ci return; 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci ctx->cmdlist->SetDescriptorHeaps(2, heaps); 186bf215546Sopenharmony_ci ctx->cmdlist_dirty = ~0; 187bf215546Sopenharmony_ci for (int i = 0; i < PIPE_SHADER_TYPES; ++i) 188bf215546Sopenharmony_ci ctx->shader_dirty[i] = ~0; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci if (!ctx->queries_disabled) 191bf215546Sopenharmony_ci d3d12_resume_queries(ctx); 192bf215546Sopenharmony_ci if (ctx->current_predication) 193bf215546Sopenharmony_ci d3d12_enable_predication(ctx); 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci batch->submit_id = ++ctx->submit_id; 196bf215546Sopenharmony_ci} 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_civoid 199bf215546Sopenharmony_cid3d12_end_batch(struct d3d12_context *ctx, struct d3d12_batch *batch) 200bf215546Sopenharmony_ci{ 201bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci if (!ctx->queries_disabled) 204bf215546Sopenharmony_ci d3d12_suspend_queries(ctx); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci if (FAILED(ctx->cmdlist->Close())) { 207bf215546Sopenharmony_ci debug_printf("D3D12: closing ID3D12GraphicsCommandList failed\n"); 208bf215546Sopenharmony_ci batch->has_errors = true; 209bf215546Sopenharmony_ci return; 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci mtx_lock(&screen->submit_mutex); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci d3d12_process_batch_residency(screen, batch); 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci bool has_state_fixup = d3d12_context_state_resolve_submission(ctx, batch); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci ID3D12CommandList *cmdlists[] = { ctx->state_fixup_cmdlist, ctx->cmdlist }; 219bf215546Sopenharmony_ci ID3D12CommandList **to_execute = cmdlists; 220bf215546Sopenharmony_ci UINT count_to_execute = ARRAY_SIZE(cmdlists); 221bf215546Sopenharmony_ci if (!has_state_fixup) { 222bf215546Sopenharmony_ci to_execute++; 223bf215546Sopenharmony_ci count_to_execute--; 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci screen->cmdqueue->ExecuteCommandLists(count_to_execute, to_execute); 226bf215546Sopenharmony_ci batch->fence = d3d12_create_fence(screen); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci mtx_unlock(&screen->submit_mutex); 229bf215546Sopenharmony_ci} 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_cienum batch_bo_reference_state 232bf215546Sopenharmony_ci{ 233bf215546Sopenharmony_ci batch_bo_reference_read = (1 << 0), 234bf215546Sopenharmony_ci batch_bo_reference_written = (1 << 1), 235bf215546Sopenharmony_ci}; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_cibool 238bf215546Sopenharmony_cid3d12_batch_has_references(struct d3d12_batch *batch, 239bf215546Sopenharmony_ci struct d3d12_bo *bo, 240bf215546Sopenharmony_ci bool want_to_write) 241bf215546Sopenharmony_ci{ 242bf215546Sopenharmony_ci hash_entry *entry = _mesa_hash_table_search(batch->bos, bo); 243bf215546Sopenharmony_ci if (entry == NULL) 244bf215546Sopenharmony_ci return false; 245bf215546Sopenharmony_ci bool resource_was_written = ((batch_bo_reference_state)(size_t)entry->data & batch_bo_reference_written) != 0; 246bf215546Sopenharmony_ci return want_to_write || resource_was_written; 247bf215546Sopenharmony_ci} 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_civoid 250bf215546Sopenharmony_cid3d12_batch_reference_resource(struct d3d12_batch *batch, 251bf215546Sopenharmony_ci struct d3d12_resource *res, 252bf215546Sopenharmony_ci bool write) 253bf215546Sopenharmony_ci{ 254bf215546Sopenharmony_ci hash_entry *entry = _mesa_hash_table_search(batch->bos, res->bo); 255bf215546Sopenharmony_ci if (entry == NULL) { 256bf215546Sopenharmony_ci d3d12_bo_reference(res->bo); 257bf215546Sopenharmony_ci entry = _mesa_hash_table_insert(batch->bos, res->bo, NULL); 258bf215546Sopenharmony_ci } 259bf215546Sopenharmony_ci size_t new_data = write ? batch_bo_reference_written : batch_bo_reference_read; 260bf215546Sopenharmony_ci size_t old_data = (size_t)entry->data; 261bf215546Sopenharmony_ci entry->data = (void*)(old_data | new_data); 262bf215546Sopenharmony_ci} 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_civoid 265bf215546Sopenharmony_cid3d12_batch_reference_sampler_view(struct d3d12_batch *batch, 266bf215546Sopenharmony_ci struct d3d12_sampler_view *sv) 267bf215546Sopenharmony_ci{ 268bf215546Sopenharmony_ci struct set_entry *entry = _mesa_set_search(batch->sampler_views, sv); 269bf215546Sopenharmony_ci if (!entry) { 270bf215546Sopenharmony_ci entry = _mesa_set_add(batch->sampler_views, sv); 271bf215546Sopenharmony_ci pipe_reference(NULL, &sv->base.reference); 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, d3d12_resource(sv->base.texture), false); 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci} 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_civoid 278bf215546Sopenharmony_cid3d12_batch_reference_surface_texture(struct d3d12_batch *batch, 279bf215546Sopenharmony_ci struct d3d12_surface *surf) 280bf215546Sopenharmony_ci{ 281bf215546Sopenharmony_ci d3d12_batch_reference_resource(batch, d3d12_resource(surf->base.texture), true); 282bf215546Sopenharmony_ci} 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_civoid 285bf215546Sopenharmony_cid3d12_batch_reference_object(struct d3d12_batch *batch, 286bf215546Sopenharmony_ci ID3D12Object *object) 287bf215546Sopenharmony_ci{ 288bf215546Sopenharmony_ci struct set_entry *entry = _mesa_set_search(batch->objects, object); 289bf215546Sopenharmony_ci if (!entry) { 290bf215546Sopenharmony_ci entry = _mesa_set_add(batch->objects, object); 291bf215546Sopenharmony_ci object->AddRef(); 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci} 294