Hey Unreal team, we are facing a slow landscape RVT update issue when driving fast. We are aware of that we may have an expensive landscape material, however, besides simplifying the material, we are also looking for an approach to update the RVT pages near the player characters first and then other distant pages. We noticed a sorting algorithm is implemented in FUniqueRequestList::SortRequests(), while it does not take distance into account. Do you think it is possible to make it a distance sensitive sorting function (or there may be any other better place to implement our ideas)?
Besides, we are also considering adding some mip bias when sampling RVT so that it is faster to update a larger area under a limited number of RVT page update per frame at a cost of generally blurrier landscape (moving fast, so may be not very noticeable). Here comes a question, when requesting a low mip level (high detail) RVT page, does it force generating the targeted mip level RVT page in current frame? Or it compromises, i.e. generates a little bit higher mip level than targeted in given frame time and then update it to targeted mip level in the next frame? If the VT system is smart enough to compromise it, our mip bias idea may do not have considerable improvement.
In addition, we would also like to know the GPU cost of requesting a SVT page. We have some levels of a RVT are already baked to SVT. When requesting a high mip level page (should be SVT), does it introduce some GPU cost, or it is just a streaming cost on CPU side when accessing hard disk memory?
Another question, when we have set a landscape (we use nanite landscape) to write to RVT, does it use the nanite version landscape when rendering to RVT pages? Or it uses a fallback version of landscape? It seems it does not need nanite level mesh details in this case.
Hello,
Thank you for reaching out to us.
This related ticket discusses dealing with RVT requests for something fast moving like your use-case:
[Content removed]
The redirection for RVT and SVT happens through the FVirtualTextureLevelRedirector class and until the SVT is available from disk, the RVT will continue to be used.
The following document and ticket talks about the need for the Non-Nanite data for RVT, water rendering, etc.
https://dev.epicgames.com/documentation/en\-us/unreal\-engine/using\-nanite\-with\-landscapes\-in\-unreal\-engine?application\_version\=5\.5
[Content removed]
Please let us know if this helps.
Thank you Kevin, these tickets are helpful, but still do not answer the two questions:
- When requesting a low mip level (high detail) RVT page, does it force generating the targeted mip level RVT page in current frame? Or it compromises when it is not fast enough to generate it in current frame, i.e. it generates a little bit higher mip level than targeted level within given frame time and then updates it to targeted mip level in the next frame? (I have noticed that no matter how large r.vt.MaxUploadsPerFrame and r.vt.MaxTilesProducedPerFrame I use, it does not render to required mip level in one frame, the system split the works into phases, it looks like there is a long mip upgrading chain) If it is possible, can you tell me where I should look into in the code? Can I force it to render the mip level I want in one frame?
- generating a RVT cost some GPU time, but when requesting high mip level SVT, does it still cost GPU time?
One of the context I want to know the answer of question 1 is, we have cut scene in our game. When the camera position changes, the requested RVT pages changes very much. I can see the landscape RVT pages always update from blurry mip to clear mip, which results a noticeable popping artefact. Do you have solution for this type of problem?
The updates are throttled as you have found and the CVars you have found are the ones that are responsible for the throttling. If you are testing in editor, you can try adjusting “r.VT.MaxUploadsPerFrameInEditor”.
The code paths you can look into include:
- FVirtualTextureSystem::BeginUpdate(…)
- FVirtualTextureSystem::EndUpdate(…)
- FVirtualTextureSystem::SubmitThrottledRequests(…)
Virtual texturing in general is reactive so the mip request only occurs after the frame is rendered. This is where the throttling CVars help to speed up the catching up process.
generating a RVT cost some GPU time, but when requesting high mip level SVT, does it still cost GPU time
In this case, the GPU costs will be similar to virtual texture sampling costs as described in this page:
https://dev.epicgames.com/documentation/en\-us/unreal\-engine/streaming\-virtual\-texturing\-in\-unreal\-engine\#performance\-and\-cost
I can see the landscape RVT pages always update from blurry mip to clear mip, which results a noticeable popping artefact
This seems like you may need to increase your uploads per frame. If you have already split your updates for streamed pages, please make sure you are tuning “r.VT.MaxUploadsPerFrame.Streaming” as well.
Alternatively, it is possible that your pools are being oversubscribed as well as described in this related ticket:
[Content removed]
Please let us know if this helps.
Hey Kevin, thanks for the links❤️ , while I felt I might not phrase my questions very well:
Regarding the baked RVT (which is high mip levels of RVT, but baked into SVT), I do not worry about the cost of sampling it, but the cost of preparing it. If I understand it correctly, when a page is required, as for low mip level RVT, the system will render the required page, while for baked RVT (SVT), the system will stream the required page. Do I understand this correctly? If it is just streaming, it does not introduce GPU cost (maybe a bit for data transferring?)
Regarding the landscape RVT pages update from blurry mip to clear mip, I have tried the CVar you mentioned. I suppose that tuning the CVars is not the solution. You mentioned throttling and oversubscription, but what we encountered is with large r.vt.MaxUploadsPerFrame and r.vt.MaxTilesProducedPerFrame and r.VT.MaxUploadsPerFrame.Streaming, and large enough physical pool, which means no throttling and oversubscription, it still renders from blurry mip to clear mip. For example, when required a mip 0 page, I can see it renders mip 6 then update to around mip 3 and then update to mip 0, the system splits the process into several steps. It does not renders mip 0 in the very next frame after the feedback buffer is generated. Do you know which part of the source code is related to this behaviour?
Hi, I just wanted to let you know that we have moved the discussion to another thread. Pavel should reach out to you in order to get you access