export const description = `
createBindGroupLayout validation tests.

TODO: make sure tests are complete.
`;

import { AllFeaturesMaxLimitsGPUTest } from '../.././gpu_test.js';
import { kUnitCaseParamsBuilder } from '../../../common/framework/params_builder.js';
import { makeTestGroup } from '../../../common/framework/test_group.js';
import {
  kShaderStages,
  kShaderStageCombinations,
  kStorageTextureAccessValues,
  kTextureSampleTypes,
  kTextureViewDimensions,
  allBindingEntries,
  bindingTypeInfo,
  bufferBindingTypeInfo,
  kBufferBindingTypes,
  BGLEntry,
  getBindingLimitForBindingType,
} from '../../capability_info.js';
import {
  isTextureFormatUsableWithStorageAccessMode,
  kAllTextureFormats,
} from '../../format_info.js';

function clone<T extends GPUBindGroupLayoutDescriptor>(descriptor: T): T {
  return JSON.parse(JSON.stringify(descriptor));
}

function isValidBufferTypeForStages(
  device: GPUDevice,
  visibility: number,
  type: GPUBufferBindingType | undefined
) {
  if (type === 'read-only-storage' || type === 'storage') {
    if (visibility & GPUShaderStage.VERTEX) {
      if (!(device.limits.maxStorageBuffersInVertexStage! > 0)) {
        return false;
      }
    }

    if (visibility & GPUShaderStage.FRAGMENT) {
      if (!(device.limits.maxStorageBuffersInFragmentStage! > 0)) {
        return false;
      }
    }
  }

  return true;
}

function isValidStorageTextureForStages(device: GPUDevice, visibility: number) {
  if (visibility & GPUShaderStage.VERTEX) {
    if (!(device.limits.maxStorageTexturesInVertexStage! > 0)) {
      return false;
    }
  }

  if (visibility & GPUShaderStage.FRAGMENT) {
    if (!(device.limits.maxStorageTexturesInFragmentStage! > 0)) {
      return false;
    }
  }

  return true;
}

function isValidBGLEntryForStages(device: GPUDevice, visibility: number, entry: BGLEntry) {
  return entry.storageTexture
    ? isValidStorageTextureForStages(device, visibility)
    : entry.buffer
    ? isValidBufferTypeForStages(device, visibility, entry.buffer?.type)
    : true;
}

export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest);

g.test('duplicate_bindings')
  .desc('Test that uniqueness of binding numbers across entries is enforced.')
  .paramsSubcasesOnly([
    { bindings: [0, 1], _valid: true },
    { bindings: [0, 0], _valid: false },
  ])
  .fn(t => {
    const { bindings, _valid } = t.params;
    const entries: Array<GPUBindGroupLayoutEntry> = [];

    for (const binding of bindings) {
      entries.push({
        binding,
        visibility: GPUShaderStage.COMPUTE,
        buffer: { type: 'storage' as const },
      });
    }

    t.expectValidationError(() => {
      t.device.createBindGroupLayout({
        entries,
      });
    }, !_valid);
  });

g.test('maximum_binding_limit')
  .desc(
    `
  Test that a validation error is generated if the binding number exceeds the maximum binding limit.

  TODO: Need to also test with higher limits enabled on the device, once we have a way to do that.
  `
  )
  .paramsSubcasesOnly(u =>
    u.combine('bindingVariant', [1, 4, 8, 256, 'default', 'default-minus-one'] as const)
  )
  .fn(t => {
    const { bindingVariant } = t.params;
    const entries: Array<GPUBindGroupLayoutEntry> = [];

    const binding =
      bindingVariant === 'default'
        ? t.device.limits.maxBindingsPerBindGroup
        : bindingVariant === 'default-minus-one'
        ? t.device.limits.maxBindingsPerBindGroup - 1
        : bindingVariant;

    entries.push({
      binding,
      visibility: GPUShaderStage.COMPUTE,
      buffer: { type: 'storage' as const },
    });

    const success = binding < t.device.limits.maxBindingsPerBindGroup;

    t.expectValidationError(() => {
      t.device.createBindGroupLayout({
        entries,
      });
    }, !success);
  });

