Я полагаю, что вы ошиблись в отношении между threadGroups в вашем вызове Dispatch()
и [numthreads()]
в спецификации вашего ядра.
Результат shader.Dispatch(kernelHandle, vertices.Length, 1, 1);
в сочетании с [numthreads(32,1,1)]
не является«многие группы потоков все с одним потоком», это vertices.Length
группы потоков, все с 32 потоками.
Таким образом, ваше ядро будет вызываться 32*vertices.Length
раз, при этом id.x
будет соразмерно расти ...вы получите правильный результат с кодом из вашего комментария, потому что что бы ни происходило, когда вы пытаетесь читать и писать vertex[id.x]
после того, как id.x
вышло за пределы, это не меняет того факта, что к тому времени вы уже вычислили всеправильные результаты и сохранили их в соответствующем месте.
Что нужно сделать , тогда, чтобы не тратить время, установите threadGroupsX в вашем Dispatch()
в ceil(vertices.Length/32)
(псевдокод).
Вы также можете добавить что-то вроде
if (id.x >= vertexLength) return;
в свое ядро (потому что если у вас не будет кратного 32 вершин, некоторые потоки будут выходить за пределы) ..но на самом деле это, вероятно, не поможет ни с точки зрения производительности, ни с точки зрения безопасности;чтение и запись за пределами вершин. Длина будет по существу бездействующей, в то время как дополнительное ветвление в ядре может повлечь за собой затраты.Я полагаю, что в данном случае это, вероятно, незначительно, и, возможно, такое утверждение может сделать логику более понятной для читателей ... но это действительно означает дополнительный шаблон передачи дополнительной униформы.
Кстати, вы также можете использовать ASyncGPUReadbackRequest
, чтобы избежать остановки вашего кода на vertex.GetData(vertices);
, если это имеет смысл в вашем приложении.Вы могли бы написать это так в вопросе краткости (что, как вы можете заметить, не всегда является моей сильной стороной).