有没有办法检查Texture2D当前是否未使用,以便我可以对其执行SetData()?

问题描述 投票:0回答:3

尝试在最近由 SpriteBatch 进行 Draw()-n 的 Texture2D 上执行 SetData() 会导致以下异常:

操作被中止。您不得修改已在设备上设置的资源,或在平铺括号内使用该资源后的资源。

我可以提前判断执行SetData()是否会抛出这个异常吗?

c# vb.net xna
3个回答
1
投票

基本上,您有三种选择:

1)查看SpriteBatch是否完成其操作,然后调用SetData()。绘图方法通常是异步的。这意味着,它们只是被添加到 please-render-me 队列中,并且该方法立即返回。您需要的是绘图完成时的回调通知或同步调用 Draw()。

2) 避免 SetData() 被中断。您可以通过将其放入我不推荐的关键部分来做到这一点。应该可以锁定纹理数据。在Direct3D中叫做LockRect(),在XNA中应该类似。

3)应该有一些像 Flush() 这样的方法等待所有与图形相关的操作完成。

抱歉提供了相当模糊的帮助,但您应该能够从 XNA 文档中找到方法名称。


1
投票

我通过创建两个纹理并在活动纹理之间切换(本质上是双缓冲)解决了这样的问题:

void CreateTextures()
{

  depth_1 = new Texture2D(this.GraphicsDevice, width, height, false, SurfaceFormat.Single);
  depth_2 = new Texture2D(this.GraphicsDevice, width, height, false, SurfaceFormat.Single);

  depth_current = depth_1;

  ...

}

void Draw(GameTime gt)
{
  depth_current = depth_current == depth_1 ? depth_2 : depth_1;
  Depth.SetData(this.DepthBuffer);

  ...

}

就我而言,无法将

SetData
移到 Draw 之外,但我认为这是最好的方法。


1
投票

基本上没有。

最简单的方法是仅在

SetData
方法中调用
Update

SetData
方法中使用
Draw
是不好的做法,因为设备可能会使用旧数据执行各种巫毒魔法。 其 MSDN 页面上的“警告”框中对此进行了详细解释

现在,直到 XNA 3.1,您都可以将

SetDataOptions
Texture2D.SetData
一起使用。但看起来该功能已在 XNA 4.0 中删除了纹理。

Shawn Hargreaves 在此解释 如何使用 SetDataOptions

 告诉 GPU“实际上是的,我
确实想要覆盖您可能正在使用的数据,请不要抱怨”。以及为什么很难做到正确。

© www.soinside.com 2019 - 2024. All rights reserved.