gpt4 book ai didi

wpf - D3DImage 和 SharpDX 在慢速硬件上闪烁

转载 作者:行者123 更新时间:2023-12-03 12:44:27 24 4
gpt4 key购买 nike

我正在将 SharpDX.WPF 项目用于 WPF 功能,与 SharpDX 附带的工具包相比,它似乎是一个易于理解的低开销库(具有相同的问题!)

首先:我使用以下方法为最新的 SharpDX 修复了 SharpDX.WPF 项目:https://stackoverflow.com/a/19791534/442833

然后我对 DXElement.cs 进行了以下 hacky 调整,解决方案也做了 here :

private Query queryForCompletion;
public void Render()
{
if (Renderer == null || IsInDesignMode)
return;

var test = Renderer as D3D11;
if (queryForCompletion == null)
{

queryForCompletion = new Query(test.Device,
new QueryDescription {Type = QueryType.Event, Flags = QueryFlags.None});
}

Renderer.Render(GetDrawEventArgs());

Surface.Lock();
test.Device.ImmediateContext.End(queryForCompletion);
// wait until drawing completes
Bool completed;
var counter = 0;
while (!(test.Device.ImmediateContext.GetData(queryForCompletion, out completed)
&& completed))
{
Console.WriteLine("Yielding..." + ++counter);
Thread.Yield();
}
//Surface.Invalidate();
Surface.AddDirtyRect(new Int32Rect(0, 0, Surface.PixelWidth, Surface.PixelHeight));
Surface.Unlock();
}

然后我以立方体模式渲染 8000 个立方体......

Yielding...



经常打印到控制台,但闪烁仍然存在。
我假设 WPF 足以在渲染完成之前使用不同的线程显示图像,但不确定......
当我将 WPF 支持的 Toolkit 变体与 SharpDX 一起使用时,也会发生同样的问题。

展示问题的图片:
  • Bad
  • Better
  • Almost
  • Intended

  • 注意:它在这些旧图像之间随机切换,随机。我还在使用非常旧的硬件,这使得闪烁更加明显(GeForce Quadro FX 1700)

    A 做了一个 repo ,其中包含与我用来解决此问题的完全相同的源代码:
    https://github.com/ManIkWeet/FlickeringIssue/

    最佳答案

    相关 D3DImage锁定,注意 D3DImage.TryLock API 具有大多数开发人员不会想到的非常规语义:

    Beware!
    You must call Unlock even in the case where TryLock indicates failure (i.e., returns false)



    虽然可能更多的是 惊人的设计选择与错误本身相比,误解这种行为会很容易导致 D3DImage 死锁和挂起,因此可能是人们在尝试获取 D3DImage 时遇到的大部分挫败感的原因。好好工作。

    以下代码是正确的 WPF D3D 渲染,在我的应用程序中没有闪烁:
    void WPF_D3D_render(IntPtr pSurface)
    {
    if (TryLock(new Duration(default(TimeSpan))))
    {
    SetBackBuffer(D3DResourceType.IDirect3DSurface9, pSurface);
    AddDirtyRect(new Int32Rect(0, 0, PixelWidth, PixelHeight));
    }
    Unlock(); // <--- !
    }

    是的,这个不直观的代码实际上是正确的;就是这样 D3DImage.TryLock(0) 泄漏一个内部 D3D 缓冲区锁 每次它返回失败。您不必相信我的话,这是来自 PresentationCore.dll 的 CLR 代码v4.0.30319:
    private bool LockImpl(Duration timeout)
    {
    bool flag = false;

    if (_lockCount == uint.MaxValue)
    throw new InvalidOperationException();

    if (_lockCount == 0)
    {
    if (timeout == Duration.Forever)
    flag = _canWriteEvent.WaitOne();
    else
    flag = _canWriteEvent.WaitOne(timeout.TimeSpan, false);

    UnsubscribeFromCommittingBatch();
    }
    _lockCount++;
    return flag;
    }

    请注意,内部 _lockCount无论函数返回成功还是失败,字段都会递增。您必须调用 Unlock()你自己,如上面的第一个代码示例所示,如果你想避免某些死锁。如果不这样做,调试起来也很麻烦,因为组件在下一次渲染之前不会(可能)死锁,到那时相关的证据早就不复存在了。

    MSDN 中似乎没有提到异常行为。 ,但公平地说,该文档没有指出您必须调用 Unlock()如果通话成功,要么。

    enter image description here

    关于wpf - D3DImage 和 SharpDX 在慢速硬件上闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27358128/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com