We have been investigating reports of a certain non-virtual texture not streaming in as expected, with the texture maintaining the minimum amount of mips loaded as the camera approached the mesh using it, with all mips suddenly being streamed in when the camera was enclosed in the mesh’s bounding box. The problem was noticeable in packaged builds.
The material referencing this texture was translucent. We then noticed that if we made it opaque the texture would stream in normally. Comparing the texture streaming data in packaged builds we found that the sampling scale (FMaterialTextureInfo::SamplingScale) was very different in each case. The material was just using UV0 as is to sample the texture so it was unexpected that having a different Blend Mode would affect the generated sampling scales.
We opted to take PIX captures of the texture scales generation, comparing the results of the translucent material against the opaque one. When analysing the captures we found that blending was enabled when rendering the translucent material, so despite the fact that the pixel shader calculated the same data for each texture of the material, the results stored in the render target (which are then processed on the CPU to generate the sampling scale) were different.
Having this in mind we started investigating the relevant rendering paths and found that FDebugViewModeInterface::SetDrawRenderState() was overriding the depth stencil state for DVSM_OutputMaterialTextureScales but enabled blending based on the input blend mode (taken from the relevant material).
We then made the following change in said function:
else if (DebugViewMode == DVSM_OutputMaterialTextureScales)
{
// BEGIN CHANGE
DrawRenderState.BlendState = TStaticBlendState<>::GetRHI();
// END CHANGE
DrawRenderState.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
}
And repeated our tests - this resulted in the same sampling scales being generated for the translucent and opaque versions of the material, with the texture streaming in normally at runtime in both cases.
We have checked the history of DebugViewModeInterface.cpp in Perforce - it would appear the exact change shown above was part of this file up to revision 12, with CL 45836355 having removed it. The description does not seem to indicate that the deletion of this line was part of the intent of the change (“Fix validation errors on Metal with RT1 in DebugViewModePixelShader. Previously, RT 1 could have a missing or incorrect RT bound in viewmodes that do not use DebugAux. To prevent this, a dummy texture is bound by default.”), so our thinking is that this was an unintended deletion that has led to an engine bug.
We are happy with our change and don’t foresee any problems with it but would be glad to hear your thoughts on the case.
[Attachment Removed]