дароф спецы.
Как быстро получить массив с ГПУ?
че тока не делал. и так , и через текстуры, и через мапБуффер. Скорость одинаковая.
Я конечно понимаю что если решил считать на гпу, то делай уже там ВСЁ от и до. Но нет.
Мне нужно получить результат, и дальше вступает в работу CPU
// get glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, countersBuffer); glGetBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(bufferCounter), bufferCounter); _numContacts = bufferCounter[0]; glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0); if (_numContacts > 0) { if (_numContacts == 1) { SDFContact crez[1]; glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->contactsBuffer); glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(SDFContact)*_numContacts, crez); rez = true; contact = crez[0]; } else { g_system->out->Insert(0, "*** SDFConvex::CheckSphere: bad contact num\n"); } }
Да- получение каунтера и одного контакта = 40мс, но есть ньюанс:
вызываю 100 раз. Один раз где-то занимает 1мс
Если не получать ничего, то работа шадера занимает вообще по нулям всё.
glDispatchCompute(NUMGROUPS, 1, 1); // We need to block here on compute completion to ensure that the // computation is done before we render glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
Полюбому это хрень какая-то. Аналог на CPU - 3-4мс
The Andreyp
> вызываю 100 раз
Похоже проблема в этом
Когда создаешь буфер, есть возможность указать способ его размещения, будет он в видеопамяти, в оперативке или и там, и там. Самый быстрый вариант - в видеопамяти, поэтому обычно указывают его. Но быстрый он только если не нужен к нему доступ, а иначе придется все время делать копию.
Стоит сгруппировать все контакты в один большой буфер. Чтобы они один раз заполнялись на ГПУ и один раз читались ЦПУ.
Затем использовать двойную/тройную буферизацию. То есть пусть ГПУ заполняет следующий буфер, а ЦПУ читает результат из предыдущего кадра. В этом случае не будет такой дикой задержки.
Собственно в этом проблема, с ГПУ нормально можно делать readback только через 1-2 кадра.
Apfel1994
> с ГПУ нормально можно делать readback только через 1-2 кадра.
Я недавно делал замеры асинхронного чтения (PBO) у себя в движке и бывало до 4 кадров доходило на RXT2070 при чтении всего-то 28кб. Во временном выражении это 10 мс где-то (vsync выключен). Это довольно грустно, особенно если алгоритм считает какой-нибудь occlusion culling.
Попробуй копировать буфер счётчика из local в host buffer, жди glFinish() и потом мапь host buffer.
Андрей5000
специально делаю стрессТесты
Zab
типа stream static dynamic draw/read ? разницы 0
Apfel1994
меня стремает что физика начнет хреново работать и пропускать колижены когда в кадре он есть, а его не будет.
mr.DIMAS
у меня 4080 и как видим таже хеня. Не понимаю почему так трудно быстро слить данные.
v1c
из local в host buffer - это как?
glFinish где ставить?
мапь - Хз мапБуффер по скорости как getdata было,когда пробовал
The Andreyp
> типа stream static dynamic draw/read ? разницы 0
Это от видяхи зависит и от дров.
https://stackoverflow.com/questions/62109861/glgetbuffersubdata-a… r-very-slow-o
https://www.khronos.org/opengl/wiki/Buffer_Object#Persistent_mapping
fake.pdf
Типа персистент быстро работает ? Туторы поищу тогда как это юзать
Если этих тасков несколько, тогда их можно считать последовательно-параллельно. Тогда долгими будут только первые и последние.
The Andreyp
> Типа персистент быстро работает ? Туторы поищу тогда как это юзать
Это тебе не поможет
v1c
это наоборот на залив в буфер?
v1c
fake.pdf
толку 0. Это я так понимаю идея с двумя буферами
1) сначала основной буфер куда пишет CS
glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->ssbo_id_); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(SDFContact) * newSize, NULL, GL_STATIC_DRAW); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2) далее основная работа после CS
если нет копиБуфера - создаю и сохраняю указатель
далее каждыйкадр:
- в него копирую из основного
- жду
- копирую в CPU
if (!persistent_ptr_ || !read_fence_) { size_t size_in_bytes_ = sizeof(SDFContact) * oldContactBufferSize; if (read_ssbo_id_ == 0) { glGenBuffers(1, &read_ssbo_id_); glBindBuffer(GL_SHADER_STORAGE_BUFFER, read_ssbo_id_); glBufferStorage(GL_SHADER_STORAGE_BUFFER, size_in_bytes_, NULL, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT); persistent_ptr_ = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, size_in_bytes_, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); } glBindBuffer(GL_COPY_READ_BUFFER, ssbo_id_); glBindBuffer(GL_COPY_WRITE_BUFFER, read_ssbo_id_); glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, size_in_bytes_); glBindBuffer(GL_COPY_READ_BUFFER, 0); glBindBuffer(GL_COPY_WRITE_BUFFER, 0); glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); if (read_fence_) glDeleteSync(read_fence_); read_fence_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); } while (glClientWaitSync(read_fence_, GL_SYNC_FLUSH_COMMANDS_BIT, 1000) == GL_TIMEOUT_EXPIRED) { // Repeat until the data is ready. } glDeleteSync(read_fence_); read_fence_ = 0; contacts = new SDFContact[numContacts]; memcpy(contacts, persistent_ptr_, sizeof(SDFContact)*numContacts);
The Andreyp
Оставь фенс синк но убери glCopyBufferSubData и замерь какое время получается. Если такое же, то копирование не при чём.