Посмотрел еще киберпанк, там от дальних источниках вообще нет спекуляра. А от рекламных щитов аж 2 света - отражение по SSR/RTX и лайт проба как точечный источник.
В RTX отражениях на слишком дифузных поверхностях свет накапливается очень долго, а вдвижении шумный.
В общем думаю смогу сделать намного лучше и быстрее, если заранее пометить большие отражающие поверхности (обычно их 1-2).
innuendo
> Кад делаешь .... Очень интересно
Как здесь (glsl/vulkan) можно грамотно обойтись без while, который, естественно, напрочь всё лочит зараза... Поставил пока что тройную проверку, ну типа если уж с третьего раза не получилось - тогда пока...
uint index = atomicCompSwap(selBuffer[customIndex].counter, 0, 0xffffffff); if( index == 0) { index = atomicAdd( selBuffer[0].counter, 1) + 1; atomicExchange( selBuffer[customIndex].counter, index); } else { //while(index == 0xffffffff) // index = atomicAdd(selBuffer[customIndex].counter, 0); if ( index == 0xffffffff) index = atomicAdd( selBuffer[customIndex].counter, 0); if ( index == 0xffffffff) index = atomicAdd( selBuffer[customIndex].counter, 0); if ( index == 0xffffffff) return; }
смысл в чём, в первой строчке я блокирую поле, выставляя туда что угодно кроме ноля (0xffffffff), потом выставляю этому полю нормальный индекс (если он до этого не был выставлен и был нулём), ну а если он не ноль уже был, тогда пытаюсь его прочитать, но засада в том, что в это время там может быть ещё 0xffffffff...
THE_MASTER
> Как грамотно обойтись без while
uint index = atomicCompSwap(selBuffer[customIndex].counter, 0, 0xffffffff); if(index == 0) { // Мы получили блокировку index = atomicAdd(selBuffer[0].counter, 1) + 1; atomicExchange(selBuffer[customIndex].counter, index); } else { // Читаем значение с барьером index = atomicAdd(selBuffer[customIndex].counter, 0); if(index == 0xffffffff) { // Если всё ещё заблокировано, читаем ещё раз (максимум 3 попытки) for(int i = 0; i < 2; i++) { memoryBarrier(); index = atomicAdd(selBuffer[customIndex].counter, 0); if(index != 0xffffffff) break; } if(index == 0xffffffff) return; } }
std::variant
> uint index = atomicCompSwap(selBuffer[customIndex].counter, 0, 0xffffffff);
> if(index == 0) {
> // Мы получили блокировку
> index = atomicAdd(selBuffer[0].counter, 1) + 1;
> atomicExchange(selBuffer[customIndex].counter, index);
В этом месте как минимум две инструкции, которые дважды во времени обращаются к selBuffer[customIndex]. Таким образом атомарность не обеспечить ;)
totoro
> Таким образом атомарность не обеспечить ;)
Тогда чтоб гарантировать атомарность, нужно сразу записывать итоговое значение в atomicCompSwap, а не в два этапа.
// 1. Пытаемся атомарно захватить ячейку, записывая в неё временный маркер (0xffffffff) uint index = atomicCompSwap(selBuffer[customIndex].counter, 0, 0xffffffff); if (index == 0) { // 2. Если захватили успешно, вычисляем новый индекс uint newIndex = atomicAdd(selBuffer[0].counter, 1) + 1; // 3. Атомарно записываем итоговый индекс (вместо 0xffffffff) uint oldValue = atomicCompSwap(selBuffer[customIndex].counter, 0xffffffff, newIndex); // 4. Проверяем, что никто не испортил значение (если да — это ошибка логики) if (oldValue != 0xffffffff) { // Это не должно происходить, если логика корректна return; // или какая-то обработка ошибки } index = newIndex; } else { // 5. Если ячейка уже занята, читаем её значение (с барьерами) for (int i = 0; i < 3; i++) { index = atomicAdd(selBuffer[customIndex].counter, 0); if (index != 0xffffffff) break; memoryBarrier(); } if (index == 0xffffffff) return; // не удалось прочитать }
std::variant
> Пытаемся атомарно захватить ячейку
У меня именно так и сделано
Как на АМД включить dual-issue?
Обещают что будет 2х к производительности ALU и во всех спеках указываются FLOPS с учетом dual-issue.