【发布时间】:2019-05-11 06:21:15
【问题描述】:
我对 SDL_Texture 的理解是:
- 当您调用 SDL_CreateTextureFromSurface() 时,SDL_Texture 位于主内存中。
- 当您调用 SDL_RenderCopy() 时,纹理位于 VRAM 上。
- 当您调用 SDL_DestroyTexture() 时,纹理会从 VRAM 和主内存中释放。
我说的对吗?
我正在制作一个应用程序,在渲染它们之前从图像文件一次创建大量纹理,因为图像非常大并且 SDL_CreateTextureFromSurface() 需要很长时间。当我依次使用 SDL_RenderCopy() 和 SDL_RenderPresent() 渲染它们时,VRAM 的使用量逐渐增加,使用量达到最大限制后应用程序变慢。
我想从 VRAM 中释放纹理,但不想从主内存中释放它,因为重新创建纹理需要很长时间。有可能吗?
这是最少的代码。它一直工作到专用 GPU 内存使用率达到 100%。之后,它变得非常缓慢。 (Windows10、Visual Studio 2017、NVIDIA P6000)
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <filesystem>
#include <thread>
#include <chrono>
#include "SDL.h"
#include "SDL_image.h"
int main(int argc, char** argv) {
std::vector<SDL_Texture*> texture_list;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow( "", 0, 0, 7680, 4320, SDL_WINDOW_BORDERLESS);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
namespace fs = std::experimental::filesystem;
for ( auto ent : fs::recursive_directory_iterator("c:\\picture\\1k") ) {
if(!fs::is_directory(ent)){
auto f = ent.path().generic_string();
auto surface = IMG_Load(f.c_str());
std::cout << "file:" << f << std::endl;
auto tex = SDL_CreateTextureFromSurface(renderer, surface);
if(!tex){
std::cout << "SDL_CreateTextureFromSurface error" << std::endl;
std::cout << SDL_GetError() << std::endl;
}
texture_list.push_back(tex);
SDL_FreeSurface(surface);
}
}
while (true) {
for (auto tex : texture_list) {
if(SDL_RenderClear(renderer) != 0){
std::cout << "SDL_RenderClear error" << std::endl;
std::cout << SDL_GetError() << std::endl;
}
if(SDL_RenderCopy(renderer, tex, NULL, NULL) < 0){
std::cout << "SDL_RenderCopy error" << std::endl;
std::cout << SDL_GetError() << std::endl;
}
SDL_RenderPresent(renderer);
SDL_Delay(1);
//std::cout << cnt++ << std::endl;
SDL_Event event;
if(SDL_PollEvent(&event)){
std::cout << event.type << std::endl;
switch (event.type) {
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_q:
exit(0);
}
break;
}
}
}
}
return 0;
}
【问题讨论】:
-
重复 RenderCopy 不会增加您的内存占用。如果您在问题中添加一些代码(最好的情况是最小的完整可编译可验证示例),那么可能会说出您的内存使用量来自哪里。也不清楚您如何衡量内存使用情况,尤其是 VRAM。
-
您不必担心为各种后端特意从您那里抽象出来的实现细节。您的内存使用与调用
SDL_RenderCopy()几乎没有关系。我怀疑您实际上是在创建多个重复的纹理。 -
感谢您的建议。我添加了我制作的代码。
-
@yamasv 我认为给定的代码示例没有任何问题。只是为了确保,您使用您提供的代码对其进行了测试,它显示了非常快速的幻灯片,但内存使用量随着每一帧的通过而不断增加?您如何衡量 VRAM 的使用率? RAM使用量也增加了吗?如果是这样,则可能是图形驱动程序问题;您可以通过例如尝试不同的渲染后端吗?
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");在创建窗口/渲染器之前(但在 SDL_Init 之后)? -
不,不正确。
SDL_Textures 始终驻留在 VRAM 中(除非您使用软件渲染器),而SDL_Surfaces 则存储在常规 RAM 中。SDL_RenderCopy只是渲染图像(“复制”到屏幕上)的函数的一个有趣名称。