import type { AnyData } from '../../data/dataTypes.ts';
import type { BaseData } from '../../data/wgslTypes.ts';
import type { StorageFlag } from '../../extension.ts';
import type { TgpuNamable } from '../../shared/meta.ts';
import type { Infer, InferInput, InferPatch, InferPartial, IsValidIndexSchema, IsValidStorageSchema, IsValidUniformSchema, IsValidVertexSchema, MemIdentity } from '../../shared/repr.ts';
import type { TgpuDeviceOwningSoul } from '../../shared/soul.ts';
import { $internal, $soul } from '../../shared/symbols.ts';
import type { Prettify, UnionToIntersection } from '../../shared/utilityTypes.ts';
import type { TgpuCommandEncoder } from '../commandEncoder/commandEncoder.ts';
import type { ExperimentalTgpuRoot } from '../root/rootTypes.ts';
import { type TgpuMutable, type TgpuReadonly, type TgpuUniform } from './bufferBinding.ts';
export interface UniformFlag {
    usableAsUniform: true;
}
/**
 * @deprecated Use UniformFlag instead.
 */
export type Uniform = UniformFlag;
export interface VertexFlag {
    usableAsVertex: true;
}
export interface IndexFlag {
    usableAsIndex: true;
}
export interface IndirectFlag {
    usableAsIndirect: true;
}
/**
 * @deprecated Use VertexFlag instead.
 */
export type Vertex = VertexFlag;
export type TgpuStorageBuffer<T extends BaseData> = TgpuBuffer<T> & StorageFlag;
export type TgpuUniformBuffer<T extends BaseData> = TgpuBuffer<T> & UniformFlag;
export type TgpuVertexBuffer<T extends BaseData> = TgpuBuffer<T> & VertexFlag;
export type TgpuIndexBuffer<T extends BaseData> = TgpuBuffer<T> & IndexFlag;
export type UsageLiteral = 'uniform' | 'storage' | 'vertex' | 'index' | 'indirect';
export interface TgpuBufferSoul<TData extends BaseData = BaseData> extends TgpuDeviceOwningSoul<'buffer', GPUBuffer> {
    readonly dataType: TData;
    flags: GPUBufferUsageFlags;
    readonly usages: UsageLiteral[];
}
type LiteralToUsageType<T extends UsageLiteral> = T extends 'uniform' ? UniformFlag : T extends 'storage' ? StorageFlag : T extends 'vertex' ? VertexFlag : T extends 'index' ? IndexFlag : T extends 'indirect' ? IndirectFlag : never;
type ViewUsages<TBuffer extends TgpuBuffer<BaseData>> = (boolean extends TBuffer['usableAsUniform'] ? never : 'uniform') | (boolean extends TBuffer['usableAsStorage'] ? never : 'readonly' | 'mutable');
type UsageTypeToBufferBinding<TData extends BaseData> = {
    uniform: TgpuUniform<TData>;
    mutable: TgpuMutable<TData>;
    readonly: TgpuReadonly<TData>;
};
/**
 * Done as an object to later Prettify it
 */
type InnerValidUsagesFor<T> = {
    usage: (IsValidStorageSchema<T> extends true ? 'storage' : never) | (IsValidUniformSchema<T> extends true ? 'uniform' : never) | (IsValidVertexSchema<T> extends true ? 'vertex' : never) | (IsValidIndexSchema<T> extends true ? 'index' : never) | 'indirect';
};
export type ValidUsagesFor<T> = InnerValidUsagesFor<T>['usage'];
export type BufferWriteOptions = {
    startOffset?: number;
    endOffset?: number;
};
export type BufferInitCallback<TData extends BaseData> = (buffer: TgpuBuffer<TData>) => void;
export type BufferInitialData<TData extends BaseData> = InferInput<TData> | BufferInitCallback<TData>;
export interface TgpuBuffer<TData extends BaseData> extends TgpuNamable {
    readonly [$internal]: {
        readonly root: ExperimentalTgpuRoot;
        readonly materialize: () => GPUBuffer;
    };
    readonly [$soul]: TgpuBufferSoul<TData>;
    readonly resourceType: 'buffer';
    readonly dataType: TData;
    readonly initial?: InferInput<TData> | undefined;
    readonly arrayBuffer: ArrayBuffer;
    readonly buffer: GPUBuffer;
    readonly destroyed: boolean;
    usableAsUniform: boolean;
    usableAsStorage: boolean;
    usableAsVertex: boolean;
    usableAsIndex: boolean;
    usableAsIndirect: boolean;
    $usage<T extends [
        Prettify<InnerValidUsagesFor<TData>>['usage'],
        ...Prettify<InnerValidUsagesFor<TData>>['usage'][]
    ]>(...usages: T): this & UnionToIntersection<LiteralToUsageType<T[number]>>;
    $addFlags(flags: GPUBufferUsageFlags): this;
    as<T extends ViewUsages<this>>(usage: T): UsageTypeToBufferBinding<TData>[T];
    compileWriter(): void;
    write(data: InferInput<TData>, options?: BufferWriteOptions): void;
    write(data: ArrayBuffer, options?: BufferWriteOptions): void;
    /** @deprecated Use {@link patch} instead. */
    writePartial(data: InferPartial<TData>): void;
    patch(data: InferPatch<TData>): void;
    clear(encoder?: TgpuCommandEncoder): void;
    copyFrom(srcBuffer: TgpuBuffer<MemIdentity<TData>>, encoder?: TgpuCommandEncoder): void;
    read(): Promise<Infer<TData>>;
    destroy(): void;
    toString(): string;
}
export declare function INTERNAL_createBuffer<TData extends AnyData>(group: ExperimentalTgpuRoot, typeSchema: TData, initialOrBuffer?: BufferInitialData<TData> | GPUBuffer): TgpuBuffer<TData>;
export declare function INTERNAL_applyBufferUsages(buffer: TgpuBuffer<BaseData>, usages: UsageLiteral[]): void;
export {};
