2010-07-29 57 views
7

我有一個繪製和旋轉立方體的類。每次我旋轉立方體我重新加載與立方體的新值的緩衝區。OutOfMemory繪製立方體時出現異常

public void LoadBuffer(GraphicsDevice graphicsDevice) 
    { 
     buffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, triangles * 3, BufferUsage.None); 
     buffer.SetData<VertexPositionNormalTexture>(verts); 
     graphicsDevice.SetVertexBuffer(buffer); 
    } 

    public void Draw(GraphicsDevice graphicsDevice) 
    { 
     graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, triangles); 
    } 

然後調用Cube.Draw方法Game.Draw

protected override void Draw(GameTime gameTime) 
    { 
     GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.White, 1f, 0); 

     basicEffect.Parameters["WorldViewProj"].SetValue(world * view * projection); 

     EffectPass pass = basicEffect.CurrentTechnique.Passes[0]; 
     if (pass != null) 
     { 
      pass.Apply(); 
      cube1.LoadBuffer(GraphicsDevice); 
      cube1.Draw(GraphicsDevice); 
      cube2.LoadBuffer(GraphicsDevice); 
      cube2.Draw(GraphicsDevice); 
      cube3.LoadBuffer(GraphicsDevice); 
      cube3.Draw(GraphicsDevice); 
     } 
     base.Draw(gameTime); 
    } 

幾分鐘後,還是讓我得到就行了內存溢出異常:

buffer.SetData<VertexPositionNormalTexture>(verts); 

有人能請解釋爲什麼會發生這種情況,以及我能做些什麼來解決這個問題。

+0

喜,@harryovers,你有沒有找到解決辦法,帶着這種「BUG」,我覺得選擇XNA太難過了。 – 2013-01-06 14:38:37

+0

@DuSijun我確實得到了這個工作,但它是2。5年前,所以我真的不記得很多關於它的細節抱歉。 – harryovers 2013-01-23 19:07:22

回答

8

頂點緩衝區是非託管資源。垃圾收集器不知道他們在幕後使用了大量非託管內存(和GPU資源)。它所知道的僅僅是每個人使用的管理內存的一小部分。

我會講更多關於XNA中的非託管資源my answer to this question

在泄漏之前(但是在完成繪圖之後,因爲它仍然在使用!),您可以在每個VertexBuffer上調用Dispose(),以釋放非託管資源。這將避免內存不足的錯誤,但仍然會很慢!

你真的應該做的是創建最小必要的頂點緩衝區只有一次。做這個的理想場所是在你的LoadContent功能(然後Dispose()他們在你的UnloadContent功能)。如果您有大量的多維數據集,您只需要一個描述多維數據集的頂點緩衝區,每次繪製多維數據集時都要重複使用。

很明顯,你不想在同一個地方繪製所有的立方體。這是世界矩陣的用途。每次繪製立方體時,請將BasicEffect.World設置爲該立方體的轉換矩陣,並調用Apply()

(您直接設置WorldViewProj的方式是確定了。但是用漂亮的API,沒錯,是更好)。

如果旋轉是你想要什麼,用Matrix.CreateFromYawPitchRoll(yaw, pitch, roll)來創建變換矩陣。

有關這方面的更多詳細信息,您的問題與another question I have answered類似。

(需要注意的是,如果頂點自己確實改變每一幀,你應該使用DrawUserPrimitives。但是請注意,這仍然是相當不是讓頂點着色器在GPU上處理任何轉換慢。)

0

它看起來像你每幀創建一個新的頂點緩衝區,並且不允許舊的緩衝區超出範圍被垃圾收集。事實上,你正在爲每個立方體做這件事。

更好的方法是更新每個幀的頂點值,或者更好地更新每個幀的立方體變換。

+0

所有對每個緩衝區的引用都被刪除了,所以我會爭辯說,如果垃圾收集器是好的,它應該知道刪除舊的不再使用的緩衝區。它不像舊的緩衝區被存儲在列表或其他東西中。我錯了嗎?在任何情況下,它肯定不是要走的路,因爲重複的分配和釋放非常低效,因爲每次調用LoadBuffer時都會使用「新VertexBuffer」進行操作。 – Ricket 2010-07-29 19:06:15

+0

@Ricket - 重複的分配是令我感到震驚的事情,沒有任何相反的證據可以使它意識到舊緩衝區沒有被釋放。 – ChrisF 2010-07-29 19:40:20

+0

@Ricket GC不知道支持頂點緩衝區的非託管資源。這就是爲什麼它認爲它有很多記憶,當它沒有。 – 2010-07-30 07:31:56