Skip to content

Add texture streaming documentation. - #12268

Open
tdaven wants to merge 4 commits into
godotengine:masterfrom
tdaven:texture-stream-rework
Open

tdaven wants to merge 4 commits into
godotengine:masterfrom
tdaven:texture-stream-rework

Conversation

@tdaven

@tdaven tdaven commented Aug 12, 2026

Copy link
Copy Markdown

This is a PR to add documentation for my texture streaming PR:
godotengine/godot#113429

.. figure:: img/texture_streaming_comparison.webp
:align: center
:alt: The same scene with texture streaming forced to max quality and to an
aggressive Min LOD

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be on the same line to work correctly, at least the highlighting is broken

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah...it did.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for extra info, the alt text can be in multiple lines, so long as the padding is the same as the first line + :alt:. The line breaks are also preserved in translations for some reason, so I wouldn't recommend it. Annoying.

@AThousandShips AThousandShips added content:new page Issues and PRs related to creation of new documentation pages for new or undocumented features area:manual Issues and PRs related to the Manual/Tutorials section of the documentation waiting on pr merge PRs that can't be merged until an engine PR is merged first labels Aug 14, 2026

@AThousandShips AThousandShips left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise I think this looks good style wise

in the project, and textures have to be imported into a streamable format.

1. Enable
:ref:`Rendering > Textures > Streaming > Enabled<class_ProjectSettings_property_rendering/textures/streaming/enabled>`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
:ref:`Rendering > Textures > Streaming > Enabled<class_ProjectSettings_property_rendering/textures/streaming/enabled>`
:ref:`Rendering > Textures > Streaming > Enabled <class_ProjectSettings_property_rendering/textures/streaming/enabled>`

For all these for readability

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to be clear, you mean add a space before <class throughout the file?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!

@Calinou

Calinou commented Aug 24, 2026

Copy link
Copy Markdown
Member

@tdaven Could you apply the above suggestions? I'll take a look soon.

@AThousandShips AThousandShips left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM style wise

@AThousandShips AThousandShips removed the waiting on pr merge PRs that can't be merged until an engine PR is merged first label Aug 27, 2026
@skyace65 skyace65 added this to the 4.8 milestone Aug 30, 2026

@Calinou Calinou left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, aside of stylistic changes.

Note that CI is expected to fail until we update the copy of the class reference in this repository.

----------

Everything in the streaming system is expressed in mipmap levels, where **0 is
the full-resolution image** and each level above that halves the resolution:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it clearer that the values in the table are an example for a specific texture size:

Suggested change
the full-resolution image** and each level above that halves the resolution:
the full-resolution image** and each level above that halves the resolution.
For example, for a 4096×4096 texture:
Comment on lines +113 to +115
Some textures may require a **Max LOD** setting that prevents it from losing
important detail like alpha channels used for alpha scissors or other fine
details like an atlas.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Some textures may require a **Max LOD** setting that prevents it from losing
important detail like alpha channels used for alpha scissors or other fine
details like an atlas.
Generally, the **Min LOD** and **Max LOD** are configured globally for all textures. However, these can also be overridden on a per-texture basis.
Some textures may require a **Max LOD** setting that prevents it from losing
important detail like alpha channels used for alpha scissors, or other fine
details like an atlas.
:ref:`StreamedTexture2D.max_lod_override <class_StreamedTexture2D_property_max_lod_override>`,
which can be changed from a script.

``.dds`` files cannot currently be imported as streamed textures.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this limitation also applies to KTX textures, which aren't imported and are loaded as-is by Godot:

Suggested change
``.dds`` files cannot currently be imported as streamed textures.
DDS and KTX files currently cannot be imported as streamed textures.
TextureStreaming.memory_budget_mb_override = 256

These overrides take precedence over the project settings. Setting an LOD
override above ``13``, or the budget override to ``4294967295``, clears the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both GDScript and the inspector support the ** exponentiation operator, so we can make use of it here:

