Unreal Engine

Counting memory in UE4

UE4 has many stats and memory counting mechanisms with great tools to display it. Unfortunately useful tools, like Statistics window or Size Map, display not really useful data. Major problem is that in-editor memory is reported and not memory for a cooked game. Another problem is that even this memory is not always properly counted. Under the hood UE4 has two memory size counting mechanisms. One is serialization based and uses FArchiveCountMem serializer. Another is based on calling a special GetResourceSizeEx virtual function defined in UObject. You can see both used in functions like UEngine::HandleListStaticMeshesCommand. Digging deeper you can see that in fact GetResourceSizeEx internally uses FArchiveCountMem to count memory of a current object.

During my work on UE4 based games (Evil West and Shadow Warrior 3) counting memory properly was a top priority. Therefore I modified memory counting mechanisms to count memory for specific cooked platforms. Using this corrected counting mechanism I was able to create easy to use level streaming budgets (displayed in the viewport) and assets’ budgets based on Data Validation interface (https://docs.unrealengine.com/en-US/ProgrammingAndScripting/ProgrammingWithCPP/Assets/DataValidation/index.html).

Creating GI Multiplier: useful custom output material node

Our team was creating cutscenes for the game and they had problems setting up proper lighting. We generally use stationary lights, because we want precomputed GI and shadows for the game. Unfortunately the cutscene team was unable to get rid of GI on characters, without modifying lighting on the environment. Custom code was needed. At first I thought I would have to add another output to the main material node, but while looking inside the code I realised that I can create a custom output node. I used UMaterialExpressionBentNormalCustomOutput as my template. Work on C++ side consisted of creating the node and registering it in FMaterialAttributeDefinitionMap::InitializeAttributeMap.

AddCustomAttribute(FGuid(0x2E5E2BF3, 0x646F4531, 0x8E36B5C0, 0xA8055AFB), "GIMultiplier", "GIMultiplier", MCT_Float1, FVector4(1, 0, 0, 0));

The engine created a shader define and function for me. On HLSL side I just used them in GetPrecomputedIndirectLightingAndSkyLight function in BasePassPixelShader.ush

  float GIMultiplier = saturate(GIMultiplier0(MaterialParameters));
  OutDiffuseLighting *= GIMultiplier;
  OutSubsurfaceLighting *= GIMultiplier;

When my node was ready I placed it together with a parameter from Material Parameter Collection in base materials for characters. Now our cutscene lighting artist is able to use it inside a sequencer to scale GI to his wish.

Debugging texture streaming in UE4

Today I was working on a problem with impostor texture streaming in UE4. I was not satisfied with the possibility of disabling the streaming for those textures, because they are quite large. I also found out that generating material streaming information does not work properly, because it reads GameThreadShaderMap that, as the comment states, is loaded from cooked assets and not available in the editor. This is a topic for further investigation, though. Meanwhile my solution was to modify FStreamingTexture::GetExtraBoost function, adding a branch for impostor texture groups with a boost value of 16.

I found some useful console variables and a command during the process. Here they are:

r.Streaming.DropMips 2 - disables mip map caching, not needed mip levels will be unstreamed immediately

r.Streaming.FullyLoadUsedTextures 1 – forces loading of an entire mip chain

r.Streaming.Boost <value> - global wanted texture size multiplier

InvestigateTexture <texture name> - displays streaming information  for a texture in a console window, most notably the highest loaded mip  level