Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Сделал мегатекстуры (5 стр)

Сделал мегатекстуры (5 стр)

Поделиться

Страницы: 1 2 3 4 5 6 Следующая

Fantom09Постоялецwww24 окт. 201711:13#60
Джек Аллигатор
> Но, если не ошибаюсь, эти расширения лишь упрощают работу с координатами и
> сэмплинг тайлов из кэша, а вся грязная работа по определению видимых тайлов и
> их подгрузке остаётся на программисте.
Расширения специфичны, потому я туда сильно не зарывался, думал ты уже этот вопрос изучил.
На сколько я помню там как раз решается проблема подгрузки текстур, там вроде создается виртуальная текстура, которая маппится на физическую память, потом просто указывается какой кусок должен быть загружен, далее драйвер сам подгружает. Но могу ошибаться.
Так же в шейдере появляется возможность получать информацию о том, загружен ли нужный кусок, с учетом лодов.
В сумме это можно использовать для определения видимых тайлов и их лодов, да и сам алгоритм можно перенести на вычислительные шейдера.

Ну а железо таки нужно периодически обновлять, видюха за 40 баксов это не роскошь.

Джек АллигаторПостоялецwww3 ноя. 20170:48#61
Решил старые проблемы, появились новые.
1. Поднял разрешение до 64к х 32к, размер тайла 256х256.
При 32 транспортных буферах PBO никаких подгрузок не видно, но некоторые тайлы грузятся битыми:
+ Показать

притом это ещё удачный скриншот, чаще всего бывает рандомное содержание или части других тайлов.
32 буфера - значит за один кадр грузится максимум 32 тайла.
Если уменьшить кол-во буферов до 4 или даже до 1, проблема исчезает, но и подгрузки отчетливо видны.
Не понимаю - или это из-за маппинга файла мегатекстуры в память, или другого маппинга, но уже буфера.
А может дело вообще в SSD, который стремительно устаревает и в последнее время часто подлагивает?
Не понимаю, что в этом коде может сбоить =\
let bytes_offset = MT_PART_BYTES * part_id;
let file_mmap = MmapOptions::new().offset(bytes_offset)
                                  .len(MT_PART_BYTES)
                                  .map(&megatex_heightnormal)
                                  .unwrap();

gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, packed_buffer_id);
gl::BufferData(gl::PIXEL_UNPACK_BUFFER, MT_PART_BYTES as isize, ::std::ptr::null(), gl::STREAM_DRAW);

let mut ptr = gl::MapBuffer(gl::PIXEL_UNPACK_BUFFER, gl::WRITE_ONLY);
ptr::copy_nonoverlapping(file_mmap.as_ptr() as *mut c_void, ptr, MT_PART_BYTES);

gl::UnmapBuffer(gl::PIXEL_UNPACK_BUFFER);
gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, 0);

далее этот буфер биндится вместе с текстурой кэша, вызывается glCompressedTexSubImage3D с нулевым указателем - ну там то точно не может быть ошибки.
На всякий случай обновил библиотеку mmap до последней версии, но ничего не изменилось. Да и насколько знаю, она не делает ничего особого кроме вызова системных апи - навряд ли проблема там.
Может есть какие-то тонкости в работе с memory mapped file, которых я не знаю? =\ в духе - нельзя отображать много мелких кусков за короткий промежуток времени

2. 64к мегатекстура генерилась 4 часа. Решил это дело оптимизировать, теперь генерация высоты+нормалей, сжатие в dds и запись в файл занимают 20мин.
Наибольший выигрыш дала оптимизация сжатия в dds - убрал промежуточное звено в виде imagemagick, заменив на вызов команд opengl загрузки+чтения текстуры.
И всё бы хорошо, но качество настолько отвратительное, что делает бессмысленным использование мегатекстуры.
Думается, дело в параметре -define dds:cluster-fit=true в imagemagick, что улучшало картинку в разы.
Правильно ли я понимаю, что в opengl такой фичи отродясь не было и для улучшения качества компрессии при сопоставимой скорости остается лишь искать готовый энкодер на цпу с такой же опцией, или писать самому?

