HolyDel
> Но, как мне кажется, худшее, что может возникнуть без правильной синхронизации - это при семплинге текстуры вернется некорректный результат
ахаха, или bsod на amd, если семплить кубмапу как шадоумапу.
Suslik
> если семплить кубмапу как шадоумапу.
и как такое же может быть? вот мне в теме про исключения пишут что нужно жёстко тестировать:)
VK_EXT_descriptor_indexing на мобильных GPU https://community.arm.com/developer/tools-software/graphics/b/blo… ptor-indexing
/A\
Таймлиайн семафор ещё. Я так понимаю он будет как Fence из Dx12 работать
UP
Возник возможно глупый вопрос по шейдерам на современных видеокартах.
Есть у меня полноэкранный квадрат и фрагментный шейдер. Во фрагментном шейдере есть цикл, который читает какие-то данные (источники освещения, например) и для каждой итерации производит некоторые вычисления. При этом в процессе этих вычислений возможны некоторые ветвления. Поскольку все соседние потоки имеют одинаковые входные общие данные и соответственно цикл для них всегда будет иметь одинаковое количество итераций, но вот уже внутри итераций могут быть ветвления разные для разных фрагментов, но не совсем хаотично, а более-менее упорядоченно.
Вопрос следующий - есть ли способ как-то указать что в таком-то месте у меня должна быть синхронизация потока управления для всех фрагментов в группе, чтобы предотвратить случай, когда на первой итерации вычислений произвойдёт рассихнроназиция потока управления и как следствие, все дальнейшие итерации будут выполняться несинхронно (а значит медленно)?
Не очень понял, что ты хочешь, но наверное тебе подойдёт shader subgroup: https://www.khronos.org/blog/vulkan-subgroup-tutorial
Настало время на реализацию VK_EXT_descriptor_index с учетом поддержки на android: https://vulkan.gpuinfo.org/listdevicescoverage.php?extension=VK_E… tform=android
Vulkan 1.2 на Android
https://vulkan.gpuinfo.org/displayreport.php?id=9843
Panzerschrek[CN]
> Вопрос следующий - есть ли способ как-то указать что в таком-то месте у меня должна быть синхронизация потока управления для всех фрагментов в группе
В пределах варпа рассинхронизация принципиально не возможна, потому что "потоки" по терминологии GPU маркетологов — это отдельные элементы SIMD регистров. Рассинхронизация возможна в пределах сабгрупп, которые суть пачка потоков в режиме гипертрединга, работающая на одном ядре. Для локальной синхронизации сабгрупп обычно есть инструкции барьеров. Ну и для синхронизации между ядрами (глобальной) вменяемых средств обычно нету.
Andrey
> Vulkan 1.2 на Android
А толку? Полно девайсов, где вулкан версии 1.0.62, у меня самый старый на 1.0.82
}:+()___ [Smile]
> В пределах варпа рассинхронизация принципиально не возможна
Значит ли это, что при первом ветвлении с разным результатом GPU раскидает поток управления по разным warp-ам? Если да, то как подсказать ему, что в таком-то месте надо их обратно в один warp помещать?
> Рассинхронизация возможна в пределах сабгрупп, которые суть пачка потоков в
> режиме гипертрединга
Вот здесь не понял. Поток управления в подгруппах принципиально разный же? Если да, то мне безразлична их на синхронизация, ибо прироста в производительности я от этого не получу.
HolyDel
> shader subgroup
Чё-то мне подсказывает, что то, что описано в статье и есть разбиение вычислений на эти подгруппы с независимым потоком управления.
Panzerschrek[CN]
> Значит ли это, что при первом ветвлении с разным результатом GPU раскидает поток управления по разным warp-ам?
Нет, каждый поток жестко прибит к варпу (по типу: warp_id = thread_id >> 5).
Если в пределах одного варпа есть ветвление, то сначала варп выполняет первую ветку с соответствующей маской записи, а потом — вторую с дополнительной маской. В принципе, один-в-один то, что приходится делать при векторизации кода с ветвлениями на SSE/AVX или любом другом SIMD. Еще можно посмотреть AVX512 — эта система инструкций родилась как раз под видеокарты, там есть все эти операции с масками и пр.
> Поток управления в подгруппах принципиально разный же?
Да, это независимые потоки. От потоков на разных ядрах их отличает доступ к быстрой локальной памяти и возможности взаимной синхронизации.
}:+()___ [Smile]
> Если в пределах одного варпа есть ветвление, то сначала варп выполняет первую
> ветку с соответствующей маской записи, а потом — вторую
А после ветвления warp будет продолжать дальше выполнять параллельно код после ветвления?
А что при этом происходит с циклами? А что если у меня есть switch-case на десяток вариантов или аналогичная ему цепь if-else?
не подскажите, в чем кардинальное отличие pass от subpass, и зачем нужны последние?
MAMOHT-92
Что за pass? Renderpass? Если да, то рендерпасс - это такая штука, по окончании работы которой у тебя окажется в памяти какая-то картинка. А субпассы за милую душу эту картинку оставляют временно, в локальной памяти для тайла, например. Вобщем сабпасы нужны для мобилок в первую очередь (ИМХО). Чтобы можно было посчитать условный G-Buffer и его освещение внутри тайла, не гоняя пиксели туда-сюда в основную память.
Но это все так, дилетантское ИМХО, с мобилками плотных дел не имел.
Panzerschrek[CN]
> А после ветвления warp будет продолжать дальше выполнять параллельно код после ветвления?
SIMD код, в принципе, не может выполняться не параллельно. Например, шейдер типа
float test(bool mask, float a, float b) { float c; if( mask)c = a + b; else c = a - b; c += 100; // операция после ветвления return c; }
float32 test(bool32 mask, float32 a, float32 b) { float32 c = {0}; if( any_set( mask))c |= ( a + b) & mask; if( any_set( ~mask))c |= ( a - b) & ~mask; c += 100; // операция после ветвления return c; }
> А что при этом происходит с циклами?
Крутятся до тех пор, пока хотя бы один поток из варпа что-то считает:
bool32 mask = {true}; while(true) { mask = loop_condition( ...) & mask; // обновление маски активных потоков if( !any_set( mask))break; loop_body( ..., mask); // тело цикла, обновляет потоки по маске }
> А что если у меня есть switch-case на десяток вариантов или аналогичная ему цепь if-else?
Выполнятся все ветки, в которые зашел хотя бы один поток из варпа.
В общем, основной посыл — у всех потоков варпа один общий instruction pointer на всех.