Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
TextureManager.h
Go to the documentation of this file.
1/* Copyright (C) 2023 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef INCLUDED_TEXTUREMANAGER
19#define INCLUDED_TEXTUREMANAGER
20
21#include "graphics/Texture.h"
22#include "lib/file/vfs/vfs.h"
23#include "lib/tex/tex.h"
27
28#include <memory>
29
32
33/**
34 * Texture manager with asynchronous loading and automatic DDS conversion/compression.
35 *
36 * Input textures can be any format. They will be converted to DDS using settings defined
37 * in files named "texture.xml", in the same directory as the texture and in its parent
38 * directories. See CTextureConverter for the XML syntax. The DDS file will be cached
39 * for faster loading in the future.
40 *
41 * Typically the graphics code will initialise many textures at the start of the game,
42 * mostly for off-screen objects, by calling CreateTexture().
43 * Loading texture data may be very slow (especially if it needs to be converted
44 * to DDS), and we don't want the game to become unresponsive.
45 * CreateTexture therefore returns an object immediately, without loading the
46 * texture. If the object is never used then the data will never be loaded.
47 *
48 * Typically, the renderer will call CTexture::Bind() when it wants to use the
49 * texture. This will trigger the loading of the texture data. If it can be loaded
50 * quickly (i.e. there is already a cached DDS version), then it will be loaded before
51 * the function returns, and the texture can be rendered as normal.
52 *
53 * If loading will take a long time, then Bind() binds a default placeholder texture
54 * and starts loading the texture in the background. It will use the correct texture
55 * when the renderer next calls Bind() after the load has finished.
56 *
57 * It is also possible to prefetch textures which are not being rendered yet, but
58 * are expected to be rendered soon (e.g. for off-screen terrain tiles).
59 * These will be loaded in the background, when there are no higher-priority textures
60 * to load.
61 *
62 * The same texture file can be safely loaded multiple times with different backend parameters
63 * (but this should be avoided whenever possible, as it wastes VRAM).
64 *
65 * For release packages, DDS files can be precached by appending ".dds" to their name,
66 * which will be used instead of doing runtime conversion. This means most players should
67 * never experience the slow asynchronous conversion behaviour.
68 * These cache files will typically be packed into an archive for faster loading;
69 * if no archive cache is available then the source file will be converted and stored
70 * as a loose cache file on the user's disk.
71 */
73{
75
76public:
77 /**
78 * Construct texture manager. vfs must be the VFS instance used for all textures
79 * loaded from this object.
80 * highQuality is slower and intended for batch-conversion modes.
81 */
82 CTextureManager(PIVFS vfs, bool highQuality, Renderer::Backend::IDevice* device);
83
85
86 /**
87 * Create a texture with the given properties.
88 * The texture data will not be loaded immediately.
89 */
91
92 /**
93 * Wraps a backend texture.
94 */
96 std::unique_ptr<Renderer::Backend::ITexture> backendTexture);
97
98 /**
99 * Returns a magenta texture. Use this for highlighting errors
100 * (e.g. missing terrain textures).
101 */
103
104 /**
105 * Returns a single color RGBA texture with CColor(1.0f, 1.0f, 1.0f, 1.0f).
106 */
108
109 /**
110 * Returns a single color RGBA texture with CColor(0.0f, 0.0f, 0.0f, 0.0f).
111 */
113
114 /**
115 * Returns a white RGBA texture with alpha gradient.
116 */
118
119 /**
120 * Returns a single color RGBA texture cube with CColor(0.0f, 0.0f, 0.0f, 1.0f).
121 */
123
124 /**
125 * Work on asynchronous texture loading operations, if any.
126 * Returns true if it did any work.
127 * The caller should typically loop this per frame until it returns
128 * false or exceeds the allocated time for this frame.
129 */
130 bool MakeProgress();
131
132 /**
133 * Work on asynchronous texture uploading operations, if any.
134 * Returns true if it did any work. Mostly the same as MakeProgress.
135 */
137
138 /**
139 * Synchronously converts and compresses and saves the texture,
140 * and returns the output path (minus a "cache/" prefix). This
141 * is intended for pre-caching textures in release archives.
142 * @return true on success
143 */
144 bool GenerateCachedTexture(const VfsPath& path, VfsPath& outputPath);
145
146 /**
147 * @return a cached version of the path
148 */
149 VfsPath GetCachedPath(const VfsPath& path) const;
150
151 /**
152 * Returns true if the given texture exists.
153 * This tests both for the original and converted filename.
154 */
155 bool TextureExists(const VfsPath& path) const;
156
157 /**
158 * Returns total number of bytes uploaded for all current texture.
159 */
160 size_t GetBytesUploaded() const;
161
162 /**
163 * Should be called on any quality or anisotropic change.
164 */
165 void OnQualityChanged();
166
167private:
169};
170
171/**
172 * Represents the filename and GL parameters of a texture,
173 * for passing to CTextureManager::CreateTexture.
174 */
176{
178 friend struct TextureCacheCmp;
179 friend struct TPequal_to;
180 friend struct TPhash;
181
182public:
183 /**
184 * Use the given texture name, and default GL parameters.
185 */
186 explicit CTextureProperties(const VfsPath& path)
187 : m_Path(path)
188 {
189 }
190
192 const VfsPath& path, const Renderer::Backend::Format formatOverride)
193 : m_Path(path), m_FormatOverride(formatOverride)
194 {
195 }
196
197 /**
198 * Set sampler address mode.
199 */
201 {
202 m_AddressModeU = m_AddressModeV = addressMode;
203 }
204
205 /**
206 * Set sampler address mode separately for different coordinates.
207 */
211 {
212 m_AddressModeU = addressModeU;
213 m_AddressModeV = addressModeV;
214 }
215
216 /**
217 * The value of max anisotropy is set by options. Though it might make sense
218 * to add an override.
219 */
220 void SetAnisotropicFilter(const bool enabled) { m_AnisotropicFilterEnabled = enabled; }
221
222 // TODO: rather than this static definition of texture properties
223 // (especially anisotropy), maybe we want something that can be more
224 // easily tweaked in an Options menu? e.g. the caller just specifies
225 // "terrain texture mode" and we combine it with the user's options.
226 // That'd let us dynamically change texture properties easily.
227 //
228 // enum EQualityMode
229 // {
230 // NONE,
231 // TERRAIN,
232 // MODEL,
233 // GUI
234 // }
235 // void SetQuality(EQualityMode mode, float anisotropy, float lodbias, int reducemipmaps, ...);
236 //
237 // or something a bit like that.
238
239 void SetIgnoreQuality(bool ignore) { m_IgnoreQuality = ignore; }
240
241private:
242 // Must update TPhash, TPequal_to when changing these fields
244
252 bool m_IgnoreQuality = false;
253};
254
255/**
256 * Represents a texture object.
257 * The texture data may or may not have been loaded yet.
258 * Before it has been loaded, all operations will act on a default
259 * 1x1-pixel grey texture instead.
260 */
262{
264public:
266
267 /**
268 * Returns the width (in pixels) of the current texture.
269 */
270 size_t GetWidth() const;
271
272 /**
273 * Returns the height (in pixels) of the current texture.
274 */
275 size_t GetHeight() const;
276
277 /**
278 * Returns whether the current texture has an alpha channel.
279 */
280 bool HasAlpha() const;
281
282 /**
283 * Returns the ARGB value of the lowest mipmap level (i.e. the
284 * average of the whole texture).
285 * Returns 0 if the texture has no mipmaps.
286 */
287 u32 GetBaseColor() const;
288
289 /**
290 * Returns total number of bytes uploaded for this texture.
291 */
292 size_t GetUploadedSize() const;
293
294 /**
295 * Uploads a texture data to a backend texture if successfully loaded.
296 * If the texture data hasn't been loaded yet, this may wait a short while to
297 * load it. If loading takes too long then it will return sooner and the data will
298 * be loaded in a background thread, so this does not guarantee the texture really
299 * will be uploaded.
300 */
302 Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
303
304 /**
305 * Returns a backend texture if successfully uploaded, else fallback.
306 */
309
310 /**
311 * Attempt to load the texture data quickly, as with
312 * GetUploadedBackendTextureIfNeeded(). Returns whether the texture data is
313 * currently loaded (but not uploaded).
314 */
315 bool TryLoad();
316
317 /**
318 * Returns whether the texture data is currently loaded.
319 */
320 bool IsLoaded() const { return m_State == LOADED; }
321
322 /**
323 * Returns whether the texture data is currently uploaded.
324 */
325 bool IsUploaded() const { return m_State == UPLOADED; }
326
327 /**
328 * Activate the prefetching optimisation for this texture.
329 * Use this if it is likely the texture will be needed in the near future.
330 * It will be loaded in the background so that it is likely to be ready when
331 * it is used by Bind().
332 */
333 void Prefetch();
334
335private:
337 friend class CPredefinedTexture;
338 friend struct TextureCacheCmp;
339 friend struct TPequal_to;
340 friend struct TPhash;
341
342 // Only the texture manager can create these
343 explicit CTexture(
344 std::unique_ptr<Renderer::Backend::ITexture> texture,
346 const CTextureProperties& props, CTextureManagerImpl* textureManager);
347
349 std::unique_ptr<Renderer::Backend::ITexture> backendTexture,
350 Renderer::Backend::ITexture* fallbackBackendTexture);
351
353
354 std::unique_ptr<Renderer::Backend::ITexture> m_BackendTexture;
355 // It's possible to m_FallbackBackendTexture references m_BackendTexture.
358 std::unique_ptr<Tex> m_TextureData;
359 size_t m_UploadedSize = 0;
361
362 enum
363 {
364 UNLOADED, // loading has not started
365 PREFETCH_NEEDS_LOADING, // was prefetched; currently waiting to try loading from cache
366 PREFETCH_NEEDS_CONVERTING, // was prefetched; currently waiting to be sent to the texture converter
367 PREFETCH_IS_CONVERTING, // was prefetched; currently being processed by the texture converter
368 HIGH_NEEDS_CONVERTING, // high-priority; currently waiting to be sent to the texture converter
369 HIGH_IS_CONVERTING, // high-priority; currently being processed by the texture converter
370 LOADED, // loading texture data has completed (successfully or not)
371 UPLOADED // uploading to backend has completed (successfully or not)
373
375
376 // Self-reference to let us recover the CTexturePtr for this object.
377 // (weak pointer to avoid cycles)
378 std::weak_ptr<CTexture> m_Self;
379};
380
381#endif // INCLUDED_TEXTUREMANAGER
Definition: TextureManager.cpp:117
Definition: TextureManager.cpp:360
Texture manager with asynchronous loading and automatic DDS conversion/compression.
Definition: TextureManager.h:73
const CTexturePtr & GetErrorTexture()
Returns a magenta texture.
Definition: TextureManager.cpp:1072
const CTexturePtr & GetWhiteTexture()
Returns a single color RGBA texture with CColor(1.0f, 1.0f, 1.0f, 1.0f).
Definition: TextureManager.cpp:1077
CTextureManagerImpl * m
Definition: TextureManager.h:168
const CTexturePtr & GetTransparentTexture()
Returns a single color RGBA texture with CColor(0.0f, 0.0f, 0.0f, 0.0f).
Definition: TextureManager.cpp:1082
NONCOPYABLE(CTextureManager)
bool GenerateCachedTexture(const VfsPath &path, VfsPath &outputPath)
Synchronously converts and compresses and saves the texture, and returns the output path (minus a "ca...
Definition: TextureManager.cpp:1108
CTexturePtr CreateTexture(const CTextureProperties &props)
Create a texture with the given properties.
Definition: TextureManager.cpp:1056
CTexturePtr WrapBackendTexture(std::unique_ptr< Renderer::Backend::ITexture > backendTexture)
Wraps a backend texture.
Definition: TextureManager.cpp:1061
bool TextureExists(const VfsPath &path) const
Returns true if the given texture exists.
Definition: TextureManager.cpp:1067
void OnQualityChanged()
Should be called on any quality or anisotropic change.
Definition: TextureManager.cpp:1123
CTextureManager(PIVFS vfs, bool highQuality, Renderer::Backend::IDevice *device)
Construct texture manager.
Definition: TextureManager.cpp:1046
bool MakeProgress()
Work on asynchronous texture loading operations, if any.
Definition: TextureManager.cpp:1097
const CTexturePtr & GetBlackTextureCube()
Returns a single color RGBA texture cube with CColor(0.0f, 0.0f, 0.0f, 1.0f).
Definition: TextureManager.cpp:1092
size_t GetBytesUploaded() const
Returns total number of bytes uploaded for all current texture.
Definition: TextureManager.cpp:1118
bool MakeUploadProgress(Renderer::Backend::IDeviceCommandContext *deviceCommandContext)
Work on asynchronous texture uploading operations, if any.
Definition: TextureManager.cpp:1102
~CTextureManager()
Definition: TextureManager.cpp:1051
const CTexturePtr & GetAlphaGradientTexture()
Returns a white RGBA texture with alpha gradient.
Definition: TextureManager.cpp:1087
VfsPath GetCachedPath(const VfsPath &path) const
Definition: TextureManager.cpp:1113
Represents the filename and GL parameters of a texture, for passing to CTextureManager::CreateTexture...
Definition: TextureManager.h:176
friend struct TextureCacheCmp
Definition: TextureManager.h:178
Renderer::Backend::Format m_FormatOverride
Definition: TextureManager.h:250
bool m_AnisotropicFilterEnabled
Definition: TextureManager.h:249
VfsPath m_Path
Definition: TextureManager.h:243
CTextureProperties(const VfsPath &path)
Use the given texture name, and default GL parameters.
Definition: TextureManager.h:186
CTextureProperties(const VfsPath &path, const Renderer::Backend::Format formatOverride)
Definition: TextureManager.h:191
Renderer::Backend::Sampler::AddressMode m_AddressModeU
Definition: TextureManager.h:245
void SetIgnoreQuality(bool ignore)
Definition: TextureManager.h:239
void SetAddressMode(const Renderer::Backend::Sampler::AddressMode addressMode)
Set sampler address mode.
Definition: TextureManager.h:200
Renderer::Backend::Sampler::AddressMode m_AddressModeV
Definition: TextureManager.h:247
bool m_IgnoreQuality
Definition: TextureManager.h:252
void SetAnisotropicFilter(const bool enabled)
The value of max anisotropy is set by options.
Definition: TextureManager.h:220
void SetAddressMode(const Renderer::Backend::Sampler::AddressMode addressModeU, const Renderer::Backend::Sampler::AddressMode addressModeV)
Set sampler address mode separately for different coordinates.
Definition: TextureManager.h:208
Represents a texture object.
Definition: TextureManager.h:262
friend struct TextureCacheCmp
Definition: TextureManager.h:338
Renderer::Backend::ITexture * m_FallbackBackendTexture
Definition: TextureManager.h:356
bool IsUploaded() const
Returns whether the texture data is currently uploaded.
Definition: TextureManager.h:325
u32 GetBaseColor() const
Returns the ARGB value of the lowest mipmap level (i.e.
Definition: TextureManager.cpp:1034
NONCOPYABLE(CTexture)
size_t GetHeight() const
Returns the height (in pixels) of the current texture.
Definition: TextureManager.cpp:1018
Renderer::Backend::ITexture * GetBackendTexture()
Returns a backend texture if successfully uploaded, else fallback.
Definition: TextureManager.cpp:966
CTexture(std::unique_ptr< Renderer::Backend::ITexture > texture, Renderer::Backend::ITexture *fallback, const CTextureProperties &props, CTextureManagerImpl *textureManager)
Definition: TextureManager.cpp:923
CTextureManagerImpl * m_TextureManager
Definition: TextureManager.h:374
bool HasAlpha() const
Returns whether the current texture has an alpha channel.
Definition: TextureManager.cpp:1023
const CTextureProperties m_Properties
Definition: TextureManager.h:352
uint32_t m_BaseLevelOffset
Definition: TextureManager.h:360
void ResetBackendTexture(std::unique_ptr< Renderer::Backend::ITexture > backendTexture, Renderer::Backend::ITexture *fallbackBackendTexture)
Definition: TextureManager.cpp:1005
std::unique_ptr< Tex > m_TextureData
Definition: TextureManager.h:358
void UploadBackendTextureIfNeeded(Renderer::Backend::IDeviceCommandContext *deviceCommandContext)
Uploads a texture data to a backend texture if successfully loaded.
Definition: TextureManager.cpp:935
std::unique_ptr< Renderer::Backend::ITexture > m_BackendTexture
Definition: TextureManager.h:354
size_t GetWidth() const
Returns the width (in pixels) of the current texture.
Definition: TextureManager.cpp:1013
size_t GetUploadedSize() const
Returns total number of bytes uploaded for this texture.
Definition: TextureManager.cpp:1039
bool TryLoad()
Attempt to load the texture data quickly, as with GetUploadedBackendTextureIfNeeded().
Definition: TextureManager.cpp:976
std::weak_ptr< CTexture > m_Self
Definition: TextureManager.h:378
enum CTexture::@12 m_State
bool IsLoaded() const
Returns whether the texture data is currently loaded.
Definition: TextureManager.h:320
@ HIGH_NEEDS_CONVERTING
Definition: TextureManager.h:368
@ UNLOADED
Definition: TextureManager.h:364
@ PREFETCH_IS_CONVERTING
Definition: TextureManager.h:367
@ PREFETCH_NEEDS_LOADING
Definition: TextureManager.h:365
@ PREFETCH_NEEDS_CONVERTING
Definition: TextureManager.h:366
@ HIGH_IS_CONVERTING
Definition: TextureManager.h:369
@ LOADED
Definition: TextureManager.h:370
@ UPLOADED
Definition: TextureManager.h:371
size_t m_UploadedSize
Definition: TextureManager.h:359
void Prefetch()
Activate the prefetching optimisation for this texture.
Definition: TextureManager.cpp:994
u32 m_BaseColor
Definition: TextureManager.h:357
Definition: path.h:80
Definition: IDeviceCommandContext.h:42
Definition: IDevice.h:48
Definition: ITexture.h:34
std::shared_ptr< CTexture > CTexturePtr
Definition: Texture.h:23
AddressMode
Definition: Sampler.h:42
Format
Definition: Format.h:28
Definition: vfs_util.cpp:39
Definition: TextureManager.cpp:341
Definition: TextureManager.cpp:318
uint32_t u32
Definition: types.h:39
std::shared_ptr< IVFS > PIVFS
Definition: vfs.h:220
unsigned int uint32_t
Definition: wposix_types.h:53