我编写了一个模拟器,我正在移植到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。
答案 0 :(得分:10)
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,1024,1024,0,GL_RGBA,GL_UNSIGNED_BYTE,textureBuffer);
你在这里犯了几件错事。首先,glTexImage2D
相当于每帧创建一个Direct3D纹理资源。但你不是在创造它;你只是上传到它。每个感兴趣的mipmap图层只应使用glTexImage2D
一次;之后,所有上传都应该在glTexSubImage2D
上进行。
其次,您的internal format(左起第三个参数)为GL_RGBA
。您应始终为图像格式使用显式大小。所以使用GL_RGBA8
。这不是一个真正的问题,但你现在应该养成这个习惯。
第三,您正在使用GL_RGBA
订购pixel transfer format(右侧中的第三个参数,而不是左侧)。这通常不是最佳的像素传输格式,因为许多硬件往往更喜欢GL_BGRA
排序。但是,如果你没有从按顺序生成数据的任何数据中获取数据,那么就没有什么可以做的了。
第四,如果你在开始上传和实际渲染之间有其他的东西,你可以使用asynchronous pixel transfer operations。您将数据写入缓冲区对象(可以映射,以便您不必复制到缓冲区对象中)。然后使用glTexSubImage2D
将此数据传输到OpenGL。由于源数据和目标图像是OpenGL内存的一部分,因此在glTexSubImage2D
返回之前,不必将数据从客户端内存中复制出来。
当然,这可能不会对你有多大帮助,因为你已经在D3D案件中有效地完成了这个副本。
在OpenGL中,它从427下降到297(下降30%!)
更重要的统计数据是它的差异为1毫秒。您应该在绝对时间内查看您的时间,而不是每秒帧数,也不是FPS的百分比下降。
答案 1 :(得分:7)
glTexImage2d执行内存重新分配以及更新。尝试使用glTexSubImage2d代替。