Skip to content

Commit

Permalink
fixed #17593: [v3.8.6] 2D Particle crash on native platforms.
Browse files Browse the repository at this point in the history
Batcher2D may use destroyed Material whose passes is empty, which will cause 'curdrawBatch->getPasses().at(0);' vector visit overflow.
  • Loading branch information
dumganhar committed Dec 21, 2024
1 parent ca29ce0 commit 8f82630
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 14 deletions.
3 changes: 3 additions & 0 deletions cocos/misc/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ export class Renderer extends Component {
if (material && material instanceof MaterialInstance) {
errorID(12012);
}

if (this._materials[index] === material) return;

this._materials[index] = material;
const inst = this._materialInstances[index];
if (inst) {
Expand Down
30 changes: 16 additions & 14 deletions native/cocos/2d/renderer/Batcher2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ void Batcher2d::generateBatch(RenderEntity* entity, RenderDrawInfo* drawInfo) {
return;
}
gfx::InputAssembler* ia = nullptr;

uint32_t indexOffset = 0;
uint32_t indexCount = 0;
if (drawInfo->getIsMeshBuffer()) {
Expand All @@ -345,9 +345,9 @@ void Batcher2d::generateBatch(RenderEntity* entity, RenderDrawInfo* drawInfo) {
_meshRenderDrawInfo.emplace_back(drawInfo);
} else {
UIMeshBuffer* currMeshBuffer = drawInfo->getMeshBuffer();

currMeshBuffer->setDirty(true);

ia = currMeshBuffer->requireFreeIA(getDevice());
indexCount = currMeshBuffer->getIndexOffset() - _indexStart;
if (ia == nullptr) {
Expand All @@ -356,31 +356,33 @@ void Batcher2d::generateBatch(RenderEntity* entity, RenderDrawInfo* drawInfo) {
indexOffset = _indexStart;
_indexStart = currMeshBuffer->getIndexOffset();
}

_currMeshBuffer = nullptr;

// stencilStage
gfx::DepthStencilState* depthStencil = nullptr;
ccstd::hash_t dssHash = 0;
StencilStage entityStage = entity->getEnumStencilStage();
depthStencil = _stencilManager->getDepthStencilState(entityStage, _currMaterial);
dssHash = _stencilManager->getStencilHash(entityStage);

auto* curdrawBatch = _drawBatchPool.alloc();
curdrawBatch->setVisFlags(_currLayer);
curdrawBatch->setInputAssembler(ia);
curdrawBatch->setFirstIndex(indexOffset);
curdrawBatch->setIndexCount(indexCount);
curdrawBatch->fillPass(_currMaterial, depthStencil, dssHash);
const auto& pass = curdrawBatch->getPasses().at(0);

if (entity->getUseLocal()) {
drawInfo->updateLocalDescriptorSet(entity->getRenderTransform(), pass->getLocalSetLayout());
curdrawBatch->setDescriptorSet(drawInfo->getLocalDes());
} else {
curdrawBatch->setDescriptorSet(getDescriptorSet(_currTexture, _currSampler, pass->getLocalSetLayout()));
const auto &passes = curdrawBatch->getPasses();
if (!passes.empty())
const auto& pass = passes.at(0);
if (entity->getUseLocal()) {
drawInfo->updateLocalDescriptorSet(entity->getRenderTransform(), pass->getLocalSetLayout());
curdrawBatch->setDescriptorSet(drawInfo->getLocalDes());
} else {
curdrawBatch->setDescriptorSet(getDescriptorSet(_currTexture, _currSampler, pass->getLocalSetLayout()));
}
_batches.push_back(curdrawBatch);
}
_batches.push_back(curdrawBatch);
}

void Batcher2d::generateBatchForMiddleware(RenderEntity* entity, RenderDrawInfo* drawInfo) {
Expand Down

0 comments on commit 8f82630

Please sign in to comment.