gpt4 book ai didi

c++ - 为什么基于 Dear ImGui 的渲染器这么慢?

转载 作者:太空狗 更新时间:2023-10-29 23:11:08 39 4
gpt4 key购买 nike

我完成了基于 Dear ImGui DrawList 渲染 2d 对象的类,因为它可以绘制许多不同的对象变体,这要归功于索引 vector 动态数组并且仍然保持良好的优化。亲爱的 ImGui 可以渲染 30k 未填充的矩形,同时在 Debug模式下具有 ~36fps 和 ~70MB,没有抗锯齿(我的电脑)。我的非常有限的版本绘制了 30k 未填充的矩形,同时在 Debug模式下具有 ~3 fps 和 ~130MB。

class Renderer
{
public:
Renderer();
~Renderer();

void Create();

void DrawRect(float x, float y, float w, float h, GLuint color, float thickness);

void Render(float w, float h);

void Clear();

void ReserveData(int numVertices, int numElements);

void CreatePolygon(const Vector2* vertices, const GLuint verticesCount, GLuint color, float thickness);

GLuint vao, vbo, ebo;
GLShader shader;

Vertex* mappedVertex = nullptr;
GLuint* mappedElement = nullptr,
currentVertexIndex = 0;

std::vector<Vertex> vertexBuffer;
std::vector<GLuint> elementBuffer;
std::vector<Vector2> vertices;

};

const char* vtx =
R"(

#version 460 core

layout(location = 0) in vec3 a_position;
layout(location = 1) in vec4 a_color;

out vec3 v_position;
out vec4 v_color;

uniform mat4 projection;

void main()
{
gl_Position = projection * vec4(a_position, 1.0);

v_color = a_color;
}

)";

const char* frag =
R"(
#version 460 core

layout (location = 0) out vec4 outColor;

in vec4 v_color;

void main()
{
outColor = v_color;
}
)";

void Renderer::Clear()
{
vertexBuffer.resize(0);
elementBuffer.resize(0);
vertices.resize(0);
mappedVertex = nullptr;
mappedElement = nullptr;
currentVertexIndex = 0;
}

void Renderer::Create()
{
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);

shader.VtxFromFile(vtx);
shader.FragFromFile(frag);
}

void Renderer::DrawRect(float x, float y, float w, float h, GLuint color, float thickness)
{
// Add vertices
vertices.push_back({ x, y });
vertices.push_back(Vector2(x, y + w));
vertices.push_back(Vector2( x, y ) + Vector2(w, h));
vertices.push_back(Vector2(x + w, y));
// Create rect
CreatePolygon(vertices.data(), vertices.size(), color, thickness);
}

void Renderer::Render(float w, float h)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

shader.UseProgram();
shader.UniformMatrix4fv("projection", glm::ortho(0.0f, w, 0.0f, h));

GLuint elemCount = elementBuffer.size();

glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, position));
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (const void*)offsetof(Vertex, position));

glBufferData(GL_ARRAY_BUFFER, vertexBuffer.size() * sizeof(Vertex), vertexBuffer.data(), GL_STREAM_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBuffer.size() * sizeof(GLuint), elementBuffer.data(), GL_STREAM_DRAW);

const unsigned short* idxBufferOffset = 0;

glDrawElements(GL_TRIANGLES, elemCount, GL_UNSIGNED_INT, idxBufferOffset);

idxBufferOffset += elemCount;

glDeleteVertexArrays(1, &vao);

glDisable(GL_BLEND);
}

void Renderer::CreatePolygon(const Vector2* vertices, const GLuint verticesCount, GLuint color, float thickness)
{
// To create for example unfilled rect, we have to draw 4 rects with small sizes
// So, unfilled rect is built from 4 rects and each rect contains 4 vertices ( * 4) and 6 indices ( *6)
ReserveData(verticesCount * 4, verticesCount * 6);

for (GLuint i = 0; i < verticesCount; ++i)
{
const int j = (i + 1) == verticesCount ? 0 : i + 1;

const Vector2& position1 = vertices[i];
const Vector2& position2 = vertices[j];

Vector2 difference = position2 - position1;

difference *= difference.Magnitude() > 0 ? 1.0f / difference.Magnitude() : 1.0f;

const float dx = difference.x * (thickness * 0.5f);
const float dy = difference.y * (thickness * 0.5f);

mappedVertex[0].position = Vector2(position1.x + dy, position1.y - dx);
mappedVertex[1].position = Vector2(position2.x + dy, position2.y - dx);
mappedVertex[2].position = Vector2(position2.x - dy, position2.y + dx);
mappedVertex[3].position = Vector2(position1.x - dy, position1.y + dx);

mappedVertex[0].color = color;
mappedVertex[1].color = color;
mappedVertex[2].color = color;
mappedVertex[3].color = color;

mappedVertex += 4;

mappedElement[0] = currentVertexIndex;
mappedElement[1] = currentVertexIndex + 1;
mappedElement[2] = currentVertexIndex + 2;
mappedElement[3] = currentVertexIndex + 2;
mappedElement[4] = currentVertexIndex + 3;
mappedElement[5] = currentVertexIndex;

mappedElement += 6;
currentVertexIndex += 4;
}

this->vertices.clear();
}

void Renderer::ReserveData(int numVertices, int numElements)
{
currentVertexIndex = vertexBuffer.size();

// Map vertex buffer
int oldVertexSize = vertexBuffer.size();
vertexBuffer.resize(oldVertexSize + numVertices);
mappedVertex = vertexBuffer.data() + oldVertexSize;

// Map element buffer
int oldIndexSize = elementBuffer.size();
elementBuffer.resize(oldIndexSize + numElements);
mappedElement = elementBuffer.data() + oldIndexSize;
}


int main()
{
//Create window, init opengl, etc.
Renderer renderer;
renderer.Create();
bool quit=false;
while(!quit) {
//Events
//Clear color bit

renderer.Clear();

for(int i = 0; i < 30000; ++i)
renderer.DrawRect(100.0f, 100.0f, 50.0f, 50.0f, 0xffff0000, 1.5f);

renderer.Render(windowW, windowH);

//swap buffers
}
return 0;
}

为什么这么慢?我怎样才能使它更快并且占用更少的内存?

最佳答案

该代码中最大的瓶颈似乎是您的分配永远不会跨帧摊销,因为您正在清除缓冲区容量而不是重用它们,导致您进行大量重新分配/复制(如果您的可能是 Log2(n) 重新分配/复制) vector 实现增长了 2 倍)。尝试使用 .resize(0) 更改您的 .clear() 调用,也许您可​​以在未使用的情况下对 .clear() 进行更懒惰/罕见的调用。

In debug or in release mode? Vectors are terribly slow in debug due to memory checking. Profiling should always be done in Release.

如果您打算在调试/未优化模式下使用和处理您的应用程序,则应该在发布和调试/未优化模式下进行分析。现代 C++ 的“零成本抽象”谎言是,它让使用调试器变得很痛苦,因为大型应用程序不再以正确的帧速率在“调试”模式下运行。理想情况下,您应该始终在 Debug模式下运行所有​​应用程序。帮自己提高工作效率,同时针对最坏的情况做一些分析/优化。

祝您学习顺利! :)

关于c++ - 为什么基于 Dear ImGui 的渲染器这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51671642/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com