1/* 2 * Copyright © Microsoft Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "d3d12_context.h" 25#include "d3d12_descriptor_pool.h" 26#include "d3d12_screen.h" 27 28#include "pipe/p_context.h" 29#include "pipe/p_state.h" 30 31#include "util/list.h" 32#include "util/u_dynarray.h" 33#include "util/u_memory.h" 34 35#include <directx/d3d12.h> 36#include <dxguids/dxguids.h> 37 38struct d3d12_descriptor_pool { 39 ID3D12Device *dev; 40 D3D12_DESCRIPTOR_HEAP_TYPE type; 41 uint32_t num_descriptors; 42 list_head heaps; 43}; 44 45struct d3d12_descriptor_heap { 46 struct d3d12_descriptor_pool *pool; 47 48 D3D12_DESCRIPTOR_HEAP_DESC desc; 49 ID3D12Device *dev; 50 ID3D12DescriptorHeap *heap; 51 uint32_t desc_size; 52 uint64_t cpu_base; 53 uint64_t gpu_base; 54 uint32_t size; 55 uint32_t next; 56 util_dynarray free_list; 57 list_head link; 58}; 59 60struct d3d12_descriptor_heap* 61d3d12_descriptor_heap_new(ID3D12Device *dev, 62 D3D12_DESCRIPTOR_HEAP_TYPE type, 63 D3D12_DESCRIPTOR_HEAP_FLAGS flags, 64 uint32_t num_descriptors) 65{ 66 struct d3d12_descriptor_heap *heap = CALLOC_STRUCT(d3d12_descriptor_heap); 67 68 heap->desc.NumDescriptors = num_descriptors; 69 heap->desc.Type = type; 70 heap->desc.Flags = flags; 71 if (FAILED(dev->CreateDescriptorHeap(&heap->desc, 72 IID_PPV_ARGS(&heap->heap)))) { 73 FREE(heap); 74 return NULL; 75 } 76 77 heap->dev = dev; 78 heap->desc_size = dev->GetDescriptorHandleIncrementSize(type); 79 heap->size = num_descriptors * heap->desc_size; 80 heap->cpu_base = heap->heap->GetCPUDescriptorHandleForHeapStart().ptr; 81 if (flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) 82 heap->gpu_base = heap->heap->GetGPUDescriptorHandleForHeapStart().ptr; 83 util_dynarray_init(&heap->free_list, NULL); 84 85 return heap; 86} 87 88void 89d3d12_descriptor_heap_free(struct d3d12_descriptor_heap *heap) 90{ 91 heap->heap->Release(); 92 util_dynarray_fini(&heap->free_list); 93 FREE(heap); 94} 95 96ID3D12DescriptorHeap* 97d3d12_descriptor_heap_get(struct d3d12_descriptor_heap *heap) 98{ 99 return heap->heap; 100} 101 102static uint32_t 103d3d12_descriptor_heap_is_online(struct d3d12_descriptor_heap *heap) 104{ 105 return (heap->desc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) ? 1 : 0; 106} 107 108static uint32_t 109d3d12_descriptor_heap_can_allocate(struct d3d12_descriptor_heap *heap) 110{ 111 return (heap->free_list.size > 0 || 112 heap->size >= heap->next + heap->desc_size); 113} 114 115uint32_t 116d3d12_descriptor_heap_get_remaining_handles(struct d3d12_descriptor_heap *heap) 117{ 118 return (heap->size - heap->next) / heap->desc_size; 119} 120 121void 122d2d12_descriptor_heap_get_next_handle(struct d3d12_descriptor_heap *heap, 123 struct d3d12_descriptor_handle *handle) 124{ 125 handle->heap = heap; 126 handle->cpu_handle.ptr = heap->cpu_base + heap->next; 127 handle->gpu_handle.ptr = d3d12_descriptor_heap_is_online(heap) ? 128 heap->gpu_base + heap->next : 0; 129} 130 131uint32_t 132d3d12_descriptor_heap_alloc_handle(struct d3d12_descriptor_heap *heap, 133 struct d3d12_descriptor_handle *handle) 134{ 135 uint32_t offset = 0; 136 137 assert(handle != NULL); 138 139 if (heap->free_list.size > 0) { 140 offset = util_dynarray_pop(&heap->free_list, uint32_t); 141 } else if (heap->size >= heap->next + heap->desc_size) { 142 offset = heap->next; 143 heap->next += heap->desc_size; 144 } else { 145 /* Todo: we should add a new descriptor heap to get more handles */ 146 assert(0 && "No handles available in descriptor heap"); 147 return 0; 148 } 149 150 handle->heap = heap; 151 handle->cpu_handle.ptr = heap->cpu_base + offset; 152 handle->gpu_handle.ptr = d3d12_descriptor_heap_is_online(heap) ? 153 heap->gpu_base + offset : 0; 154 155 return 1; 156} 157 158void 159d3d12_descriptor_handle_free(struct d3d12_descriptor_handle *handle) 160{ 161 const uint32_t index = handle->cpu_handle.ptr - handle->heap->cpu_base; 162 if (index + handle->heap->desc_size == handle->heap->next) { 163 handle->heap->next = index; 164 } else { 165 util_dynarray_append(&handle->heap->free_list, uint32_t, index); 166 } 167 168 handle->heap = NULL; 169 handle->cpu_handle.ptr = 0; 170 handle->gpu_handle.ptr = 0; 171} 172 173void 174d3d12_descriptor_heap_append_handles(struct d3d12_descriptor_heap *heap, 175 D3D12_CPU_DESCRIPTOR_HANDLE *handles, 176 unsigned num_handles) 177{ 178 D3D12_CPU_DESCRIPTOR_HANDLE dst; 179 180 assert(heap->next + (num_handles * heap->desc_size) <= heap->size); 181 dst.ptr = heap->cpu_base + heap->next; 182 heap->dev->CopyDescriptors(1, &dst, &num_handles, 183 num_handles, handles, NULL, 184 heap->desc.Type); 185 heap->next += num_handles * heap->desc_size; 186} 187 188void 189d3d12_descriptor_heap_clear(struct d3d12_descriptor_heap *heap) 190{ 191 heap->next = 0; 192 util_dynarray_clear(&heap->free_list); 193} 194 195struct d3d12_descriptor_pool* 196d3d12_descriptor_pool_new(struct d3d12_screen *screen, 197 D3D12_DESCRIPTOR_HEAP_TYPE type, 198 uint32_t num_descriptors) 199{ 200 struct d3d12_descriptor_pool *pool = CALLOC_STRUCT(d3d12_descriptor_pool); 201 if (!pool) 202 return NULL; 203 204 pool->dev = screen->dev; 205 pool->type = type; 206 pool->num_descriptors = num_descriptors; 207 list_inithead(&pool->heaps); 208 209 return pool; 210} 211 212void 213d3d12_descriptor_pool_free(struct d3d12_descriptor_pool *pool) 214{ 215 list_for_each_entry_safe(struct d3d12_descriptor_heap, heap, &pool->heaps, link) { 216 list_del(&heap->link); 217 d3d12_descriptor_heap_free(heap); 218 } 219 FREE(pool); 220} 221 222uint32_t 223d3d12_descriptor_pool_alloc_handle(struct d3d12_descriptor_pool *pool, 224 struct d3d12_descriptor_handle *handle) 225{ 226 struct d3d12_descriptor_heap *valid_heap = NULL; 227 228 list_for_each_entry(struct d3d12_descriptor_heap, heap, &pool->heaps, link) { 229 if (d3d12_descriptor_heap_can_allocate(heap)) { 230 valid_heap = heap; 231 break; 232 } 233 } 234 235 if (!valid_heap) { 236 valid_heap = d3d12_descriptor_heap_new(pool->dev, 237 pool->type, 238 D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 239 pool->num_descriptors); 240 list_addtail(&valid_heap->link, &pool->heaps); 241 } 242 243 return d3d12_descriptor_heap_alloc_handle(valid_heap, handle); 244} 245