Skip to content

Commit

Permalink
fis native skinning model with realtime-texture mode (cocos#45)
Browse files Browse the repository at this point in the history
Co-authored-by: zhakesi <zhakesi@foxmail.com>
  • Loading branch information
zhakesi and zhakesi authored Jun 22, 2022
1 parent 994512f commit 5309dc2
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 49 deletions.
28 changes: 7 additions & 21 deletions cocos/3d/models/skinning-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class SkinningModel extends MorphModel {
private _joints: IJointInfo[] = [];
private _bufferIndices: number[] | null = null;
private _realTimeJointTexture = new RealTimeJointTexture();
private _realTimeTextureModel = false;
private _realTimeTextureMode = false;
constructor () {
super();
this.type = ModelType.SKINNING;
Expand Down Expand Up @@ -142,7 +142,6 @@ export class SkinningModel extends MorphModel {
const jointMaps = mesh.struct.jointMaps;
this._ensureEnoughBuffers(jointMaps && jointMaps.length || 1, skeleton.joints.length);
this._bufferIndices = mesh.jointBufferIndices;
const nativeJoints: NativeJointInfo[] = [];
this._initRealTimeJointTexture(skeleton.joints.length);
for (let index = 0; index < skeleton.joints.length; index++) {
const bound = boneSpaceBounds[index];
Expand Down Expand Up @@ -204,7 +203,7 @@ export class SkinningModel extends MorphModel {
uploadJointData(this._dataArray[buffers[b]], indices[b] * 12, m4_1, i === 0);
}
}
if (this._realTimeTextureModel === false) {
if (this._realTimeTextureMode === false) {
for (let b = 0; b < this._buffers.length; b++) {
this._buffers[b].update(this._dataArray[b]);
}
Expand Down Expand Up @@ -233,7 +232,7 @@ export class SkinningModel extends MorphModel {
public getMacroPatches (subModelIndex: number): IMacroPatch[] | null {
const superMacroPatches = super.getMacroPatches(subModelIndex);
let myPatches = uniformPatches;
if (this._realTimeTextureModel) {
if (this._realTimeTextureMode) {
myPatches = texturePatches;
}
if (superMacroPatches) {
Expand All @@ -247,11 +246,6 @@ export class SkinningModel extends MorphModel {
*/
public _updateLocalDescriptors (submodelIdx: number, descriptorSet: DescriptorSet) {
super._updateLocalDescriptors(submodelIdx, descriptorSet);
// TODO implementation directly in native SkinningModel
// if (JSB) {
// (this._nativeObj! as NativeSkinningModel).updateLocalDescriptors(submodelIdx, descriptorSet);
// return;
// }
const idx = this._bufferIndices![submodelIdx];
const buffer = this._buffers[idx];
if (buffer) { descriptorSet.bindBuffer(UBOSkinning.BINDING, buffer); }
Expand Down Expand Up @@ -287,9 +281,9 @@ export class SkinningModel extends MorphModel {
}
private _initRealTimeJointTexture (jointCount: number) {
if (UBOSkinning.JOINT_UNIFORM_CAPACITY < jointCount) {
this._realTimeTextureModel = true;
this._realTimeTextureMode = true;
}
if (!this._realTimeTextureModel) return;
if (!this._realTimeTextureMode) return;

const gfxDevice = director.root!.device;
let width = RealTimeJointTexture.WIDTH;
Expand Down Expand Up @@ -321,18 +315,10 @@ export class SkinningModel extends MorphModel {
texture.image = image;
textures[i] = texture;
}
// TODO implementation directly in native SkinningModel
// if (JSB) {
// const gfxTextures: Texture[] = [];
// for (let i = 0; i < textures.length; i++) {
// gfxTextures.push(textures[i].getGFXTexture()!);
// }
// (this._nativeObj! as NativeSkinningModel).setRealTimeJointTextures(gfxTextures);
// }
}

private _bindRealTimeJointTexture (idx: number, descriptorSet: DescriptorSet) {
if (!this._realTimeTextureModel) return;
if (!this._realTimeTextureMode) return;
const jointTexture = this._realTimeJointTexture._textures[idx];
if (jointTexture) {
const gfxTexture = jointTexture.getGFXTexture();
Expand All @@ -343,7 +329,7 @@ export class SkinningModel extends MorphModel {
}

private _updateRealTimeJointTextureBuffer () {
if (!this._realTimeTextureModel) return;
if (!this._realTimeTextureMode) return;
const textures = this._realTimeJointTexture._textures;
const buffers = this._realTimeJointTexture._buffers;
for (let idx = 0; idx < textures.length; idx++) {
Expand Down
4 changes: 2 additions & 2 deletions native/cocos/3d/models/BakedSkinningModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ void BakedSkinningModel::bindSkeleton(Skeleton *skeleton, Node *skinningRoot, Me
_jointMedium.buffer = _device->createBuffer({
gfx::BufferUsageBit::UNIFORM | gfx::BufferUsageBit::TRANSFER_DST,
gfx::MemoryUsageBit::DEVICE,
pipeline::UBOSkinning::SIZE,
pipeline::UBOSkinning::SIZE,
pipeline::UBOSkinning::size,
pipeline::UBOSkinning::size,
});
}
}
Expand Down
65 changes: 50 additions & 15 deletions native/cocos/3d/models/SkinningModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ void getRelevantBuffers(ccstd::vector<index_t> &outIndices, ccstd::vector<int32_
}
}

ccstd::vector<cc::scene::IMacroPatch> myPatches{{"CC_USE_SKINNING", true}};
ccstd::vector<cc::scene::IMacroPatch> uniformPatches{{"CC_USE_SKINNING", true}, {"CC_USE_REAL_TIME_JOINT_TEXTURE", false}};
ccstd::vector<cc::scene::IMacroPatch> texturePatches{{"CC_USE_SKINNING", true}, {"CC_USE_REAL_TIME_JOINT_TEXTURE", true}};

} // namespace
namespace cc {
Expand Down Expand Up @@ -95,7 +96,7 @@ void SkinningModel::bindSkeleton(Skeleton *skeleton, Node *skinningRoot, Mesh *m
const auto &jointMaps = mesh->getStruct().jointMaps;
ensureEnoughBuffers((jointMaps.has_value() && !jointMaps->empty()) ? static_cast<int32_t>(jointMaps->size()) : 1);
_bufferIndices = mesh->getJointBufferIndices();

initRealTimeJointTexture(skeleton->getJoints().size());
for (index_t index = 0; index < skeleton->getJoints().size(); ++index) {
geometry::AABB *bound = boneSpaceBounds[index];
auto *target = skinningRoot->getChildByPath(skeleton->getJoints()[index]);
Expand Down Expand Up @@ -183,6 +184,10 @@ void SkinningModel::initSubModel(index_t idx, RenderingSubMesh *subMeshData, Mat

ccstd::vector<scene::IMacroPatch> SkinningModel::getMacroPatches(index_t subModelIndex) {
auto patches = Super::getMacroPatches(subModelIndex);
auto myPatches = uniformPatches;
if (_realTimeTextureMode) {
myPatches = texturePatches;
}
if (!patches.empty()) {
patches.reserve(myPatches.size() + patches.size());
patches.insert(std::begin(patches), std::begin(myPatches), std::end(myPatches));
Expand All @@ -201,13 +206,14 @@ void SkinningModel::uploadJointData(uint32_t base, const Mat4 &mat, float *dst)

void SkinningModel::updateLocalDescriptors(index_t submodelIdx, gfx::DescriptorSet *descriptorset) {
Super::updateLocalDescriptors(submodelIdx, descriptorset);
gfx::Buffer *buffer = _buffers[_bufferIndices[submodelIdx]];
uint32_t idx = _bufferIndices[submodelIdx];
gfx::Buffer *buffer = _buffers[idx];
if (buffer) {
descriptorset->bindBuffer(pipeline::UBOSkinning::BINDING, buffer);
}
if (!_realTimeTextureMode) return;
if (_realTimeJointTexture->textures.size() < idx + 1) return;
gfx::Texture *texture = _realTimeJointTexture->textures[idx];
gfx::Texture* texture = _realTimeJointTexture->textures[idx];
if (texture) {
gfx::SamplerInfo info{
gfx::Filter::POINT,
Expand Down Expand Up @@ -249,6 +255,10 @@ void SkinningModel::ensureEnoughBuffers(index_t count) {
}

if (i >= _dataArray.size()) {
for (auto i = 0; i < _dataArray.size(); i++) {
delete[] _dataArray[i];
_dataArray[i] = nullptr;
}
_dataArray.resize(i + 1);
}

Expand All @@ -259,19 +269,42 @@ void SkinningModel::ensureEnoughBuffers(index_t count) {
}
}

void SkinningModel::setRealTimeJointTextures(std::vector<gfx::Texture *> textures) {
if (textures.empty()) return;
_realTimeTextureMode = true;
_realTimeJointTexture = new RealTimeJointTexture();
void SkinningModel::initRealTimeJointTexture(index_t jointCount)
{
if (_realTimeJointTexture) {
delete _realTimeJointTexture;
_realTimeJointTexture = nullptr;
}
if (pipeline::SkinningJointCapacity::jointUniformCapacity < jointCount) {
_realTimeTextureMode = true;
}
if (!_realTimeTextureMode) return;
_realTimeJointTexture = new RealTimeJointTexture;
auto *device = gfx::Device::getInstance();
uint32_t texWidth = RealTimeJointTexture::WIDTH;
uint32_t texHeight = RealTimeJointTexture::HEIGHT;
gfx::Format textureFormat = gfx::Format::RGBA32F;

gfx::FormatFeature formatFeature = device->getFormatFeatures(gfx::Format::RGBA32F);
if (!(formatFeature & gfx::FormatFeature::SAMPLED_TEXTURE)) {
textureFormat = gfx::Format::RGBA8;
texWidth = 4 * RealTimeJointTexture::WIDTH;
}
uint32_t length = 4 * RealTimeJointTexture::WIDTH * RealTimeJointTexture::HEIGHT;
size_t count = _dataArray.size();
const size_t count = _dataArray.size();
for (size_t i = 0; i < count; i++) {
delete[] _dataArray[i];
_dataArray[i] = new float[length];
memset(_dataArray[i], 0, sizeof(float) * length);
}
delete[] _dataArray[i];
_dataArray[i] = new float[length];
memset(_dataArray[i], 0, sizeof(float) * length);

_realTimeJointTexture->textures = std::move(textures);
gfx::TextureInfo textureInfo;
textureInfo.width = texWidth;
textureInfo.height = texHeight;
textureInfo.usage = gfx::TextureUsageBit::STORAGE | gfx::TextureUsageBit::SAMPLED | gfx::TextureUsageBit::TRANSFER_SRC | gfx::TextureUsageBit::TRANSFER_DST;
textureInfo.format = textureFormat;
IntrusivePtr<gfx::Texture> texture = device->createTexture(textureInfo);
_realTimeJointTexture->textures.push_back(texture);
}
_realTimeJointTexture->buffer = new float[length];
}

Expand All @@ -280,7 +313,7 @@ void SkinningModel::updateRealTimeJointTextureBuffer()
uint32_t bIdx = 0;
uint32_t width = RealTimeJointTexture::WIDTH;
uint32_t height = RealTimeJointTexture::HEIGHT;
for (gfx::Texture* texture: _realTimeJointTexture->textures) {
for (IntrusivePtr<gfx::Texture> texture : _realTimeJointTexture->textures) {
auto *buffer = _realTimeJointTexture->buffer;
auto *src = _dataArray[bIdx];
uint32_t count = width;
Expand All @@ -303,10 +336,12 @@ void SkinningModel::updateRealTimeJointTextureBuffer()
buffer[index0++] = src[index1++];
buffer[index0++] = src[index1++];
}
uint32_t buffOffset = 0;
cc::gfx::TextureSubresLayers layer;
cc::gfx::Offset texOffset;
cc::gfx::Extent extent = {width, height, 1};
cc::gfx::BufferTextureCopy region = {
buffOffset,
width,
height,
texOffset,
Expand Down
4 changes: 2 additions & 2 deletions native/cocos/3d/models/SkinningModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class SkinningModel final : public MorphModel {
void updateLocalDescriptors(index_t submodelIdx, gfx::DescriptorSet *descriptorset) override;
void updateTransform(uint32_t stamp) override;
void updateUBOs(uint32_t stamp) override;
void setRealTimeJointTextures(std::vector<gfx::Texture *> textures);
void destroy() override;

void initSubModel(index_t idx, RenderingSubMesh *subMeshData, Material *mat) override;
Expand All @@ -70,13 +69,14 @@ class SkinningModel final : public MorphModel {
static void uploadJointData(uint32_t base, const Mat4 &mat, float *dst);
void ensureEnoughBuffers(index_t count);
void updateRealTimeJointTextureBuffer();
void initRealTimeJointTexture(index_t count);

ccstd::vector<index_t> _bufferIndices;
ccstd::vector<IntrusivePtr<gfx::Buffer>> _buffers;
ccstd::vector<JointInfo> _joints;
ccstd::vector<float *> _dataArray;
bool _realTimeTextureMode = false;
RealTimeJointTexture *_realTimeJointTexture;
RealTimeJointTexture *_realTimeJointTexture = nullptr;

CC_DISALLOW_COPY_MOVE_ASSIGN(SkinningModel);
};
Expand Down
6 changes: 4 additions & 2 deletions native/cocos/core/animation/SkeletalAnimationUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "base/Ptr.h"
#include "base/RefCounted.h"
#include "math/Mat4.h"
#include "renderer/gfx-base/GFXTexture.h"

namespace cc {

Expand All @@ -49,12 +50,13 @@ class RealTimeJointTexture {

~RealTimeJointTexture() {
textures.clear();
delete buffer;
delete[] buffer;
buffer = nullptr;
}

static const uint32_t WIDTH = 256;
static const uint32_t HEIGHT = 3;
std::vector<gfx::Texture *> textures;
std::vector<IntrusivePtr<gfx::Texture>> textures;
float *buffer = nullptr;
};

Expand Down
5 changes: 3 additions & 2 deletions native/cocos/renderer/pipeline/Define.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ const gfx::UniformBlock UBOSkinningAnimation::LAYOUT = {
};

uint SkinningJointCapacity::jointUniformCapacity = 0;

uint32_t UBOSkinning::count = 0;
uint32_t UBOSkinning::size = 0;
const ccstd::string UBOSkinning::NAME = "CCSkinning";
const gfx::DescriptorSetLayoutBinding UBOSkinning::DESCRIPTOR = {
UBOSkinning::BINDING,
Expand Down Expand Up @@ -409,7 +410,7 @@ const gfx::UniformSamplerTexture JOINTTEXTURE::LAYOUT = {
1,
};

const ccstd::string REALTIMEJOINTTEXTURE::NAME = "cc_realTimeJoint";
const ccstd::string REALTIMEJOINTTEXTURE::NAME = "cc_realtimeJoint";
const gfx::DescriptorSetLayoutBinding REALTIMEJOINTTEXTURE::DESCRIPTOR = {
REALTIMEJOINTTEXTURE::BINDING,
gfx::DescriptorType::SAMPLER_TEXTURE,
Expand Down
10 changes: 5 additions & 5 deletions native/cocos/renderer/pipeline/Define.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,11 +344,11 @@ struct CC_DLL UBOSkinningAnimation {
};

struct CC_DLL UBOSkinning {
static uint32_t count = 0;
static uint32_t size = 0;
static uint32_t count;
static uint32_t size;
static constexpr uint32_t BINDING = static_cast<uint32_t>(ModelLocalBindings::UBO_SKINNING_TEXTURE);
static const gfx::DescriptorSetLayoutBinding DESCRIPTOR;
static const gfx::UniformBlock layout;
static gfx::UniformBlock layout;
static const ccstd::string NAME;
static void initLayout (uint capacity);
};
Expand Down Expand Up @@ -557,11 +557,11 @@ struct CC_DLL JOINTTEXTURE {
static const ccstd::string NAME;
};

struct CC_DLL REALTIMEJOINTTEXTURE : public Object {
struct CC_DLL REALTIMEJOINTTEXTURE {
static constexpr uint BINDING = static_cast<uint>(ModelLocalBindings::SAMPLER_JOINTS);
static const gfx::DescriptorSetLayoutBinding DESCRIPTOR;
static const gfx::UniformSamplerTexture LAYOUT;
static const String NAME;
static const ccstd::string NAME;
};

struct CC_DLL POSITIONMORPH {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ void GlobalDSManager::activate(gfx::Device *device) {
gfx::Address::CLAMP,
});

//tips: for compatibility with old version, when maxVertexUniformVectors is 128, maxJoints = 30
uint maxJoints = (_device->getCapabilities().maxVertexUniformVectors - 38) / 3;
maxJoints = maxJoints < 256 ? maxJoints : 256;
SkinningJointCapacity::jointUniformCapacity = maxJoints;
Expand Down

0 comments on commit 5309dc2

Please sign in to comment.