unit DStorage;
{ This unit is automatically generated by Chet:
  https://github.com/neslib/Chet }

{$MINENUMSIZE 4}

interface

uses
  InitCode,
  Utils, LibImport,
  WinAPI.Windows, WinAPI.D3D12;

const
  dstoragelib = 'dstorage.dll';
  dstoragecorelib = 'dstoragecore.dll';

const
  FACILITY_GAME = 2340;
  E_DSTORAGE_ALREADY_RUNNING = $89240001;
  E_DSTORAGE_NOT_RUNNING = $89240002;
  E_DSTORAGE_INVALID_QUEUE_CAPACITY = $89240003;
  E_DSTORAGE_XVD_DEVICE_NOT_SUPPORTED = $89240004;
  E_DSTORAGE_UNSUPPORTED_VOLUME = $89240005;
  E_DSTORAGE_END_OF_FILE = $89240007;
  E_DSTORAGE_REQUEST_TOO_LARGE = $89240008;
  E_DSTORAGE_ACCESS_VIOLATION = $89240009;
  E_DSTORAGE_UNSUPPORTED_FILE = $8924000A;
  E_DSTORAGE_FILE_NOT_OPEN = $8924000B;
  E_DSTORAGE_RESERVED_FIELDS = $8924000C;
  E_DSTORAGE_INVALID_BCPACK_MODE = $8924000D;
  E_DSTORAGE_INVALID_SWIZZLE_MODE = $8924000E;
  E_DSTORAGE_INVALID_DESTINATION_SIZE = $8924000F;
  E_DSTORAGE_QUEUE_CLOSED = $89240010;
  E_DSTORAGE_INVALID_CLUSTER_SIZE = $89240011;
  E_DSTORAGE_TOO_MANY_QUEUES = $89240012;
  E_DSTORAGE_INVALID_QUEUE_PRIORITY = $89240013;
  E_DSTORAGE_TOO_MANY_FILES = $89240014;
  E_DSTORAGE_INDEX_BOUND = $89240015;
  E_DSTORAGE_IO_TIMEOUT = $89240016;
  E_DSTORAGE_INVALID_FILE_HANDLE = $89240017;
  E_DSTORAGE_DEPRECATED_PREVIEW_GDK = $89240018;
  E_DSTORAGE_XVD_NOT_REGISTERED = $89240019;
  E_DSTORAGE_INVALID_FILE_OFFSET = $8924001A;
  E_DSTORAGE_INVALID_SOURCE_TYPE = $8924001B;
  E_DSTORAGE_INVALID_INTERMEDIATE_SIZE = $8924001C;
  E_DSTORAGE_SYSTEM_NOT_SUPPORTED = $8924001D;
  E_DSTORAGE_STAGING_BUFFER_LOCKED = $8924001F;
  E_DSTORAGE_INVALID_STAGING_BUFFER_SIZE = $89240020;
  E_DSTORAGE_STAGING_BUFFER_TOO_SMALL = $89240021;
  E_DSTORAGE_INVALID_FENCE = $89240022;
  E_DSTORAGE_INVALID_STATUS_ARRAY = $89240023;
  E_DSTORAGE_INVALID_MEMORY_QUEUE_PRIORITY = $89240024;
  E_DSTORAGE_DECOMPRESSION_ERROR = $89240030;
  E_DSTORAGE_ZLIB_BAD_HEADER = $89240031;
  E_DSTORAGE_ZLIB_BAD_DATA = $89240032;
  E_DSTORAGE_ZLIB_PARITY_FAIL = $89240033;
  E_DSTORAGE_BCPACK_BAD_HEADER = $89240034;
  E_DSTORAGE_BCPACK_BAD_DATA = $89240035;
  E_DSTORAGE_DECRYPTION_ERROR = $89240036;
  E_DSTORAGE_PASSTHROUGH_ERROR = $89240037;
  E_DSTORAGE_FILE_TOO_FRAGMENTED = $89240038;
  E_DSTORAGE_COMPRESSED_DATA_TOO_LARGE = $89240039;
  E_DSTORAGE_INVALID_DESTINATION_TYPE = $89240040;
  E_DSTORAGE_FILEBUFFERING_REQUIRES_DISABLED_BYPASSIO = $89240041;
  DSTORAGE_SDK_VERSION = 201;
  DSTORAGE_MIN_QUEUE_CAPACITY = $80;
  DSTORAGE_MAX_QUEUE_CAPACITY = $2000;
  DSTORAGE_REQUEST_MAX_NAME = 64;
  DSTORAGE_DISABLE_BUILTIN_CPU_DECOMPRESSION = -1;
  IID_IDStorageCompressionCodec
    : TGUID = '{84EF5121-9B43-4D03-B5C1-CC34606B262D}';

type
  // Forward declarations
  PID3D12Device = ^ID3D12Device;
  PID3D12Resource = Pointer;
  PPID3D12Resource = ^PID3D12Resource;
  PID3D12Fence = Pointer;
  PPID3D12Fence = ^PID3D12Fence;
  PDSTORAGE_QUEUE_DESC = ^DSTORAGE_QUEUE_DESC;
  PDSTORAGE_QUEUE_INFO = ^DSTORAGE_QUEUE_INFO;
  PDSTORAGE_REQUEST_OPTIONS = ^DSTORAGE_REQUEST_OPTIONS;
  PIDStorageFile = ^IDStorageFile;
  PIDStorageFileVtbl = ^IDStorageFileVtbl;
  PDSTORAGE_SOURCE_FILE = ^DSTORAGE_SOURCE_FILE;
  PDSTORAGE_SOURCE_MEMORY = ^DSTORAGE_SOURCE_MEMORY;
  PDSTORAGE_DESTINATION_MEMORY = ^DSTORAGE_DESTINATION_MEMORY;
  PDSTORAGE_DESTINATION_BUFFER = ^DSTORAGE_DESTINATION_BUFFER;
  PDSTORAGE_DESTINATION_TEXTURE_REGION = ^DSTORAGE_DESTINATION_TEXTURE_REGION;
  PDSTORAGE_DESTINATION_MULTIPLE_SUBRESOURCES = ^
    DSTORAGE_DESTINATION_MULTIPLE_SUBRESOURCES;
  PDSTORAGE_DESTINATION_TILES = ^DSTORAGE_DESTINATION_TILES;
  PDSTORAGE_REQUEST = ^DSTORAGE_REQUEST;
  PDSTORAGE_ERROR_PARAMETERS_REQUEST = ^DSTORAGE_ERROR_PARAMETERS_REQUEST;
  PDSTORAGE_ERROR_PARAMETERS_STATUS = ^DSTORAGE_ERROR_PARAMETERS_STATUS;
  PDSTORAGE_ERROR_PARAMETERS_SIGNAL = ^DSTORAGE_ERROR_PARAMETERS_SIGNAL;
  PDSTORAGE_ERROR_PARAMETERS_EVENT = ^DSTORAGE_ERROR_PARAMETERS_EVENT;
  PDSTORAGE_ERROR_FIRST_FAILURE = ^DSTORAGE_ERROR_FIRST_FAILURE;
  PDSTORAGE_ERROR_RECORD = ^DSTORAGE_ERROR_RECORD;
  PDSTORAGE_CUSTOM_DECOMPRESSION_REQUEST = ^
    DSTORAGE_CUSTOM_DECOMPRESSION_REQUEST;
  PDSTORAGE_CUSTOM_DECOMPRESSION_RESULT = ^DSTORAGE_CUSTOM_DECOMPRESSION_RESULT;
  PIDStorageCustomDecompressionQueue = ^IDStorageCustomDecompressionQueue;
  PIDStorageCustomDecompressionQueueVtbl = ^
    IDStorageCustomDecompressionQueueVtbl;
  PIDStorageCustomDecompressionQueue1 = ^IDStorageCustomDecompressionQueue1;
  PIDStorageCustomDecompressionQueue1Vtbl = ^
    IDStorageCustomDecompressionQueue1Vtbl;
  PIDStorageFactory = ^IDStorageFactory;
  PIDStorageFactoryVtbl = ^IDStorageFactoryVtbl;
  PIDStorageStatusArray = ^IDStorageStatusArray;
  PIDStorageStatusArrayVtbl = ^IDStorageStatusArrayVtbl;
  PIDStorageQueue = ^IDStorageQueue;
  PIDStorageQueueVtbl = ^IDStorageQueueVtbl;
  PIDStorageQueue1 = ^IDStorageQueue1;
  PIDStorageQueue1Vtbl = ^IDStorageQueue1Vtbl;
  PIDStorageQueue2 = ^IDStorageQueue2;
  PIDStorageQueue2Vtbl = ^IDStorageQueue2Vtbl;
  PDSTORAGE_CONFIGURATION = ^DSTORAGE_CONFIGURATION;
  PDSTORAGE_CONFIGURATION1 = ^DSTORAGE_CONFIGURATION1;
  PIDStorageCompressionCodec = ^IDStorageCompressionCodec;
  PIDStorageCompressionCodecVtbl = ^IDStorageCompressionCodecVtbl;

  /// <summary>
  /// The priority of a DirectStorage queue.
  /// </summary>
  DSTORAGE_PRIORITY = (DSTORAGE_PRIORITY_LOW = -1, DSTORAGE_PRIORITY_NORMAL = 0,
    DSTORAGE_PRIORITY_HIGH = 1, DSTORAGE_PRIORITY_REALTIME = 2,
    /// <summary>
    /// The following values can be used for iterating over all priority levels.
    /// </summary>
    DSTORAGE_PRIORITY_FIRST = -1,
    /// <summary>
    /// The following values can be used for iterating over all priority levels.
    /// </summary>
    DSTORAGE_PRIORITY_LAST = 2,
    /// <summary>
    /// The following values can be used for iterating over all priority levels.
    /// </summary>
    DSTORAGE_PRIORITY_COUNT = 4);
  PDSTORAGE_PRIORITY = ^DSTORAGE_PRIORITY;

  /// <summary>
  /// The source type of a DirectStorage request.
  /// </summary>
  DSTORAGE_REQUEST_SOURCE_TYPE = (
    /// <summary>
    /// The source of the DirectStorage request is a file.
    /// </summary>
    DSTORAGE_REQUEST_SOURCE_FILE = 0,
    /// <summary>
    /// The source of the DirectStorage request is a block of memory.
    /// </summary>
    DSTORAGE_REQUEST_SOURCE_MEMORY = 1);
  PDSTORAGE_REQUEST_SOURCE_TYPE = ^DSTORAGE_REQUEST_SOURCE_TYPE;

  /// <summary>
  /// The destination type of a DirectStorage request.
  /// </summary>
  DSTORAGE_REQUEST_DESTINATION_TYPE = (
    /// <summary>
    /// The destination of the DirectStorage request is a block of memory.
    /// </summary>
    DSTORAGE_REQUEST_DESTINATION_MEMORY = 0,
    /// <summary>
    /// The destination of the DirectStorage request is an ID3D12Resource
    /// that is a buffer.
    /// </summary>
    DSTORAGE_REQUEST_DESTINATION_BUFFER = 1,
    /// <summary>
    /// The destination of the DirectStorage request is an ID3D12Resource
    /// that is a texture.
    /// </summary>
    DSTORAGE_REQUEST_DESTINATION_TEXTURE_REGION = 2,
    /// <summary>
    /// The destination of the DirectStorage request is an ID3D12Resource
    /// that is a texture that will receive all subresources in a
    /// single request.
    /// </summary>
    DSTORAGE_REQUEST_DESTINATION_MULTIPLE_SUBRESOURCES = 3,
    /// <summary>
    /// The destination of the DirectStorage request is an ID3D12Resource
    /// that is tiled.
    /// </summary>
    DSTORAGE_REQUEST_DESTINATION_TILES = 4);
  PDSTORAGE_REQUEST_DESTINATION_TYPE = ^DSTORAGE_REQUEST_DESTINATION_TYPE;

  /// <summary>
  /// The DSTORAGE_QUEUE_DESC structure contains the properties of a DirectStorage
  /// queue for the queue's creation.
  /// </summary>
  DSTORAGE_QUEUE_DESC = record
    /// <summary>
    /// The source type of requests that this DirectStorage queue can accept.
    /// </summary>
    SourceType: DSTORAGE_REQUEST_SOURCE_TYPE;
    /// <summary>
    /// The maximum number of requests that the queue can hold.
    /// </summary>
    Capacity: UINT16;
    /// <summary>
    /// The priority of the requests in this queue.
    /// </summary>
    Priority: DSTORAGE_PRIORITY;
    /// <summary>
    /// Optional name of the queue. Used for debugging.
    /// </summary>
    Name: PCHAR;
    /// <summary>
    /// Optional device to use for writing to destination resources and
    /// performing GPU decompression. The destination resource's device
    /// must match this device.
    ///
    /// This member may be null. If you specify a null device, then the
    /// destination type must be DSTORAGE_REQUEST_DESTINATION_MEMORY.
    /// </summary>
    Device: PID3D12Device;
  end;

  /// <summary>
  /// The DSTORAGE_QUEUE_INFO structure contains the properties and current state
  /// of a DirectStorage queue.
  /// </summary>
  DSTORAGE_QUEUE_INFO = record
    /// <summary>
    /// The DSTORAGE_QUEUE_DESC structure used for the queue's creation.
    /// </summary>
    Desc: DSTORAGE_QUEUE_DESC;
    /// <summary>
    /// The number of available empty slots. If a queue is empty, then the number
    /// of empty slots equals capacity - 1. The reserved slot is used to
    /// distinguish between empty and full cases.
    /// </summary>
    EmptySlotCount: UINT16;
    /// <summary>
    /// The number of entries that would need to be enqueued in order to trigger
    /// automatic submission.
    /// </summary>
    RequestCountUntilAutoSubmit: UINT16;
  end;

  /// <summary>
  /// The type of compression format used at the decompression stage.
  /// Your application can implement custom decompressors, starting from
  /// DSTORAGE_CUSTOM_COMPRESSION_0.
  /// </summary>
  DSTORAGE_COMPRESSION_FORMAT = (
    /// <summary>
    /// The data is uncompressed.
    /// </summary>
    DSTORAGE_COMPRESSION_FORMAT_NONE = 0,
    /// <summary>
    /// The data is compressed using the built-in GDEFLATE format.
    /// </summary>
    DSTORAGE_COMPRESSION_FORMAT_GDEFLATE = 1,
    /// <summary>
    /// The data is stored in an application-defined custom format. The
    /// application must use IDStorageCustomDecompressionQueue to implement
    /// custom decompression.  Additional custom compression formats can be
    /// used, for example `(DSTORAGE_CUSTOM_COMPRESSION_0 + 1)`.
    DSTORAGE_CUSTOM_COMPRESSION_0 = -128);
  PDSTORAGE_COMPRESSION_FORMAT = ^DSTORAGE_COMPRESSION_FORMAT;

  /// <summary>
  /// Options for a DirectStorage request.
  /// </summary>
  DSTORAGE_REQUEST_OPTIONS = record
  private
    Data0: Cardinal;
    function GetData0Value(const AIndex: Integer): Cardinal;
    procedure SetData0Value(const AIndex: Integer; const AValue: Cardinal);
  public
    /// <summary>
    /// DSTORAGE_COMPRESSION_FORMAT indicating how the data is compressed.
    /// </summary>
    property CompressionFormat: Cardinal index $8 read GetData0Value
      write SetData0Value; // 8 bits at offset 0 in Data0

  var
    /// <summary>
    /// Reserved fields. Must be 0.
    /// </summary>
    Reserved1: array [0 .. 6] of UINT8;
    /// <summary>
    /// DSTORAGE_REQUEST_SOURCE_TYPE enum value indicating whether the
    /// source of the request is a file or a block of memory.
    /// </summary>
    property SourceType: Cardinal index $00000801 read GetData0Value
      write SetData0Value; // 1 bits at offset 8 in Data0
    /// <summary>
    /// DSTORAGE_REQUEST_DESTINATION_TYPE enum value indicating the
    /// destination of the request. Block of memory, resource.
    /// </summary>
    property DestinationType: Cardinal index $00000907 read GetData0Value
      write SetData0Value; // 7 bits at offset 9 in Data0
    /// <summary>
    /// Reserved fields. Must be 0.
    /// </summary>
    property Reserved: Cardinal index $00001030 read GetData0Value
      write SetData0Value; // 48 bits at offset 16 in Data0
  end;

  /// <summary>
  /// Flags controlling DirectStorage debug layer.
  /// </summary>
  DSTORAGE_DEBUG = (
    /// <summary>
    /// DirectStorage debug layer is disabled.
    /// </summary>
    DSTORAGE_DEBUG_NONE = 0,
    /// <summary>
    /// Print error information to a debugger.
    /// </summary>
    DSTORAGE_DEBUG_SHOW_ERRORS = 1,
    /// <summary>
    /// Trigger a debug break each time an error is detected.
    /// </summary>
    DSTORAGE_DEBUG_BREAK_ON_ERROR = 2,
    /// <summary>
    /// Include object names in ETW events.
    /// </summary>
    DSTORAGE_DEBUG_RECORD_OBJECT_NAMES = 4);
  PDSTORAGE_DEBUG = ^DSTORAGE_DEBUG;

  /// <summary>
  /// Represents a file to be accessed by DirectStorage.
  /// </summary>
  IDStorageFile = record
    lpVtbl: PIDStorageFileVtbl;
  end;

  IDStorageFileVtbl = record
  end;

  /// <summary>
  /// Describes a source for a request with SourceType
  /// DSTORAGE_REQUEST_SOURCE_FILE.
  /// </summary>
  DSTORAGE_SOURCE_FILE = record
    /// <summary>
    /// The file to perform this read request from.
    /// </summary>
    Source: PIDStorageFile;
    /// <summary>
    /// The offset, in bytes, in the file to start the read request at.
    /// </summary>
    Offset: UINT64;
    /// <summary>
    /// Number of bytes to read from the file.
    /// </summary>
    Size: UINT32;
  end;

  /// <summary>
  /// Describes the source for a request with SourceType
  /// DSTORAGE_REQUEST_SOURCE_MEMORY.
  /// </summary>
  DSTORAGE_SOURCE_MEMORY = record
    /// <summary>
    /// Address of the source buffer to be read from.
    /// </summary>
    Source: Pointer;
    /// <summary>
    /// Number of bytes to read from the source buffer.
    /// </summary>
    Size: UINT32;
  end;

  /// <summary>
  /// Describes the destination for a request with DestinationType
  /// DSTORAGE_REQUEST_DESTINATION_MEMORY.
  /// </summary>
  DSTORAGE_DESTINATION_MEMORY = record
    /// <summary>
    /// Address of the buffer to receive the final result of this request.
    /// </summary>
    Buffer: Pointer;
    /// <summary>
    /// Number of bytes to write to the destination buffer.
    /// </summary>
    Size: UINT32;
  end;

  /// <summary>
  /// Describes the destination for a request with DestinationType
  /// DSTORAGE_REQUEST_DESTINATION_BUFFER.
  /// </summary>
  DSTORAGE_DESTINATION_BUFFER = record
    /// <summary>
    /// Address of the resource to receive the final result of this request.
    /// </summary>
    Resource: PID3D12Resource;
    /// <summary>
    /// The offset, in bytes, in the buffer resource to write into.
    /// </summary>
    Offset: UINT64;
    /// <summary>
    /// Number of bytes to write to the destination buffer.
    /// </summary>
    Size: UINT32;
  end;

  /// <summary>
  /// Describes the destination for a request with DestinationType
  /// DSTORAGE_REQUEST_DESTINATION_TEXTURE_REGION.
  /// </summary>
  DSTORAGE_DESTINATION_TEXTURE_REGION = record
    /// <summary>
    /// Address of the resource to receive the final result of this request.
    /// </summary>
    Resource: PID3D12Resource;
    /// <summary>
    /// Describes the destination texture copy location. The subresource
    /// referred to must be in the D3D12_RESOURCE_STATE_COMMON state.
    /// </summary>
    SubresourceIndex: UINT;
    /// <summary>
    /// Coordinates and size of the destination region to copy, in pixels.
    /// </summary>
    Region: D3D12_BOX;
  end;

  /// <summary>
  /// Describes the destination for a request with DestinationType
  /// DSTORAGE_REQUEST_DESTINATION_MULTIPLE_SUBRESOURCES.
  /// </summary>
  DSTORAGE_DESTINATION_MULTIPLE_SUBRESOURCES = record
    /// <summary>
    /// Address of the resource to receive the final result of this request. The
    /// source is expected to contain full data for all subresources, starting
    /// from FirstSubresource.
    /// </summary>
    Resource: PID3D12Resource;
    /// <summary>
    /// Describes the first subresource of the destination texture copy
    /// location. The subresource referred to must be in the
    /// D3D12_RESOURCE_STATE_COMMON state.
    /// </summary>
    FirstSubresource: UINT;
  end;

  /// <summary>
  /// Describes the destination for a request with DestinationType
  /// DSTORAGE_REQUEST_DESTINATION_TILES.
  /// </summary>
  DSTORAGE_DESTINATION_TILES = record
    /// <summary>
    /// Address of the resource to receive the final result of this request. The
    /// source buffer is expected to contain data arranged as if it were the
    /// source to a CopyTiles call with these parameters.
    /// </summary>
    Resource: PID3D12Resource;
    /// <summary>
    /// The starting coordinates of the tiled region.
    /// </summary>
    TiledRegionStartCoordinate: D3D12_TILED_RESOURCE_COORDINATE;
    /// <summary>
    /// The size of the tiled region.
    /// </summary>
    TileRegionSize: D3D12_TILE_REGION_SIZE;
  end;

  /// <summary>
  /// Describes the source specified for a DirectStorage request. For a request,
  /// the value of `request.Options.SourceType` determines which of these union
  /// fields is active.
  /// </summary>
  DSTORAGE_SOURCE = record
    case Integer of
      0:
        (Memory: DSTORAGE_SOURCE_MEMORY);
      1:
        (&File: DSTORAGE_SOURCE_FILE);
  end;

  /// <summary>
  /// Describes the destination for a DirectStorage request.  For a request, the
  /// value of `request.Options.DestinationType` determines which of these union
  /// fields is active.
  /// </summary>
  DSTORAGE_DESTINATION = record
    case Integer of
      0:
        (Memory: DSTORAGE_DESTINATION_MEMORY);
      1:
        (Buffer: DSTORAGE_DESTINATION_BUFFER);
      2:
        (Texture: DSTORAGE_DESTINATION_TEXTURE_REGION);
      3:
        (MultipleSubresources: DSTORAGE_DESTINATION_MULTIPLE_SUBRESOURCES);
      4:
        (Tiles: DSTORAGE_DESTINATION_TILES);
  end;

  /// <summary>
  /// Represents a DirectStorage request.
  /// </summary>
  DSTORAGE_REQUEST = record
    /// <summary>
    /// Combination of decompression and other options for this request.
    /// </summary>
    Options: DSTORAGE_REQUEST_OPTIONS;
    /// <summary>
    /// The source for this request.
    /// </summary>
    Source: DSTORAGE_SOURCE;
    /// <summary>
    /// The destination for this request.
    /// </summary>
    Destination: DSTORAGE_DESTINATION;
    /// <summary>
    /// The uncompressed size in bytes for the destination for this request.
    /// If the request is not compressed, then this can be left as 0.
    ///
    /// For compressed data, if the destination is memory, then the uncompressed size must
    /// exactly equal the destination size. For other destination types, the uncompressed
    /// size may be greater than the destination size.
    ///
    /// If the destination is to memory or buffer, then the destination size should
    /// be specified in the corresponding struct (for example, DSTORAGE_DESTINATION_MEMORY).
    /// For textures, it's the value of pTotalBytes returned by GetCopyableFootprints.
    /// For tiles, it's 64k * number of tiles.
    /// </summary>
    UncompressedSize: UINT32;
    /// <summary>
    /// An arbitrary UINT64 number used for cancellation matching.
    /// </summary>
    CancellationTag: UINT64;
    /// <summary>
    /// Optional name of the request. Used for debugging. If specified, the
    /// string should be accessible until the request completes.
    /// </summary>
    Name: PCHAR;
  end;

  /// <summary>
  /// The type of command that failed, as reported by
  /// DSTORAGE_ERROR_FIRST_FAILURE.
  /// </summary>
  DSTORAGE_COMMAND_TYPE = (DSTORAGE_COMMAND_TYPE_NONE = -1,
    DSTORAGE_COMMAND_TYPE_REQUEST = 0, DSTORAGE_COMMAND_TYPE_STATUS = 1,
    DSTORAGE_COMMAND_TYPE_SIGNAL = 2, DSTORAGE_COMMAND_TYPE_EVENT = 3);
  PDSTORAGE_COMMAND_TYPE = ^DSTORAGE_COMMAND_TYPE;

  /// <summary>
  /// The parameters passed to the EnqueueRequest call, and optional
  /// filename if the request is for a file source.
  /// </summary>
  DSTORAGE_ERROR_PARAMETERS_REQUEST = record
    /// <summary>
    /// For a file source request, the name of the file the request was
    /// targeted to.
    /// </summary>
    Filename: array [0 .. 259] of WCHAR;
    /// <summary>
    /// The name of the request if one was specified.
    /// </summary>
    RequestName: array [0 .. 63] of CHAR;
    /// <summary>
    /// The parameters passed to the EnqueueRequest call.
    /// </summary>
    Request: DSTORAGE_REQUEST;
  end;

  /// <summary>
  /// The parameters passed to the EnqueueStatus call.
  /// </summary>
  DSTORAGE_ERROR_PARAMETERS_STATUS = record
    StatusArray: PIDStorageStatusArray;
    Index: UINT32;
  end;

  /// <summary>
  /// The parameters passed to the EnqueueSignal call.
  /// </summary>
  DSTORAGE_ERROR_PARAMETERS_SIGNAL = record
    Fence: PID3D12Fence;
    Value: UINT64;
  end;

  /// <summary>
  /// The parameters passed to the EnqueueSetEvent call.
  /// </summary>
  DSTORAGE_ERROR_PARAMETERS_EVENT = record
    Handle: THandle;
  end;

  /// <summary>
  /// The parameters passed to the Enqueue call.
  /// </summary>
  P_anonymous_type_1 = ^_anonymous_type_1;

  _anonymous_type_1 = record
    case Integer of
      0:
        (Request: DSTORAGE_ERROR_PARAMETERS_REQUEST);
      1:
        (Status: DSTORAGE_ERROR_PARAMETERS_STATUS);
      2:
        (Signal: DSTORAGE_ERROR_PARAMETERS_SIGNAL);
      3:
        (Event: DSTORAGE_ERROR_PARAMETERS_EVENT);
  end;

  /// <summary>
  /// Structure to receive the detailed record of the first failed DirectStorage
  /// request.
  /// </summary>
  DSTORAGE_ERROR_FIRST_FAILURE = record
    /// <summary>
    /// The HRESULT code of the failure.
    /// </summary>
    HResult: HResult;
    /// <summary>
    /// Type of the Enqueue command that caused the failure.
    /// </summary>
    CommandType: DSTORAGE_COMMAND_TYPE;
    f3: _anonymous_type_1;
  end;

  /// <summary>
  /// Structure to receive the detailed record of a failed DirectStorage request.
  /// </summary>
  DSTORAGE_ERROR_RECORD = record
    /// <summary>
    /// The number of failed requests in the queue since the last
    /// RetrieveErrorRecord call.
    /// </summary>
    FailureCount: UINT32;
    /// <summary>
    /// Detailed record about the first failed command in the enqueue order.
    /// </summary>
    FirstFailure: DSTORAGE_ERROR_FIRST_FAILURE;
  end;

  /// <summary>
  /// Defines common staging buffer sizes.
  /// </summary>
  DSTORAGE_STAGING_BUFFER_SIZE = (
    /// <summary>
    /// There is no staging buffer.  Use this value to force DirectStorage to
    /// deallocate any memory it has allocated for staging buffers.
    /// <summary>
    DSTORAGE_STAGING_BUFFER_SIZE_0 = 0,
    /// <summary>
    /// The default staging buffer size of 32MB.
    /// </summary>
    DSTORAGE_STAGING_BUFFER_SIZE_32MB = 33554432);
  PDSTORAGE_STAGING_BUFFER_SIZE = ^DSTORAGE_STAGING_BUFFER_SIZE;

  /// <summary>
  /// Flags used with GetRequests1 when requesting
  /// items from the custom decompression queue.
  /// </summary>
  DSTORAGE_GET_REQUEST_FLAGS = (
    /// <summary>
    /// Request entries that use custom decompression formats
    /// >= DSTORAGE_CUSTOM_COMPRESSION_0.
    /// </summary>
    DSTORAGE_GET_REQUEST_FLAG_SELECT_CUSTOM = 1,
    /// <summary>
    /// Request entries that use built in compression formats
    /// that DirectStorage understands.
    /// </summary>
    DSTORAGE_GET_REQUEST_FLAG_SELECT_BUILTIN = 2,
    /// <summary>
    /// Request all entries. This includes custom decompression and
    /// built-in compressed formats.
    /// </summary>
    DSTORAGE_GET_REQUEST_FLAG_SELECT_ALL = 3);
  PDSTORAGE_GET_REQUEST_FLAGS = ^DSTORAGE_GET_REQUEST_FLAGS;

  /// <summary>
  /// Specifies information about a custom decompression request.
  /// </summary>
  DSTORAGE_CUSTOM_DECOMPRESSION_FLAGS = (
    /// <summary>
    /// No additional information.
    /// </summary>
    DSTORAGE_CUSTOM_DECOMPRESSION_FLAG_NONE = 0,
    /// <summary>
    /// The uncompressed destination buffer is located in an
    /// upload heap, and is marked as WRITE_COMBINED.
    /// </summary>
    DSTORAGE_CUSTOM_DECOMPRESSION_FLAG_DEST_IN_UPLOAD_HEAP = 1);
  PDSTORAGE_CUSTOM_DECOMPRESSION_FLAGS = ^DSTORAGE_CUSTOM_DECOMPRESSION_FLAGS;

  /// <summary>
  /// A custom decompression request. Use IDStorageCustomDecompressionQueue to
  /// retrieve these requests.
  /// </summary>
  DSTORAGE_CUSTOM_DECOMPRESSION_REQUEST = record
    /// <summary>
    /// An identifier provided by DirectStorage. This should be used to
    /// identify the request in DSTORAGE_CUSTOM_DECOMPRESSION_RESULT. This
    /// identifier is unique among uncompleted requests, but may be reused after
    /// a request has completed.
    /// </summary>
    Id: UINT64;
    /// <summary>
    /// The compression format.  This will be >= DSTORAGE_CUSTOM_COMPRESSION_0
    /// if DSTORAGE_CUSTOM_DECOMPRESSION_CUSTOMONLY is used to retrieve requests.
    /// </summary>
    CompressionFormat: DSTORAGE_COMPRESSION_FORMAT;
    /// <summary>
    /// Reserved for future use.
    /// </summary>
    Reserved: array [0 .. 2] of UINT8;
    /// <summary>
    /// Flags containing additional details about the decompression request.
    /// </summary>
    Flags: DSTORAGE_CUSTOM_DECOMPRESSION_FLAGS;
    /// <summary>
    /// The size of SrcBuffer in bytes.
    /// </summary>
    SrcSize: UINT64;
    /// <summary>
    /// The compressed source buffer.
    /// </summary>
    SrcBuffer: Pointer;
    /// <summary>
    /// The size of DstBuffer in bytes.
    /// </summary>
    DstSize: UINT64;
    /// <summary>
    /// The uncompressed destination buffer. SrcBuffer should be decompressed to
    /// DstBuffer.
    /// </summary>
    DstBuffer: Pointer;
  end;

  /// <summary>
  /// The result of a custom decompression operation. If the request failed, then
  /// the Result code is passed back through the standard DirectStorage
  /// status/error reporting mechanism.
  /// </summary>
  DSTORAGE_CUSTOM_DECOMPRESSION_RESULT = record
    /// <summary>
    /// The identifier for the request, from DSTORAGE_CUSTOM_DECOMPRESSION_REQUEST.
    /// </summary>
    Id: UINT64;
    /// <summary>
    /// The result of this decompression. S_OK indicates success.
    /// </summary>
    Result: HResult;
  end;

  /// <summary>
  /// A queue of decompression requests. This can be obtained using QueryInterface
  /// against the factory. Your application must take requests from this queue,
  /// decompress them, and report that decompression is complete. That allows an
  /// application to provide its own custom decompression.
  /// </summary>
  IDStorageCustomDecompressionQueue = record
    lpVtbl: PIDStorageCustomDecompressionQueueVtbl;
  end;

  IDStorageCustomDecompressionQueueVtbl = record
  end;

  /// <summary>
  /// An extension of IDStorageCustomDecompressionQueue that allows an
  /// application to retrieve specific types of custom decompression
  /// requests from the decompression queue.
  /// </summary>
  IDStorageCustomDecompressionQueue1 = record
    lpVtbl: PIDStorageCustomDecompressionQueue1Vtbl;
  end;

  IDStorageCustomDecompressionQueue1Vtbl = record
  end;

  /// <summary>
  /// Represents the static DirectStorage object used to create DirectStorage
  /// queues, open files for DirectStorage access, and other global operations.
  /// </summary>
  IDStorageFactory = record
    lpVtbl: PIDStorageFactoryVtbl;
  end;

  IDStorageFactoryVtbl = record
  end;

  /// <summary>
  /// Represents an array of status entries to receive completion results for the
  /// read requests before them.
  /// </summary>
  /// <remarks>
  /// A status entry receives completion status for all the requests in the
  /// DStorageQueue between where it is enqueued and the previously enqueued
  /// status entry. Only when all requests enqueued before the status entry
  /// complete (that is, IsComplete for the entry returns true), the status entry
  /// can be enqueued again.
  /// </remarks>
  IDStorageStatusArray = record
    lpVtbl: PIDStorageStatusArrayVtbl;
  end;

  IDStorageStatusArrayVtbl = record
  end;

  /// <summary>
  /// Represents a DirectStorage queue to perform read operations.
  /// </summary>
  IDStorageQueue = record
    lpVtbl: PIDStorageQueueVtbl;
  end;

  IDStorageQueueVtbl = record
  end;

  /// <summary>
  /// Represents a DirectStorage queue to perform read operations.
  /// </summary>
  IDStorageQueue1 = record
    lpVtbl: PIDStorageQueue1Vtbl;
  end;

  IDStorageQueue1Vtbl = record
  end;

  /// <summary>
  /// Flags returned with GetCompressionSupport that describe the features
  /// used by the runtime to decompress content.
  /// </summary>
  DSTORAGE_COMPRESSION_SUPPORT = (
    /// <summary>
    /// None
    /// </summary>
    DSTORAGE_COMPRESSION_SUPPORT_NONE = 0,
    /// <summary>
    /// Optimized driver support for GPU decompression will be used.
    /// </summary>
    DSTORAGE_COMPRESSION_SUPPORT_GPU_OPTIMIZED = 1,
    /// <summary>
    /// Built-in GPU decompression fallback shader will be used.  This can occur if
    /// optimized driver support is not available and the D3D12 device used for this
    /// DirectStorage queue supports the required capabilities.
    /// </summary>
    DSTORAGE_COMPRESSION_SUPPORT_GPU_FALLBACK = 2,
    /// <summary>
    /// CPU fallback implementation will be used.
    /// This can occur if:
    /// * Optimized driver support and built-in GPU decompression is not available.
    /// * GPU decompression support has been explicitly disabled using
    /// DSTORAGE_CONFIGURATION.
    /// * DirectStorage runtime encounters a failure during initialization of its
    /// GPU decompression system.
    /// </summary>
    DSTORAGE_COMPRESSION_SUPPORT_CPU_FALLBACK = 4,
    /// <summary>
    /// Executes work on a compute queue.
    /// </summary>
    DSTORAGE_COMPRESSION_SUPPORT_USES_COMPUTE_QUEUE = 8,
    /// <summary>
    /// Executes work on a copy queue.
    /// </summary>
    DSTORAGE_COMPRESSION_SUPPORT_USES_COPY_QUEUE = 16);
  PDSTORAGE_COMPRESSION_SUPPORT = ^DSTORAGE_COMPRESSION_SUPPORT;

  /// <summary>
  /// Represents a DirectStorage queue to perform read operations.
  /// </summary>
  IDStorageQueue2 = record
    lpVtbl: PIDStorageQueue2Vtbl;
  end;

  IDStorageQueue2Vtbl = record
  end;

  /// <summary>
  /// DirectStorage Configuration. Zero initializing this will result in the default values.
  /// </summary>
  DSTORAGE_CONFIGURATION = record
    /// <summary>
    /// Sets the number of threads to use for submitting IO operations.
    /// Specifying 0 means use the system's best guess at a good value.
    /// Default == 0.
    /// </summary>
    NumSubmitThreads: UINT32;
    /// <summary>
    /// Sets the number of threads to be used by the DirectStorage runtime to
    /// decompress data using the CPU for built-in compressed formats
    /// that cannot be decompressed using the GPU.
    ///
    /// Specifying 0 means to use the system's best guess at a good value.
    ///
    /// Specifying DSTORAGE_DISABLE_BUILTIN_CPU_DECOMPRESSION means no decompression
    /// threads will be created and the title is fully responsible for checking
    /// the custom decompression queue and pulling off ALL entries to decompress.
    ///
    /// Default == 0.
    /// </summary>
    NumBuiltInCpuDecompressionThreads: INT32;
    /// <summary>
    /// Forces the use of the IO mapping layer, even when running on an
    /// operation system that doesn't require it.  This may be useful during
    /// development, but should be set to the FALSE for release. Default=FALSE.
    /// </summary>
    ForceMappingLayer: BOOL;
    /// <summary>
    /// Disables the use of the bypass IO optimization, even if it is available.
    /// This might be useful during development, but should be set to FALSE
    /// for release unless ForceFileBuffering is set to TRUE.
    /// Default == FALSE.
    /// </summary>
    DisableBypassIO: BOOL;
    /// <summary>
    /// Disables the reporting of telemetry data when set to TRUE.
    /// Telemetry data is enabled by default in the DirectStorage runtime.
    /// Default == FALSE.
    /// </summary>
    DisableTelemetry: BOOL;
    /// <summary>
    /// Disables the use of a decompression metacommand, even if one
    /// is available. This will force the runtime to use the built-in GPU decompression
    /// fallback shader.
    /// This may be useful during development, but should be set to the FALSE
    /// for release. Default == FALSE.
    /// </summary>
    DisableGpuDecompressionMetacommand: BOOL;
    /// <summary>
    /// Disables the use of GPU based decompression, even if it is available.
    /// This will force the runtime to use the CPU. Default=FALSE.
    /// </summary>
    DisableGpuDecompression: BOOL;
  end;

  /// <summary>
  /// DirectStorage Configuration. Zero initializing this will result in the default values.
  /// </summary>
  DSTORAGE_CONFIGURATION1 = record
    /// <summary>
    /// Sets the number of threads to use for submitting IO operations.
    /// Specifying 0 means use the system's best guess at a good value.
    /// Default == 0.
    /// </summary>
    NumSubmitThreads: UINT32;
    /// <summary>
    /// Sets the number of threads to be used by the DirectStorage runtime to
    /// decompress data using the CPU for built-in compressed formats
    /// that cannot be decompressed using the GPU.
    ///
    /// Specifying 0 means to use the system's best guess at a good value.
    ///
    /// Specifying DSTORAGE_DISABLE_BUILTIN_CPU_DECOMPRESSION means no decompression
    /// threads will be created and the title is fully responsible for checking
    /// the custom decompression queue and pulling off ALL entries to decompress.
    ///
    /// Default == 0.
    /// </summary>
    NumBuiltInCpuDecompressionThreads: INT32;
    /// <summary>
    /// Forces the use of the IO mapping layer, even when running on an
    /// operation system that doesn't require it.  This may be useful during
    /// development, but should be set to the FALSE for release. Default=FALSE.
    /// </summary>
    ForceMappingLayer: BOOL;
    /// <summary>
    /// Disables the use of the bypass IO optimization, even if it is available.
    /// This might be useful during development, but should be set to FALSE
    /// for release unless ForceFileBuffering is set to TRUE.
    /// Default == FALSE.
    /// </summary>
    DisableBypassIO: BOOL;
    /// <summary>
    /// Disables the reporting of telemetry data when set to TRUE.
    /// Telemetry data is enabled by default in the DirectStorage runtime.
    /// Default == FALSE.
    /// </summary>
    DisableTelemetry: BOOL;
    /// <summary>
    /// Disables the use of a decompression metacommand, even if one
    /// is available. This will force the runtime to use the built-in GPU decompression
    /// fallback shader.
    /// This may be useful during development, but should be set to the FALSE
    /// for release. Default == FALSE.
    /// </summary>
    DisableGpuDecompressionMetacommand: BOOL;
    /// <summary>
    /// Disables the use of GPU based decompression, even if it is available.
    /// This will force the runtime to use the CPU. Default=FALSE.
    /// </summary>
    DisableGpuDecompression: BOOL;
    /// <summary>
    /// Forces the use of the built-in file caching behaviors supported
    /// within the Windows operating system by not setting
    /// FILE_FLAG_NO_BUFFERING when opening files.
    ///
    /// DisableBypassIO must be set to TRUE when using this option or
    /// E_DSTORAGE_FILEBUFFERING_REQUIRES_DISABLED_BYPASSIO will be returned.
    ///
    /// It is the title's responsibility to know when to use this setting.
    /// This feature should ONLY be enabled for slower HDD drives that will
    /// benefit from the OS file buffering features.
    ///
    /// WARNING: Enabling file buffering on high speed drives may reduce
    /// overall performance when reading from that drive because BypassIO
    /// is also disabled. Default=FALSE.
    /// </summary>
    ForceFileBuffering: BOOL;
  end;

  /// <summary>
  /// Settings controlling DirectStorage compression codec behavior.
  /// </summary>
  DSTORAGE_COMPRESSION = (
    /// <summary>
    /// Compress data at a fast rate which may not yield the best
    /// compression ratio.
    /// </summary>
    DSTORAGE_COMPRESSION_FASTEST = -1,
    /// <summary>
    /// Compress data at an average rate with a good compression ratio.
    /// </summary>
    DSTORAGE_COMPRESSION_DEFAULT = 0,
    /// <summary>
    /// Compress data at slow rate with the best compression ratio.
    /// </summary>
    DSTORAGE_COMPRESSION_BEST_RATIO = 1);
  PDSTORAGE_COMPRESSION = ^DSTORAGE_COMPRESSION;

  /// <summary>
  /// Represents the DirectStorage object for compressing and decompressing the buffers.
  ///
  /// Use DStorageCreateCompressionCodec to get an instance of this.
  ///
  /// </summary>
  IDStorageCompressionCodec = interface(IUnknown)
    ['{84EF5121-9B43-4D03-B5C1-CC34606B262D}']
    /// <summary>
    /// Compresses a buffer of data using a known compression format at the specifed
    /// compression level.
    /// </summary>
    /// <param name="uncompressedData">Points to a buffer containing uncompressed data.</param>
    /// <param name="uncompressedDataSize">Size, in bytes, of the uncompressed data buffer.</param>
    /// <param name="compressionSetting">Specifies the compression settings to use.</param>
    /// <param name="compressedBuffer">Points to a buffer where compressed data will be
    /// written.</param>
    /// <param name="compressedBufferSize">Size, in bytes, of the buffer which will receive
    /// the compressed data</param>
    /// <param name="compressedDataSize">Size, in bytes, of the actual size written to compressedBuffer</param>
    /// <returns>Standard HRESULT error code.</returns>
    function CompressBuffer(const uncompressedData: Pointer;
      uncompressedDataSize: size_t; compressionSetting: DSTORAGE_COMPRESSION;
      compressedBuffer: Pointer; compressedBufferSize: size_t;
      compressedDataSize: psize_t): HResult stdcall;

    /// <summary>
    /// Decompresses data previously compressed using CompressBuffer.
    /// </summary>
    /// <param name="compressedData">Points to a buffer containing compressed data.</param>
    /// <param name="compressedDataSize">Size, in bytes, of the compressed data buffer.</param>
    /// <param name="uncompressedBuffer">Points to a buffer where uncompressed data will be
    /// written.</param>
    /// <param name="uncompressedBufferSize">Size, in bytes, of the buffer which will receive
    /// the uncompressed data</param>
    /// <param name="uncompressedDataSize">Size, in bytes, of the actual size written to uncompressedBuffer</param>
    /// <returns>Standard HRESULT error code.</returns>
    function DecompressBuffer(compressedData: Pointer;
      compressedDataSize: size_t; uncompressedBuffer: Pointer;
      uncompressedBufferSize: size_t; uncompressedDataSize: psize_t)
      : HResult stdcall;

    /// <summary>
    /// Returns an upper bound estimated size in bytes required to compress the specified data size.
    /// </summary>
    /// <param name="uncompressedDataSize">Size, in bytes, of the data to be compressed</param>
    function CompressBufferBound(uncompressedDataSize: size_t): size_t stdcall;
  end;

  IDStorageCompressionCodecVtbl = record
  end;

var
  DStorageSetConfiguration: function(configuration: PDSTORAGE_CONFIGURATION)
    : HResult stdcall = nil;
  DStorageSetConfiguration1: function(configuration: PDSTORAGE_CONFIGURATION1)
    : HResult stdcall = nil;
  DStorageGetFactory: function(const riid: TGUID; out ppv)
    : HResult stdcall = nil;
  DStorageCreateCompressionCodec: function(format: DSTORAGE_COMPRESSION_FORMAT;
    numThreads: UINT32; const riid: TGUID; out ppv): HResult stdcall = nil;
  DLLLoaded: Boolean = False;

implementation

{ DSTORAGE_REQUEST_OPTIONS }

function DSTORAGE_REQUEST_OPTIONS.GetData0Value(const AIndex: Integer)
  : Cardinal;
var
  BitCount, Offset, Mask: Cardinal;
begin
  BitCount := AIndex and $FF;
  Offset := AIndex shr 8;
  Mask := ((1 shl BitCount) - 1);
  Result := (Data0 shr Offset) and Mask;
end;

procedure DSTORAGE_REQUEST_OPTIONS.SetData0Value(const AIndex: Integer;
  const AValue: Cardinal);
var
  BitCount, Offset, Mask: Cardinal;
begin
  BitCount := AIndex and $FF;
  Offset := AIndex shr 8;
  Mask := ((1 shl BitCount) - 1);
  Data0 := (Data0 and (not(Mask shl Offset))) or (AValue shl Offset);
end;

var
  Lib1, Lib2: TLibImport;

procedure Init;
begin
  Lib1 := TLibImport.Create;
  Lib1.LoadLib(ExpandPath(PluginsPath + dstoragelib, True));
  Lib2 := TLibImport.Create;
  Lib2.LoadLib(ExpandPath(PluginsPath + dstoragecorelib, True));
  if Lib1.Loaded and Lib2.Loaded then
  begin
    @DStorageSetConfiguration := Lib1.GetProcAddr('DStorageSetConfiguration');
    @DStorageSetConfiguration1 := Lib1.GetProcAddr('DStorageSetConfiguration1');
    @DStorageGetFactory := Lib1.GetProcAddr('DStorageGetFactory');
    @DStorageCreateCompressionCodec :=
      Lib1.GetProcAddr('DStorageCreateCompressionCodec');
    DLLLoaded := Assigned(DStorageCreateCompressionCodec);
  end;
end;

procedure Deinit;
begin
  Lib1.Free;
  Lib2.Free;
end;

initialization

Init;

finalization

Deinit;

end.