Правка: 3 ноя. 2017 0:51

MrShoorУчастникwww3 ноя. 20172:37#62
Джек Аллигатор
> Не понимаю, что в этом коде может сбоить =\
А gl::MapBuffer точно маппит у тебя память. Прикол оригинального glMapBuffer в том, что он может выдать ошибку при нехватки какой-то там своей памяти в драйвере:
https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBuffer.xhtml
GL_OUT_OF_MEMORY is generated if the GL is unable to map the buffer object's data store. This may occur for a variety of system-specific reasons, such as the absence of sufficient remaining virtual memory.

И почему ты не льешь данные сразу в gl::BufferData?

Вот так:

let bytes_offset = MT_PART_BYTES * part_id;
let file_mmap = MmapOptions::new().offset(bytes_offset)
                                  .len(MT_PART_BYTES)
                                  .map(&megatex_heightnormal)
                                  .unwrap();

gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, packed_buffer_id);
gl::BufferData(gl::PIXEL_UNPACK_BUFFER, MT_PART_BYTES as isize, file_mmap.as_ptr() as *mut c_void, gl::STREAM_DRAW);
gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, 0);

А еще лучше вот так:

let bytes_offset = MT_PART_BYTES * part_id;
let file_mmap = MmapOptions::new().offset(bytes_offset)
                                  .len(MT_PART_BYTES)
                                  .map(&megatex_heightnormal)
                                  .unwrap();

gl::NamedBufferData(packed_buffer_id, gl::PIXEL_UNPACK_BUFFER, MT_PART_BYTES as isize, file_mmap.as_ptr() as *mut c_void, gl::STREAM_DRAW);

Не работает?

Правка: 3 ноя. 2017 2:38

Daniil PetrovПостоялецwww3 ноя. 20173:33#63
А что за структура let? На Спектруме это была команда присваивания значения переменной :)
MrShoorУчастникwww3 ноя. 20174:03#64
Daniil Petrov
> А что за структура let?
Из какого-нибудь rust-а объявление переменной.
Daniil PetrovПостоялецwww3 ноя. 20174:04#65
MrShoor
Это не плюсы?
MrShoorУчастникwww3 ноя. 20174:16#66
Daniil Petrov
> Это не плюсы?
А это по твоему похоже на плюсы:
let
MT_PART_BYTES as isize
::std::ptr::null()
file_mmap.as_ptr() as *mut c_void
?

Правка: 3 ноя. 2017 4:16

Daniil PetrovПостоялецwww3 ноя. 20174:33#67
MrShoor
Я вообще понять не могу, что это :))) ни на один мне знакомый язык не похоже
Джек АллигаторПостоялецwww3 ноя. 20178:56#68
MrShoor
> И почему ты не льешь данные сразу в gl::BufferData?
http://www.songho.ca/opengl/gl_pbo.html#unpack
Note that glMapBufferARB() causes sync issue. If GPU is working with this buffer, glMapBufferARB() will wait(stall) until GPU to finish its job. To avoid waiting (idle), you can call first glBufferDataARB() with NULL pointer before glMapBufferARB(). If you do that, the previous data in PBO will be discarded and glMapBufferARB() returns a new allocated pointer immediately even if GPU is still working with the previous data.

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

Daniil Petrov
https://www.rust-lang.org/ru-RU/

Правка: 3 ноя. 2017 9:24

