5

我写了一个模拟器,正在移植到 Linux。目前我正在使用 Direct3D 11 制作视频,我正在将其移植到 OpenGL(我现在正在 Windows 上运行)。我渲染到 1024x1024 纹理,每帧上传到内存(原始硬件并不真正适合现代硬件加速,所以我只是在软件中完成)。但是,我发现在 OpenGL 中上传纹理要慢得多。

在 Direct3D 中,每帧上传纹理都会将帧速率从 416 下降到 395(下降 5%)。在 OpenGL 中,它从 427 下降到 297(下降了 30%!)。

这是我的绘图函数中的相关代码。

Direct3D:

D3D11_MAPPED_SUBRESOURCE resource;
deviceContext_->Map(texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
uint32_t *buf = reinterpret_cast<uint32_t *>(resource.pData);
memcpy(buf, ...);
deviceContext_->Unmap(texture, 0);

OpenGL:

glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA,
    GL_UNSIGNED_BYTE, textureBuffer);

任何人都可以提出可能导致这种放缓的原因吗?

如果有任何可能性,我正在运行带有 NVIDIA GeForce GTX 550 Ti 的 Windows 7 x64。

4

2 回答 2

11

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer);

你在这里做错了几件事。首先,glTexImage2D相当于每帧创建一个 Direct3D 纹理资源。但你不是在创造它;你只是上传到它。每个感兴趣的 mipmap 层应该glTexImage2D只使用一次;之后,所有上传都应该使用glTexSubImage2D.

其次,您的内部格式(左起第三个参数)是GL_RGBA. 您应该始终为图像格式使用明确的尺寸。所以使用GL_RGBA8. 这不是一个真正的问题,但你现在应该养成这个习惯。

第三,您使用的是像素传输格式GL_RGBA的排序(右边的第三个参数,而不是左边的第三个参数)。这通常不是最理想的像素传输格式,因为许多硬件倾向于排序。但是,如果您没有从按该顺序生成数据的任何事物中获取数据,那么就无能为力了。GL_BGRA

第四,如果您在开始上传和实际渲染之间还有其他事情可以做,您可以使用异步像素传输操作。您将数据写入缓冲区对象(可以映射,因此您不必复制到其中)。然后你用glTexSubImage2D这个数据传输到OpenGL。因为源数据和目标图像是 OpenGL 内存的一部分,所以它不必在glTexSubImage2D返回之前将数据从客户端内存中复制出来。

当然,这可能对您没有多大帮助,因为您已经在 D3D 案例中有效地进行了该复制。

在 OpenGL 中,它从 427 下降到 297(下降了 30%!)

更重要的统计数据是 1 毫秒的差异。您应该以绝对时间而不是每秒帧数或 FPS 下降百分比来查看您的时间。

于 2012-10-16T20:53:24.713 回答
7

glTexImage2d 进行内存重新分配和更新。尝试改用 glTexSubImage2d。

于 2012-10-16T20:40:03.930 回答