Question about URuntimeVirtualTextureComponent::RequestPreload()

Hey Epic,

I tried your URuntimeVirtualTextureComponent::RequestPreload() function, but I afraid it still has some issues with adaptive virtual texture. If I have a wrong understanding, can you help me get on right track? I just copied your commit (https://github.com/EpicGames/UnrealEngine/commit/4f239f8b6af74672a94146d947eafeecda63c703) to our code base (UE5.4 for our project) for a quick test. Let me explain why I feel it does not work or may be lack of something.

URuntimeVirtualTextureComponent::RequestPreload() calls FScene::RequestPreloadRuntimeVirtualTexture() and then enqueues a command to RT, the command is to invoke the RequestPreload() function of the proxy which is constructed with a URuntimeVirtualTextureComponent.

Then in FRuntimeVirtualTextureSceneProxy::RequestPreload(), it passes the member variable AllocatedVirtualTexture together with the calculated UV to compute which tile in the VT should be requested.

The calculation in the RequestTiles() function is understandable, while I found the AllocatedVirtualTexture member variable of FRuntimeVirtualTextureSceneProxy may be not correctly set up for an AVT, so I always got only a few pages for processing. If you check how AllocatedVirtualTexture is set in the FRuntimeVirtualTextureSceneProxy constructor, you will see it is set by getting the allocated virtual texture from the VirtualTexture in the URuntimeVirtualTextureComponent. Then, if the RVT is an AVT, the function always returns AllocatedVirtualTextureLowMips of the FAdaptiveVirtualTexture. As a result, RequestPreload() function only preload pages based on AllocatedVirtualTextureLowMips, which is a low res mip covering a large area, I could not preload more detailed mip levels.

​​

If my investigation is correct, I have another concern. Each RVT volume has only one RVT component, each RVT component corresponds to one RVT scene proxy, and each RVT scene proxy contains only one **AllocatedVirtualTexture,**whereas AVT may have multiple AllocatedVirtualTexture for each grid, which means is not feasible to preload exact AVT tiles by call a function in RVT component in current implementation. Except we can have correct WidthInBlocks, WidthsInTiles etc. of each AllocatedVirtualTexture in an AVT when doing the math in FVirtualTextureSystem::RequestTilesForRegionInternal().

Besides this, would the ​URuntimeVirtualTextureComponent::RequestPreload() has similar problem where the camera moves a lot in next cut scene, while the AllocatedVirtualTexture of that grid is not allocated yet, so the request may fail. I suppose this may not happen, but for double checking.

In addition, theoretically, the area used in RequestPreload() may cover multiple grids of an AVT. Maximum 4 grids in a 2D space if I understand it correctly. So it needs to go through maximum AllocatedVirtualTextures. Is this also considered in the implementation?

Best regards,

Jing

Hi Jing,

You are right that the RequestPreload() implementation isn’t properly taking into account adaptive virtual textures when the requested mip level is not in the shared AllocatedVirtualTextureLowMips. Thanks for reporting that. We have added this to our backlog. The public issue should appear here soon: https://issues.unrealengine.com/issue/UE-305005

My first thought about fixing this is to do something similar to what we do in FVirtualTextureSystem::FlushCache(). In that code we call FAdaptiveVirtualTexture::GetProducers() to give us the set of producers in the adaptive virtual texture within a given region. We then use that to make multiple calls to EvictPages() calls instead of just one.

Maybe we can have a new function on FAdaptiveVirtualTexture that is similar to GetProducers() but instead of producers returns the IAllocatedVirtualTexture objects. It could also take and return modified UV ranges instead of texel rectangles. With this we could change RequestTilesForRegionInternal() to get all the IAllocatedVirtualTexture objects for the adaptive VT case and then iterate over all of them to add the encoded pages to RequestedPackedTiles.

The other subtle change with that is that we would need is to detect when the requested mip isn’t yet available in an IAllocatedVirtualTexture and change the implementation of EncodePage so that vLevelPlus1 is zero. Doing this is necessary to make sure that the grid of IAllocatedVirtualTexture is getting allocated to the correct sizes.

Doing something like this should work. But one concern is that adaptive virtual textures will have a bit more latency in the preload requests than simple RVT. That is due to the grid of IAllocatedVirtualTexture objects needing to allocate to the right size before we can finally start to map the requested pages. Possibly this won’t be a problem in practice if we have enough frames for preloading.

Best regards,

Jeremy

Thank you, Jeremy, for confirming. We’re looking forward to the fixes in 5.7.

We can’t try these fixes ourselves on our 5.4 game any more.