fix: 视锥剔除平面归一化(透视因数误剔)+ 材质去重 + 描述符池可增长
- Frustum::FromMatrix 平面归一化:Gribb-Hartmann 提取的 left/right/ bottom/top 法线模长含 1/tan(fov/2) 因子(>1),未归一化时包围球 距离测试被放大,视锥边缘物体被误剔(SunTemple 全场景可见)—— 修正注释:必须传 [0,1] 重映射矩阵 - 材质去重:Model 新增 MaterialCache(按贴图路径共享 Material), Mesh 改持 Material* 非拥有指针。1056 mesh 渲染只需 48 个描述符集 (对齐 UE/Unity 材质实例化思路,大场景第一道闸门) - DescriptorManager 池改可增长分块(chunk=4096,OutOfPool/Fragmented 自动续块):材质集数量不可预估(1G 资产可能上万),固定上限迟早爆
This commit is contained in:
@@ -11,24 +11,32 @@ namespace Engine
|
||||
DescriptorManager::DescriptorManager(Device& device)
|
||||
: m_Device(device)
|
||||
{
|
||||
std::array<vk::DescriptorPoolSize, 3> poolSizes = {
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, kMaxSets),
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, kMaxSets),
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, kMaxSets),
|
||||
};
|
||||
|
||||
vk::DescriptorPoolCreateInfo poolInfo;
|
||||
poolInfo.setMaxSets(kMaxSets)
|
||||
.setPoolSizes(poolSizes)
|
||||
.setFlags(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet);
|
||||
|
||||
m_Pool = m_Device.GetDevice().createDescriptorPool(poolInfo);
|
||||
ENGINE_INFO("DescriptorManager created");
|
||||
m_Pools.push_back(CreateChunk());
|
||||
ENGINE_INFO("DescriptorManager created (growable, chunk = {} sets)",
|
||||
kChunkSets);
|
||||
}
|
||||
|
||||
DescriptorManager::~DescriptorManager()
|
||||
{
|
||||
m_Device.GetDevice().destroyDescriptorPool(m_Pool);
|
||||
for (auto pool : m_Pools) {
|
||||
m_Device.GetDevice().destroyDescriptorPool(pool);
|
||||
}
|
||||
}
|
||||
|
||||
vk::DescriptorPool DescriptorManager::CreateChunk()
|
||||
{
|
||||
std::array<vk::DescriptorPoolSize, 3> poolSizes = {
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, kChunkSets),
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, kChunkSets),
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, kChunkSets),
|
||||
};
|
||||
|
||||
vk::DescriptorPoolCreateInfo poolInfo;
|
||||
poolInfo.setMaxSets(kChunkSets)
|
||||
.setPoolSizes(poolSizes)
|
||||
.setFlags(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet);
|
||||
|
||||
return m_Device.GetDevice().createDescriptorPool(poolInfo);
|
||||
}
|
||||
|
||||
vk::DescriptorSetLayout DescriptorManager::CreateLayout(const std::vector<DescriptorBinding>& bindings)
|
||||
@@ -52,12 +60,24 @@ namespace Engine
|
||||
|
||||
vk::DescriptorSet DescriptorManager::AllocateDescriptorSet(vk::DescriptorSetLayout layout)
|
||||
{
|
||||
vk::DescriptorSetAllocateInfo allocInfo;
|
||||
allocInfo.setDescriptorPool(m_Pool)
|
||||
.setSetLayouts(layout);
|
||||
|
||||
auto sets = m_Device.GetDevice().allocateDescriptorSets(allocInfo);
|
||||
return sets[0];
|
||||
// 从最新块分配;耗尽(OutOfPool/Fragmented)则追加一块重试
|
||||
for (;;) {
|
||||
try {
|
||||
vk::DescriptorSetAllocateInfo allocInfo;
|
||||
allocInfo.setDescriptorPool(m_Pools.back())
|
||||
.setSetLayouts(layout);
|
||||
auto sets = m_Device.GetDevice().allocateDescriptorSets(allocInfo);
|
||||
return sets[0];
|
||||
} catch (const vk::OutOfPoolMemoryError&) {
|
||||
m_Pools.push_back(CreateChunk());
|
||||
ENGINE_INFO("DescriptorManager: pool chunk grown -> {} chunks",
|
||||
m_Pools.size());
|
||||
} catch (const vk::FragmentedPoolError&) {
|
||||
m_Pools.push_back(CreateChunk());
|
||||
ENGINE_INFO("DescriptorManager: pool fragmented, new chunk -> {}",
|
||||
m_Pools.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorManager::UpdateUniformBuffer(vk::DescriptorSet set, u32 binding,
|
||||
|
||||
Reference in New Issue
Block a user