gpt4 book ai didi

c# - 使用单例 PixelShader 应该是最佳实践吗?

转载 作者:太空狗 更新时间:2023-10-29 17:56:02 26 4
gpt4 key购买 nike

在微软的example对于如何使用 PixelShader,他们使用单例。我在 other places 中看到了相同的模式, 他们在这里说

The pixel shader is stored in a private static field _pixelShader. This field is static, because one instance of the compiled shader code is enough for the whole class.

我们在使用此模式时遇到了几个内存泄漏问题。 PixelShader 涉及的事件处理并不总是正确清除。我们不得不freeze他们,并看到了一些改进。我们不得不手动进行一些分离

        // Attach/detach effect as UI element is loaded/unloaded.  This avoids
// a memory leak in the shader code as described here:
element.Loaded += (obj, args) =>
{
effect.PixelShader = ms_shader;
element.Effect = effect;
};
element.Unloaded += (obj, args) =>
{
effect.PixelShader = null;
element.Effect = null;
};

即使在压力下,该区域仍然存在内存泄漏。有谁知道 PixelShader 使用繁重的资源是否值得使用单例?

最佳答案

绝对没有。然而,原因不在于 PixelShader 本身,而在于它在 ShaderEffect 中的使用。
几乎所有 WPF 自定义着色器效果的实现都基于 Microsoft 的 .NET 3.5 示例,这些示例未针对 .NET 4.0 进行更新。可以为所有效果使用单例 PixelShader 实例,它仅支持 ps_2_0 着色器。在 .NET 4.0 中,Microsoft 引入了对 ps_3_0 像素着色器(用于 GPU 加速设备)的支持,并因此将内存泄漏引入了 ShaderEffect 类。
ShaderEffect 跟踪它的 PixelShader 属性,并通过强订阅名为 _shaderBytecodeChanged 的 PixelShader 内部事件来检查它没有使用 ps_2_0 字节码的 ps_3_0 寄存器。因此,多个 ShaderEffect 实例使用的单例 PixelShader 充当 GC 的支配根,并重新保留与相应 ShaderEffect 的任何实例一起使用的所有对象。即known memory leak ,这不会被修复。
如果您想将 PixelShader 用作无泄漏的单例,那么您将不得不使用运行时黑客:每次将 PixelShader 实例分配给 PixelShader ShaderEffect 类的属性,PixelShader 实例的 _shaderBytecodeChanged 字段应手动清除,例如:

var ei = typeof(PixelShader).GetEvent("_shaderBytecodeChanged",
BindingFlags.Instance | BindingFlags.NonPublic);
var fi = typeof(PixelShader).GetField(ei.Name,
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(pixelShader,null);

当然,这些操作可以通过 DynamicMethod 基础设施或类似机制在运行时生成辅助方法来优化。但是,这应该仅用于肯定是 ps_2_0 或肯定是 ps_3_0 的着色器

关于c# - 使用单例 PixelShader 应该是最佳实践吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33176446/

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