Я пытаюсь записать в SSBO с вычислительным шейдером и прочитать данные обратно на процессоре.
Вычислительный шейдер - просто игрушечный пример 1x1x1, который записывает 24 числа с плавающей запятой:
#version 450 core
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout (std430, binding = 0) buffer particles {
float Particle[];
};
void main() {
for (int i = 0; i < 24; ++i) {
Particle[i] = i + 1;
}
}
Вот так я запускаю шейдер и читаю данные:
val bufferFlags = GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT
val bufferSize = 24 * 4
val bufferId = glCreateBuffers()
glNamedBufferStorage(bufferId, bufferSize, bufferFlags)
val mappedBuffer = glMapNamedBufferRange(bufferId, 0, bufferSize, bufferFlags)
mappedBuffer.rewind()
val mappedFloatBuffer = mappedBuffer.asFloatBuffer()
mappedFloatBuffer.rewind()
val ssboIndex = glGetProgramResourceIndex(progId, GL_SHADER_STORAGE_BLOCK, "particles")
val props = Array(GL_BUFFER_BINDING)
val params = Array(-1)
glGetProgramResourceiv(progId, GL_SHADER_STORAGE_BLOCK, ssboIndex, props, null, params)
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, params(0), bufferId)
glUseProgram(progId)
val sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)
glDispatchCompute(1, 1, 1)
glClientWaitSync(sync, 0, 1000000000) match {
case GL_TIMEOUT_EXPIRED =>
println("Timeout expired")
case GL_WAIT_FAILED =>
println("Wait failed. " + glGetError())
case _ =>
println("Result:")
while(mappedFloatBuffer.hasRemaining) {
println(mappedFloatBuffer.get())
}
}
Я ожидаю, что он напечатает числа от 1 до 24, но вместо этого он печатает 24 нуля. Используя процессор, я могу читать и записывать (если установлен GL_MAP_WRITE_BIT
) в буфер. То же самое происходит, если я не использую DSA (вместо glBindBuffer
/ glBufferStorage
/ glMapBufferRange
). Однако, если буфер не отображается во время работы шейдера, и я отображаю его только перед печатью содержимого, все работает правильно. Разве это не то, для чего постоянно отображаются буферы? Так что я могу сохранить его на карте, пока его использует графический процессор?
Я проверил на наличие ошибок, с glGetError
, а также с более новыми выходными данными отладки, но я не получаю никаких.
Здесь (pastebin) - полностью рабочий пример. Вам нужно LWJGL , чтобы запустить его.