Monogame RenderTarget2D 填满显卡内存
Monogame RenderTarget2D filling up graphic card memory
我在尝试在 Monogame 中创建 Post 处理器 class 时遇到问题。
我的显卡内存在几秒钟内就满了,我不明白为什么。
我已经 post在 Monogame 社区论坛中解决了完整的问题。但也许其他人可以帮助我解决问题。
参考 Monogame 社区 post:http://community.monogame.net/t/problem-with-rendertarget2d-fills-up-the-graphic-card-memory/2730/3
我已经在 Monogame 社区论坛上描述了这个问题。
我已经解决了我的问题,现在我的后处理器看起来像这样:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Brick
{
class Postprocessor
{
private Effect CurrentEffect;
private Effect DefaultEffect;
private bool Multipass;
private RenderTarget2D FinalImage;
private RenderTarget2D EmptyTarget;
public int Passescount
{
get
{
return CurrentEffect.CurrentTechnique.Passes.Count;
}
}
public Postprocessor(Effect EffectToUse, Effect StandardEffect)
{
if (!ChangeCurrentEffect(EffectToUse))
return;
DefaultEffect = StandardEffect;
EmptyTarget = new RenderTarget2D(DefaultEffect.GraphicsDevice, GameSettings.WindowWidth, GameSettings.WindowHeight);
}
public bool ChangeCurrentEffect(Effect EffectToUse)
{
CurrentEffect = EffectToUse;
if (CurrentEffect.CurrentTechnique.Passes.Count > 1)
Multipass = true;
else
Multipass = false;
return true;
}
private bool CheckIfParameterExist(string Name)
{
foreach (EffectParameter parameter in CurrentEffect.Parameters)
{
if (parameter.Name == Name)
return true;
}
return false;
}
public void Update(GameTime gametime, Vector2 MousePosition)
{
SetParameters((float)gametime.TotalGameTime.TotalSeconds, MousePosition);
}
private void SetParameters(float gametime, Vector2 MousePosition)
{
if (CheckIfParameterExist("GameTime"))
CurrentEffect.Parameters["GameTime"].SetValue(gametime);
if (CheckIfParameterExist("MousePosition"))
CurrentEffect.Parameters["MousePosition"].SetValue(MousePosition);
}
public void Draw(GraphicsDevice graphics, RenderTarget2D Target, SpriteBatch SB)
{
if (Multipass)
{
FinalImage = MultiCallPostprocess(graphics, SB, Target);
}
else
{
FinalImage = SinglePostprocessCall(graphics, SB, Target, 0);
}
graphics.Clear(Color.Transparent);
DefaultEffect.CurrentTechnique.Passes[0].Apply();
SB.Draw(FinalImage, new Rectangle(0, 0, FinalImage.Width, FinalImage.Height), Color.White);
}
private RenderTarget2D MultiCallPostprocess(GraphicsDevice graphics, SpriteBatch SB, RenderTarget2D DrawTarget)
{
for (int i = 0; i < CurrentEffect.CurrentTechnique.Passes.Count; i++)
{
DrawTarget = SinglePostprocessCall(graphics, SB, DrawTarget, i);
}
return DrawTarget;
}
private RenderTarget2D SinglePostprocessCall(GraphicsDevice graphics, SpriteBatch SB, RenderTarget2D DrawTarget, int PassPosition)
{
EmptyTarget.Dispose();
EmptyTarget = new RenderTarget2D(graphics, DrawTarget.Width, DrawTarget.Height);
if (CurrentEffect.CurrentTechnique.Passes.Count >= PassPosition)
{
graphics.SetRenderTarget(EmptyTarget);
graphics.Clear(Color.Transparent);
CurrentEffect.CurrentTechnique.Passes[PassPosition].Apply();
SB.Draw(DrawTarget, new Rectangle(0, 0, DrawTarget.Width, DrawTarget.Height), Color.White);
graphics.SetRenderTarget(null);
}
else
{
EmptyTarget = DrawTarget;
}
return CloneRenderTarget(EmptyTarget);
}
private RenderTarget2D CloneRenderTarget(RenderTarget2D target)
{
var clone = new RenderTarget2D(target.GraphicsDevice, target.Width,
target.Height, target.LevelCount > 1, target.Format,
target.DepthStencilFormat, target.MultiSampleCount,
target.RenderTargetUsage);
for (int i = 0; i < target.LevelCount; i++)
{
double rawMipWidth = target.Width / Math.Pow(2, i);
double rawMipHeight = target.Height / Math.Pow(2, i);
// make sure that mipmap dimensions are always > 0.
int mipWidth = (rawMipWidth < 1) ? 1 : (int)rawMipWidth;
int mipHeight = (rawMipHeight < 1) ? 1 : (int)rawMipHeight;
var mipData = new Color[mipWidth * mipHeight];
target.GetData(i, null, mipData, 0, mipData.Length);
clone.SetData(i, null, mipData, 0, mipData.Length);
}
return clone;
}
}
}
重要的功能是 "CloneRenderTarget" 似乎从没有此功能的旧 RenderTarget2D 创建一个新的 RenderTarget2D 它只是创建一个指针,因此如果您处置副本,原始副本也会被处置。
我在尝试在 Monogame 中创建 Post 处理器 class 时遇到问题。
我的显卡内存在几秒钟内就满了,我不明白为什么。
我已经 post在 Monogame 社区论坛中解决了完整的问题。但也许其他人可以帮助我解决问题。
参考 Monogame 社区 post:http://community.monogame.net/t/problem-with-rendertarget2d-fills-up-the-graphic-card-memory/2730/3
我已经在 Monogame 社区论坛上描述了这个问题。
我已经解决了我的问题,现在我的后处理器看起来像这样:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Brick
{
class Postprocessor
{
private Effect CurrentEffect;
private Effect DefaultEffect;
private bool Multipass;
private RenderTarget2D FinalImage;
private RenderTarget2D EmptyTarget;
public int Passescount
{
get
{
return CurrentEffect.CurrentTechnique.Passes.Count;
}
}
public Postprocessor(Effect EffectToUse, Effect StandardEffect)
{
if (!ChangeCurrentEffect(EffectToUse))
return;
DefaultEffect = StandardEffect;
EmptyTarget = new RenderTarget2D(DefaultEffect.GraphicsDevice, GameSettings.WindowWidth, GameSettings.WindowHeight);
}
public bool ChangeCurrentEffect(Effect EffectToUse)
{
CurrentEffect = EffectToUse;
if (CurrentEffect.CurrentTechnique.Passes.Count > 1)
Multipass = true;
else
Multipass = false;
return true;
}
private bool CheckIfParameterExist(string Name)
{
foreach (EffectParameter parameter in CurrentEffect.Parameters)
{
if (parameter.Name == Name)
return true;
}
return false;
}
public void Update(GameTime gametime, Vector2 MousePosition)
{
SetParameters((float)gametime.TotalGameTime.TotalSeconds, MousePosition);
}
private void SetParameters(float gametime, Vector2 MousePosition)
{
if (CheckIfParameterExist("GameTime"))
CurrentEffect.Parameters["GameTime"].SetValue(gametime);
if (CheckIfParameterExist("MousePosition"))
CurrentEffect.Parameters["MousePosition"].SetValue(MousePosition);
}
public void Draw(GraphicsDevice graphics, RenderTarget2D Target, SpriteBatch SB)
{
if (Multipass)
{
FinalImage = MultiCallPostprocess(graphics, SB, Target);
}
else
{
FinalImage = SinglePostprocessCall(graphics, SB, Target, 0);
}
graphics.Clear(Color.Transparent);
DefaultEffect.CurrentTechnique.Passes[0].Apply();
SB.Draw(FinalImage, new Rectangle(0, 0, FinalImage.Width, FinalImage.Height), Color.White);
}
private RenderTarget2D MultiCallPostprocess(GraphicsDevice graphics, SpriteBatch SB, RenderTarget2D DrawTarget)
{
for (int i = 0; i < CurrentEffect.CurrentTechnique.Passes.Count; i++)
{
DrawTarget = SinglePostprocessCall(graphics, SB, DrawTarget, i);
}
return DrawTarget;
}
private RenderTarget2D SinglePostprocessCall(GraphicsDevice graphics, SpriteBatch SB, RenderTarget2D DrawTarget, int PassPosition)
{
EmptyTarget.Dispose();
EmptyTarget = new RenderTarget2D(graphics, DrawTarget.Width, DrawTarget.Height);
if (CurrentEffect.CurrentTechnique.Passes.Count >= PassPosition)
{
graphics.SetRenderTarget(EmptyTarget);
graphics.Clear(Color.Transparent);
CurrentEffect.CurrentTechnique.Passes[PassPosition].Apply();
SB.Draw(DrawTarget, new Rectangle(0, 0, DrawTarget.Width, DrawTarget.Height), Color.White);
graphics.SetRenderTarget(null);
}
else
{
EmptyTarget = DrawTarget;
}
return CloneRenderTarget(EmptyTarget);
}
private RenderTarget2D CloneRenderTarget(RenderTarget2D target)
{
var clone = new RenderTarget2D(target.GraphicsDevice, target.Width,
target.Height, target.LevelCount > 1, target.Format,
target.DepthStencilFormat, target.MultiSampleCount,
target.RenderTargetUsage);
for (int i = 0; i < target.LevelCount; i++)
{
double rawMipWidth = target.Width / Math.Pow(2, i);
double rawMipHeight = target.Height / Math.Pow(2, i);
// make sure that mipmap dimensions are always > 0.
int mipWidth = (rawMipWidth < 1) ? 1 : (int)rawMipWidth;
int mipHeight = (rawMipHeight < 1) ? 1 : (int)rawMipHeight;
var mipData = new Color[mipWidth * mipHeight];
target.GetData(i, null, mipData, 0, mipData.Length);
clone.SetData(i, null, mipData, 0, mipData.Length);
}
return clone;
}
}
}
重要的功能是 "CloneRenderTarget" 似乎从没有此功能的旧 RenderTarget2D 创建一个新的 RenderTarget2D 它只是创建一个指针,因此如果您处置副本,原始副本也会被处置。