如重现步聚
重现步骤
我们使用的是5.4的引擎,最近发现一个CustomDepth和CustomStencil复用的bug。
在使用GPUScene的情况下几乎必现,在不使用GPUScene的情况下播放了特效是偶现。
具体表现为,CustomDepth和CustomStencil被复用了。
抓帧贴图如下:
正常情况下,customdepth使用的是customdepth
[Image Removed]
出bug的情况下,customdepth使用的是customstencil
[Image Removed]
大概猜测原因是:
opengl中,不支持d3d11那样的类型化SRV。
而5.4的实现方式:
1.深度访问:使用原始的深度模板纹理,保持默认的GL_DEPTH_COMPONENT模式
2.模板访问:创建PF_X24_G8格式的SRV时,5.4会将这个opengl纹理对象绑定到新的纹理单元。
目测这种机制是用两个不同状态配置的纹理绑定来模拟d3d11中一个纹理的两种不同类型化视图。
基于上述实现机制,当深度/模板纹理(PF_DepthStecil)被用作PF_X24_G8格式的SRV时,会修改纹理的opengl状态:
GL_DEPTH_STENCIL_TEXTURE_MODE 被设为 GL_STENCIL_INDEX
纹理swizzle被修改为(0,R, 0, 0)
这些修改是永久性的,当此纹理从RenderTargetPool复用时,就会出现上述的bug。
有其它项目报过上述问题吗?在5.4之后版里有过修复吗?
我们自己也尝试修改了一下,可以解决问题,帮忙看看这样改有没有问题:
在RenderTargetPool.cpp中修改FinalFreeElement接口,只针对customDepth来重置状态。
[Image Removed]
RHIResetDepthStencilTextureState接口的实现如下:
[Image Removed]
Hi,
感谢提供信息,这的确应该是一个bug,能否试一下这个改动,在FOpenGLShaderResourceView::Invalidate()里面,改成如下,麻烦确认后给个反馈,谢谢。
`void FOpenGLShaderResourceView::Invalidate()
{
if (Resource && OwnsResource)
{
FOpenGLDynamicRHI::Get().InvalidateTextureResourceInCache(Resource);
FOpenGL::DeleteTextures(1, &Resource);
}
else if (!ViewDesc.IsBuffer())
{
FOpenGLTexture* Texture = FOpenGLDynamicRHI::ResourceCast(GetTexture());
auto const Info = ViewDesc.Texture.SRV.GetViewInfo(Texture);
if (Info.Format == PF_X24_G8)
{
FOpenGLDynamicRHI::Get().CachedSetupTextureStage(FOpenGL::GetMaxCombinedTextureImageUnits() - 1, Target, Resource, LimitMip, Texture->GetNumMips());
//set the texture to return the depth component, and then force the components to match D3D
glTexParameteri(Target, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
glTexParameteri(Target, GL_TEXTURE_SWIZZLE_R, GL_RED);
glTexParameteri(Target, GL_TEXTURE_SWIZZLE_G, GL_ZERO);
glTexParameteri(Target, GL_TEXTURE_SWIZZLE_B, GL_ZERO);
glTexParameteri(Target, GL_TEXTURE_SWIZZLE_A, GL_ZERO);
}
}
Resource = GL_NONE;
Target = GL_TEXTURE_BUFFER;
LimitMip = -1;
OwnsResource = false;
}`
这个改法还是会有问题,在移动前向管线上,切换高低画质时,很容易复现bug。
我们这边分析了一下,可能跟srv和texture的生命周期有关。
可能存在,srv没销毁但是texture已经销毁了的情况。
Hi,
请问上面的这个改法造成的问题具体是什么表现?还是最开始的那种问题吗?还是因为srv没销毁但是texture已经销毁了,执行到下面这行的时候因为Texture已经无效了,导致崩溃了?
FOpenGLDynamicRHI::Get().CachedSetupTextureStage(FOpenGL::GetMaxCombinedTextureImageUnits() - 1, Target, Resource, LimitMip, Texture->GetNumMips());
不是崩溃,是还是会出现customstencil/depth混用的情况。
流程有点复杂,在开gpuscene+播特效的情况下,很容易复现。
按你提供的思路,改FOpenGLShaderResourceView::Invalidate,后来我们也改了几版,还是不行,还是会触发。
只有我上面拍图的那种改法,在RenderTargetPool.cpp中修改FinalFreeElement接口,只针对customDepth来重置状态。才可以堵住所有的情况。
感谢反馈,我大概知道问题出在哪了,方便的话,麻烦再试试这个改动。如果有结果,麻烦同步一下,感谢。
[Image Removed]
这个patch文件似乎有点问题。
我这边使用的是
git version 2.49.0.windows.2
git tortoisegit 2.9.0.0
请问你打开文件也是这样吗?我又重传了一次,麻烦再试试。[Image Removed]
patch文件还是有问题,跟上面反馈一样的乱码。
你截图的改动是全的吗?全的话,我们照截图的改动测试一下。
是全的,改动就这些。
GET
hi liu wei,按这套改法可以了,问题解决了。感谢分享。