Suggested change
override above ``13``, or the budget override to ``4294967295``, clears the
override above ``13``, or the budget override to ``2 ** 32 - 1``, clears the
Comment on lines +265 to +271
Streaming reacts to what has already been rendered, so right after a scene load
or a teleport within a scene, textures are still at low resolution and increase
in quality over the next frames. To minimize visual disruptions you can call
:ref:`flush_texture_streaming() <class_TextureStreaming_method_flush_texture_streaming>`
to complete all pending streaming work immediately, ignoring any throttling. It then
emits :ref:`flush_completed <class_TextureStreaming_signal_flush_completed>` when
every texture has reached its target resolution.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Streaming reacts to what has already been rendered, so right after a scene load
or a teleport within a scene, textures are still at low resolution and increase
in quality over the next frames. To minimize visual disruptions you can call
:ref:`flush_texture_streaming() <class_TextureStreaming_method_flush_texture_streaming>`
to complete all pending streaming work immediately, ignoring any throttling. It then
emits :ref:`flush_completed <class_TextureStreaming_signal_flush_completed>` when
every texture has reached its target resolution.
Streaming reacts to what has already been rendered, so right after a scene load
or a teleport within a scene, textures are still at low resolution and increase
in quality over the next frames. To minimize visual disruptions, you can call
:ref:`flush_texture_streaming() <class_TextureStreaming_method_flush_texture_streaming>`
to complete all pending streaming work immediately, ignoring any throttling. It then
emits :ref:`flush_completed <class_TextureStreaming_signal_flush_completed>` when
every texture has reached its target resolution.
Comment on lines +341 to +343
- Streaming reads from the imported ``.stex`` files during gameplay, so it trades
VRAM for disk I/O. On storage with high latency, expect textures to take
longer to sharpen.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Streaming reads from the imported ``.stex`` files during gameplay, so it trades
VRAM for disk I/O. On storage with high latency, expect textures to take
longer to sharpen.
- Streaming reads from the imported ``.stex`` files during gameplay, so it trades
VRAM for disk I/O. On storage with high latency (such as mechanical hard drives),
expect textures to take longer to sharpen.
Comment on lines +39 to +41
Textures used only in 2D or in the UI produce no streaming feedback and
would remain at their lowest allowed quality — keep using the regular
Texture2D importer for those.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Textures used only in 2D or in the UI produce no streaming feedback and
would remain at their lowest allowed quality — keep using the regular
Texture2D importer for those.
Textures used only in 2D or in the UI produce no streaming feedback and
would remain at their lowest allowed quality. Keep using the regular
Texture2D importer for those.
Comment on lines +52 to +54
2. The feedback buffer is read back periodically and processed. The requested
level is clamped to the allowed LOD range, and — if a memory budget is set
— adjusted so all streamed textures fit inside that budget.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
2. The feedback buffer is read back periodically and processed. The requested
level is clamped to the allowed LOD range, and — if a memory budget is set
— adjusted so all streamed textures fit inside that budget.
2. The feedback buffer is read back periodically and processed. The requested
level is clamped to the allowed LOD range. If a memory budget is set,
the level is adjusted so all streamed textures fit inside that budget.
but do more I/O and texture work per frame.
- :ref:`Inactivity Decay Rate Ms <class_ProjectSettings_property_rendering/textures/streaming/inactivity_decay_rate_ms>`
(default ``5000``) — time per LOD level of quality decay for textures that
stop being requested.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
stop being requested.
- :ref:`Enabled <class_ProjectSettings_property_rendering/textures/streaming/enabled>`
(default ``false``): Global feature toggle. Requires a restart when changed.
- :ref:`Min Lod <class_ProjectSettings_property_rendering/textures/streaming/min_lod>`
(default ``0``): The best quality any streamed texture may reach.
- :ref:`Max Lod <class_ProjectSettings_property_rendering/textures/streaming/max_lod>`
(default ``3``): The worst quality a streamed texture may fall back to, and the
level textures are first loaded at.
- :ref:`Memory Budget Enabled <class_ProjectSettings_property_rendering/textures/streaming/memory_budget_enabled>`
(default ``false``): Enables the video RAM budget setting below.
- :ref:`Memory Budget Mb <class_ProjectSettings_property_rendering/textures/streaming/memory_budget_mb>`
(default ``512``): The video RAM budget for all streamed textures together, in MB.
- :ref:`Max Ops Per Second <class_ProjectSettings_property_rendering/textures/streaming/max_ops_per_second>`
(default ``200``): Throttle on mipmap operations. Higher values adapt faster
but do more I/O and texture work per frame.
- :ref:`Inactivity Decay Rate Ms <class_ProjectSettings_property_rendering/textures/streaming/inactivity_decay_rate_ms>`
(default ``5000``): Time per LOD level of quality decay for textures that
stop being requested.
Comment on lines +214 to +216
The budget only covers streamed textures. Render targets, meshes, shadow atlases,
and non-streamed textures are not counted, so the budget must be set well below
the total VRAM you expect to have available.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While there's no "one size fits all" budget, we should probably give out a recommendation that would suit a majority of projects. For example, is it realistic to use a texture memory budget of 2 GB on a 8 GB GPU at 1920×1080 resolution? Or should it be set to a lower value to avoid running out of VRAM in most situations?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difficulty is depends on how much and what you have the scene. I think most things godot does today a 2GB budget could be enough. But at the end of the day, the question is really how mnay unique material/textures are using and what re their resolutions.

@gnat

gnat commented Oct 29, 2026 •

Copy link
Copy Markdown

Really nice work. Followed the instructions, this all works well- really should get merged soon for 4.8... this edition does its job.

I can play large scenes from Unreal now without OOM-ing 😆

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:manual Issues and PRs related to the Manual/Tutorials section of the documentation content:new page Issues and PRs related to creation of new documentation pages for new or undocumented features

7 participants