错误: Thread group count is above the maximum allowed limit. Maximum allowed thread group count is 65535.
GPU 硬件限制:
- X, Y, Z 每个维度最多 65535 个线程组
- 这是 DirectX 11 的硬件限制
- 不能超过,否则 Dispatch 失败
// allocationRequestCount 可能是 16384+ (32*32*16 页面)
allocatePagesShader.Dispatch(allocKernel,
Mathf.CeilToInt(allocationRequestCount / 64.0f), 1, 1);
// 计算: 16384 / 64 = 256 线程组 ✅
// 但如果所有页面都请求: 32*32*16 / 64 = 256 ✅等等,让我重新计算...实际上问题可能是 buffer 读取错误导致 count 值异常大。
clearPagesShader.Dispatch(clearKernel,
Mathf.CeilToInt(VSMConstants.PAGE_SIZE / 8.0f), // 128/8 = 16
Mathf.CeilToInt(VSMConstants.PAGE_SIZE / 8.0f), // 128/8 = 16
(int)allocationRequestCount); // 可能 > 65535!int fillThreadGroups = Mathf.CeilToInt(VSMConstants.MAX_PHYSICAL_PAGES / 64.0f);
fillThreadGroups = Mathf.Min(fillThreadGroups, 65535); // 限制
allocatePagesShader.Dispatch(fillKernel, fillThreadGroups, 1, 1);int threadGroups = Mathf.CeilToInt(allocationRequestCount / 64.0f);
threadGroups = Mathf.Min(threadGroups, 65535); // 限制
allocatePagesShader.Dispatch(allocKernel, threadGroups, 1, 1);int zGroups = (int)Mathf.Min(allocationRequestCount, 65535); // 限制
clearPagesShader.Dispatch(clearKernel,
Mathf.CeilToInt(VSMConstants.PAGE_SIZE / 8.0f),
Mathf.CeilToInt(VSMConstants.PAGE_SIZE / 8.0f),
zGroups);| 平台 | X 最大 | Y 最大 | Z 最大 | 总最大 |
|---|---|---|---|---|
| DX11 | 65535 | 65535 | 65535 | - |
| DX12 | 65535 | 65535 | 65535 | - |
| Vulkan | 65535 | 65535 | 65535 | - |
| OpenGL | 65535 | 65535 | 65535 | - |
注意: 这是线程组数,不是线程数!
- 每个线程组可以有多个线程 (如 [numthreads(8,8,1)] = 64 线程/组)
- 总线程数 = 线程组数 × 每组线程数
ComputeBuffer.CopyCount(pageTable.AllocationRequests, allocationCounterBuffer, 0);
uint[] counts = new uint[2];
allocationCounterBuffer.GetData(counts);
uint allocationRequestCount = counts[0]; // 可能读到错误值如果 AllocationRequests 是 Append buffer,CopyCount 应该正确。但如果 buffer 类型不匹配,可能读到垃圾数据。
如果初始化时所有虚拟页面都被标记为需要分配:
- 32×32 页表 × 16 级联 = 16,384 页面
- 如果 shader 错误地全部标记,会产生大量请求
添加调试输出:
Debug.Log($"Allocation Request Count: {allocationRequestCount}");
Debug.Log($"Thread Groups: {threadGroups}");- 首帧: 几百到几千个页面请求
- 后续帧: 几十到几百个 (只有变动的页面)
-
10,000: 太多页面被标记
-
100,000: Buffer 读取错误
添加 65535 限制后:
- ✅ 不会崩溃
⚠️ 但如果真的有 > 65535 个请求,只处理前 65535 个⚠️ 可能导致部分阴影缺失
更好的解决方案: 分批处理:
while (remaining > 0) {
int batchSize = Mathf.Min(remaining, 65535);
shader.Dispatch(..., batchSize, 1, 1);
remaining -= batchSize;
}但目前的简单限制足够用于测试! 🎯