g.test('visibility')
  .desc(
    `
    Test that only the appropriate combinations of visibilities are allowed for each resource type.
    - Test each possible combination of shader stage visibilities.
    - Test each type of bind group resource.`
  )
  .params(u =>
    u
      .combine('visibility', kShaderStageCombinations)
      .beginSubcases()
      .combine('entry', allBindingEntries(false))
  )
  .fn(t => {
    const { visibility, entry } = t.params;
    const info = bindingTypeInfo(entry);

    const success =
      (visibility & ~info.validStages) === 0 &&
      isValidBGLEntryForStages(t.device, visibility, entry);

    t.expectValidationError(() => {
      t.device.createBindGroupLayout({
        entries: [{ binding: 0, visibility, ...entry }],
      });
    }, !success);
  });

g.test('visibility,VERTEX_shader_stage_buffer_type')
  .desc(
    `
  Test that a validation error is generated if the buffer type is 'storage' when the
  visibility of the entry includes VERTEX.
  `
  )
  .params(u =>
    u //
      .combine('shaderStage', kShaderStageCombinations)
      .beginSubcases()
      .combine('type', kBufferBindingTypes)
  )
  .fn(t => {
    const { shaderStage, type } = t.params;

    const success =
      !(type === 'storage' && shaderStage & GPUShaderStage.VERTEX) &&
      isValidBufferTypeForStages(t.device, shaderStage, type);

    t.expectValidationError(() => {
      t.device.createBindGroupLayout({
        entries: [
          {
            binding: 0,
            visibility: shaderStage,
            buffer: { type },
          },
        ],
      });
    }, !success);
  });

g.test('visibility,VERTEX_shader_stage_storage_texture_access')
  .desc(
    `
  Test that a validation error is generated if the access value is 'write-only' when the
  visibility of the entry includes VERTEX.
  `
  )
  .params(u =>
    u //
      .combine('shaderStage', kShaderStageCombinations)
      .beginSubcases()
      .combine('access', [undefined, ...kStorageTextureAccessValues])
  )
  .fn(t => {
    const { shaderStage, access } = t.params;

    const appliedAccess = access ?? 'write-only';
    const success =
      !(
        // If visibility includes VERETX, storageTexture.access must be "read-only"
        (shaderStage & GPUShaderStage.VERTEX && appliedAccess !== 'read-only')
      ) && isValidStorageTextureForStages(t.device, shaderStage);

    t.expectValidationError(() => {
      t.device.createBindGroupLayout({
        entries: [
          {
            binding: 0,
            visibility: shaderStage,
            storageTexture: { access, format: 'r32uint' },
          },
        ],
      });
    }, !success);
  });

g.test('multisampled_validation')
  .desc(
    `
  Test that multisampling is only allowed if view dimensions is "2d" and the sampleType is not
  "float".
  `
  )
  .params(u =>
    u //
      .combine('viewDimension', [undefined, ...kTextureViewDimensions])
      .beginSubcases()
      .combine('sampleType', [undefined, ...kTextureSampleTypes])
  )
  .fn(t => {
    const { viewDimension, sampleType } = t.params;

    const success =
      (viewDimension === '2d' || viewDimension === undefined) &&
      (sampleType ?? 'float') !== 'float';

    t.expectValidationError(() => {
      t.device.createBindGroupLayout({
        entries: [
          {
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            texture: { multisampled: true, viewDimension, sampleType },
          },
        ],
      });
    }, !success);
  });

