BsRenderAPICapabilities.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #pragma once
  2. #include "BsCorePrerequisites.h"
  3. #include "BsGpuProgram.h"
  4. #define CAPS_CATEGORY_SIZE 8i64
  5. #define BS_CAPS_BITSHIFT (64i64 - CAPS_CATEGORY_SIZE)
  6. #define CAPS_CATEGORY_MASK (((1i64 << CAPS_CATEGORY_SIZE) - 1i64) << BS_CAPS_BITSHIFT)
  7. #define BS_CAPS_VALUE(cat, val) ((cat << BS_CAPS_BITSHIFT) | (1i64 << val))
  8. #define MAX_BOUND_VERTEX_BUFFERS 32
  9. namespace BansheeEngine
  10. {
  11. /** @cond INTERNAL */
  12. /** @addtogroup RenderAPI
  13. * @{
  14. */
  15. /** Categories of render API capabilities. */
  16. enum CapabilitiesCategory : UINT64
  17. {
  18. CAPS_CATEGORY_COMMON = 0,
  19. CAPS_CATEGORY_D3D9 = 1,
  20. CAPS_CATEGORY_GL = 2,
  21. CAPS_CATEGORY_D3D11 = 3,
  22. CAPS_CATEGORY_COUNT = 32 /**< Maximum number of categories. */
  23. };
  24. /** Enum describing the different hardware capabilities we can check for. */
  25. enum Capabilities : UINT64
  26. {
  27. RSC_AUTOMIPMAP = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 0), /**< Supports generating mipmaps in hardware. */
  28. RSC_ANISOTROPY = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 1), /**< Supports anisotropic texture filtering. */
  29. RSC_CUBEMAPPING = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 2), /**< Supports cube mapping. */
  30. RSC_TWO_SIDED_STENCIL = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 3), /**< Supports separate stencil updates for both front and back faces. */
  31. RSC_STENCIL_WRAP = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 4), /**< Supports wrapping the stencil value at the range extremes. */
  32. RSC_HWOCCLUSION = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 5), /**< Supports hardware occlusion queries. */
  33. RSC_USER_CLIP_PLANES = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 6), /**< Supports user clipping planes. */
  34. RSC_VERTEX_FORMAT_UBYTE4 = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 7), /**< Supports the VET_UBYTE4 vertex element type. */
  35. RSC_INFINITE_FAR_PLANE = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 8), /**< Supports infinite far plane projection. */
  36. RSC_HWRENDER_TO_TEXTURE = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 9), /**< Supports hardware render-to-texture. */
  37. RSC_TEXTURE_FLOAT = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 10), /**< Supports float textures and render targets. */
  38. RSC_NON_POWER_OF_2_TEXTURES = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 11), /**< Supports non-power of two textures. */
  39. RSC_TEXTURE_3D = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 12), /**< Supports 3d (volume) textures. */
  40. RSC_POINT_SPRITES = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 13), /**< Supports basic point sprite rendering. */
  41. RSC_POINT_EXTENDED_PARAMETERS = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 14), /**< Supports extra point parameters (minsize, maxsize, attenuation). */
  42. RSC_VERTEX_TEXTURE_FETCH = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 15), /**< Supports vertex texture fetch. */
  43. RSC_MIPMAP_LOD_BIAS = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 16), /**< Supports mipmap LOD biasing. */
  44. RSC_GEOMETRY_PROGRAM = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 17), /**< Supports hardware geometry programs. */
  45. RSC_TEXTURE_COMPRESSION = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 18), /**< Supports compressed textures. */
  46. RSC_TEXTURE_COMPRESSION_DXT = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 19), /**< Supports compressed textures in the DXT/ST3C formats. */
  47. RSC_TEXTURE_COMPRESSION_VTC = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 20), /**< Supports compressed textures in the VTC format. */
  48. RSC_TEXTURE_COMPRESSION_PVRTC = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 21), /**< Supports compressed textures in the PVRTC format. */
  49. RSC_MRT_DIFFERENT_BIT_DEPTHS = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 22), /**< Supports multiple render targets with different bit depths. */
  50. RSC_ALPHA_TO_COVERAGE = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 23), /**< Supports Alpha to Coverage. */
  51. RSC_ADVANCED_BLEND_OPERATIONS = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 24), /**< Supports blend operations like subtract, min, max. */
  52. RSC_SHADER_SUBROUTINE = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 25), /**< Supports dynamic shader linking. */
  53. RSC_HWOCCLUSION_ASYNCHRONOUS = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 26), /**< Support for async occlusion queries. */
  54. RSC_HWRENDER_TO_VERTEX_BUFFER = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 27), /**< Supports rendering to vertex buffers. */
  55. RSC_TESSELLATION_PROGRAM = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 28), /**< Supports hardware tessellation programs. */
  56. RSC_COMPUTE_PROGRAM = BS_CAPS_VALUE(CAPS_CATEGORY_COMMON, 29), /**< Supports hardware compute programs. */
  57. // ***** DirectX 9 specific caps *****
  58. RSC_PERSTAGECONSTANT = BS_CAPS_VALUE(CAPS_CATEGORY_D3D9, 0), /**< Are per stage constants supported. */
  59. // ***** GL Specific caps *****
  60. RSC_FBO = BS_CAPS_VALUE(CAPS_CATEGORY_GL, 0), /**< Support for Frame Buffer Objects. */
  61. RSC_PBUFFER = BS_CAPS_VALUE(CAPS_CATEGORY_GL, 1), /**< Support for PBuffers. */
  62. };
  63. /** Holds data about render system driver version. */
  64. struct BS_CORE_EXPORT DriverVersion
  65. {
  66. int major;
  67. int minor;
  68. int release;
  69. int build;
  70. DriverVersion()
  71. {
  72. major = minor = release = build = 0;
  73. }
  74. /** Returns the driver version as a single string. */
  75. String toString() const
  76. {
  77. StringStream str;
  78. str << major << "." << minor << "." << release << "." << build;
  79. return str.str();
  80. }
  81. /** Parses a string in the major.minor.release.build format and stores the version numbers. */
  82. void fromString(const String& versionString)
  83. {
  84. Vector<BansheeEngine::String> tokens = StringUtil::split(versionString, ".");
  85. if(!tokens.empty())
  86. {
  87. major = parseINT32(tokens[0]);
  88. if (tokens.size() > 1)
  89. minor = parseINT32(tokens[1]);
  90. if (tokens.size() > 2)
  91. release = parseINT32(tokens[2]);
  92. if (tokens.size() > 3)
  93. build = parseINT32(tokens[3]);
  94. }
  95. }
  96. };
  97. /** Types of GPU vendors. */
  98. enum GPUVendor
  99. {
  100. GPU_UNKNOWN = 0,
  101. GPU_NVIDIA = 1,
  102. GPU_AMD = 2,
  103. GPU_INTEL = 3,
  104. GPU_VENDOR_COUNT = 4
  105. };
  106. /**
  107. * Holds information about render hardware and driver capabilities and allows you to easily set and query those
  108. * capabilities.
  109. */
  110. class BS_CORE_EXPORT RenderAPICapabilities
  111. {
  112. public:
  113. RenderAPICapabilities ();
  114. virtual ~RenderAPICapabilities ();
  115. /** Sets the current driver version. */
  116. void setDriverVersion(const DriverVersion& version)
  117. {
  118. mDriverVersion = version;
  119. }
  120. /** Returns current driver version. */
  121. DriverVersion getDriverVersion() const
  122. {
  123. return mDriverVersion;
  124. }
  125. /** Returns vendor of the currently used GPU. */
  126. GPUVendor getVendor() const
  127. {
  128. return mVendor;
  129. }
  130. /** Sets the GPU vendor. */
  131. void setVendor(GPUVendor v)
  132. {
  133. mVendor = v;
  134. }
  135. /** Parses a vendor string and returns an enum with the vendor if parsed succesfully. */
  136. static GPUVendor vendorFromString(const String& vendorString);
  137. /** Converts a vendor enum to a string. */
  138. static String vendorToString(GPUVendor v);
  139. /** Sets the maximum number of texture units per pipeline stage. */
  140. void setNumTextureUnits(GpuProgramType type, UINT16 num)
  141. {
  142. mNumTextureUnitsPerStage[type] = num;
  143. }
  144. /** Sets the maximum number of texture units in all pipeline stages. */
  145. void setNumCombinedTextureUnits(UINT16 num)
  146. {
  147. mNumCombinedTextureUnits = num;
  148. }
  149. /** Sets the maximum number of GPU param block buffers per pipeline stage. */
  150. void setNumGpuParamBlockBuffers(GpuProgramType type, UINT16 num)
  151. {
  152. mNumGpuParamBlocksPerStage[type] = num;
  153. }
  154. /** Sets the maximum number of GPU param block buffers in all pipeline stages. */
  155. void setNumCombinedGpuParamBlockBuffers(UINT16 num)
  156. {
  157. mNumCombinedUniformBlocks = num;
  158. }
  159. /** Sets maximum stencil buffer depth in bits. */
  160. void setStencilBufferBitDepth(UINT16 num)
  161. {
  162. mStencilBufferBitDepth = num;
  163. }
  164. /** Sets maximum number of bound vertex buffers. */
  165. void setMaxBoundVertexBuffers(UINT32 num)
  166. {
  167. mMaxBoundVertexBuffers = num;
  168. }
  169. /** Sets maximum number of simultaneously set render targets. */
  170. void setNumMultiRenderTargets(UINT16 num)
  171. {
  172. mNumMultiRenderTargets = num;
  173. }
  174. /** Returns the number of texture units supported per pipeline stage. */
  175. UINT16 getNumTextureUnits(GpuProgramType type) const
  176. {
  177. auto iterFind = mNumTextureUnitsPerStage.find(type);
  178. if(iterFind != mNumTextureUnitsPerStage.end())
  179. return iterFind->second;
  180. else
  181. return 0;
  182. }
  183. /** Returns the number of texture units supported in all pipeline stages. */
  184. UINT16 getNumCombinedTextureUnits() const
  185. {
  186. return mNumCombinedTextureUnits;
  187. }
  188. /** Returns the maximum number of bound GPU program param block buffers per pipeline stage. */
  189. UINT16 getNumGpuParamBlockBuffers(GpuProgramType type) const
  190. {
  191. auto iterFind = mNumGpuParamBlocksPerStage.find(type);
  192. if(iterFind != mNumGpuParamBlocksPerStage.end())
  193. return iterFind->second;
  194. else
  195. return 0;
  196. }
  197. /** Returns the maximum number of bound GPU program param block buffers in all pipeline stages. */
  198. UINT16 getNumCombinedGpuParamBlockBuffers() const
  199. {
  200. return mNumCombinedUniformBlocks;
  201. }
  202. /** Returns the maximum number of bits available for the stencil buffer. */
  203. UINT16 getStencilBufferBitDepth() const
  204. {
  205. return mStencilBufferBitDepth;
  206. }
  207. /** Returns the maximum number of vertex buffers that can be bound at once. */
  208. UINT32 getMaxBoundVertexBuffers() const
  209. {
  210. return mMaxBoundVertexBuffers;
  211. }
  212. /** Returns the maximum number of render targets we can render to simultaneously. */
  213. UINT16 getNumMultiRenderTargets() const
  214. {
  215. return mNumMultiRenderTargets;
  216. }
  217. /** Sets a capability flag indicating this capability is supported. */
  218. void setCapability(const Capabilities c)
  219. {
  220. UINT64 index = (CAPS_CATEGORY_MASK & c) >> BS_CAPS_BITSHIFT;
  221. mCapabilities[index] |= (c & ~CAPS_CATEGORY_MASK);
  222. }
  223. /** Remove a capability flag indicating this capability is not supported (default). */
  224. void unsetCapability(const Capabilities c)
  225. {
  226. UINT64 index = (CAPS_CATEGORY_MASK & c) >> BS_CAPS_BITSHIFT;
  227. mCapabilities[index] &= (~c | CAPS_CATEGORY_MASK);
  228. }
  229. /** Checks is the specified capability supported. */
  230. bool hasCapability(const Capabilities c) const
  231. {
  232. UINT64 index = (CAPS_CATEGORY_MASK & c) >> BS_CAPS_BITSHIFT;
  233. return (mCapabilities[index] & (c & ~CAPS_CATEGORY_MASK)) != 0;
  234. }
  235. /** Adds a shader profile to the list of render-system specific supported profiles. */
  236. void addShaderProfile(const String& profile)
  237. {
  238. mSupportedShaderProfiles.insert(profile);
  239. }
  240. /** Adds a mapping between GPU program profile enum and render-system specific profile name. */
  241. void addGpuProgramProfile(GpuProgramProfile gpuProgProfile, const String& rsSpecificProfile)
  242. {
  243. mGenericToSpecificShaderProfileMap[gpuProgProfile] = rsSpecificProfile;
  244. }
  245. /** Returns true if the provided profile is supported. */
  246. bool isShaderProfileSupported(const String& profile) const
  247. {
  248. return (mSupportedShaderProfiles.end() != mSupportedShaderProfiles.find(profile));
  249. }
  250. /** Returns a set of all supported shader profiles. */
  251. const Set<String>& getSupportedShaderProfiles() const
  252. {
  253. return mSupportedShaderProfiles;
  254. }
  255. /**
  256. * Converts a generic GpuProgramProfile identifier into a render-system specific one. Returns an empty string if
  257. * conversion cannot be done.
  258. */
  259. String gpuProgProfileToRSSpecificProfile(GpuProgramProfile gpuProgProfile) const
  260. {
  261. auto iterFind = mGenericToSpecificShaderProfileMap.find(gpuProgProfile);
  262. if(mGenericToSpecificShaderProfileMap.end() != iterFind)
  263. {
  264. return iterFind->second;
  265. }
  266. return "";
  267. }
  268. /** Gets the number of floating-point constants vertex programs support. */
  269. UINT16 getVertexProgramConstantFloatCount() const
  270. {
  271. return mVertexProgramConstantFloatCount;
  272. }
  273. /** Gets the number of integer constants vertex programs support. */
  274. UINT16 getVertexProgramConstantIntCount() const
  275. {
  276. return mVertexProgramConstantIntCount;
  277. }
  278. /** Gets the number of boolean constants vertex programs support. */
  279. UINT16 getVertexProgramConstantBoolCount() const
  280. {
  281. return mVertexProgramConstantBoolCount;
  282. }
  283. /** Gets the number of floating-point constants geometry programs support. */
  284. UINT16 getGeometryProgramConstantFloatCount() const
  285. {
  286. return mGeometryProgramConstantFloatCount;
  287. }
  288. /** Gets the number of integer constants geometry programs support. */
  289. UINT16 getGeometryProgramConstantIntCount() const
  290. {
  291. return mGeometryProgramConstantIntCount;
  292. }
  293. /** Gets the number of boolean constants geometry programs support. */
  294. UINT16 getGeometryProgramConstantBoolCount() const
  295. {
  296. return mGeometryProgramConstantBoolCount;
  297. }
  298. /** Gets the number of floating-point constants fragment programs support. */
  299. UINT16 getFragmentProgramConstantFloatCount() const
  300. {
  301. return mFragmentProgramConstantFloatCount;
  302. }
  303. /** Gets the number of integer constants fragment programs support. */
  304. UINT16 getFragmentProgramConstantIntCount() const
  305. {
  306. return mFragmentProgramConstantIntCount;
  307. }
  308. /** Gets the number of boolean constants fragment programs support. */
  309. UINT16 getFragmentProgramConstantBoolCount() const
  310. {
  311. return mFragmentProgramConstantBoolCount;
  312. }
  313. /** Sets the current GPU device name. */
  314. void setDeviceName(const String& name)
  315. {
  316. mDeviceName = name;
  317. }
  318. /** Gets the current GPU device name. */
  319. String getDeviceName() const
  320. {
  321. return mDeviceName;
  322. }
  323. /** Sets the number of floating-point constants vertex programs support. */
  324. void setVertexProgramConstantFloatCount(UINT16 c)
  325. {
  326. mVertexProgramConstantFloatCount = c;
  327. }
  328. /** Sets the number of integer constants vertex programs support. */
  329. void setVertexProgramConstantIntCount(UINT16 c)
  330. {
  331. mVertexProgramConstantIntCount = c;
  332. }
  333. /** Sets the number of boolean constants vertex programs support. */
  334. void setVertexProgramConstantBoolCount(UINT16 c)
  335. {
  336. mVertexProgramConstantBoolCount = c;
  337. }
  338. /** Sets the number of floating-point constants geometry programs support. */
  339. void setGeometryProgramConstantFloatCount(UINT16 c)
  340. {
  341. mGeometryProgramConstantFloatCount = c;
  342. }
  343. /** Sets the number of integer constants geometry programs support. */
  344. void setGeometryProgramConstantIntCount(UINT16 c)
  345. {
  346. mGeometryProgramConstantIntCount = c;
  347. }
  348. /** Sets the number of boolean constants geometry programs support. */
  349. void setGeometryProgramConstantBoolCount(UINT16 c)
  350. {
  351. mGeometryProgramConstantBoolCount = c;
  352. }
  353. /** Sets the number of floating-point constants fragment programs support. */
  354. void setFragmentProgramConstantFloatCount(UINT16 c)
  355. {
  356. mFragmentProgramConstantFloatCount = c;
  357. }
  358. /** Sets the number of integer constants fragment programs support. */
  359. void setFragmentProgramConstantIntCount(UINT16 c)
  360. {
  361. mFragmentProgramConstantIntCount = c;
  362. }
  363. /** Sets the number of boolean constants fragment programs support. */
  364. void setFragmentProgramConstantBoolCount(UINT16 c)
  365. {
  366. mFragmentProgramConstantBoolCount = c;
  367. }
  368. /** Sets the maximum point screen size in pixels. */
  369. void setMaxPointSize(float s)
  370. {
  371. mMaxPointSize = s;
  372. }
  373. /** Gets the maximum point screen size in pixels. */
  374. float getMaxPointSize(void) const
  375. {
  376. return mMaxPointSize;
  377. }
  378. /** Sets the number of vertices a single geometry program run can emit. */
  379. void setGeometryProgramNumOutputVertices(int numOutputVertices)
  380. {
  381. mGeometryProgramNumOutputVertices = numOutputVertices;
  382. }
  383. /** Gets the number of vertices a single geometry program run can emit. */
  384. int getGeometryProgramNumOutputVertices(void) const
  385. {
  386. return mGeometryProgramNumOutputVertices;
  387. }
  388. /** Get the identifier of the render system from which these capabilities were generated. */
  389. StringID getRenderAPIName() const
  390. {
  391. return mRenderAPIName;
  392. }
  393. /** Set the identifier of the render system from which these capabilities were generated. */
  394. void setRenderAPIName(const StringID& rs)
  395. {
  396. mRenderAPIName = rs;
  397. }
  398. private:
  399. /** Initializes vendor enum -> vendor name mappings. */
  400. static void initVendorStrings();
  401. private:
  402. static Vector<String> msGPUVendorStrings;
  403. DriverVersion mDriverVersion;
  404. GPUVendor mVendor = GPU_UNKNOWN;
  405. // The number of texture units available per stage
  406. Map<GpuProgramType, UINT16> mNumTextureUnitsPerStage;
  407. // Total number of texture units available
  408. UINT16 mNumCombinedTextureUnits = 0;
  409. // The number of uniform blocks available per stage
  410. Map<GpuProgramType, UINT16> mNumGpuParamBlocksPerStage;
  411. // Total number of uniform blocks available
  412. UINT16 mNumCombinedUniformBlocks = 0;
  413. // The stencil buffer bit depth
  414. UINT16 mStencilBufferBitDepth = 0;
  415. // Maximum number of vertex buffers we can bind at once
  416. UINT32 mMaxBoundVertexBuffers = 0;
  417. // Stores the capabilities flags.
  418. UINT32 mCapabilities[CAPS_CATEGORY_COUNT];
  419. // The name of the device as reported by the render system
  420. String mDeviceName;
  421. // The identifier associated with the render API for which these capabilities are valid
  422. StringID mRenderAPIName;
  423. // The number of floating-point constants vertex programs support
  424. UINT16 mVertexProgramConstantFloatCount = 0;
  425. // The number of integer constants vertex programs support
  426. UINT16 mVertexProgramConstantIntCount = 0;
  427. // The number of boolean constants vertex programs support
  428. UINT16 mVertexProgramConstantBoolCount = 0;
  429. // The number of floating-point constants geometry programs support
  430. UINT16 mGeometryProgramConstantFloatCount = 0;
  431. // The number of integer constants vertex geometry support
  432. UINT16 mGeometryProgramConstantIntCount = 0;
  433. // The number of boolean constants vertex geometry support
  434. UINT16 mGeometryProgramConstantBoolCount = 0;
  435. // The number of floating-point constants fragment programs support
  436. UINT16 mFragmentProgramConstantFloatCount = 0;
  437. // The number of integer constants fragment programs support
  438. UINT16 mFragmentProgramConstantIntCount = 0;
  439. // The number of boolean constants fragment programs support
  440. UINT16 mFragmentProgramConstantBoolCount = 0;
  441. // The number of simultaneous render targets supported
  442. UINT16 mNumMultiRenderTargets = 0;
  443. // The maximum point size in pixels
  444. float mMaxPointSize = 0.0f;
  445. // The number of vertices a geometry program can emit in a single run
  446. UINT32 mGeometryProgramNumOutputVertices = 0;
  447. // The list of supported shader profiles
  448. Set<String> mSupportedShaderProfiles;
  449. // Allows us to convert a generic shader profile to a render-system specific one
  450. UnorderedMap<GpuProgramProfile, String> mGenericToSpecificShaderProfileMap;
  451. };
  452. /** @} */
  453. /** @endcond */
  454. }