1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
3 /*=============================================================================
4 Texture.cpp : Common texture manager implementation.
7 * Created by Honich Andrey
9 =============================================================================*/
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 int CTexture::s_nStreamingMode
;
33 int CTexture::s_nStreamingUpdateMode
;
34 bool CTexture::s_bPrecachePhase
;
35 bool CTexture::s_bInLevelPhase
= false;
36 bool CTexture::s_bPrestreamPhase
;
38 size_t CTexture::s_nStreamingThroughput
= 0;
39 float CTexture::s_nStreamingTotalTime
= 0;
41 CTextureStreamPoolMgr
* CTexture::s_pPoolMgr
;
42 std::set
<string
> CTexture::s_vTexReloadRequests
;
43 CryCriticalSection
CTexture::s_xTexReloadLock
;
44 #ifdef TEXTURE_GET_SYSTEM_COPY_SUPPORT
45 CTexture::LowResSystemCopyType
CTexture::s_LowResSystemCopy
[TEX_SYS_COPY_MAX_SLOTS
];
46 CryReadModifyLock
CTexture::s_LowResSystemCopyLock
;
49 #if defined(TEXSTRM_DEFERRED_UPLOAD)
50 ID3D11DeviceContext
* CTexture::s_pStreamDeferredCtx
= nullptr;
53 //============================================================
55 SResourceView
SResourceView::ShaderResourceView(DXGI_FORMAT nFormat
, int nFirstSlice
, int nSliceCount
, int nMostDetailedMip
, int nMipCount
, bool bSrgbRead
, bool bMultisample
, int nFlags
)
57 SResourceView
result(0);
59 result
.m_Desc
.eViewType
= eShaderResourceView
;
60 result
.m_Desc
.nFormat
= nFormat
;
61 result
.m_Desc
.nFirstSlice
= nFirstSlice
;
62 result
.m_Desc
.nSliceCount
= nSliceCount
;
63 result
.m_Desc
.nMostDetailedMip
= nMostDetailedMip
;
64 result
.m_Desc
.nMipCount
= nMipCount
;
65 result
.m_Desc
.bSrgbRead
= bSrgbRead
? 1 : 0;
66 result
.m_Desc
.nFlags
= nFlags
;
67 result
.m_Desc
.bMultisample
= bMultisample
? 1 : 0;
72 SResourceView
SResourceView::RenderTargetView(DXGI_FORMAT nFormat
, int nFirstSlice
, int nSliceCount
, int nMipLevel
, bool bMultisample
)
74 SResourceView
result(0);
76 result
.m_Desc
.eViewType
= eRenderTargetView
;
77 result
.m_Desc
.nFormat
= nFormat
;
78 result
.m_Desc
.nFirstSlice
= nFirstSlice
;
79 result
.m_Desc
.nSliceCount
= nSliceCount
;
80 result
.m_Desc
.nMostDetailedMip
= nMipLevel
;
81 result
.m_Desc
.nMipCount
= 1;
82 result
.m_Desc
.bMultisample
= bMultisample
? 1 : 0;
87 SResourceView
SResourceView::DepthStencilView(DXGI_FORMAT nFormat
, int nFirstSlice
, int nSliceCount
, int nMipLevel
, bool bMultisample
, int nFlags
)
89 SResourceView
result(0);
91 result
.m_Desc
.eViewType
= eDepthStencilView
;
92 result
.m_Desc
.nFormat
= nFormat
;
93 result
.m_Desc
.nFirstSlice
= nFirstSlice
;
94 result
.m_Desc
.nSliceCount
= nSliceCount
;
95 result
.m_Desc
.nMostDetailedMip
= nMipLevel
;
96 result
.m_Desc
.nMipCount
= 1;
97 result
.m_Desc
.nFlags
= nFlags
;
98 result
.m_Desc
.bMultisample
= bMultisample
? 1 : 0;
103 SResourceView
SResourceView::UnorderedAccessView(DXGI_FORMAT nFormat
, int nFirstSlice
, int nSliceCount
, int nMipLevel
, int nFlags
)
105 SResourceView
result(0);
107 result
.m_Desc
.eViewType
= eUnorderedAccessView
;
108 result
.m_Desc
.nFormat
= nFormat
;
109 result
.m_Desc
.nFirstSlice
= nFirstSlice
;
110 result
.m_Desc
.nSliceCount
= nSliceCount
;
111 result
.m_Desc
.nMostDetailedMip
= nMipLevel
;
112 result
.m_Desc
.nMipCount
= 1;
113 result
.m_Desc
.nFlags
= nFlags
;
118 //============================================================
121 static inline uint32
ConvertFromTextureFlags(ETextureFlags eFlags
)
123 // NOTE Currently without correspondence:
128 // FT_USAGE_ALLOWREADSRGB
132 (!(eFlags
& FT_DONT_READ
) ? CDeviceObjectFactory::BIND_SHADER_RESOURCE
: 0) |
133 ( (eFlags
& FT_USAGE_RENDERTARGET
) ? CDeviceObjectFactory::BIND_RENDER_TARGET
: 0) |
134 ( (eFlags
& FT_USAGE_DEPTHSTENCIL
) ? CDeviceObjectFactory::BIND_DEPTH_STENCIL
: 0) |
135 ( (eFlags
& FT_USAGE_UNORDERED_ACCESS
) ? CDeviceObjectFactory::BIND_UNORDERED_ACCESS
: 0) |
136 (!(eFlags
& FT_DONT_STREAM
) ? CDeviceObjectFactory::USAGE_STREAMING
: 0) |
137 ( (eFlags
& FT_STAGE_READBACK
) ? (CDeviceObjectFactory::USAGE_STAGE_ACCESS
| CDeviceObjectFactory::USAGE_CPU_READ
) : 0) |
138 ( (eFlags
& FT_STAGE_UPLOAD
) ? (CDeviceObjectFactory::USAGE_STAGE_ACCESS
| CDeviceObjectFactory::USAGE_CPU_WRITE
) : 0) |
139 ( (eFlags
& FT_FORCE_MIPS
) ? CDeviceObjectFactory::USAGE_AUTOGENMIPS
: 0) |
140 ( (eFlags
& FT_USAGE_TEMPORARY
) ? CDeviceObjectFactory::USAGE_HIFREQ_HEAP
: 0) |
141 ( (eFlags
& FT_USAGE_UAV_OVERLAP
) ? CDeviceObjectFactory::USAGE_UAV_OVERLAP
: 0) |
142 ( (eFlags
& FT_USAGE_UAV_RWTEXTURE
) ? CDeviceObjectFactory::USAGE_UAV_READWRITE
: 0);
147 static inline ETextureFlags
ConvertToTextureFlags(uint32 eFlags
)
149 // NOTE Currently without correspondence:
154 // FT_USAGE_ALLOWREADSRGB
157 return ETextureFlags(
158 (!(eFlags
& CDeviceObjectFactory::BIND_SHADER_RESOURCE
) ? FT_DONT_READ
: 0) |
159 ( (eFlags
& CDeviceObjectFactory::BIND_RENDER_TARGET
) ? FT_USAGE_RENDERTARGET
: 0) |
160 ( (eFlags
& CDeviceObjectFactory::BIND_DEPTH_STENCIL
) ? FT_USAGE_DEPTHSTENCIL
: 0) |
161 ( (eFlags
& CDeviceObjectFactory::BIND_UNORDERED_ACCESS
) ? FT_USAGE_UNORDERED_ACCESS
: 0) |
162 (!(eFlags
& CDeviceObjectFactory::USAGE_STREAMING
) ? FT_DONT_STREAM
: 0) |
163 ( (eFlags
& (CDeviceObjectFactory::USAGE_STAGE_ACCESS
| CDeviceObjectFactory::USAGE_CPU_READ
)) ? FT_STAGE_READBACK
: 0) |
164 ( (eFlags
& (CDeviceObjectFactory::USAGE_STAGE_ACCESS
| CDeviceObjectFactory::USAGE_CPU_WRITE
)) ? FT_STAGE_UPLOAD
: 0) |
165 ( (eFlags
& CDeviceObjectFactory::USAGE_AUTOGENMIPS
) ? FT_FORCE_MIPS
: 0) |
166 ( (eFlags
& CDeviceObjectFactory::USAGE_HIFREQ_HEAP
) ? FT_USAGE_TEMPORARY
: 0) |
167 ( (eFlags
& CDeviceObjectFactory::USAGE_UAV_OVERLAP
) ? FT_USAGE_UAV_OVERLAP
: 0) |
168 ( (eFlags
& CDeviceObjectFactory::USAGE_UAV_READWRITE
) ? FT_USAGE_UAV_RWTEXTURE
: 0));
172 //============================================================
173 CTexture::CTexture(const uint32 nFlags
, const ColorF
& clearColor
/*= ColorF(Clr_Empty)*/, CDeviceTexture
* devTexToOwn
/*= nullptr*/)
176 m_eDstFormat
= eTF_Unknown
;
177 m_eSrcFormat
= eTF_Unknown
;
184 m_nDevTextureSize
= 0;
185 m_fAvgBrightness
= 1.0f
;
188 m_cClearColor
= clearColor
;
189 m_nPersistentSize
= 0;
190 m_fAvgBrightness
= 0.0f
;
193 m_nUpdateFrameID
= -1;
194 m_nAccessFrameID
= -1;
196 m_pDevTexture
= nullptr;
199 m_bNeedRestoring
= false;
200 m_bNoTexture
= false;
202 m_bUseMultisampledRTV
= false;
203 m_bCustomFormat
= false;
204 m_eSrcTileMode
= eTM_Unspecified
;
206 m_bPostponed
= false;
207 m_bForceStreamHighRes
= false;
208 m_bWasUnloaded
= false;
210 m_bStreamPrepared
= false;
211 m_bStreamRequested
= false;
212 m_bVertexTexture
= false;
213 m_bUseDecalBorderCol
= false;
215 m_bNoDevTexture
= false;
216 m_bInDistanceSortedList
= false;
217 m_bCreatedInLevel
= gRenDev
->m_bInLevel
;
220 m_bStreamHighPriority
= 0;
221 m_nStreamingPriority
= 0;
222 m_nMinMipVidUploaded
= MAX_MIP_LEVELS
;
223 m_nMinMipVidActive
= MAX_MIP_LEVELS
;
224 m_nStreamSlot
= InvalidStreamSlot
;
225 m_fpMinMipCur
= MAX_MIP_LEVELS
<< 8;
226 m_nStreamFormatCode
= 0;
228 m_pFileTexMips
= NULL
;
229 m_fCurrentMipBias
= 0.f
;
231 static_assert(MaxStreamTasks
< 32767, "Too many stream tasks!");
235 OwnDevTexture(devTexToOwn
);
239 //============================================================
241 CTexture::~CTexture()
243 InvalidateDeviceResource(this, eResourceDestroyed
);
245 // sizes of these structures should NOT exceed L2 cache line!
246 static_assert((offsetof(CTexture
, m_fCurrentMipBias
) - offsetof(CTexture
, m_pFileTexMips
)) <= 64, "Invalid offset!");
248 CRY_ASSERT(gRenDev
->m_pRT
->IsRenderThread() && !gRenDev
->m_pRT
->IsRenderLoadingThread());
249 CRY_ASSERT(!IsStreaming());
251 ReleaseDeviceTexture(false);
256 StreamState_ReleaseInfo(this, m_pFileTexMips
);
257 m_pFileTexMips
= NULL
;
260 #ifdef ENABLE_TEXTURE_STREAM_LISTENER
261 if (s_pStreamListener
)
262 s_pStreamListener
->OnDestroyedStreamedTexture(this);
265 CRY_ASSERT(!m_bInDistanceSortedList
);
267 #ifdef TEXTURE_GET_SYSTEM_COPY_SUPPORT
269 AUTO_MODIFYLOCK(s_LowResSystemCopyLock
);
271 for (int slot
= 0; slot
< TEX_SYS_COPY_MAX_SLOTS
; slot
++)
272 s_LowResSystemCopy
[slot
].erase(this);
277 const CCryNameTSCRC
& CTexture::mfGetClassName()
282 CCryNameTSCRC
CTexture::GenName(const char* name
, uint32 nFlags
)
284 stack_string strName
= name
;
287 //'\\' in texture names causing duplication
288 PathUtil::ToUnixPath(strName
);
290 if (nFlags
& FT_ALPHA
)
293 return CCryNameTSCRC(strName
.c_str());
299 bool operator()(const char* s1
, const char* s2
) const { return strcmp(s1
, s2
) < 0; }
302 CTexture
* CTexture::GetByID(int nID
)
304 CTexture
* pTex
= CRendererResources::s_ptexNoTexture
;
306 const CCryNameTSCRC
& className
= mfGetClassName();
307 CBaseResource
* pBR
= CBaseResource::GetResource(className
, nID
, false);
309 pTex
= (CTexture
*)pBR
;
313 CTexture
* CTexture::GetByName(const char* szName
, uint32 flags
)
315 CTexture
* pTex
= nullptr;
317 CCryNameTSCRC Name
= GenName(szName
, flags
);
318 CBaseResource
* pBR
= CBaseResource::GetResource(mfGetClassName(), Name
, false);
320 pTex
= (CTexture
*)pBR
;
324 CTexture
* CTexture::GetByNameCRC(CCryNameTSCRC Name
)
326 CTexture
* pTex
= nullptr;
328 CBaseResource
* pBR
= CBaseResource::GetResource(mfGetClassName(), Name
, false);
330 pTex
= (CTexture
*)pBR
;
334 CTexture
* CTexture::FindOrRegisterTextureObject(const char* name
, uint32 nFlags
, ETEX_Format eTFDst
, bool& bFound
)
336 CTexture
* pTex
= nullptr;
338 CCryNameTSCRC Name
= GenName(name
, nFlags
);
339 CBaseResource
* pBR
= CBaseResource::GetResource(mfGetClassName(), Name
, false);
342 pTex
= new CTexture(nFlags
);
343 pTex
->Register(mfGetClassName(), Name
);
344 pTex
->m_eFlags
= nFlags
;
345 pTex
->m_eDstFormat
= eTFDst
;
346 pTex
->m_SrcName
= name
;
351 pTex
= (CTexture
*)pBR
;
359 void CTexture::RefDevTexture(CDeviceTexture
* pDeviceTex
)
361 // Hard-wired device-resources can't have a unique owner (they are shared)
363 CRY_ASSERT(!DEVICE_TEXTURE_STORE_OWNER
|| m_pDevTexture
->GetOwner() == nullptr);
365 if ((m_pDevTexture
= pDeviceTex
))
366 m_pDevTexture
->SetOwner(nullptr, nullptr);
368 InvalidateDeviceResource(this, eDeviceResourceDirty
);
371 void CTexture::SetDevTexture(CDeviceTexture
* pDeviceTex
)
373 // Substitute device-resource by a strictly subset one (texture-config doesn't change, only residency)
376 CRY_ASSERT(!DEVICE_TEXTURE_STORE_OWNER
|| m_pDevTexture
->GetOwner() == this);
377 m_pDevTexture
->SetOwner(nullptr, nullptr);
378 m_pDevTexture
->Release();
381 if ((m_pDevTexture
= pDeviceTex
))
383 m_pDevTexture
->SetNoDelete(!!(m_eFlags
& FT_DONT_RELEASE
));
384 m_pDevTexture
->SetOwner(this, m_SrcName
.c_str());
386 m_nDevTextureSize
= m_nPersistentSize
= m_pDevTexture
->GetDeviceSize();
389 InvalidateDeviceResource(this, eDeviceResourceDirty
);
392 void CTexture::OwnDevTexture(CDeviceTexture
* pDeviceTex
)
394 // Take ownership of an entirely different device-resource (texture-config does change)
397 CRY_ASSERT(!DEVICE_TEXTURE_STORE_OWNER
|| m_pDevTexture
->GetOwner() == this);
398 m_pDevTexture
->SetOwner(nullptr, nullptr);
399 m_pDevTexture
->Release();
402 if ((m_pDevTexture
= pDeviceTex
))
404 m_pDevTexture
->SetOwner(this, m_SrcName
.c_str());
406 const STextureLayout Layput
= m_pDevTexture
->GetLayout();
408 m_nWidth
= Layput
.m_nWidth
;
409 m_nHeight
= Layput
.m_nHeight
;
410 m_nDepth
= Layput
.m_nDepth
;
411 m_nArraySize
= Layput
.m_nArraySize
;
412 m_nMips
= Layput
.m_nMips
;
413 m_eSrcFormat
= Layput
.m_eSrcFormat
;
414 m_eDstFormat
= Layput
.m_eDstFormat
;
415 m_eTT
= Layput
.m_eTT
;
416 m_eFlags
= Layput
.m_eFlags
; /* TODO: change FT_... to CDeviceObjectFactory::... */
417 m_bIsSRGB
= Layput
.m_bIsSRGB
;
419 m_nDevTextureSize
= m_nPersistentSize
= m_pDevTexture
->GetDeviceSize();
422 InvalidateDeviceResource(this, eDeviceResourceDirty
);
425 void CTexture::PostCreate()
427 m_nUpdateFrameID
= gRenDev
->m_pRT
->IsRenderThread() ? gRenDev
->GetRenderFrameID() : gRenDev
->GetMainFrameID();
428 m_bPostponed
= false;
431 void CTexture::GetMemoryUsage(ICrySizer
* pSizer
) const
434 pSizer
->AddObject(m_SrcName
);
436 #ifdef TEXTURE_GET_SYSTEM_COPY_SUPPORT
438 AUTO_MODIFYLOCK(s_LowResSystemCopyLock
);
440 for (int slot
= 0; slot
< TEX_SYS_COPY_MAX_SLOTS
; slot
++)
442 const LowResSystemCopyType::iterator
& it
= s_LowResSystemCopy
[slot
].find(this);
443 if (it
!= CTexture::s_LowResSystemCopy
[slot
].end())
444 pSizer
->AddObject((*it
).second
.m_lowResSystemCopy
);
450 m_pFileTexMips
->GetMemoryUsage(pSizer
, m_nMips
, m_CacheFileHeader
.m_nSides
);
453 //=======================================================
454 // Low-level functions calling CreateDeviceTexture()
456 void CTexture::CreateRenderTarget(ETEX_Format eFormat
, const ColorF
& cClear
)
458 if (m_eSrcFormat
== eTF_Unknown
)
459 m_eSrcFormat
= eFormat
;
460 if (m_eSrcFormat
== eTF_Unknown
)
462 m_eFlags
|= FT_FAILED
;
466 SetClosestFormatSupported();
467 m_eFlags
|= FT_USAGE_RENDERTARGET
;
468 m_cClearColor
= cClear
;
469 m_nMips
= m_eFlags
& FT_FORCE_MIPS
? CTexture::CalcNumMips(m_nWidth
, m_nHeight
) : m_nMips
;
471 SSubresourceData
pData(nullptr);
472 CreateDeviceTexture(std::move(pData
));
476 void CTexture::CreateDepthStencil(ETEX_Format eFormat
, const ColorF
& cClear
)
478 if (m_eSrcFormat
== eTF_Unknown
)
479 m_eSrcFormat
= eFormat
;
480 if (m_eSrcFormat
== eTF_Unknown
)
482 m_eFlags
|= FT_FAILED
;
486 SetClosestFormatSupported();
487 m_eFlags
|= FT_USAGE_DEPTHSTENCIL
;
488 m_cClearColor
= cClear
;
489 m_nMips
= m_eFlags
& FT_FORCE_MIPS
? CTexture::CalcNumMips(m_nWidth
, m_nHeight
) : m_nMips
;
491 SSubresourceData
pData(nullptr);
492 CreateDeviceTexture(std::move(pData
));
496 void CTexture::CreateShaderResource(STexDataPtr
&& td
)
498 m_nWidth
= td
->m_nWidth
;
499 m_nHeight
= td
->m_nHeight
;
500 m_nDepth
= td
->m_nDepth
;
501 m_eSrcFormat
= td
->m_eFormat
;
502 m_nMips
= td
->m_nMips
;
503 m_fAvgBrightness
= td
->m_fAvgBrightness
;
504 m_cMinColor
= td
->m_cMinColor
;
505 m_cMaxColor
= td
->m_cMaxColor
;
506 m_bUseDecalBorderCol
= (td
->m_nFlags
& FIM_DECAL
) != 0;
507 m_bIsSRGB
= (td
->m_nFlags
& FIM_SRGB_READ
) != 0;
509 assert((m_nDepth
== 1) || (m_eTT
== eTT_3D
));
510 assert((m_nArraySize
== 1) || (m_eTT
== eTT_Cube
|| m_eTT
== eTT_CubeArray
|| m_eTT
== eTT_2DArray
));
511 assert((m_nArraySize
% 6) || (m_eTT
== eTT_Cube
|| m_eTT
== eTT_CubeArray
));
512 assert(!td
->m_pData
[1] || !(m_eFlags
& FT_REPLICATE_TO_ALL_SIDES
) || (m_eTT
== eTT_Cube
|| m_eTT
== eTT_CubeArray
));
513 assert(m_nWidth
&& m_nHeight
&& m_nMips
);
515 SetClosestFormatSupported();
516 if (!(td
= ImagePreprocessing(std::move(td
), m_eDstFormat
)))
518 SetNoTexture(m_eTT
== eTT_Cube
? CRendererResources::s_ptexNoTextureCM
: CRendererResources::s_ptexNoTexture
);
523 #if defined(TEXTURE_GET_SYSTEM_COPY_SUPPORT)
524 if (m_eFlags
& FT_KEEP_LOWRES_SYSCOPY
)
526 uint16 width
, height
;
527 ITexture::GetLowResSystemCopy(width
, height
);
531 assert(m_nWidth
&& m_nHeight
&& m_nMips
);
533 const int nMaxTextureSize
= gRenDev
->GetMaxTextureSize();
534 if (nMaxTextureSize
> 0)
536 if (m_nWidth
> nMaxTextureSize
|| m_nHeight
> nMaxTextureSize
)
538 SetNoTexture(m_eTT
== eTT_Cube
? CRendererResources::s_ptexNoTextureCM
: CRendererResources::s_ptexNoTexture
);
544 SSubresourceData pData
= td
->Transfer();
545 CreateDeviceTexture(std::move(pData
));
549 //=======================================================
550 // Mid-level functions calling Create...()
552 void CTexture::Create2DTexture(int nWidth
, int nHeight
, int nMips
, int nFlags
, const byte
* pSrcData
, ETEX_Format eSrcFormat
)
555 nMips
= CTexture::CalcNumMips(nWidth
, nHeight
);
556 m_eSrcTileMode
= pSrcData
? eTM_None
: eTM_Unspecified
;
557 m_eSrcFormat
= eSrcFormat
;
560 STexDataPtr td
= new STexData
;
562 td
->m_eFormat
= eSrcFormat
;
563 td
->m_eTileMode
= m_eSrcTileMode
;
564 td
->m_nWidth
= nWidth
;
565 td
->m_nHeight
= nHeight
;
568 td
->m_pData
[0] = pSrcData
;
569 if (nFlags
& FT_TAKEOVER_DATA_POINTER
)
570 td
->SetReallocated(0);
572 CreateShaderResource(std::move(td
));
576 void CTexture::Create3DTexture(int nWidth
, int nHeight
, int nDepth
, int nMips
, int nFlags
, const byte
* pSrcData
, ETEX_Format eSrcFormat
)
579 // nMips = CTexture::CalcNumMips(nWidth, nHeight);
580 m_eSrcTileMode
= pSrcData
? eTM_None
: eTM_Unspecified
;
581 m_eSrcFormat
= eSrcFormat
;
584 STexDataPtr td
= new STexData
;
586 td
->m_eFormat
= eSrcFormat
;
587 td
->m_eTileMode
= m_eSrcTileMode
;
588 td
->m_nWidth
= nWidth
;
589 td
->m_nHeight
= nHeight
;
590 td
->m_nDepth
= nDepth
;
592 td
->m_pData
[0] = pSrcData
;
593 if (nFlags
& FT_TAKEOVER_DATA_POINTER
)
594 td
->SetReallocated(0);
596 CreateShaderResource(std::move(td
));
600 //=======================================================
601 // High-level functions calling Create...()
603 CTexture
* CTexture::GetOrCreateTextureObject(const char* name
, uint32 nWidth
, uint32 nHeight
, int nDepth
, ETEX_Type eTT
, uint32 nFlags
, ETEX_Format eFormat
, int nCustomID
)
605 SYNCHRONOUS_LOADING_TICK();
609 MEMSTAT_CONTEXT(EMemStatContextType::Texture
, name
);
611 CTexture
* pTex
= FindOrRegisterTextureObject(name
, nFlags
, eFormat
, bFound
);
614 if (pTex
->m_nWidth
== 0)
615 pTex
->SetWidth(nWidth
);
616 if (pTex
->m_nHeight
== 0)
617 pTex
->SetHeight(nHeight
);
619 pTex
->m_nMips
= nFlags
& FT_FORCE_MIPS
? CTexture::CalcNumMips(pTex
->m_nWidth
, pTex
->m_nHeight
) : pTex
->m_nMips
;
620 pTex
->m_eFlags
|= nFlags
& (FT_DONT_RELEASE
| FT_USAGE_RENDERTARGET
| FT_USAGE_DEPTHSTENCIL
);
625 pTex
->m_nDepth
= nDepth
;
626 pTex
->SetWidth(nWidth
);
627 pTex
->SetHeight(nHeight
);
628 pTex
->m_nMips
= nFlags
& FT_FORCE_MIPS
? CTexture::CalcNumMips(pTex
->m_nWidth
, pTex
->m_nHeight
) : pTex
->m_nMips
;
630 pTex
->m_eSrcFormat
= eFormat
;
631 pTex
->m_nCustomID
= nCustomID
;
632 pTex
->m_SrcName
= name
;
633 pTex
->SetClosestFormatSupported();
638 _smart_ptr
<CTexture
> CTexture::GetOrCreateTextureObjectPtr(const char* name
, uint32 nWidth
, uint32 nHeight
, int nDepth
, ETEX_Type eTT
, uint32 nFlags
, ETEX_Format eFormat
, int nCustomID
)
640 CTexture
* pTex
= GetOrCreateTextureObject(name
, nWidth
, nHeight
, nDepth
, eTT
, nFlags
, eFormat
, nCustomID
);
641 _smart_ptr
<CTexture
> result
;
642 result
.Assign_NoAddRef(pTex
);
647 CTexture
* CTexture::GetOrCreateTextureArray(const char* name
, uint32 nWidth
, uint32 nHeight
, uint32 nArraySize
, int nMips
, ETEX_Type eType
, uint32 nFlags
, ETEX_Format eFormat
, int nCustomID
)
649 assert(eType
== eTT_2DArray
|| eType
== eTT_CubeArray
);
651 if (nArraySize
> 2048 /*D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION*/)
658 nMips
= CTexture::CalcNumMips(nWidth
, nHeight
);
660 bool sRGB
= (nFlags
& FT_USAGE_ALLOWREADSRGB
) != 0;
661 nFlags
&= ~FT_USAGE_ALLOWREADSRGB
;
663 CTexture
* pTex
= GetOrCreateTextureObject(name
, nWidth
, nHeight
, 1, eType
, nFlags
, eFormat
, nCustomID
);
665 pTex
->SetWidth(nWidth
);
666 pTex
->SetHeight(nHeight
);
667 pTex
->m_nMips
= nFlags
& FT_FORCE_MIPS
? CTexture::CalcNumMips(pTex
->m_nWidth
, pTex
->m_nHeight
) : pTex
->m_nMips
;
668 pTex
->m_nArraySize
= nArraySize
;
669 assert((eType
!= eTT_CubeArray
) || !(nArraySize
% 6));
672 if (nFlags
& FT_USAGE_RENDERTARGET
)
674 pTex
->CreateRenderTarget(eFormat
, Clr_Unknown
);
676 else if (nFlags
& FT_USAGE_DEPTHSTENCIL
)
678 pTex
->CreateDepthStencil(eFormat
, Clr_Unknown
);
682 STexDataPtr td
= new STexData
;
684 td
->m_eFormat
= eFormat
;
686 td
->m_nWidth
= nWidth
;
687 td
->m_nHeight
= nHeight
;
689 td
->m_nFlags
= sRGB
? FIM_SRGB_READ
: 0;
691 pTex
->CreateShaderResource(std::move(td
));
699 CTexture
* CTexture::GetOrCreateRenderTarget(const char* name
, uint32 nWidth
, uint32 nHeight
, const ColorF
& cClear
, ETEX_Type eTT
, uint32 nFlags
, ETEX_Format eFormat
, int nCustomID
)
701 CTexture
* pTex
= GetOrCreateTextureObject(name
, nWidth
, nHeight
, 1, eTT
, nFlags
| FT_USAGE_RENDERTARGET
, eFormat
, nCustomID
);
702 pTex
->SetWidth(nWidth
);
703 pTex
->SetHeight(nHeight
);
704 pTex
->m_nMips
= nFlags
& FT_FORCE_MIPS
? CTexture::CalcNumMips(pTex
->m_nWidth
, pTex
->m_nHeight
) : pTex
->m_nMips
;
705 pTex
->m_eFlags
|= nFlags
;
707 pTex
->CreateRenderTarget(eFormat
, cClear
);
713 _smart_ptr
<CTexture
> CTexture::GetOrCreateRenderTargetPtr(const char* name
, uint32 nWidth
, uint32 nHeight
, const ColorF
& cClear
, ETEX_Type eTT
, uint32 nFlags
, ETEX_Format eFormat
, int nCustomID
)
715 CTexture
* pTex
= GetOrCreateRenderTarget(name
, nWidth
, nHeight
, cClear
, eTT
, nFlags
, eFormat
, nCustomID
);
716 _smart_ptr
<CTexture
> result
;
717 result
.Assign_NoAddRef(pTex
);
722 CTexture
* CTexture::GetOrCreateDepthStencil(const char* name
, uint32 nWidth
, uint32 nHeight
, const ColorF
& cClear
, ETEX_Type eTT
, uint32 nFlags
, ETEX_Format eFormat
, int nCustomID
)
724 CTexture
* pTex
= GetOrCreateTextureObject(name
, nWidth
, nHeight
, 1, eTT
, nFlags
| FT_USAGE_DEPTHSTENCIL
, eFormat
, nCustomID
);
725 pTex
->SetWidth(nWidth
);
726 pTex
->SetHeight(nHeight
);
727 pTex
->m_nMips
= nFlags
& FT_FORCE_MIPS
? CTexture::CalcNumMips(pTex
->m_nWidth
, pTex
->m_nHeight
) : pTex
->m_nMips
;
728 pTex
->m_eFlags
|= nFlags
;
730 pTex
->CreateDepthStencil(eFormat
, cClear
);
736 _smart_ptr
<CTexture
> CTexture::GetOrCreateDepthStencilPtr(const char* name
, uint32 nWidth
, uint32 nHeight
, const ColorF
& cClear
, ETEX_Type eTT
, uint32 nFlags
, ETEX_Format eFormat
, int nCustomID
)
738 CTexture
* pTex
= GetOrCreateDepthStencil(name
, nWidth
, nHeight
, cClear
, eTT
, nFlags
, eFormat
, nCustomID
);
739 _smart_ptr
<CTexture
> result
;
740 result
.Assign_NoAddRef(pTex
);
745 CTexture
* CTexture::GetOrCreate2DTexture(const char* szName
, int nWidth
, int nHeight
, int nMips
, int nFlags
, const byte
* pSrcData
, ETEX_Format eSrcFormat
, bool bAsyncDevTexCreation
)
747 CRY_PROFILE_FUNCTION(PROFILE_RENDERER
);
749 CTexture
* pTex
= GetOrCreateTextureObject(szName
, nWidth
, nHeight
, 1, eTT_2D
, nFlags
, eSrcFormat
, -1);
750 pTex
->Create2DTexture(nWidth
, nHeight
, nMips
, nFlags
, pSrcData
, eSrcFormat
);
755 CTexture
* CTexture::GetOrCreate3DTexture(const char* szName
, int nWidth
, int nHeight
, int nDepth
, int nMips
, int nFlags
, const byte
* pSrcData
, ETEX_Format eSrcFormat
)
757 CTexture
* pTex
= GetOrCreateTextureObject(szName
, nWidth
, nHeight
, nDepth
, eTT_3D
, nFlags
, eSrcFormat
, -1);
758 pTex
->Create3DTexture(nWidth
, nHeight
, nDepth
, nMips
, nFlags
, pSrcData
, eSrcFormat
);
763 //=======================================================
765 // This function tries to do the minimum amount of operations for events like SysSpec changes,
766 // where it's unclear which changes in the texture's state and residency are required to get
767 // from the old to the new spec.
768 void CTexture::Refresh()
772 AbortStreamingTasks(this);
774 // Demote streamed textures to their minimum persistent mips
775 // Configuration changes will stream the texture in with the final configurations.
776 int8 nKillMip
= m_nMinMipVidUploaded
;
777 int8 nKillPersMip
= m_bForceStreamHighRes
? 0 : m_nMips
- m_CacheFileHeader
.m_nMipsPersistent
;
779 if (nKillPersMip
> nKillMip
)
781 StreamTrim(nKillPersMip
);
786 // Very difficult case, as CVars can clamp number of mips, and it's not anticipateable
787 // what the final calculated configurations for these textures are.
792 void CTexture::Reload()
794 // If the texture is flagged to not be released, we skip the reloading
795 if (m_eFlags
& FT_DONT_RELEASE
)
800 ReleaseDeviceTexture(false);
801 ToggleStreaming(true);
805 if (m_eFlags
& (FT_USAGE_RENDERTARGET
| FT_USAGE_DEPTHSTENCIL
))
807 SSubresourceData
pData(nullptr);
808 CreateDeviceTexture(std::move(pData
));
812 LoadFromImage(m_SrcName
.c_str());
819 CTexture
* CTexture::ForName(const char* name
, uint32 nFlags
, ETEX_Format eFormat
)
825 MEMSTAT_CONTEXT(EMemStatContextType::Other
, "Textures");
826 MEMSTAT_CONTEXT(EMemStatContextType::Texture
, name
);
828 CRY_DEFINE_ASSET_SCOPE("Texture", name
);
830 CTexture
* pTex
= FindOrRegisterTextureObject(name
, nFlags
, eFormat
, bFound
);
831 if (bFound
|| name
[0] == '$')
835 pTex
->m_SrcName
= name
;
839 // switch off streaming for the same texture with the same flags except DONT_STREAM
840 if ((nFlags
& FT_DONT_STREAM
) != 0 && (pTex
->GetFlags() & FT_DONT_STREAM
) == 0)
842 if (!pTex
->m_bPostponed
)
843 pTex
->ReleaseDeviceTexture(false);
844 pTex
->m_eFlags
|= FT_DONT_STREAM
;
845 if (!pTex
->m_bPostponed
)
852 pTex
->m_SrcName
= name
;
855 pTex
->m_sAssetScopeName
= gEnv
->pLog
->GetAssetScopeString();
858 if (CTexture::s_bPrecachePhase
|| (pTex
->m_eFlags
& FT_ASYNC_PREPARE
))
860 // NOTE: attached alpha isn't detectable by flags before the header is loaded, so we do it by file-suffix
861 if (/*(nFlags & FT_TEX_NORMAL_MAP) &&*/ TextureHelpers::VerifyTexSuffix(EFTT_NORMALS
, name
) && TextureHelpers::VerifyTexSuffix(EFTT_SMOOTHNESS
, name
))
862 nFlags
|= FT_HAS_ATTACHED_ALPHA
;
864 pTex
->m_eDstFormat
= eFormat
;
865 pTex
->m_eFlags
= nFlags
;
866 pTex
->m_bPostponed
= true;
867 pTex
->m_bWasUnloaded
= true;
870 if (!CTexture::s_bPrecachePhase
)
876 _smart_ptr
<CTexture
> CTexture::ForNamePtr(const char* name
, uint32 nFlags
, ETEX_Format eFormat
)
878 CTexture
* pTex
= ForName(name
, nFlags
, eFormat
);
879 _smart_ptr
<CTexture
> result
;
880 result
.Assign_NoAddRef(pTex
);
885 struct CompareTextures
887 bool operator()(const CTexture
* a
, const CTexture
* b
)
889 return (stricmp(a
->GetSourceName(), b
->GetSourceName()) < 0);
893 void CTexture::Precache(const bool isBlocking
)
895 CRY_PROFILE_FUNCTION(PROFILE_LOADING_ONLY
)(iSystem
);
897 if (!s_bPrecachePhase
)
902 gEnv
->pLog
->UpdateLoadingScreen("Requesting textures precache ...");
904 gRenDev
->ExecuteRenderThreadCommand( [isBlocking
]{ CTexture::RT_Precache(isBlocking
); },
905 ERenderCommandFlags::LevelLoadingThread_executeDirect
906 | (isBlocking
? ERenderCommandFlags::FlushAndWait
: ERenderCommandFlags::None
));
909 gEnv
->pLog
->UpdateLoadingScreen("Textures precache done.");
913 void CTexture::RT_Precache(const bool isFinalPrecache
)
915 CRY_PROFILE_FUNCTION(PROFILE_RENDERER
);
917 // Disable invalid file access logging if texture streaming is disabled
918 // If texture streaming is turned off, we will hit this on the renderthread
919 // and stall due to the invalid file access stalls
920 ICVar
* sysPakLogInvalidAccess
= NULL
;
921 int pakLogFileAccess
= 0;
922 if (!CRenderer::CV_r_texturesstreaming
)
924 if ((sysPakLogInvalidAccess
= gEnv
->pConsole
->GetCVar("sys_PakLogInvalidFileAccess")))
926 pakLogFileAccess
= sysPakLogInvalidAccess
->GetIVal();
930 #if !defined(EXCLUDE_NORMAL_LOG)
931 CTimeValue t0
= gEnv
->pTimer
->GetAsyncTime();
934 CryLog("-- Precaching textures...");
935 iLog
->UpdateLoadingScreen(0);
937 if (!gEnv
->IsEditor())
938 CryLog("=============================== Loading textures ================================");
940 // Search texture(s) in a thread-safe manner, and protect the found texture(s) from deletion
941 // Loop should block the resource-library as briefly as possible (don't call heavy stuff in the loop)
942 std::forward_list
<_smart_ptr
<CTexture
>> pFoundTextures
;
943 size_t countableTextures
= 0;
946 CryAutoReadLock
<CryRWLock
> lock(CBaseResource::s_cResLock
);
948 SResourceContainer
* pRL
= CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
951 ResourcesMapItor itor
;
952 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
954 CTexture
* pTexture
= (CTexture
*)itor
->second
;
955 if (!pTexture
|| !pTexture
->CTexture::IsPostponed())
958 pFoundTextures
.emplace_front(pTexture
);
964 // Preload all the post poned textures
966 pFoundTextures
.sort(CompareTextures());
968 gEnv
->pSystem
->GetStreamEngine()->PauseStreaming(false, 1 << eStreamTaskTypeTexture
);
970 // Trigger the texture(s)'s load without holding the resource-library lock to evade dead-locks
972 int countedTextures
= 0;
973 int numTextures
= countableTextures
;
974 int prevProgress
= 0;
977 pFoundTextures
.remove_if([&, numTextures
](_smart_ptr
<CTexture
>& pTexture
)
979 if (!pTexture
->m_bStreamPrepared
|| !pTexture
->IsStreamable())
981 pTexture
->m_fpMinMipCur
= MAX_MIP_LEVELS
<< 8;
982 pTexture
->m_bPostponed
= false;
983 pTexture
->Load(pTexture
->m_eDstFormat
);
986 int progress
= (++countedTextures
* 10) / numTextures
;
987 if (progress
!= prevProgress
)
989 prevProgress
= progress
;
990 gEnv
->pLog
->UpdateLoadingScreen("Precaching progress: %d0.0%% (%d of %d)", progress
, countedTextures
, countableTextures
);
993 // Only keep texture which really need Precache()
994 return !(pTexture
->m_bStreamed
&& pTexture
->m_bForceStreamHighRes
);
999 CTimeValue time0
= iTimer
->GetAsyncTime();
1001 while (s_StreamPrepTasks
.GetNumLive())
1003 if (gRenDev
->m_pRT
->IsRenderThread() && !gRenDev
->m_pRT
->IsRenderLoadingThread() && !gRenDev
->m_pRT
->IsLevelLoadingThread())
1005 StreamState_Update();
1006 StreamState_UpdatePrep();
1008 else if (gRenDev
->m_pRT
->IsRenderLoadingThread() || gRenDev
->m_pRT
->IsLevelLoadingThread())
1010 StreamState_UpdatePrep();
1016 SRenderStatistics::Write().m_fTexUploadTime
+= (iTimer
->GetAsyncTime() - time0
).GetSeconds();
1019 // Trigger the texture(s)'s load without holding the resource-library lock to evade dead-locks
1022 pFoundTextures
.remove_if([](_smart_ptr
<CTexture
>& pTexture
)
1024 pTexture
->m_bStreamHighPriority
|= 1;
1025 pTexture
->m_fpMinMipCur
= MAX_MIP_LEVELS
<< 8;
1027 s_pTextureStreamer
->Precache(pTexture
);
1034 if (!gEnv
->IsEditor())
1035 CryLog("========================== Finished loading textures ============================");
1037 #if !defined(EXCLUDE_NORMAL_LOG)
1038 CTimeValue t1
= gEnv
->pTimer
->GetAsyncTime();
1039 float dt
= (t1
- t0
).GetSeconds();
1040 CryLog("Precaching textures done in %.2f seconds", dt
);
1043 if (isFinalPrecache
)
1045 s_bPrecachePhase
= false;
1048 // Restore pakLogFileAccess if it was disabled during precaching
1049 // because texture precaching was disabled
1050 if (pakLogFileAccess
)
1052 sysPakLogInvalidAccess
->Set(pakLogFileAccess
);
1056 void CTexture::Load(ETEX_Format eFormat
)
1058 CRY_PROFILE_SECTION_ARG(PROFILE_LOADING_ONLY
, "CTexture::Load(ETEX_Format eTFDst)", m_SrcName
);
1059 m_bWasUnloaded
= false;
1060 m_bStreamed
= false;
1062 LoadFromImage(m_SrcName
.c_str(), eFormat
); // false=not reloading
1064 m_eFlags
|= FT_FROMIMAGE
;
1068 void CTexture::ToggleStreaming(const bool bEnable
)
1070 if (!(m_eFlags
& (FT_FROMIMAGE
| FT_DONT_RELEASE
)) || (m_eFlags
& FT_DONT_STREAM
))
1073 AbortStreamingTasks(this);
1079 ReleaseDeviceTexture(false);
1081 if (StreamPrepare(true))
1087 StreamState_ReleaseInfo(this, m_pFileTexMips
);
1088 m_pFileTexMips
= NULL
;
1091 m_bStreamed
= false;
1096 ReleaseDeviceTexture(false);
1100 void CTexture::LoadFromImage(const char* name
, ETEX_Format eFormat
)
1102 CRY_PROFILE_FUNCTION_ARG(PROFILE_LOADING_ONLY
, name
);
1104 if (CRenderer::CV_r_texnoload
&& SetNoTexture())
1107 string
sFileName(name
);
1108 sFileName
.MakeLower();
1110 m_eDstFormat
= eFormat
;
1112 // try to stream-in the texture
1116 if (StreamPrepare(true))
1118 assert(m_pDevTexture
);
1122 m_eFlags
|= FT_DONT_STREAM
;
1123 m_bStreamed
= false;
1124 m_bForceStreamHighRes
= false;
1130 StreamState_ReleaseInfo(this, m_pFileTexMips
);
1131 m_pFileTexMips
= NULL
;
1132 m_bStreamed
= false;
1138 CRY_DEFINE_ASSET_SCOPE("Texture", m_sAssetScopeName
);
1143 if (s_pTextureStreamer
->BeginPrepare(this, sFileName
, (m_eFlags
& FT_ALPHA
) ? FIM_ALPHA
: 0))
1147 uint32 nImageFlags
=
1148 ((m_eFlags
& FT_ALPHA
) ? FIM_ALPHA
: 0) |
1149 ((m_eFlags
& FT_STREAMED_PREPARE
) ? FIM_READ_VIA_STREAMS
: 0) |
1150 ((m_eFlags
& FT_DONT_STREAM
) ? FIM_IMMEDIATE_RC
: 0);
1152 Load(CImageFile::mfLoad_file(sFileName
, nImageFlags
));
1155 void CTexture::Load(CImageFilePtr
&& pImage
)
1157 if (!pImage
|| pImage
->mfGetFormat() == eTF_Unknown
)
1159 SetNoTexture(m_eTT
== eTT_Cube
? CRendererResources::s_ptexNoTextureCM
: CRendererResources::s_ptexNoTexture
);
1163 //CRY_PROFILE_SECTION_ARG(PROFILE_LOADING_ONLY, "CTexture::Load(CImageFile* pImage)", pImage->mfGet_filename().c_str());
1165 if ((m_eFlags
& FT_ALPHA
) && !pImage
->mfIs_image(0))
1167 SetNoTexture(CRendererResources::s_ptexWhite
);
1171 const char* name
= pImage
->mfGet_filename().c_str();
1172 if (pImage
->mfGet_Flags() & FIM_SPLITTED
) // propagate splitted file flag
1173 m_eFlags
|= FT_SPLITTED
;
1174 if (pImage
->mfGet_Flags() & FIM_FILESINGLE
) // propagate flag from image to texture
1175 m_eFlags
|= FT_FILESINGLE
;
1176 if (pImage
->mfGet_Flags() & FIM_NORMALMAP
)
1178 if (!(m_eFlags
& FT_TEX_NORMAL_MAP
) && !CryStringUtils::stristr(name
, "_ddn"))
1180 // becomes reported as editor error
1181 gEnv
->pSystem
->Warning(VALIDATOR_MODULE_RENDERER
, VALIDATOR_WARNING
, VALIDATOR_FLAG_FILE
| VALIDATOR_FLAG_TEXTURE
,
1182 name
, "Not a normal map texture attempted to be used as a normal map: %s", name
);
1186 if (!(m_eFlags
& FT_ALPHA
) && !(
1187 pImage
->mfGetFormat() == eTF_BC5U
|| pImage
->mfGetFormat() == eTF_BC5S
|| pImage
->mfGetFormat() == eTF_BC7
||
1188 pImage
->mfGetFormat() == eTF_EAC_RG11
|| pImage
->mfGetFormat() == eTF_EAC_RG11S
1189 ) && CryStringUtils::stristr(name
, "_ddn") != 0 && GetDevTexture()) // improvable code
1191 // becomes reported as editor error
1192 gEnv
->pSystem
->Warning(VALIDATOR_MODULE_RENDERER
, VALIDATOR_WARNING
, VALIDATOR_FLAG_FILE
| VALIDATOR_FLAG_TEXTURE
,
1193 name
, "Wrong format '%s' for normal map texture '%s'", CTexture::GetFormatName(), name
);
1196 if (pImage
->mfGet_Flags() & FIM_NOTSUPPORTS_MIPS
&& !(m_eFlags
& FT_NOMIPS
))
1197 m_eFlags
|= FT_FORCE_MIPS
;
1198 if (pImage
->mfGet_Flags() & FIM_HAS_ATTACHED_ALPHA
)
1199 m_eFlags
|= FT_HAS_ATTACHED_ALPHA
; // if the image has alpha attached we store this in the CTexture
1201 m_eSrcTileMode
= pImage
->mfGetTileMode();
1202 m_nArraySize
= pImage
->mfGet_NumSides();
1204 (pImage
->mfGet_depth() > 1) ? eTT_3D
:
1205 (pImage
->mfGet_NumSides() == 6) ? eTT_Cube
:
1206 !(pImage
->mfGet_NumSides() % 6) ? eTT_CubeArray
:
1207 (pImage
->mfGet_NumSides() == 1) ? eTT_2D
:
1210 STexDataPtr td
= new STexData
;
1212 td
->m_nFlags
= pImage
->mfGet_Flags();
1213 td
->m_nWidth
= pImage
->mfGet_width();
1214 td
->m_nHeight
= pImage
->mfGet_height();
1215 td
->m_nDepth
= pImage
->mfGet_depth();
1216 td
->m_eFormat
= pImage
->mfGetFormat();
1217 td
->m_eTileMode
= pImage
->mfGetTileMode();
1218 td
->m_nMips
= pImage
->mfGet_numMips();
1219 td
->m_fAvgBrightness
= pImage
->mfGet_avgBrightness();
1220 td
->m_cMinColor
= pImage
->mfGet_minColor();
1221 td
->m_cMaxColor
= pImage
->mfGet_maxColor();
1222 if ((m_eFlags
& FT_NOMIPS
) || td
->m_nMips
<= 0)
1224 td
->m_pFilePath
= pImage
->mfGet_filename();
1226 // base range after normalization, fe. [0,1] for 8bit images, or [0,2^15] for RGBE/HDR data
1227 if (CImageExtensionHelper::IsDynamicRange(td
->m_eFormat
))
1229 td
->m_cMinColor
/= td
->m_cMaxColor
.a
;
1230 td
->m_cMaxColor
/= td
->m_cMaxColor
.a
;
1233 // Move data-pointer from Image into TexData
1234 for (int i
= 0, j
= !pImage
->mfIs_image(1) ? 1 : 6; i
< j
; i
++)
1236 td
->AssignData(i
, pImage
->mfGet_image(i
, true));
1239 CreateShaderResource(std::move(CTexture::FormatFixup(std::move(td
))));
1242 void CTexture::UpdateData(STexDataPtr
&& td
, int flags
)
1245 m_eDstFormat
= td
->m_eFormat
;
1247 CreateShaderResource(std::move(td
));
1250 ETEX_Format
CTexture::FormatFixup(ETEX_Format eFormat
)
1256 return eTF_R8G8B8A8S
;
1260 return eTF_R8G8B8A8
;
1262 // only available as hardware format under DX11.1 with DXGI 1.2
1267 //! Only available as hardware format under Vulkan or XBO.
1271 const SPixFormat
* pPF
;
1272 return CTexture::GetClosestFormatSupported(eFormat
, pPF
);
1280 STexDataPtr
CTexture::FormatFixup(STexDataPtr
&& td
)
1282 const ETEX_Format eSrcFormat
= td
->m_eFormat
;
1283 const ETEX_Format eDstFormat
= FormatFixup(eSrcFormat
);
1284 CRY_ASSERT(eDstFormat
!= eTF_Unknown
);
1286 if (td
->m_eTileMode
== eTM_None
)
1289 uint32 nSourceSize
= CTexture::TextureDataSize(td
->m_nWidth
, td
->m_nHeight
, td
->m_nDepth
, td
->m_nMips
, 1, eSrcFormat
, eTM_None
);
1290 uint32 nTargetSize
= CTexture::TextureDataSize(td
->m_nWidth
, td
->m_nHeight
, td
->m_nDepth
, td
->m_nMips
, 1, eDstFormat
, eTM_None
);
1292 for (int nImage
= 0; nImage
< sizeof(td
->m_pData
) / sizeof(td
->m_pData
[0]); ++nImage
)
1294 if (td
->m_pData
[nImage
])
1296 byte
* pNewImage
= new byte
[nTargetSize
];
1297 CTexture::ExpandMipFromFile(pNewImage
, nTargetSize
, td
->m_pData
[nImage
], nSourceSize
, eSrcFormat
, eDstFormat
);
1298 td
->AssignData(nImage
, pNewImage
);
1302 td
->m_eFormat
= eDstFormat
;
1306 CRY_ASSERT(eDstFormat
== eSrcFormat
);
1312 STexDataPtr
CTexture::ImagePreprocessing(STexDataPtr
&& td
, ETEX_Format eDstFormat
)
1314 CRY_PROFILE_FUNCTION(PROFILE_RENDERER
);
1316 #if !defined(_RELEASE)
1317 const char* pTexFileName
= td
->m_pFilePath
? td
->m_pFilePath
: "$Unknown";
1320 if (eDstFormat
== eTF_Unknown
)
1322 // NOTE: leaks memory
1323 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;
1325 #if !defined(_RELEASE)
1326 TextureError(pTexFileName
, "Trying to process a texture with unsupported target format %s->unknown!", NameForTextureFormat(td
->m_eFormat
));
1331 const ETEX_Format eSrcFormat
= td
->m_eFormat
;
1332 const bool fmtConversionNeeded
= eSrcFormat
!= eDstFormat
;
1334 #if !CRY_PLATFORM_WINDOWS
1335 if (fmtConversionNeeded
)
1337 // NOTE: leaks memory
1338 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;
1340 #if !defined(_RELEASE)
1341 TextureError(pTexFileName
, "Trying an image format conversion from %s to %s. This is not supported on this platform!", NameForTextureFormat(eSrcFormat
), NameForTextureFormat(eDstFormat
));
1347 const bool doProcessing
= fmtConversionNeeded
;
1350 const int nSrcWidth
= td
->m_nWidth
;
1351 const int nSrcHeight
= td
->m_nHeight
;
1353 for (int i
= 0; i
< 6; i
++)
1355 if (const byte
* pSrcData
= td
->m_pData
[i
])
1357 uint32 nOutSize
= 0;
1358 const byte
* pNewData
= Convert(pSrcData
, nSrcWidth
, nSrcHeight
, td
->m_nMips
, eSrcFormat
, eDstFormat
, td
->m_nMips
, nOutSize
, true);
1360 td
->AssignData(i
, pNewData
);
1364 td
->m_eFormat
= eDstFormat
;
1371 int8
CTexture::CalcNumMips(int nWidth
, int nHeight
)
1374 while (nWidth
|| nHeight
)
1376 if (!nWidth
) nWidth
= 1;
1377 if (!nHeight
) nHeight
= 1;
1385 uint32
CTexture::TextureDataSize(uint32 nWidth
, uint32 nHeight
, uint32 nDepth
, int8 nMips
, uint32 nSlices
, const ETEX_Format eTF
, ETEX_TileMode eTM
)
1387 FUNCTION_PROFILER_RENDERER();
1389 // Don't allow 0 dimensions, it's clearly wrong to reflect on "unspecified-yet" textures.
1390 CRY_ASSERT(eTF
!= eTF_Unknown
&& nWidth
&& nHeight
&& nDepth
);
1391 // Allow 0 mips and 0 slices to generate offsets with this function.
1392 if (!nMips
|| !nSlices
)
1395 const bool bIsBlockCompressed
= IsBlockCompressed(eTF
);
1396 nWidth
= max(1U, nWidth
);
1397 nHeight
= max(1U, nHeight
);
1398 nDepth
= max(1U, nDepth
);
1400 if (eTM
!= eTM_None
)
1402 // NOTE: Using this function to acquire strides of elements or rows (and even slices in arrays),
1403 // is not yielding any usable information. In the moment the clients need to be aware that
1404 // the internal layout for tiled modes can't be interpreted and stay away from it.
1405 // TODO: Create separate interfaces for sub-resource size queries and for layout-stride queries
1407 #if CRY_PLATFORM_ORBIS
1408 if (bIsBlockCompressed
)
1410 nWidth
= ((nWidth
+ 3) & (-4));
1411 nHeight
= ((nHeight
+ 3) & (-4));
1415 #if CRY_PLATFORM_CONSOLE
1416 return CDeviceTexture::TextureDataSize(nWidth
, nHeight
, nDepth
, nMips
, nSlices
, eTF
, eTM
, CDeviceObjectFactory::BIND_SHADER_RESOURCE
);
1421 const uint32 nBytesPerElement
= bIsBlockCompressed
? BytesPerBlock(eTF
) : BytesPerPixel(eTF
);
1424 while ((nWidth
|| nHeight
|| nDepth
) && nMips
)
1426 nWidth
= max(1U, nWidth
);
1427 nHeight
= max(1U, nHeight
);
1428 nDepth
= max(1U, nDepth
);
1431 uint32 nV
= nHeight
;
1434 if (bIsBlockCompressed
)
1436 // depth is not 4x4x4 compressed, but 4x4x1
1437 nU
= ((nWidth
+ 3) / (4));
1438 nV
= ((nHeight
+ 3) / (4));
1441 nSize
+= nU
* nV
* nW
* nBytesPerElement
;
1450 return nSize
* nSlices
;
1454 bool CTexture::IsInPlaceFormat(const ETEX_Format fmt
)
1475 case eTF_R11G11B10F
:
1476 case eTF_R10G10B10A2
:
1477 case eTF_R16G16B16A16
:
1478 case eTF_R16G16B16A16S
:
1479 case eTF_R16G16B16A16F
:
1480 case eTF_R32G32B32A32F
:
1489 #if defined(CRY_DDS_DX10_SUPPORT)
1502 case eTF_ASTC_LDR_4x4
:
1512 void CTexture::ExpandMipFromFile(byte
* dst
, const uint32 dstSize
, const byte
* src
, const uint32 srcSize
, const ETEX_Format eSrcFormat
, const ETEX_Format eDstFormat
)
1514 if (IsInPlaceFormat(eSrcFormat
))
1516 assert(dstSize
== srcSize
);
1519 memcpy(dst
, src
, srcSize
);
1525 // upload mip from file with conversions depending on format and platform specifics
1528 case eTF_B8G8R8
: // -> eTF_R8G8B8A8
1529 assert(eDstFormat
== eTF_R8G8B8A8
);
1531 for (ptrdiff_t i
= ptrdiff_t(srcSize
/ 3) - 1; i
>= 0; --i
)
1533 dst
[i
* 4 + 0] = src
[i
* 3 + 2];
1534 dst
[i
* 4 + 1] = src
[i
* 3 + 1];
1535 dst
[i
* 4 + 2] = src
[i
* 3 + 0];
1536 dst
[i
* 4 + 3] = 255;
1540 case eTF_L8V8U8X8
: // -> eTF_R8G8B8A8S
1541 assert(eDstFormat
== eTF_R8G8B8A8S
);
1543 for (ptrdiff_t i
= ptrdiff_t(srcSize
/ 4) - 1; i
>= 0; --i
)
1545 dst
[i
* 4 + 0] = src
[i
* 3 + 0];
1546 dst
[i
* 4 + 1] = src
[i
* 3 + 1];
1547 dst
[i
* 4 + 2] = src
[i
* 3 + 2];
1548 dst
[i
* 4 + 3] = src
[i
* 3 + 3];
1552 case eTF_L8V8U8
: // -> eTF_R8G8B8A8S
1553 assert(eDstFormat
== eTF_R8G8B8A8S
);
1555 for (ptrdiff_t i
= ptrdiff_t(srcSize
/ 3) - 1; i
>= 0; --i
)
1557 dst
[i
* 4 + 0] = src
[i
* 3 + 0];
1558 dst
[i
* 4 + 1] = src
[i
* 3 + 1];
1559 dst
[i
* 4 + 2] = src
[i
* 3 + 2];
1560 dst
[i
* 4 + 3] = 255;
1564 case eTF_L8
: // -> eTF_R8G8B8A8
1565 assert(eDstFormat
== eTF_R8G8B8A8
);
1567 for (ptrdiff_t i
= ptrdiff_t(srcSize
) - 1; i
>= 0; --i
)
1569 const byte bSrc
= src
[i
];
1570 dst
[i
* 4 + 0] = bSrc
;
1571 dst
[i
* 4 + 1] = bSrc
;
1572 dst
[i
* 4 + 2] = bSrc
;
1573 dst
[i
* 4 + 3] = 255;
1577 case eTF_A8L8
: // -> eTF_R8G8B8A8
1578 assert(eDstFormat
== eTF_R8G8B8A8
);
1580 for (ptrdiff_t i
= ptrdiff_t(srcSize
) - 1; i
>= 0; i
-= 2)
1582 const byte bSrcL
= src
[i
- 1];
1583 const byte bSrcA
= src
[i
- 0];
1584 dst
[i
* 4 + 0] = bSrcL
;
1585 dst
[i
* 4 + 1] = bSrcL
;
1586 dst
[i
* 4 + 2] = bSrcL
;
1587 dst
[i
* 4 + 3] = bSrcA
;
1592 case eTF_B5G5R5A1
: // -> eTF_B8G8R8A8
1593 assert(eDstFormat
== eTF_B8G8R8A8
);
1595 for (ptrdiff_t i
= ptrdiff_t(srcSize
/ 2) - 1; i
>= 0; --i
)
1597 const uint16 rgb5551
= uint16((src
[i
* 2 + 0] << 8) + src
[i
* 2 + 1]);
1598 dst
[i
* 4 + 0] = ((rgb5551
>> 0) * 33) >> 2;
1599 dst
[i
* 4 + 1] = ((rgb5551
>> 5) * 33) >> 2;
1600 dst
[i
* 4 + 2] = ((rgb5551
>> 10) * 33) >> 2;
1601 dst
[i
* 4 + 3] = ((rgb5551
>> 15) ? 255 : 0);
1605 case eTF_B5G6R5
: // -> eTF_B8G8R8X8
1606 assert(eDstFormat
== eTF_B8G8R8X8
);
1608 for (ptrdiff_t i
= ptrdiff_t(srcSize
/ 2) - 1; i
>= 0; --i
)
1610 const uint16 rgb565
= uint16((src
[i
* 2 + 0] << 8) + src
[i
* 2 + 1]);
1611 dst
[i
* 4 + 0] = ((rgb565
>> 0) * 33) >> 2;
1612 dst
[i
* 4 + 1] = ((rgb565
>> 5) * 65) >> 4;
1613 dst
[i
* 4 + 2] = ((rgb565
>> 11) * 33) >> 2;
1614 dst
[i
* 4 + 3] = 255;
1618 case eTF_B4G4R4A4
: // -> eTF_B8G8R8A8
1619 case eTF_R4G4B4A4
: // -> eTF_R8G8B8A8
1620 assert((eSrcFormat
== eTF_B4G4R4A4
&& eDstFormat
== eTF_B8G8R8A8
) ||
1621 (eSrcFormat
== eTF_R4G4B4A4
&& eDstFormat
== eTF_R8G8B8A8
));
1623 for (ptrdiff_t i
= ptrdiff_t(srcSize
/ 2) - 1; i
>= 0; --i
)
1625 const uint16 rgb4444
= uint16((src
[i
* 2 + 0] << 8) + src
[i
* 2 + 1]);
1626 dst
[i
* 4 + 0] = (rgb4444
>> 0) * 17;
1627 dst
[i
* 4 + 1] = (rgb4444
>> 4) * 17;
1628 dst
[i
* 4 + 2] = (rgb4444
>> 8) * 17;
1629 dst
[i
* 4 + 3] = (rgb4444
>> 12) * 17;
1633 case eTF_R4G4
: // -> eTF_R8G8|eTF_R8G8B8A8
1634 assert(eDstFormat
== eTF_R8G8
|| eDstFormat
== eTF_R8G8B8A8
);
1635 if (eDstFormat
== eTF_R8G8
)
1637 for (ptrdiff_t i
= ptrdiff_t(srcSize
/ 1) - 1; i
>= 0; --i
)
1639 const uint8 rgb44
= uint8(src
[i
* 1 + 0]);
1640 dst
[i
* 2 + 0] = (rgb44
>> 0) * 17;
1641 dst
[i
* 2 + 1] = (rgb44
>> 4) * 17;
1646 for (ptrdiff_t i
= ptrdiff_t(srcSize
/ 1) - 1; i
>= 0; --i
)
1648 const uint8 rgb44
= uint8(src
[i
* 1 + 0]);
1649 dst
[i
* 4 + 0] = (rgb44
>> 0) * 17;
1650 dst
[i
* 4 + 1] = (rgb44
>> 4) * 17;
1652 dst
[i
* 4 + 3] = 255;
1662 bool CTexture::Invalidate(int nNewWidth
, int nNewHeight
, ETEX_Format eNewFormat
)
1664 bool bRelease
= false;
1665 if (nNewWidth
> 0 && nNewWidth
!= m_nWidth
)
1667 m_nWidth
= nNewWidth
;
1670 if (nNewHeight
> 0 && nNewHeight
!= m_nHeight
)
1672 m_nHeight
= nNewHeight
;
1675 if (eNewFormat
!= eTF_Unknown
&& eNewFormat
!= m_eSrcFormat
)
1677 m_eSrcFormat
= eNewFormat
;
1678 SetClosestFormatSupported();
1688 if (m_eFlags
& FT_FORCE_MIPS
)
1691 ReleaseDeviceTexture(true);
1697 D3DBaseView
* CTexture::GetResourceView(const SResourceView
& rvDesc
)
1699 if (CDeviceTexture
* pDevTex
= GetDevTexture(rvDesc
.m_Desc
.bMultisample
))
1701 ResourceViewHandle hView
= pDevTex
->GetOrCreateResourceViewHandle(rvDesc
);
1702 return pDevTex
->LookupResourceView(hView
).second
;
1708 D3DBaseView
* CTexture::GetResourceView(const SResourceView
& rvDesc
) const
1710 if (CDeviceTexture
* pDevTex
= GetDevTexture(rvDesc
.m_Desc
.bMultisample
))
1712 ResourceViewHandle hView
= pDevTex
->GetResourceViewHandle(rvDesc
);
1713 if (hView
!= ResourceViewHandle::Unspecified
)
1714 return pDevTex
->LookupResourceView(hView
).second
;
1720 void CTexture::SetResourceView(const SResourceView
& rvDesc
, D3DBaseView
* pView
)
1722 if (CDeviceTexture
* pDevTex
= GetDevTexture(rvDesc
.m_Desc
.bMultisample
))
1724 ResourceViewHandle hView
= pDevTex
->GetResourceViewHandle(rvDesc
);
1725 if (hView
!= ResourceViewHandle::Unspecified
)
1727 SAFE_RELEASE(pDevTex
->LookupResourceView(hView
).second
);
1729 pDevTex
->LookupResourceView(hView
).second
= pView
;
1730 pDevTex
->LookupResourceView(hView
).second
->AddRef();
1735 void CTexture::SetDefaultShaderResourceView(D3DBaseView
* pDeviceShaderResource
, bool bMultisampled
/*= false*/)
1737 CDeviceTexture
* pDevTex
= GetDevTexture(bMultisampled
&& IsMSAA());
1739 SAFE_RELEASE(pDevTex
->LookupResourceView(EDefaultResourceViews::Default
).second
);
1741 pDevTex
->LookupResourceView(EDefaultResourceViews::Default
).second
= pDeviceShaderResource
;
1742 pDevTex
->LookupResourceView(EDefaultResourceViews::Default
).second
->AddRef();
1744 // Notify that resource is dirty
1745 if (!(m_eFlags
& FT_USAGE_RENDERTARGET
))
1747 InvalidateDeviceResource(this, eDeviceResourceViewDirty
);
1751 byte
* CTexture::GetData32(int nSide
, int nLevel
, byte
* pDstData
, ETEX_Format eDstFormat
)
1753 #if CRY_PLATFORM_WINDOWS
1754 // NOTE: the function will not maintain any dirty state and always download the data, don't use it in the render-loop
1755 CDeviceTexture
* pDevTexture
= GetDevTexture();
1756 pDevTexture
->DownloadToStagingResource(D3D11CalcSubresource(nLevel
, nSide
, m_nMips
), [&](void* pData
, uint32 rowPitch
, uint32 slicePitch
)
1758 if (m_eDstFormat
!= eTF_R8G8B8A8
)
1760 uint32 nOutSize
= 0;
1762 if (m_eSrcFormat
== eDstFormat
&& pDstData
)
1764 memcpy(pDstData
, pData
, GetDeviceDataSize());
1768 pDstData
= (byte
*)Convert((byte
*)pData
, m_nWidth
, m_nHeight
, 1, m_eSrcFormat
, eDstFormat
, 1, nOutSize
, true);
1775 pDstData
= new byte
[m_nWidth
* m_nHeight
* 4];
1778 memcpy(pDstData
, pData
, m_nWidth
* m_nHeight
* 4);
1790 const size_t CTexture::GetAllocatedSystemMemory(bool bIncludePool
, bool bIncludeCache
) const
1792 size_t nSize
= sizeof(*this);
1793 nSize
+= m_SrcName
.capacity();
1795 // TODO: neccessary?
1796 // if (m_pRenderTargetData)
1798 // nSize += sizeof(*m_pRenderTargetData);
1799 // nSize += m_pRenderTargetData->m_DirtyRects.capacity() * sizeof(RECT);
1805 nSize
+= m_pFileTexMips
->GetAllocatedSystemMemory(m_nMips
, m_CacheFileHeader
.m_nSides
);
1806 if (bIncludePool
&& m_pFileTexMips
->m_pPoolItem
)
1807 nSize
+= m_pFileTexMips
->m_pPoolItem
->GetAllocatedSystemMemory();
1813 void CTexture::Init()
1815 SDynTexture::Init();
1819 void CTexture::PostInit()
1821 CRY_PROFILE_FUNCTION(PROFILE_LOADING_ONLY
);
1824 int __cdecl
TexCallback(const VOID
* arg1
, const VOID
* arg2
)
1826 CTexture
** pi1
= (CTexture
**)arg1
;
1827 CTexture
** pi2
= (CTexture
**)arg2
;
1828 CTexture
* ti1
= *pi1
;
1829 CTexture
* ti2
= *pi2
;
1831 if (ti1
->GetDeviceDataSize() > ti2
->GetDeviceDataSize())
1833 if (ti1
->GetDeviceDataSize() < ti2
->GetDeviceDataSize())
1835 return stricmp(ti1
->GetSourceName(), ti2
->GetSourceName());
1838 int __cdecl
TexCallbackMips(const VOID
* arg1
, const VOID
* arg2
)
1840 CTexture
** pi1
= (CTexture
**)arg1
;
1841 CTexture
** pi2
= (CTexture
**)arg2
;
1842 CTexture
* ti1
= *pi1
;
1843 CTexture
* ti2
= *pi2
;
1847 nSize1
= ti1
->GetActualSize();
1848 nSize2
= ti2
->GetActualSize();
1850 if (nSize1
> nSize2
)
1852 if (nSize1
< nSize2
)
1854 return stricmp(ti1
->GetSourceName(), ti2
->GetSourceName());
1857 void CTexture::Update()
1859 FUNCTION_PROFILER_RENDERER();
1861 // reload pending texture reload requests
1863 std::set
<string
> queue
;
1865 s_xTexReloadLock
.Lock();
1866 s_vTexReloadRequests
.swap(queue
);
1867 s_xTexReloadLock
.Unlock();
1870 for (std::set
<string
>::iterator i
= queue
.begin(); i
!= queue
.end(); ++i
)
1874 CTexture::s_bStreamingFromHDD
= gEnv
->pSystem
->GetStreamEngine()->IsStreamDataOnHDD();
1875 CTexture::s_nStatsStreamPoolInUseMem
= CTexture::s_pPoolMgr
->GetInUseSize();
1877 s_pTextureStreamer
->ApplySchedule(ITextureStreamer::eASF_Full
);
1878 s_pTextureStreamer
->BeginUpdateSchedule();
1880 #ifdef ENABLE_TEXTURE_STREAM_LISTENER
1881 StreamUpdateStats();
1884 SDynTexture::Tick();
1886 if ((s_nStreamingMode
!= CRenderer::CV_r_texturesstreaming
) || (s_nStreamingUpdateMode
!= CRenderer::CV_r_texturesstreamingUpdateType
))
1891 #ifndef CONSOLE_CONST_CVAR_MODE
1894 if (CRenderer::CV_r_texlog
)
1896 CryAutoReadLock
<CryRWLock
> lock(CBaseResource::s_cResLock
);
1898 SResourceContainer
* pRL
= CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
1899 ResourcesMapItor itor
;
1902 if (pRL
&& (CRenderer::CV_r_texlog
== 2 || CRenderer::CV_r_texlog
== 3 || CRenderer::CV_r_texlog
== 4))
1905 TArray
<CTexture
*> Texs
;
1908 if (CRenderer::CV_r_texlog
== 2 || CRenderer::CV_r_texlog
== 3)
1910 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
1912 CTexture
* tp
= (CTexture
*)itor
->second
;
1913 if (CRenderer::CV_r_texlog
== 3 && tp
->IsNoTexture())
1917 else if (CRenderer::CV_r_texlog
== 2 && !tp
->IsNoTexture() && tp
->m_pFileTexMips
) // (tp->GetFlags() & FT_FROMIMAGE))
1922 if (CRenderer::CV_r_texlog
== 3)
1924 CryLogAlways("Logging to MissingTextures.txt...");
1925 fp
= fxopen("MissingTextures.txt", "w");
1929 CryLogAlways("Logging to UsedTextures.txt...");
1930 fp
= fxopen("UsedTextures.txt", "w");
1932 fprintf(fp
, "*** All textures: ***\n");
1935 qsort(&Texs
[0], Texs
.Num(), sizeof(CTexture
*), TexCallbackMips
);
1937 for (i
= 0; i
< Texs
.Num(); i
++)
1939 int w
= Texs
[i
]->GetWidth();
1940 int h
= Texs
[i
]->GetHeight();
1942 size_t nTSize
= Texs
[i
]->m_pFileTexMips
->GetAllocatedSystemMemory(Texs
[i
]->GetNumMips(), Texs
[i
]->GetNumSides());
1944 fprintf(fp
, "%" PRISIZE_T
"\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());
1945 //Size += Texs[i]->GetDataSize();
1948 PartSize
+= Texs
[i
]->GetDeviceDataSize();
1950 fprintf(fp
, "*** Total Size: %d\n\n", Size
/*, PartSize, PartSize */);
1954 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
1956 CTexture
* tp
= (CTexture
*)itor
->second
;
1957 if (tp
->m_nAccessFrameID
== gRenDev
->GetMainFrameID())
1969 fp
= fxopen("UsedTextures_Frame.txt", "w");
1972 fprintf(fp
, "\n\n*** Textures used in current frame: ***\n");
1974 IRenderAuxText::TextToScreenColor(4, 13, 1, 1, 0, 1, "*** Textures used in current frame: ***");
1978 qsort(&Texs
[0], Texs
.Num(), sizeof(CTexture
*), TexCallback
);
1981 for (i
= 0; i
< Texs
.Num(); i
++)
1984 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());
1987 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());
1988 IRenderAuxText::TextToScreenColor(4, nY
, 0, 1, 0, 1, buf
);
1991 PartSize
+= Texs
[i
]->GetDeviceDataSize();
1992 Size
+= Texs
[i
]->GetDataSize();
1996 fprintf(fp
, "*** Total Size: %.3fMb, Device Size: %.3fMb\n\n", Size
/ (1024.0f
* 1024.0f
), PartSize
/ (1024.0f
* 1024.0f
));
2000 cry_sprintf(buf
, "*** Total Size: %.3fMb, Device Size: %.3fMb", Size
/ (1024.0f
* 1024.0f
), PartSize
/ (1024.0f
* 1024.0f
));
2001 IRenderAuxText::TextToScreenColor(4, nY
+ 1, 0, 1, 1, 1, buf
);
2005 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
2007 CTexture
* tp
= (CTexture
*)itor
->second
;
2008 if (tp
&& !tp
->IsNoTexture())
2019 fp
= fxopen("UsedTextures_All.txt", "w");
2022 fprintf(fp
, "\n\n*** All Existing Textures: ***\n");
2024 IRenderAuxText::TextToScreenColor(4, 13, 1, 1, 0, 1, "*** Textures loaded: ***");
2027 qsort(&Texs
[0], Texs
.Num(), sizeof(CTexture
*), TexCallback
);
2030 for (i
= 0; i
< Texs
.Num(); i
++)
2034 int w
= Texs
[i
]->GetWidth();
2035 int h
= Texs
[i
]->GetHeight();
2036 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());
2040 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());
2041 IRenderAuxText::TextToScreenColor(4, nY
, 0, 1, 0, 1, buf
);
2044 Size
+= Texs
[i
]->GetDeviceDataSize();
2048 fprintf(fp
, "*** Total Size: %.3fMb\n\n", Size
/ (1024.0f
* 1024.0f
));
2052 cry_sprintf(buf
, "*** Total Size: %.3fMb", Size
/ (1024.0f
* 1024.0f
));
2053 IRenderAuxText::TextToScreenColor(4, nY
+ 1, 0, 1, 1, 1, buf
);
2057 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
2059 CTexture
* tp
= (CTexture
*)itor
->second
;
2060 if (tp
&& !tp
->IsNoTexture() && !tp
->IsStreamed())
2072 if (CRenderer::CV_r_texlog
!= 4)
2073 CRenderer::CV_r_texlog
= 0;
2075 else if (pRL
&& (CRenderer::CV_r_texlog
== 1))
2077 //char *str = GetTexturesStatusText();
2079 TArray
<CTexture
*> Texs
;
2080 //TArray<CTexture *> TexsNM;
2081 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
2083 CTexture
* tp
= (CTexture
*)itor
->second
;
2084 if (tp
&& !tp
->IsNoTexture())
2087 //if (tp->GetFlags() & FT_TEX_NORMAL_MAP)
2088 // TexsNM.AddElem(tp);
2093 qsort(&Texs
[0], Texs
.Num(), sizeof(CTexture
*), TexCallback
);
2098 int64 NonStrSize
= 0;
2101 int64 SizeDynCom
= 0;
2102 int64 SizeDynAtl
= 0;
2103 int64 PartSizeNM
= 0;
2106 int nNumTexDynAtl
= 0;
2107 int nNumTexDynCom
= 0;
2108 for (i
= 0; i
< Texs
.Num(); i
++)
2110 CTexture
* tex
= Texs
[i
];
2111 const uint32 texFlags
= tex
->GetFlags();
2112 const int texDataSize
= tex
->GetDataSize();
2113 const int texDeviceDataSize
= tex
->GetDeviceDataSize();
2115 if (tex
->GetDevTexture() && !(texFlags
& FT_USAGE_RENDERTARGET
))
2117 AllSize
+= texDataSize
;
2118 if (!Texs
[i
]->IsStreamed())
2120 NonStrSize
+= texDataSize
;
2125 if (texFlags
& FT_USAGE_RENDERTARGET
)
2127 if (texFlags
& FT_USAGE_ATLAS
)
2130 SizeDynAtl
+= texDataSize
;
2135 SizeDynCom
+= texDataSize
;
2138 else if (0 == (texFlags
& FT_TEX_NORMAL_MAP
))
2140 if (!Texs
[i
]->IsUnloaded())
2143 Size
+= texDataSize
;
2144 PartSize
+= texDeviceDataSize
;
2149 if (!Texs
[i
]->IsUnloaded())
2152 SizeNM
+= texDataSize
;
2153 PartSizeNM
+= texDeviceDataSize
;
2158 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));
2159 IRenderAuxText::TextToScreenColor(4, 13, 1, 1, 0, 1, buf
);
2160 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));
2161 IRenderAuxText::TextToScreenColor(4, 16, 1, 1, 0, 1, buf
);
2162 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));
2163 IRenderAuxText::TextToScreenColor(4, 19, 1, 1, 0, 1, buf
);
2164 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));
2165 IRenderAuxText::TextToScreenColor(4, 22, 1, 1, 0, 1, buf
);
2168 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
2170 CTexture
* tp
= (CTexture
*)itor
->second
;
2171 if (tp
&& !tp
->IsNoTexture() && tp
->m_nAccessFrameID
== gRenDev
->GetMainFrameID())
2178 qsort(&Texs
[0], Texs
.Num(), sizeof(CTexture
*), TexCallback
);
2185 for (i
= 0; i
< Texs
.Num(); i
++)
2187 Size
+= Texs
[i
]->GetDataSize();
2188 if (Texs
[i
]->GetFlags() & FT_USAGE_RENDERTARGET
)
2190 if (Texs
[i
]->GetFlags() & FT_USAGE_ATLAS
)
2191 SizeDynAtl
+= Texs
[i
]->GetDataSize();
2193 SizeDynCom
+= Texs
[i
]->GetDataSize();
2196 PartSize
+= Texs
[i
]->GetDeviceDataSize();
2197 if (!Texs
[i
]->IsStreamed())
2198 NonStrSize
+= Texs
[i
]->GetDataSize();
2200 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
));
2201 IRenderAuxText::TextToScreenColor(4, 27, 1, 0, 0, 1, buf
);
2207 void CTexture::RT_LoadingUpdate()
2209 CTexture::s_bStreamingFromHDD
= gEnv
->pSystem
->GetStreamEngine()->IsStreamDataOnHDD();
2210 CTexture::s_nStatsStreamPoolInUseMem
= CTexture::s_pPoolMgr
->GetInUseSize();
2212 ITextureStreamer::EApplyScheduleFlags asf
= CTexture::s_bPrecachePhase
2213 ? ITextureStreamer::eASF_InOut
// Exclude the prep update, as it will be done by the RLT (and can be expensive)
2214 : ITextureStreamer::eASF_Full
;
2216 s_pTextureStreamer
->ApplySchedule(asf
);
2219 void CTexture::RLT_LoadingUpdate()
2221 s_pTextureStreamer
->BeginUpdateSchedule();
2224 //=========================================================================
2226 void CTexture::ShutDown()
2228 RT_FlushAllStreamingTasks(true);
2230 if (s_pStatsTexWantedLists
)
2232 for (int i
= 0; i
< 2; ++i
)
2233 s_pStatsTexWantedLists
[i
].clear();
2236 if (CRenderer::CV_r_releaseallresourcesonexit
)
2238 SResourceContainer
* pRL
= CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2242 ResourcesMapItor itor
;
2243 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); )
2245 CTexture
* pTX
= (CTexture
*)itor
->second
;
2249 if (CRenderer::CV_r_printmemoryleaks
)
2250 iLog
->Log("Warning: CTexture::ShutDown: Texture %s was not deleted (%d)", pTX
->GetName(), pTX
->GetRefCounter());
2251 SAFE_RELEASE_FORCE(pTX
);
2257 s_pPoolMgr
->Flush();
2260 void CTexture::ReloadFile_Request(const char* szFileName
)
2262 s_xTexReloadLock
.Lock();
2263 s_vTexReloadRequests
.insert(szFileName
);
2264 s_xTexReloadLock
.Unlock();
2267 void CTexture::ReloadFile(const char* szFileName
) threadsafe
2269 FUNCTION_PROFILER_RENDERER();
2271 char gameFolderPath
[256];
2272 cry_strcpy(gameFolderPath
, PathUtil::GetGameFolder());
2273 PREFAST_SUPPRESS_WARNING(6054); // it is nullterminated
2274 int gameFolderPathLength
= strlen(gameFolderPath
);
2275 if (gameFolderPathLength
> 0 && gameFolderPath
[gameFolderPathLength
- 1] == '\\')
2277 gameFolderPath
[gameFolderPathLength
- 1] = '/';
2279 else if (gameFolderPathLength
> 0 && gameFolderPath
[gameFolderPathLength
- 1] != '/')
2281 gameFolderPath
[gameFolderPathLength
++] = '/';
2282 gameFolderPath
[gameFolderPathLength
] = 0;
2285 string realName
= PathUtil::ToUnixPath(szFileName
);
2286 if (realName
.size() >= (uint32
)gameFolderPathLength
&& memcmp(realName
.data(), gameFolderPath
, gameFolderPathLength
) == 0)
2287 realName
+= gameFolderPathLength
;
2289 CCryNameTSCRC crc32NameBase
= GenName(realName
, 0);
2290 CCryNameTSCRC crc32NameAtch
= GenName(realName
, FT_ALPHA
);
2292 // Search texture in a thread-safe manner, and protect the found texture from deletion
2293 _smart_ptr
<CTexture
> pFoundTextureBase
= nullptr;
2294 _smart_ptr
<CTexture
> pFoundTextureAtch
= nullptr;
2297 CryAutoReadLock
<CryRWLock
> lock(s_cResLock
);
2299 SResourceContainer
* pRL
= CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2302 const auto& itorBase
= pRL
->m_RMap
.find(crc32NameBase
);
2303 const auto& itorAtch
= pRL
->m_RMap
.find(crc32NameAtch
);
2305 if (itorBase
!= pRL
->m_RMap
.end())
2306 pFoundTextureBase
= (CTexture
*)itorBase
->second
;
2307 if (itorAtch
!= pRL
->m_RMap
.end())
2308 pFoundTextureAtch
= (CTexture
*)itorAtch
->second
;
2312 // Trigger the texture's reload without holding the resource-library lock to evade dead-locks
2313 if (pFoundTextureBase
)
2314 pFoundTextureBase
->Reload();
2315 if (pFoundTextureAtch
)
2316 pFoundTextureAtch
->Reload();
2319 void CTexture::ReloadTextures() threadsafe
2321 gRenDev
->ExecuteRenderThreadCommand([]{ CTexture::RT_ReloadTextures(); }, ERenderCommandFlags::LevelLoadingThread_executeDirect
);
2324 void CTexture::RT_ReloadTextures()
2326 FUNCTION_PROFILER_RENDERER();
2328 // Flush any outstanding texture requests before reloading
2329 CTexture::RT_FlushStreaming(true);
2331 std::forward_list
<_smart_ptr
<CTexture
>> pFoundTextures
;
2333 // Search texture(s) in a thread-safe manner, and protect the found texture(s) from deletion
2334 // Loop should block the resource-library as briefly as possible (don't call heavy stuff in the loop)
2336 CryAutoReadLock
<CryRWLock
> lock(CBaseResource::s_cResLock
);
2338 SResourceContainer
* pRL
= CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2341 ResourcesMapItor itor
;
2342 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
2344 CTexture
* pTexture
= (CTexture
*)itor
->second
;
2345 if (!pTexture
|| !(pTexture
->m_eFlags
& FT_FROMIMAGE
))
2348 pFoundTextures
.emplace_front(pTexture
);
2353 // Trigger the texture(s)'s reload without holding the resource-library lock to evade dead-locks
2356 pFoundTextures
.remove_if([](_smart_ptr
<CTexture
>& pTexture
) { pTexture
->Reload(); return true; });
2360 void CTexture::RefreshTextures() threadsafe
2362 gRenDev
->ExecuteRenderThreadCommand([]{ CTexture::RT_RefreshTextures(); }, ERenderCommandFlags::LevelLoadingThread_executeDirect
);
2365 void CTexture::RT_RefreshTextures()
2367 FUNCTION_PROFILER_RENDERER();
2369 // Flush any outstanding texture requests before reloading
2370 CTexture::RT_FlushStreaming(true);
2372 std::forward_list
<_smart_ptr
<CTexture
>> pFoundTextures
;
2374 // Search texture(s) in a thread-safe manner, and protect the found texture(s) from deletion
2375 // Loop should block the resource-library as briefly as possible (don't call heavy stuff in the loop)
2377 CryAutoReadLock
<CryRWLock
> lock(CBaseResource::s_cResLock
);
2379 SResourceContainer
* pRL
= CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2382 ResourcesMapItor itor
;
2383 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
2385 CTexture
* pTexture
= (CTexture
*)itor
->second
;
2386 if (!pTexture
|| !(pTexture
->m_eFlags
& FT_FROMIMAGE
))
2389 pFoundTextures
.emplace_front(pTexture
);
2394 // Trigger the texture(s)'s refresh without holding the resource-library lock to evade dead-locks
2397 pFoundTextures
.remove_if([](_smart_ptr
<CTexture
>& pTexture
) { pTexture
->Refresh(); return true; });
2401 void CTexture::ToggleTexturesStreaming() threadsafe
2403 gRenDev
->ExecuteRenderThreadCommand([]{ CTexture::RT_ToggleTexturesStreaming(); }, ERenderCommandFlags::LevelLoadingThread_executeDirect
);
2406 void CTexture::RT_ToggleTexturesStreaming()
2408 FUNCTION_PROFILER_RENDERER();
2410 // Flush any outstanding texture requests before reloading
2411 CTexture::RT_FlushStreaming(true);
2413 std::forward_list
<_smart_ptr
<CTexture
>> pFoundTextures
;
2415 // Search texture(s) in a thread-safe manner, and protect the found texture(s) from deletion
2416 // Loop should block the resource-library as briefly as possible (don't call heavy stuff in the loop)
2418 CryAutoReadLock
<CryRWLock
> lock(CBaseResource::s_cResLock
);
2420 SResourceContainer
* pRL
= CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2423 ResourcesMapItor itor
;
2424 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
2426 CTexture
* pTexture
= (CTexture
*)itor
->second
;
2427 if (!pTexture
|| !(pTexture
->m_eFlags
& FT_FROMIMAGE
))
2430 pFoundTextures
.emplace_front(pTexture
);
2435 // Trigger the texture(s)'s reload without holding the resource-library lock to evade dead-locks
2438 pFoundTextures
.remove_if([](_smart_ptr
<CTexture
>& pTexture
) { pTexture
->ToggleStreaming(CRenderer::CV_r_texturesstreaming
!= 0); return true; });
2442 void CTexture::LogTextures(ILog
* pLog
) threadsafe
2444 std::forward_list
<_smart_ptr
<CTexture
>> pFoundTextures
;
2446 // Search texture(s) in a thread-safe manner, and protect the found texture(s) from deletion
2447 // Loop should block the resource-library as briefly as possible (don't call heavy stuff in the loop)
2449 CryAutoReadLock
<CryRWLock
> lock(CBaseResource::s_cResLock
);
2451 SResourceContainer
* pRL
= CBaseResource::GetResourcesForClass(CTexture::mfGetClassName());
2454 ResourcesMapItor itor
;
2455 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
2457 CTexture
* pTexture
= (CTexture
*)itor
->second
;
2460 const char* pName
= pTexture
->GetName();
2461 if (!pName
|| strchr(pName
, '/'))
2464 pFoundTextures
.emplace_front(pTexture
);
2469 // Trigger the texture(s)'s reload without holding the resource-library lock to evade dead-locks
2471 pFoundTextures
.remove_if([](_smart_ptr
<CTexture
>& pTexture
) { iLog
->Log("\t%s -- fmt: %s, dim: %d x %d\n", pTexture
->GetName(), pTexture
->GetFormatName(), pTexture
->GetWidth(), pTexture
->GetHeight()); return true; });
2475 bool CTexture::SetNoTexture(CTexture
* pDefaultTexture
/* = s_ptexNoTexture*/)
2477 m_eFlags
|= FT_FAILED
;
2479 if (pDefaultTexture
)
2481 RefDevTexture(pDefaultTexture
->GetDevTexture());
2483 m_eSrcFormat
= pDefaultTexture
->GetSrcFormat();
2484 m_eDstFormat
= pDefaultTexture
->GetDstFormat();
2485 m_nMips
= pDefaultTexture
->GetNumMips();
2486 m_nWidth
= pDefaultTexture
->GetWidth();
2487 m_nHeight
= pDefaultTexture
->GetHeight();
2489 m_fAvgBrightness
= 1.0f
;
2492 m_cClearColor
= ColorF(0.0f
, 0.0f
, 0.0f
, 1.0f
);
2494 m_bNoTexture
= true;
2498 StreamState_ReleaseInfo(this, m_pFileTexMips
);
2499 m_pFileTexMips
= NULL
;
2502 m_bStreamed
= false;
2503 m_bPostponed
= false;
2505 m_nDevTextureSize
= 0;
2506 m_nPersistentSize
= 0;
2514 //////////////////////////////////////////////////////////////////////////
2515 const char* CTexture::GetFormatName() const
2517 return NameForTextureFormat(GetDstFormat());
2520 //////////////////////////////////////////////////////////////////////////
2521 const char* CTexture::GetTypeName() const
2523 return NameForTextureType(GetTextureType());
2526 struct FlashTextureSourceSharedRT_AutoUpdate
2529 static void Add(CFlashTextureSourceBase
* pSrc
)
2531 CryAutoCriticalSection
lock(ms_lock
);
2532 stl::push_back_unique(ms_sources
, pSrc
);
2535 static void AddToLightList(CFlashTextureSourceBase
* pSrc
)
2537 if (stl::find(ms_LightTextures
, pSrc
)) return;
2538 ms_LightTextures
.push_back(pSrc
);
2541 static void Remove(CFlashTextureSourceBase
* pSrc
)
2543 CryAutoCriticalSection
lock(ms_lock
);
2545 const size_t size
= ms_sources
.size();
2546 for (size_t i
= 0; i
< size
; ++i
)
2548 if (ms_sources
[i
] == pSrc
)
2550 ms_sources
[i
] = ms_sources
[size
- 1];
2551 ms_sources
.pop_back();
2552 if (ms_sources
.empty())
2554 stl::reconstruct(ms_sources
);
2559 stl::find_and_erase(ms_LightTextures
, pSrc
);
2564 SRenderThread
* pRT
= gRenDev
->m_pRT
;
2565 if (!pRT
|| (pRT
->IsMainThread() && pRT
->m_eVideoThreadMode
== SRenderThread::eVTM_Disabled
))
2567 CTimeValue curTime
= gEnv
->pTimer
->GetAsyncTime();
2568 const int frameID
= gRenDev
->GetMainFrameID();
2569 if (ms_lastTickFrameID
!= frameID
)
2571 CryAutoCriticalSection
lock(ms_lock
);
2573 const float deltaTime
= gEnv
->pTimer
->GetFrameTime();
2574 const bool isEditing
= gEnv
->IsEditing();
2575 const bool isPaused
= gEnv
->pSystem
->IsPaused();
2577 const size_t size
= ms_sources
.size();
2578 for (size_t i
= 0; i
< size
; ++i
)
2580 ms_sources
[i
]->AutoUpdate(curTime
, deltaTime
, isEditing
, isPaused
);
2583 ms_lastTickFrameID
= frameID
;
2588 static void TickRT()
2590 SRenderThread
* pRT
= gRenDev
->m_pRT
;
2591 if (!pRT
|| (pRT
->IsRenderThread() && pRT
->m_eVideoThreadMode
== SRenderThread::eVTM_Disabled
))
2593 const int frameID
= gRenDev
->GetRenderFrameID();
2594 if (ms_lastTickRTFrameID
!= frameID
)
2596 CryAutoCriticalSection
lock(ms_lock
);
2598 const size_t size
= ms_sources
.size();
2599 for (size_t i
= 0; i
< size
; ++i
)
2601 ms_sources
[i
]->AutoUpdateRT(frameID
);
2604 ms_lastTickRTFrameID
= frameID
;
2609 static void RenderLightTextures()
2611 for (std::vector
<CFlashTextureSourceBase
*>::const_iterator it
= ms_LightTextures
.begin(); it
!= ms_LightTextures
.end(); ++it
)
2613 ms_LightTextures
.clear();
2617 static std::vector
<CFlashTextureSourceBase
*> ms_sources
;
2618 static std::vector
<CFlashTextureSourceBase
*> ms_LightTextures
;
2619 static CryCriticalSection ms_lock
;
2620 static int ms_lastTickFrameID
;
2621 static int ms_lastTickRTFrameID
;
2624 void CFlashTextureSourceBase::Tick()
2626 FlashTextureSourceSharedRT_AutoUpdate::Tick();
2629 void CFlashTextureSourceBase::TickRT()
2631 FlashTextureSourceSharedRT_AutoUpdate::TickRT();
2634 void CFlashTextureSourceBase::RenderLights()
2636 FlashTextureSourceSharedRT_AutoUpdate::RenderLightTextures();
2639 void CFlashTextureSourceBase::AddToLightRenderList(const IDynTextureSource
* pSrc
)
2641 FlashTextureSourceSharedRT_AutoUpdate::AddToLightList((CFlashTextureSourceBase
*)pSrc
);
2644 void CFlashTextureSourceBase::AutoUpdate(const CTimeValue
& curTime
, const float delta
, const bool isEditing
, const bool isPaused
)
2648 m_pFlashPlayer
->UpdatePlayer(this);
2649 #if CRY_PLATFORM_WINDOWS
2650 m_perFrameRendering
&= !isEditing
;
2653 if (m_perFrameRendering
|| (curTime
- m_lastVisible
).GetSeconds() < 1.0f
)
2655 Advance(delta
, isPaused
);
2660 void CFlashTextureSourceBase::AutoUpdateRT(const int frameID
)
2664 if (m_perFrameRendering
&& (frameID
!= m_lastVisibleFrameID
))
2671 std::vector
<CFlashTextureSourceBase
*> FlashTextureSourceSharedRT_AutoUpdate::ms_sources
;
2672 std::vector
<CFlashTextureSourceBase
*> FlashTextureSourceSharedRT_AutoUpdate::ms_LightTextures
;
2673 CryCriticalSection
FlashTextureSourceSharedRT_AutoUpdate::ms_lock
;
2674 int FlashTextureSourceSharedRT_AutoUpdate::ms_lastTickFrameID
= 0;
2675 int FlashTextureSourceSharedRT_AutoUpdate::ms_lastTickRTFrameID
= 0;
2677 CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::~CFlashPlayerInstanceWrapper()
2679 SAFE_RELEASE(m_pBootStrapper
);
2682 std::shared_ptr
<IFlashPlayer
> CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::GetTempPtr() const
2687 std::shared_ptr
<IFlashPlayer
> CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::GetPermPtr(CFlashTextureSourceBase
* pSrc
)
2689 CryAutoCriticalSection
lock(m_lock
);
2691 m_canDeactivate
= false;
2692 CreateInstance(pSrc
);
2697 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::Activate(bool activate
, CFlashTextureSourceBase
* pSrc
)
2701 CryAutoCriticalSection
lock(m_lock
);
2702 CreateInstance(pSrc
);
2704 else if (m_canDeactivate
)
2706 m_pPlayer
= nullptr;
2710 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::CreateInstance(CFlashTextureSourceBase
* pSrc
)
2712 if (!m_pPlayer
&& m_pBootStrapper
)
2714 m_pPlayer
= m_pBootStrapper
->CreatePlayerInstance(IFlashPlayer::DEFAULT_NO_MOUSE
);
2717 #if defined(ENABLE_DYNTEXSRC_PROFILING)
2718 m_pPlayer
->LinkDynTextureSource(pSrc
);
2720 m_pPlayer
->Advance(0.0f
);
2721 m_width
= m_pPlayer
->GetWidth();
2722 m_height
= m_pPlayer
->GetHeight();
2727 const char* CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::GetSourceFilePath() const
2729 return m_pBootStrapper
? m_pBootStrapper
->GetFilePath() : "UNDEFINED";
2732 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapper::Advance(float delta
)
2735 m_pPlayer
->Advance(delta
);
2738 CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::~CFlashPlayerInstanceWrapperLayoutElement()
2742 m_pUILayout
->Unload();
2748 std::shared_ptr
<IFlashPlayer
> CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::GetTempPtr() const
2753 std::shared_ptr
<IFlashPlayer
> CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::GetPermPtr(CFlashTextureSourceBase
* pSrc
)
2755 CryAutoCriticalSection
lock(m_lock
);
2757 m_canDeactivate
= false;
2758 CreateInstance(pSrc
, m_layoutName
.c_str());
2763 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::Activate(bool activate
, CFlashTextureSourceBase
* pSrc
)
2767 CryAutoCriticalSection
lock(m_lock
);
2768 CreateInstance(pSrc
, m_layoutName
.c_str());
2770 else if (m_canDeactivate
)
2772 m_pPlayer
= nullptr;
2776 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::CreateInstance(CFlashTextureSourceBase
* pSrc
, const char* layoutName
)
2778 UIFramework::IUIFramework
* pUIFramework
= gEnv
->pUIFramework
;
2781 char name
[_MAX_PATH
];
2782 cry_strcpy(name
, layoutName
);
2783 PathUtil::RemoveExtension(name
);
2784 const char* pExt
= PathUtil::GetExt(layoutName
);
2785 if (!pExt
|| strcmpi(pExt
, "layout") != 0)
2790 if (pUIFramework
->LoadLayout(name
) != INVALID_LAYOUT_ID
)
2792 m_layoutName
= name
;
2793 m_pUILayout
= pUIFramework
->GetLayoutBase(m_layoutName
);
2796 m_pPlayer
= m_pUILayout
->GetPlayer();
2800 pSrc
->m_autoUpdate
= !m_pPlayer
->HasMetadata("CE_NoAutoUpdate");
2802 #if defined(ENABLE_DYNTEXSRC_PROFILING)
2803 m_pPlayer
->LinkDynTextureSource(pSrc
);
2805 m_pPlayer
->Advance(0.0f
);
2806 m_width
= m_pPlayer
->GetWidth();
2807 m_height
= m_pPlayer
->GetHeight();
2814 const char* CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::GetSourceFilePath() const
2816 return m_pPlayer
? m_pPlayer
->GetFilePath() : "UNDEFINED";
2819 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperLayoutElement::Advance(float delta
)
2822 m_pPlayer
->Advance(delta
);
2825 CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::~CFlashPlayerInstanceWrapperUIElement()
2827 SAFE_RELEASE(m_pUIElement
);
2830 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::SetUIElement(IUIElement
* p
)
2832 assert(!m_pUIElement
);
2834 m_pUIElement
->AddRef();
2837 std::shared_ptr
<IFlashPlayer
> CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::GetTempPtr() const
2842 std::shared_ptr
<IFlashPlayer
> CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::GetPermPtr(CFlashTextureSourceBase
* pSrc
)
2844 CryAutoCriticalSection
lock(m_lock
);
2846 m_canDeactivate
= false;
2848 UpdateUIElementPlayer(pSrc
);
2853 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::Activate(bool activate
, CFlashTextureSourceBase
* pSrc
)
2855 CryAutoCriticalSection
lock(m_lock
);
2857 m_activated
= m_canDeactivate
? activate
: m_activated
;
2858 UpdateUIElementPlayer(pSrc
);
2861 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::Clear(CFlashTextureSourceBase
* pSrc
)
2863 CryAutoCriticalSection
lock(m_lock
);
2865 if (m_pUIElement
&& m_pPlayer
)
2866 m_pUIElement
->RemoveTexture(pSrc
);
2868 m_pPlayer
= nullptr;
2871 const char* CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::GetSourceFilePath() const
2873 return m_pUIElement
? m_pUIElement
->GetFlashFile() : "UNDEFINED";
2876 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::UpdatePlayer(CFlashTextureSourceBase
* pSrc
)
2878 CryAutoCriticalSection
lock(m_lock
);
2880 UpdateUIElementPlayer(pSrc
);
2883 void CFlashTextureSourceBase::CFlashPlayerInstanceWrapperUIElement::UpdateUIElementPlayer(CFlashTextureSourceBase
* pSrc
)
2885 CRY_ASSERT(gRenDev
->m_pRT
->IsMainThread() || gRenDev
->m_pRT
->IsLevelLoadingThread());
2891 const bool isVisible
= m_pUIElement
->IsVisible();
2892 std::shared_ptr
<IFlashPlayer
> pPlayer
= isVisible
? m_pUIElement
->GetFlashPlayer() : NULL
;
2893 if (pPlayer
!= m_pPlayer
)
2895 const bool addTex
= m_pPlayer
== nullptr;
2896 m_pPlayer
= nullptr;
2898 m_pPlayer
= pPlayer
;
2902 m_width
= m_pPlayer
->GetWidth();
2903 m_height
= m_pPlayer
->GetHeight();
2905 m_pUIElement
->AddTexture(pSrc
);
2908 m_pUIElement
->RemoveTexture(pSrc
);
2914 m_pUIElement
->RemoveTexture(pSrc
);
2915 m_pPlayer
= nullptr;
2920 CFlashTextureSourceBase::CFlashTextureSourceBase(const char* pFlashFileName
, const IRenderer::SLoadShaderItemArgs
* pArgs
)
2923 , m_lastVisibleFrameID(0)
2926 , m_aspectRatio(1.0f
)
2927 , m_autoUpdate(true)
2928 , m_perFrameRendering(false)
2929 , m_pFlashFileName(pFlashFileName
)
2930 , m_pFlashPlayer(CFlashPlayerInstanceWrapperNULL::Get())
2933 #if defined(ENABLE_DYNTEXSRC_PROFILING)
2934 , m_pMatSrc(pArgs
? pArgs
->m_pMtlSrc
: 0)
2935 , m_pMatSrcParent(pArgs
? pArgs
->m_pMtlSrcParent
: 0)
2942 if (IsFlashUIFile(pFlashFileName
))
2944 valid
= CreateTexFromFlashFile(pFlashFileName
);
2947 gEnv
->pFlashUI
->RegisterModule(this, pFlashFileName
);
2952 std::pair
<IUIElement
*, IUIElement
*> result
= gEnv
->pFlashUI
->GetUIElementsByInstanceStr(pFlashFileName
);
2953 std::pair
<string
, int> identifiers
= gEnv
->pFlashUI
->GetUIIdentifiersByInstanceStr(pFlashFileName
);
2956 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_WARNING
,
2957 "UI-Element identifier \"%s\" can't be found in the UI-Database.\n", identifiers
.first
.c_str());
2958 else if (!result
.second
)
2959 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_WARNING
,
2960 "UI-Element \"%s\" doesn't have an instance %d.\n", identifiers
.first
.c_str(), identifiers
.second
);
2964 else if (IsFlashUILayoutFile(pFlashFileName
))
2967 m_pFlashPlayer
->Clear(this);
2969 m_pFlashPlayer
= nullptr;
2971 CFlashPlayerInstanceWrapperLayoutElement
* pInstanceWrapper
= new CFlashPlayerInstanceWrapperLayoutElement();
2972 pInstanceWrapper
->CreateInstance(this, pFlashFileName
);
2973 m_pFlashPlayer
= pInstanceWrapper
;
2978 IFlashPlayerBootStrapper
* pBootStrapper
= gEnv
->pScaleformHelper
? gEnv
->pScaleformHelper
->CreateFlashPlayerBootStrapper() : nullptr;
2981 if (pBootStrapper
->Load(pFlashFileName
))
2983 m_autoUpdate
= !pBootStrapper
->HasMetadata("CE_NoAutoUpdate");
2985 CFlashPlayerInstanceWrapper
* pInstanceWrapper
= new CFlashPlayerInstanceWrapper();
2986 pInstanceWrapper
->SetBootStrapper(pBootStrapper
);
2987 pInstanceWrapper
->CreateInstance(this);
2988 m_pFlashPlayer
= pInstanceWrapper
;
2993 SAFE_RELEASE(pBootStrapper
);
2999 for (size_t i
= 0; i
< NumCachedTexStateIDs
; ++i
)
3001 m_texStateIDs
[i
].original
= EDefaultSamplerStates::Unspecified
;
3002 m_texStateIDs
[i
].patched
= EDefaultSamplerStates::Unspecified
;
3005 if (valid
&& m_autoUpdate
)
3006 FlashTextureSourceSharedRT_AutoUpdate::Add(this);
3009 bool CFlashTextureSourceBase::IsFlashFile(const char* pFlashFileName
)
3013 const char* pExt
= PathUtil::GetExt(pFlashFileName
);
3014 const bool bPath
= strchr(pFlashFileName
, '/') || strchr(pFlashFileName
, '\\');
3020 // Pseudo files (no path, looks up flow-node)
3021 return (!stricmp(pExt
, "ui"));
3024 // Real files (looks up filesystem)
3025 return (!stricmp(pExt
, "layout") || !stricmp(pExt
, "gfx") || !stricmp(pExt
, "swf") || !stricmp(pExt
, "usm"));
3032 bool CFlashTextureSourceBase::IsFlashUIFile(const char* pFlashFileName
)
3036 const char* pExt
= PathUtil::GetExt(pFlashFileName
);
3037 const bool bPath
= strchr(pFlashFileName
, '/') || strchr(pFlashFileName
, '\\');
3043 // Pseudo files (no path, looks up flow-node)
3044 return !stricmp(pExt
, "ui");
3052 bool CFlashTextureSourceBase::IsFlashUILayoutFile(const char* pFlashFileName
)
3056 const char* pExt
= PathUtil::GetExt(pFlashFileName
);
3060 return !stricmp(pExt
, "layout");
3067 bool CFlashTextureSourceBase::DestroyTexOfFlashFile(const char* name
)
3071 IUIElement
* pElement
= gEnv
->pFlashUI
->GetUIElementByInstanceStr(name
);
3075 pElement
->DestroyThis();
3083 bool CFlashTextureSourceBase::CreateTexFromFlashFile(const char* name
)
3089 m_pFlashPlayer
->Clear(this);
3090 m_pFlashPlayer
= nullptr;
3092 m_pElement
= gEnv
->pFlashUI
->GetUIElementByInstanceStr(name
);
3095 CFlashPlayerInstanceWrapperUIElement
* pInstanceWrapper
= new CFlashPlayerInstanceWrapperUIElement();
3096 m_pElement
->SetVisible(true);
3097 pInstanceWrapper
->SetUIElement(m_pElement
);
3098 pInstanceWrapper
->Activate(true, this);
3099 m_pFlashPlayer
= pInstanceWrapper
;
3107 CFlashTextureSourceBase::~CFlashTextureSourceBase()
3109 FlashTextureSourceSharedRT_AutoUpdate::Remove(this);
3111 if (m_pElement
) // If module registration happened m_pElement is set
3113 gEnv
->pFlashUI
->UnregisterModule(this);
3117 m_pFlashPlayer
->Clear(this);
3119 m_pFlashPlayer
= nullptr;
3122 void CFlashTextureSourceBase::AddRef()
3124 CryInterlockedIncrement(&m_refCount
);
3127 void CFlashTextureSourceBase::Release()
3129 long refCnt
= CryInterlockedDecrement(&m_refCount
);
3134 void CFlashTextureSourceBase::Activate(bool activate
)
3136 m_pFlashPlayer
->Activate(activate
, this);
3139 #if defined(ENABLE_DYNTEXSRC_PROFILING)
3140 string
CFlashTextureSourceBase::GetProfileInfo() const
3143 const char* pMtlName
= "NULL";
3144 if (m_pMatSrc
|| m_pMatSrcParent
)
3146 if (m_pMatSrcParent
)
3148 if (m_pMatSrcParent
->GetName())
3149 pMtlName
= m_pMatSrcParent
->GetName();
3153 if (m_pMatSrc
->GetName())
3154 pMtlName
= m_pMatSrc
->GetName();
3158 const char* pSubMtlName
= "NULL";
3159 if (m_pMatSrcParent
)
3163 if (m_pMatSrc
->GetName())
3164 pSubMtlName
= m_pMatSrc
->GetName();
3172 CryFixedStringT
<128> info
;
3173 info
.Format("mat: %s%s%s%s", pMtlName
, pSubMtlName
? "|sub: " : "", pSubMtlName
? pSubMtlName
: "", !m_pFlashPlayer
->CanDeactivate() ? "|$4can't be deactivated!$O" : "");
3175 return info
.c_str();
3179 void* CFlashTextureSourceBase::GetSourceTemp(EDynTextureSource type
) const
3181 if (m_pFlashPlayer
!= nullptr && type
== DTS_I_FLASHPLAYER
)
3183 return m_pFlashPlayer
->GetTempPtr().get();
3188 void* CFlashTextureSourceBase::GetSourcePerm(EDynTextureSource type
)
3190 if (m_pFlashPlayer
!= nullptr && type
== DTS_I_FLASHPLAYER
)
3192 return m_pFlashPlayer
->GetPermPtr(this).get();
3197 const char* CFlashTextureSourceBase::GetSourceFilePath() const
3199 if (m_pFlashPlayer
!= nullptr)
3201 return m_pFlashPlayer
->GetSourceFilePath();
3206 void CFlashTextureSourceBase::GetTexGenInfo(float& offsX
, float& offsY
, float& scaleX
, float& scaleY
) const
3208 SDynTexture
* pDynTexture
= GetDynTexture();
3209 assert(pDynTexture
);
3210 if (!pDynTexture
|| !pDynTexture
->IsValid())
3219 ITexture
* pSrcTex
= pDynTexture
->GetTexture();
3220 float invSrcWidth
= 1.0f
/ (float) pSrcTex
->GetWidth();
3221 float invSrcHeight
= 1.0f
/ (float) pSrcTex
->GetHeight();
3224 assert(m_width
<= pDynTexture
->m_nWidth
&& m_height
<= pDynTexture
->m_nHeight
);
3225 scaleX
= m_width
* invSrcWidth
;
3226 scaleY
= m_height
* invSrcHeight
;
3229 //////////////////////////////////////////////////////////////////////////
3230 CFlashTextureSource::CFlashTextureSource(const char* pFlashFileName
, const IRenderer::SLoadShaderItemArgs
* pArgs
)
3231 : CFlashTextureSourceBase(pFlashFileName
, pArgs
)
3233 // create render-target with mip-maps
3234 m_pDynTexture
= new SDynTexture(GetWidth(), GetHeight(), Clr_Transparent
, eTF_R8G8B8A8
, eTT_2D
, FT_USAGE_RENDERTARGET
| FT_STATE_CLAMP
| FT_FORCE_MIPS
| FT_USAGE_ALLOWREADSRGB
, "FlashTextureSourceUniqueRT");
3235 m_pMipMapper
= nullptr;
3238 CFlashTextureSource::~CFlashTextureSource()
3240 SAFE_DELETE(m_pMipMapper
);
3241 SAFE_DELETE(m_pDynTexture
);
3244 int CFlashTextureSource::GetWidth() const
3246 IFlashPlayerInstanceWrapper
* pFlash
= GetFlashPlayerInstanceWrapper();
3247 return pFlash
? max(Align8(pFlash
->GetWidth()), 16) : 16;
3250 int CFlashTextureSource::GetHeight() const
3252 IFlashPlayerInstanceWrapper
* pFlash
= GetFlashPlayerInstanceWrapper();
3253 return pFlash
? max(Align8(pFlash
->GetHeight()), 16) : 16;
3256 bool CFlashTextureSource::UpdateDynTex(int rtWidth
, int rtHeight
)
3258 bool needResize
= rtWidth
!= m_pDynTexture
->m_nWidth
|| rtHeight
!= m_pDynTexture
->m_nHeight
|| !m_pDynTexture
->IsValid();
3261 if (!m_pDynTexture
->Update(rtWidth
, rtHeight
))
3267 //////////////////////////////////////////////////////////////////////////
3268 SDynTexture
* CFlashTextureSourceSharedRT::ms_pDynTexture
= nullptr;
3269 CMipmapGenPass
* CFlashTextureSourceSharedRT::ms_pMipMapper
= nullptr;
3270 int CFlashTextureSourceSharedRT::ms_instCount
= 0;
3271 uint16
CFlashTextureSourceSharedRT::ms_sharedRTWidth
= 256;
3272 uint16
CFlashTextureSourceSharedRT::ms_sharedRTHeight
= 256;
3274 CFlashTextureSourceSharedRT::CFlashTextureSourceSharedRT(const char* pFlashFileName
, const IRenderer::SLoadShaderItemArgs
* pArgs
)
3275 : CFlashTextureSourceBase(pFlashFileName
, pArgs
)
3278 if (!ms_pDynTexture
)
3280 // create render-target with mip-maps
3281 ms_pDynTexture
= new SDynTexture(ms_sharedRTWidth
, ms_sharedRTHeight
, Clr_Transparent
, eTF_R8G8B8A8
, eTT_2D
, FT_USAGE_RENDERTARGET
| FT_STATE_CLAMP
| FT_FORCE_MIPS
| FT_USAGE_ALLOWREADSRGB
, "FlashTextureSourceSharedRT");
3282 ms_pMipMapper
= nullptr;
3286 CFlashTextureSourceSharedRT::~CFlashTextureSourceSharedRT()
3289 if (ms_instCount
<= 0)
3291 SAFE_DELETE(ms_pMipMapper
);
3292 SAFE_DELETE(ms_pDynTexture
);
3296 int CFlashTextureSourceSharedRT::GetSharedRTWidth()
3298 return CRenderer::CV_r_DynTexSourceSharedRTWidth
> 0 ? Align8(max(CRenderer::CV_r_DynTexSourceSharedRTWidth
, 16)) : ms_sharedRTWidth
;
3301 int CFlashTextureSourceSharedRT::GetSharedRTHeight()
3303 return CRenderer::CV_r_DynTexSourceSharedRTHeight
> 0 ? Align8(max(CRenderer::CV_r_DynTexSourceSharedRTHeight
, 16)) : ms_sharedRTHeight
;
3306 int CFlashTextureSourceSharedRT::NearestPowerOfTwo(int n
)
3316 return (k
- n
) <= (n
- (k
>> 1)) ? k
: (k
>> 1);
3319 void CFlashTextureSourceSharedRT::SetSharedRTDim(int width
, int height
)
3321 ms_sharedRTWidth
= NearestPowerOfTwo(width
> 16 ? width
: 16);
3322 ms_sharedRTHeight
= NearestPowerOfTwo(height
> 16 ? height
: 16);
3325 void CFlashTextureSourceSharedRT::SetupSharedRenderTargetRT()
3329 const int rtWidth
= GetSharedRTWidth();
3330 const int rtHeight
= GetSharedRTHeight();
3331 bool needResize
= rtWidth
!= ms_pDynTexture
->m_nWidth
|| rtHeight
!= ms_pDynTexture
->m_nHeight
;
3332 if (!ms_pDynTexture
->IsValid() || needResize
)
3334 ms_pDynTexture
->Update(rtWidth
, rtHeight
);
3335 ms_pDynTexture
->SetUpdateMask();
3337 CTexture
* pTex
= (CTexture
*) ms_pDynTexture
->GetTexture();
3338 // prevent leak, this code is only needed on D3D11 to force texture creating
3340 pTex
->GetSurface(-1, 0);
3341 ProbeDepthStencilSurfaceCreation(rtWidth
, rtHeight
);
3346 //////////////////////////////////////////////////////////////////////////
3347 CDynTextureSourceLayerActivator::PerLayerDynSrcMtls
CDynTextureSourceLayerActivator::s_perLayerDynSrcMtls
;
3349 void CDynTextureSourceLayerActivator::LoadLevelInfo()
3353 const char* pLevelPath
= iSystem
->GetI3DEngine()->GetLevelFilePath("dyntexsrclayeract.xml");
3355 XmlNodeRef root
= iSystem
->LoadXmlFromFile(pLevelPath
);
3358 const int numLayers
= root
->getChildCount();
3359 for (int curLayer
= 0; curLayer
< numLayers
; ++curLayer
)
3361 XmlNodeRef layer
= root
->getChild(curLayer
);
3364 const char* pLayerName
= layer
->getAttr("Name");
3367 const int numMtls
= layer
->getChildCount();
3369 std::vector
<string
> mtls
;
3370 mtls
.reserve(numMtls
);
3372 for (int curMtl
= 0; curMtl
< numMtls
; ++curMtl
)
3374 XmlNodeRef mtl
= layer
->getChild(curMtl
);
3377 const char* pMtlName
= mtl
->getAttr("Name");
3379 mtls
.push_back(pMtlName
);
3383 s_perLayerDynSrcMtls
.insert(PerLayerDynSrcMtls::value_type(pLayerName
, mtls
));
3390 void CDynTextureSourceLayerActivator::ReleaseData()
3392 stl::reconstruct(s_perLayerDynSrcMtls
);
3395 void CDynTextureSourceLayerActivator::ActivateLayer(const char* pLayerName
, bool activate
)
3397 PerLayerDynSrcMtls::const_iterator it
= pLayerName
? s_perLayerDynSrcMtls
.find(pLayerName
) : s_perLayerDynSrcMtls
.end();
3398 if (it
!= s_perLayerDynSrcMtls
.end())
3400 const std::vector
<string
>& mtls
= (*it
).second
;
3401 const size_t numMtls
= mtls
.size();
3403 const IMaterialManager
* pMatMan
= gEnv
->p3DEngine
->GetMaterialManager();
3405 for (size_t i
= 0; i
< numMtls
; ++i
)
3407 const char* pMtlName
= mtls
[i
].c_str();
3408 IMaterial
* pMtl
= pMatMan
->FindMaterial(pMtlName
);
3411 pMtl
->ActivateDynamicTextureSources(activate
);
3417 //////////////////////////////////////////////////////////////////////////
3418 void CRenderer::EF_AddRTStat(CTexture
* pTex
, int nFlags
, int nW
, int nH
)
3427 nW
= CRendererResources::s_renderWidth
;
3429 nH
= CRendererResources::s_renderHeight
;
3430 nSize
= CTexture::TextureDataSize(nW
, nH
, 1, 1, 1, eTF
, eTM_Optimal
);
3431 TS
.m_Name
= "Back buffer";
3435 eTF
= pTex
->GetDstFormat();
3437 nW
= pTex
->GetWidth();
3439 nH
= pTex
->GetHeight();
3440 nSize
= CTexture::TextureDataSize(nW
, nH
, 1, pTex
->GetNumMips(), 1, eTF
, eTM_Optimal
);
3441 const char* szName
= pTex
->GetName();
3442 if (szName
&& szName
[0] == '$')
3443 TS
.m_Name
= string("@") + string(&szName
[1]);
3452 TS
.m_Name
+= " (Target)";
3453 else if (nFlags
== 2)
3455 TS
.m_Name
+= " (Depth)";
3456 nSize
= nW
* nH
* 3;
3458 else if (nFlags
== 4)
3460 TS
.m_Name
+= " (Stencil)";
3463 else if (nFlags
== 3)
3465 TS
.m_Name
+= " (Target + Depth)";
3466 nSize
+= nW
* nH
* 3;
3468 else if (nFlags
== 6)
3470 TS
.m_Name
+= " (Depth + Stencil)";
3471 nSize
= nW
* nH
* 4;
3473 else if (nFlags
== 5)
3475 TS
.m_Name
+= " (Target + Stencil)";
3478 else if (nFlags
== 7)
3480 TS
.m_Name
+= " (Target + Depth + Stencil)";
3481 nSize
+= nW
* nH
* 4;
3492 m_renderTargetStats
.push_back(TS
);
3495 void CRenderer::EF_PrintRTStats(const char* szName
)
3497 const int nYstep
= 14;
3498 int nY
= 30; // initial Y pos
3499 int nX
= 20; // initial X pos
3500 ColorF col
= Col_Green
;
3501 IRenderAuxText::Draw2dLabel((float)nX
, (float)nY
, 1.6f
, &col
.r
, false, "%s", szName
);
3508 for (size_t i
= 0; i
< m_renderTargetStats
.size(); i
++)
3510 SRTargetStat
* pRT
= &m_renderTargetStats
[i
];
3512 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
);
3514 if (nY
>= CRendererResources::s_displayHeight
- 25)
3519 nSize
+= pRT
->m_nSize
;
3522 IRenderAuxText::Draw2dLabel((float)nX
, (float)(nY
+ 10), 1.4f
, &col
.r
, false, "Total: %d RT's, Size: %.3f Mb", m_renderTargetStats
.size(), nSize
/ 1024.0f
/ 1024.0f
);
3525 STexPool::~STexPool()
3528 bool poolEmpty
= true;
3531 STexPoolItemHdr
* pITH
= m_ItemsList
.m_Next
;
3532 while (pITH
!= &m_ItemsList
)
3534 STexPoolItemHdr
* pNext
= pITH
->m_Next
;
3535 STexPoolItem
* pIT
= static_cast<STexPoolItem
*>(pITH
);
3537 assert(pIT
->m_pOwner
== this);
3539 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);
3544 pIT
->m_pTex
->ReleaseDeviceTexture(true); // Try to recover in release
3547 *const_cast<STexPool
**>(&pIT
->m_pOwner
) = NULL
;
3550 CRY_ASSERT(poolEmpty
, "Texture pool was not empty on shutdown");
3553 const ETEX_Type
CTexture::GetTextureType() const
3558 const int CTexture::GetTextureID() const
3563 #ifdef TEXTURE_GET_SYSTEM_COPY_SUPPORT
3565 const ColorB
* CTexture::GetLowResSystemCopy(uint16
& width
, uint16
& height
, int** ppUserData
, int maxTexSize
)
3567 AUTO_READLOCK(s_LowResSystemCopyLock
);
3569 // find slot based on requested texture size, snap texture size to power of 2
3570 int slot
= CLAMP((int)log2(maxTexSize
) - 4, 0, TEX_SYS_COPY_MAX_SLOTS
- 1);
3571 maxTexSize
= (int)exp2(slot
+ 4);
3573 LowResSystemCopyType::iterator it
= s_LowResSystemCopy
[slot
].find(this);
3575 // load if not ready yet
3576 if (it
== CTexture::s_LowResSystemCopy
[slot
].end())
3578 if (m_eTT
!= eTT_2D
|| (m_nMips
<= 1 && (m_nWidth
> maxTexSize
|| m_nHeight
> maxTexSize
)) || m_eDstFormat
< eTF_BC1
|| m_eDstFormat
> eTF_BC7
)
3581 // to switch to modify we need to unlock first
3582 s_LowResSystemCopyLock
.UnlockRead();
3583 { // to reduce contention, we want to hold the modify lock as shortly as possible
3584 AUTO_MODIFYLOCK(s_LowResSystemCopyLock
);
3585 s_LowResSystemCopy
[slot
][this]; // make a map entry for this
3588 // 'restore' AUTO_READLOCK
3589 s_LowResSystemCopyLock
.LockRead();
3590 it
= s_LowResSystemCopy
[slot
].find(this);
3591 SLowResSystemCopy
& rCopy
= it
->second
;
3592 PrepareLowResSystemCopy(maxTexSize
, rCopy
.m_lowResSystemCopy
, rCopy
.m_nLowResCopyWidth
, rCopy
.m_nLowResCopyHeight
);
3595 if (it
!= CTexture::s_LowResSystemCopy
[slot
].end())
3597 width
= (*it
).second
.m_nLowResCopyWidth
;
3598 height
= (*it
).second
.m_nLowResCopyHeight
;
3600 *ppUserData
= &(*it
).second
.m_nLowResSystemCopyAtlasId
;
3601 return (*it
).second
.m_lowResSystemCopy
.GetElements();
3604 assert(!"CTexture::GetLowResSystemCopy failed");
3609 bool CTexture::PrepareLowResSystemCopy(const uint16 maxTexSize
, PodArray
<ColorB
>& textureData
, uint16
& width
, uint16
& height
)
3611 _smart_ptr
<IImageFile
> imageData
= gEnv
->pRenderer
->EF_LoadImage(GetName(), 0);
3615 width
= imageData
->mfGet_width();
3616 height
= imageData
->mfGet_height();
3617 byte
* pSrcData
= imageData
->mfGet_image(0);
3618 ETEX_Format texFormat
= imageData
->mfGetFormat();
3622 while (width
> maxTexSize
|| height
> maxTexSize
)
3624 int sizeDxtMip
= gRenDev
->GetTextureFormatDataSize(width
, height
, 1, 1, texFormat
, eTM_None
);
3625 pSrcData
+= sizeDxtMip
;
3632 assert(texFormat
>= eTF_BC1
&& texFormat
<= eTF_BC7
);
3634 int nSizeDxtMip0
= gRenDev
->GetTextureFormatDataSize(width
, height
, 1, 1, texFormat
, eTM_None
);
3635 int nSizeMip0
= gRenDev
->GetTextureFormatDataSize(width
, height
, 1, 1, eTF_R8G8B8A8
, eTM_None
);
3637 textureData
.PreAllocate(nSizeMip0
/ sizeof(ColorB
), nSizeMip0
/ sizeof(ColorB
));
3639 gRenDev
->DXTDecompress(pSrcData
, nSizeDxtMip0
, (byte
*)textureData
.GetElements(), width
, height
, 1, texFormat
, false, 4);
3643 for (int i
= 0; i
< textureData
.Count(); i
++)
3645 ColorF colF
= textureData
[i
];
3647 textureData
[i
] = colF
;
3652 return !textureData
.IsEmpty();
3655 #endif // TEXTURE_GET_SYSTEM_COPY_SUPPORT