Daniil PetrovПостоялецwww3 ноя. 20179:25#69
Джек Аллигатор
Значит и здесь LET имеет то же значение, что и на Спектруме :)
MrShoorУчастникwww3 ноя. 201710:58#70
Джек Аллигатор
> Попробовал лить данные напрямую в glBufferData - проблема не исчезает, зато
> появляются подлагивания и просадки фпс.
А проблема наблюдается при любых объемах данных? Если взять не сотни мегабайт, а поменьше -
проблема есть?
p.s. И странно, что просадки фпс. Что у тебя за железка? Что зо ОС?
Джек АллигаторПостоялецwww3 ноя. 201713:05#71
MrShoor
> p.s. И странно, что просадки фпс. Что у тебя за железка? Что зо ОС?
Просадки небольшие совсем. Просто хочу сохранить асинхронную загрузку текстур. Разве так не лучше? Куда ни глянь - все советуют юзать PBO.

Сделал такой тест - загрузил один тайл и подсовывал его вместо чтения из мегатекстуры.
Таки проблема в PBO.
Думаю, правильно везде советуют не мешать OpenGL с многопоточностью. Баг этот появился как раз после переноса подгрузки в отдельный тред.

Интересно, что при увеличении кол-ва буферов до 64 проблема почти исчезает.

Железо https://www.sony.ru/electronics/support/laptop-pc-vpc-series/vpce… pecifications
linux mint x64 с амд дровами

Fantom09
> Ну а железо таки нужно периодически обновлять, видюха за 40 баксов это не
> роскошь.
был бы стационарный комп - давно бы докупил видюху нормальную.
а так, придется 2к долларов копить на всё сразу

nonamezeroxПостоялецwww3 ноя. 201713:14#72
Джек Аллигатор

А тебе точно нужно весь буфер мапить?

Просто есть

https://www.khronos.org/opengl/wiki/GLAPI/glMapBufferRange

С разными клевыми флагами.

И вот еще

When replacing the entire data store, consider using glBufferSubData rather than completely recreating the data store with glBufferData. This avoids the cost of reallocating the data store.

Consider using multiple buffer objects to avoid stalling the rendering pipeline during data store updates. If any rendering in the pipeline makes reference to data in the buffer object being updated by glBufferSubData, especially from the specific region being updated, that rendering must drain from the pipeline before the data store can be updated.

Clients must align data elements consistent with the requirements of the client platform, with an additional base-level requirement that an offset within a buffer to a datum comprising


For vertex buffers, immutable storage opens a class of performance optimizations (e.g. persistent mapped memory) that would not be possible if you could change the size of the buffer at any time. You create a buffer whose size can never be changed, but you are still free to send it new data at any time using glBufferSubData* (...) commands or by writing to the buffer while it is memory mapped.

With glBufferData (...), you can call that command multiple times on the same object and it will orphan the old memory and allocate new storage. With glBufferStorage (...), the buffer's size is set for the lifetime of the object (immutable) and it is an error (GL_INVALID_OPERATION) to call glBufferStorage (...) again once it has been allocated immutably.

In short, it is the data store (storage characteristics) that is immutable, not the actual data.

Ты свой буфер с packed_buffer_id используешь один раз, или же многократно? Если многократно, то  glBufferData  используй только адын раз (при инициализации) , начиная со второго раза используй glBufferSubData. Иначе у тебя каждый вызов glBufferData  будет заново пересоздавать буфер и осуществлять выделение памяти (про glBufFerStorage, как я понял, на твоем железе не вариант вообще).

Правка: 3 ноя. 2017 13:43

Джек АллигаторПостоялецwww3 ноя. 201713:43#73
nonamezerox
> А тебе точно нужно весь буфер мапить?
> Ты свой буфер с packed_buffer_id используешь один раз, или же многократно?
Да и да. Берем тайл из мегатекстуры, пишем в буфер, в основном треде считываем из этого буфера тайл в текстуру и помечаем буфер свободным.
Буфер размером с тайл.

Не понимаю как вышеописанное может помочь, если проблема вероятно из-за того, что OpenGL не дружит с многопоточностью.

Пора на Vulkan валить =\

innuendoПостоялецwww3 ноя. 201713:45#74
Джек Аллигатор
> Пора на Vulkan валить =\

С нетерпением ждём результата

Страницы: 1 2 3 4 5 6 Следующая

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

Тема закрыта.

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