g.test('max_dynamic_buffers')
  .desc(
    `
    Test that limits on the maximum number of dynamic buffers are enforced.
    - Test creation of a bind group layout using the maximum number of dynamic buffers works.
    - Test creation of a bind group layout using the maximum number of dynamic buffers + 1 fails.
    - TODO(#230): Update to enforce per-stage and per-pipeline-layout limits on BGLs as well.`
  )
  .params(u =>
    u
      .combine('type', kBufferBindingTypes)
      .beginSubcases()
      .combine('extraDynamicBuffers', [0, 1])
      .combine('staticBuffers', [0, 1])
  )
  .fn(t => {
    const { type, extraDynamicBuffers, staticBuffers } = t.params;
    const info = bufferBindingTypeInfo({ type });

    const limitName = info.perPipelineLimitClass.maxDynamicLimit;
    const bufferCount = limitName ? t.device.limits[limitName]! : 0;
    const dynamicBufferCount = bufferCount + extraDynamicBuffers;
    const perStageLimit = t.device.limits[info.perStageLimitClass.maxLimits.COMPUTE]!;

    const entries = [];
    for (let i = 0; i < dynamicBufferCount; i++) {
      entries.push({
        binding: i,
        visibility: GPUShaderStage.COMPUTE,
        buffer: { type, hasDynamicOffset: true },
      });
    }

    for (let i = dynamicBufferCount; i < dynamicBufferCount + staticBuffers; i++) {
      entries.push({
        binding: i,
        visibility: GPUShaderStage.COMPUTE,
        buffer: { type, hasDynamicOffset: false },
      });
    }

    const descriptor = {
      entries,
    };

    t.expectValidationError(
      () => {
        t.device.createBindGroupLayout(descriptor);
      },
      extraDynamicBuffers > 0 || entries.length > perStageLimit
    );
  });

/**
 * One bind group layout will be filled with kPerStageBindingLimit[...] of the type |type|.
 * For each item in the array returned here, a case will be generated which tests a pipeline
 * layout with one extra bind group layout with one extra binding. That extra binding will have:
 *
 *   - If extraTypeSame, any of the binding types which counts toward the same limit as |type|.
 *     (i.e. 'storage-buffer' <-> 'readonly-storage-buffer').
 *   - Otherwise, an arbitrary other type.
 */
function* pickExtraBindingTypesForPerStage(entry: BGLEntry, extraTypeSame: boolean) {
  if (extraTypeSame) {
    const info = bindingTypeInfo(entry);
    for (const extra of allBindingEntries(false)) {
      const extraInfo = bindingTypeInfo(extra);
      if (info.perStageLimitClass.class === extraInfo.perStageLimitClass.class) {
        yield extra;
      }
    }
  } else {
    yield entry.sampler ? { texture: {} } : { sampler: {} };
  }
}

const kMaxResourcesCases = kUnitCaseParamsBuilder
  .combine('maxedEntry', allBindingEntries(false))
  .beginSubcases()
  .combine('maxedVisibility', kShaderStages)
  .filter(p => (bindingTypeInfo(p.maxedEntry).validStages & p.maxedVisibility) !== 0)
  .expand('extraEntry', p => [
    ...pickExtraBindingTypesForPerStage(p.maxedEntry, true),
    ...pickExtraBindingTypesForPerStage(p.maxedEntry, false),
  ])
  .combine('extraVisibility', kShaderStages)
  .filter(p => (bindingTypeInfo(p.extraEntry).validStages & p.extraVisibility) !== 0);

// Should never fail unless limitInfo.maxBindingsPerBindGroup.default is exceeded, because the validation for
// resources-of-type-per-stage is in pipeline layout creation.
g.test('max_resources_per_stage,in_bind_group_layout')
  .desc(
    `
    Test that the maximum number of bindings of a given type per-stage cannot be exceeded in a
    single bind group layout.
    - Test each binding type.
    - Test that creation of a bind group layout using the maximum number of bindings works.
    - Test that creation of a bind group layout using the maximum number of bindings + 1 fails.
    - TODO(#230): Update to enforce per-stage and per-pipeline-layout limits on BGLs as well.`
  )
  .params(kMaxResourcesCases)
  .fn(t => {
    const { maxedEntry, extraEntry, maxedVisibility, extraVisibility } = t.params;
    const maxedTypeInfo = bindingTypeInfo(maxedEntry);
    const maxedCount = getBindingLimitForBindingType(t.device, maxedVisibility, maxedEntry);
    const extraTypeInfo = bindingTypeInfo(extraEntry);

    t.skipIf(!isValidBGLEntryForStages(t.device, extraVisibility, extraEntry));

    const maxResourceBindings: GPUBindGroupLayoutEntry[] = [];
    for (let i = 0; i < maxedCount; i++) {
      maxResourceBindings.push({
        binding: i,
        visibility: maxedVisibility,
        ...maxedEntry,
      });
    }

    const goodDescriptor = { entries: maxResourceBindings };

    // Control
    t.device.createBindGroupLayout(goodDescriptor);

    // Add an entry counting towards the same limit. It should produce a validation error.
    const newDescriptor = clone(goodDescriptor);
    newDescriptor.entries.push({
      binding: maxedCount,
      visibility: extraVisibility,
      ...extraEntry,
    });

    const newBindingCountsTowardSamePerStageLimit =
      (maxedVisibility & extraVisibility) !== 0 &&
      maxedTypeInfo.perStageLimitClass.class === extraTypeInfo.perStageLimitClass.class;

    t.expectValidationError(() => {
      t.device.createBindGroupLayout(newDescriptor);
    }, newBindingCountsTowardSamePerStageLimit);
  });

