2

我有一个具体的问题。

在调整窗口大小以更改分辨率后,我一直在尝试重置 SlimDX9 设备。一切都在 Pool.Managed 中,没有字体,没有状态块,一切正常,但纹理+表面+RenderToSurface 组合。我需要纹理作为着色器的渲染目标,以便稍后进行后处理,所以我需要它调整大小以适应客户端大小以及后缓冲区。

我确实创建了这样的组合:

rtTexture = new Texture(this.Device, this.owner.ClientSize.Width, this.owner.ClientSize.Height, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);
rtSurface = rtTexture.GetSurfaceLevel(0);
rtHelper = new RenderToSurface(this.Device, this.owner.ClientSize.Width, this.owner.ClientSize.Height, Format.A8R8G8B8, Format.D24S8);

调整窗口大小时,我会

rtTexture.Dispose();
rtSurface.Dispose();

我都试过了

rtHelper.OnLostDevice();

rtHelper.Dispose();

当然,在 Device.Reset(getParameters()) 之后我重新创建资源/调用 rtHelper.OnResetDevice(),两者都不起作用。我尝试了 Dispose()s 和 OnDeviceLost() 的所有可能组合。

在不成功的重置和通常的 InvalidCall 之后,我收到了这条消息

All user created D3DPOOL_DEFAULT surfaces must be freed before ResetEx can succeed. ResetEx Fails.

所以我对应用程序进行了 PIX 处理,发现纹理和表面都没有被处理(在被破坏的列中有“从不”)尽管事实是 .Dispose() 在这两个对象上都被显式调用并且 IsDisposed 在之前是真的Device.Reset()。

删除组合使重置正常。问题出在 RenderToSurface 重置和/或纹理+表面的某个地方。

我像这样使用 RenderToSurface:

rtHelper.BeginScene(rtSurface, new Viewport(0, 0, this.owner.ClientSize.Width, this.owner.ClientSize.Height));
{
    Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, FogColor, 1, 0);
    terrainEffect.BeginPass(0);
    RenderTiles();
    terrainEffect.EndPass();
}
rtHelper.EndScene(Filter.None);

甚至可能吗?它是 SlimDX 中的错误吗?我能做些什么?我可以以某种方式访问​​非托管资源并手动销毁它们吗?

请帮忙,我不知道下一步该怎么做。我非常感谢对此的任何回应。谢谢。

编辑:我试图绕过 RenderToSurface 并使用 Device.get/setRenderTarget(),但问题仍然存在,在 Device.Reset() 之前,Dispose() 不会破坏表面和纹理。

4

1 回答 1

1

我已经想通了!对于遇到相同问题的任何人:

如果您使用在一个着色器通道中创建的纹理,将其分配给着色器并在第二个通道中使用,请务必在使用后(之前Device.Present())将纹理设置为null. 像这样:

terrainEffect.SetTexture(hRTTexture, null);

wherehRTTexture是纹理的处理程序。似乎着色器锁定了纹理,并且如果着色器具有此锁定,SlimDX 无法处理此类纹理(和关联的表面)。

希望这可以帮助某人。

于 2013-01-05T01:43:04.823 回答