MrShoor
Там по ссылкам приведены формулы, они работают вне зависимости от d3dx.
И открой уже для себя wvp преобразование. То, что ты можешь работать в каком то пространстве это не значит что его нельзя изменить.
И учи матчасть. Что такое кеш процессора и чем опасен кеш мисс.
Ты лишними проверками можешь создать нагрузку больше чем убрав их.
innuendo
Я же говорю это сложная тема, к ней нельзя подходить топорно. Там нужно весь код смотреть. По коду автора скорее всего его проверка действительно даст прирост поскольку у него довольно тяжелый апдейт
Стас
> Там по ссылкам приведены формулы, они работают вне зависимости от d3dx.
> И открой уже для себя wvp преобразование. То, что ты можешь работать в каком то пространстве это не значит что его нельзя изменить.
Еще раз. В DX захардкожен клипспейс XY ∈ [-1;1] и Z ∈ [0;1]. Изменить ты его не можешь (Scissor не в счет, т.к. он не изменяет, а дополнительно клипает). Ты сейчас утверждаешь, что это не так?
> И учи матчасть. Что такое кеш процессора и чем опасен кеш мисс.
> Ты лишними проверками можешь создать нагрузку больше чем убрав их.
glMatrixLoad/glUniform/IDirect3DDevice9::SetTransform будет на порядки ( это *10^k ) дороже проверки флага с кешмиссом.
MrShoor
> Да хоть 8 кешмиссов, главное, чтобы этот флаг позволил мне избежать установки
> на конвеер.
Мы сейчас спорим о двух совершенно разных вещах. Автор уже сказал, что матрица сразу в константы не устанавливается, так что ты ошибся.
Стас
Да с чего ты взял, что у меня апдейт тяжелый? Это ТОЛЬКО пересчет матрицы на основе позиции, вращения и размера. Там больше ничего нет. Весь код Update() я выложил в первопосте, причем в самом тяжелом варианте - когда запрашивается инверсная матрица. Запрос матрицы идет каждый кадр, после чего она перемножается с матрицами камеры и передается в юниформ. Что еще такого может быть в моем коде особенного, что повлияет на способность dirty ускорить/замедлить выполнение?
bazhenovc
Это как, матрица в константы?
bazhenovc
> Мы сейчас спорим о двух совершенно разных вещах. Автор уже сказал, что матрица
> сразу в константы не устанавливается, так что ты ошибся.
Ну да, я же уже посоветовал автору не пихать стейты если матрица не поменялась.
Dampire
> Это как, матрица в константы?
Это когда ты делаешь:
> Матрицу передаю в шейдер.
MrShoor
> Еще раз. В DX захардкожен клипспейс XY ∈ [-1;1] и Z ∈ [0;1]. Изменить ты его не
> можешь (Scissor не в счет, т.к. он не изменяет, а дополнительно клипает). Ты
> сейчас утверждаешь, что это не так?
Мы говорим об одном и том же походу, после wvp преобразования, координаты как раз и будут в этой системе,
но до этого преобразования они могут быть в какой угодно.
MrShoor
> glMatrixLoad/glUniform/IDirect3DDevice9::SetTransform будет на порядки ( это
> *10^k ) дороже проверки флага с кешмиссом.
У тебя все объекты находятся в одних и тех же координатах? Если нет, то эта проверка не имеет абсолютно ни какого смысла.
Поскольку она только проверяет что матрица не была изменена, но не проверяет необходимость, выставить новую матрицу,
если ты рисуешь хотя бы 2 объекта с разными матрицами, то ты безусловно будешь выставлять новую матрицу, для каждого объекта
вне зависимости изменилась она или нет.
Dampire
> Да с чего ты взял, что у меня апдейт тяжелый?
В смысле тяжелый чтобы не грузиться кеш миссом. В тех оптимизациях о которых говорил bazhenovc убрать иф дает прирост только, если
время затраченное на работу с кешем будет больше выполнения самой операции. В твоем случае у тебя в апдейте выполняется
несколько умножений + инверсия, + еще проверка. Это довольно тяжелые операции, и суммарно, они скорее всего обойдутся дороже перегрузки кеша.
Стас
> если ты рисуешь хотя бы 2 объекта с разными матрицами, то ты безусловно будешь
> выставлять новую матрицу, для каждого объекта
> вне зависимости изменилась она или нет.
Совсем не обязательно. Это может быть например общая трансформация для группы объектов. А если даже и нет - то для всех объектов я могу складывать матрицы в один буфер. Тогда перед отрисовкой объекта надо будет выставить этот буфер, и брать матрицы из него. В DX11 например уже есть оффсеты по константным буферам.
MrShoor
Я вообще не вкурил. Что и куда я не должен пихать?
void MeshRenderer::Render(Camera *camera) { glUseProgram( shader->program); glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); glBindTexture( GL_TEXTURE_2D, texture->GetID( )); glEnableVertexAttribArray( shader->aPosition); glVertexAttribPointer( shader->aPosition, 3, GL_FLOAT, 0, sizeof( Vertex), ( GLvoid*)offsetof( Vertex, position)); glEnableVertexAttribArray( shader->aUV); glVertexAttribPointer( shader->aUV, 2, GL_FLOAT, 0, sizeof( Vertex), ( GLvoid*)offsetof( Vertex, uv)); glm::mat4 tr = camera->GetProjection( ) * camera->GetView( ) * _transform->GetWorldMatrix( ); glUniformMatrix4fv( shader->uTransform, 1, false, glm::value_ptr( tr)); glUniform1i( shader->uTexture, 0); glDrawElements( GL_TRIANGLES, mesh->indices.size( ), GL_UNSIGNED_INT, 0); glDisableVertexAttribArray( shader->aPosition); glDisableVertexAttribArray( shader->aUV); glUseProgram( 0); glBindBuffer( GL_ARRAY_BUFFER, 0); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0); glBindTexture( GL_TEXTURE_2D, 0); }
В GL есть UBO. На его основе я планирую инстансинг. Биндинг UBO как-бэ тоже стоит времени, причем поболе простого юниформа. И размеры UBO не бесконечны, навечно туда все статические юниформы не зальешь. Поправьте если не так.
Upd.
У меня не будет объектов с общим трансформом. Просто не будет. Я вообще не представляю как это возможно, и главное зачем. Мешпарты это один MeshRenderer, соответственно там вообще не надо повторно вызывать GetMatrix.
Dampire
> camera->GetProjection() * camera->GetView()
А заранее это посчитать не судьба?
-1 умножение на отрисовке каждого объекта.
Стас
Можно. Еще надо glUseProgram вынести за пределы рендерера и сортировать объекты по шейдеру. Тут еще можно кучу оптимизаций провести. Суть пока в Transform.
Dampire
Попробуй удалить весь рендеринг, оставить только апдейт сущностей. Дальше померяй, сколько времени занимает апдейт 10 тысяч объектов. И вот от этого момента уже можно начинать плясать.
10k маловато. Сделал 1kk
С dirty inverse матрица
4.410925
4.377917
4.373969
Без dirty inverse матрица
13.032024
12.884807
12.974728
С dirty прямая матрица
2.112842
2.124213
2.116378
Без dirty прямая матрица
6.287452
6.326793
6.163499
Интереса ради сделал UpdateMatrix не inline, и оно почему-то оказалось быстрее. Проверял дважды. Забавно.
6.179623
6.079405
6.072957
А вот что экономит убирание проверки на парента
5.957463
5.954906
5.958094
Код теста
std::vector<Transform> trs; for(int i = 0; i < 1000000; i++) { trs.push_back( Transform( )); } double time = glfwGetTime( ); for( int i = 0; i < 3; i++) { for( int j = 0; j < 1000000; j++) { trs[j].GetWorldMatrix( ); } } double tmp = glfwGetTime( ) - time; Debug->Log( std::to_string( tmp)); return 0;
Dampire
> Я вообще не вкурил. Что и куда я не должен пихать?
На свалку этот код. Ну я думаю ты понимаешь. Если десяток батчей рисовать - то покатит еще. Если надо максимум выжать, то:
1. glUseProgram вынести (ну ты знаешь уже)
2.
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); glEnableVertexAttribArray( shader->aPosition); glVertexAttribPointer( shader->aPosition, 3, GL_FLOAT, 0, sizeof( Vertex), ( GLvoid*)offsetof( Vertex, position)); glEnableVertexAttribArray( shader->aUV); glVertexAttribPointer( shader->aUV, 2, GL_FLOAT, 0, sizeof( Vertex), ( GLvoid*)offsetof( Vertex, uv));
объединить в VAO
3.
glUniformMatrix4fv(shader->uTransform, 1, false, glm::value_ptr( tr)); glUniform1i( shader->uTexture, 0);
вынести в UBO, ну и перезаливать данные если они реально поменялись.
> Биндинг UBO как-бэ тоже стоит времени, причем поболе простого юниформа.
glBindBufferRange тебе в помощь. Не хватает размера UBO, можно менеджить их, либо сложить все в обычный VBO и через glDrawElementsInstancedBaseVertexBaseInstance фигачить смещения.
4. Объединить все меши с одинаковым форматом вершин в один большой VBO, и биндить его вначале, а дальше через BaseVertex рисовать каждый меш.
Ну и в догонку презентация вот: http://on-demand.gputechconf.com/gtc/2014/presentations/S4379-ope… echniques.pdf