!T (Renderer) Outputing a fatal error when the non-optional principle textures are...
[CRYENGINE.git] / Code / CryEngine / RenderDll / Common / Textures / Texture.cpp
blob9208996824e347d2e31e7e107efae6524e205d13
1 // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
3 /*=============================================================================
4 Texture.cpp : Common texture manager implementation.
6 Revision history:
7 * Created by Honich Andrey
9 =============================================================================*/
11 #include "StdAfx.h"
12 #include <Cry3DEngine/ImageExtensionHelper.h>
13 #include "Image/CImage.h"
14 #include "Image/DDSImage.h"
15 #include "TextureManager.h"
16 #include <CrySystem/Scaleform/IFlashUI.h>
17 #include <CrySystem/File/IResourceManager.h>
18 #include <Cry3DEngine/I3DEngine.h>
19 #include <CryString/StringUtils.h> // stristr()
20 #include "TextureStreamPool.h"
21 #include "TextureHelpers.h"
22 #include <CrySystem/Scaleform/IUIFramework.h>
23 #include <CrySystem/Scaleform/IScaleformHelper.h>
25 // class CMipmapGenPass;
26 #include "../../XRenderD3D9/GraphicsPipeline/Common/UtilityPasses.h"
28 #define TEXTURE_LEVEL_CACHE_PAK "dds0.pak"
30 SSamplerState SSamplerState::s_sDefState;
32 STexStageInfo CTexture::s_TexStages[MAX_TMU];
33 SamplerStateHandle CTexture::s_TexStateIDs[eHWSC_Num][MAX_TMU];
34 int CTexture::s_nStreamingMode;
35 int CTexture::s_nStreamingUpdateMode;
36 bool CTexture::s_bPrecachePhase;
37 bool CTexture::s_bInLevelPhase = false;
38 bool CTexture::s_bPrestreamPhase;
39 int CTexture::s_nStreamingThroughput = 0;
40 float CTexture::s_nStreamingTotalTime = 0;
41 CTextureStreamPoolMgr* CTexture::s_pPoolMgr;
42 std::set<string> CTexture::s_vTexReloadRequests;
43 CryCriticalSection CTexture::s_xTexReloadLock;
44 CryCriticalSectionNonRecursive CTexture::s_invalidationLock;
45 #ifdef TEXTURE_GET_SYSTEM_COPY_SUPPORT
46 CTexture::LowResSystemCopyType CTexture::s_LowResSystemCopy;
47 #endif
49 bool CTexture::m_bLoadedSystem;
51 // ==============================================================================
52 CTexture* CTexture::s_ptexNoTexture;
53 CTexture* CTexture::s_ptexNoTextureCM;
54 CTexture* CTexture::s_ptexWhite;
55 CTexture* CTexture::s_ptexGray;
56 CTexture* CTexture::s_ptexBlack;
57 CTexture* CTexture::s_ptexBlackAlpha;
58 CTexture* CTexture::s_ptexBlackCM;
59 CTexture* CTexture::s_ptexDefaultProbeCM;
60 CTexture* CTexture::s_ptexDefaultMergedDetail;
61 CTexture* CTexture::s_ptexFlatBump;
62 #if !defined(_RELEASE)
63 CTexture* CTexture::s_ptexMipMapDebug;
64 CTexture* CTexture::s_ptexColorBlue;
65 CTexture* CTexture::s_ptexColorCyan;
66 CTexture* CTexture::s_ptexColorGreen;
67 CTexture* CTexture::s_ptexColorPurple;
68 CTexture* CTexture::s_ptexColorRed;
69 CTexture* CTexture::s_ptexColorWhite;
70 CTexture* CTexture::s_ptexColorYellow;
71 CTexture* CTexture::s_ptexColorOrange;
72 CTexture* CTexture::s_ptexColorMagenta;
73 #endif
74 CTexture* CTexture::s_ptexPaletteDebug;
75 CTexture* CTexture::s_ptexPaletteTexelsPerMeter;
76 CTexture* CTexture::s_ptexIconShaderCompiling;
77 CTexture* CTexture::s_ptexIconStreaming;
78 CTexture* CTexture::s_ptexIconStreamingTerrainTexture;
79 CTexture* CTexture::s_ptexIconNavigationProcessing;
80 CTexture* CTexture::s_ptexMipColors_Diffuse;
81 CTexture* CTexture::s_ptexMipColors_Bump;
82 CTexture* CTexture::s_ptexShadowJitterMap;
83 CTexture* CTexture::s_ptexEnvironmentBRDF;
84 CTexture* CTexture::s_ptexScreenNoiseMap;
85 CTexture* CTexture::s_ptexDissolveNoiseMap;
86 CTexture* CTexture::s_ptexNoise3D;
87 CTexture* CTexture::s_ptexGrainFilterMap;
88 CTexture* CTexture::s_ptexFilmGrainMap;
89 CTexture* CTexture::s_ptexVignettingMap;
90 CTexture* CTexture::s_ptexAOJitter;
91 CTexture* CTexture::s_ptexAOVOJitter;
92 CTexture* CTexture::s_ptexFromRE[8];
93 CTexture* CTexture::s_ptexShadowID[8];
94 CTexture* CTexture::s_ptexShadowMask;
95 CTexture* CTexture::s_ptexCachedShadowMap[MAX_GSM_LODS_NUM];
96 CTexture* CTexture::s_ptexNearestShadowMap;
97 CTexture* CTexture::s_ptexHeightMapAO[2];
98 CTexture* CTexture::s_ptexHeightMapAODepth[2];
99 CTexture* CTexture::s_ptexFromRE_FromContainer[2];
100 CTexture* CTexture::s_ptexFromObj;
101 CTexture* CTexture::s_ptexSvoTree;
102 CTexture* CTexture::s_ptexSvoTris;
103 CTexture* CTexture::s_ptexSvoGlobalCM;
104 CTexture* CTexture::s_ptexSvoRgbs;
105 CTexture* CTexture::s_ptexSvoNorm;
106 CTexture* CTexture::s_ptexSvoOpac;
107 CTexture* CTexture::s_ptexRT_2D;
108 CTexture* CTexture::s_ptexNormalsFitting;
109 CTexture* CTexture::s_ptexPerlinNoiseMap;
111 CTexture* CTexture::s_ptexSceneNormalsMap;
112 CTexture* CTexture::s_ptexSceneNormalsMapMS;
113 CTexture* CTexture::s_ptexSceneNormalsBent;
114 CTexture* CTexture::s_ptexAOColorBleed;
115 CTexture* CTexture::s_ptexSceneDiffuse;
116 CTexture* CTexture::s_ptexSceneSpecular;
118 CTexture* CTexture::s_ptexSceneSelectionIDs;
119 CTexture* CTexture::s_ptexSceneHalfDepthStencil;
121 CTexture* CTexture::s_ptexWindGrid;
123 #if defined(DURANGO_USE_ESRAM)
124 CTexture* CTexture::s_ptexSceneSpecularESRAM;
125 #endif
127 // Post-process related textures
128 CTexture* CTexture::s_ptexBackBuffer = NULL;
129 CTexture* CTexture::s_ptexModelHudBuffer;
130 CTexture* CTexture::s_ptexPrevBackBuffer[2][2] = {
131 { NULL }
133 CTexture* CTexture::s_ptexCached3DHud;
134 CTexture* CTexture::s_ptexCached3DHudScaled;
135 CTexture* CTexture::s_ptexBackBufferScaled[3];
136 CTexture* CTexture::s_ptexBackBufferScaledTemp[2];
137 CTexture* CTexture::s_ptexPrevFrameScaled;
139 CTexture* CTexture::s_ptexDepthBufferQuarter;
140 CTexture* CTexture::s_ptexDepthBufferHalfQuarter;
142 CTexture* CTexture::s_ptexWaterOcean;
143 CTexture* CTexture::s_ptexWaterVolumeTemp[2];
144 CTexture* CTexture::s_ptexWaterVolumeDDN;
145 CTexture* CTexture::s_ptexWaterVolumeRefl[2] = { NULL };
146 CTexture* CTexture::s_ptexWaterCaustics[2] = { NULL };
147 CTexture* CTexture::s_ptexRainOcclusion;
148 CTexture* CTexture::s_ptexRainSSOcclusion[2];
150 CTexture* CTexture::s_ptexRainDropsRT[2];
152 CTexture* CTexture::s_ptexRT_ShadowPool;
153 CTexture* CTexture::s_ptexFarPlane;
154 CTexture* CTexture::s_ptexCloudsLM;
156 CTexture* CTexture::s_ptexSceneTarget = NULL;
157 CTexture* CTexture::s_ptexSceneTargetR11G11B10F[2] = { NULL };
158 CTexture* CTexture::s_ptexSceneTargetScaledR11G11B10F[4] = { NULL };
159 CTexture* CTexture::s_ptexCurrSceneTarget;
160 CTexture* CTexture::s_ptexCurrentSceneDiffuseAccMap;
161 CTexture* CTexture::s_ptexSceneDiffuseAccMap;
162 CTexture* CTexture::s_ptexSceneSpecularAccMap;
163 CTexture* CTexture::s_ptexSceneDiffuseAccMapMS;
164 CTexture* CTexture::s_ptexSceneSpecularAccMapMS;
165 CTexture* CTexture::s_ptexZTarget;
166 CTexture* CTexture::s_ptexZOcclusion[2];
167 CTexture* CTexture::s_ptexZTargetReadBack[4];
168 CTexture* CTexture::s_ptexZTargetDownSample[4];
169 CTexture* CTexture::s_ptexZTargetScaled;
170 CTexture* CTexture::s_ptexZTargetScaled2;
171 CTexture* CTexture::s_ptexZTargetScaled3;
172 CTexture* CTexture::s_ptexHDRTarget;
173 CTexture* CTexture::s_ptexVelocity;
174 CTexture* CTexture::s_ptexVelocityTiles[3] = { NULL };
175 CTexture* CTexture::s_ptexVelocityObjects[2] = { NULL };
176 CTexture* CTexture::s_ptexHDRTargetPrev = NULL;
177 CTexture* CTexture::s_ptexHDRTargetScaled[4];
178 CTexture* CTexture::s_ptexHDRTargetScaledTmp[4];
179 CTexture* CTexture::s_ptexHDRTargetScaledTempRT[4];
180 CTexture* CTexture::s_ptexHDRDofLayers[2];
181 CTexture* CTexture::s_ptexSceneCoC[MIN_DOF_COC_K] = { NULL };
182 CTexture* CTexture::s_ptexSceneCoCTemp = NULL;
183 CTexture* CTexture::s_ptexHDRTempBloom[2];
184 CTexture* CTexture::s_ptexHDRFinalBloom;
185 CTexture* CTexture::s_ptexHDRAdaptedLuminanceCur[8];
186 int CTexture::s_nCurLumTextureIndex;
187 CTexture* CTexture::s_ptexCurLumTexture;
188 CTexture* CTexture::s_ptexHDRToneMaps[NUM_HDR_TONEMAP_TEXTURES];
189 CTexture* CTexture::s_ptexHDRMeasuredLuminance[MAX_GPU_NUM];
190 CTexture* CTexture::s_ptexHDRMeasuredLuminanceDummy;
191 CTexture* CTexture::s_ptexSkyDomeMie;
192 CTexture* CTexture::s_ptexSkyDomeRayleigh;
193 CTexture* CTexture::s_ptexSkyDomeMoon;
194 CTexture* CTexture::s_ptexColorChart;
195 CTexture* CTexture::s_ptexSceneTargetScaled;
196 CTexture* CTexture::s_ptexSceneTargetScaledBlurred;
197 CTexture* CTexture::s_ptexStereoL = NULL;
198 CTexture* CTexture::s_ptexStereoR = NULL;
199 CTexture* CTexture::s_ptexQuadLayers[2] = { NULL };
201 CTexture* CTexture::s_ptexFlaresOcclusionRing[MAX_OCCLUSION_READBACK_TEXTURES] = { NULL };
202 CTexture* CTexture::s_ptexFlaresGather = NULL;
204 SEnvTexture CTexture::s_EnvTexts[MAX_ENVTEXTURES];
206 TArray<SEnvTexture> CTexture::s_CustomRT_2D;
208 TArray<CTexture> CTexture::s_ShaderTemplates(EFTT_MAX);
209 bool CTexture::s_ShaderTemplatesInitialized = false;
211 CTexture* CTexture::s_pTexNULL = 0;
213 CTexture* CTexture::s_pBackBuffer;
214 CTexture* CTexture::s_FrontBufferTextures[2] = { NULL };
216 CTexture* CTexture::s_ptexVolumetricFog = NULL;
217 CTexture* CTexture::s_ptexVolumetricClipVolumeStencil = NULL;
219 CTexture* CTexture::s_ptexVolCloudShadow = NULL;
221 #if defined(TEXSTRM_DEFERRED_UPLOAD)
222 ID3D11DeviceContext* CTexture::s_pStreamDeferredCtx = nullptr;
223 #endif
225 #if defined(VOLUMETRIC_FOG_SHADOWS)
226 CTexture* CTexture::s_ptexVolFogShadowBuf[2] = { 0 };
227 #endif
229 ETEX_Format CTexture::s_eTFZ = eTF_R32F;
231 //============================================================
233 SResourceView SResourceView::ShaderResourceView(DXGI_FORMAT nFormat, int nFirstSlice, int nSliceCount, int nMostDetailedMip, int nMipCount, bool bSrgbRead, bool bMultisample, int nFlags)
235 SResourceView result(0);
237 result.m_Desc.eViewType = eShaderResourceView;
238 result.m_Desc.nFormat = nFormat;
239 result.m_Desc.nFirstSlice = nFirstSlice;
240 result.m_Desc.nSliceCount = nSliceCount;
241 result.m_Desc.nMostDetailedMip = nMostDetailedMip;
242 result.m_Desc.nMipCount = nMipCount;
243 result.m_Desc.bSrgbRead = bSrgbRead ? 1 : 0;
244 result.m_Desc.nFlags = nFlags;
245 result.m_Desc.bMultisample = bMultisample ? 1 : 0;
247 return result;
250 SResourceView SResourceView::RenderTargetView(DXGI_FORMAT nFormat, int nFirstSlice, int nSliceCount, int nMipLevel, bool bMultisample)
252 SResourceView result(0);
254 result.m_Desc.eViewType = eRenderTargetView;
255 result.m_Desc.nFormat = nFormat;
256 result.m_Desc.nFirstSlice = nFirstSlice;
257 result.m_Desc.nSliceCount = nSliceCount;
258 result.m_Desc.nMostDetailedMip = nMipLevel;
259 result.m_Desc.nMipCount = 1;
260 result.m_Desc.bMultisample = bMultisample ? 1 : 0;
262 return result;
265 SResourceView SResourceView::DepthStencilView(DXGI_FORMAT nFormat, int nFirstSlice, int nSliceCount, int nMipLevel, bool bMultisample, int nFlags)
267 SResourceView result(0);
269 result.m_Desc.eViewType = eDepthStencilView;
270 result.m_Desc.nFormat = nFormat;
271 result.m_Desc.nFirstSlice = nFirstSlice;
272 result.m_Desc.nSliceCount = nSliceCount;
273 result.m_Desc.nMostDetailedMip = nMipLevel;
274 result.m_Desc.nMipCount = 1;
275 result.m_Desc.nFlags = nFlags;
276 result.m_Desc.bMultisample = bMultisample ? 1 : 0;
278 return result;
281 SResourceView SResourceView::UnorderedAccessView(DXGI_FORMAT nFormat, int nFirstSlice, int nSliceCount, int nMipLevel, int nFlags)
283 SResourceView result(0);
285 result.m_Desc.eViewType = eUnorderedAccessView;
286 result.m_Desc.nFormat = nFormat;
287 result.m_Desc.nFirstSlice = nFirstSlice;
288 result.m_Desc.nSliceCount = nSliceCount;
289 result.m_Desc.nMostDetailedMip = nMipLevel;
290 result.m_Desc.nMipCount = 1;
291 result.m_Desc.nFlags = nFlags;
293 return result;
296 //============================================================
298 template<typename T>
299 static inline uint32 ConvertFromTextureFlags(ETextureFlags eFlags)
301 // NOTE Currently without correspondence:
303 // FT_DONT_RELEASE
304 // FT_USAGE_MSAA
305 // FT_FROMIMAGE
306 // FT_USAGE_ALLOWREADSRGB
308 // *INDENT-OFF*
309 return
310 (!(eFlags & FT_DONT_READ ) ? CDeviceObjectFactory::BIND_SHADER_RESOURCE : 0) |
311 ( (eFlags & FT_USAGE_RENDERTARGET ) ? CDeviceObjectFactory::BIND_RENDER_TARGET : 0) |
312 ( (eFlags & FT_USAGE_DEPTHSTENCIL ) ? CDeviceObjectFactory::BIND_DEPTH_STENCIL : 0) |
313 ( (eFlags & FT_USAGE_UNORDERED_ACCESS) ? CDeviceObjectFactory::BIND_UNORDERED_ACCESS : 0) |
314 ( (eFlags & FT_USAGE_DYNAMIC ) ? CDeviceObjectFactory::USAGE_CPU_WRITE : 0) |
315 (!(eFlags & FT_DONT_STREAM ) ? CDeviceObjectFactory::USAGE_STREAMING : 0) |
316 ( (eFlags & FT_STAGE_READBACK ) ? (CDeviceObjectFactory::USAGE_STAGE_ACCESS | CDeviceObjectFactory::USAGE_CPU_READ ) : 0) |
317 ( (eFlags & FT_STAGE_UPLOAD ) ? (CDeviceObjectFactory::USAGE_STAGE_ACCESS | CDeviceObjectFactory::USAGE_CPU_WRITE) : 0) |
318 ( (eFlags & FT_FORCE_MIPS ) ? CDeviceObjectFactory::USAGE_AUTOGENMIPS : 0) |
319 ( (eFlags & FT_USAGE_UAV_RWTEXTURE ) ? CDeviceObjectFactory::USAGE_UAV_READWRITE : 0);
320 // *INDENT-ON*
323 template<typename T>
324 static inline ETextureFlags ConvertToTextureFlags(uint32 eFlags)
326 // NOTE Currently without correspondence:
328 // FT_DONT_RELEASE
329 // FT_USAGE_MSAA
330 // FT_FROMIMAGE
331 // FT_USAGE_ALLOWREADSRGB
333 // *INDENT-OFF*
334 return ETextureFlags(
335 (!(eFlags & CDeviceObjectFactory::BIND_SHADER_RESOURCE ) ? FT_DONT_READ : 0) |
336 ( (eFlags & CDeviceObjectFactory::BIND_RENDER_TARGET ) ? FT_USAGE_RENDERTARGET : 0) |
337 ( (eFlags & CDeviceObjectFactory::BIND_DEPTH_STENCIL ) ? FT_USAGE_DEPTHSTENCIL : 0) |
338 ( (eFlags & CDeviceObjectFactory::BIND_UNORDERED_ACCESS ) ? FT_USAGE_UNORDERED_ACCESS : 0) |
339 (((eFlags & (CDeviceObjectFactory::USAGE_STAGE_ACCESS | CDeviceObjectFactory::USAGE_CPU_WRITE ))
340 == CDeviceObjectFactory::USAGE_CPU_WRITE ) ? FT_USAGE_DYNAMIC : 0) |
341 (!(eFlags & CDeviceObjectFactory::USAGE_STREAMING ) ? FT_DONT_STREAM : 0) |
342 ( (eFlags & (CDeviceObjectFactory::USAGE_STAGE_ACCESS | CDeviceObjectFactory::USAGE_CPU_READ )) ? FT_STAGE_READBACK : 0) |
343 ( (eFlags & (CDeviceObjectFactory::USAGE_STAGE_ACCESS | CDeviceObjectFactory::USAGE_CPU_WRITE)) ? FT_STAGE_UPLOAD : 0) |
344 ( (eFlags & CDeviceObjectFactory::USAGE_AUTOGENMIPS ) ? FT_FORCE_MIPS : 0) |
345 ( (eFlags & CDeviceObjectFactory::USAGE_UAV_READWRITE ) ? FT_USAGE_UAV_RWTEXTURE : 0));
346 // *INDENT-ON*
349 //============================================================
350 CTexture::CTexture(const uint32 nFlags, const ColorF& clearColor /*= ColorF(Clr_Empty)*/, CDeviceTexture* devTexToOwn /*= nullptr*/)
352 m_eFlags = nFlags;
353 m_eDstFormat = eTF_Unknown;
354 m_eSrcFormat = eTF_Unknown;
355 m_nMips = 1;
356 m_nWidth = 0;
357 m_nHeight = 0;
358 m_eTT = eTT_2D;
359 m_nDepth = 1;
360 m_nArraySize = 1;
361 m_nDevTextureSize = 0;
362 m_fAvgBrightness = 1.0f;
363 m_cMinColor = 0.0f;
364 m_cMaxColor = 1.0f;
365 m_cClearColor = clearColor;
366 m_nPersistentSize = 0;
367 m_fAvgBrightness = 0.0f;
369 #if CRY_PLATFORM_DURANGO && (CRY_RENDERER_DIRECT3D >= 110) && (CRY_RENDERER_DIRECT3D < 120)
370 m_nDeviceAddressInvalidated = 0;
371 #endif
372 #if CRY_PLATFORM_DURANGO && DURANGO_USE_ESRAM
373 m_nESRAMOffset = SKIP_ESRAM;
374 #endif
376 m_nUpdateFrameID = -1;
377 m_nAccessFrameID = -1;
378 m_nCustomID = -1;
379 m_pPixelFormat = NULL;
380 m_pDevTexture = NULL;
382 m_bAsyncDevTexCreation = false;
384 m_bIsLocked = false;
385 m_bNeedRestoring = false;
386 m_bNoTexture = false;
387 m_bResolved = true;
388 m_bUseMultisampledRTV = true;
389 m_bHighQualityFiltering = false;
390 m_bCustomFormat = false;
391 m_eSrcTileMode = eTM_Unspecified;
393 m_bPostponed = false;
394 m_bForceStreamHighRes = false;
395 m_bWasUnloaded = false;
396 m_bStreamed = false;
397 m_bStreamPrepared = false;
398 m_bStreamRequested = false;
399 m_bVertexTexture = false;
400 m_bUseDecalBorderCol = false;
401 m_bIsSRGB = false;
402 m_bNoDevTexture = false;
403 m_bInDistanceSortedList = false;
404 m_bCreatedInLevel = gRenDev->m_bInLevel;
405 m_bUsedRecently = 0;
406 m_bStatTracked = 0;
407 m_bStreamHighPriority = 0;
408 m_nStreamingPriority = 0;
409 m_nMinMipVidUploaded = MAX_MIP_LEVELS;
410 m_nMinMipVidActive = MAX_MIP_LEVELS;
411 m_nStreamSlot = InvalidStreamSlot;
412 m_fpMinMipCur = MAX_MIP_LEVELS << 8;
413 m_nStreamFormatCode = 0;
415 m_nDefState = EDefaultSamplerStates::PointClamp;
416 m_pFileTexMips = NULL;
417 m_fCurrentMipBias = 0.f;
419 static_assert(MaxStreamTasks < 32767, "Too many stream tasks!");
421 if (devTexToOwn)
423 OwnDevTexture(devTexToOwn);
427 //============================================================
429 CTexture::~CTexture()
431 InvalidateDeviceResource(eResourceDestroyed);
433 // sizes of these structures should NOT exceed L2 cache line!
434 #if CRY_PLATFORM_64BIT
435 static_assert((offsetof(CTexture, m_composition) - offsetof(CTexture, m_pFileTexMips)) <= 64, "Invalid offset!");
436 //static_assert((offsetof(CTexture, m_pFileTexMips) % 64) == 0, "Invalid offset!");
437 #endif
439 #ifndef _RELEASE
440 if (!gRenDev->m_pRT->IsRenderThread() || gRenDev->m_pRT->IsRenderLoadingThread())
441 __debugbreak();
442 #endif
444 #ifndef _RELEASE
445 if (IsStreaming())
446 __debugbreak();
447 #endif
449 if (gRenDev && gRenDev->m_pRT)
450 gRenDev->m_pRT->RC_ReleaseDeviceTexture(this);
452 if (m_pFileTexMips)
454 Unlink();
455 StreamState_ReleaseInfo(this, m_pFileTexMips);
456 m_pFileTexMips = NULL;
459 #ifdef ENABLE_TEXTURE_STREAM_LISTENER
460 if (s_pStreamListener)
461 s_pStreamListener->OnDestroyedStreamedTexture(this);
462 #endif
464 #ifndef _RELEASE
465 if (m_bInDistanceSortedList)
466 __debugbreak();
467 #endif
469 #ifdef TEXTURE_GET_SYSTEM_COPY_SUPPORT
470 s_LowResSystemCopy.erase(this);
471 #endif
473 CRY_ASSERT_MESSAGE(m_invalidateCallbacks.empty(), "Make sure any clients (e.g. Renderpasses, resource sets, etc..) are released before destroying this resource");
476 void CTexture::RT_ReleaseDevice()
478 ReleaseDeviceTexture(false);
481 const CCryNameTSCRC& CTexture::mfGetClassName()
483 return s_sClassName;
486 CCryNameTSCRC CTexture::GenName(const char* name, uint32 nFlags)
488 stack_string strName = name;
489 strName.MakeLower();
491 //'\\' in texture names causing duplication
492 PathUtil::ToUnixPath(strName);
494 if (nFlags & FT_ALPHA)
495 strName += "_a";
497 return CCryNameTSCRC(strName.c_str());
500 class StrComp
502 public:
503 bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }
506 CTexture* CTexture::GetByID(int nID)
508 CTexture* pTex = s_ptexNoTexture;
510 const CCryNameTSCRC& className = mfGetClassName();
511 CBaseResource* pBR = CBaseResource::GetResource(className, nID, false);
512 if (pBR)
513 pTex = (CTexture*)pBR;
514 return pTex;
517 CTexture* CTexture::GetByName(const char* szName, uint32 flags)
519 CTexture* pTex = nullptr;
521 CCryNameTSCRC Name = GenName(szName, flags);
522 CBaseResource* pBR = CBaseResource::GetResource(mfGetClassName(), Name, false);
523 if (pBR)
524 pTex = (CTexture*)pBR;
525 return pTex;
528 CTexture* CTexture::GetByNameCRC(CCryNameTSCRC Name)
530 CTexture* pTex = nullptr;
532 CBaseResource* pBR = CBaseResource::GetResource(mfGetClassName(), Name, false);
533 if (pBR)
534 pTex = (CTexture*)pBR;
535 return pTex;
538 CTexture* CTexture::FindOrRegisterTextureObject(const char* name, uint32 nFlags, ETEX_Format eTFDst, bool& bFound)
540 CTexture* pTex = nullptr;
542 CCryNameTSCRC Name = GenName(name, nFlags);
543 CBaseResource* pBR = CBaseResource::GetResource(mfGetClassName(), Name, false);
544 if (!pBR)
546 pTex = new CTexture(nFlags);
547 pTex->Register(mfGetClassName(), Name);
548 pTex->m_eFlags = nFlags;
549 pTex->m_eDstFormat = eTFDst;
550 pTex->m_SrcName = name;
551 bFound = false;
553 else
555 pTex = (CTexture*)pBR;
556 pTex->AddRef();
557 bFound = true;
560 return pTex;
563 void CTexture::SetDevTexture(CDeviceTexture* pDeviceTex)
565 if (m_pDevTexture)
566 m_pDevTexture->SetOwner(NULL);
567 SAFE_RELEASE(m_pDevTexture);
569 m_pDevTexture = pDeviceTex;
570 if (m_pDevTexture)
572 m_pDevTexture->SetNoDelete(!!(m_eFlags & FT_DONT_RELEASE));
573 m_pDevTexture->SetOwner(this);
576 InvalidateDeviceResource(eDeviceResourceDirty);
579 void CTexture::OwnDevTexture(CDeviceTexture* pDeviceTex)
581 SAFE_RELEASE(m_pDevTexture);
583 m_pDevTexture = pDeviceTex;
584 if (m_pDevTexture)
586 const STextureLayout Layput = m_pDevTexture->GetLayout();
588 m_nWidth = Layput.m_nWidth;
589 m_nHeight = Layput.m_nHeight;
590 m_nDepth = Layput.m_nDepth;
591 m_nArraySize = Layput.m_nArraySize;
592 m_nMips = Layput.m_nMips;
593 m_eSrcFormat = Layput.m_eSrcFormat;
594 m_eDstFormat = Layput.m_eDstFormat;
595 m_pPixelFormat = Layput.m_pPixelFormat;
596 m_eTT = Layput.m_eTT;
597 m_eFlags = Layput.m_eFlags; /* TODO: change FT_... to CDeviceObjectFactory::... */
598 m_bIsSRGB = Layput.m_bIsSRGB;
600 m_nDevTextureSize = m_nPersistentSize = m_pDevTexture->GetDeviceSize();
601 CryInterlockedAdd(&CTexture::s_nStatsCurManagedNonStreamedTexMem, m_nDevTextureSize);
604 InvalidateDeviceResource(eDeviceResourceDirty);
607 void CTexture::PostCreate()
609 m_nUpdateFrameID = gRenDev->GetFrameID(false);
610 m_bPostponed = false;
613 void CTexture::GetMemoryUsage(ICrySizer* pSizer) const
615 pSizer->Add(*this);
616 pSizer->AddObject(m_SrcName);
618 #ifdef TEXTURE_GET_SYSTEM_COPY_SUPPORT
619 const LowResSystemCopyType::iterator& it = s_LowResSystemCopy.find(this);
620 if (it != CTexture::s_LowResSystemCopy.end())
621 pSizer->AddObject((*it).second.m_lowResSystemCopy);
622 #endif
624 if (m_pFileTexMips)
625 m_pFileTexMips->GetMemoryUsage(pSizer, m_nMips, m_CacheFileHeader.m_nSides);
628 //=======================================================
629 // Low-level functions calling CreateDeviceTexture()
631 bool CTexture::CreateRenderTarget(ETEX_Format eFormat, const ColorF& cClear)
633 if (m_eSrcFormat == eTF_Unknown)
634 m_eSrcFormat = eFormat;
635 if (m_eSrcFormat == eTF_Unknown)
636 return false;
637 const void** pData = nullptr;
639 SetClosestFormatSupported();
640 m_eFlags |= FT_USAGE_RENDERTARGET;
641 m_cClearColor = cClear;
642 m_nMips = m_eFlags & FT_FORCE_MIPS ? CTexture::CalcNumMips(m_nWidth, m_nHeight) : m_nMips;
643 bool bRes = CreateDeviceTexture(pData);
644 PostCreate();
646 return bRes;
649 bool CTexture::CreateDepthStencil(ETEX_Format eFormat, const ColorF& cClear)
651 if (m_eSrcFormat == eTF_Unknown)
652 m_eSrcFormat = eFormat;
653 if (m_eSrcFormat == eTF_Unknown)
654 return false;
655 const void** pData = nullptr;
657 SetClosestFormatSupported();
658 m_eFlags |= FT_USAGE_DEPTHSTENCIL;
659 m_cClearColor = cClear;
660 m_nMips = m_eFlags & FT_FORCE_MIPS ? CTexture::CalcNumMips(m_nWidth, m_nHeight) : m_nMips;
661 bool bRes = CreateDeviceTexture(pData);
662 PostCreate();
664 return bRes;
667 bool CTexture::CreateShaderResource(STexData& td)
669 m_nWidth = td.m_nWidth;
670 m_nHeight = td.m_nHeight;
671 m_nDepth = td.m_nDepth;
672 m_eSrcFormat = td.m_eFormat;
673 m_nMips = td.m_nMips;
674 m_fAvgBrightness = td.m_fAvgBrightness;
675 m_cMinColor = td.m_cMinColor;
676 m_cMaxColor = td.m_cMaxColor;
677 m_cClearColor = ColorF(0.0f, 0.0f, 0.0f, 1.0f);
678 m_bUseDecalBorderCol = (td.m_nFlags & FIM_DECAL) != 0;
679 m_bIsSRGB = (td.m_nFlags & FIM_SRGB_READ) != 0;
681 assert((m_nDepth == 1) || (m_eTT == eTT_3D));
682 assert((m_nArraySize == 1) || (m_eTT == eTT_Cube || m_eTT == eTT_CubeArray || m_eTT == eTT_2DArray));
683 assert((m_nArraySize % 6) || (m_eTT == eTT_Cube || m_eTT == eTT_CubeArray));
684 assert(!td.m_pData[1] || !(m_eFlags & FT_REPLICATE_TO_ALL_SIDES) || (m_eTT == eTT_Cube || m_eTT == eTT_CubeArray));
685 assert(m_nWidth && m_nHeight && m_nMips);
687 SetClosestFormatSupported();
688 if (!ImagePreprocessing(td))
689 return false;
691 assert(m_nWidth && m_nHeight && m_nMips);
693 const int nMaxTextureSize = gRenDev->GetMaxTextureSize();
694 if (nMaxTextureSize > 0)
696 if (m_nWidth > nMaxTextureSize || m_nHeight > nMaxTextureSize)
697 return false;
700 // Semi-consecutive data: {{slice,0},{slice,0},{0,0}}
701 const void* pData[6 * 2 + 2];
702 pData[6 * 2 + 0] = nullptr;
703 pData[6 * 2 + 1] = nullptr;
704 for (uint32 i = 0; i < 6; i++)
705 pData[i * 2 + 0] = td.m_pData[i],
706 pData[i * 2 + 1] = nullptr;
708 bool bRes = CreateDeviceTexture(pData);
710 return bRes;
713 //=======================================================
714 // Mid-level functions calling Create...()
716 bool CTexture::Create2DTexture(int nWidth, int nHeight, int nMips, int nFlags, byte* pSrcData, ETEX_Format eSrcFormat)
718 if (nMips <= 0)
719 nMips = CTexture::CalcNumMips(nWidth, nHeight);
720 m_eSrcTileMode = pSrcData ? eTM_None : eTM_Unspecified;
721 m_eSrcFormat = eSrcFormat;
722 m_nMips = nMips;
724 STexData td;
725 td.m_eFormat = eSrcFormat;
726 td.m_nWidth = nWidth;
727 td.m_nHeight = nHeight;
728 td.m_nDepth = 1;
729 td.m_nMips = nMips;
730 td.m_pData[0] = pSrcData;
732 bool bRes = CreateShaderResource(td);
733 if (!bRes)
734 m_eFlags |= FT_FAILED;
736 PostCreate();
738 return bRes;
741 bool CTexture::Create3DTexture(int nWidth, int nHeight, int nDepth, int nMips, int nFlags, byte* pSrcData, ETEX_Format eSrcFormat)
743 //if (nMips <= 0)
744 // nMips = CTexture::CalcNumMips(nWidth, nHeight);
745 m_eSrcTileMode = pSrcData ? eTM_None : eTM_Unspecified;
746 m_eSrcFormat = eSrcFormat;
747 m_nMips = nMips;
749 STexData td;
750 td.m_eFormat = eSrcFormat;
751 td.m_nWidth = nWidth;
752 td.m_nHeight = nHeight;
753 td.m_nDepth = nDepth;
754 td.m_nMips = nMips;
755 td.m_pData[0] = pSrcData;
757 bool bRes = CreateShaderResource(td);
758 if (!bRes)
759 m_eFlags |= FT_FAILED;
761 PostCreate();
763 return bRes;
766 //=======================================================
767 // High-level functions calling Create...()
769 CTexture* CTexture::GetOrCreateTextureObject(const char* name, uint32 nWidth, uint32 nHeight, int nDepth, ETEX_Type eTT, uint32 nFlags, ETEX_Format eFormat, int nCustomID)
771 SYNCHRONOUS_LOADING_TICK();
773 bool bFound = false;
775 MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Texture, 0, "%s", name);
777 CTexture* pTex = FindOrRegisterTextureObject(name, nFlags, eFormat, bFound);
778 if (bFound)
780 if (pTex->m_nWidth == 0)
781 pTex->SetWidth(nWidth);
782 if (pTex->m_nHeight == 0)
783 pTex->SetHeight(nHeight);
785 pTex->m_nMips = nFlags & FT_FORCE_MIPS ? CTexture::CalcNumMips(pTex->m_nWidth, pTex->m_nHeight) : pTex->m_nMips;
786 pTex->m_eFlags |= nFlags & (FT_DONT_RELEASE | FT_USAGE_RENDERTARGET | FT_USAGE_DEPTHSTENCIL);
788 return pTex;
791 pTex->m_nDepth = nDepth;
792 pTex->SetWidth(nWidth);
793 pTex->SetHeight(nHeight);
794 pTex->m_nMips = nFlags & FT_FORCE_MIPS ? CTexture::CalcNumMips(pTex->m_nWidth, pTex->m_nHeight) : pTex->m_nMips;
795 pTex->m_eTT = eTT;
796 pTex->m_eSrcFormat = eFormat;
797 pTex->m_nCustomID = nCustomID;
798 pTex->m_SrcName = name;
799 pTex->SetClosestFormatSupported();
801 return pTex;
804 _smart_ptr<CTexture> CTexture::GetOrCreateTextureObjectPtr(const char* name, uint32 nWidth, uint32 nHeight, int nDepth, ETEX_Type eTT, uint32 nFlags, ETEX_Format eFormat, int nCustomID)
806 CTexture* pTex = GetOrCreateTextureObject(name, nWidth, nHeight, nDepth, eTT, nFlags, eFormat, nCustomID);
807 _smart_ptr<CTexture> result;
808 result.Assign_NoAddRef(pTex);
810 return result;
813 CTexture* CTexture::GetOrCreateTextureArray(const char* name, uint32 nWidth, uint32 nHeight, uint32 nArraySize, int nMips, ETEX_Type eType, uint32 nFlags, ETEX_Format eFormat, int nCustomID)
815 assert(eType == eTT_2DArray || eType == eTT_CubeArray);
817 if (nArraySize > 2048 /*D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION*/)
819 assert(0);
820 return NULL;
823 if (nMips <= 0)
824 nMips = CTexture::CalcNumMips(nWidth, nHeight);
826 bool sRGB = (nFlags & FT_USAGE_ALLOWREADSRGB) != 0;
827 nFlags &= ~FT_USAGE_ALLOWREADSRGB;
829 CTexture* pTex = GetOrCreateTextureObject(name, nWidth, nHeight, 1, eType, nFlags, eFormat, nCustomID);
830 pTex->SetWidth(nWidth);
831 pTex->SetHeight(nHeight);
832 pTex->m_nMips = nFlags & FT_FORCE_MIPS ? CTexture::CalcNumMips(pTex->m_nWidth, pTex->m_nHeight) : pTex->m_nMips;
833 pTex->m_nArraySize = nArraySize; assert((eType != eTT_CubeArray) || !(nArraySize % 6));
834 pTex->m_nDepth = 1;
836 bool bRes;
837 if (nFlags & FT_USAGE_RENDERTARGET)
839 bRes = pTex->CreateRenderTarget(eFormat, Clr_Unknown);
841 else if (nFlags & FT_USAGE_DEPTHSTENCIL)
843 bRes = pTex->CreateDepthStencil(eFormat, Clr_Unknown);
845 else
847 STexData td;
849 td.m_eFormat = eFormat;
850 td.m_nDepth = 1;
851 td.m_nWidth = nWidth;
852 td.m_nHeight = nHeight;
853 td.m_nMips = nMips;
854 td.m_nFlags = sRGB ? FIM_SRGB_READ : 0;
856 bRes = pTex->CreateShaderResource(td);
859 if (!bRes)
860 pTex->m_eFlags |= FT_FAILED;
861 pTex->PostCreate();
863 return pTex;
866 CTexture* CTexture::GetOrCreateRenderTarget(const char* name, uint32 nWidth, uint32 nHeight, const ColorF& cClear, ETEX_Type eTT, uint32 nFlags, ETEX_Format eFormat, int nCustomID)
868 CTexture* pTex = GetOrCreateTextureObject(name, nWidth, nHeight, 1, eTT, nFlags | FT_USAGE_RENDERTARGET, eFormat, nCustomID);
869 pTex->SetWidth(nWidth);
870 pTex->SetHeight(nHeight);
871 pTex->m_nMips = nFlags & FT_FORCE_MIPS ? CTexture::CalcNumMips(pTex->m_nWidth, pTex->m_nHeight) : pTex->m_nMips;
872 pTex->m_eFlags |= nFlags;
874 bool bRes = pTex->CreateRenderTarget(eFormat, cClear);
875 if (!bRes)
876 pTex->m_eFlags |= FT_FAILED;
877 pTex->PostCreate();
879 return pTex;
882 CTexture* CTexture::GetOrCreateDepthStencil(const char* name, uint32 nWidth, uint32 nHeight, const ColorF& cClear, ETEX_Type eTT, uint32 nFlags, ETEX_Format eFormat, int nCustomID)
884 CTexture* pTex = GetOrCreateTextureObject(name, nWidth, nHeight, 1, eTT, nFlags | FT_USAGE_DEPTHSTENCIL, eFormat, nCustomID);
885 pTex->SetWidth(nWidth);
886 pTex->SetHeight(nHeight);
887 pTex->m_nMips = nFlags & FT_FORCE_MIPS ? CTexture::CalcNumMips(pTex->m_nWidth, pTex->m_nHeight) : pTex->m_nMips;
888 pTex->m_eFlags |= nFlags;
890 bool bRes = pTex->CreateDepthStencil(eFormat, cClear);
891 if (!bRes)
892 pTex->m_eFlags |= FT_FAILED;
893 pTex->PostCreate();
895 return pTex;
898 CTexture* CTexture::GetOrCreate2DTexture(const char* szName, int nWidth, int nHeight, int nMips, int nFlags, byte* pSrcData, ETEX_Format eSrcFormat, bool bAsyncDevTexCreation)
900 FUNCTION_PROFILER(GetISystem(), PROFILE_RENDERER);
902 CTexture* pTex = GetOrCreateTextureObject(szName, nWidth, nHeight, 1, eTT_2D, nFlags, eSrcFormat, -1);
903 pTex->m_bAsyncDevTexCreation = bAsyncDevTexCreation;
904 bool bFound = false;
906 pTex->Create2DTexture(nWidth, nHeight, nMips, nFlags, pSrcData, eSrcFormat);
908 return pTex;
911 CTexture* CTexture::GetOrCreate3DTexture(const char* szName, int nWidth, int nHeight, int nDepth, int nMips, int nFlags, byte* pSrcData, ETEX_Format eSrcFormat)
913 CTexture* pTex = GetOrCreateTextureObject(szName, nWidth, nHeight, nDepth, eTT_3D, nFlags, eSrcFormat, -1);
914 bool bFound = false;
916 pTex->Create3DTexture(nWidth, nHeight, nDepth, nMips, nFlags, pSrcData, eSrcFormat);
918 return pTex;
921 CTexture* CTexture::GetOrCreate2DCompositeTexture(const char* szName, int nWidth, int nHeight, int nMips, int nFlags, ETEX_Format eFormat, const STexComposition* pCompositions, size_t nCompositions)
923 nFlags |= FT_COMPOSITE;
924 nFlags &= ~FT_DONT_STREAM;
926 if (nMips <= 0)
927 nMips = CTexture::CalcNumMips(nWidth, nHeight);
929 bool bFound = false;
930 CTexture* pTex = FindOrRegisterTextureObject(szName, nFlags, eFormat, bFound);
931 if (!bFound)
933 pTex->SetWidth(nWidth);
934 pTex->SetHeight(nHeight);
935 pTex->m_nMips = nMips;
936 pTex->m_composition.assign(pCompositions, pCompositions + nCompositions);
938 // Strip all invalid textures from the composition
940 int w = 0;
941 for (int r = 0, c = pTex->m_composition.size(); r != c; ++r)
943 if (!pTex->m_composition[r].pTexture)
945 CryWarning(VALIDATOR_MODULE_RENDERER, VALIDATOR_WARNING, "Composition %i for '%s' is missing", r, szName);
946 continue;
949 if (r != w)
950 pTex->m_composition[w] = pTex->m_composition[r];
951 ++w;
953 pTex->m_composition.resize(w);
955 if (CTexture::s_bPrecachePhase)
957 pTex->m_bPostponed = true;
958 pTex->m_bWasUnloaded = true;
960 else
962 pTex->StreamPrepareComposition();
966 return pTex;
969 //=======================================================
971 bool CTexture::Reload()
973 bool bOK = false;
975 // If the texture is flagged to not be released, we skip the reloading
976 if (m_eFlags & FT_DONT_RELEASE)
977 return bOK;
979 if (IsStreamed())
981 ReleaseDeviceTexture(false);
982 return ToggleStreaming(true);
985 if (m_eFlags & FT_FROMIMAGE)
987 assert(!(m_eFlags & (FT_USAGE_RENDERTARGET | FT_USAGE_DEPTHSTENCIL | FT_USAGE_DYNAMIC)));
988 bOK = LoadFromImage(m_SrcName.c_str()); // true=reloading
989 if (!bOK)
990 SetNoTexture(m_eTT == eTT_Cube ? s_ptexNoTextureCM : s_ptexNoTexture);
992 else if (m_eFlags & (FT_USAGE_RENDERTARGET | FT_USAGE_DEPTHSTENCIL | FT_USAGE_DYNAMIC))
994 const void** pData = nullptr;
995 bOK = CreateDeviceTexture(pData);
996 assert(bOK);
999 PostCreate();
1001 return bOK;
1004 CTexture* CTexture::ForName(const char* name, uint32 nFlags, ETEX_Format eFormat)
1006 SLICE_AND_SLEEP();
1008 bool bFound = false;
1010 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Textures");
1011 MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Texture, 0, "%s", name);
1013 CRY_DEFINE_ASSET_SCOPE("Texture", name);
1015 CTexture* pTex = FindOrRegisterTextureObject(name, nFlags, eFormat, bFound);
1016 if (bFound || name[0] == '$')
1018 if (!bFound)
1020 pTex->m_SrcName = name;
1022 else
1024 // switch off streaming for the same texture with the same flags except DONT_STREAM
1025 if ((nFlags & FT_DONT_STREAM) != 0 && (pTex->GetFlags() & FT_DONT_STREAM) == 0)
1027 if (!pTex->m_bPostponed)
1028 pTex->ReleaseDeviceTexture(false);
1029 pTex->m_eFlags |= FT_DONT_STREAM;
1030 if (!pTex->m_bPostponed)
1031 pTex->Reload();
1035 return pTex;
1037 pTex->m_SrcName = name;
1039 #ifndef _RELEASE
1040 pTex->m_sAssetScopeName = gEnv->pLog->GetAssetScopeString();
1041 #endif
1043 if (CTexture::s_bPrecachePhase || (pTex->m_eFlags & FT_ASYNC_PREPARE))
1045 // NOTE: attached alpha isn't detectable by flags before the header is loaded, so we do it by file-suffix
1046 if (/*(nFlags & FT_TEX_NORMAL_MAP) &&*/ TextureHelpers::VerifyTexSuffix(EFTT_NORMALS, name) && TextureHelpers::VerifyTexSuffix(EFTT_SMOOTHNESS, name))
1047 nFlags |= FT_HAS_ATTACHED_ALPHA;
1049 pTex->m_eDstFormat = eFormat;
1050 pTex->m_eFlags = nFlags;
1051 pTex->m_bPostponed = true;
1052 pTex->m_bWasUnloaded = true;
1055 if (!CTexture::s_bPrecachePhase)
1056 pTex->Load(eFormat);
1058 return pTex;
1061 _smart_ptr<CTexture> CTexture::ForNamePtr(const char* name, uint32 nFlags, ETEX_Format eFormat)
1063 CTexture* pTex = ForName(name, nFlags, eFormat);
1064 _smart_ptr<CTexture> result;
1065 result.Assign_NoAddRef(pTex);
1067 return result;
1071 struct CompareTextures
1073 bool operator()(const CTexture* a, const CTexture* b)
1075 return (stricmp(a->GetSourceName(), b->GetSourceName()) < 0);
1079 void CTexture::Precache()
1081 LOADING_TIME_PROFILE_SECTION(iSystem);
1083 if (!s_bPrecachePhase)
1084 return;
1085 if (!gRenDev)
1086 return;
1088 gEnv->pLog->UpdateLoadingScreen("Requesting textures precache ...");
1090 gRenDev->m_pRT->RC_PreloadTextures();
1092 gEnv->pLog->UpdateLoadingScreen("Textures precache done.");
1095 void CTexture::RT_Precache()
1097 if (gRenDev->CheckDeviceLost())
1098 return;
1100 LOADING_TIME_PROFILE_SECTION(iSystem);
1102 // Disable invalid file access logging if texture streaming is disabled
1103 // If texture streaming is turned off, we will hit this on the renderthread
1104 // and stall due to the invalid file access stalls
1105 ICVar* sysPakLogInvalidAccess = NULL;
1106 int pakLogFileAccess = 0;
1107 if (!CRenderer::CV_r_texturesstreaming)
1109 if (sysPakLogInvalidAccess = gEnv->pConsole->GetCVar("sys_PakLogInvalidFileAccess"))
1111 pakLogFileAccess = sysPakLogInvalidAccess->GetIVal();
1115 CTimeValue t0 = gEnv->pTimer->GetAsyncTime();
1116 CryLog("-- Precaching textures...");
1117 iLog->UpdateLoadingScreen(0);
1119 std::vector<CTexture*> TexturesForPrecaching;
1120 std::vector<CTexture*> TexturesForComposition;
1122 bool bTextureCacheExists = false;
1125 AUTO_LOCK(CBaseResource::s_cResLock);
1127 SResourceContainer* pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
1128 if (pRL)
1130 TexturesForPrecaching.reserve(pRL->m_RMap.size());
1132 ResourcesMapItor itor;
1133 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++)
1135 CTexture* tp = (CTexture*)itor->second;
1136 if (!tp)
1137 continue;
1138 if (tp->CTexture::IsPostponed())
1140 if (tp->CTexture::GetFlags() & FT_COMPOSITE)
1141 TexturesForComposition.push_back(tp);
1142 else
1143 TexturesForPrecaching.push_back(tp);
1149 // Preload all the post poned textures
1151 if (!gEnv->IsEditor())
1152 CryLog("=============================== Loading textures ================================");
1154 std::vector<CTexture*>& Textures = TexturesForPrecaching;
1155 std::sort(Textures.begin(), Textures.end(), CompareTextures());
1157 gEnv->pSystem->GetStreamEngine()->PauseStreaming(false, 1 << eStreamTaskTypeTexture);
1159 int numTextures = Textures.size();
1160 int prevProgress = 0;
1162 for (uint32 i = 0; i < Textures.size(); i++)
1164 CTexture* tp = Textures[i];
1166 if (!CRenderer::CV_r_texturesstreaming || !tp->m_bStreamPrepared)
1168 tp->m_bPostponed = false;
1169 tp->Load(tp->m_eDstFormat);
1171 int progress = (i * 10) / numTextures;
1172 if (progress != prevProgress)
1174 prevProgress = progress;
1175 gEnv->pLog->UpdateLoadingScreen("Precaching progress: %d", progress);
1179 while (s_StreamPrepTasks.GetNumLive())
1181 if (gRenDev->m_pRT->IsRenderThread() && !gRenDev->m_pRT->IsRenderLoadingThread())
1183 StreamState_Update();
1184 StreamState_UpdatePrep();
1186 else if (gRenDev->m_pRT->IsRenderLoadingThread())
1188 StreamState_UpdatePrep();
1191 CrySleep(1);
1194 for (uint32 i = 0; i < Textures.size(); i++)
1196 CTexture* tp = Textures[i];
1198 if (tp->m_bStreamed && tp->m_bForceStreamHighRes)
1200 tp->m_bStreamHighPriority |= 1;
1201 tp->m_fpMinMipCur = 0;
1202 s_pTextureStreamer->Precache(tp);
1206 if (!gEnv->IsEditor())
1207 CryLog("========================== Finished loading textures ============================");
1211 std::vector<CTexture*>& Textures = TexturesForComposition;
1213 for (uint32 i = 0; i < Textures.size(); i++)
1215 CTexture* tp = Textures[i];
1217 if (!CRenderer::CV_r_texturesstreaming || !tp->m_bStreamPrepared)
1219 tp->m_bPostponed = false;
1220 tp->StreamPrepareComposition();
1224 for (uint32 i = 0; i < Textures.size(); i++)
1226 CTexture* tp = Textures[i];
1228 if (tp->m_bStreamed && tp->m_bForceStreamHighRes)
1230 tp->m_bStreamHighPriority |= 1;
1231 tp->m_fpMinMipCur = 0;
1232 s_pTextureStreamer->Precache(tp);
1237 if (bTextureCacheExists)
1239 //GetISystem()->GetIResourceManager()->UnloadLevelCachePak( TEXTURE_LEVEL_CACHE_PAK );
1242 CTimeValue t1 = gEnv->pTimer->GetAsyncTime();
1243 float dt = (t1 - t0).GetSeconds();
1244 CryLog("Precaching textures done in %.2f seconds", dt);
1246 s_bPrecachePhase = false;
1248 // Restore pakLogFileAccess if it was disabled during precaching
1249 // because texture precaching was disabled
1250 if (pakLogFileAccess)
1252 sysPakLogInvalidAccess->Set(pakLogFileAccess);
1256 bool CTexture::Load(ETEX_Format eFormat)
1258 LOADING_TIME_PROFILE_SECTION_NAMED_ARGS("CTexture::Load(ETEX_Format eTFDst)", m_SrcName);
1259 m_bWasUnloaded = false;
1260 m_bStreamed = false;
1262 bool bFound = LoadFromImage(m_SrcName.c_str(), eFormat); // false=not reloading
1264 if (!bFound)
1265 SetNoTexture(m_eTT == eTT_Cube ? s_ptexNoTextureCM : s_ptexNoTexture);
1267 m_eFlags |= FT_FROMIMAGE;
1268 PostCreate();
1270 return bFound;
1273 bool CTexture::ToggleStreaming(const bool bEnable)
1275 if (!(m_eFlags & (FT_FROMIMAGE | FT_DONT_RELEASE)) || (m_eFlags & FT_DONT_STREAM))
1276 return false;
1277 AbortStreamingTasks(this);
1278 if (bEnable)
1280 if (IsStreamed())
1281 return true;
1282 ReleaseDeviceTexture(false);
1283 m_bStreamed = true;
1284 if (StreamPrepare(true))
1285 return true;
1286 if (m_pFileTexMips)
1288 Unlink();
1289 StreamState_ReleaseInfo(this, m_pFileTexMips);
1290 m_pFileTexMips = NULL;
1292 m_bStreamed = false;
1293 if (m_bNoTexture)
1294 return true;
1296 ReleaseDeviceTexture(false);
1297 return Reload();
1300 bool CTexture::LoadFromImage(const char* name, ETEX_Format eFormat)
1302 LOADING_TIME_PROFILE_SECTION_ARGS(name);
1304 if (CRenderer::CV_r_texnoload)
1306 if (SetNoTexture())
1307 return true;
1310 string sFileName(name);
1311 sFileName.MakeLower();
1313 m_eDstFormat = eFormat;
1315 // try to stream-in the texture
1316 if (CRenderer::CV_r_texturesstreaming && !(m_eFlags & FT_DONT_STREAM) && (m_eTT == eTT_2D || m_eTT == eTT_Cube))
1318 m_bStreamed = true;
1319 if (StreamPrepare(true))
1321 assert(m_pDevTexture);
1322 return true;
1324 m_eFlags |= FT_DONT_STREAM;
1325 m_bStreamed = false;
1326 m_bForceStreamHighRes = false;
1327 if (m_bNoTexture)
1329 if (m_pFileTexMips)
1331 Unlink();
1332 StreamState_ReleaseInfo(this, m_pFileTexMips);
1333 m_pFileTexMips = NULL;
1334 m_bStreamed = false;
1336 return true;
1340 #ifndef _RELEASE
1341 CRY_DEFINE_ASSET_SCOPE("Texture", m_sAssetScopeName);
1342 #endif
1344 if (m_bPostponed)
1346 if (s_pTextureStreamer->BeginPrepare(this, sFileName, (m_eFlags & FT_ALPHA) ? FIM_ALPHA : 0))
1347 return true;
1350 uint32 nImageFlags =
1351 ((m_eFlags & FT_ALPHA) ? FIM_ALPHA : 0) |
1352 ((m_eFlags & FT_STREAMED_PREPARE) ? FIM_READ_VIA_STREAMS : 0);
1354 _smart_ptr<CImageFile> pImage = CImageFile::mfLoad_file(sFileName, nImageFlags);
1355 return Load(pImage);
1358 bool CTexture::Load(CImageFile* pImage)
1360 if (!pImage || pImage->mfGetFormat() == eTF_Unknown)
1361 return false;
1363 LOADING_TIME_PROFILE_SECTION_NAMED_ARGS("CTexture::Load(CImageFile* pImage)", pImage->mfGet_filename().c_str());
1365 if ((m_eFlags & FT_ALPHA) && !pImage->mfIs_image(0))
1367 SetNoTexture(s_ptexWhite);
1368 return true;
1370 const char* name = pImage->mfGet_filename().c_str();
1371 if (pImage->mfGet_Flags() & FIM_SPLITTED) // propagate splitted file flag
1372 m_eFlags |= FT_SPLITTED;
1373 if (pImage->mfGet_Flags() & FIM_X360_NOT_PRETILED)
1374 m_eFlags |= FT_TEX_WAS_NOT_PRE_TILED;
1375 if (pImage->mfGet_Flags() & FIM_FILESINGLE) // propagate flag from image to texture
1376 m_eFlags |= FT_FILESINGLE;
1377 if (pImage->mfGet_Flags() & FIM_NORMALMAP)
1379 if (!(m_eFlags & FT_TEX_NORMAL_MAP) && !CryStringUtils::stristr(name, "_ddn"))
1381 // becomes reported as editor error
1382 gEnv->pSystem->Warning(VALIDATOR_MODULE_RENDERER, VALIDATOR_WARNING, VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE,
1383 name, "Not a normal map texture attempted to be used as a normal map: %s", name);
1387 if (!(m_eFlags & FT_ALPHA) && !(
1388 pImage->mfGetFormat() == eTF_BC5U || pImage->mfGetFormat() == eTF_BC5S || pImage->mfGetFormat() == eTF_BC7 ||
1389 pImage->mfGetFormat() == eTF_EAC_RG11 || pImage->mfGetFormat() == eTF_EAC_RG11S
1390 ) && CryStringUtils::stristr(name, "_ddn") != 0 && GetDevTexture()) // improvable code
1392 // becomes reported as editor error
1393 gEnv->pSystem->Warning(VALIDATOR_MODULE_RENDERER, VALIDATOR_WARNING, VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE,
1394 name, "Wrong format '%s' for normal map texture '%s'", CTexture::GetFormatName(), name);
1397 if (pImage->mfGet_Flags() & FIM_NOTSUPPORTS_MIPS && !(m_eFlags & FT_NOMIPS))
1398 m_eFlags |= FT_FORCE_MIPS;
1399 if (pImage->mfGet_Flags() & FIM_HAS_ATTACHED_ALPHA)
1400 m_eFlags |= FT_HAS_ATTACHED_ALPHA; // if the image has alpha attached we store this in the CTexture
1402 m_eSrcTileMode = pImage->mfGetTileMode();
1403 m_nArraySize = pImage->mfGet_NumSides();
1404 m_eTT =
1405 (pImage->mfGet_depth () > 1) ? eTT_3D :
1406 (pImage->mfGet_NumSides() == 6) ? eTT_Cube :
1407 !(pImage->mfGet_NumSides() % 6) ? eTT_CubeArray :
1408 (pImage->mfGet_NumSides() == 1) ? eTT_2D :
1409 eTT_2DArray;
1411 STexData td;
1412 td.m_nFlags = pImage->mfGet_Flags();
1413 td.m_pData[0] = pImage->mfGet_image(0);
1414 td.m_nWidth = pImage->mfGet_width();
1415 td.m_nHeight = pImage->mfGet_height();
1416 td.m_nDepth = pImage->mfGet_depth();
1417 td.m_eFormat = pImage->mfGetFormat();
1418 td.m_nMips = pImage->mfGet_numMips();
1419 td.m_fAvgBrightness = pImage->mfGet_avgBrightness();
1420 td.m_cMinColor = pImage->mfGet_minColor();
1421 td.m_cMaxColor = pImage->mfGet_maxColor();
1422 if ((m_eFlags & FT_NOMIPS) || td.m_nMips <= 0)
1423 td.m_nMips = 1;
1424 td.m_pFilePath = pImage->mfGet_filename();
1426 // base range after normalization, fe. [0,1] for 8bit images, or [0,2^15] for RGBE/HDR data
1427 if (CImageExtensionHelper::IsDynamicRange(td.m_eFormat))
1429 td.m_cMinColor /= td.m_cMaxColor.a;
1430 td.m_cMaxColor /= td.m_cMaxColor.a;
1433 // check if it's a cubemap
1434 if (pImage->mfIs_image(1))
1436 for (int i = 1; i < 6; i++)
1438 td.m_pData[i] = pImage->mfGet_image(i);
1442 bool bRes = false;
1443 if (pImage)
1445 FormatFixup(td);
1446 bRes = CreateShaderResource(td);
1449 for (int i = 0; i < 6; i++)
1450 if (td.m_pData[i] && td.WasReallocated(i))
1451 SAFE_DELETE_ARRAY(td.m_pData[i]);
1453 return bRes;
1456 void CTexture::UpdateData(STexData &td, int flags)
1458 m_eFlags = flags;
1459 m_eDstFormat = td.m_eFormat;
1460 CreateShaderResource(td);
1463 ETEX_Format CTexture::FormatFixup(ETEX_Format eFormat)
1465 switch (eFormat)
1467 case eTF_L8V8U8X8:
1468 case eTF_L8V8U8:
1469 return eTF_R8G8B8A8S;
1470 case eTF_B8G8R8:
1471 case eTF_A8L8:
1472 case eTF_L8:
1473 return eTF_R8G8B8A8;
1475 // only available as hardware format under DX11.1 with DXGI 1.2
1476 case eTF_B5G5R5A1:
1477 case eTF_B5G6R5:
1478 case eTF_B4G4R4A4:
1480 //! Only available as hardware format under Vulkan or XBO.
1481 case eTF_R4G4:
1482 case eTF_R4G4B4A4:
1484 const SPixFormat* pPF;
1485 return GetClosestFormatSupported(eFormat, pPF);
1488 default:
1489 return eFormat;
1493 bool CTexture::FormatFixup(STexData& td)
1495 const ETEX_Format eSrcFormat = td.m_eFormat;
1496 const ETEX_Format eDstFormat = FormatFixup(td.m_eFormat);
1497 CRY_ASSERT(eDstFormat != eTF_Unknown);
1499 if (m_eSrcTileMode == eTM_None)
1501 // Try and expand
1502 int nSourceSize = CTexture::TextureDataSize(td.m_nWidth, td.m_nHeight, td.m_nDepth, td.m_nMips, 1, eSrcFormat);
1503 int nTargetSize = CTexture::TextureDataSize(td.m_nWidth, td.m_nHeight, td.m_nDepth, td.m_nMips, 1, eDstFormat);
1505 for (int nImage = 0; nImage < sizeof(td.m_pData) / sizeof(td.m_pData[0]); ++nImage)
1507 if (td.m_pData[nImage])
1509 byte* pNewImage = new byte[nTargetSize];
1510 CTexture::ExpandMipFromFile(pNewImage, nTargetSize, td.m_pData[nImage], nSourceSize, eSrcFormat, eDstFormat);
1511 td.AssignData(nImage, pNewImage);
1515 td.m_eFormat = eDstFormat;
1517 else
1519 #ifndef _RELEASE
1520 if (eDstFormat != eSrcFormat)
1521 __debugbreak();
1522 #endif
1525 return true;
1528 bool CTexture::ImagePreprocessing(STexData& td)
1530 FUNCTION_PROFILER(GetISystem(), PROFILE_RENDERER);
1532 const char* pTexFileName = td.m_pFilePath ? td.m_pFilePath : "$Unknown";
1534 if (m_eDstFormat == eTF_Unknown)
1536 td.m_pData[0] = td.m_pData[1] = td.m_pData[2] = td.m_pData[3] = td.m_pData[4] = td.m_pData[5] = 0;
1537 m_nWidth = m_nHeight = m_nDepth = m_nMips = 0;
1539 #if !defined(_RELEASE)
1540 TextureError(pTexFileName, "Trying to create a texture with unsupported target format %s!", NameForTextureFormat(m_eSrcFormat));
1541 #endif
1542 return false;
1545 const ETEX_Format eSrcFormat = td.m_eFormat;
1546 const bool fmtConversionNeeded = eSrcFormat != m_eDstFormat;
1548 #if !CRY_PLATFORM_WINDOWS || CRY_RENDERER_OPENGL
1549 if (fmtConversionNeeded)
1551 td.m_pData[0] = td.m_pData[1] = td.m_pData[2] = td.m_pData[3] = td.m_pData[4] = td.m_pData[5] = 0;
1552 m_nWidth = m_nHeight = m_nDepth = m_nMips = 0;
1554 #if !defined(_RELEASE)
1555 TextureError(pTexFileName, "Trying an image format conversion from %s to %s. This is not supported on this platform!", NameForTextureFormat(eSrcFormat), NameForTextureFormat(m_eDstFormat));
1556 #endif
1557 return false;
1559 #else
1561 const bool doProcessing = fmtConversionNeeded && (m_eFlags & FT_TEX_FONT) == 0; // we generate the font in native format
1562 if (doProcessing)
1564 const int nSrcWidth = td.m_nWidth;
1565 const int nSrcHeight = td.m_nHeight;
1567 for (int i = 0; i < 6; i++)
1569 byte* pSrcData = td.m_pData[i];
1570 if (pSrcData)
1572 int nOutSize = 0;
1573 byte* pNewData = Convert(pSrcData, nSrcWidth, nSrcHeight, td.m_nMips, eSrcFormat, m_eDstFormat, td.m_nMips, nOutSize, true);
1574 if (pNewData)
1575 td.AssignData(i, pNewData);
1579 #endif
1581 #if defined(TEXTURE_GET_SYSTEM_COPY_SUPPORT)
1582 if (m_eFlags & FT_KEEP_LOWRES_SYSCOPY)
1583 PrepareLowResSystemCopy(td.m_pData[0], true);
1584 #endif
1586 return true;
1589 int CTexture::CalcNumMips(int nWidth, int nHeight)
1591 int nMips = 0;
1592 while (nWidth || nHeight)
1594 if (!nWidth ) nWidth = 1;
1595 if (!nHeight) nHeight = 1;
1596 nWidth >>= 1;
1597 nHeight >>= 1;
1598 nMips++;
1600 return nMips;
1603 uint32 CTexture::TextureDataSize(uint32 nWidth, uint32 nHeight, uint32 nDepth, uint32 nMips, uint32 nSlices, const ETEX_Format eTF, ETEX_TileMode eTM)
1605 FUNCTION_PROFILER_RENDERER;
1607 // Don't allow 0 dimensions, it's clearly wrong to reflect on "unspecified-yet" textures.
1608 CRY_ASSERT(eTF != eTF_Unknown && nWidth && nHeight && nDepth);
1609 // Allow 0 mips and 0 slices to generate offsets with this function.
1610 if (!nMips || !nSlices)
1611 return 0;
1613 const bool bIsBlockCompressed = IsBlockCompressed(eTF);
1614 nWidth = max(1U, nWidth );
1615 nHeight = max(1U, nHeight);
1616 nDepth = max(1U, nDepth );
1618 if (eTM != eTM_None)
1620 // NOTE: Using this function to acquire strides of elements or rows (and even slices in arrays),
1621 // is not yielding any usable information. In the moment the clients need to be aware that
1622 // the internal layout for tiled modes can't be interpreted and stay away from it.
1623 // TODO: Create separate interfaces for sub-resource size queries and for layout-stride queries
1625 #if CRY_PLATFORM_ORBIS
1626 if (bIsBlockCompressed)
1628 nWidth = ((nWidth + 3) & (-4));
1629 nHeight = ((nHeight + 3) & (-4));
1631 #endif
1633 #if CRY_PLATFORM_CONSOLE
1634 return CDeviceTexture::TextureDataSize(nWidth, nHeight, nDepth, nMips, nSlices, eTF, eTM, CDeviceObjectFactory::BIND_SHADER_RESOURCE);
1635 #endif
1637 __debugbreak();
1638 return 0;
1640 else
1642 const uint32 nBytesPerElement = bIsBlockCompressed ? BytesPerBlock(eTF) : BytesPerPixel(eTF);
1644 uint32 nSize = 0;
1645 while ((nWidth || nHeight || nDepth) && nMips)
1647 nWidth = max(1U, nWidth );
1648 nHeight = max(1U, nHeight);
1649 nDepth = max(1U, nDepth );
1651 uint32 nU = nWidth;
1652 uint32 nV = nHeight;
1653 uint32 nW = nDepth;
1655 if (bIsBlockCompressed)
1657 // depth is not 4x4x4 compressed, but 4x4x1
1658 nU = ((nWidth + 3) / (4));
1659 nV = ((nHeight + 3) / (4));
1662 nSize += nU * nV * nW * nBytesPerElement;
1664 nWidth >>= 1;
1665 nHeight >>= 1;
1666 nDepth >>= 1;
1668 --nMips;
1671 return nSize * nSlices;
1675 bool CTexture::IsInPlaceFormat(const ETEX_Format fmt)
1677 switch (fmt)
1679 case eTF_R8G8B8A8S:
1680 case eTF_R8G8B8A8:
1682 case eTF_R1:
1683 case eTF_A8:
1684 case eTF_R8:
1685 case eTF_R8S:
1686 case eTF_R16:
1687 case eTF_R16S:
1688 case eTF_R16F:
1689 case eTF_R32F:
1690 case eTF_R8G8:
1691 case eTF_R8G8S:
1692 case eTF_R16G16:
1693 case eTF_R16G16S:
1694 case eTF_R16G16F:
1695 case eTF_R32G32F:
1696 case eTF_R11G11B10F:
1697 case eTF_R10G10B10A2:
1698 case eTF_R16G16B16A16:
1699 case eTF_R16G16B16A16S:
1700 case eTF_R16G16B16A16F:
1701 case eTF_R32G32B32A32F:
1703 case eTF_BC1:
1704 case eTF_BC2:
1705 case eTF_BC3:
1706 case eTF_BC4U:
1707 case eTF_BC4S:
1708 case eTF_BC5U:
1709 case eTF_BC5S:
1710 #if defined(CRY_DDS_DX10_SUPPORT)
1711 case eTF_BC6UH:
1712 case eTF_BC6SH:
1713 case eTF_BC7:
1714 case eTF_R9G9B9E5:
1715 #endif
1716 case eTF_CTX1:
1717 case eTF_EAC_R11:
1718 case eTF_EAC_R11S:
1719 case eTF_EAC_RG11:
1720 case eTF_EAC_RG11S:
1721 case eTF_ETC2:
1722 case eTF_ETC2A:
1723 case eTF_ASTC_LDR_4x4:
1725 case eTF_B8G8R8A8:
1726 case eTF_B8G8R8X8:
1727 return true;
1728 default:
1729 return false;
1733 void CTexture::ExpandMipFromFile(byte* pSrcData, const int dstSize, const byte* src, const int srcSize, const ETEX_Format eSrcFormat, const ETEX_Format eDstFormat)
1735 if (IsInPlaceFormat(eSrcFormat))
1737 assert(dstSize == srcSize);
1738 if (pSrcData != src)
1740 cryMemcpy(pSrcData, src, srcSize);
1743 return;
1746 // upload mip from file with conversions depending on format and platform specifics
1747 switch (eSrcFormat)
1749 case eTF_B8G8R8: // -> eTF_R8G8B8A8
1750 assert(eDstFormat == eTF_R8G8B8A8);
1752 for (int i = srcSize / 3 - 1; i >= 0; --i)
1754 pSrcData[i * 4 + 0] = src[i * 3 + 2];
1755 pSrcData[i * 4 + 1] = src[i * 3 + 1];
1756 pSrcData[i * 4 + 2] = src[i * 3 + 0];
1757 pSrcData[i * 4 + 3] = 255;
1760 break;
1761 case eTF_L8V8U8X8: // -> eTF_R8G8B8A8S
1762 assert(eDstFormat == eTF_R8G8B8A8S);
1764 for (int i = srcSize / 4 - 1; i >= 0; --i)
1766 pSrcData[i * 4 + 0] = src[i * 3 + 0];
1767 pSrcData[i * 4 + 1] = src[i * 3 + 1];
1768 pSrcData[i * 4 + 2] = src[i * 3 + 2];
1769 pSrcData[i * 4 + 3] = src[i * 3 + 3];
1772 break;
1773 case eTF_L8V8U8: // -> eTF_R8G8B8A8S
1774 assert(eDstFormat == eTF_R8G8B8A8S);
1776 for (int i = srcSize / 3 - 1; i >= 0; --i)
1778 pSrcData[i * 4 + 0] = src[i * 3 + 0];
1779 pSrcData[i * 4 + 1] = src[i * 3 + 1];
1780 pSrcData[i * 4 + 2] = src[i * 3 + 2];
1781 pSrcData[i * 4 + 3] = 255;
1784 break;
1785 case eTF_L8: // -> eTF_R8G8B8A8
1786 assert(eDstFormat == eTF_R8G8B8A8);
1788 for (int i = srcSize - 1; i >= 0; --i)
1790 const byte bSrc = src[i];
1791 pSrcData[i * 4 + 0] = bSrc;
1792 pSrcData[i * 4 + 1] = bSrc;
1793 pSrcData[i * 4 + 2] = bSrc;
1794 pSrcData[i * 4 + 3] = 255;
1797 break;
1798 case eTF_A8L8: // -> eTF_R8G8B8A8
1799 assert(eDstFormat == eTF_R8G8B8A8);
1801 for (int i = srcSize - 1; i >= 0; i -= 2)
1803 const byte bSrcL = src[i - 1];
1804 const byte bSrcA = src[i - 0];
1805 pSrcData[i * 4 + 0] = bSrcL;
1806 pSrcData[i * 4 + 1] = bSrcL;
1807 pSrcData[i * 4 + 2] = bSrcL;
1808 pSrcData[i * 4 + 3] = bSrcA;
1811 break;
1813 case eTF_B5G5R5A1: // -> eTF_B8G8R8A8
1814 assert(eDstFormat == eTF_B8G8R8A8);
1816 for (int i = srcSize / 2 - 1; i >= 0; --i)
1818 const uint16 rgb5551 = uint16((src[i * 2 + 0] << 8) + src[i * 2 + 1]);
1819 pSrcData[i * 4 + 0] = ((rgb5551 >> 0) * 33) >> 2;
1820 pSrcData[i * 4 + 1] = ((rgb5551 >> 5) * 33) >> 2;
1821 pSrcData[i * 4 + 2] = ((rgb5551 >> 10) * 33) >> 2;
1822 pSrcData[i * 4 + 3] = ((rgb5551 >> 15) ? 255 : 0);
1825 break;
1826 case eTF_B5G6R5: // -> eTF_B8G8R8X8
1827 assert(eDstFormat == eTF_B8G8R8X8);
1829 for (int i = srcSize / 2 - 1; i >= 0; --i)
1831 const uint16 rgb565 = uint16((src[i * 2 + 0] << 8) + src[i * 2 + 1]);
1832 pSrcData[i * 4 + 0] = ((rgb565 >> 0) * 33) >> 2;
1833 pSrcData[i * 4 + 1] = ((rgb565 >> 5) * 65) >> 4;
1834 pSrcData[i * 4 + 2] = ((rgb565 >> 11) * 33) >> 2;
1835 pSrcData[i * 4 + 3] = 255;
1838 break;
1839 case eTF_B4G4R4A4: // -> eTF_B8G8R8A8
1840 case eTF_R4G4B4A4: // -> eTF_R8G8B8A8
1841 assert((eSrcFormat == eTF_B4G4R4A4 && eDstFormat == eTF_B8G8R8A8) ||
1842 (eSrcFormat == eTF_R4G4B4A4 && eDstFormat == eTF_R8G8B8A8));
1844 for (int i = srcSize / 2 - 1; i >= 0; --i)
1846 const uint16 rgb4444 = uint16((src[i * 2 + 0] << 8) + src[i * 2 + 1]);
1847 pSrcData[i * 4 + 0] = (rgb4444 >> 0) * 17;
1848 pSrcData[i * 4 + 1] = (rgb4444 >> 4) * 17;
1849 pSrcData[i * 4 + 2] = (rgb4444 >> 8) * 17;
1850 pSrcData[i * 4 + 3] = (rgb4444 >> 12) * 17;
1853 break;
1854 case eTF_R4G4: // -> eTF_R8G8|eTF_R8G8B8A8
1855 assert(eDstFormat == eTF_R8G8 || eDstFormat == eTF_R8G8B8A8);
1856 if (eDstFormat == eTF_R8G8)
1858 for (int i = srcSize / 1 - 1; i >= 0; --i)
1860 const uint8 rgb44 = uint8(src[i * 1 + 0]);
1861 pSrcData[i * 2 + 0] = (rgb44 >> 0) * 17;
1862 pSrcData[i * 2 + 1] = (rgb44 >> 4) * 17;
1865 else
1867 for (int i = srcSize / 1 - 1; i >= 0; --i)
1869 const uint8 rgb44 = uint8(src[i * 1 + 0]);
1870 pSrcData[i * 4 + 0] = (rgb44 >> 0) * 17;
1871 pSrcData[i * 4 + 1] = (rgb44 >> 4) * 17;
1872 pSrcData[i * 4 + 2] = 0;
1873 pSrcData[i * 4 + 3] = 255;
1876 break;
1878 default:
1879 assert(0);
1883 bool CTexture::Invalidate(int nNewWidth, int nNewHeight, ETEX_Format eNewFormat)
1885 bool bRelease = false;
1886 if (nNewWidth > 0 && nNewWidth != m_nWidth)
1888 m_nWidth = nNewWidth;
1889 bRelease = true;
1891 if (nNewHeight > 0 && nNewHeight != m_nHeight)
1893 m_nHeight = nNewHeight;
1894 bRelease = true;
1896 if (eNewFormat != eTF_Unknown && eNewFormat != m_eSrcFormat)
1898 m_eSrcFormat = eNewFormat;
1899 SetClosestFormatSupported();
1901 bRelease = true;
1904 if (!m_pDevTexture)
1905 return false;
1907 if (bRelease)
1909 if (m_eFlags & FT_FORCE_MIPS)
1910 m_nMips = 1;
1912 ReleaseDeviceTexture(true);
1915 return bRelease;
1918 D3DBaseView* CTexture::GetResourceView(const SResourceView& rvDesc)
1920 if (CDeviceTexture* pDevTex = GetDevTexture(rvDesc.m_Desc.bMultisample))
1922 ResourceViewHandle hView = pDevTex->GetOrCreateResourceViewHandle(rvDesc);
1923 return pDevTex->LookupResourceView(hView).second;
1926 return nullptr;
1929 D3DBaseView* CTexture::GetResourceView(const SResourceView& rvDesc) const
1931 if (CDeviceTexture* pDevTex = GetDevTexture(rvDesc.m_Desc.bMultisample))
1933 ResourceViewHandle hView = pDevTex->GetResourceViewHandle(rvDesc);
1934 if (hView != ResourceViewHandle::Unspecified)
1935 return pDevTex->LookupResourceView(hView).second;
1938 return nullptr;
1941 void CTexture::SetResourceView(const SResourceView& rvDesc, D3DBaseView* pView)
1943 if (CDeviceTexture* pDevTex = GetDevTexture(rvDesc.m_Desc.bMultisample))
1945 ResourceViewHandle hView = pDevTex->GetResourceViewHandle(rvDesc);
1946 if (hView != ResourceViewHandle::Unspecified)
1948 SAFE_RELEASE(pDevTex->LookupResourceView(hView).second);
1950 pDevTex->LookupResourceView(hView).second = pView;
1951 pDevTex->LookupResourceView(hView).second->AddRef();
1956 void CTexture::SetDefaultShaderResourceView(D3DBaseView* pDeviceShaderResource, bool bMultisampled /*= false*/)
1958 CDeviceTexture* pDevTex = GetDevTexture(bMultisampled && IsMSAA());
1960 SAFE_RELEASE(pDevTex->LookupResourceView(EDefaultResourceViews::Default).second);
1962 pDevTex->LookupResourceView(EDefaultResourceViews::Default).second = pDeviceShaderResource;
1963 pDevTex->LookupResourceView(EDefaultResourceViews::Default).second->AddRef();
1965 // Notify that resource is dirty
1966 if (!(m_eFlags & FT_USAGE_RENDERTARGET))
1968 InvalidateDeviceResource(eDeviceResourceViewDirty);
1972 byte* CTexture::GetData32(int nSide, int nLevel, byte* pDstData, ETEX_Format eDstFormat)
1974 #if CRY_PLATFORM_WINDOWS
1975 // NOTE: the function will not maintain any dirty state and always download the data, don't use it in the render-loop
1976 CDeviceTexture* pDevTexture = GetDevTexture();
1977 pDevTexture->DownloadToStagingResource(D3D11CalcSubresource(nLevel, nSide, m_nMips), [&](void* pData, uint32 rowPitch, uint32 slicePitch)
1979 if (m_eDstFormat != eTF_R8G8B8A8)
1981 int nOutSize = 0;
1983 if (m_eSrcFormat == eDstFormat && pDstData)
1985 memcpy(pDstData, pData, GetDeviceDataSize());
1987 else
1989 pDstData = Convert((byte*)pData, m_nWidth, m_nHeight, 1, m_eSrcFormat, eDstFormat, 1, nOutSize, true);
1992 else
1994 if (!pDstData)
1996 pDstData = new byte[m_nWidth * m_nHeight * 4];
1999 memcpy(pDstData, pData, m_nWidth * m_nHeight * 4);
2002 return true;
2005 return pDstData;
2006 #else
2007 return 0;
2008 #endif
2011 const int CTexture::GetSize(bool bIncludePool) const
2013 int nSize = sizeof(CTexture);
2014 nSize += m_SrcName.capacity();
2016 // TODO: neccessary?
2017 // if (m_pRenderTargetData)
2018 // {
2019 // nSize += sizeof(*m_pRenderTargetData);
2020 // nSize += m_pRenderTargetData->m_DirtyRects.capacity() * sizeof(RECT);
2021 // }
2023 if (m_pFileTexMips)
2025 nSize += m_pFileTexMips->GetSize(m_nMips, m_CacheFileHeader.m_nSides);
2026 if (bIncludePool && m_pFileTexMips->m_pPoolItem)
2027 nSize += m_pFileTexMips->m_pPoolItem->GetSize();
2030 return nSize;
2033 void CTexture::Init()
2035 SDynTexture::Init();
2036 InitStreaming();
2037 ResetTMUs();
2039 SDynTexture2::Init(eTP_Clouds);
2040 SDynTexture2::Init(eTP_Sprites);
2041 SDynTexture2::Init(eTP_VoxTerrain);
2042 SDynTexture2::Init(eTP_DynTexSources);
2044 if (!gRenDev->IsShaderCacheGenMode())
2045 LoadScaleformSystemTextures();
2048 void CTexture::PostInit()
2050 LOADING_TIME_PROFILE_SECTION;
2051 if (!gRenDev->IsShaderCacheGenMode())
2052 CTexture::LoadDefaultSystemTextures();
2055 int __cdecl TexCallback(const VOID* arg1, const VOID* arg2)
2057 CTexture** pi1 = (CTexture**)arg1;
2058 CTexture** pi2 = (CTexture**)arg2;
2059 CTexture* ti1 = *pi1;
2060 CTexture* ti2 = *pi2;
2062 if (ti1->GetDeviceDataSize() > ti2->GetDeviceDataSize())
2063 return -1;
2064 if (ti1->GetDeviceDataSize() < ti2->GetDeviceDataSize())
2065 return 1;
2066 return stricmp(ti1->GetSourceName(), ti2->GetSourceName());
2069 int __cdecl TexCallbackMips(const VOID* arg1, const VOID* arg2)
2071 CTexture** pi1 = (CTexture**)arg1;
2072 CTexture** pi2 = (CTexture**)arg2;
2073 CTexture* ti1 = *pi1;
2074 CTexture* ti2 = *pi2;
2076 int nSize1, nSize2;
2078 nSize1 = ti1->GetActualSize();
2079 nSize2 = ti2->GetActualSize();
2081 if (nSize1 > nSize2)
2082 return -1;
2083 if (nSize1 < nSize2)
2084 return 1;
2085 return stricmp(ti1->GetSourceName(), ti2->GetSourceName());
2088 void CTexture::Update()
2090 FUNCTION_PROFILER_RENDERER;
2092 CRenderer* rd = gRenDev;
2093 char buf[256] = "";
2095 // reload pending texture reload requests
2097 std::set<string> queue;
2099 s_xTexReloadLock.Lock();
2100 s_vTexReloadRequests.swap(queue);
2101 s_xTexReloadLock.Unlock();
2103 for (std::set<string>::iterator i = queue.begin(); i != queue.end(); ++i)
2104 ReloadFile(*i);
2107 CTexture::s_bStreamingFromHDD = gEnv->pSystem->GetStreamEngine()->IsStreamDataOnHDD();
2108 CTexture::s_nStatsStreamPoolInUseMem = CTexture::s_pPoolMgr->GetInUseSize();
2110 s_pTextureStreamer->ApplySchedule(ITextureStreamer::eASF_Full);
2111 s_pTextureStreamer->BeginUpdateSchedule();
2113 #ifdef ENABLE_TEXTURE_STREAM_LISTENER
2114 StreamUpdateStats();
2115 #endif
2117 SDynTexture::Tick();
2119 SResourceContainer* pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2120 ResourcesMapItor itor;
2122 if ((s_nStreamingMode != CRenderer::CV_r_texturesstreaming) || (s_nStreamingUpdateMode != CRenderer::CV_r_texturesstreamingUpdateType))
2124 InitStreaming();
2127 if (pRL)
2129 #ifndef CONSOLE_CONST_CVAR_MODE
2130 uint32 i;
2131 if (CRenderer::CV_r_texlog == 2 || CRenderer::CV_r_texlog == 3 || CRenderer::CV_r_texlog == 4)
2133 FILE* fp = NULL;
2134 TArray<CTexture*> Texs;
2135 int Size = 0;
2136 int PartSize = 0;
2137 if (CRenderer::CV_r_texlog == 2 || CRenderer::CV_r_texlog == 3)
2139 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++)
2141 CTexture* tp = (CTexture*)itor->second;
2142 if (CRenderer::CV_r_texlog == 3 && tp->IsNoTexture())
2144 Texs.AddElem(tp);
2146 else if (CRenderer::CV_r_texlog == 2 && !tp->IsNoTexture() && tp->m_pFileTexMips) // (tp->GetFlags() & FT_FROMIMAGE))
2148 Texs.AddElem(tp);
2151 if (CRenderer::CV_r_texlog == 3)
2153 CryLogAlways("Logging to MissingTextures.txt...");
2154 fp = fxopen("MissingTextures.txt", "w");
2156 else
2158 CryLogAlways("Logging to UsedTextures.txt...");
2159 fp = fxopen("UsedTextures.txt", "w");
2161 fprintf(fp, "*** All textures: ***\n");
2163 if (Texs.Num())
2164 qsort(&Texs[0], Texs.Num(), sizeof(CTexture*), TexCallbackMips);
2166 for (i = 0; i < Texs.Num(); i++)
2168 int w = Texs[i]->GetWidth();
2169 int h = Texs[i]->GetHeight();
2171 int nTSize = Texs[i]->m_pFileTexMips->GetSize(Texs[i]->GetNumMips(), Texs[i]->GetNumSides());
2173 fprintf(fp, "%d\t\t%d x %d\t\tType: %s\t\tMips: %d\t\tFormat: %s\t\t(%s)\n", nTSize, w, h, Texs[i]->NameForTextureType(Texs[i]->GetTextureType()), Texs[i]->GetNumMips(), Texs[i]->NameForTextureFormat(Texs[i]->GetDstFormat()), Texs[i]->GetName());
2174 //Size += Texs[i]->GetDataSize();
2175 Size += nTSize;
2177 PartSize += Texs[i]->GetDeviceDataSize();
2179 fprintf(fp, "*** Total Size: %d\n\n", Size /*, PartSize, PartSize */);
2181 Texs.Free();
2183 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++)
2185 CTexture* tp = (CTexture*)itor->second;
2186 if (tp->m_nAccessFrameID == rd->m_RP.m_TI[rd->m_RP.m_nProcessThreadID].m_nFrameUpdateID)
2188 Texs.AddElem(tp);
2192 if (fp)
2194 fclose(fp);
2195 fp = 0;
2198 fp = fxopen("UsedTextures_Frame.txt", "w");
2200 if (fp)
2201 fprintf(fp, "\n\n*** Textures used in current frame: ***\n");
2202 else
2203 IRenderAuxText::TextToScreenColor(4, 13, 1, 1, 0, 1, "*** Textures used in current frame: ***");
2204 int nY = 17;
2206 if (Texs.Num())
2207 qsort(&Texs[0], Texs.Num(), sizeof(CTexture*), TexCallback);
2209 Size = 0;
2210 for (i = 0; i < Texs.Num(); i++)
2212 if (fp)
2213 fprintf(fp, "%.3fKb\t\tType: %s\t\tFormat: %s\t\t(%s)\n", Texs[i]->GetDeviceDataSize() / 1024.0f, CTexture::NameForTextureType(Texs[i]->GetTextureType()), CTexture::NameForTextureFormat(Texs[i]->GetDstFormat()), Texs[i]->GetName());
2214 else
2216 cry_sprintf(buf, "%.3fKb Type: %s Format: %s (%s)", Texs[i]->GetDeviceDataSize() / 1024.0f, CTexture::NameForTextureType(Texs[i]->GetTextureType()), CTexture::NameForTextureFormat(Texs[i]->GetDstFormat()), Texs[i]->GetName());
2217 IRenderAuxText::TextToScreenColor(4, nY, 0, 1, 0, 1, buf);
2218 nY += 3;
2220 PartSize += Texs[i]->GetDeviceDataSize();
2221 Size += Texs[i]->GetDataSize();
2223 if (fp)
2225 fprintf(fp, "*** Total Size: %.3fMb, Device Size: %.3fMb\n\n", Size / (1024.0f * 1024.0f), PartSize / (1024.0f * 1024.0f));
2227 else
2229 cry_sprintf(buf, "*** Total Size: %.3fMb, Device Size: %.3fMb", Size / (1024.0f * 1024.0f), PartSize / (1024.0f * 1024.0f));
2230 IRenderAuxText::TextToScreenColor(4, nY + 1, 0, 1, 1, 1, buf);
2233 Texs.Free();
2234 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++)
2236 CTexture* tp = (CTexture*)itor->second;
2237 if (tp && !tp->IsNoTexture())
2239 Texs.AddElem(tp);
2243 if (fp)
2245 fclose(fp);
2246 fp = 0;
2248 fp = fxopen("UsedTextures_All.txt", "w");
2250 if (fp)
2251 fprintf(fp, "\n\n*** All Existing Textures: ***\n");
2252 else
2253 IRenderAuxText::TextToScreenColor(4, 13, 1, 1, 0, 1, "*** Textures loaded: ***");
2255 if (Texs.Num())
2256 qsort(&Texs[0], Texs.Num(), sizeof(CTexture*), TexCallback);
2258 Size = 0;
2259 for (i = 0; i < Texs.Num(); i++)
2261 if (fp)
2263 int w = Texs[i]->GetWidth();
2264 int h = Texs[i]->GetHeight();
2265 fprintf(fp, "%d\t\t%d x %d\t\t%d mips (%.3fKb)\t\tType: %s \t\tFormat: %s\t\t(%s)\n", Texs[i]->GetDataSize(), w, h, Texs[i]->GetNumMips(), Texs[i]->GetDeviceDataSize() / 1024.0f, CTexture::NameForTextureType(Texs[i]->GetTextureType()), CTexture::NameForTextureFormat(Texs[i]->GetDstFormat()), Texs[i]->GetName());
2267 else
2269 cry_sprintf(buf, "%.3fKb Type: %s Format: %s (%s)", Texs[i]->GetDataSize() / 1024.0f, CTexture::NameForTextureType(Texs[i]->GetTextureType()), CTexture::NameForTextureFormat(Texs[i]->GetDstFormat()), Texs[i]->GetName());
2270 IRenderAuxText::TextToScreenColor(4, nY, 0, 1, 0, 1, buf);
2271 nY += 3;
2273 Size += Texs[i]->GetDeviceDataSize();
2275 if (fp)
2277 fprintf(fp, "*** Total Size: %.3fMb\n\n", Size / (1024.0f * 1024.0f));
2279 else
2281 cry_sprintf(buf, "*** Total Size: %.3fMb", Size / (1024.0f * 1024.0f));
2282 IRenderAuxText::TextToScreenColor(4, nY + 1, 0, 1, 1, 1, buf);
2285 Texs.Free();
2286 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++)
2288 CTexture* tp = (CTexture*)itor->second;
2289 if (tp && !tp->IsNoTexture() && !tp->IsStreamed())
2291 Texs.AddElem(tp);
2295 if (fp)
2297 fclose(fp);
2298 fp = 0;
2301 if (CRenderer::CV_r_texlog != 4)
2302 CRenderer::CV_r_texlog = 0;
2304 else if (CRenderer::CV_r_texlog == 1)
2306 //char *str = GetTexturesStatusText();
2308 TArray<CTexture*> Texs;
2309 //TArray<CTexture *> TexsNM;
2310 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++)
2312 CTexture* tp = (CTexture*)itor->second;
2313 if (tp && !tp->IsNoTexture())
2315 Texs.AddElem(tp);
2316 //if (tp->GetFlags() & FT_TEX_NORMAL_MAP)
2317 // TexsNM.AddElem(tp);
2321 if (Texs.Num())
2322 qsort(&Texs[0], Texs.Num(), sizeof(CTexture*), TexCallback);
2324 int64 AllSize = 0;
2325 int64 Size = 0;
2326 int64 PartSize = 0;
2327 int64 NonStrSize = 0;
2328 int nNoStr = 0;
2329 int64 SizeNM = 0;
2330 int64 SizeDynCom = 0;
2331 int64 SizeDynAtl = 0;
2332 int64 PartSizeNM = 0;
2333 int nNumTex = 0;
2334 int nNumTexNM = 0;
2335 int nNumTexDynAtl = 0;
2336 int nNumTexDynCom = 0;
2337 for (i = 0; i < Texs.Num(); i++)
2339 CTexture* tex = Texs[i];
2340 const uint32 texFlags = tex->GetFlags();
2341 const int texDataSize = tex->GetDataSize();
2342 const int texDeviceDataSize = tex->GetDeviceDataSize();
2344 if (tex->GetDevTexture() && !(texFlags & (FT_USAGE_DYNAMIC | FT_USAGE_RENDERTARGET)))
2346 AllSize += texDataSize;
2347 if (!Texs[i]->IsStreamed())
2349 NonStrSize += texDataSize;
2350 nNoStr++;
2354 if (texFlags & (FT_USAGE_RENDERTARGET | FT_USAGE_DYNAMIC))
2356 if (texFlags & FT_USAGE_ATLAS)
2358 ++nNumTexDynAtl;
2359 SizeDynAtl += texDataSize;
2361 else
2363 ++nNumTexDynCom;
2364 SizeDynCom += texDataSize;
2367 else if (0 == (texFlags & FT_TEX_NORMAL_MAP))
2369 if (!Texs[i]->IsUnloaded())
2371 ++nNumTex;
2372 Size += texDataSize;
2373 PartSize += texDeviceDataSize;
2376 else
2378 if (!Texs[i]->IsUnloaded())
2380 ++nNumTexNM;
2381 SizeNM += texDataSize;
2382 PartSizeNM += texDeviceDataSize;
2387 cry_sprintf(buf, "All texture objects: %u (Size: %.3fMb), NonStreamed: %d (Size: %.3fMb)", Texs.Num(), AllSize / (1024.0 * 1024.0), nNoStr, NonStrSize / (1024.0 * 1024.0));
2388 IRenderAuxText::TextToScreenColor(4, 13, 1, 1, 0, 1, buf);
2389 cry_sprintf(buf, "All Loaded Texture Maps: %d (All MIPS: %.3fMb, Loaded MIPS: %.3fMb)", nNumTex, Size / (1024.0f * 1024.0f), PartSize / (1024.0 * 1024.0));
2390 IRenderAuxText::TextToScreenColor(4, 16, 1, 1, 0, 1, buf);
2391 cry_sprintf(buf, "All Loaded Normal Maps: %d (All MIPS: %.3fMb, Loaded MIPS: %.3fMb)", nNumTexNM, SizeNM / (1024.0 * 1024.0), PartSizeNM / (1024.0 * 1024.0));
2392 IRenderAuxText::TextToScreenColor(4, 19, 1, 1, 0, 1, buf);
2393 cry_sprintf(buf, "All Dynamic textures: %d (%.3fMb), %d Atlases (%.3fMb), %d Separared (%.3fMb)", nNumTexDynAtl + nNumTexDynCom, (SizeDynAtl + SizeDynCom) / (1024.0 * 1024.0), nNumTexDynAtl, SizeDynAtl / (1024.0 * 1024.0), nNumTexDynCom, SizeDynCom / (1024.0 * 1024.0));
2394 IRenderAuxText::TextToScreenColor(4, 22, 1, 1, 0, 1, buf);
2396 Texs.Free();
2397 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++)
2399 CTexture* tp = (CTexture*)itor->second;
2400 if (tp && !tp->IsNoTexture() && tp->m_nAccessFrameID == rd->m_RP.m_TI[rd->m_RP.m_nProcessThreadID].m_nFrameUpdateID)
2402 Texs.AddElem(tp);
2406 if (Texs.Num())
2407 qsort(&Texs[0], Texs.Num(), sizeof(CTexture*), TexCallback);
2409 Size = 0;
2410 SizeDynAtl = 0;
2411 SizeDynCom = 0;
2412 PartSize = 0;
2413 NonStrSize = 0;
2414 for (i = 0; i < Texs.Num(); i++)
2416 Size += Texs[i]->GetDataSize();
2417 if (Texs[i]->GetFlags() & (FT_USAGE_DYNAMIC | FT_USAGE_RENDERTARGET))
2419 if (Texs[i]->GetFlags() & FT_USAGE_ATLAS)
2420 SizeDynAtl += Texs[i]->GetDataSize();
2421 else
2422 SizeDynCom += Texs[i]->GetDataSize();
2424 else
2425 PartSize += Texs[i]->GetDeviceDataSize();
2426 if (!Texs[i]->IsStreamed())
2427 NonStrSize += Texs[i]->GetDataSize();
2429 cry_sprintf(buf, "Current tex. objects: %u (Size: %.3fMb, Dyn. Atlases: %.3f, Dyn. Separated: %.3f, Loaded: %.3f, NonStreamed: %.3f)", Texs.Num(), Size / (1024.0f * 1024.0f), SizeDynAtl / (1024.0f * 1024.0f), SizeDynCom / (1024.0f * 1024.0f), PartSize / (1024.0f * 1024.0f), NonStrSize / (1024.0f * 1024.0f));
2430 IRenderAuxText::TextToScreenColor(4, 27, 1, 0, 0, 1, buf);
2432 #endif
2436 void CTexture::RT_LoadingUpdate()
2438 CTexture::s_bStreamingFromHDD = gEnv->pSystem->GetStreamEngine()->IsStreamDataOnHDD();
2439 CTexture::s_nStatsStreamPoolInUseMem = CTexture::s_pPoolMgr->GetInUseSize();
2441 ITextureStreamer::EApplyScheduleFlags asf = CTexture::s_bPrecachePhase
2442 ? ITextureStreamer::eASF_InOut // Exclude the prep update, as it will be done by the RLT (and can be expensive)
2443 : ITextureStreamer::eASF_Full;
2445 s_pTextureStreamer->ApplySchedule(asf);
2448 void CTexture::RLT_LoadingUpdate()
2450 s_pTextureStreamer->BeginUpdateSchedule();
2453 //=========================================================================
2455 Ang3 sDeltAngles(Ang3& Ang0, Ang3& Ang1)
2457 Ang3 out;
2458 for (int i = 0; i < 3; i++)
2460 float a0 = Ang0[i];
2461 a0 = (float)((360.0 / 65536) * ((int)(a0 * (65536 / 360.0)) & 65535)); // angmod
2462 float a1 = Ang1[i];
2463 a1 = (float)((360.0 / 65536) * ((int)(a1 * (65536 / 360.0)) & 65535));
2464 out[i] = a0 - a1;
2466 return out;
2469 SEnvTexture* CTexture::FindSuitableEnvTex(Vec3& Pos, Ang3& Angs, bool bMustExist, int RendFlags, bool bUseExistingREs, CShader* pSH, CShaderResources* pRes, CRenderObject* pObj, bool bReflect, CRenderElement* pRE, bool* bMustUpdate)
2471 SEnvTexture* cm = NULL;
2472 float time0 = iTimer->GetAsyncCurTime();
2474 int i;
2475 float distO = 999999;
2476 float adist = 999999;
2477 int firstForUse = -1;
2478 int firstFree = -1;
2479 Vec3 objPos;
2480 if (bMustUpdate)
2481 *bMustUpdate = false;
2482 if (!pObj)
2483 bReflect = false;
2484 else
2486 if (bReflect)
2488 Plane pl;
2489 pRE->mfGetPlane(pl);
2490 objPos = pl.MirrorPosition(Vec3(0, 0, 0));
2492 else if (pRE)
2493 pRE->mfCenter(objPos, pObj);
2494 else
2495 objPos = pObj->GetTranslation();
2497 float dist = 999999;
2498 for (i = 0; i < MAX_ENVTEXTURES; i++)
2500 SEnvTexture* cur = &CTexture::s_EnvTexts[i];
2501 if (cur->m_bReflected != bReflect)
2502 continue;
2503 float s = (cur->m_CamPos - Pos).GetLengthSquared();
2504 Ang3 angDelta = sDeltAngles(Angs, cur->m_Angle);
2505 float a = angDelta.x * angDelta.x + angDelta.y * angDelta.y + angDelta.z * angDelta.z;
2506 float so = 0;
2507 if (bReflect)
2508 so = (cur->m_ObjPos - objPos).GetLengthSquared();
2509 if (s <= dist && a <= adist && so <= distO)
2511 dist = s;
2512 adist = a;
2513 distO = so;
2514 firstForUse = i;
2515 if (!so && !s && !a)
2516 break;
2518 if (cur->m_pTex && !cur->m_pTex->m_pTexture && firstFree < 0)
2519 firstFree = i;
2521 if (bMustExist && firstForUse >= 0)
2522 return &CTexture::s_EnvTexts[firstForUse];
2523 if (bReflect)
2524 dist = distO;
2526 float curTime = iTimer->GetCurrTime();
2527 int nUpdate = -2;
2528 float fTimeInterval = dist * CRenderer::CV_r_envtexupdateinterval + CRenderer::CV_r_envtexupdateinterval * 0.5f;
2529 float fDelta = curTime - CTexture::s_EnvTexts[firstForUse].m_TimeLastUpdated;
2530 if (bMustExist)
2531 nUpdate = -2;
2532 else if (dist > MAX_ENVTEXSCANDIST)
2534 if (firstFree >= 0)
2535 nUpdate = firstFree;
2536 else
2537 nUpdate = -1;
2539 else if (fDelta > fTimeInterval)
2540 nUpdate = firstForUse;
2541 if (nUpdate == -2)
2543 // No need to update (Up to date)
2544 return &CTexture::s_EnvTexts[firstForUse];
2546 if (!CTexture::s_EnvTexts[nUpdate].m_pTex)
2547 return NULL;
2548 if (nUpdate >= 0)
2550 if (!CTexture::s_EnvTexts[nUpdate].m_pTex->m_pTexture || gRenDev->m_RP.m_PS[gRenDev->m_RP.m_nProcessThreadID].m_fEnvTextUpdateTime < 0.1f)
2552 int n = nUpdate;
2553 CTexture::s_EnvTexts[n].m_TimeLastUpdated = curTime;
2554 CTexture::s_EnvTexts[n].m_CamPos = Pos;
2555 CTexture::s_EnvTexts[n].m_Angle = Angs;
2556 CTexture::s_EnvTexts[n].m_ObjPos = objPos;
2557 CTexture::s_EnvTexts[n].m_bReflected = bReflect;
2558 if (bMustUpdate)
2559 *bMustUpdate = true;
2561 gRenDev->m_RP.m_PS[gRenDev->m_RP.m_nProcessThreadID].m_fEnvTextUpdateTime += iTimer->GetAsyncCurTime() - time0;
2562 return &CTexture::s_EnvTexts[nUpdate];
2565 dist = 0;
2566 firstForUse = -1;
2567 for (i = 0; i < MAX_ENVTEXTURES; i++)
2569 SEnvTexture* cur = &CTexture::s_EnvTexts[i];
2570 if (dist < curTime - cur->m_TimeLastUpdated && !cur->m_bInprogress)
2572 dist = curTime - cur->m_TimeLastUpdated;
2573 firstForUse = i;
2576 if (firstForUse < 0)
2578 return NULL;
2580 int n = firstForUse;
2581 CTexture::s_EnvTexts[n].m_TimeLastUpdated = curTime;
2582 CTexture::s_EnvTexts[n].m_CamPos = Pos;
2583 CTexture::s_EnvTexts[n].m_ObjPos = objPos;
2584 CTexture::s_EnvTexts[n].m_Angle = Angs;
2585 CTexture::s_EnvTexts[n].m_bReflected = bReflect;
2586 if (bMustUpdate)
2587 *bMustUpdate = true;
2589 gRenDev->m_RP.m_PS[gRenDev->m_RP.m_nProcessThreadID].m_fEnvTextUpdateTime += iTimer->GetAsyncCurTime() - time0;
2590 return &CTexture::s_EnvTexts[n];
2594 //===========================================================================
2596 void CTexture::ShutDown()
2598 uint32 i;
2600 RT_FlushAllStreamingTasks(true);
2602 ReleaseSystemTextures(true);
2604 if (CRenderer::CV_r_releaseallresourcesonexit)
2606 SResourceContainer* pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2607 if (pRL)
2609 int n = 0;
2610 ResourcesMapItor itor;
2611 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); )
2613 CTexture* pTX = (CTexture*)itor->second;
2614 itor++;
2615 if (!pTX)
2616 continue;
2617 if (CRenderer::CV_r_printmemoryleaks)
2618 iLog->Log("Warning: CTexture::ShutDown: Texture %s was not deleted (%d)", pTX->GetName(), pTX->GetRefCounter());
2619 SAFE_RELEASE_FORCE(pTX);
2620 n++;
2623 // To avoid crash on ShutDown
2624 CTexture::s_ptexSceneNormalsMap = NULL;
2625 CTexture::s_ptexSceneDiffuse = NULL;
2626 CTexture::s_ptexSceneSpecular = NULL;
2627 CTexture::s_ptexSceneDiffuseAccMap = NULL;
2628 CTexture::s_ptexSceneSpecularAccMap = NULL;
2629 CTexture::s_ptexBackBuffer = NULL;
2630 CTexture::s_ptexPrevBackBuffer[0][0] = NULL;
2631 CTexture::s_ptexPrevBackBuffer[1][0] = NULL;
2632 CTexture::s_ptexPrevBackBuffer[0][1] = NULL;
2633 CTexture::s_ptexPrevBackBuffer[1][1] = NULL;
2634 CTexture::s_ptexSceneTarget = NULL;
2635 CTexture::s_ptexZTarget = NULL;
2636 CTexture::s_ptexHDRTarget = NULL;
2637 CTexture::s_ptexStereoL = NULL;
2638 CTexture::s_ptexStereoR = NULL;
2639 for (uint32 i = 0; i < 2; ++i)
2640 CTexture::s_ptexQuadLayers[i] = NULL;
2643 if (s_ShaderTemplatesInitialized)
2645 for (i = 0; i < EFTT_MAX; i++)
2647 s_ShaderTemplates[i].~CTexture();
2650 s_ShaderTemplates.Free();
2652 SAFE_DELETE(s_pTexNULL);
2654 s_pPoolMgr->Flush();
2657 bool CTexture::ReloadFile_Request(const char* szFileName)
2659 s_xTexReloadLock.Lock();
2660 s_vTexReloadRequests.insert(szFileName);
2661 s_xTexReloadLock.Unlock();
2663 return true;
2666 bool CTexture::ReloadFile(const char* szFileName)
2668 char realNameBuffer[256];
2669 fpConvertDOSToUnixName(realNameBuffer, szFileName);
2671 char gameFolderPath[256];
2672 cry_strcpy(gameFolderPath, PathUtil::GetGameFolder());
2673 PREFAST_SUPPRESS_WARNING(6054); // it is nullterminated
2674 int gameFolderPathLength = strlen(gameFolderPath);
2675 if (gameFolderPathLength > 0 && gameFolderPath[gameFolderPathLength - 1] == '\\')
2677 gameFolderPath[gameFolderPathLength - 1] = '/';
2679 else if (gameFolderPathLength > 0 && gameFolderPath[gameFolderPathLength - 1] != '/')
2681 gameFolderPath[gameFolderPathLength++] = '/';
2682 gameFolderPath[gameFolderPathLength] = 0;
2685 char* realName = realNameBuffer;
2686 if (strlen(realNameBuffer) >= (uint32)gameFolderPathLength && memcmp(realName, gameFolderPath, gameFolderPathLength) == 0)
2687 realName += gameFolderPathLength;
2689 bool bStatus = true;
2691 SResourceContainer* pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2692 if (pRL)
2694 AUTO_LOCK(CBaseResource::s_cResLock);
2696 ResourcesMapItor itor;
2697 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++)
2699 CTexture* tp = (CTexture*)itor->second;
2700 if (!tp)
2701 continue;
2703 if (!(tp->m_eFlags & FT_FROMIMAGE))
2704 continue;
2705 char srcNameBuffer[MAX_PATH + 1];
2706 fpConvertDOSToUnixName(srcNameBuffer, tp->m_SrcName.c_str());
2707 char* srcName = srcNameBuffer;
2708 if (strlen(srcName) >= (uint32)gameFolderPathLength && _strnicmp(srcName, gameFolderPath, gameFolderPathLength) == 0)
2709 srcName += gameFolderPathLength;
2710 //CryLogAlways("realName = %s srcName = %s gameFolderPath = %s szFileName = %s", realName, srcName, gameFolderPath, szFileName);
2711 if (!stricmp(realName, srcName))
2713 if (!tp->Reload())
2715 bStatus = false;
2721 return bStatus;
2724 void CTexture::ReloadTextures()
2726 LOADING_TIME_PROFILE_SECTION;
2728 // Flush any outstanding texture requests before reloading
2729 gEnv->pRenderer->FlushPendingTextureTasks();
2731 SResourceContainer* pRL = CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2732 if (pRL)
2734 ResourcesMapItor itor;
2735 int nID = 0;
2736 for (itor = pRL->m_RMap.begin(); itor != pRL->m_RMap.end(); itor++, nID++)
2738 CTexture* tp = (CTexture*)itor->second;
2739 if (!tp)
2740 continue;
2741 if (!(tp->m_eFlags & FT_FROMIMAGE))
2742 continue;
2743 tp->Reload();
2748 bool CTexture::SetNoTexture(CTexture* pDefaultTexture /* = s_ptexNoTexture*/)
2750 if (pDefaultTexture)
2752 m_pDevTexture = pDefaultTexture->m_pDevTexture;
2753 m_eSrcFormat = pDefaultTexture->GetSrcFormat();
2754 m_eDstFormat = pDefaultTexture->GetDstFormat();
2755 m_nMips = pDefaultTexture->GetNumMips();
2756 m_nWidth = pDefaultTexture->GetWidth();
2757 m_nHeight = pDefaultTexture->GetHeight();
2758 m_nDepth = 1;
2759 m_nDefState = pDefaultTexture->m_nDefState;
2760 m_fAvgBrightness = 1.0f;
2761 m_cMinColor = 0.0f;
2762 m_cMaxColor = 1.0f;
2763 m_cClearColor = ColorF(0.0f, 0.0f, 0.0f, 1.0f);
2765 #if CRY_PLATFORM_DURANGO && (CRY_RENDERER_DIRECT3D >= 110) && (CRY_RENDERER_DIRECT3D < 120)
2766 m_nDeviceAddressInvalidated = m_pDevTexture->GetBaseAddressInvalidated();
2767 #endif
2768 #if CRY_PLATFORM_DURANGO && DURANGO_USE_ESRAM
2769 m_nESRAMOffset = SKIP_ESRAM;
2770 #endif
2772 m_bNoTexture = true;
2773 if (m_pFileTexMips)
2775 Unlink();
2776 StreamState_ReleaseInfo(this, m_pFileTexMips);
2777 m_pFileTexMips = NULL;
2779 m_bStreamed = false;
2780 m_bPostponed = false;
2781 m_eFlags |= FT_FAILED;
2782 m_nDevTextureSize = 0;
2783 m_nPersistentSize = 0;
2784 return true;
2786 return false;
2789 //===========================================================================
2791 void CTexture::ReleaseSystemTextures(bool bFinalRelease)
2793 if (gRenDev->m_pTextureManager)
2794 gRenDev->m_pTextureManager->ReleaseDefaultTextures();
2796 if (s_pStatsTexWantedLists)
2798 for (int i = 0; i < 2; ++i)
2799 s_pStatsTexWantedLists[i].clear();
2802 // Keep these valid - if any textures failed to load and also leaked across the shutdown,
2803 // they'll be left with a dangling dev texture pointer otherwise.
2804 //SAFE_RELEASE_FORCE(s_ptexNoTexture);
2805 //SAFE_RELEASE_FORCE(s_ptexNoTextureCM);
2806 //SAFE_RELEASE_FORCE(s_ptexWhite);
2807 //SAFE_RELEASE_FORCE(s_ptexGray);
2808 //SAFE_RELEASE_FORCE(s_ptexBlack);
2809 //SAFE_RELEASE_FORCE(s_ptexBlackAlpha);
2810 //SAFE_RELEASE_FORCE(s_ptexBlackCM);
2811 //SAFE_RELEASE_FORCE(s_ptexFlatBump);
2812 #if !defined(_RELEASE)
2813 //SAFE_RELEASE_FORCE(s_ptexDefaultMergedDetail);
2814 //SAFE_RELEASE_FORCE(s_ptexMipMapDebug);
2815 //SAFE_RELEASE_FORCE(s_ptexColorBlue);
2816 //SAFE_RELEASE_FORCE(s_ptexColorCyan);
2817 //SAFE_RELEASE_FORCE(s_ptexColorGreen);
2818 //SAFE_RELEASE_FORCE(s_ptexColorPurple);
2819 //SAFE_RELEASE_FORCE(s_ptexColorRed);
2820 //SAFE_RELEASE_FORCE(s_ptexColorWhite);
2821 //SAFE_RELEASE_FORCE(s_ptexColorYellow);
2822 //SAFE_RELEASE_FORCE(s_ptexColorMagenta);
2823 //SAFE_RELEASE_FORCE(s_ptexColorOrange);
2824 #endif
2825 //SAFE_RELEASE_FORCE(s_ptexPaletteDebug);
2826 //SAFE_RELEASE_FORCE(s_ptexShadowJitterMap);
2827 //SAFE_RELEASE_FORCE(s_ptexEnvironmentBRDF);
2828 //SAFE_RELEASE_FORCE(s_ptexScreenNoiseMap);
2829 //SAFE_RELEASE_FORCE(s_ptexDissolveNoiseMap);
2830 //SAFE_RELEASE_FORCE(s_ptexNoise3D);
2831 //SAFE_RELEASE_FORCE(s_ptexGrainFilterMap);
2832 //SAFE_RELEASE_FORCE(s_ptexFilmGrainMap);
2833 //SAFE_RELEASE_FORCE(s_ptexVignettingMap);
2834 //SAFE_RELEASE_FORCE(s_ptexAOJitter);
2835 //SAFE_RELEASE_FORCE(s_ptexAOVOJitter);
2836 SAFE_RELEASE_FORCE(s_ptexRT_2D);
2837 SAFE_RELEASE_FORCE(s_ptexCloudsLM);
2838 //SAFE_RELEASE_FORCE(s_ptexRainOcclusion);
2839 //SAFE_RELEASE_FORCE(s_ptexRainSSOcclusion[0]);
2840 //SAFE_RELEASE_FORCE(s_ptexRainSSOcclusion[1]);
2842 //SAFE_RELEASE_FORCE(s_ptexHitAreaRT[0]);
2843 //SAFE_RELEASE_FORCE(s_ptexHitAreaRT[1]);
2845 SAFE_RELEASE_FORCE(s_ptexVolumetricFog);
2846 SAFE_RELEASE_FORCE(s_ptexVolumetricClipVolumeStencil);
2848 SAFE_RELEASE_FORCE(s_ptexVolCloudShadow);
2850 uint32 i;
2851 for (i = 0; i < 8; i++)
2853 //SAFE_RELEASE_FORCE(s_ptexFromRE[i]);
2855 for (i = 0; i < 8; i++)
2857 SAFE_RELEASE_FORCE(s_ptexShadowID[i]);
2860 for (i = 0; i < 2; i++)
2862 //SAFE_RELEASE_FORCE(s_ptexFromRE_FromContainer[i]);
2865 SAFE_RELEASE_FORCE(s_ptexFromObj);
2866 SAFE_RELEASE_FORCE(s_ptexSvoTree);
2867 SAFE_RELEASE_FORCE(s_ptexSvoTris);
2868 SAFE_RELEASE_FORCE(s_ptexSvoGlobalCM);
2869 SAFE_RELEASE_FORCE(s_ptexSvoRgbs);
2870 SAFE_RELEASE_FORCE(s_ptexSvoNorm);
2871 SAFE_RELEASE_FORCE(s_ptexSvoOpac);
2873 SAFE_RELEASE_FORCE(s_ptexColorChart);
2875 SAFE_RELEASE_FORCE(s_ptexWindGrid);
2877 for (i = 0; i < MAX_ENVTEXTURES; i++)
2879 s_EnvTexts[i].Release();
2881 //m_EnvTexTemp.Release();
2883 SAFE_RELEASE_FORCE(s_ptexMipColors_Diffuse);
2884 SAFE_RELEASE_FORCE(s_ptexMipColors_Bump);
2885 SAFE_RELEASE_FORCE(s_ptexSkyDomeMie);
2886 SAFE_RELEASE_FORCE(s_ptexSkyDomeRayleigh);
2887 SAFE_RELEASE_FORCE(s_ptexSkyDomeMoon);
2888 SAFE_RELEASE_FORCE(s_ptexRT_ShadowPool);
2889 SAFE_RELEASE_FORCE(s_ptexFarPlane);
2891 SAFE_RELEASE_FORCE(s_ptexSceneNormalsMapMS);
2892 SAFE_RELEASE_FORCE(s_ptexSceneDiffuseAccMapMS);
2893 SAFE_RELEASE_FORCE(s_ptexSceneSpecularAccMapMS);
2895 s_CustomRT_2D.Free();
2896 //s_ShaderTemplates.Free();
2898 s_pPoolMgr->Flush();
2900 // release targets pools
2901 //SDynTexture_Shadow::ShutDown();
2902 SDynTexture::ShutDown();
2903 SDynTexture2::ShutDown();
2905 //ReleaseSystemTargets();
2907 m_bLoadedSystem = false;
2910 void CTexture::LoadScaleformSystemTextures()
2912 LOADING_TIME_PROFILE_SECTION;
2915 void CTexture::LoadDefaultSystemTextures()
2917 LOADING_TIME_PROFILE_SECTION;
2919 char str[256];
2920 int i;
2922 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Engine textures");
2924 if (!m_bLoadedSystem)
2926 m_bLoadedSystem = true;
2928 // Textures loaded directly from file
2929 struct
2931 CTexture*& pTexture;
2932 const char* szFileName;
2933 uint32 flags;
2935 texturesFromFile[] =
2937 { s_ptexWhite, "%ENGINE%/EngineAssets/Textures/White.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2938 { s_ptexBlack, "%ENGINE%/EngineAssets/Textures/Black.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2939 { s_ptexBlackAlpha, "%ENGINE%/EngineAssets/Textures/BlackAlpha.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2940 { s_ptexBlackCM, "%ENGINE%/EngineAssets/Textures/BlackCM.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2941 { s_ptexGray, "%ENGINE%/EngineAssets/Textures/Grey.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2942 { s_ptexDefaultMergedDetail, "%ENGINE%/EngineAssets/Textures/GreyAlpha.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2943 { s_ptexDefaultProbeCM, "%ENGINE%/EngineAssets/Shading/defaultProbe_cm.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2944 { s_ptexFlatBump, "%ENGINE%/EngineAssets/Textures/White_ddn.dds", FT_DONT_RELEASE | FT_DONT_STREAM | FT_TEX_NORMAL_MAP },
2945 { s_ptexPaletteDebug, "%ENGINE%/EngineAssets/Textures/palletteInst.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2946 { s_ptexPaletteTexelsPerMeter, "%ENGINE%/EngineAssets/Textures/TexelsPerMeterGrad.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2947 { s_ptexIconShaderCompiling, "%ENGINE%/EngineAssets/Icons/ShaderCompiling.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2948 { s_ptexIconStreaming, "%ENGINE%/EngineAssets/Icons/Streaming.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2949 { s_ptexIconStreamingTerrainTexture, "%ENGINE%/EngineAssets/Icons/StreamingTerrain.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2950 { s_ptexIconNavigationProcessing, "%ENGINE%/EngineAssets/Icons/NavigationProcessing.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2951 { s_ptexShadowJitterMap, "%ENGINE%/EngineAssets/Textures/rotrandom.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2952 { s_ptexEnvironmentBRDF, "%ENGINE%/EngineAssets/Shading/environmentBRDF.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2953 { s_ptexScreenNoiseMap, "%ENGINE%/EngineAssets/Textures/JumpNoiseHighFrequency_x27y19.dds", FT_DONT_RELEASE | FT_DONT_STREAM | FT_NOMIPS },
2954 { s_ptexDissolveNoiseMap, "%ENGINE%/EngineAssets/Textures/noise.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2955 { s_ptexNoise3D, "%ENGINE%/EngineAssets/Textures/noise3d.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2956 { s_ptexGrainFilterMap, "%ENGINE%/EngineAssets/ScreenSpace/grain_bayer_mul.tif", FT_DONT_RELEASE | FT_DONT_STREAM | FT_NOMIPS },
2957 { s_ptexFilmGrainMap, "%ENGINE%/EngineAssets/ScreenSpace/film_grain.dds", FT_DONT_RELEASE | FT_DONT_STREAM | FT_NOMIPS },
2958 { s_ptexVignettingMap, "%ENGINE%/EngineAssets/Shading/vignetting.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2959 { s_ptexAOJitter, "%ENGINE%/EngineAssets/ScreenSpace/PointsOnSphere4x4.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2960 { s_ptexAOVOJitter, "%ENGINE%/EngineAssets/ScreenSpace/PointsOnSphereVO4x4.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2961 { s_ptexNormalsFitting, "%ENGINE%/EngineAssets/ScreenSpace/NormalsFitting.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2962 { s_ptexPerlinNoiseMap, "%ENGINE%/EngineAssets/Textures/perlinNoise2D.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2964 #if !defined(_RELEASE)
2965 { s_ptexNoTexture, "%ENGINE%/EngineAssets/TextureMsg/ReplaceMe.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2966 { s_ptexNoTextureCM, "%ENGINE%/EngineAssets/TextureMsg/ReplaceMeCM.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2967 { s_ptexMipMapDebug, "%ENGINE%/EngineAssets/TextureMsg/MipMapDebug.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2968 { s_ptexColorBlue, "%ENGINE%/EngineAssets/TextureMsg/color_Blue.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2969 { s_ptexColorCyan, "%ENGINE%/EngineAssets/TextureMsg/color_Cyan.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2970 { s_ptexColorGreen, "%ENGINE%/EngineAssets/TextureMsg/color_Green.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2971 { s_ptexColorPurple, "%ENGINE%/EngineAssets/TextureMsg/color_Purple.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2972 { s_ptexColorRed, "%ENGINE%/EngineAssets/TextureMsg/color_Red.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2973 { s_ptexColorWhite, "%ENGINE%/EngineAssets/TextureMsg/color_White.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2974 { s_ptexColorYellow, "%ENGINE%/EngineAssets/TextureMsg/color_Yellow.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2975 { s_ptexColorOrange, "%ENGINE%/EngineAssets/TextureMsg/color_Orange.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2976 { s_ptexColorMagenta, "%ENGINE%/EngineAssets/TextureMsg/color_Magenta.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2977 #else
2978 { s_ptexNoTexture, "%ENGINE%/EngineAssets/Textures/Grey.dds", FT_DONT_RELEASE | FT_DONT_STREAM },
2979 { s_ptexNoTextureCM, "%ENGINE%/EngineAssets/Shading/defaultProbe_cm.tif", FT_DONT_RELEASE | FT_DONT_STREAM },
2980 #endif
2983 for (int t = 0; t < CRY_ARRAY_COUNT(texturesFromFile); ++t)
2985 if (!texturesFromFile[t].pTexture)
2986 texturesFromFile[t].pTexture = CTexture::ForName(texturesFromFile[t].szFileName, texturesFromFile[t].flags, eTF_Unknown);
2988 if (!texturesFromFile[t].pTexture || !texturesFromFile[t].pTexture->IsLoaded() || !texturesFromFile[t].pTexture->GetDevTexture())
2989 CryFatalError("Can't open %s texture file.", texturesFromFile[t].szFileName);
2992 // Associate dummy NULL-resource with s_pTexNULL
2993 s_pTexNULL = new CTexture(FT_DONT_RELEASE | FT_DONT_STREAM, Clr_Transparent, CDeviceTexture::Associate(s_ptexBlackAlpha->GetLayout(), nullptr));
2995 // Default Template textures
2996 int nRTFlags = FT_DONT_RELEASE | FT_DONT_STREAM | FT_STATE_CLAMP | FT_USAGE_RENDERTARGET;
2997 s_ptexMipColors_Diffuse = CTexture::GetOrCreateTextureObject("$MipColors_Diffuse", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_MIPCOLORS_DIFFUSE);
2998 s_ptexMipColors_Bump = CTexture::GetOrCreateTextureObject("$MipColors_Bump", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_MIPCOLORS_BUMP);
3000 s_ptexRT_2D = CTexture::GetOrCreateTextureObject("$RT_2D", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_RT_2D);
3002 s_ptexRainOcclusion = CTexture::GetOrCreateTextureObject("$RainOcclusion", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3003 s_ptexRainSSOcclusion[0] = CTexture::GetOrCreateTextureObject("$RainSSOcclusion0", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3004 s_ptexRainSSOcclusion[1] = CTexture::GetOrCreateTextureObject("$RainSSOcclusion1", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3006 //s_ptexHitAreaRT[0] = CTexture::CreateTextureObject("$HitEffectAccumBuffRT_0", 128, 128, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3007 //s_ptexHitAreaRT[1] = CTexture::CreateTextureObject("$HitEffectAccumBuffRT_1", 128, 128, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3009 s_ptexFromObj = CTexture::GetOrCreateTextureObject("FromObj", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_FROMOBJ);
3010 s_ptexSvoTree = CTexture::GetOrCreateTextureObject("SvoTree", 0, 0, 1, eTT_3D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SVOTREE);
3011 s_ptexSvoTris = CTexture::GetOrCreateTextureObject("SvoTris", 0, 0, 1, eTT_3D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SVOTRIS);
3012 s_ptexSvoGlobalCM = CTexture::GetOrCreateTextureObject("SvoGlobalCM", 0, 0, 1, eTT_Cube, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SVOGLCM);
3013 s_ptexSvoRgbs = CTexture::GetOrCreateTextureObject("SvoRgbs", 0, 0, 1, eTT_3D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SVORGBS);
3014 s_ptexSvoNorm = CTexture::GetOrCreateTextureObject("SvoNorm", 0, 0, 1, eTT_3D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SVONORM);
3015 s_ptexSvoOpac = CTexture::GetOrCreateTextureObject("SvoOpac", 0, 0, 1, eTT_3D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SVOOPAC);
3017 s_ptexWindGrid = CTexture::GetOrCreateTextureObject("WindGrid", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_STAGE_UPLOAD, eTF_Unknown, TO_WINDGRID);
3018 if (!CTexture::IsTextureExist(CTexture::s_ptexWindGrid))
3020 CTexture::s_ptexWindGrid->Create2DTexture(256, 256, 1, FT_DONT_RELEASE | FT_DONT_STREAM | FT_STAGE_UPLOAD, nullptr, eTF_R16G16F);
3023 s_ptexZTargetReadBack[0] = CTexture::GetOrCreateTextureObject("$ZTargetReadBack0", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM, eTF_Unknown);
3024 s_ptexZTargetReadBack[1] = CTexture::GetOrCreateTextureObject("$ZTargetReadBack1", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM, eTF_Unknown);
3025 s_ptexZTargetReadBack[2] = CTexture::GetOrCreateTextureObject("$ZTargetReadBack2", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM, eTF_Unknown);
3026 s_ptexZTargetReadBack[3] = CTexture::GetOrCreateTextureObject("$ZTargetReadBack3", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM, eTF_Unknown);
3028 s_ptexZTargetDownSample[0] = CTexture::GetOrCreateTextureObject("$ZTargetDownSample0", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM, eTF_Unknown);
3029 s_ptexZTargetDownSample[1] = CTexture::GetOrCreateTextureObject("$ZTargetDownSample1", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM, eTF_Unknown);
3030 s_ptexZTargetDownSample[2] = CTexture::GetOrCreateTextureObject("$ZTargetDownSample2", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM, eTF_Unknown);
3031 s_ptexZTargetDownSample[3] = CTexture::GetOrCreateTextureObject("$ZTargetDownSample3", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM, eTF_Unknown);
3033 s_ptexSceneNormalsMapMS = CTexture::GetOrCreateTextureObject("$SceneNormalsMapMS", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SCENE_NORMALMAP_MS);
3034 s_ptexSceneDiffuseAccMapMS = CTexture::GetOrCreateTextureObject("$SceneDiffuseAccMS", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SCENE_DIFFUSE_ACC_MS);
3035 s_ptexSceneSpecularAccMapMS = CTexture::GetOrCreateTextureObject("$SceneSpecularAccMS", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SCENE_SPECULAR_ACC_MS);
3037 s_ptexRT_ShadowPool = CTexture::GetOrCreateTextureObject("$RT_ShadowPool", 0, 0, 1, eTT_2D, FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL, eTF_Unknown);
3038 s_ptexFarPlane = CTexture::GetOrCreateTextureObject("$FarPlane", 8, 8, 1, eTT_2D, FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL, eTF_Unknown);
3040 #if CRY_PLATFORM_WINDOWS || CRY_PLATFORM_APPLE || CRY_PLATFORM_LINUX
3041 s_ptexDepthBufferQuarter = CTexture::GetOrCreateTextureObject("$DepthBufferQuarter", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL, eTF_Unknown);
3042 #else
3043 s_ptexDepthBufferQuarter = NULL;
3044 #endif
3045 s_ptexDepthBufferHalfQuarter = CTexture::GetOrCreateTextureObject("$DepthBufferHalfQuarter", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL, eTF_Unknown);
3047 if (!s_ptexModelHudBuffer)
3048 s_ptexModelHudBuffer = CTexture::GetOrCreateTextureObject("$ModelHud", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_MODELHUD);
3050 if (!s_ptexBackBuffer)
3052 s_ptexSceneTarget = CTexture::GetOrCreateTextureObject("$SceneTarget", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SCENE_TARGET);
3053 s_ptexCurrSceneTarget = s_ptexSceneTarget;
3055 s_ptexSceneTargetR11G11B10F[0] = CTexture::GetOrCreateTextureObject("$SceneTargetR11G11B10F_0", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3056 s_ptexSceneTargetR11G11B10F[1] = CTexture::GetOrCreateTextureObject("$SceneTargetR11G11B10F_1", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3057 s_ptexSceneTargetScaledR11G11B10F[0] = CTexture::GetOrCreateTextureObject("$SceneTargetScaled0R11G11B10F", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3058 s_ptexSceneTargetScaledR11G11B10F[1] = CTexture::GetOrCreateTextureObject("$SceneTargetScaled1R11G11B10F", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3059 s_ptexSceneTargetScaledR11G11B10F[2] = CTexture::GetOrCreateTextureObject("$SceneTargetScaled2R11G11B10F", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3060 s_ptexSceneTargetScaledR11G11B10F[3] = CTexture::GetOrCreateTextureObject("$SceneTargetScaled3R11G11B10F", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3062 s_ptexVelocity = CTexture::GetOrCreateTextureObject("$Velocity", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3063 s_ptexVelocityTiles[0] = CTexture::GetOrCreateTextureObject("$VelocityTilesTmp0", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3064 s_ptexVelocityTiles[1] = CTexture::GetOrCreateTextureObject("$VelocityTilesTmp1", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3065 s_ptexVelocityTiles[2] = CTexture::GetOrCreateTextureObject("$VelocityTiles", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3066 s_ptexVelocityObjects[0] = CTexture::GetOrCreateTextureObject("$VelocityObjects", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3067 // Only used for VR, but we need to support runtime switching
3068 s_ptexVelocityObjects[1] = CTexture::GetOrCreateTextureObject("$VelocityObjects_R", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3070 s_ptexBackBuffer = CTexture::GetOrCreateTextureObject("$BackBuffer", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_BACKBUFFERMAP);
3072 s_ptexPrevFrameScaled = CTexture::GetOrCreateTextureObject("$PrevFrameScale", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3074 s_ptexBackBufferScaled[0] = CTexture::GetOrCreateTextureObject("$BackBufferScaled_d2", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_BACKBUFFERSCALED_D2);
3075 s_ptexBackBufferScaled[1] = CTexture::GetOrCreateTextureObject("$BackBufferScaled_d4", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_BACKBUFFERSCALED_D4);
3076 s_ptexBackBufferScaled[2] = CTexture::GetOrCreateTextureObject("$BackBufferScaled_d8", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_BACKBUFFERSCALED_D8);
3078 s_ptexBackBufferScaledTemp[0] = CTexture::GetOrCreateTextureObject("$BackBufferScaledTemp_d2", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3079 s_ptexBackBufferScaledTemp[1] = CTexture::GetOrCreateTextureObject("$BackBufferScaledTemp_d4", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, -1);
3081 s_ptexSceneNormalsMap = CTexture::GetOrCreateTextureObject("$SceneNormalsMap", 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8, TO_SCENE_NORMALMAP);
3082 s_ptexSceneNormalsBent = CTexture::GetOrCreateTextureObject("$SceneNormalsBent", 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8);
3083 s_ptexSceneDiffuse = CTexture::GetOrCreateTextureObject("$SceneDiffuse", 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8);
3084 s_ptexSceneSpecular = CTexture::GetOrCreateTextureObject("$SceneSpecular", 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8);
3085 #if defined(DURANGO_USE_ESRAM)
3086 s_ptexSceneSpecularESRAM = CTexture::GetOrCreateTextureObject("$SceneSpecularESRAM", 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8);
3087 #endif
3088 s_ptexSceneDiffuseAccMap = CTexture::GetOrCreateTextureObject("$SceneDiffuseAcc", 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8, TO_SCENE_DIFFUSE_ACC);
3089 s_ptexSceneSpecularAccMap = CTexture::GetOrCreateTextureObject("$SceneSpecularAcc", 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8, TO_SCENE_SPECULAR_ACC);
3090 s_ptexShadowMask = CTexture::GetOrCreateTextureObject("$ShadowMask", 0, 0, 1, eTT_2DArray, nRTFlags, eTF_R8, TO_SHADOWMASK);
3092 s_ptexFlaresGather = CTexture::GetOrCreateTextureObject("$FlaresGather", 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8);
3093 for (i = 0; i < MAX_OCCLUSION_READBACK_TEXTURES; i++)
3095 cry_sprintf(str, "$FlaresOcclusion_%d", i);
3096 s_ptexFlaresOcclusionRing[i] = CTexture::GetOrCreateTextureObject(str, 0, 0, 1, eTT_2D, nRTFlags, eTF_R8G8B8A8);
3099 // fixme: get texture resolution from CREWaterOcean
3100 // TODO: make s_ptexWaterVolumeTemp an array texture
3101 s_ptexWaterOcean = CTexture::GetOrCreateTextureObject("$WaterOceanMap", 64, 64, 1, eTT_2D, FT_DONT_RELEASE | FT_NOMIPS | FT_STAGE_UPLOAD | FT_DONT_STREAM, eTF_Unknown, TO_WATEROCEANMAP);
3102 s_ptexWaterVolumeTemp[0] = CTexture::GetOrCreateTextureObject("$WaterVolumeTemp_0", 64, 64, 1, eTT_2D, /*FT_DONT_RELEASE |*/ FT_NOMIPS | FT_STAGE_UPLOAD | FT_DONT_STREAM, eTF_Unknown);
3103 s_ptexWaterVolumeTemp[1] = CTexture::GetOrCreateTextureObject("$WaterVolumeTemp_1", 64, 64, 1, eTT_2D, /*FT_DONT_RELEASE |*/ FT_NOMIPS | FT_STAGE_UPLOAD | FT_DONT_STREAM, eTF_Unknown);
3104 s_ptexWaterVolumeDDN = CTexture::GetOrCreateTextureObject("$WaterVolumeDDN", 64, 64, 1, eTT_2D, /*FT_DONT_RELEASE |*/ FT_DONT_STREAM | FT_USAGE_RENDERTARGET | FT_FORCE_MIPS, eTF_Unknown, TO_WATERVOLUMEMAP);
3105 s_ptexWaterVolumeRefl[0] = CTexture::GetOrCreateTextureObject("$WaterVolumeRefl", 64, 64, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET | FT_FORCE_MIPS, eTF_Unknown, TO_WATERVOLUMEREFLMAP);
3106 s_ptexWaterVolumeRefl[1] = CTexture::GetOrCreateTextureObject("$WaterVolumeReflPrev", 64, 64, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET | FT_FORCE_MIPS, eTF_Unknown, TO_WATERVOLUMEREFLMAPPREV);
3107 s_ptexWaterCaustics[0] = CTexture::GetOrCreateTextureObject("$WaterVolumeCaustics", 512, 512, 1, eTT_2D, /*FT_DONT_RELEASE |*/ FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_WATERVOLUMECAUSTICSMAP);
3108 s_ptexWaterCaustics[1] = CTexture::GetOrCreateTextureObject("$WaterVolumeCausticsTemp", 512, 512, 1, eTT_2D, /*FT_DONT_RELEASE |*/ FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_WATERVOLUMECAUSTICSMAPTEMP);
3110 s_ptexRainDropsRT[0] = CTexture::GetOrCreateTextureObject("$RainDropsAccumRT_0", 512, 512, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3111 s_ptexRainDropsRT[1] = CTexture::GetOrCreateTextureObject("$RainDropsAccumRT_1", 512, 512, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3113 if (!s_ptexZTarget)
3115 //for d3d10 we cannot free it during level transition, therefore allocate once and keep it
3116 s_ptexZTarget = CTexture::GetOrCreateTextureObject("$ZTarget", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3119 s_ptexZTargetScaled = CTexture::GetOrCreateTextureObject("$ZTargetScaled", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_DOWNSCALED_ZTARGET_FOR_AO);
3120 s_ptexZTargetScaled2 = CTexture::GetOrCreateTextureObject("$ZTargetScaled2", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_QUARTER_ZTARGET_FOR_AO);
3121 s_ptexZTargetScaled3 = CTexture::GetOrCreateTextureObject("$ZTargetScaled3", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown);
3124 s_ptexSceneSelectionIDs = CTexture::GetOrCreateTextureObject("$SceneSelectionIDs", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_R32F);
3125 s_ptexSceneHalfDepthStencil = CTexture::GetOrCreateTextureObject("$SceneHalfDepthStencil", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL, eTF_D32F);
3127 s_ptexHDRTarget = CTexture::GetOrCreateTextureObject("$HDRTarget", 0, 0, 1, eTT_2D, nRTFlags, eTF_Unknown);
3129 // Create dummy texture object for terrain and clouds lightmap
3130 s_ptexCloudsLM = CTexture::GetOrCreateTextureObject("$CloudsLM", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_CLOUDS_LM);
3132 for (i = 0; i < 8; i++)
3134 cry_sprintf(str, "$FromRE_%d", i);
3135 if (!s_ptexFromRE[i])
3136 s_ptexFromRE[i] = CTexture::GetOrCreateTextureObject(str, 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_FROMRE0 + i);
3139 for (i = 0; i < 8; i++)
3141 cry_sprintf(str, "$ShadowID_%d", i);
3142 s_ptexShadowID[i] = CTexture::GetOrCreateTextureObject(str, 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SHADOWID0 + i);
3145 for (i = 0; i < 2; i++)
3147 cry_sprintf(str, "$FromRE%d_FromContainer", i);
3148 if (!s_ptexFromRE_FromContainer[i])
3149 s_ptexFromRE_FromContainer[i] = CTexture::GetOrCreateTextureObject(str, 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_FROMRE0_FROM_CONTAINER + i);
3152 s_ptexColorChart = CTexture::GetOrCreateTextureObject("$ColorChart", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_COLORCHART);
3154 s_ptexSkyDomeMie = CTexture::GetOrCreateTextureObject("$SkyDomeMie", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SKYDOME_MIE);
3155 s_ptexSkyDomeRayleigh = CTexture::GetOrCreateTextureObject("$SkyDomeRayleigh", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SKYDOME_RAYLEIGH);
3156 s_ptexSkyDomeMoon = CTexture::GetOrCreateTextureObject("$SkyDomeMoon", 0, 0, 1, eTT_2D, FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_RENDERTARGET, eTF_Unknown, TO_SKYDOME_MOON);
3158 for (i = 0; i < EFTT_MAX; i++)
3160 new(&s_ShaderTemplates[i])CTexture(FT_DONT_RELEASE);
3161 s_ShaderTemplates[i].SetCustomID(EFTT_DIFFUSE + i);
3162 s_ShaderTemplates[i].SetFlags(FT_DONT_RELEASE);
3164 s_ShaderTemplatesInitialized = true;
3166 s_ptexVolumetricFog = CTexture::GetOrCreateTextureObject("$VolFogInscattering", 0, 0, 0, eTT_3D, FT_NOMIPS | FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_UNORDERED_ACCESS, eTF_Unknown);
3167 s_ptexVolumetricClipVolumeStencil = CTexture::GetOrCreateTextureObject("$ClipVolumeStencilVolume", 0, 0, 0, eTT_2D, FT_NOMIPS | FT_DONT_RELEASE | FT_DONT_STREAM | FT_USAGE_DEPTHSTENCIL | FT_USAGE_RENDERTARGET, eTF_Unknown);
3169 s_ptexVolCloudShadow = CTexture::GetOrCreateTextureObject("$VolCloudShadows", 0, 0, 0, eTT_3D, FT_NOMIPS | FT_USAGE_UNORDERED_ACCESS, eTF_Unknown);
3171 #if defined(DURANGO_USE_ESRAM)
3172 // Assign ESRAM offsets
3173 if (CRenderer::CV_r_useESRAM)
3175 // Precomputed offsets, using xg library and aligned to 4k
3176 // 1600x900 RGBA16F: 11894784
3177 // 1600x900 RGBA8: 5955584
3179 if (gRenDev->GetWidth() <= 1600 && gRenDev->GetHeight() <= 900)
3181 s_ptexHDRTarget->SetESRAMOffset(0);
3182 s_ptexSceneSpecularESRAM->SetESRAMOffset(0);
3183 s_ptexSceneNormalsMap->SetESRAMOffset(11894784 + 5955584 * 0);
3184 s_ptexSceneDiffuse->SetESRAMOffset(11894784 + 5955584 * 1);
3185 // Depth target uses: 11894784 + 5955584 * 2
3187 else
3189 iLog->LogError("Disabling ESRAM since resolution is larger than 1600x900");
3190 assert(0);
3193 #endif
3195 if (gRenDev->m_pTextureManager)
3196 gRenDev->m_pTextureManager->PreloadDefaultTextures();
3201 //////////////////////////////////////////////////////////////////////////
3202 const char* CTexture::GetFormatName() const
3204 return NameForTextureFormat(GetDstFormat());
3207 //////////////////////////////////////////////////////////////////////////
3208 const char* CTexture::GetTypeName() const
3210 return NameForTextureType(GetTextureType());
3213 //////////////////////////////////////////////////////////////////////////
3214 CDynTextureSource::CDynTextureSource()
3215 : m_refCount(1)
3216 , m_width(0)
3217 , m_height(0)
3218 , m_lastUpdateTime(0)
3219 , m_lastUpdateFrameID(0)
3220 , m_pDynTexture(0)
3224 CDynTextureSource::~CDynTextureSource()
3226 SAFE_DELETE(m_pDynTexture);
3229 void CDynTextureSource::AddRef()
3231 CryInterlockedIncrement(&m_refCount);
3234 void CDynTextureSource::Release()
3236 long refCnt = CryInterlockedDecrement(&m_refCount);
3237 if (refCnt <= 0)
3238 delete this;
3241 void CDynTextureSource::CalcSize(uint32& width, uint32& height, float distToCamera) const
3243 uint32 size;
3244 uint32 logSize;
3245 switch (CRenderer::CV_r_envtexresolution)
3247 case 0:
3248 case 1:
3249 size = 256;
3250 logSize = 8;
3251 break;
3252 case 2:
3253 case 3:
3254 default:
3255 size = 512;
3256 logSize = 9;
3257 break;
3260 if (distToCamera > 0)
3262 int x(0), y(0), vpwidth(1), vpheight(1);
3263 gRenDev->GetViewport(&x, &y, &vpwidth, &vpheight);
3264 float lod = logf(max(distToCamera * 1024.0f / (float) max(vpwidth, vpheight), 1.0f));
3265 uint32 lodFixed = fastround_positive(lod);
3266 size = 1 << max(logSize - lodFixed, 5u);
3269 width = size;
3270 height = size;
3273 bool CDynTextureSource::Apply(int nTUnit, SamplerStateHandle nTS)
3275 assert(m_pDynTexture);
3276 if (!m_pDynTexture || !m_pDynTexture->IsValid())
3277 return false;
3279 m_pDynTexture->Apply(nTUnit, nTS);
3280 return true;
3283 void CDynTextureSource::GetTexGenInfo(float& offsX, float& offsY, float& scaleX, float& scaleY) const
3285 assert(m_pDynTexture);
3286 if (!m_pDynTexture || !m_pDynTexture->IsValid())
3288 offsX = 0;
3289 offsY = 0;
3290 scaleX = 1;
3291 scaleY = 1;
3292 return;
3295 ITexture* pSrcTex(m_pDynTexture->GetTexture());
3296 float invSrcWidth(1.0f / (float) pSrcTex->GetWidth());
3297 float invSrcHeight(1.0f / (float) pSrcTex->GetHeight());
3298 offsX = m_pDynTexture->m_nX * invSrcWidth;
3299 offsY = m_pDynTexture->m_nY * invSrcHeight;
3300 assert(m_width <= m_pDynTexture->m_nWidth && m_height <= m_pDynTexture->m_nHeight);
3301 scaleX = m_width * invSrcWidth;
3302 scaleY = m_height * invSrcHeight;
3305 void CDynTextureSource::InitDynTexture(ETexPool eTexPool)
3307 CalcSize(m_width, m_height);
3308 m_pDynTexture = new SDynTexture2(m_width, m_height, FT_USAGE_RENDERTARGET | FT_STATE_CLAMP | FT_NOMIPS, "DynTextureSource", eTexPool);
3311 struct FlashTextureSourceSharedRT_AutoUpdate
3313 public:
3314 static void Add(CFlashTextureSourceBase* pSrc)
3316 CryAutoCriticalSection lock(ms_lock);
3317 stl::push_back_unique(ms_sources, pSrc);
3320 static void AddToLightList(CFlashTextureSourceBase* pSrc)
3322 if (stl::find(ms_LightTextures, pSrc)) return;
3323 ms_LightTextures.push_back(pSrc);
3326 static void Remove(CFlashTextureSourceBase* pSrc)
3328 CryAutoCriticalSection lock(ms_lock);
3330 const size_t size = ms_sources.size();
3331 for (size_t i = 0; i < size; ++i)
3333 if (ms_sources[i] == pSrc)
3335 ms_sources[i] = ms_sources[size - 1];
3336 ms_sources.pop_back();
3337 if (ms_sources.empty())
3339 stl::reconstruct(ms_sources);
3341 break;
3344 stl::find_and_erase(ms_LightTextures, pSrc);
3347 static void Tick()
3349 SRenderThread* pRT = gRenDev->m_pRT;
3350 if (!pRT || (pRT->IsMainThread() && pRT->m_eVideoThreadMode == SRenderThread::eVTM_Disabled))
3352 CTimeValue curTime = gEnv->pTimer->GetAsyncTime();
3353 const int frameID = gRenDev->GetFrameID(false);
3354 if (ms_lastTickFrameID != frameID)
3356 CryAutoCriticalSection lock(ms_lock);
3358 const float deltaTime = gEnv->pTimer->GetFrameTime();
3359 const bool isEditing = gEnv->IsEditing();
3360 const bool isPaused = gEnv->pSystem->IsPaused();
3362 const size_t size = ms_sources.size();
3363 for (size_t i = 0; i < size; ++i)
3365 ms_sources[i]->AutoUpdate(curTime, deltaTime, isEditing, isPaused);
3368 ms_lastTickFrameID = frameID;
3373 static void TickRT()
3375 SRenderThread* pRT = gRenDev->m_pRT;
3376 if (!pRT || (pRT->IsRenderThread() && pRT->m_eVideoThreadMode == SRenderThread::eVTM_Disabled))
3378 const int frameID = gRenDev->GetFrameID(false);
3379 if (ms_lastTickRTFrameID != frameID)
3381 CryAutoCriticalSection lock(ms_lock);
3383 const size_t size = ms_sources.size();
3384 for (size_t i = 0; i < size; ++i)
3386 ms_sources[i]->AutoUpdateRT(frameID);
3389 ms_lastTickRTFrameID = frameID;
3394 static void RenderLightTextures()
3396 for (std::vector<CFlashTextureSourceBase*>::const_iterator it = ms_LightTextures.begin(); it != ms_LightTextures.end(); ++it)
3397 (*it)->Update();
3398 ms_LightTextures.clear();
3401 private:
3402 static std::vector<CFlashTextureSourceBase*> ms_sources;
3403 static std::vector<CFlashTextureSourceBase*> ms_LightTextures;
3404 static CryCriticalSection ms_lock;
3405 static int ms_lastTickFrameID;
3406 static int ms_lastTickRTFrameID;
3409 void CFlashTextureSourceBase::Tick()
3411 FlashTextureSourceSharedRT_AutoUpdate::Tick();
3414 void CFlashTextureSourceBase::TickRT()
3416 FlashTextureSourceSharedRT_AutoUpdate::TickRT();
3419 void CFlashTextureSourceBase::RenderLights()
3421 FlashTextureSourceSharedRT_AutoUpdate::RenderLightTextures();
3424 void CFlashTextureSourceBase::AddToLightRenderList(const IDynTextureSource* pSrc)
3426 FlashTextureSourceSharedRT_AutoUpdate::AddToLightList((CFlashTextureSourceBase*)pSrc);
3429 void CFlashTextureSourceBase::AutoUpdate(const CTimeValue& curTime, const float delta, const bool isEditing, const bool isPaused)
3431 if (m_autoUpdate)
3433 m_pFlashPlayer->UpdatePlayer(this);
3434 #if CRY_PLATFORM_WINDOWS
3435 m_perFrameRendering &= !isEditing;
3436 #endif
3438 if (m_perFrameRendering || (curTime - m_lastVisible).GetSeconds() < 1.0f)
3440 Advance(delta, isPaused);
3445 void CFlashTextureSourceBase::AutoUpdateRT(const int frameID)
3447 if (m_autoUpdate)
3449 if (m_perFrameRendering && (frameID != m_lastVisibleFrameID))
3451 Update();
3456 std::vector<CFlashTextureSourceBase*> FlashTextureSourceSharedRT_AutoUpdate::ms_sources;
3457 std::vector<CFlashTextureSourceBase*> FlashTextureSourceSharedRT_AutoUpdate::ms_LightTextures;
3458 CryCriticalSection FlashTextureSourceSharedRT_AutoUpdate::ms_lock;
3459 int FlashTextureSourceSharedRT_AutoUpdate::ms_lastTickFrameID = 0;
3460 int FlashTextureSourceSharedRT_AutoUpdate::ms_lastTickRTFrameID = 0;
3462 CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::~CFlashPlayerInstanceWrapper()
3464 SAFE_RELEASE(m_pBootStrapper);
3465 SAFE_RELEASE(m_pPlayer);
3468 IFlashPlayer* CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::GetTempPtr() const
3470 CryAutoCriticalSection lock(m_lock);
3472 if (m_pPlayer)
3473 m_pPlayer->AddRef();
3475 return m_pPlayer;
3478 IFlashPlayer* CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::GetPermPtr(CFlashTextureSourceBase* pSrc)
3480 CryAutoCriticalSection lock(m_lock);
3482 m_canDeactivate = false;
3483 CreateInstance(pSrc);
3485 return m_pPlayer;
3488 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::Activate(bool activate, CFlashTextureSourceBase* pSrc)
3490 CryAutoCriticalSection lock(m_lock);
3492 if (activate)
3494 CreateInstance(pSrc);
3496 else
3498 if (m_canDeactivate)
3500 SAFE_RELEASE(m_pPlayer);
3505 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::CreateInstance(CFlashTextureSourceBase* pSrc)
3507 if (!m_pPlayer && m_pBootStrapper)
3509 m_pPlayer = m_pBootStrapper->CreatePlayerInstance(IFlashPlayer::DEFAULT_NO_MOUSE);
3510 if (m_pPlayer)
3512 #if defined(ENABLE_DYNTEXSRC_PROFILING)
3513 m_pPlayer->LinkDynTextureSource(pSrc);
3514 #endif
3515 m_pPlayer->Advance(0.0f);
3516 m_width = m_pPlayer->GetWidth();
3517 m_height = m_pPlayer->GetHeight();
3522 const char* CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::GetSourceFilePath() const
3524 return m_pBootStrapper ? m_pBootStrapper->GetFilePath() : "UNDEFINED";
3527 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::Advance(float delta)
3529 if (m_pPlayer)
3530 m_pPlayer->Advance(delta);
3533 CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::~CFlashPlayerInstanceWrapperLayoutElement()
3535 if (m_pUILayout)
3537 m_pUILayout->Unload();
3539 m_pUILayout = NULL;
3540 m_pPlayer = NULL;
3543 IFlashPlayer* CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::GetTempPtr() const
3545 CryAutoCriticalSection lock(m_lock);
3547 if (m_pPlayer)
3548 m_pPlayer->AddRef();
3550 return m_pPlayer;
3553 IFlashPlayer* CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::GetPermPtr(CFlashTextureSourceBase* pSrc)
3555 CryAutoCriticalSection lock(m_lock);
3557 m_canDeactivate = false;
3558 CreateInstance(pSrc, m_layoutName.c_str());
3560 return m_pPlayer;
3563 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::Activate(bool activate, CFlashTextureSourceBase* pSrc)
3565 CryAutoCriticalSection lock(m_lock);
3567 if (activate)
3569 CreateInstance(pSrc, m_layoutName.c_str());
3571 else
3573 if (m_canDeactivate)
3575 SAFE_RELEASE(m_pPlayer);
3580 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::CreateInstance(CFlashTextureSourceBase* pSrc, const char* layoutName)
3582 UIFramework::IUIFramework* pUIFramework = gEnv->pUIFramework;
3583 if (pUIFramework)
3585 char name[_MAX_PATH];
3586 cry_strcpy(name, layoutName);
3587 PathUtil::RemoveExtension(name);
3588 const char* pExt = fpGetExtension(layoutName);
3589 if (!pExt || strcmpi(pExt, ".layout") != 0)
3591 return;
3594 if (pUIFramework->LoadLayout(name) != INVALID_LAYOUT_ID)
3596 m_layoutName = name;
3597 m_pUILayout = pUIFramework->GetLayoutBase(m_layoutName);
3598 if (m_pUILayout)
3600 m_pPlayer = m_pUILayout->GetPlayer();
3602 if (m_pPlayer)
3604 pSrc->m_autoUpdate = !m_pPlayer->HasMetadata("CE_NoAutoUpdate");
3606 #if defined(ENABLE_DYNTEXSRC_PROFILING)
3607 m_pPlayer->LinkDynTextureSource(pSrc);
3608 #endif
3609 m_pPlayer->Advance(0.0f);
3610 m_width = m_pPlayer->GetWidth();
3611 m_height = m_pPlayer->GetHeight();
3618 const char* CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::GetSourceFilePath() const
3620 return m_pPlayer ? m_pPlayer->GetFilePath() : "UNDEFINED";
3623 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::Advance(float delta)
3625 if (m_pPlayer)
3626 m_pPlayer->Advance(delta);
3629 CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::~CFlashPlayerInstanceWrapperUIElement()
3631 SAFE_RELEASE(m_pUIElement);
3632 SAFE_RELEASE(m_pPlayer);
3635 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::SetUIElement(IUIElement* p)
3637 assert(!m_pUIElement);
3638 m_pUIElement = p;
3639 m_pUIElement->AddRef();
3642 IFlashPlayer* CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::GetTempPtr() const
3644 CryAutoCriticalSection lock(m_lock);
3646 if (m_pPlayer)
3647 m_pPlayer->AddRef();
3649 return m_pPlayer;
3652 IFlashPlayer* CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::GetPermPtr(CFlashTextureSourceBase* pSrc)
3654 CryAutoCriticalSection lock(m_lock);
3656 m_canDeactivate = false;
3657 m_activated = true;
3658 UpdateUIElementPlayer(pSrc);
3660 return m_pPlayer;
3663 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::Activate(bool activate, CFlashTextureSourceBase* pSrc)
3665 CryAutoCriticalSection lock(m_lock);
3667 m_activated = m_canDeactivate ? activate : m_activated;
3668 UpdateUIElementPlayer(pSrc);
3671 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::Clear(CFlashTextureSourceBase* pSrc)
3673 CryAutoCriticalSection lock(m_lock);
3675 if (m_pUIElement && m_pPlayer)
3676 m_pUIElement->RemoveTexture(pSrc);
3678 SAFE_RELEASE(m_pPlayer);
3681 const char* CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::GetSourceFilePath() const
3683 return m_pUIElement ? m_pUIElement->GetFlashFile() : "UNDEFINED";
3686 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::UpdatePlayer(CFlashTextureSourceBase* pSrc)
3688 CryAutoCriticalSection lock(m_lock);
3690 UpdateUIElementPlayer(pSrc);
3693 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::UpdateUIElementPlayer(CFlashTextureSourceBase* pSrc)
3695 if (m_pUIElement)
3697 if (m_activated)
3699 const bool isVisible = m_pUIElement->IsVisible();
3700 IFlashPlayer* pPlayer = isVisible ? m_pUIElement->GetFlashPlayer() : NULL;
3701 if (pPlayer != m_pPlayer)
3703 assert(gRenDev->m_pRT->IsMainThread());
3705 const bool addTex = m_pPlayer == NULL;
3706 SAFE_RELEASE(m_pPlayer);
3707 if (isVisible)
3708 m_pPlayer = pPlayer;
3710 if (m_pPlayer)
3712 m_width = m_pPlayer->GetWidth();
3713 m_height = m_pPlayer->GetHeight();
3714 m_pPlayer->AddRef();
3715 if (addTex)
3716 m_pUIElement->AddTexture(pSrc);
3718 else
3719 m_pUIElement->RemoveTexture(pSrc);
3722 else
3724 assert(gRenDev->m_pRT->IsMainThread());
3726 if (m_pPlayer)
3727 m_pUIElement->RemoveTexture(pSrc);
3728 SAFE_RELEASE(m_pPlayer);
3733 CFlashTextureSourceBase::CFlashTextureSourceBase(const char* pFlashFileName, const IRenderer::SLoadShaderItemArgs* pArgs)
3734 : m_refCount(1)
3735 , m_lastVisible()
3736 , m_lastVisibleFrameID(0)
3737 , m_width(16)
3738 , m_height(16)
3739 , m_aspectRatio(1.0f)
3740 , m_pElement(NULL)
3741 , m_autoUpdate(true)
3742 , m_pFlashFileName(pFlashFileName)
3743 , m_perFrameRendering(false)
3744 , m_pFlashPlayer(CFlashPlayerInstanceWrapperNULL::Get())
3745 //, m_texStateIDs
3746 #if defined(ENABLE_DYNTEXSRC_PROFILING)
3747 , m_pMatSrc(pArgs ? pArgs->m_pMtlSrc : 0)
3748 , m_pMatSrcParent(pArgs ? pArgs->m_pMtlSrcParent : 0)
3749 #endif
3751 bool valid = false;
3753 if (pFlashFileName)
3755 if (IsFlashUIFile(pFlashFileName))
3757 valid = CreateTexFromFlashFile(pFlashFileName);
3758 if (valid)
3760 gEnv->pFlashUI->RegisterModule(this, pFlashFileName);
3763 else if (IsFlashUILayoutFile(pFlashFileName))
3765 if (m_pFlashPlayer)
3766 m_pFlashPlayer->Clear(this);
3768 SAFE_RELEASE(m_pFlashPlayer);
3770 CFlashPlayerInstanceWrapperLayoutElement* pInstanceWrapper = new CFlashPlayerInstanceWrapperLayoutElement();
3771 pInstanceWrapper->CreateInstance(this, pFlashFileName);
3772 m_pFlashPlayer = pInstanceWrapper;
3773 valid = true;
3775 else
3777 IFlashPlayerBootStrapper* pBootStrapper = gEnv->pScaleformHelper ? gEnv->pScaleformHelper->CreateFlashPlayerBootStrapper() : nullptr;
3778 if (pBootStrapper)
3780 if (pBootStrapper->Load(pFlashFileName))
3782 m_autoUpdate = !pBootStrapper->HasMetadata("CE_NoAutoUpdate");
3784 CFlashPlayerInstanceWrapper* pInstanceWrapper = new CFlashPlayerInstanceWrapper();
3785 pInstanceWrapper->SetBootStrapper(pBootStrapper);
3786 pInstanceWrapper->CreateInstance(this);
3787 m_pFlashPlayer = pInstanceWrapper;
3788 valid = true;
3790 else
3792 SAFE_RELEASE(pBootStrapper);
3798 for (size_t i = 0; i < NumCachedTexStateIDs; ++i)
3800 m_texStateIDs[i].original = EDefaultSamplerStates::Unspecified;
3801 m_texStateIDs[i].patched = EDefaultSamplerStates::Unspecified;
3804 if (valid && m_autoUpdate)
3805 FlashTextureSourceSharedRT_AutoUpdate::Add(this);
3808 bool CFlashTextureSourceBase::IsFlashFile(const char* pFlashFileName)
3810 if (pFlashFileName)
3812 const char* pExt = fpGetExtension(pFlashFileName);
3813 const bool bPath = strchr(pFlashFileName, '/') || strchr(pFlashFileName, '\\');
3815 if (pExt)
3817 if (!bPath)
3819 // Pseudo files (no path, looks up flow-node)
3820 return (!stricmp(pExt, ".ui"));
3823 // Real files (looks up filesystem)
3824 return (!stricmp(pExt, ".layout") || !stricmp(pExt, ".gfx") || !stricmp(pExt, ".swf") || !stricmp(pExt, ".usm"));
3828 return false;
3831 bool CFlashTextureSourceBase::IsFlashUIFile(const char* pFlashFileName)
3833 if (pFlashFileName)
3835 const char* pExt = fpGetExtension(pFlashFileName);
3836 const bool bPath = strchr(pFlashFileName, '/') || strchr(pFlashFileName, '\\');
3838 if (pExt)
3840 if (!bPath)
3842 // Pseudo files (no path, looks up flow-node)
3843 return !stricmp(pExt, ".ui");
3848 return false;
3851 bool CFlashTextureSourceBase::IsFlashUILayoutFile(const char* pFlashFileName)
3853 if (pFlashFileName)
3855 const char* pExt = fpGetExtension(pFlashFileName);
3857 if (pExt)
3859 return !stricmp(pExt, ".layout");
3863 return false;
3866 bool CFlashTextureSourceBase::DestroyTexOfFlashFile(const char* name)
3868 if (gEnv->pFlashUI)
3870 IUIElement* pElement = gEnv->pFlashUI->GetUIElementByInstanceStr(name);
3871 if (pElement)
3873 pElement->Unload();
3874 pElement->DestroyThis();
3879 return false;
3882 bool CFlashTextureSourceBase::CreateTexFromFlashFile(const char* name)
3884 if (gEnv->pFlashUI)
3886 //delete old one
3887 if (m_pFlashPlayer)
3888 m_pFlashPlayer->Clear(this);
3889 SAFE_RELEASE(m_pFlashPlayer);
3891 m_pElement = gEnv->pFlashUI->GetUIElementByInstanceStr(name);
3892 if (m_pElement)
3894 CFlashPlayerInstanceWrapperUIElement* pInstanceWrapper = new CFlashPlayerInstanceWrapperUIElement();
3895 m_pElement->SetVisible(true);
3896 pInstanceWrapper->SetUIElement(m_pElement);
3897 pInstanceWrapper->Activate(true, this);
3898 m_pFlashPlayer = pInstanceWrapper;
3899 return true;
3903 return false;
3906 CFlashTextureSourceBase::~CFlashTextureSourceBase()
3908 FlashTextureSourceSharedRT_AutoUpdate::Remove(this);
3910 if (m_pElement) // If module registration happened m_pElement is set
3912 gEnv->pFlashUI->UnregisterModule(this);
3915 if (m_pFlashPlayer)
3916 m_pFlashPlayer->Clear(this);
3918 SAFE_RELEASE(m_pFlashPlayer);
3921 void CFlashTextureSourceBase::AddRef()
3923 CryInterlockedIncrement(&m_refCount);
3926 void CFlashTextureSourceBase::Release()
3928 long refCnt = CryInterlockedDecrement(&m_refCount);
3929 if (refCnt <= 0)
3930 delete this;
3933 void CFlashTextureSourceBase::Activate(bool activate)
3935 m_pFlashPlayer->Activate(activate, this);
3938 #if defined(ENABLE_DYNTEXSRC_PROFILING)
3939 string CFlashTextureSourceBase::GetProfileInfo() const
3942 const char* pMtlName = "NULL";
3943 if (m_pMatSrc || m_pMatSrcParent)
3945 if (m_pMatSrcParent)
3947 if (m_pMatSrcParent->GetName())
3948 pMtlName = m_pMatSrcParent->GetName();
3950 else if (m_pMatSrc)
3952 if (m_pMatSrc->GetName())
3953 pMtlName = m_pMatSrc->GetName();
3957 const char* pSubMtlName = "NULL";
3958 if (m_pMatSrcParent)
3960 if (m_pMatSrc)
3962 if (m_pMatSrc->GetName())
3963 pSubMtlName = m_pMatSrc->GetName();
3966 else
3968 pSubMtlName = 0;
3971 CryFixedStringT<128> info;
3972 info.Format("mat: %s%s%s%s", pMtlName, pSubMtlName ? "|sub: " : "", pSubMtlName ? pSubMtlName : "", !m_pFlashPlayer->CanDeactivate() ? "|$4can't be deactivated!$O" : "");
3974 return info.c_str();
3976 #endif
3978 void* CFlashTextureSourceBase::GetSourceTemp(EDynTextureSource type) const
3980 if (m_pFlashPlayer != nullptr && type == DTS_I_FLASHPLAYER)
3982 return m_pFlashPlayer->GetTempPtr();
3984 return nullptr;
3987 void* CFlashTextureSourceBase::GetSourcePerm(EDynTextureSource type)
3989 if (m_pFlashPlayer != nullptr && type == DTS_I_FLASHPLAYER)
3991 return m_pFlashPlayer->GetPermPtr(this);
3993 return nullptr;
3996 const char* CFlashTextureSourceBase::GetSourceFilePath() const
3998 if (m_pFlashPlayer != nullptr)
4000 return m_pFlashPlayer->GetSourceFilePath();
4002 return nullptr;
4005 bool CFlashTextureSourceBase::Apply(int nTUnit, SamplerStateHandle nTS)
4007 SDynTexture* pDynTexture = GetDynTexture();
4008 assert(pDynTexture);
4009 if (!m_pFlashPlayer || !m_pFlashPlayer->CheckPtr() || !pDynTexture)
4010 return false;
4012 SamplerStateHandle patchedTexStateID = EDefaultSamplerStates::Unspecified;
4014 size_t i = 0;
4015 for (; i < NumCachedTexStateIDs; ++i)
4017 if (m_texStateIDs[i].original == EDefaultSamplerStates::Unspecified)
4018 break;
4020 if (m_texStateIDs[i].original == nTS)
4022 patchedTexStateID = m_texStateIDs[i].patched;
4023 assert(patchedTexStateID != EDefaultSamplerStates::Unspecified);
4024 break;
4028 if (patchedTexStateID == EDefaultSamplerStates::Unspecified)
4030 SSamplerState State = CDeviceObjectFactory::LookupSamplerState(nTS).first;
4031 State.m_bSRGBLookup = true;
4032 patchedTexStateID = CDeviceObjectFactory::GetOrCreateSamplerStateHandle(State);
4034 if (i < NumCachedTexStateIDs)
4036 m_texStateIDs[i].original = nTS;
4037 m_texStateIDs[i].patched = patchedTexStateID;
4041 pDynTexture->Apply(nTUnit, patchedTexStateID);
4042 return true;
4045 void CFlashTextureSourceBase::GetTexGenInfo(float& offsX, float& offsY, float& scaleX, float& scaleY) const
4047 SDynTexture* pDynTexture = GetDynTexture();
4048 assert(pDynTexture);
4049 if (!pDynTexture || !pDynTexture->IsValid())
4051 offsX = 0;
4052 offsY = 0;
4053 scaleX = 1;
4054 scaleY = 1;
4055 return;
4058 ITexture* pSrcTex = pDynTexture->GetTexture();
4059 float invSrcWidth = 1.0f / (float) pSrcTex->GetWidth();
4060 float invSrcHeight = 1.0f / (float) pSrcTex->GetHeight();
4061 offsX = 0;
4062 offsY = 0;
4063 assert(m_width <= pDynTexture->m_nWidth && m_height <= pDynTexture->m_nHeight);
4064 scaleX = m_width * invSrcWidth;
4065 scaleY = m_height * invSrcHeight;
4068 //////////////////////////////////////////////////////////////////////////
4069 CFlashTextureSource::CFlashTextureSource(const char* pFlashFileName, const IRenderer::SLoadShaderItemArgs* pArgs)
4070 : CFlashTextureSourceBase(pFlashFileName, pArgs)
4072 // create render-target with mip-maps
4073 m_pDynTexture = new SDynTexture(GetWidth(), GetHeight(), eTF_R8G8B8A8, eTT_2D, FT_USAGE_RENDERTARGET | FT_STATE_CLAMP | FT_FORCE_MIPS | FT_USAGE_ALLOWREADSRGB, "FlashTextureSourceUniqueRT");
4074 m_pMipMapper = nullptr;
4077 CFlashTextureSource::~CFlashTextureSource()
4079 SAFE_DELETE(m_pMipMapper);
4080 SAFE_DELETE(m_pDynTexture);
4083 int CFlashTextureSource::GetWidth() const
4085 IFlashPlayerInstanceWrapper* pFlash = GetFlashPlayerInstanceWrapper();
4086 return pFlash ? max(Align8(pFlash->GetWidth()), 16) : 16;
4089 int CFlashTextureSource::GetHeight() const
4091 IFlashPlayerInstanceWrapper* pFlash = GetFlashPlayerInstanceWrapper();
4092 return pFlash ? max(Align8(pFlash->GetHeight()), 16) : 16;
4095 bool CFlashTextureSource::UpdateDynTex(int rtWidth, int rtHeight)
4097 bool needResize = rtWidth != m_pDynTexture->m_nWidth || rtHeight != m_pDynTexture->m_nHeight || !m_pDynTexture->IsValid();
4098 if (needResize)
4100 if (!m_pDynTexture->Update(rtWidth, rtHeight))
4101 return false;
4103 return true;
4106 //////////////////////////////////////////////////////////////////////////
4107 SDynTexture* CFlashTextureSourceSharedRT::ms_pDynTexture = nullptr;
4108 CMipmapGenPass* CFlashTextureSourceSharedRT::ms_pMipMapper = nullptr;
4109 int CFlashTextureSourceSharedRT::ms_instCount = 0;
4110 int CFlashTextureSourceSharedRT::ms_sharedRTWidth = 256;
4111 int CFlashTextureSourceSharedRT::ms_sharedRTHeight = 256;
4113 CFlashTextureSourceSharedRT::CFlashTextureSourceSharedRT(const char* pFlashFileName, const IRenderer::SLoadShaderItemArgs* pArgs)
4114 : CFlashTextureSourceBase(pFlashFileName, pArgs)
4116 ++ms_instCount;
4117 if (!ms_pDynTexture)
4119 // create render-target with mip-maps
4120 ms_pDynTexture = new SDynTexture(ms_sharedRTWidth, ms_sharedRTHeight, eTF_R8G8B8A8, eTT_2D, FT_USAGE_RENDERTARGET | FT_STATE_CLAMP | FT_FORCE_MIPS | FT_USAGE_ALLOWREADSRGB, "FlashTextureSourceSharedRT");
4121 ms_pMipMapper = nullptr;
4125 CFlashTextureSourceSharedRT::~CFlashTextureSourceSharedRT()
4127 --ms_instCount;
4128 if (ms_instCount <= 0)
4130 SAFE_DELETE(ms_pMipMapper);
4131 SAFE_DELETE(ms_pDynTexture);
4135 int CFlashTextureSourceSharedRT::GetSharedRTWidth()
4137 return CRenderer::CV_r_DynTexSourceSharedRTWidth > 0 ? Align8(max(CRenderer::CV_r_DynTexSourceSharedRTWidth, 16)) : ms_sharedRTWidth;
4140 int CFlashTextureSourceSharedRT::GetSharedRTHeight()
4142 return CRenderer::CV_r_DynTexSourceSharedRTHeight > 0 ? Align8(max(CRenderer::CV_r_DynTexSourceSharedRTHeight, 16)) : ms_sharedRTHeight;
4145 int CFlashTextureSourceSharedRT::NearestPowerOfTwo(int n)
4147 int k = n;
4148 k--;
4149 k |= k >> 1;
4150 k |= k >> 2;
4151 k |= k >> 4;
4152 k |= k >> 8;
4153 k |= k >> 16;
4154 k++;
4155 return (k - n) <= (n - (k >> 1)) ? k : (k >> 1);
4158 void CFlashTextureSourceSharedRT::SetSharedRTDim(int width, int height)
4160 ms_sharedRTWidth = NearestPowerOfTwo(width > 16 ? width : 16);
4161 ms_sharedRTHeight = NearestPowerOfTwo(height > 16 ? height : 16);
4164 void CFlashTextureSourceSharedRT::SetupSharedRenderTargetRT()
4166 if (ms_pDynTexture)
4168 const int rtWidth = GetSharedRTWidth();
4169 const int rtHeight = GetSharedRTHeight();
4170 bool needResize = rtWidth != ms_pDynTexture->m_nWidth || rtHeight != ms_pDynTexture->m_nHeight;
4171 if (!ms_pDynTexture->IsValid() || needResize)
4173 ms_pDynTexture->Update(rtWidth, rtHeight);
4174 ms_pDynTexture->SetUpdateMask();
4176 CTexture* pTex = (CTexture*) ms_pDynTexture->GetTexture();
4177 // prevent leak, this code is only needed on D3D11 to force texture creating
4178 if (pTex)
4179 pTex->GetSurface(-1, 0);
4180 ProbeDepthStencilSurfaceCreation(rtWidth, rtHeight);
4185 //////////////////////////////////////////////////////////////////////////
4186 CDynTextureSourceLayerActivator::PerLayerDynSrcMtls CDynTextureSourceLayerActivator::s_perLayerDynSrcMtls;
4188 void CDynTextureSourceLayerActivator::LoadLevelInfo()
4190 ReleaseData();
4192 const char* pLevelPath = iSystem->GetI3DEngine()->GetLevelFilePath("dyntexsrclayeract.xml");
4194 XmlNodeRef root = iSystem->LoadXmlFromFile(pLevelPath);
4195 if (root)
4197 const int numLayers = root->getChildCount();
4198 for (int curLayer = 0; curLayer < numLayers; ++curLayer)
4200 XmlNodeRef layer = root->getChild(curLayer);
4201 if (layer)
4203 const char* pLayerName = layer->getAttr("Name");
4204 if (pLayerName)
4206 const int numMtls = layer->getChildCount();
4208 std::vector<string> mtls;
4209 mtls.reserve(numMtls);
4211 for (int curMtl = 0; curMtl < numMtls; ++curMtl)
4213 XmlNodeRef mtl = layer->getChild(curMtl);
4214 if (mtl)
4216 const char* pMtlName = mtl->getAttr("Name");
4217 if (pMtlName)
4218 mtls.push_back(pMtlName);
4222 s_perLayerDynSrcMtls.insert(PerLayerDynSrcMtls::value_type(pLayerName, mtls));
4229 void CDynTextureSourceLayerActivator::ReleaseData()
4231 stl::reconstruct(s_perLayerDynSrcMtls);
4234 void CDynTextureSourceLayerActivator::ActivateLayer(const char* pLayerName, bool activate)
4236 PerLayerDynSrcMtls::const_iterator it = pLayerName ? s_perLayerDynSrcMtls.find(pLayerName) : s_perLayerDynSrcMtls.end();
4237 if (it != s_perLayerDynSrcMtls.end())
4239 const std::vector<string>& mtls = (*it).second;
4240 const size_t numMtls = mtls.size();
4242 const IMaterialManager* pMatMan = gEnv->p3DEngine->GetMaterialManager();
4244 for (size_t i = 0; i < numMtls; ++i)
4246 const char* pMtlName = mtls[i].c_str();
4247 IMaterial* pMtl = pMatMan->FindMaterial(pMtlName);
4248 if (pMtl)
4250 pMtl->ActivateDynamicTextureSources(activate);
4256 //////////////////////////////////////////////////////////////////////////
4257 void CRenderer::EF_AddRTStat(CTexture* pTex, int nFlags, int nW, int nH)
4259 SRTargetStat TS;
4260 int nSize;
4261 ETEX_Format eTF;
4262 if (!pTex)
4264 eTF = eTF_R8G8B8A8;
4265 if (nW < 0)
4266 nW = m_width;
4267 if (nH < 0)
4268 nH = m_height;
4269 nSize = CTexture::TextureDataSize(nW, nH, 1, 1, 1, eTF);
4270 TS.m_Name = "Back buffer";
4272 else
4274 eTF = pTex->GetDstFormat();
4275 if (nW < 0)
4276 nW = pTex->GetWidth();
4277 if (nH < 0)
4278 nH = pTex->GetHeight();
4279 nSize = CTexture::TextureDataSize(nW, nH, 1, pTex->GetNumMips(), 1, eTF);
4280 const char* szName = pTex->GetName();
4281 if (szName && szName[0] == '$')
4282 TS.m_Name = string("@") + string(&szName[1]);
4283 else
4284 TS.m_Name = szName;
4286 TS.m_eTF = eTF;
4288 if (nFlags > 0)
4290 if (nFlags == 1)
4291 TS.m_Name += " (Target)";
4292 else if (nFlags == 2)
4294 TS.m_Name += " (Depth)";
4295 nSize = nW * nH * 3;
4297 else if (nFlags == 4)
4299 TS.m_Name += " (Stencil)";
4300 nSize = nW * nH;
4302 else if (nFlags == 3)
4304 TS.m_Name += " (Target + Depth)";
4305 nSize += nW * nH * 3;
4307 else if (nFlags == 6)
4309 TS.m_Name += " (Depth + Stencil)";
4310 nSize = nW * nH * 4;
4312 else if (nFlags == 5)
4314 TS.m_Name += " (Target + Stencil)";
4315 nSize += nW * nH;
4317 else if (nFlags == 7)
4319 TS.m_Name += " (Target + Depth + Stencil)";
4320 nSize += nW * nH * 4;
4322 else
4324 assert(0);
4327 TS.m_nSize = nSize;
4328 TS.m_nWidth = nW;
4329 TS.m_nHeight = nH;
4331 m_RP.m_RTStats.push_back(TS);
4334 void CRenderer::EF_PrintRTStats(const char* szName)
4336 const int nYstep = 14;
4337 int nY = 30; // initial Y pos
4338 int nX = 20; // initial X pos
4339 ColorF col = Col_Green;
4340 IRenderAuxText::Draw2dLabel((float)nX, (float)nY, 1.6f, &col.r, false, "%s", szName);
4341 nX += 10;
4342 nY += 25;
4344 col = Col_White;
4345 int nYstart = nY;
4346 int nSize = 0;
4347 for (int i = 0; i < m_RP.m_RTStats.size(); i++)
4349 SRTargetStat* pRT = &m_RP.m_RTStats[i];
4351 IRenderAuxText::Draw2dLabel((float)nX, (float)nY, 1.4f, &col.r, false, "%s (%d x %d x %s), Size: %.3f Mb", pRT->m_Name.c_str(), pRT->m_nWidth, pRT->m_nHeight, CTexture::NameForTextureFormat(pRT->m_eTF), (float)pRT->m_nSize / 1024.0f / 1024.0f);
4352 nY += nYstep;
4353 if (nY >= m_height - 25)
4355 nY = nYstart;
4356 nX += 500;
4358 nSize += pRT->m_nSize;
4360 col = Col_Yellow;
4361 IRenderAuxText::Draw2dLabel((float)nX, (float)(nY + 10), 1.4f, &col.r, false, "Total: %d RT's, Size: %.3f Mb", m_RP.m_RTStats.size(), nSize / 1024.0f / 1024.0f);
4364 STexPool::~STexPool()
4366 bool poolEmpty = true;
4367 STexPoolItemHdr* pITH = m_ItemsList.m_Next;
4368 while (pITH != &m_ItemsList)
4370 STexPoolItemHdr* pNext = pITH->m_Next;
4371 STexPoolItem* pIT = static_cast<STexPoolItem*>(pITH);
4373 assert(pIT->m_pOwner == this);
4374 #ifndef _RELEASE
4375 CryLogAlways("***** Texture %p (%s) still in pool %p! Memory leak and crash will follow *****\n", pIT->m_pTex, pIT->m_pTex ? pIT->m_pTex->GetName() : "NULL", this);
4376 poolEmpty = false;
4377 #else
4378 if (pIT->m_pTex)
4380 pIT->m_pTex->ReleaseDeviceTexture(true); // Try to recover in release
4382 #endif
4383 *const_cast<STexPool**>(&pIT->m_pOwner) = NULL;
4384 pITH = pNext;
4386 CRY_ASSERT_MESSAGE(poolEmpty, "Texture pool was not empty on shutdown");
4389 const ETEX_Type CTexture::GetTextureType() const
4391 return m_eTT;
4394 const int CTexture::GetTextureID() const
4396 return GetID();
4399 #ifdef TEXTURE_GET_SYSTEM_COPY_SUPPORT
4401 const ColorB* CTexture::GetLowResSystemCopy(uint16& nWidth, uint16& nHeight, int** ppLowResSystemCopyAtlasId)
4403 const LowResSystemCopyType::iterator& it = s_LowResSystemCopy.find(this);
4404 if (it != CTexture::s_LowResSystemCopy.end())
4406 nWidth = (*it).second.m_nLowResCopyWidth;
4407 nHeight = (*it).second.m_nLowResCopyHeight;
4408 *ppLowResSystemCopyAtlasId = &(*it).second.m_nLowResSystemCopyAtlasId;
4409 return (*it).second.m_lowResSystemCopy.GetElements();
4412 return NULL;
4415 /*#ifndef eTF_BC3
4416 #define eTF_BC1 eTF_DXT1
4417 #define eTF_BC2 eTF_DXT3
4418 #define eTF_BC3 eTF_DXT5
4419 #endif*/
4421 void CTexture::PrepareLowResSystemCopy(byte* pTexData, bool bTexDataHasAllMips)
4423 if (m_eTT != eTT_2D || (m_nMips <= 1 && (m_nWidth > 16 || m_nHeight > 16)))
4424 return;
4426 // this function handles only compressed textures for now
4427 if (m_eDstFormat != eTF_BC3 && m_eDstFormat != eTF_BC1 && m_eDstFormat != eTF_BC2 && m_eDstFormat != eTF_BC7)
4428 return;
4430 // make sure we skip non diffuse textures
4431 if (strstr(GetName(), "_ddn")
4432 || strstr(GetName(), "_ddna")
4433 || strstr(GetName(), "_mask")
4434 || strstr(GetName(), "_spec.")
4435 || strstr(GetName(), "_gloss")
4436 || strstr(GetName(), "_displ")
4437 || strstr(GetName(), "characters")
4438 || strstr(GetName(), "$")
4440 return;
4442 if (pTexData)
4444 SLowResSystemCopy& rSysCopy = s_LowResSystemCopy[this];
4446 rSysCopy.m_nLowResCopyWidth = m_nWidth;
4447 rSysCopy.m_nLowResCopyHeight = m_nHeight;
4449 int nSrcOffset = 0;
4450 int nMipId = 0;
4452 while ((rSysCopy.m_nLowResCopyWidth > 16 || rSysCopy.m_nLowResCopyHeight > 16 || nMipId < 2) && (rSysCopy.m_nLowResCopyWidth >= 8 && rSysCopy.m_nLowResCopyHeight >= 8))
4454 nSrcOffset += TextureDataSize(rSysCopy.m_nLowResCopyWidth, rSysCopy.m_nLowResCopyHeight, 1, 1, 1, m_eDstFormat);
4455 rSysCopy.m_nLowResCopyWidth /= 2;
4456 rSysCopy.m_nLowResCopyHeight /= 2;
4457 nMipId++;
4460 int nSizeDxtMip = TextureDataSize(rSysCopy.m_nLowResCopyWidth, rSysCopy.m_nLowResCopyHeight, 1, 1, 1, m_eDstFormat);
4461 int nSizeRgbaMip = TextureDataSize(rSysCopy.m_nLowResCopyWidth, rSysCopy.m_nLowResCopyHeight, 1, 1, 1, eTF_R8G8B8A8);
4463 rSysCopy.m_lowResSystemCopy.CheckAllocated(nSizeRgbaMip / sizeof(ColorB));
4465 gRenDev->DXTDecompress(pTexData + (bTexDataHasAllMips ? nSrcOffset : 0), nSizeDxtMip,
4466 (byte*)rSysCopy.m_lowResSystemCopy.GetElements(), rSysCopy.m_nLowResCopyWidth, rSysCopy.m_nLowResCopyHeight, 1, m_eDstFormat, false, 4);
4470 #endif // TEXTURE_GET_SYSTEM_COPY_SUPPORT
4472 void CTexture::AddInvalidateCallback(void* listener, const SResourceBinding::InvalidateCallbackFunction& callback)
4474 AUTO_LOCK_T(CryCriticalSectionNonRecursive, s_invalidationLock);
4476 #if !CRY_PLATFORM_ORBIS || defined(__GXX_RTTI)
4477 CRY_ASSERT(callback.target<SResourceBinding::InvalidateCallbackSignature*>() != nullptr);
4478 #endif
4480 auto insertResult = m_invalidateCallbacks.emplace(listener, callback);
4481 ++insertResult.first->second.refCount;
4483 // We only allow one callback function per listener
4484 #if !CRY_PLATFORM_ORBIS || defined(__GXX_RTTI)
4485 CRY_ASSERT(*callback.target<SResourceBinding::InvalidateCallbackSignature*>() == *insertResult.first->second.callback.target<SResourceBinding::InvalidateCallbackSignature*>());
4486 #endif
4489 void CTexture::RemoveInvalidateCallbacks(void* listener)
4491 AUTO_LOCK_T(CryCriticalSectionNonRecursive, s_invalidationLock);
4493 auto it = m_invalidateCallbacks.find(listener);
4495 if (it != m_invalidateCallbacks.end())
4497 if (--it->second.refCount <= 0)
4498 m_invalidateCallbacks.erase(listener);
4502 void CTexture::InvalidateDeviceResource(uint32 dirtyFlags)
4504 AUTO_LOCK_T(CryCriticalSectionNonRecursive, s_invalidationLock);
4506 for (auto it = m_invalidateCallbacks.begin(), end = m_invalidateCallbacks.end(); it != end;)
4508 auto itCurrentCallback = it++;
4509 if (itCurrentCallback->second.callback(itCurrentCallback->first, dirtyFlags) == false)
4510 m_invalidateCallbacks.erase(itCurrentCallback);