WebGPUBindings.js 5.2 KB
Newer Older
M
Mugen87 已提交
1 2
class WebGPUBindings {

3
	constructor( device, info, properties, textures, renderPipelines, computePipelines, attributes, nodes ) {
M
Mugen87 已提交
4 5 6 7 8

		this.device = device;
		this.info = info;
		this.properties = properties;
		this.textures = textures;
9
		this.renderPipelines = renderPipelines;
10 11
		this.computePipelines = computePipelines;
		this.attributes = attributes;
S
sunag 已提交
12
		this.nodes = nodes;
M
Mugen87 已提交
13 14 15 16 17 18 19 20 21 22 23 24 25

		this.uniformsData = new WeakMap();

		this.updateMap = new WeakMap();

	}

	get( object ) {

		let data = this.uniformsData.get( object );

		if ( data === undefined ) {

26
			// each object defines an array of bindings (ubos, textures, samplers etc.)
M
Mugen87 已提交
27

S
sunag 已提交
28
			const nodeBuilder = this.nodes.get( object );
S
sunag 已提交
29
			const bindings = nodeBuilder.getBindings();
M
Mugen87 已提交
30 31 32

			// setup (static) binding layout and (dynamic) binding group

33 34
			const renderPipelines = this.renderPipelines.get( object );

35
			const bindLayout = renderPipelines.pipeline.getBindGroupLayout( 0 );
M
Mugen87 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
			const bindGroup = this._createBindGroup( bindings, bindLayout );

			data = {
				layout: bindLayout,
				group: bindGroup,
				bindings: bindings
			};

			this.uniformsData.set( object, data );

		}

		return data;

	}

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
	getForCompute( param ) {

		let data = this.uniformsData.get( param );

		if ( data === undefined ) {

			const pipeline = this.computePipelines.get( param );
			const bindings = param.bindings !== undefined ? param.bindings.slice() : [];
			const bindLayout = pipeline.getBindGroupLayout( 0 );
			const bindGroup = this._createBindGroup( bindings, bindLayout );

			data = {
				layout: bindLayout,
				group: bindGroup,
				bindings: bindings
			};

			this.uniformsData.set( param, data );

		}

		return data;

	}

M
Mugen87 已提交
77 78
	update( object, camera ) {

79 80
		const textures = this.textures;

M
Mugen87 已提交
81 82 83 84 85 86 87 88 89 90 91 92
		const data = this.get( object );
		const bindings = data.bindings;

		const updateMap = this.updateMap;
		const frame = this.info.render.frame;

		let needsBindGroupRefresh = false;

		// iterate over all bindings and check if buffer updates or a new binding group is required

		for ( const binding of bindings ) {

S
cleanup  
sunag 已提交
93
			const isShared = binding.isShared;
S
sunag 已提交
94
			const isUpdated = updateMap.get( binding ) === frame;
M
Mugen87 已提交
95

S
sunag 已提交
96
			if ( isShared && isUpdated ) continue;
M
Mugen87 已提交
97

S
sunag 已提交
98
			if ( binding.isUniformsGroup ) {
M
Mugen87 已提交
99 100 101 102

				const array = binding.array;
				const bufferGPU = binding.bufferGPU;

M
Mugen87 已提交
103 104 105
				binding.onBeforeUpdate( object, camera );

				const needsBufferWrite = binding.update();
M
Mugen87 已提交
106 107 108

				if ( needsBufferWrite === true ) {

M
Mugen87 已提交
109
					this.device.queue.writeBuffer(
M
Mugen87 已提交
110 111 112 113 114 115 116 117
						bufferGPU,
						0,
						array,
						0
					);

				}

118 119 120 121 122
			} else if ( binding.isStorageBuffer ) {

				const attribute = binding.attribute;
				this.attributes.update( attribute, false, binding.usage );

M
Mugen87 已提交
123 124
			} else if ( binding.isSampler ) {

125
				const texture = binding.getTexture();
M
Mugen87 已提交
126

S
sunag 已提交
127
				textures.updateSampler( texture );
128

S
sunag 已提交
129
				const samplerGPU = textures.getSampler( texture );
M
Mugen87 已提交
130

S
sunag 已提交
131
				if ( binding.samplerGPU !== samplerGPU ) {
M
Mugen87 已提交
132

S
sunag 已提交
133 134
					binding.samplerGPU = samplerGPU;
					needsBindGroupRefresh = true;
M
Mugen87 已提交
135 136 137 138 139

				}

			} else if ( binding.isSampledTexture ) {

140
				const texture = binding.getTexture();
M
Mugen87 已提交
141

S
sunag 已提交
142 143
				const forceUpdate = textures.updateTexture( texture );
				const textureGPU = textures.getTextureGPU( texture );
144

S
sunag 已提交
145
				if ( binding.textureGPU !== textureGPU || forceUpdate === true ) {
146

S
sunag 已提交
147 148
					binding.textureGPU = textureGPU;
					needsBindGroupRefresh = true;
M
Mugen87 已提交
149 150 151 152 153

				}

			}

S
sunag 已提交
154 155
			updateMap.set( binding, frame );

M
Mugen87 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
		}

		if ( needsBindGroupRefresh === true ) {

			data.group = this._createBindGroup( bindings, data.layout );

		}

	}

	dispose() {

		this.uniformsData = new WeakMap();
		this.updateMap = new WeakMap();

	}

	_createBindGroup( bindings, layout ) {

		let bindingPoint = 0;
		const entries = [];

		for ( const binding of bindings ) {

			if ( binding.isUniformsGroup ) {

				if ( binding.bufferGPU === null ) {

					const byteLength = binding.getByteLength();

					binding.array = new Float32Array( new ArrayBuffer( byteLength ) );

					binding.bufferGPU = this.device.createBuffer( {
						size: byteLength,
						usage: binding.usage,
					} );

				}

				entries.push( { binding: bindingPoint, resource: { buffer: binding.bufferGPU } } );

197 198 199 200 201 202 203 204 205 206 207 208 209
			} else if ( binding.isStorageBuffer ) {

				if ( binding.bufferGPU === null ) {

					const attribute = binding.attribute;

					this.attributes.update( attribute, false, binding.usage );
					binding.bufferGPU = this.attributes.get( attribute ).buffer;

				}

				entries.push( { binding: bindingPoint, resource: { buffer: binding.bufferGPU } } );

M
Mugen87 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223
			} else if ( binding.isSampler ) {

				if ( binding.samplerGPU === null ) {

					binding.samplerGPU = this.textures.getDefaultSampler();

				}

				entries.push( { binding: bindingPoint, resource: binding.samplerGPU } );

			} else if ( binding.isSampledTexture ) {

				if ( binding.textureGPU === null ) {

224 225 226 227 228 229 230 231 232
					if ( binding.isSampledCubeTexture ) {

						binding.textureGPU = this.textures.getDefaultCubeTexture();

					} else {

						binding.textureGPU = this.textures.getDefaultTexture();

					}
M
Mugen87 已提交
233 234 235

				}

236
				entries.push( { binding: bindingPoint, resource: binding.textureGPU.createView( { dimension: binding.dimension } ) } );
M
Mugen87 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253

			}

			bindingPoint ++;

		}

		return this.device.createBindGroup( {
			layout: layout,
			entries: entries
		} );

	}

}

export default WebGPUBindings;