// One pipeline layout can have a maximum number of each type of binding *per stage* (which is
// different for each type). Test that the max works, then add one more binding of same-or-different
// type and same-or-different visibility.
g.test('max_resources_per_stage,in_pipeline_layout')
  .desc(
    `
    Test that the maximum number of bindings of a given type per-stage cannot be exceeded across
    multiple bind group layouts when creating a pipeline layout.
    - Test each binding type.
    - Test that creation of a pipeline using the maximum number of bindings works.
    - Test that creation of a pipeline using the maximum number of bindings + 1 fails.
  `
  )
  .params(kMaxResourcesCases)
  .fn(t => {
    const { maxedEntry, extraEntry, maxedVisibility, extraVisibility } = t.params;
    const maxedTypeInfo = bindingTypeInfo(maxedEntry);
    const maxedCount = getBindingLimitForBindingType(t.device, maxedVisibility, maxedEntry);
    const extraTypeInfo = bindingTypeInfo(extraEntry);

    t.skipIf(!isValidBGLEntryForStages(t.device, extraVisibility, extraEntry));

    const maxResourceBindings: GPUBindGroupLayoutEntry[] = [];
    for (let i = 0; i < maxedCount; i++) {
      maxResourceBindings.push({
        binding: i,
        visibility: maxedVisibility,
        ...maxedEntry,
      });
    }

    const goodLayout = t.device.createBindGroupLayout({ entries: maxResourceBindings });

    // Control
    t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout] });

    const extraLayout = t.device.createBindGroupLayout({
      entries: [
        {
          binding: 0,
          visibility: extraVisibility,
          ...extraEntry,
        },
      ],
    });

    // Some binding types use the same limit, e.g. 'storage-buffer' and 'readonly-storage-buffer'.
    const newBindingCountsTowardSamePerStageLimit =
      (maxedVisibility & extraVisibility) !== 0 &&
      maxedTypeInfo.perStageLimitClass.class === extraTypeInfo.perStageLimitClass.class;

    t.expectValidationError(() => {
      t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout, extraLayout] });
    }, newBindingCountsTowardSamePerStageLimit);
  });

g.test('storage_texture,layout_dimension')
  .desc(
    `
  Test that viewDimension is not cube or cube-array if storageTextureLayout is not undefined.
  `
  )
  .params(u =>
    u //
      .combine('viewDimension', [undefined, ...kTextureViewDimensions])
  )
  .fn(t => {
    const { viewDimension } = t.params;

    const success = viewDimension !== 'cube' && viewDimension !== `cube-array`;

    t.expectValidationError(() => {
      t.device.createBindGroupLayout({
        entries: [
          {
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            storageTexture: { format: 'rgba8unorm', viewDimension },
          },
        ],
      });
    }, !success);
  });

g.test('storage_texture,formats')
  .desc(
    `
  Test that a validation error is generated if the format doesn't support the storage usage. A
  validation error is also generated if the format doesn't support the 'read-write' storage access
  when the storage access is 'read-write'.
  `
  )
  .params(u =>
    u //
      .combine('format', kAllTextureFormats) //
      .combine('access', kStorageTextureAccessValues)
  )
  .fn(t => {
    const { format, access } = t.params;
    t.skipIfTextureFormatNotSupported(format);

    const success = isTextureFormatUsableWithStorageAccessMode(t.device.features, format, access);

    t.expectValidationError(() => {
      t.device.createBindGroupLayout({
        entries: [
          {
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            storageTexture: { format, access },
          },
        ],
      });
    }, !success);
  });
