2010-07-29 43 views
7

tôi có một lớp vẽ và xoay khối lập phương. mỗi khi tôi xoay khối lập phương tôi tải lại bộ đệm với các giá trị mới cho khối lập phương.Ngoại lệ OutOfMemory khi vẽ hình khối

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); 
    } 

sau đó gọi phương thức Cube.Draw trong 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); 
    } 

sau một vài phút hoặc lâu hơn tôi nhận được một ngoại lệ OutOfMemory trên dòng:

buffer.SetData<VertexPositionNormalTexture>(verts); 

có thể ai đó hãy giải thích tại sao điều này xảy ra và những gì tôi có thể làm để giải quyết nó.

+0

Hi , @harryovers, bạn đã tìm thấy một công việc xung quanh, với loại "BUG", tôi cảm thấy quá buồn khi chọn XNA. –

+0

@DuSijun tôi đã làm điều này để làm việc nhưng nó là 2.5 năm trước vì vậy tôi thực sự không nhớ nhiều chi tiết về nó xin lỗi. – harryovers

Trả lời

8

Bộ đệm Vertex là tài nguyên không được quản lý. Người thu gom rác không biết rằng họ đang sử dụng toàn bộ bộ nhớ không được quản lý (và tài nguyên GPU) đằng sau hậu trường. Tất cả những gì nó biết là bộ nhớ được quản lý nhỏ bé mà mỗi người sử dụng.

Tôi nói thêm về tài nguyên không được quản lý trong XNA theo số my answer to this question.

Bạn có thể gọi Dispose() trên mỗi VertexBuffer trước khi bạn bị rò rỉ (nhưng sau khi vẽ xong, vì nó sẽ vẫn được sử dụng!), Để giải phóng tài nguyên không được quản lý. Điều này sẽ tránh được lỗi bộ nhớ, nhưng vẫn sẽ rất chậm!

Điều bạn thực sự nên làm là tạo bộ đệm đỉnh tối thiểu cần thiết chỉ một lần. Nơi lý tưởng để thực hiện việc này là trong chức năng LoadContent của bạn (và sau đó Dispose() chúng trong chức năng UnloadContent của bạn). Nếu bạn có một bó toàn bộ khối, tất cả những gì bạn cần là một bộ đệm đỉnh đơn mô tả một khối lập phương, mà bạn sử dụng lại mỗi khi bạn vẽ một khối lập phương.

Rõ ràng là bạn không muốn vẽ tất cả hình khối của mình ở cùng một nơi. Đây là những gì ma trận Thế giới dành cho. Mỗi khi bạn vẽ một hình lập phương, hãy đặt BasicEffect.World thành ma trận biến đổi của bạn cho hình khối đó và gọi Apply().

(Cách bạn đang thiết WorldViewProj trực tiếp là ok quá. Nhưng sử dụng API tốt đẹp là, tốt, đẹp hơn.)

Nếu luân chuyển là những gì bạn muốn, sử dụng Matrix.CreateFromYawPitchRoll(yaw, pitch, roll) để tạo ra ma trận chuyển đổi của bạn.

Để biết thêm chi tiết về vấn đề này, sự cố của bạn tương tự như another question I have answered.

(Lưu ý rằng, nếu các đỉnh tự thực sự làm thay đổi mỗi khung hình, bạn nên sử dụng DrawUserPrimitives. Nhưng lưu ý rằng đây vẫn là đáng kể chậm hơn so với để cho vertex shader trên GPU xử lý bất kỳ biến đổi.)

0

Dường như bạn đang tạo bộ đệm đỉnh mới mỗi khung và không cho phép ảnh cũ bị rơi ra khỏi phạm vi để thu gom rác thải. Trong thực tế, bạn đang làm điều này cho mỗi khối của bạn.

Cách tiếp cận tốt hơn là chỉ cập nhật giá trị đỉnh mỗi khung hình hoặc tốt hơn vẫn cập nhật biến đổi trên khối lập phương mỗi khung hình.

+0

Tất cả các tham chiếu đến mỗi bộ đệm đều bị loại bỏ, vì vậy tôi sẽ cho rằng nếu bộ thu gom rác là bất kỳ tốt nào cần biết để xóa bộ đệm không còn sử dụng cũ. Nó không giống như các bộ đệm cũ đang được lưu trữ trong một danh sách hoặc một cái gì đó. Liệu tôi có sai? Trong mọi trường hợp, nó chắc chắn không phải là cách để đi, như phân bổ lặp đi lặp lại và deallocation là khủng khiếp không hiệu quả, như hành động của "VertexBuffer mới" với mỗi cuộc gọi đến LoadBuffer. – Ricket

+0

@ Ricket - sự phân bổ lặp đi lặp lại là thứ đã đánh tôi, và không có bằng chứng nào ngược lại chính nó cho ý tưởng rằng bộ đệm cũ không được giải thoát. – ChrisF

+0

@Ricket GC không biết về các tài nguyên không được quản lý sao lưu các bộ đệm đỉnh. Đó là lý do tại sao nó nghĩ rằng nó có nhiều bộ nhớ, khi nó không. –

Các vấn đề liên quan