Texture streaming pool over unreal engine 4 что делать
Fixing ‘Texture Streaming Pool Over Budget’ in UE4
Although the warning ‘ TEXTURE STREAMING POOL OVER ’ (followed by a value in mebi bytes) uses intimidating red text and is written all in shouty capital letters, it’s not something to panic over. This is a very common warning that is simply telling you that the textures in your scene are using more memory than you have allocated for them, and as a result the engine has started decreasing the quality of your textures to compensate.
There are two productive ways to fix the ‘Texture Streaming Pool Over # MiB’ warning message. The first is to increase the size of your texture pool either via the console or your project’s configuration files. The second is to optimize your levels/materials to keep the size of your textures down.
Side note: Yes, there are also unproductive ways to clear this error. If you absolutely must, in a pinch you can enter the command DisableAllScreenMessages into your console and all warning messages will be suppressed. Just remember this isn’t actually solving anything though, and those warnings will be back the next time you open the editor. Don’t sweep your dust under the carpet. Fix it properly!
To understand why you’ve received this warning message you’ll need to have a basic grasp of Unreal’s texture streaming system – what it does, and why it’s so important. Let’s do a quick overview.
What is texture streaming?
No matter what kind of environment you’re making, your level is going to have textures – and if you’re making something anywhere close to substantial you’re going to have a lot of them. Even if you’re not using 4k texture maps for every single asset, the amount of data these textures contain will add up really fast. It’s a lot of information to keep in memory at any one time.
This is where Unreal’s texture streaming system comes in. It uses a combination of clever techniques to dynamically load textures in and out as required to improve the performance of your game. It also uses a level-of-detail optimization method called mipmapping to increase or decrease the resolution of your textures on the fly. This ensures that the least amount of texture data is loaded at any given time without sacrificing visual fidelity.
Using this technique will make your textures take up 33% more space on disk, but it will mean less data is loaded at any one time. They also make your textures look a lot better when viewed at a distance, like in this example.
Streaming data (including mipmap information) is precomputed as part of the Build all levels procedure. It can be generated on its own by selecting Build Texture Streaming from the Build menu.
The texture streaming system has been designed to make your textures look as good as possible, at any distance, and with the least possible overhead. Moreover, it is highly customizable to fit your project’s performance specifications with a wealth of configurable options.
You can wholesale disable texture streaming via your Project Settings – but I don’t know why you’d want to!
What is the Texture Streaming Pool?
The TEXTURE STREAMING POOL is a virtual storage container for all of the textures that are currently being drawn by the streaming system. This value will not be the same as the physical RAM you have installed on your machine (which is lucky, because you need some of that for your operating system and other vital services), and is composed of several different pools of memory that operate together to make sure textures can be streamed in and out safely.
You can enter the command ‘stat streaming’ into your console in either the editor or at run-time to see a comprehensive breakdown of your texture streaming system’s memory allocation.
You can see each pool’s maximum capacity in the far right column of the Memory Counters section. By default the size of the texture streaming pool is set to 1000 MB.
The Fix
Option A: Increase your texture streaming pool memory allocation
This is the quick and easy solution. Simply increase the size of your texture streaming pool to encompass your texture data and you’re all set. Of course, this is only advisable if your hardware (and your target spec) has the memory to spare.
Check the bottom of this article for a quick and easy method of finding out how large your texture pool needs to be to meet your texture requirements.
You can change the size of your streaming pool in the editor with the following console command, where # is the value you want to set in megabytes.
r.Streaming.PoolSize #
You can check that your change was accepted by using the stat streaming command.
Remember, like many config commands entered via the console, altering the size of the pool this way is only temporary. It will reset to the default value of 1000 whenever you reopen the editor. If you want this change to persist, you’ll need to navigate to your project’s DefaultEngine.ini config file and add r.Streaming.PoolSize=# to the [/Script/Engine.RendererSettings] section. If it doesn’t exist, create it.
You’ll know it worked on editor restart because there will be a line in the output log marking the change, and you’ll see it reflected in your stat streaming profiler.
That’s it. Problem solved. Assuming you have the memory to spare. If not, there is always…
Option B: Reduce your texture overhead
If you don’t want to raise the size of the pool to meet the demands of your textures, then you’ll need to reduce the amount of data your textures require. It’s one way or the other.
It’s very common for artists to author textures at up to four times the anticipated use-case resolution as a contingency. This means there are often 4k textures floating around that would look just as good at a quarter of that size.
Have a close look at your texture maps in the context of your level, and play around with reducing their resolution by half (and then half again if you can). You might be surprised at how little quality is lost for such a significant performance gain.
How big does my texture streaming pool need to be?
Here is a quick tip for figuring out the minimum size in MB that your texture streaming pool needs to be to encompass your level’s texture data.
If you input r.Streaming.PoolSize 1 into your console, you’ll set the texture streaming pool to 1 MB and all your textures will immediately be mipped out of existence – but this is okay. It’s just temporary.
You’ll notice now that as you move around the map the texture streaming pool over budget warning message will be updating to tell you just how over-budget you are. Zip around your map and pick out the highest number – that value (+1) is your minimum pool size.
Huge thanks to YouTuber OneUp Game Dev and their video on texture streaming for this awesome tip!
Further reading
Thanks for checking out my article. I hope it’s helped you understand why the texture streaming system is such a vital part of the engine – and why that warning message can get so persistent.
If you’re interested in further information on texture streaming, I absolutely recommend checking out Epic’s extensive documentation on both how it works, and how you can best bend it to your will.
If you’re keen to learn more optimization tricks for textures, materials, and more; VFX extraordinaire Luos_83 has been collating those he has discovered in a document which you can read here. Super useful!
I am a technical artist from Adelaide, Australia. I created techarthub to share my knowledge and love for this industry. I hope you feel it too!
Recent Posts
Keeping your Blueprints organized doesn’t have to be a pain. Here are 10 tips I’ve found for maintaining your graphs.
Seven different techniques you can try that will significantly lessen the amount of time it will take to compile your shaders.
Texture Streaming Configuration
System for loading and unloading textures into and out of memory during play.
After checking the accuracy of your built texture streaming, you may want to adjust the texture streamer’s behavior and priorities. The parameters below can be adjusted through configuration files, and most of them can also be updated at runtime from the console window.
This enables or disables the texture streamer. When it is disabled, all texture mips will get fully loaded in memory, even if the texture is never used for rendering. You can toggle this option at runtime, if needed.
The pool size in MB available for textures in the engine. This pool contains UI textures, NeverStream textures, cubemaps and streaming textures. On some platforms, this pool can also hold non texture resouces like GPU particle buffers and vertex buffers. When set to 0, the pool size will be unlimited.
When using a non-zero value, the texture pool size can be changed at runtime.
The number of frames between each full update of the texture streamer. Each update recomputes the required resolution of each texture and generate mip load or unload requests. Higher values reduce the texture streamer CPU usage while lower values increase its reactivity.
For compatibility only. When set to false, the texture streamer will proceed as per 4.12 version.
The amount of temporary memory in MB allowed for updating the textures. This should be big enough to avoid starving the texture streamer while being small enough to prevent wasting (unused) memory.
This controls the loading strategy for hierarchical LOD textures :
0 : Allow streaming of all mips
1 : Only stream the last mip. The other mips are always loaded.
2 : Don’t stream any mips. All mips are always loaded.
This controls a scale applied to the «wanted» resolution when the component referring to a texture is not visible (i.e. its bounding box is occluded). This only affects the resolution before it gets clamped by the max available resolution to avoid downgrading textures that are already limited. In other words, it only affects textures that have appropriate resolutions for the viewpoint.
When non-zero, this will limit the screen size considered by the streamer when computing the «wanted» resolution of textures. This will prevent high resolutions from requiring significantly bigger streaming pools.
This is a global boost affecting the «wanted» resolution of textures.
There are a few exceptions to how this bias is applied :
Terrain & Landscape textures : bias has no effect.
Hierarchical LOD textures : bias does not limit max resolution.
Lightmaps & Shadowmaps : bias only limits max resolution.
This is a debug option used to prevent keeping mips in memory even if the streaming pool allows it:
1 : Drop cached mips.
2 : Drop cached and hidden mips.
The purpose of this is to assets the accuracy of the wanted mip computation, as the displayed resolution can be affected by previous load requests or hidden primitives.
This will stream all used textures to their max available resolution and keep them in memory for as long as the application is opened. This should be used as an alternative to disabling texture streaming completely, which would load textures that are never used and ultimately, requiring more memory usage.
Whether or not to remove all resolution limitations coming from texture group settings and cinematic settings. This should only be used when showcasing art or making promotional material.
This is used in Material Texture Coordinate Scale Accuracy View Mode to investigate the accuracy for individual textures.
If enabled, the engine will check if texture streaming needs to be rebuilt, displaying a warning when simulating or in Play in Editor (PIE) mode.
If enabled, unused dynamic bounds will be removed from the update loop.
If enabled, the texture pool size will be limited to how much GPU memory is available.
When non 0, this allows the texture streamer to first load the visible mips from a texture when non visible mips must also be loaded. This improves the visual quality by prioritizing visible mips over force loaded mips or hidden mips that could become visible.
If non-zero, this sets the number of components the engine will incrementally load per frame before the level is visible. This applies to components with their mobility set to static. The default value is set to 50.
Whether the streaming texture’s «wanted» resolution will be scaled down by the global mip bias.
Whether the material texture scales and the coordinates will be used for texture streaming.
Оптимизация в UE4. Базовые советы
Всем привет и с новым годом! Наступили новогодние праздники, и у меня наконец-то появилась возможность выделить 2-3 дня на новую статью =)
В этой статье мы рассмотрим базовые вещи, которые необходимо отслеживать с самого начала работы над проектом в Unreal Engine. Здесь не будет каких-то откровений или ноу-хау, но надеюсь, статья окажется вам полезной. Особенно, если вы не так давно дружите с движком и вообще в сфере.
В целом, это будет полезно не только разработчикам на Unreal, но и на всех остальных движках так же, так как принципы оптимизации плюс-минус везде одинаковы.
В этой статье мы поговорим о:
В играх же ситуация кардинально другая. Каждый кадр отрисовывается с нуля без учета движений. То есть, все объекты в этом кадре всегда статичны, и кадр не фиксирует движение объектов за отведенное ему время. В итоге 30 игровых кадров в секунду кажутся дерганными, недостаточными для глаза, чтобы довольствоваться картинкой, и отсюда стремления к 60 кадрам и выше.
Да, это очевидная штука, которой мне не хватало когда-то, чтобы прочувствовать саму суть проблемы. Оно было интуитивно понятно, но вот так вот четко я не встречал описания до определенной статьи. Может быть, у вас так же будет и с этой =)
В VR играх требуется 90 кадров в секунду. Тут требование закономерно. Если в 30 кадров в секунду вы играете и видите дергания, и это в целом нормально, то в VR вас не окружает квартира/офис или где вы играете. В VR вас окружает только игра и черный фон. Поэтому чувствительность к количеству кадров возрастает на порядок, а возможность вертеть головой в пространстве создает дополнительный дискомфорт при низком FPS. А некоторых и вовсе выворачивает.
Что касается объектов в игре, то здесь очень много нюансов, но все они сводятся к 2 моментам:
Если вы делаете модель с учетом запекания фасок в Normal Map, то вы прекрасно должны понимать, что ваши вертексы на жестких гранях будут расщепляться для того, чтобы сохранить в себе информацию о направлении Vertex Normal.
И мы все прекрасно понимаем, что на швах развертки точки так же расщепляются.
Вертекс может содержать в себе различные данные одновременно, но данные одного типа может хранить только по 1 штуке.
Исходя из этого понимания можно прогнозировать, сколько будет реально занимать ваша модель вертексов и как это можно контролировать.
Так же помните, что второй и последующие слои развертки так же увеличивают количество вертексов.
Количество треугольников в вашей модели определяет степень загруженности вашей видеокарты для рендера этих поверхностей.
Казалось бы, круто, понятно, нужно делать меньшее количество треугольников (полигонов и т.д.) и рендер будет быстрее обрабатывать модель. Но это не совсем так. Размер и положение треугольника так же важно, как и то, как собрана модель.
А теперь представьте, что у вас модель имеет следующую сетку:
Так же по этой же причине не рекомендуется делать длинные тонкие треугольники, а значит, возникает вопрос о том, что делать с фасками, которые создаются на уровне моделей?
Если вы не читали мои статьи о текстурировании, то рекомендую сейчас бегло ознакомиться с 4ой частью, где в конце статьи я описывал о фасках и о том, как можно их сделать красивыми без карт нормалей.
Красивые фаски очень часто тянутся по всей модели через весь экран, и это совсем тоненькие треугольники, которые заставляют GPU пробегать по пиксельным группам несколько раз, чтобы отобразить их.
Но здесь стоит учитывать 2 момента:
В UE4 они генерируются автоматически. Ну, то есть, нужно нажать на кнопки, но руками модель править не нужно, и это ускоряет процесс до пары кликов.
Например, у нас есть вот такая красивая лампа, которая сжирает 58 594 вертекса.
Мы создали LOD’ы для этой лампы, которые автоматически подменяют модели на менее детализированные. А вы и не заметите, что у лампы на заднем фоне всего 5648 вертексов.
Без LOD’ов в этом кинотеатре около 7 миллионов вертексов:
С LOD’ами на таком расстоянии кинотеатр имеет около 800 тысяч вертексов. При отдалении камеры их будет в разы меньше вплоть до 300 тысяч.
В UE4 можно так же посмотреть какие уровни LOD’ов сейчас активны и где вообще они используются:
Дело в том, что если объект каким-то образом попадает в камеру и должен отображаться, то он будет просчитан полностью весь и весь будет отображаться, даже если попал в кадр малюсенький треугольник.
Поэтому большие объемные объекты должны быть собраны таким образом, чтобы их можно было нарезать на куски.
Например, так наш кинотеатр отображается на камеру:
А вот так сработал Culling объектов, и кинотеатр был обрезан для рендера:
LOD’ы позволяют нам снижать нагрузку на рендер.
Оптимизация Вертексов позволяет нам снижать расчеты для отображения модели.
В UE4 есть множество способов оптимизировать шейдеры. Но я рассмотрю только основные моменты.
Таким образом, если вы создадите суперсложный шейдер, который жрет миллион инструкций и требует ядерного реактора для расчетов, но при этом сам объект будет занимать площадь 40 на 40 пикселей, то отображение этого шейдера будет занимать ничтожно мало времени и практически не сожрет FPS.
Иначе говоря, чем больше площадь объекта, тем меньше нагруженным должен быть шейдер.
Это говорит нам о том, что нужно учитывать, в какой момент мы можем себе позволить сложный шейдер с сотней расчетов и 1000 инструкций, а в какой момент нам нужно создать самый простой материал, чтобы он не отжирал ресурсы.
И нет, это не значит, что теперь на карандашик, который занимает 20 пикселей, вы можете наложить суперсложный материал. Однажды в какой-нибудь кат-сцене он может быть ключевым объектом в кадре, и ваш GPU вас поблагодарит.
Исходя из выше написанного мы теперь понимаем, что шейдер обрабатывается и отображается только в тех пикселях, где должен. Но что же происходит с шейдером, когда в его коде есть разветвления?
Нужно понимать, что если вы делаете материал с разделением на 2 и более объектов по UV координатам (так называемые атласовые шейдеры с атласовыми текстурами), а в кадр попал только 1 объект, то все равно ВЕСЬ код будет просчитан для отображения пикселя и загружены будут все текстуры, даже которые не участвуют в текущей работе шейдера.
В связи с этим нужно несколько раз подумать, а стоит ли запихивать несколько объектов в один шейдер? Может быть, проще будет, если на каждый объект будет по собственному шейдеру?
Для этого в шейдерах существует тип данных называемый «Параметром». Этот тип данных позволяет динамически менять что-то в шейдерах, например, цвет поверхности, при этом не просчитывая с нуля весь шейдер.
Так же существует такой тип объекта, как инстанс шейдера (материала). Это копия шейдера, в которой вы можете изменять параметры шейдера, и они будут моментально просчитываться и отображаться. В этом случае вам не потребуется ждать, когда шейдер будет полностью пересчитан.
Например, вы создали шейдер, который базово можно наложить на любой объект. Вы добавили в него параметр текстуры (можно заменять текстуру) и параметр цвета, который будет изменять цвет текстуры.
Далее вы создаете инстанс этого шейдера и теперь можете подставить в него другую текстуру и цвет. Все легко, быстро и круто.
Но есть серьезные нюансы, о которых как-то не принято говорить, потому что это малозначительно и усложняет жизнь.
В шейдерах можно использовать константные значения (те, которые нельзя изменять в реальном времени) и параметры (динамические значения, которые можно изменять в реальном времени).
Когда мы создаем шейдер только на константных значениях, то он просчитывается полностью заранее и отдельно записывает свои просчеты. Так происходит до тех пор, пока в коде не появляются параметры.
Поэтому. Если вы используете инстансы с возможностью замены текстур, то убедитесь, что вы не используете сам базовый шейдер на других объектах. Это позволит вам подключить во все его параметры текстур одну и ту же текстуру-затычку, а ее размер рекомендую сделать в 1 пиксель. Это будет легко для подгрузки, не занимает память и расширит возможности подключения текстур через инстансы.
Помните, что максимальное число текстур равно 16 штукам. И это вместе с текстурами из базового шейдера и используемого инстанса.
Для всех устройств, что работают на DirectX11 и выше, вы можете указать шейдерах в настройках ноды текстуры Sampler Source на Shared: Wrap, и вам будет доступно 128 текстур с такой настройкой для работы в шейдере. Но это только в случае с работой над проектами, которые работают в DX11 и выше. Вулканы, OpenGL’ы работают в пределе 16 текстур. Поэтому будьте аккуратны в выборе.
Streaming Virtual Texturing
An overview of Streaming Virtual Textures.
Streaming Virtual Texturing (SVT) is an alternative way to stream textures in your project from disk. SVT has several advantages—along with some disadvantages—when compared to existing mip-based
Traditional mip-based texture streaming performs offline analysis of material UV usage and then at runtime decides which mip levels of a texture to load based on object visibility and distance. This process can be limiting because streaming data considered is the full texture mip levels.
When using high-resolution textures, loading a higher mip level of a texture can potentially have significant performance and memory overhead. Also, the CPU makes mip-based texture streaming decisions using CPU-based object visibility and culling.
Visibility is more conservative—meaning your system is more likely than not to load something—to avoid objects popping into view. So, if even a small part of the object is visible, the entire object is considered visible. The object loaded including any associated textures that may be required to stream in.
In contrast, the virtual texturing system only streams in parts of the textures that UE requires for it be visible. It does this by splitting all mip levels into tiles of a small, fixed size. The GPU determines which of the visible tiles are accessed by all visible pixels on the screen. This means that when UE considers an object to be visible, it’s communicated to the GPU which loads the required tiles into a GPU memory cache. No matter the size of the texture, the fixed tile size of the SVTs only considers the ones that are visible. Tile GPU computes visibility using standard depth buffers causing SVT requests to only happen for visible parts that affect pixels.
Enabling Virtual Texturing
In the Project Settings under Engine > Rendering > Virtual Textures, check the box next to Enable virtual texture support.
Click image for full size.
Under the Editor > Texture Import > Virtual Textures category in the Project Settings, you can specify a minimum texture size to consider newly imported textures for SVT. If a texture meets that minimum size, Virtual Texture Streaming will be enabled for that Texture Asset automatically.
For information on these settings, see
Converting Textures and Materials
Enabling virtual texturing for your project means that Textures and Materials require some setup to work correctly; the Texture must enable Virtual Texture Streaming support, and the Material’s Texture Samples are required to use a Virtual Sampler Type instead of a non-Virtual one.
Choose from the options below to properly set up your textures and materials for use with SVT.
Conversion Menu Option
Select any Texture Asset in the Content Browser that you want to convert to use SVT.
Right-click to open the context menu and select Convert to Virtual Texture.
This menu option also enables you to convert from a virtual texture to a regular texture as well.
The Convert To window lists any Texture(s) that you have selected and any Materials that reference them.
Click Ok to start the conversion process.
During the conversion process, Texture Assets will have Virtual Texture Streaming enabled for them in their Texture Editor settings. Materials that reference the selected texture(s) will convert the Texture Sample nodes to use the Virtual Sampler Type instead of the non-Virtual Sampler Type.
Manual Conversion
Open the Texture Editor for a given Texture Asset by double-clicking it in the Content Browser.
In the Details panel under Texture, enable Virtual Texture Streaming.
Enabling this without using the conversion menu option above will immediately invalidate any existing Materials that reference a converted texture. You should open any Materials that reference the offending texture and set the Texture Sample node to use the correct Virtual Sampler Type. For example, a virtual texture should use a Sampler Type of Virtual Color instead of Color.
When you encounter a Texture Sample node that is not using the correct Sampler Type, UE will display an error message in the Stats panel and along the bottom of the node, like this:
The error message identifies the wrong Sampler Type for the assigned VT Texture Sample expression.
Change the Texture Sample’s Sampler Type to be one of the Virtual types.
The VT Texture Sample correctly renders, indicated by the «VT» in the lower-right of the expression.
When adding a virtual texture to a Material Graph, UE assigns the Virtual sampler type automatically. However, should you make the expression a Texture Sample Parameter that you can use in Material Instances, keep in mind that the base material applies the Virtual sampler type to all child instances. Remember that you cannot assign a virtual texture to a texture parameter slot that’s not already of Virtual type in the base Material.
UDIM Support
U-Dimension (or «UDIM») is a texture naming convention that enables multiple texture images to map to separate UV regions on a Static Mesh or Skeletal Mesh model. When using the UDIM naming convention, UE will import groups of image files as a single Virtual Texture Asset.
Virtual texturing support for UDIMs is beneficial for a couple of reasons:
It works with many separate, smaller textures instead of extremely large textures.
Each UDIM image can have a different resolution enabling virtual textures that have non-uniform pixel density.
For example, if you import a UDIM virtual texture made up of four image files—two 2048×2048 and two 128×128 textures—arranged in a 2×2 pattern, the virtual texture logically samples these images like a single 4098×4098 texture. UE will stretch the smaller 128×128 images to fill the same area as the larger 2048×2048 images without disk or runtime memory usage affected. Having the smaller 128×128 textures fill a 2048×2048 texture resolution doesn’t consume any memory in this case.
For additional information on UDIM workflows, see The Foundry’s UDIM Workflow tutorial.
Start using UDIM textures with virtual texturing in your own projects by using this naming convention::
When UE imports an image matching this naming convention, it scans the source folder for any additional images matching the same BaseName followed by a different coordinate number. For each image that is located, the four-digit number defines the location where UE should map the image. Importing traditional textures map to the mesh UVs in the range of 0-1, however, UDIM image maps to a UV 0-1 space based on its defined UV coordinate.
This grid represents UV mappings to different four-digit coordinates that you can use to store your images:
Performance and Cost
Measure the performance and cost of virtual texturing in your project using the sections below:
Stat Virtual Texturing
Open the console using the backtick (`) key and enter the following commands to enable their stats information:
Use stat virtualtexturing to see details about the virtual texturing scene cost in milliseconds (ms) and counters for page tables.
Use stat virtualtexturememory to display relevant memory counters related to the use of virtual texturing in the current scene.
Streaming Virtual Texturing Visualization
Use the console command r.VT.Borders 1 to draw a mip visualization grid on Materials that use streaming virtual textures.
Use r.VT.Borders 0 to hide the grid when you no longer need it.
Material Lookups and Stacks
Sampling from a virtual texture in your materials is more expensive than sampling a traditional texture. You can break the cost of virtual texturing into two categories:
Lookups happen for each Virtual Texture your project samples in the Material Graph.
Stacks combine Virtual Textures when your project uses the same UVs and Sampler Source.
Virtual Textures will always be more expensive than traditional textures sample. There will always be at least two texture fetches and some math instructions. However, some of that cost is amortized by combining the stacks (up to 8) for the VT texture samples that use the same UVs and Sampler Source.
In this simple Material example, UE is sampling two VT Texture Sample expressions using default UVs. A Virtual Texture Lookup is added for each lookup of that texture sample and since both are using a single UV, they are combined into a single Virtual Texture Stack:
However, if your project uses different UVs, the cost increases with two Virtual Texture Stack fetches:
The first example uses three texture fetches total: two lookups and one stack. Because the VT samples use the same UVs, UE combines their stacks to save a texture fetch. In the second example, there is a total of four texture fetches: two lookups and two stacks. The VT Texture Samples use different UVs for the Base Color and Normal Texture Samples meaning they cannot be combined into a single stack.
Additional Material Notes
UE splits streaming virtual textures into fixed size tiles for each texture, no matter its size. It also limits the lowest resolution mip by the tile size. In many cases, this won’t be an issue, however, textures with a lot of noise or high detail may exhibit aliasing or MoirГ© effects due to lack of low-resolution mips. Keep in mind that this also poses potential GPU performance cost, although that can be difficult to measure in practice.
Limitations
In general, virtual textures are interchangeable with regular textures with exception that there are some limitations and added cost:
Texture dimensions must be a power of 2 but UE does not require them to be square by nature. However, they utilize memory more efficiently in the current implementation.
Support for trilinear filtering between mips is done in a stochastic manor. When using Temporal Anti-Aliasing (TAA), it is nearly indistinguishable from regular trilinear filtering but can introduce some visible noise in cases.
UE limits support for anisotropic filtering by the size of the Tile Border setting. The default value of 4 allows for less anisotropic filtering than is typical for textures but increasing this value increases memory usage.
VT streaming is reactive by nature, meaning that the CPU doesn’t know it needs to load a given VT tile until after it has already been required by a rendered frame. So, as the camera moves through the scene, some visible popping in may occur, especially as higher resolution VT tiles are loaded.
You can download this «Mip Testing» texture