/// <summary>
    /// Creates a new <see cref="ID3D12DescriptorHandleAllocator"/> instance with the specified parameters.
    /// </summary>
    /// <param name="device">The <see cref="ID3D12Device"/> instance to use.</param>
    public ID3D12DescriptorHandleAllocator(ID3D12Device *device)
    {
        this.d3D12DescriptorHeap = device->CreateDescriptorHeap(DescriptorsPerHeap, isShaderVisible: true);
        this.d3D12DescriptorHeapNonShaderVisible = device->CreateDescriptorHeap(DescriptorsPerHeap, isShaderVisible: false);
        this.d3D12DescriptorHandlePairs          = GC.AllocateUninitializedArray <ID3D12ResourceDescriptorHandles>((int)DescriptorsPerHeap);
        this.head = 0;
        this.tail = 0;
        this.size = (int)DescriptorsPerHeap;

        D3D12_CPU_DESCRIPTOR_HANDLE d3D12CpuDescriptorHandleStart = this.d3D12DescriptorHeap.Get()->GetCPUDescriptorHandleForHeapStart();
        D3D12_GPU_DESCRIPTOR_HANDLE d3D12GpuDescriptorHandleStart = this.d3D12DescriptorHeap.Get()->GetGPUDescriptorHandleForHeapStart();
        D3D12_CPU_DESCRIPTOR_HANDLE d3D12CpuDescriptorHandleNonShaderVisibleStart = this.d3D12DescriptorHeapNonShaderVisible.Get()->GetCPUDescriptorHandleForHeapStart();
        uint descriptorIncrementSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);

        for (int i = 0; i < this.d3D12DescriptorHandlePairs.Length; i++)
        {
            D3D12_CPU_DESCRIPTOR_HANDLE.InitOffsetted(out D3D12_CPU_DESCRIPTOR_HANDLE d3D12CpuDescriptorHandle, in d3D12CpuDescriptorHandleStart, i, descriptorIncrementSize);
            D3D12_GPU_DESCRIPTOR_HANDLE.InitOffsetted(out D3D12_GPU_DESCRIPTOR_HANDLE d3D12GpuDescriptorHandle, in d3D12GpuDescriptorHandleStart, i, descriptorIncrementSize);
            D3D12_CPU_DESCRIPTOR_HANDLE.InitOffsetted(out D3D12_CPU_DESCRIPTOR_HANDLE d3D12CpuDescriptorHandleNonShaderVisible, in d3D12CpuDescriptorHandleNonShaderVisibleStart, i, descriptorIncrementSize);

            this.d3D12DescriptorHandlePairs[i] = new ID3D12ResourceDescriptorHandles(
                d3D12CpuDescriptorHandle,
                d3D12GpuDescriptorHandle,
                d3D12CpuDescriptorHandleNonShaderVisible);
        }
    }
    /// <summary>
    /// Reads the contents of a <see cref="Buffer{T}"/> instance in a given range and returns an array.
    /// </summary>
    /// <typeparam name="T">The type of items stored on the buffer.</typeparam>
    /// <param name="source">The input <see cref="Buffer{T}"/> instance to read data from.</param>
    /// <param name="offset">The offset to start reading data from.</param>
    /// <param name="count">The number of items to read.</param>
    /// <returns>A <typeparamref name="T"/> array with the contents of the specified range from the current buffer.</returns>
    public static T[] ToArray <T>(this Buffer <T> source, int offset, int count)
        where T : unmanaged
    {
        Guard.IsGreaterThanOrEqualTo(count, 0, nameof(count));

        T[] data = GC.AllocateUninitializedArray <T>(count);

        source.CopyTo(data.AsSpan(), offset);

        return(data);
    }