2012-06-26 56 views
14

Trong ứng dụng của tôi, tôi đang sử dụng rộng rãi glTexImage2D. Tôi sao chép một số hình ảnh của một hình ảnh và làm cho nó như là một kết cấu, tôi làm điều đó thường xuyên ở mỗi nhấp chuột. Tôi cho nó như là một mảng byte để dựng hình. Bộ nhớ đang được ăn và bộ nhớ hoán đổi cũng được cấp phát. Nó có bị rò rỉ bộ nhớ không? hoặc là do thực tế là glTexImage2D giữ bất kỳ tài liệu tham khảo hoặc bất cứ điều gì khác.cách quản lý bộ nhớ với kết cấu trong opengl?

Edit:

//I allocate the memory once 
    GLuint texName; 
    texture_data = new GLubyte[width*height]; 

    // Each time user click I repeat the following code (this code in in callback) 
    // Before this code the texture_data is modified to reflect the changes 
    glGenTextures(3, &texname); 
    glBindTexture(GL_TEXTURE_2D, texname); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,texture_data); 

Tôi hy vọng các yêu cầu chặt chẽ của bạn và xuống bỏ phiếu sẽ dừng lại bây giờ!

+2

Mã thực tế sẽ hữu ích khi theo dõi sự cố này. –

+0

@NicolBolas, tôi đã putted mã, nhờ đã đề cập +1 – Shan

Trả lời

40

Giả sử bạn đang tạo một kết cấu mới với glGenTextures mỗi khi bạn gọi glTexImage2D, bạn đang lãng phí bộ nhớ và rò rỉ nếu bạn không theo dõi tất cả các họa tiết bạn tạo ra. glTexImage2D lấy dữ liệu đầu vào và lưu trữ bộ nhớ thẻ video. Tên kết cấu mà bạn liên kết trước khi gọi glTexImage2D - cái mà bạn tạo ra với glGenTextures là bộ xử lý cho đoạn bộ nhớ thẻ video đó.

Nếu kết cấu của bạn lớn và bạn đang cấp phát bộ nhớ mới để lưu trữ ngày càng nhiều bản sao của nó mỗi khi bạn sử dụng, thì bạn sẽ nhanh chóng hết bộ nhớ. Giải pháp là gọi glTexImage2D một lần trong quá trình khởi tạo ứng dụng của bạn và chỉ gọi glBindTexture khi bạn muốn sử dụng. Nếu bạn muốn thay đổi kết cấu khi bạn nhấp, chỉ gọi glBindTextureglTexImage2D. Nếu hình ảnh mới của bạn có cùng kích thước với hình ảnh trước đó, bạn có thể gọi glTexSubImage2D để yêu cầu OpenGL ghi đè lên dữ liệu hình ảnh cũ thay vì xóa hình ảnh đó và tải lên hình ảnh mới.

CẬP NHẬT

Để đối phó với mã mới của bạn, tôi đang cập nhật câu trả lời của tôi với một câu trả lời cụ thể hơn. Bạn đang xử lý kết cấu OpenGL theo cách sai hoàn toàn Kết quả của glGenTexturesGLuint[] và không phải là String hoặc char[]. Đối với mọi kết cấu bạn tạo ra với glGenTextures, OpenGL cung cấp cho bạn trở lại một tay cầm (như một số nguyên không dấu) cho một kết cấu. Tay cầm này lưu trữ trạng thái bạn cung cấp cho nó glTexParameteri cũng như một đoạn bộ nhớ trên cạc đồ họa nếu bạn cung cấp dữ liệu đó với glTexImage[1/2/3]D. Bạn có thể lưu trữ bộ xử lý và gửi dữ liệu mới khi muốn cập nhật. Nếu bạn ghi đè lên tay cầm hoặc quên nó, dữ liệu vẫn nằm trên card đồ họa nhưng bạn không thể truy cập nó. Bạn cũng đang yêu cầu OpenGL tạo ra 3 hoạ tiết khi bạn chỉ cần 1.

Có kích thước cố định, bạn có thể cập nhật kết cấu bằng glTexSubImage2D thay vì glTexImage2D. Dưới đây là mã của bạn được sửa đổi để tránh rò rỉ bộ nhớ khỏi sự cố này:

texture_data = new GLubyte[width*height](); 
GLuint texname; //handle to a texture 
glGenTextures(1, &texname); //Gen a new texture and store the handle in texname 

//These settings stick with the texture that's bound. You only need to set them 
//once. 
glBindTexture(GL_TEXTURE_2D, texname); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

//allocate memory on the graphics card for the texture. It's fine if 
//texture_data doesn't have any data in it, the texture will just appear black 
//until you update it. 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, 
    GL_UNSIGNED_BYTE, texture_data); 

... 

//bind the texture again when you want to update it. 
glBindTexture(GL_TEXTURE_2D, texname); 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, 0, GL_RGB, 
    GL_UNSIGNED_BYTE, texture_data); 

... 

//When you're done using the texture, delete it. This will set texname to 0 and 
//delete all of the graphics card memory associated with the texture. If you 
//don't call this method, the texture will stay in graphics card memory until you 
//close the application. 
glDeleteTextures(1, &texname); 
+0

Cảm ơn rất nhiều, tôi đã đăng mã, Vì vậy, như bạn có thể thấy rằng tôi sử dụng cùng một bộ nhớ chỉ cần thay đổi nội dung và luôn luôn làm điều tương tự. Vì vậy, theo đề xuất của bạn trong đoạn mã trên, tôi chỉ cần gọi "glGenTextures" một lần và sau đó luôn gọi glBindTexture và glTexImage2D. Nó sẽ ngăn chặn rò rỉ bộ nhớ. Tôi có đúng không? – Shan

+1

@Shan cập nhật câu trả lời của tôi với mã và (hy vọng) đủ giải thích để bạn hiểu nơi rò rỉ đến từ bên trong mã của bạn và cách khắc phục nó. Cũng sử dụng hướng dẫn OpenGL trong tương lai, nó rất hữu ích trong việc giải thích chính xác những gì phương pháp OpenGL làm: http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml –

+0

cảm ơn rất nhiều, Câu trả lời tuyệt vời!, thực sự tôi đã cập nhật mã, Nó đã được điều sai lầm, loại là GLuint cho texname.Just một truy vấn, tôi có nhiều hơn một kết cấu, làm thế nào glTexSubImage2D sẽ biết cái nào tôi đang cập nhật? hoặc đó là do cuộc gọi đến glBindTexture. – Shan