diff --git a/native/cocos/bindings/manual/jsb_scene_manual.cpp b/native/cocos/bindings/manual/jsb_scene_manual.cpp index e421a81c0b1..4dba7ef5ffc 100644 --- a/native/cocos/bindings/manual/jsb_scene_manual.cpp +++ b/native/cocos/bindings/manual/jsb_scene_manual.cpp @@ -696,7 +696,7 @@ static bool js_Model_setInstancedAttribute(se::State &s) // NOLINT(readability-i pData[i] = dataVal.toFloat(); } - cobj->setInstancedAttribute(name, pData, len * sizeof(float)); + cobj->setInstancedAttribute(name, pData, len); if (needFree) { CC_FREE(pData); @@ -709,9 +709,9 @@ static bool js_Model_setInstancedAttribute(se::State &s) // NOLINT(readability-i switch (type) { case se::Object::TypedArrayType::FLOAT32: { uint8_t *data = nullptr; - size_t byteLength = 0; - if (val.toObject()->getTypedArrayData(&data, &byteLength) && data != nullptr && byteLength > 0) { - cobj->setInstancedAttribute(name, reinterpret_cast(data), static_cast(byteLength)); + size_t byteCount = 0; + if (val.toObject()->getTypedArrayData(&data, &byteCount) && data != nullptr && byteCount > 0) { + cobj->setInstancedAttribute(name, reinterpret_cast(data), static_cast(byteCount)); } } break; diff --git a/native/cocos/scene/Model.cpp b/native/cocos/scene/Model.cpp index c5cfe23c18a..1d88206711e 100644 --- a/native/cocos/scene/Model.cpp +++ b/native/cocos/scene/Model.cpp @@ -707,9 +707,9 @@ void Model::updateReflectionProbeId() { _localDataUpdated = true; } -void Model::setInstancedAttribute(const ccstd::string &name, const float *value, uint32_t byteLength) { +void Model::setInstancedAttribute(const ccstd::string &name, const float *value, uint32_t byteCount) { for (const auto &subModel : _subModels) { - subModel->setInstancedAttribute(name, value, byteLength); + subModel->setInstancedAttribute(name, value, byteCount); } } void Model::setReflectionProbeType(UseReflectionProbeType val) { diff --git a/native/cocos/scene/Model.h b/native/cocos/scene/Model.h index 5a77d27a549..015a3ace526 100644 --- a/native/cocos/scene/Model.h +++ b/native/cocos/scene/Model.h @@ -135,7 +135,7 @@ class Model : public RefCounted { void onMacroPatchesStateChanged(); void onGeometryChanged(); void setSubModelMesh(index_t idx, RenderingSubMesh *subMesh) const; - void setInstancedAttribute(const ccstd::string &name, const float *value, uint32_t byteLength); + void setInstancedAttribute(const ccstd::string &name, const float *value, uint32_t byteCount); void updateWorldBound(); void updateWorldBoundsForJSSkinningModel(const Vec3 &min, const Vec3 &max); void updateWorldBoundsForJSBakedSkinningModel(geometry::AABB *aabb); diff --git a/native/cocos/scene/SubModel.cpp b/native/cocos/scene/SubModel.cpp index e244b169319..fab9bb1961e 100644 --- a/native/cocos/scene/SubModel.cpp +++ b/native/cocos/scene/SubModel.cpp @@ -362,7 +362,48 @@ void SubModel::setSubMesh(RenderingSubMesh *subMesh) { _subMesh = subMesh; } -void SubModel::setInstancedAttribute(const ccstd::string &name, const float *value, uint32_t byteLength) { +template +void copyInstancedData(const T& view, const float* value, uint32_t byteCount) { + auto* dstData = view.buffer()->getData() + view.byteOffset(); + uint32_t bLength; + if constexpr (std::is_same_v) { + bLength = byteCount * sizeof(float_t); + } else if constexpr (std::is_same_v) { + bLength = byteCount * sizeof(uint16_t); + } else if constexpr (std::is_same_v) { + bLength = byteCount * sizeof(int16_t); + } else if constexpr (std::is_same_v) { + bLength = byteCount * sizeof(uint32_t); + } else if constexpr (std::is_same_v) { + bLength = byteCount * sizeof(int32_t); + } else if constexpr (std::is_same_v) { + bLength = byteCount * sizeof(uint8_t); + } else if constexpr (std::is_same_v) { + bLength = byteCount * sizeof(int8_t); + } + CC_ASSERT(bLength <= view.byteLength()); + memcpy(dstData, value, bLength); +} + +void handleTypedArray(const cc::TypedArray& view, const float* value, uint32_t byteCount) { + if (ccstd::holds_alternative(view)) { + copyInstancedData(ccstd::get(view), value, byteCount); + } else if (ccstd::holds_alternative(view)) { + copyInstancedData(ccstd::get(view), value, byteCount); + } else if (ccstd::holds_alternative(view)) { + copyInstancedData(ccstd::get(view), value, byteCount); + } else if (ccstd::holds_alternative(view)) { + copyInstancedData(ccstd::get(view), value, byteCount); + } else if (ccstd::holds_alternative(view)) { + copyInstancedData(ccstd::get(view), value, byteCount); + } else if (ccstd::holds_alternative(view)) { + copyInstancedData(ccstd::get(view), value, byteCount); + } else if (ccstd::holds_alternative(view)) { + copyInstancedData(ccstd::get(view), value, byteCount); + } +} + +void SubModel::setInstancedAttribute(const ccstd::string &name, const float *value, uint32_t byteCount) { const auto &attributes = _instancedAttributeBlock.attributes; auto &views = _instancedAttributeBlock.views; for (size_t i = 0, len = attributes.size(); i < len; ++i) { @@ -370,22 +411,17 @@ void SubModel::setInstancedAttribute(const ccstd::string &name, const float *val if (attribute.name == name) { const auto &info = gfx::GFX_FORMAT_INFOS[static_cast(attribute.format)]; switch (info.type) { - case gfx::FormatType::NONE: case gfx::FormatType::UNORM: case gfx::FormatType::SNORM: case gfx::FormatType::UINT: - case gfx::FormatType::INT: { - CC_ABORT(); - } break; + case gfx::FormatType::INT: case gfx::FormatType::FLOAT: case gfx::FormatType::UFLOAT: { - CC_ASSERT(ccstd::holds_alternative(views[i])); - auto &view = ccstd::get(views[i]); - auto *dstData = reinterpret_cast(view.buffer()->getData() + view.byteOffset()); - CC_ASSERT(byteLength <= view.byteLength()); - memcpy(dstData, value, byteLength); + handleTypedArray(views[i], value, byteCount); } break; + case gfx::FormatType::NONE: default: + CC_ABORT(); break; } } diff --git a/native/cocos/scene/SubModel.h b/native/cocos/scene/SubModel.h index f92d9fffee4..a8e595f4d3b 100644 --- a/native/cocos/scene/SubModel.h +++ b/native/cocos/scene/SubModel.h @@ -66,7 +66,7 @@ class SubModel : public RefCounted { void setSubMesh(RenderingSubMesh *subMesh); inline void setInstancedWorldMatrixIndex(int32_t worldMatrixIndex) { _instancedWorldMatrixIndex = worldMatrixIndex; } inline void setInstancedSHIndex(int32_t index) { _instancedSHIndex = index; } - void setInstancedAttribute(const ccstd::string &name, const float *value, uint32_t byteLength); + void setInstancedAttribute(const ccstd::string &name, const float *value, uint32_t byteCount); inline gfx::DescriptorSet *getDescriptorSet() const { return _descriptorSet; } inline gfx::DescriptorSet *getWorldBoundDescriptorSet() const { return _worldBoundDescriptorSet; }