123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- import {
- GPUTextureAspect, GPUTextureViewDimension, GPUBufferBindingType, GPUTextureSampleType
- } from './WebGPUConstants.js';
- import { FloatType } from 'three';
- class WebGPUBindingUtils {
- constructor( backend ) {
- this.backend = backend;
- }
- createBindingsLayout( bindings ) {
- const backend = this.backend;
- const device = backend.device;
- const entries = [];
- let index = 0;
- for ( const binding of bindings ) {
- const bindingGPU = {
- binding: index ++,
- visibility: binding.visibility
- };
- if ( binding.isUniformBuffer || binding.isStorageBuffer ) {
- const buffer = {}; // GPUBufferBindingLayout
- if ( binding.isStorageBuffer ) {
- buffer.type = GPUBufferBindingType.Storage;
- }
- bindingGPU.buffer = buffer;
- } else if ( binding.isSampler ) {
- const sampler = {}; // GPUSamplerBindingLayout
- if ( binding.texture.isDepthTexture ) {
- if ( binding.texture.compareFunction !== null ) {
- sampler.type = 'comparison';
- }
- }
- bindingGPU.sampler = sampler;
- } else if ( binding.isSampledTexture && binding.texture.isVideoTexture ) {
- bindingGPU.externalTexture = {}; // GPUExternalTextureBindingLayout
- } else if ( binding.isSampledTexture && binding.store ) {
- const format = this.backend.get( binding.texture ).texture.format;
- bindingGPU.storageTexture = { format }; // GPUStorageTextureBindingLayout
- } else if ( binding.isSampledTexture ) {
- const texture = {}; // GPUTextureBindingLayout
- if ( binding.texture.isDepthTexture ) {
- texture.sampleType = GPUTextureSampleType.Depth;
- } else if ( binding.texture.isDataTexture && binding.texture.type === FloatType ) {
- // @TODO: Add support for this soon: backend.hasFeature( 'float32-filterable' )
- texture.sampleType = GPUTextureSampleType.UnfilterableFloat;
- }
- if ( binding.isSampledCubeTexture ) {
- texture.viewDimension = GPUTextureViewDimension.Cube;
- } else if ( binding.texture.isDataArrayTexture ) {
- texture.viewDimension = GPUTextureViewDimension.TwoDArray;
- }
- bindingGPU.texture = texture;
- } else {
- console.error( `WebGPUBindingUtils: Unsupported binding "${ binding }".` );
- }
- entries.push( bindingGPU );
- }
- return device.createBindGroupLayout( { entries } );
- }
- createBindings( bindings ) {
- const backend = this.backend;
- const bindingsData = backend.get( bindings );
- // setup (static) binding layout and (dynamic) binding group
- const bindLayoutGPU = this.createBindingsLayout( bindings );
- const bindGroupGPU = this.createBindGroup( bindings, bindLayoutGPU );
- bindingsData.layout = bindLayoutGPU;
- bindingsData.group = bindGroupGPU;
- bindingsData.bindings = bindings;
- }
- updateBinding( binding ) {
- const backend = this.backend;
- const device = backend.device;
- const buffer = binding.buffer;
- const bufferGPU = backend.get( binding ).buffer;
- device.queue.writeBuffer( bufferGPU, 0, buffer, 0 );
- }
- createBindGroup( bindings, layoutGPU ) {
- const backend = this.backend;
- const device = backend.device;
- let bindingPoint = 0;
- const entriesGPU = [];
- for ( const binding of bindings ) {
- if ( binding.isUniformBuffer ) {
- const bindingData = backend.get( binding );
- if ( bindingData.buffer === undefined ) {
- const byteLength = binding.byteLength;
- const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
- const bufferGPU = device.createBuffer( {
- label: 'bindingBuffer_' + binding.name,
- size: byteLength,
- usage: usage
- } );
- bindingData.buffer = bufferGPU;
- }
- entriesGPU.push( { binding: bindingPoint, resource: { buffer: bindingData.buffer } } );
- } else if ( binding.isStorageBuffer ) {
- const bindingData = backend.get( binding );
- if ( bindingData.buffer === undefined ) {
- const attribute = binding.attribute;
- //const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | /*GPUBufferUsage.COPY_SRC |*/ GPUBufferUsage.COPY_DST;
- //backend.attributeUtils.createAttribute( attribute, usage ); // @TODO: Move it to universal renderer
- bindingData.buffer = backend.get( attribute ).buffer;
- }
- entriesGPU.push( { binding: bindingPoint, resource: { buffer: bindingData.buffer } } );
- } else if ( binding.isSampler ) {
- const textureGPU = backend.get( binding.texture );
- entriesGPU.push( { binding: bindingPoint, resource: textureGPU.sampler } );
- } else if ( binding.isSampledTexture ) {
- const textureData = backend.get( binding.texture );
- let dimensionViewGPU;
- if ( binding.isSampledCubeTexture ) {
- dimensionViewGPU = GPUTextureViewDimension.Cube;
- } else if ( binding.texture.isDataArrayTexture ) {
- dimensionViewGPU = GPUTextureViewDimension.TwoDArray;
- } else {
- dimensionViewGPU = GPUTextureViewDimension.TwoD;
- }
- let resourceGPU;
- if ( textureData.externalTexture !== undefined ) {
- resourceGPU = device.importExternalTexture( { source: textureData.externalTexture } );
- } else {
- const aspectGPU = GPUTextureAspect.All;
- resourceGPU = textureData.texture.createView( { aspect: aspectGPU, dimension: dimensionViewGPU } );
- }
- entriesGPU.push( { binding: bindingPoint, resource: resourceGPU } );
- }
- bindingPoint ++;
- }
- return device.createBindGroup( {
- layout: layoutGPU,
- entries: entriesGPU
- } );
- }
- }
- export default WebGPUBindingUtils;
|