Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_descriptor_pool.cpp
4570 views
/*1* Copyright © Microsoft Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "d3d12_context.h"24#include "d3d12_descriptor_pool.h"25#include "d3d12_screen.h"2627#include "pipe/p_context.h"28#include "pipe/p_state.h"2930#include "util/list.h"31#include "util/u_dynarray.h"32#include "util/u_memory.h"3334#include <directx/d3d12.h>35#include <dxguids/dxguids.h>3637struct d3d12_descriptor_pool {38ID3D12Device *dev;39D3D12_DESCRIPTOR_HEAP_TYPE type;40uint32_t num_descriptors;41list_head heaps;42};4344struct d3d12_descriptor_heap {45struct d3d12_descriptor_pool *pool;4647D3D12_DESCRIPTOR_HEAP_DESC desc;48ID3D12Device *dev;49ID3D12DescriptorHeap *heap;50uint32_t desc_size;51uint64_t cpu_base;52uint64_t gpu_base;53uint32_t size;54uint32_t next;55util_dynarray free_list;56list_head link;57};5859struct d3d12_descriptor_heap*60d3d12_descriptor_heap_new(ID3D12Device *dev,61D3D12_DESCRIPTOR_HEAP_TYPE type,62D3D12_DESCRIPTOR_HEAP_FLAGS flags,63uint32_t num_descriptors)64{65struct d3d12_descriptor_heap *heap = CALLOC_STRUCT(d3d12_descriptor_heap);6667heap->desc.NumDescriptors = num_descriptors;68heap->desc.Type = type;69heap->desc.Flags = flags;70if (FAILED(dev->CreateDescriptorHeap(&heap->desc,71IID_PPV_ARGS(&heap->heap)))) {72FREE(heap);73return NULL;74}7576heap->dev = dev;77heap->desc_size = dev->GetDescriptorHandleIncrementSize(type);78heap->size = num_descriptors * heap->desc_size;79heap->cpu_base = heap->heap->GetCPUDescriptorHandleForHeapStart().ptr;80if (flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)81heap->gpu_base = heap->heap->GetGPUDescriptorHandleForHeapStart().ptr;82util_dynarray_init(&heap->free_list, NULL);8384return heap;85}8687void88d3d12_descriptor_heap_free(struct d3d12_descriptor_heap *heap)89{90heap->heap->Release();91util_dynarray_fini(&heap->free_list);92FREE(heap);93}9495ID3D12DescriptorHeap*96d3d12_descriptor_heap_get(struct d3d12_descriptor_heap *heap)97{98return heap->heap;99}100101static uint32_t102d3d12_descriptor_heap_is_online(struct d3d12_descriptor_heap *heap)103{104return (heap->desc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) ? 1 : 0;105}106107static uint32_t108d3d12_descriptor_heap_can_allocate(struct d3d12_descriptor_heap *heap)109{110return (heap->free_list.size > 0 ||111heap->size >= heap->next + heap->desc_size);112}113114uint32_t115d3d12_descriptor_heap_get_remaining_handles(struct d3d12_descriptor_heap *heap)116{117return (heap->size - heap->next) / heap->desc_size;118}119120void121d2d12_descriptor_heap_get_next_handle(struct d3d12_descriptor_heap *heap,122struct d3d12_descriptor_handle *handle)123{124handle->heap = heap;125handle->cpu_handle.ptr = heap->cpu_base + heap->next;126handle->gpu_handle.ptr = d3d12_descriptor_heap_is_online(heap) ?127heap->gpu_base + heap->next : 0;128}129130uint32_t131d3d12_descriptor_heap_alloc_handle(struct d3d12_descriptor_heap *heap,132struct d3d12_descriptor_handle *handle)133{134uint32_t offset = 0;135136assert(handle != NULL);137138if (heap->free_list.size > 0) {139offset = util_dynarray_pop(&heap->free_list, uint32_t);140} else if (heap->size >= heap->next + heap->desc_size) {141offset = heap->next;142heap->next += heap->desc_size;143} else {144/* Todo: we should add a new descriptor heap to get more handles */145assert(0 && "No handles available in descriptor heap");146return 0;147}148149handle->heap = heap;150handle->cpu_handle.ptr = heap->cpu_base + offset;151handle->gpu_handle.ptr = d3d12_descriptor_heap_is_online(heap) ?152heap->gpu_base + offset : 0;153154return 1;155}156157void158d3d12_descriptor_handle_free(struct d3d12_descriptor_handle *handle)159{160const uint32_t index = handle->cpu_handle.ptr - handle->heap->cpu_base;161if (index + handle->heap->desc_size == handle->heap->next) {162handle->heap->next = index;163} else {164util_dynarray_append(&handle->heap->free_list, uint32_t, index);165}166167handle->heap = NULL;168handle->cpu_handle.ptr = 0;169handle->gpu_handle.ptr = 0;170}171172void173d3d12_descriptor_heap_append_handles(struct d3d12_descriptor_heap *heap,174D3D12_CPU_DESCRIPTOR_HANDLE *handles,175unsigned num_handles)176{177D3D12_CPU_DESCRIPTOR_HANDLE dst;178179assert(heap->next + (num_handles * heap->desc_size) <= heap->size);180dst.ptr = heap->cpu_base + heap->next;181heap->dev->CopyDescriptors(1, &dst, &num_handles,182num_handles, handles, NULL,183heap->desc.Type);184heap->next += num_handles * heap->desc_size;185}186187void188d3d12_descriptor_heap_clear(struct d3d12_descriptor_heap *heap)189{190heap->next = 0;191util_dynarray_clear(&heap->free_list);192}193194struct d3d12_descriptor_pool*195d3d12_descriptor_pool_new(struct d3d12_screen *screen,196D3D12_DESCRIPTOR_HEAP_TYPE type,197uint32_t num_descriptors)198{199struct d3d12_descriptor_pool *pool = CALLOC_STRUCT(d3d12_descriptor_pool);200if (!pool)201return NULL;202203pool->dev = screen->dev;204pool->type = type;205pool->num_descriptors = num_descriptors;206list_inithead(&pool->heaps);207208return pool;209}210211void212d3d12_descriptor_pool_free(struct d3d12_descriptor_pool *pool)213{214list_for_each_entry_safe(struct d3d12_descriptor_heap, heap, &pool->heaps, link) {215list_del(&heap->link);216d3d12_descriptor_heap_free(heap);217}218FREE(pool);219}220221uint32_t222d3d12_descriptor_pool_alloc_handle(struct d3d12_descriptor_pool *pool,223struct d3d12_descriptor_handle *handle)224{225struct d3d12_descriptor_heap *valid_heap = NULL;226227list_for_each_entry(struct d3d12_descriptor_heap, heap, &pool->heaps, link) {228if (d3d12_descriptor_heap_can_allocate(heap)) {229valid_heap = heap;230break;231}232}233234if (!valid_heap) {235valid_heap = d3d12_descriptor_heap_new(pool->dev,236pool->type,237D3D12_DESCRIPTOR_HEAP_FLAG_NONE,238pool->num_descriptors);239list_addtail(&valid_heap->link, &pool->heaps);240}241242return d3d12_descriptor_heap_alloc_handle(valid_heap, handle);243}244245246