Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove uniform buffer based skinning and batching #6324

Merged
merged 2 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/deprecated/deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,13 @@ Object.defineProperties(Texture.prototype, {
}
});

Object.defineProperty(GraphicsDevice.prototype, 'boneLimit', {
get: function () {
Debug.deprecated('pc.GraphicsDevice#boneLimit is deprecated and the limit has been removed.');
return 1024;
}
});

Object.defineProperty(GraphicsDevice.prototype, 'webgl2', {
get: function () {
Debug.deprecated('pc.GraphicsDevice#webgl2 is deprecated, use pc.GraphicsDevice#isWebGL2 instead.');
Expand Down
34 changes: 0 additions & 34 deletions src/platform/graphics/graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,6 @@ class GraphicsDevice extends EventHandler {
*/
scope;

/**
* The maximum number of supported bones using uniform buffers.
*
* @type {number}
* @readonly
*/
boneLimit;

/**
* The maximum supported texture anisotropy setting.
*
Expand Down Expand Up @@ -827,32 +819,6 @@ class GraphicsDevice extends EventHandler {
return this._deviceType;
}

/**
* Queries the maximum number of bones that can be referenced by a shader. The shader
* generators (programlib) use this number to specify the matrix array size of the uniform
* 'matrix_pose[0]'. The value is calculated based on the number of available uniform vectors
* available after subtracting the number taken by a typical heavyweight shader. If a different
* number is required, it can be tuned via {@link GraphicsDevice#setBoneLimit}.
*
* @returns {number} The maximum number of bones that can be supported by the host hardware.
* @ignore
*/
getBoneLimit() {
return this.boneLimit;
}

/**
* Specifies the maximum number of bones that the device can support on the current hardware.
* This function allows the default calculated value based on available vector uniforms to be
* overridden.
*
* @param {number} maxBones - The maximum number of bones supported by the host hardware.
* @ignore
*/
setBoneLimit(maxBones) {
this.boneLimit = maxBones;
}

startRenderPass(renderPass) {
}

Expand Down
2 changes: 0 additions & 2 deletions src/platform/graphics/null/null-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class NullGraphicsDevice extends GraphicsDevice {
this.maxAnisotropy = 16;
this.supportsUniformBuffers = false;
this.supportsVolumeTextures = true;
this.supportsBoneTextures = true;
this.supportsMorphTargetTexturesCore = true;
this.supportsAreaLights = true;
this.supportsGpuParticles = false;
Expand All @@ -50,7 +49,6 @@ class NullGraphicsDevice extends GraphicsDevice {
this.textureFloatRenderable = true;
this.extTextureHalfFloat = true;
this.textureHalfFloatRenderable = true;
this.boneLimit = 1024;
this.supportsImageBitmap = true;
this.extBlendMinmax = true;
this.areaLightLutFormat = PIXELFORMAT_RGBA8;
Expand Down
19 changes: 0 additions & 19 deletions src/platform/graphics/webgl/webgl-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -711,25 +711,6 @@ class WebglGraphicsDevice extends GraphicsDevice {
gl.uniformMatrix4fv(uniform.locationId, false, value);
};

this.supportsBoneTextures = this.extTextureFloat && this.maxVertexTextures > 0;

// Calculate an estimate of the maximum number of bones that can be uploaded to the GPU
// based on the number of available uniforms and the number of uniforms required for non-
// bone data. This is based off of the Standard shader. A user defined shader may have
// even less space available for bones so this calculated value can be overridden via
// pc.GraphicsDevice.setBoneLimit.
let numUniforms = this.vertexUniformsCount;
numUniforms -= 4 * 4; // Model, view, projection and shadow matrices
numUniforms -= 8; // 8 lights max, each specifying a position vector
numUniforms -= 1; // Eye position
numUniforms -= 4 * 4; // Up to 4 texture transforms
this.boneLimit = Math.floor(numUniforms / 3); // each bone uses 3 uniforms

// Put a limit on the number of supported bones when texture skinning is not supported.
// Some GPUs have demonstrated performance issues if the number of vectors allocated to the
// skin matrix palette is left unbounded
this.boneLimit = Math.min(this.boneLimit, 128);

this.constantTexSource = this.scope.resolve("source");

if (this.extTextureFloat) {
Expand Down
2 changes: 0 additions & 2 deletions src/platform/graphics/webgpu/webgpu-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ class WebgpuGraphicsDevice extends GraphicsDevice {
this.vertexUniformsCount = limits.maxUniformBufferBindingSize / 16;
this.supportsUniformBuffers = true;
this.supportsVolumeTextures = true;
this.supportsBoneTextures = true;
this.supportsMorphTargetTexturesCore = true;
this.supportsAreaLights = true;
this.supportsGpuParticles = true;
Expand All @@ -153,7 +152,6 @@ class WebgpuGraphicsDevice extends GraphicsDevice {
this.textureHalfFloatFilterable = true;
this.extTextureHalfFloat = true;
this.textureHalfFloatRenderable = true;
this.boneLimit = 1024;
this.supportsImageBitmap = true;
this.extBlendMinmax = true;
this.areaLightLutFormat = this.textureFloatFilterable ? PIXELFORMAT_RGBA32F : PIXELFORMAT_RGBA8;
Expand Down
7 changes: 2 additions & 5 deletions src/scene/batching/batch-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ class BatchManager {
prepare(meshInstances, dynamic, maxAabbSize = Number.POSITIVE_INFINITY, translucent) {
if (meshInstances.length === 0) return [];
const halfMaxAabbSize = maxAabbSize * 0.5;
const maxInstanceCount = this.device.supportsBoneTextures ? 1024 : this.device.boneLimit;
const maxInstanceCount = 1024;

// maximum number of vertices that can be used in batch (do this for non-indexed as well,
// as in some cases (UI elements) non-indexed geometry gets batched into indexed)
Expand Down Expand Up @@ -632,10 +632,8 @@ class BatchManager {
// #endif

if (!this._init) {
const boneLimit = '#define BONE_LIMIT ' + this.device.getBoneLimit() + '\n';
this.transformVS = boneLimit + '#define DYNAMICBATCH\n' + shaderChunks.transformVS;
this.transformVS = '#define DYNAMICBATCH\n' + shaderChunks.transformVS;
this.skinTexVS = shaderChunks.skinBatchTexVS;
this.skinConstVS = shaderChunks.skinBatchConstVS;
this.vertexFormats = {};
this._init = true;
}
Expand Down Expand Up @@ -782,7 +780,6 @@ class BatchManager {
material = material.clone();
material.chunks.transformVS = this.transformVS;
material.chunks.skinTexVS = this.skinTexVS;
material.chunks.skinConstVS = this.skinConstVS;
material.update();
}

Expand Down
12 changes: 4 additions & 8 deletions src/scene/renderer/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ class Renderer {
const scope = graphicsDevice.scope;
this.boneTextureId = scope.resolve('texture_poseMap');
this.boneTextureSizeId = scope.resolve('texture_poseMapSize');
this.poseMatrixId = scope.resolve('matrix_pose[0]');

this.modelMatrixId = scope.resolve('matrix_model');
this.normalMatrixId = scope.resolve('matrix_normal');
Expand Down Expand Up @@ -760,13 +759,10 @@ class Renderer {
const skinInstance = meshInstance.skinInstance;
if (skinInstance) {
this._skinDrawCalls++;
if (device.supportsBoneTextures) {
const boneTexture = skinInstance.boneTexture;
this.boneTextureId.setValue(boneTexture);
this.boneTextureSizeId.setValue(skinInstance.boneTextureSize);
} else {
this.poseMatrixId.setValue(skinInstance.matrixPalette);
}

const boneTexture = skinInstance.boneTexture;
this.boneTextureId.setValue(boneTexture);
this.boneTextureSizeId.setValue(skinInstance.boneTextureSize);
}
}

Expand Down
4 changes: 0 additions & 4 deletions src/scene/shader-lib/chunks/chunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,7 @@ import shadowStandardPS from './lit/frag/shadowStandard.js';
import shadowStandardGL2PS from './lit/frag/shadowStandardGL2.js';
import shadowVSM8PS from './lit/frag/shadowVSM8.js';
import shadowVSM_commonPS from './lit/frag/shadowVSM_common.js';
import skinBatchConstVS from './common/vert/skinBatchConst.js';
import skinBatchTexVS from './common/vert/skinBatchTex.js';
import skinConstVS from './common/vert/skinConst.js';
import skinTexVS from './common/vert/skinTex.js';
import skyboxEnvPS from './skybox/frag/skyboxEnv.js';
import skyboxHDRPS from './skybox/frag/skyboxHDR.js';
Expand Down Expand Up @@ -374,9 +372,7 @@ const shaderChunks = {
shadowStandardGL2PS,
shadowVSM8PS,
shadowVSM_commonPS,
skinBatchConstVS,
skinBatchTexVS,
skinConstVS,
skinTexVS,
skyboxEnvPS,
skyboxHDRPS,
Expand Down
20 changes: 0 additions & 20 deletions src/scene/shader-lib/chunks/common/vert/skinBatchConst.js

This file was deleted.

44 changes: 0 additions & 44 deletions src/scene/shader-lib/chunks/common/vert/skinConst.js

This file was deleted.

5 changes: 1 addition & 4 deletions src/scene/shader-lib/programs/shader-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ class ShaderGenerator {
}

static skinCode(device, chunks = shaderChunks) {
if (device.supportsBoneTextures) {
return chunks.skinTexVS;
}
return "#define BONE_LIMIT " + device.getBoneLimit() + "\n" + chunks.skinConstVS;
return chunks.skinTexVS;
}

static fogCode(value, chunks = shaderChunks) {
Expand Down
53 changes: 21 additions & 32 deletions src/scene/skin-instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,32 +56,26 @@ class SkinInstance {

init(device, numBones) {

if (device.supportsBoneTextures) {

// texture size - roughly square that fits all bones, width is multiply of 3 to simplify shader math
const numPixels = numBones * 3;
let width = Math.ceil(Math.sqrt(numPixels));
width = math.roundUp(width, 3);
const height = Math.ceil(numPixels / width);

this.boneTexture = new Texture(device, {
width: width,
height: height,
format: PIXELFORMAT_RGBA32F,
mipmaps: false,
minFilter: FILTER_NEAREST,
magFilter: FILTER_NEAREST,
name: 'skin'
});

this.boneTextureSize = [width, height, 1.0 / width, 1.0 / height];

this.matrixPalette = this.boneTexture.lock({ mode: TEXTURELOCK_READ });
this.boneTexture.unlock();

} else {
this.matrixPalette = new Float32Array(numBones * 12);
}
// texture size - roughly square that fits all bones, width is multiply of 3 to simplify shader math
const numPixels = numBones * 3;
let width = Math.ceil(Math.sqrt(numPixels));
width = math.roundUp(width, 3);
const height = Math.ceil(numPixels / width);

this.boneTexture = new Texture(device, {
width: width,
height: height,
format: PIXELFORMAT_RGBA32F,
mipmaps: false,
minFilter: FILTER_NEAREST,
magFilter: FILTER_NEAREST,
name: 'skin'
});

this.boneTextureSize = [width, height, 1.0 / width, 1.0 / height];

this.matrixPalette = this.boneTexture.lock({ mode: TEXTURELOCK_READ });
this.boneTexture.unlock();
}

destroy() {
Expand Down Expand Up @@ -132,12 +126,7 @@ class SkinInstance {
}

uploadBones(device) {

// TODO: this is a bit strange looking. Change the Texture API to do a reupload
if (device.supportsBoneTextures) {
this.boneTexture.lock();
this.boneTexture.unlock();
}
this.boneTexture.upload();
}

_updateMatrices(rootNode, skinUpdateIndex) {
Expand Down