Home | History | Annotate | Line # | Download | only in d3d12
      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 
     38 struct d3d12_descriptor_pool {
     39    ID3D12Device *dev;
     40    D3D12_DESCRIPTOR_HEAP_TYPE type;
     41    uint32_t num_descriptors;
     42    list_head heaps;
     43 };
     44 
     45 struct 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 
     60 struct d3d12_descriptor_heap*
     61 d3d12_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 
     88 void
     89 d3d12_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 
     96 ID3D12DescriptorHeap*
     97 d3d12_descriptor_heap_get(struct d3d12_descriptor_heap *heap)
     98 {
     99    return heap->heap;
    100 }
    101 
    102 static uint32_t
    103 d3d12_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 
    108 static uint32_t
    109 d3d12_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 
    115 uint32_t
    116 d3d12_descriptor_heap_get_remaining_handles(struct d3d12_descriptor_heap *heap)
    117 {
    118    return (heap->size - heap->next) / heap->desc_size;
    119 }
    120 
    121 void
    122 d2d12_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 
    131 uint32_t
    132 d3d12_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 
    158 void
    159 d3d12_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 
    173 void
    174 d3d12_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 
    188 void
    189 d3d12_descriptor_heap_clear(struct d3d12_descriptor_heap *heap)
    190 {
    191    heap->next = 0;
    192    util_dynarray_clear(&heap->free_list);
    193 }
    194 
    195 struct d3d12_descriptor_pool*
    196 d3d12_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 
    212 void
    213 d3d12_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 
    222 uint32_t
    223 d3d12_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