You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
5.1 KiB
JavaScript
237 lines
5.1 KiB
JavaScript
2 years ago
|
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;
|
||
|
|
||
|
}
|
||
|
|
||
|
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',
|
||
|
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 {
|
||
|
|
||
|
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;
|