import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { Matrix } from '../../../maths/Matrix.mjs';
import { getTextureBatchBindGroup } from '../../batcher/gpu/getTextureBatchBindGroup.mjs';
import { MAX_TEXTURES } from '../../batcher/shared/const.mjs';
import { compileHighShaderGpuProgram } from '../../high-shader/compileHighShaderToProgram.mjs';
import { colorBit } from '../../high-shader/shader-bits/colorBit.mjs';
import { generateTextureBatchBit } from '../../high-shader/shader-bits/generateTextureBatchBit.mjs';
import { localUniformBit } from '../../high-shader/shader-bits/localUniformBit.mjs';
import { BindGroup } from '../../renderers/gpu/shader/BindGroup.mjs';
import { Shader } from '../../renderers/shared/shader/Shader.mjs';
import { UniformGroup } from '../../renderers/shared/shader/UniformGroup.mjs';
import { color32BitToUniform } from './colorToUniform.mjs';

class GpuGraphicsAdaptor {
  init() {
    const localUniforms = new UniformGroup({
      color: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
      transformMatrix: { value: new Matrix(), type: "mat3x3<f32>" }
    });
    const gpuProgram = compileHighShaderGpuProgram({
      name: "graphics",
      bits: [
        colorBit,
        generateTextureBatchBit(MAX_TEXTURES),
        localUniformBit
      ]
    });
    this._shader = new Shader({
      gpuProgram,
      groups: {
        // added on the fly!
        2: new BindGroup({ 0: localUniforms })
      }
    });
  }
  execute(graphicsPipe, renderable) {
    const context = renderable.view.context;
    const shader = context.customShader || this._shader;
    const renderer = graphicsPipe.renderer;
    const contextSystem = renderer.graphicsContext;
    if (!contextSystem.getGpuContext(context).batches.length) {
      return;
    }
    const {
      geometry,
      instructions
    } = contextSystem.getContextRenderData(context);
    graphicsPipe.state.blendMode = renderable.layerBlendMode;
    const localUniforms = shader.resources.localUniforms;
    shader.resources.localUniforms.uniforms.uTransformMatrix = renderable.layerTransform;
    color32BitToUniform(
      renderable.layerColor,
      localUniforms.uniforms.uColor,
      0
    );
    const encoder = renderer.encoder;
    encoder.setPipelineFromGeometryProgramAndState(
      geometry,
      shader.gpuProgram,
      graphicsPipe.state
    );
    encoder.setGeometry(geometry);
    const globalUniformsBindGroup = renderer.globalUniforms.bindGroup;
    encoder.setBindGroup(0, globalUniformsBindGroup, shader.gpuProgram);
    const localBindGroup = renderer.renderPipes.uniformBatch.getUniformBindGroup(localUniforms, true);
    encoder.setBindGroup(2, localBindGroup, shader.gpuProgram);
    const batches = instructions.instructions;
    for (let i = 0; i < instructions.instructionSize; i++) {
      const batch = batches[i];
      shader.groups[1] = batch.bindGroup;
      if (!batch.gpuBindGroup) {
        const textureBatch = batch.textures;
        batch.bindGroup = getTextureBatchBindGroup(textureBatch.textures, textureBatch.count);
        batch.gpuBindGroup = renderer.bindGroup.getBindGroup(
          batch.bindGroup,
          shader.gpuProgram,
          1
        );
      }
      encoder.setBindGroup(1, batch.bindGroup, shader.gpuProgram);
      encoder.renderPassEncoder.drawIndexed(batch.size, 1, batch.start);
    }
  }
  destroy() {
    this._shader.destroy(true);
    this._shader = null;
  }
}
/** @ignore */
GpuGraphicsAdaptor.extension = {
  type: [
    ExtensionType.WebGPUPipesAdaptor
  ],
  name: "graphics"
};

export { GpuGraphicsAdaptor };
//# sourceMappingURL=GpuGraphicsAdaptor.mjs.map
