Skip to content

Commit deffab6

Browse files
authored
Backend: Introduce createUniformBuffer() (#33373)
1 parent d3b629c commit deffab6

6 files changed

Lines changed: 216 additions & 92 deletions

File tree

examples/jsm/inspector/tabs/Timeline.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,11 +1044,29 @@ class Timeline extends Tab {
10441044
case 'updateBindings': {
10451045

10461046
const bindGroup = args[ 0 ];
1047-
const details = { group: bindGroup.name || 'unknown' };
10481047

1049-
if ( bindGroup.bindings ) {
1048+
const details = {
1049+
group: bindGroup.name || 'unknown',
1050+
count: bindGroup.bindings.length
1051+
};
1052+
1053+
return details;
1054+
1055+
}
1056+
1057+
case 'createUniformBuffer':
1058+
case 'destroyUniformBuffer': {
1059+
1060+
const binding = args[ 0 ];
1061+
1062+
const details = {
1063+
group: binding.groupNode.name || 'unknown',
1064+
size: binding.byteLength + ' bytes'
1065+
};
1066+
1067+
if ( binding.name !== details.group ) {
10501068

1051-
details.count = bindGroup.bindings.length;
1069+
details.name = binding.name;
10521070

10531071
}
10541072

src/renderers/common/Backend.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,22 @@ class Backend {
389389
*/
390390
createStorageAttribute( /*attribute*/ ) { }
391391

392+
/**
393+
* Creates a uniform buffer.
394+
*
395+
* @abstract
396+
* @param {Buffer} uniformBuffer - The uniform buffer.
397+
*/
398+
createUniformBuffer( /*uniformBuffer*/ ) { }
399+
400+
/**
401+
* Destroys a uniform buffer.
402+
*
403+
* @abstract
404+
* @param {Buffer} uniformBuffer - The uniform buffer.
405+
*/
406+
destroyUniformBuffer( /*uniformBuffer*/ ) { }
407+
392408
/**
393409
* Updates the GPU buffer of a shader attribute.
394410
*

src/renderers/common/Bindings.js

Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -77,39 +77,39 @@ class Bindings extends DataMap {
7777
*/
7878
getForRender( renderObject ) {
7979

80-
const bindings = renderObject.getBindings();
80+
return this._getBindings( renderObject, renderObject.getBindings() );
8181

82-
for ( const bindGroup of bindings ) {
82+
}
8383

84-
const groupData = this.get( bindGroup );
84+
/**
85+
* Returns the bind groups for the given compute node.
86+
*
87+
* @param {Node} computeNode - The compute node.
88+
* @return {Array<BindGroup>} The bind groups.
89+
*/
90+
getForCompute( computeNode ) {
8591

86-
if ( groupData.bindGroup === undefined ) {
92+
return this._getBindings( computeNode, this.nodes.getForCompute( computeNode ).bindings );
8793

88-
// each object defines an array of bindings (ubos, textures, samplers etc.)
94+
}
8995

90-
this._init( bindGroup );
96+
_getBindings( object, bindings ) {
9197

92-
this.backend.createBindings( bindGroup, bindings, 0 );
98+
const data = this.get( object );
9399

94-
groupData.bindGroup = bindGroup;
100+
if ( data.bindings !== bindings ) {
95101

96-
}
102+
if ( data.bindings !== undefined ) {
97103

98-
}
104+
this._updateBindingsUsage( data.bindings, - 1 );
99105

100-
return bindings;
106+
}
101107

102-
}
108+
this._updateBindingsUsage( bindings, 1 );
103109

104-
/**
105-
* Returns the bind groups for the given compute node.
106-
*
107-
* @param {Node} computeNode - The compute node.
108-
* @return {Array<BindGroup>} The bind groups.
109-
*/
110-
getForCompute( computeNode ) {
110+
data.bindings = bindings;
111111

112-
const bindings = this.nodes.getForCompute( computeNode ).bindings;
112+
}
113113

114114
for ( const bindGroup of bindings ) {
115115

@@ -160,14 +160,7 @@ class Bindings extends DataMap {
160160
*/
161161
deleteForCompute( computeNode ) {
162162

163-
const bindings = this.nodes.getForCompute( computeNode ).bindings;
164-
165-
for ( const bindGroup of bindings ) {
166-
167-
this.backend.deleteBindGroupData( bindGroup );
168-
this.delete( bindGroup );
169-
170-
}
163+
this._deleteBindings( computeNode );
171164

172165
}
173166

@@ -178,12 +171,57 @@ class Bindings extends DataMap {
178171
*/
179172
deleteForRender( renderObject ) {
180173

181-
const bindings = renderObject.getBindings();
174+
this._deleteBindings( renderObject );
175+
176+
}
177+
178+
_deleteBindings( object ) {
179+
180+
const data = this.get( object );
181+
182+
if ( data.bindings !== undefined ) {
183+
184+
this._updateBindingsUsage( data.bindings, - 1 );
185+
186+
data.bindings = undefined;
187+
188+
}
189+
190+
}
191+
192+
_updateBindingsUsage( bindings, delta ) {
182193

183194
for ( const bindGroup of bindings ) {
184195

185-
this.backend.deleteBindGroupData( bindGroup );
186-
this.delete( bindGroup );
196+
const groupData = this.get( bindGroup );
197+
198+
groupData.usedTimes = ( groupData.usedTimes || 0 ) + delta;
199+
200+
for ( const binding of bindGroup.bindings ) {
201+
202+
if ( binding.isUniformBuffer ) {
203+
204+
const bindingData = this.get( binding );
205+
206+
bindingData.usedTimes = ( bindingData.usedTimes || 0 ) + delta;
207+
208+
if ( bindingData.usedTimes === 0 ) {
209+
210+
this.backend.destroyUniformBuffer( binding );
211+
this.delete( binding );
212+
213+
}
214+
215+
}
216+
217+
}
218+
219+
if ( groupData.usedTimes === 0 ) {
220+
221+
this.backend.deleteBindGroupData( bindGroup );
222+
this.delete( bindGroup );
223+
224+
}
187225

188226
}
189227

@@ -213,7 +251,11 @@ class Bindings extends DataMap {
213251

214252
for ( const binding of bindGroup.bindings ) {
215253

216-
if ( binding.isSampledTexture ) {
254+
if ( binding.isUniformBuffer ) {
255+
256+
this.backend.createUniformBuffer( binding );
257+
258+
} else if ( binding.isSampledTexture ) {
217259

218260
this.textures.updateTexture( binding.texture );
219261

src/renderers/webgl-fallback/WebGLBackend.js

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,24 +1834,9 @@ class WebGLBackend extends Backend {
18341834
if ( binding.isUniformsGroup || binding.isUniformBuffer ) {
18351835

18361836
const array = binding.buffer;
1837-
let { bufferGPU } = this.get( array );
1837+
const bufferGPU = map.bufferGPU;
18381838

1839-
if ( bufferGPU === undefined ) {
1840-
1841-
// create
1842-
1843-
bufferGPU = gl.createBuffer();
1844-
1845-
gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU );
1846-
gl.bufferData( gl.UNIFORM_BUFFER, array.byteLength, gl.DYNAMIC_DRAW );
1847-
1848-
this.set( array, { bufferGPU } );
1849-
1850-
} else {
1851-
1852-
gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU );
1853-
1854-
}
1839+
gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU );
18551840

18561841
// update
18571842

@@ -1883,8 +1868,6 @@ class WebGLBackend extends Backend {
18831868

18841869
}
18851870

1886-
map.bufferGPU = bufferGPU;
1887-
18881871
this.set( binding, map );
18891872

18901873
} else if ( binding.isSampledTexture ) {
@@ -1951,6 +1934,44 @@ class WebGLBackend extends Backend {
19511934

19521935
// attributes
19531936

1937+
/**
1938+
* Creates a uniform buffer.
1939+
*
1940+
* @param {Buffer} uniformBuffer - The uniform buffer.
1941+
*/
1942+
createUniformBuffer( uniformBuffer ) {
1943+
1944+
const uniformBufferData = this.get( uniformBuffer );
1945+
1946+
if ( uniformBufferData.bufferGPU === undefined ) {
1947+
1948+
const gl = this.gl;
1949+
const array = uniformBuffer.buffer;
1950+
1951+
uniformBufferData.bufferGPU = gl.createBuffer();
1952+
1953+
gl.bindBuffer( gl.UNIFORM_BUFFER, uniformBufferData.bufferGPU );
1954+
gl.bufferData( gl.UNIFORM_BUFFER, array.byteLength, gl.DYNAMIC_DRAW );
1955+
1956+
}
1957+
1958+
}
1959+
1960+
/**
1961+
* Destroys the GPU data for the given uniform buffer.
1962+
*
1963+
* @param {Buffer} uniformBuffer - The uniform buffer.
1964+
*/
1965+
destroyUniformBuffer( uniformBuffer ) {
1966+
1967+
const uniformBufferData = this.get( uniformBuffer );
1968+
1969+
this.gl.deleteBuffer( uniformBufferData.bufferGPU );
1970+
1971+
this.delete( uniformBuffer );
1972+
1973+
}
1974+
19541975
/**
19551976
* Creates the GPU buffer of an indexed shader attribute.
19561977
*

src/renderers/webgpu/WebGPUBackend.js

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import 'https://greggman.github.io/webgpu-avoid-redundant-state-setting/webgpu-check-redundant-state-setting.js';
33
//*/
44

5-
import { GPUFeatureName, GPULoadOp, GPUStoreOp, GPUIndexFormat, GPUTextureViewDimension, GPUFeatureMap } from './utils/WebGPUConstants.js';
5+
import { GPUFeatureName, GPULoadOp, GPUStoreOp, GPUIndexFormat, GPUTextureViewDimension, GPUFeatureMap, GPUShaderStage } from './utils/WebGPUConstants.js';
66

77
import WGSLNodeBuilder from './nodes/WGSLNodeBuilder.js';
88
import Backend from '../common/Backend.js';
@@ -2178,6 +2178,70 @@ class WebGPUBackend extends Backend {
21782178

21792179
// bindings
21802180

2181+
/**
2182+
* Creates a uniform buffer.
2183+
*
2184+
* @param {Buffer} uniformBuffer - The uniform buffer.
2185+
*/
2186+
createUniformBuffer( uniformBuffer ) {
2187+
2188+
const uniformBufferData = this.get( uniformBuffer );
2189+
2190+
if ( uniformBufferData.buffer === undefined ) {
2191+
2192+
const byteLength = uniformBuffer.byteLength;
2193+
2194+
const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
2195+
2196+
const visibilities = [];
2197+
2198+
if ( uniformBuffer.visibility & GPUShaderStage.VERTEX ) {
2199+
2200+
visibilities.push( 'vertex' );
2201+
2202+
}
2203+
2204+
if ( uniformBuffer.visibility & GPUShaderStage.FRAGMENT ) {
2205+
2206+
visibilities.push( 'fragment' );
2207+
2208+
}
2209+
2210+
if ( uniformBuffer.visibility & GPUShaderStage.COMPUTE ) {
2211+
2212+
visibilities.push( 'compute' );
2213+
2214+
}
2215+
2216+
const bufferVisibility = `(${visibilities.join( ',' )})`;
2217+
2218+
const bufferGPU = this.device.createBuffer( {
2219+
label: `bindingBuffer${uniformBuffer.id}_${uniformBuffer.name}_${bufferVisibility}`,
2220+
size: byteLength,
2221+
usage: usage
2222+
} );
2223+
2224+
uniformBufferData.buffer = bufferGPU;
2225+
2226+
}
2227+
2228+
}
2229+
2230+
/**
2231+
* Destroys the GPU data for the given uniform buffer.
2232+
*
2233+
* @param {Buffer} uniformBuffer - The uniform buffer.
2234+
*/
2235+
destroyUniformBuffer( uniformBuffer ) {
2236+
2237+
const uniformBufferData = this.get( uniformBuffer );
2238+
2239+
uniformBufferData.buffer.destroy();
2240+
2241+
this.delete( uniformBuffer );
2242+
2243+
}
2244+
21812245
/**
21822246
* Creates bindings from the given bind group definition.
21832247
*

0 commit comments

Comments
 (0)