Пара вопросов знатокам:
1. В DirectX 12 signal и wait Fence (которая является аналогом timeline semaphore в Vulkan) не принимают стадию конвеера (в виде D3D12_BARRIER_SYNC). А насколько эта возможность указывать их в Vulkan вообще что либо дает на каком либо современном железе? Или, раз directX без нее обходится, то можно и в Vulkan просто ALL_COMMANDS всегда писать, упростив обертку над этими двумя API? На RTX3070, поэкспериментировав, перенеся парочку синхронизаций очередей с VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT и VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT на VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, не увидел никакой разницы в FPS, но это не доказывает что так будет всегда и на любой системе
2. На той же RTX 3070 (видимо после обновления дров) появилась еще одна, 4ая queue family. Выглядит как еще одна transfer очередь (flags QUEUE_TRANSFER | QUEUE_SPARSE_BINDING). То есть теперь как будто бы 2 async transfer queue family! Кто знает, зачем их две и какую лучше выбирать?
CatsCanFly
> А насколько эта возможность указывать их в Vulkan вообще что либо дает на каком
> либо современном железе?
Зависит от железа. Насколько я помню на АМД синхронизации работают только в top/bottom stage, а в synchronizations2 top/bottom заменили на none/all в разных ситуациях.
Явное указание этапов дает микрооптимизации, которые мало кому нужны и опасны для тех, кто в этом не разбирается.
Сама синхронизация по семафорам занимает не мало времени, это можно немного оптимизировать за счет смещения этапов синхронизации, то есть часть работы будет выполняться пока совершается другая работа по переключению командных буферов и синхронизации памяти между очередями.
На мобилках я бы не стал лишний раз синхронизировать графику и компьют этапы, так как это отдельные хардварные очереди, которые могут параллелиться в одной вулкан очереди.
CatsCanFly
> То есть теперь как будто бы 2 async transfer queue family!
Раньше они разрешали 2 очереди с async transfer но с одинаковым family, видимо с разными family что-то проще сделать.
Можно одину для девайс -> хост, другую для хост -> девайс.
Какая лучшая стратегия с дескриптор сетами под Vulkan: аллоцировать для каждого инстанса материала свой дескриптор сет, один раз забиндить в него ресурсы и просто биндить через vkCmdBindDescriptorSets() или выделить по одному глобальному дескриптор сету на каждый тип материала и обновлять их нужными ресурсами через vkUpdateDescriptorSets()?
v1c
> или выделить по одному глобальному дескриптор сету на каждый тип материала и
> обновлять их нужными ресурсами через vkUpdateDescriptorSets()
Это не будет работать, vkUpdateDescriptorSets можно вызвать один раз за кадр для одного дескриптор сета.
Если сделать барьер с oldLayout = undefined то драйвер может выкинуть содержимое текстуры, но чаще всего он это не делает и можно по ошибке продолжить использовать содержимое текстуры.
А еще самое подлое - когда текстура с exclusive sharing перемещается между очередями без queue ownership transfer operation, то ее содержимое также может быть потеряно, но и это не происходит.
При написании рендер графа такие ошибки тяжело отлавливать.
Еще вопрос про барьеры, а конкретно memory barrier.
Относится и к synchronization2 и к legacy
Что предпочтительнее и в чем вообще разница между указанием нескольких memory barrier для cmdPipelineBarrier и указанием одного с комбинацией масок. То есть (на псевдокоде):
barrier1 { .srcStageMask = PIPELINE_STAGE_A, .srcAccessMask = ACCESS_A, .dstStageMask = PIPELINE_STAGE_B, .dstAccessMask = ACCESS_B} barrier2 { .srcStageMask = PIPELINE_STAGE_C, .srcAccessMask = ACCESS_C, .dstStageMask = PIPELINE_STAGE_D, .dstAccessMask = ACCESS_D} cmdPipelineBarrier({barrier1, barrier2});
VS
barrier { .srcStageMask = PIPELINE_STAGE_A | PIPELINE_STAGE_C, .srcAccessMask = ACCESS_A | ACCESS_C, .dstStageMask = PIPELINE_STAGE_B | PIPELINE_STAGE_D, .dstAccessMask = ACCESS_B | ACCESS_D} cmdPipelineBarrier({barrier});
CatsCanFly
Например такое:
Compute|StorageWrite -> Compute|UniformRead
Transfer|CopyDst -> Fragment|Sample
Host|MemoryWrite -> Vertex|VertexAttribRead
Если объединить в один, то добавится Compute|Sample а это лишняя работа с кэшем.
Еще добавится Compute+Transfer|MemoryWrite что зафлушит все оставшиеся кэши, которых в данном примере не оказалось, разве что ClearDst+BlitDst из synchronization2 зафлушатся.
Я бы с таким не заморачивался, раньше драйвера вообще все кэши обновляли на любой барьер и никто не жаловался)
Заметил что атомики не работают в ray closest hit shader, причем началось это достаточно давно.
debugPrintfEXT() тоже не работает, в ray gen и ray miss все работает.
Есть идеи что это?
upd: на NV расширении атомики работают даже с KHR шейдерами.
Всем привет!
Помогите найти профессионала, кто нам клиент игры на вулкан портирует и в дальнейшем хотелось-бы работать с этим человеком на постоянной основе.
Вакансия: https://gamedev.ru/job/forum/?id=274462
VK_HUAWEI_cluster_culling_shader
Похоже на аналог меш шейдеров под АРМ. Возможно даже с оптимизациями, а не так как в Метале, где просто эмулируется поведение как на десктопах.
Как корректно сделать бы архитектурно стриминг текстур с descriptor indexing?
Вот есть большой descriptor set всех текстур. Каждый материал для каждой нужной ему текстуры содержит индекс, по которому из шейдера читается текстура из безразмерного массива.
Я хочу обновлять текстуру на большего разрешения. Кажется логичным и удобным обновить дексриптор по тому же индексу, в котором была менее детальная версия данной текстуры. (можно бы конечно писать текстуру в новый свободный индекс и обновлять ее индекс во всех материалах, но тогда получается нужна некрасивая связь текстура -> множество материалов которые ее используют)
Но при 2 frames in flight это потребует держать два набора дескрипторов текстур - один читает GPU, другой обновляется с CPU. Кажется расточительством (учитывая что сет большой, на тысячи дескрипторов и часть из них пусты). А как это делают другие? Помогите советом
CatsCanFly
Для десктопов можно использовать sparse memory и биндить/анбиндить верхний мип текстуры, тогда не надо будет трогать дескрипторы.
/A\
Потенциально не хочется ограничивать поддерживаемые платформы сильнее чем есть, и насколько читал, это крайне медленно работает на Windows (на реддите ходят разговоры о ~100мс на биндинг sparse memory страниц). Если есть какие то обьективные тесты, было бы интересно посмотреть, потому что что бы протестировать в своем кейсе, придется очень много чего переделать для поддержки sparse memory, и будет обидно если это все окажется на выброс
CatsCanFly
На АМД медленно работает с какими-то флагами. На нвидии проблем не наблюдал. На хбоксе вроде используют, смотри презентации shadow of war.