This is a simple change that significantly reduces the amount of (CPU) memory used by textures on non-Windows systems.
We create textures in most situations and on most platforms by populating Unreal's FBulkData class with the raw pixel data from the glTF or raster overlay. Then, sometime later, Unreal's uploads it to the GPU. I noticed while spelunking through the Unreal source code while working on #1327 that FBulkData has a flag: BULKDATA_SingleUse. When this is set, Unreal directly grabs the buffer from the FBulkData as the source of the GPU upload, and frees it afterward. It's single use because we can't use that buffer ourselves after Unreal has grabbed it. When it's not set (which is the default), Unreal copies the bulk data again, uses the copy as the source of the upload, and leaves our original buffer in FBulkData intact.
We don't need the buffer in FBulkData - we already have our own copy of this data in the glTF - so BULKDATA_SingleUse is perfect for our use, and this PR adds it. Specifying this flags avoids a game-thread copy of the texture data. It also significantly reduces memory usage by texture data because the copy in the FBulkData doesn't sit around for the entire lifetime of the texture anymore.
This affects:
Every texture on non-Windows platforms (D3D11 and D3D12 use a custom texture creation path that is not affected by this change)
Feature metadata-related textures on all platforms (even Windows, because these textures don't use the custom texture creation path on Windows)
To measure the memory reduction, I hacked the Windows implementation to use the standard texture creation instead of the custom one. If you want to do this yourself, look for GRHISupportsAsyncTextureCreation in CesiumTextureUtility.cpp and replace it with false.
Then I opened up level 1 of the Samples project in the Editor and let it load. Before this change, the Editor process used 1.669 GB. Afterward, it used 1.538. Then I loaded the Google Photorealistic 3D Tiles sample level, and let that load. On that level, the Editor process went from 2.182 GB down to 1.918 GB with this change. These don't sound like huge changes percentage-wise, but the Editor uses a lot of memory and only some of it is our textures. Textures are our biggest use of memory in many cases, so eliminating a copy of the texture data is a big deal, especially on on devices with limited memory, like mobile and AR/VR devices.
Testing both levels, I see a 14.3% reduction on 01_CesiumWorld with this change (from 2.24GB to 1.92GB) and a 15.6% reduction in 12_CesiumGoogleMapsTiles (from 3.53GB to 2.98GB). Great change!
This is a simple change that significantly reduces the amount of (CPU) memory used by textures on non-Windows systems.
We create textures in most situations and on most platforms by populating Unreal's
FBulkData
class with the raw pixel data from the glTF or raster overlay. Then, sometime later, Unreal's uploads it to the GPU. I noticed while spelunking through the Unreal source code while working on #1327 thatFBulkData
has a flag:BULKDATA_SingleUse
. When this is set, Unreal directly grabs the buffer from the FBulkData as the source of the GPU upload, and frees it afterward. It's single use because we can't use that buffer ourselves after Unreal has grabbed it. When it's not set (which is the default), Unreal copies the bulk data again, uses the copy as the source of the upload, and leaves our original buffer in FBulkData intact.We don't need the buffer in FBulkData - we already have our own copy of this data in the glTF - so
BULKDATA_SingleUse
is perfect for our use, and this PR adds it. Specifying this flags avoids a game-thread copy of the texture data. It also significantly reduces memory usage by texture data because the copy in the FBulkData doesn't sit around for the entire lifetime of the texture anymore.This affects:
To measure the memory reduction, I hacked the Windows implementation to use the standard texture creation instead of the custom one. If you want to do this yourself, look for
GRHISupportsAsyncTextureCreation
inCesiumTextureUtility.cpp
and replace it withfalse
.Then I opened up level 1 of the Samples project in the Editor and let it load. Before this change, the Editor process used 1.669 GB. Afterward, it used 1.538. Then I loaded the Google Photorealistic 3D Tiles sample level, and let that load. On that level, the Editor process went from 2.182 GB down to 1.918 GB with this change. These don't sound like huge changes percentage-wise, but the Editor uses a lot of memory and only some of it is our textures. Textures are our biggest use of memory in many cases, so eliminating a copy of the texture data is a big deal, especially on on devices with limited memory, like mobile and AR/VR devices.