По суті, тому, що не всі GPU можуть підтримувати виклики функцій - і навіть якщо вони є, функціональні виклики можуть бути досить повільними або мати такі обмеження, як дуже мала глибина стека.
Код шейдера та обчислювальний код GPU можуть виявлятись функціональними викликами в усьому місці, але за звичайних обставин вони на 100% позначаються компілятором. Машинний код, виконаний графічним процесором, містить гілки та петлі, але не викликає функцій. Однак рекурсивні виклики функцій з очевидних причин не можна накреслити. (Якщо деякі аргументи не є константами часу компіляції, таким чином, щоб компілятор міг їх скласти і встроїти все дерево викликів.)
Щоб реалізувати справжні виклики функцій, вам потрібен стек. Здебільшого шейдерний код взагалі не використовує стек - у графічних процесорах є великі регістрові файли, а шейдери можуть постійно зберігати всі свої дані в регістрах. Важко зробити роботу стеку, тому що (а) вам знадобиться багато місця для стеку, щоб забезпечити всі безлічі перетворень, які можуть бути в польоті одночасно, і (b) система пам’яті GPU оптимізована для спільної сумісної роботи транзакцій з пам'яттю для досягнення високої пропускної здатності, але це відбувається за рахунок затримки, тому я гадаю, що операції стеки, такі як збереження / відновлення локальних змінних, були б жахливо повільними.
Історично виклики функціонального рівня на апаратному рівні не були надто корисними для графічного процесора, тому що було доцільніше вкладати все в компілятор. Тож архітектори GPU не зосереджувались на тому, щоб зробити їх швидкими. Ймовірно, можуть бути здійснені різні компроміси, якщо в майбутньому буде попит на ефективні виклики на апаратному рівні, але (як і все, що стосується техніки) це спричинить витрати десь в іншому місці.
Що стосується променевої стрічки, то, як люди зазвичай поводяться з подібними речами, це створюючи черги променів, які знаходяться в процесі відстеження. Замість того, щоб повторюватись, ви додаєте промінь у чергу, а на високому рівні десь ви маєте цикл, який продовжує обробляти, поки всі черги не будуть порожніми. Однак це вимагає значної реорганізації коду візуалізації, якщо ви починаєте з класичного рекурсивного Raytracer. Для отримання додаткової інформації про це можна прочитати документ Wavefront Path Tracing .