import { type AnyData, type AnyLooseData, type IsLooseData, type LooseDecorated, type Undecorate } from './dataTypes.ts';
import { type Align, type AnyWgslData, type BaseData, type Builtin, type Decorated, type FlatInterpolatableData, type FlatInterpolationType, type Interpolate, type Invariant, type IsWgslData, type Location, type PerspectiveOrLinearInterpolatableData, type PerspectiveOrLinearInterpolationType, type Size, type Vec4f } from './wgslTypes.ts';
export declare const builtinNames: readonly ["vertex_index", "instance_index", "clip_distances", "position", "front_facing", "frag_depth", "primitive_index", "sample_index", "sample_mask", "fragment", "local_invocation_id", "local_invocation_index", "global_invocation_id", "global_invocation_index", "workgroup_id", "workgroup_index", "num_workgroups", "subgroup_invocation_id", "subgroup_size", "subgroup_id", "num_subgroups"];
export type BuiltinName = (typeof builtinNames)[number];
export type AnyAttribute<AllowedBuiltins extends Builtin<BuiltinName> = Builtin<BuiltinName>> = Align<number> | Size<number> | Location | Interpolate | Invariant | AllowedBuiltins;
export type ExtractAttributes<T> = T extends {
    readonly attribs: unknown[];
} ? T['attribs'] : [];
/**
 * Decorates a data-type `TData` with an attribute `TAttrib`.
 *
 * - if `TData` is loose
 *   - if `TData` is already `LooseDecorated`
 *     - Prepend `TAttrib` to the existing attribute tuple.
 *   - else
 *     - Wrap `TData` with `LooseDecorated` and a single attribute `[TAttrib]`
 * - else
 *   - if `TData` is already `Decorated`
 *     - Prepend `TAttrib` to the existing attribute tuple.
 *   - else
 *     - Wrap `TData` with `Decorated` and a single attribute `[TAttrib]`
 */
export type Decorate<TData extends BaseData, TAttrib extends AnyAttribute> = IsWgslData<TData> extends true ? Decorated<Undecorate<TData>, [TAttrib, ...ExtractAttributes<TData>]> : IsLooseData<TData> extends true ? LooseDecorated<Undecorate<TData>, [TAttrib, ...ExtractAttributes<TData>]> : never;
export type IsBuiltin<T> = ExtractAttributes<T>[number] extends [] ? false : ExtractAttributes<T>[number] extends Builtin<BuiltinName> ? true : false;
export type HasCustomLocation<T> = ExtractAttributes<T>[number] extends [] ? false : ExtractAttributes<T>[number] extends Location ? true : false;
export declare function attribute(data: BaseData, attrib: AnyAttribute): Decorated | LooseDecorated;
/**
 * Gives the wrapped data-type a custom byte alignment. Useful in order to
 * fulfill uniform alignment requirements.
 *
 * @example
 * const Data = d.struct({
 *   a: u32, // takes up 4 bytes
 *   // 12 bytes of padding, because `b` is custom aligned to multiples of 16 bytes
 *   b: d.align(16, u32),
 * });
 *
 * @param alignment The multiple of bytes this data should align itself to.
 * @param data The data-type to align.
 */
export declare function align<TAlign extends number, TData extends AnyData>(alignment: TAlign, data: TData): Decorate<TData, Align<TAlign>>;
/**
 * Adds padding bytes after the wrapped data-type, until the whole value takes up `size` bytes.
 *
 * @example
 * const Data = d.struct({
 *   a: d.size(16, u32), // takes up 16 bytes, instead of 4
 *   b: u32, // starts at byte 16, because `a` has a custom size
 * });
 *
 * @param size The amount of bytes that should be reserved for this data-type.
 * @param data The data-type to wrap.
 */
export declare function size<TSize extends number, TData extends AnyData>(size: TSize, data: TData): Decorate<TData, Size<TSize>>;
/**
 * Assigns an explicit numeric location to a struct member or a parameter that has this type.
 *
 * @example
 * const VertexOutput = {
 *   a: d.u32, // has implicit location 0
 *   b: d.location(5, d.u32),
 *   c: d.u32, // has implicit location 6
 * };
 *
 * @param location The explicit numeric location.
 * @param data The data-type to wrap.
 */
export declare function location<TLocation extends number, TData extends BaseData>(location: TLocation, data: TData): Decorate<TData, Location<TLocation>>;
/**
 * Specifies how user-defined vertex shader output (fragment shader input)
 * must be interpolated.
 *
 * Tip: Integer outputs cannot be interpolated.
 *
 * @example
 * const VertexOutput = {
 *   a: d.f32, // has implicit 'perspective, center' interpolation
 *   b: d.interpolate('linear, sample', d.f32),
 * };
 *
 * @param interpolationType How data should be interpolated.
 * @param data The data-type to wrap.
 */
export declare function interpolate<TInterpolation extends PerspectiveOrLinearInterpolationType, TData extends PerspectiveOrLinearInterpolatableData>(interpolationType: TInterpolation, data: TData): Decorate<TData, Interpolate<TInterpolation>>;
/**
 * Specifies how user-defined vertex shader output (fragment shader input)
 * must be interpolated.
 *
 * Tip: Default sampling method of `flat` is `first`. Unless you specifically
 * need deterministic behavior provided by `'flat, first'`, prefer explicit
 * `'flat, either'` as it could be slightly faster in hardware.
 *
 * @example
 * const VertexOutput = {
 *   a: d.f32, // has implicit 'perspective, center' interpolation
 *   b: d.interpolate('flat, either', d.u32), // integer outputs cannot interpolate
 * };
 *
 * @param interpolationType How data should be interpolated.
 * @param data The data-type to wrap.
 */
export declare function interpolate<TInterpolation extends FlatInterpolationType, TData extends FlatInterpolatableData>(interpolationType: TInterpolation, data: TData): Decorate<TData, Interpolate<TInterpolation>>;
/**
 * Marks a position built-in output value as invariant in vertex shaders.
 * If the data and control flow match for two position outputs in different
 * entry points, then the result values are guaranteed to be the same.
 *
 * Must only be applied to the position built-in value.
 *
 * @example
 * const VertexOutput = {
 *   pos: d.invariant(d.builtin.position),
 * };
 *
 * @param data The position built-in data-type to mark as invariant.
 */
export declare function invariant(data: Decorated<Vec4f, [Builtin<'position'>]>): Decorated<Vec4f, [Builtin<'position'>, Invariant]>;
export declare function isBuiltin(value: unknown): value is Decorated<AnyWgslData, AnyAttribute[]> | LooseDecorated<AnyLooseData, AnyAttribute[]>;
export declare function getAttributesString<T extends BaseData>(field: T): string;
