Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / InterlockedAdd для DrawIndirectArgs сломан на Nvidia ?

InterlockedAdd для DrawIndirectArgs сломан на Nvidia ?

Advanced: Тема повышенной сложности или важная.
Страницы: 1 2 Следующая »
0r@ngEУчастникwww7 дек. 201822:29#0
Всем привет!

Были у меня GPU партиклы, симуляция и спавн в пиксельном шейдере, на CPU менеджмент тайлов, система похожая на оную в UE4 только на стероидах (зато меньше гибкости).
Все работает как часы, быстро, весело, задорно.

Захотелось мне Compute версию сделать. Делал с подглядыванием в DooM 2016.  DX11 (компьюты на DX10 кастраты, и там будет старая система).
В планах DX12 (как минимум для консолей, ибо хочется в async).

Менеджмент с CPU переехал почти полностью на GPU, DrawIndexedInstancedIndirect и прочие радости цивилизованного мира.

И тут во весь рост встала проблема - есть следующий кусок кода:

void csmain(uint3 id : SV_DispatchThreadID)
...................
RWBuffer<uint> DrawIndirectArgs : register(u4);
...................
uint commitListIndex;
InterlockedAdd(DrawIndirectArgs[0], 6, commitListIndex);
..................
// дальше по коду (commitListIndex / 6) юзается

Так вот обнаружилось, что `commitListIndex` может получиться одинаковым для нескольких потоков! Сумашествие!

Методом научного гугления я нашел только один вот этот топик - https://www.gamedev.net/forums/topic/694086-compute-shaders-synch… zation-issue/
У человека здесь 1-в-1 та же проблема. Но то 2017 год. Неужели не починили?

Драйвера у меня новые. GTX 10xx точно проявляется эта трабла. На AMD проверить не могу (нет под рукой).

Собственно весь вопрос - то ли лыжи, то ли я?

Поделитесь тайным знанием, если кто сталкивался.  Ну или закидайте какашками если я туплю.

Правка: 7 дек. 2018 22:30

MrShoorУчастникwww7 дек. 201822:32#1
0r@ngE
> то ли я?
Этот вариант. Гугли globallycoherent :)
0r@ngEУчастникwww7 дек. 201822:36#2
MrShoor
> globallycoherent
Люблю тебя!  Похоже это оно.  Спасибо!
0r@ngEУчастникwww7 дек. 201823:03#3
Так, любовь отменяется )
globallycoherent RWBuffer<uint>  DrawIndirectArgs    : register(u4);
в асме проверил, вот так
dcl_uav_typed_buffer_glc (uint,uint,uint,uint) u4

Ничего не поменялось, к сожалению.

Может я опять чего упустил?

MrShoorУчастникwww7 дек. 201823:27#4
0r@ngE
> Так, любовь отменяется )
Ок, давай тогда полный код шейдера.
0r@ngEУчастникwww7 дек. 201823:30#5
Решил проверить Дум - и опачки, та же херня что и у меня. Сумашествие.

image (5) | InterlockedAdd для DrawIndirectArgs сломан на Nvidia ?

MrShoorУчастникwww7 дек. 201823:35#6
0r@ngE
> _glc
Это и есть globallycoherent.
Типа если убрать globallycoherent, то _glc в асме остается?
0r@ngEУчастникwww7 дек. 201823:37#7
MrShoor
> Типа если убрать globallycoherent, то _glc в асме остается?
нет, я просто привел асм чтоб показать что таки `globallycoherent` добавился, но эффекта не дало.
layout(set = 0, binding = 7, std430) coherent restrict buffer particleindirectdrawargs_b
А вот это из шейдера Дума, и, как видим из картинки, им тоже не помогло  (ай-яй-яй Тьяго ! )
0r@ngEУчастникwww7 дек. 201823:39#8
MrShoor
> Ок, давай тогда полный код шейдера.
Не могу, извини :(

Но там все просто, если изолировать, то

uint commitListIndex;
InterlockedAdd(DrawIndirectArgs[0], 6, commitListIndex);

потом если commitListIndex записать для каждого потока в буфер, и чекнуть буфер - то будут попадаться дубликаты, хотя не должны ведь.

При чем проявляется только в случае если  DrawIndirectArgs  создан с флагом  D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS

MrShoorУчастникwww7 дек. 201823:45#9
0r@ngE
> При чем проявляется только в случае если DrawIndirectArgs создан с флагом
> D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS
Может быть действительно бага, которая связана непосредственно с этим флагом, потому что у меня вроде бы нет комбинаций, в которых этот флаг и запись с Interlocked одновременно происходят.
У себя использую и InterlockedAdd, и IncrementCounter (второй кстати чаще, потому что счетчики можно проще инициализировать), и никаких проблем не было, если есть globallycoherent при записи. На широком спектре видеокарт. Возможно у NVidia рвет башню от этого, и она не учитывает этот _glc если есть флаг у ресурса.
MrShoorУчастникwww7 дек. 201823:53#10
0r@ngE
А может просто вынести счетчик не в Indirect ресурс? Тебе ведь не нужен линкед лист, а просто нужно набить команды для отрисовки. Соответственно DrawIndirectArgs может быть вполне не globallycoherent ресурсом.
0r@ngEУчастникwww8 дек. 20180:00#11
MrShoor
> А может просто вынести счетчик не в Indirect ресурс?
Да можно, просто надо ж потом скопировать его.  Хотелось элегантно все делать, а не как обычно, с хаками :(

Попробую дернуть Nvidia, может чего путного ответят.

MrShoorУчастникwww8 дек. 20180:14#12
0r@ngE
> Да можно, просто надо ж потом скопировать его.
А копировать то его зачем? Я говорю сейчас только про счетчик, а не про сами данные.
0r@ngEУчастникwww8 дек. 20180:21#13
MrShoor
> Я говорю сейчас только про счетчик, а не про сами данные.
Извини, не совсем понимаю тебя.
InterlockedAdd(DrawIndirectArgs[0], 6, commitListIndex);
Здесь я добавляю кол-во индексов для отрисовки (6 индексов на партикл).

Не совсем понимаю о каком счетчике ты пишешь, извини.

innuendoПостоялецwww8 дек. 20180:29#14
0r@ngE
> На AMD проверить не могу (нет под рукой).

демку сделай - я проверю :)

Страницы: 1 2 Следующая »

/ Форум / Программирование игр / Графика

2001—2018 © GameDev.ru — Разработка игр