gfxDevice.cpp 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "gfx/gfxDevice.h"
  24. #include "gfx/gfxInit.h"
  25. #include "gfx/gfxCubemap.h"
  26. #include "gfx/primBuilder.h"
  27. #include "gfx/gfxDrawUtil.h"
  28. #include "gfx/gfxFence.h"
  29. #include "gfx/gfxFontRenderBatcher.h"
  30. #include "gfx/gfxPrimitiveBuffer.h"
  31. #include "gfx/gfxShader.h"
  32. #include "gfx/gfxStateBlock.h"
  33. #include "gfx/screenshot.h"
  34. #include "gfx/gfxStringEnumTranslate.h"
  35. #include "gfx/gfxTextureManager.h"
  36. #include "core/frameAllocator.h"
  37. #include "core/stream/fileStream.h"
  38. #include "core/strings/unicode.h"
  39. #include "core/util/journal/process.h"
  40. #include "core/util/safeDelete.h"
  41. #include "math/util/frustum.h"
  42. #include "console/consoleTypes.h"
  43. #include "console/engineAPI.h"
  44. GFXDevice * GFXDevice::smGFXDevice = NULL;
  45. bool GFXDevice::smWireframe = false;
  46. bool GFXDevice::smDisableVSync = true;
  47. F32 GFXDevice::smForcedPixVersion = -1.0f;
  48. bool GFXDevice::smDisableOcclusionQuery = false;
  49. bool gDisassembleAllShaders = false;
  50. void GFXDevice::initConsole()
  51. {
  52. GFXStringEnumTranslate::init();
  53. Con::addVariable( "$gfx::wireframe", TypeBool, &smWireframe,
  54. "Used to toggle wireframe rendering at runtime.\n"
  55. "@ingroup GFX\n" );
  56. Con::addVariable( "$gfx::disassembleAllShaders", TypeBool, &gDisassembleAllShaders,
  57. "On supported devices this will dump shader disassembly to the "
  58. "procedural shader folder.\n"
  59. "@ingroup GFX\n" );
  60. Con::addVariable( "$gfx::disableOcclusionQuery", TypeBool, &smDisableOcclusionQuery,
  61. "Debug helper that disables all hardware occlusion queries causing "
  62. "them to return only the visibile state.\n"
  63. "@ingroup GFX\n" );
  64. Con::addVariable( "$pref::Video::disableVerticalSync", TypeBool, &smDisableVSync,
  65. "Disables vertical sync on the active device.\n"
  66. "@note The video mode must be reset for the change to take affect.\n"
  67. "@ingroup GFX\n" );
  68. Con::addVariable( "$pref::Video::forcedPixVersion", TypeF32, &smForcedPixVersion,
  69. "Will force the shader model if the value is positive and less than the "
  70. "shader model supported by the active device. Use 0 for fixed function.\n"
  71. "@note The graphics device must be reset for the change to take affect.\n"
  72. "@ingroup GFX\n" );
  73. }
  74. GFXDevice::DeviceEventSignal& GFXDevice::getDeviceEventSignal()
  75. {
  76. static DeviceEventSignal theSignal;
  77. return theSignal;
  78. }
  79. GFXDevice::GFXDevice()
  80. {
  81. VECTOR_SET_ASSOCIATION( mVideoModes );
  82. VECTOR_SET_ASSOCIATION( mRTStack );
  83. mWorldMatrixDirty = false;
  84. mWorldStackSize = 0;
  85. mProjectionMatrixDirty = false;
  86. mViewMatrixDirty = false;
  87. mTextureMatrixCheckDirty = false;
  88. mViewMatrix.identity();
  89. mProjectionMatrix.identity();
  90. for( S32 i = 0; i < WORLD_STACK_MAX; i++ )
  91. mWorldMatrix[i].identity();
  92. AssertFatal(smGFXDevice == NULL, "Already a GFXDevice created! Bad!");
  93. smGFXDevice = this;
  94. // Vertex buffer cache
  95. mCurrVertexDecl = NULL;
  96. mVertexDeclDirty = false;
  97. for ( U32 i=0; i < VERTEX_STREAM_COUNT; i++ )
  98. {
  99. mVertexBufferDirty[i] = false;
  100. mVertexBufferFrequency[i] = 0;
  101. mVertexBufferFrequencyDirty[i] = false;
  102. }
  103. // Primitive buffer cache
  104. mPrimitiveBufferDirty = false;
  105. mTexturesDirty = false;
  106. // Use of TEXTURE_STAGE_COUNT in initialization is okay [7/2/2007 Pat]
  107. for(U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
  108. {
  109. mTextureDirty[i] = false;
  110. mCurrentTexture[i] = NULL;
  111. mNewTexture[i] = NULL;
  112. mCurrentCubemap[i] = NULL;
  113. mNewCubemap[i] = NULL;
  114. mCurrentCubemapArray[i] = NULL;
  115. mNewCubemapArray[i] = NULL;
  116. mTexType[i] = GFXTDT_Normal;
  117. mTextureMatrix[i].identity();
  118. mTextureMatrixDirty[i] = false;
  119. }
  120. mLightsDirty = false;
  121. for(U32 i = 0; i < LIGHT_STAGE_COUNT; i++)
  122. {
  123. mLightDirty[i] = false;
  124. mCurrentLightEnable[i] = false;
  125. }
  126. mGlobalAmbientColorDirty = false;
  127. mGlobalAmbientColor = LinearColorF(0.0f, 0.0f, 0.0f, 1.0f);
  128. mLightMaterialDirty = false;
  129. dMemset(&mCurrentLightMaterial, 0, sizeof(GFXLightMaterial));
  130. // State block
  131. mStateBlockDirty = false;
  132. mCurrentStateBlock = NULL;
  133. mNewStateBlock = NULL;
  134. mCurrentShaderConstBuffer = NULL;
  135. // misc
  136. mAllowRender = true;
  137. mCurrentRenderStyle = RS_Standard;
  138. mCurrentStereoTarget = -1;
  139. mStereoHeadTransform = MatrixF(1);
  140. mCanCurrentlyRender = false;
  141. mInitialized = false;
  142. mRTDirty = false;
  143. mViewport = RectI::Zero;
  144. mViewportDirty = false;
  145. mCurrentFrontBufferIdx = 0;
  146. mDeviceSwizzle32 = NULL;
  147. mDeviceSwizzle24 = NULL;
  148. mResourceListHead = NULL;
  149. mCardProfiler = NULL;
  150. // Initialize our drawing utility.
  151. mDrawer = NULL;
  152. mFrameTime = PlatformTimer::create();
  153. // Add a few system wide shader macros.
  154. GFXShader::addGlobalMacro( "TORQUE", "1" );
  155. GFXShader::addGlobalMacro( "TORQUE_VERSION", String::ToString(getVersionNumber()) );
  156. #if defined TORQUE_OS_WIN
  157. GFXShader::addGlobalMacro( "TORQUE_OS_WIN" );
  158. #elif defined TORQUE_OS_MAC
  159. GFXShader::addGlobalMacro( "TORQUE_OS_MAC" );
  160. #elif defined TORQUE_OS_LINUX
  161. GFXShader::addGlobalMacro( "TORQUE_OS_LINUX" );
  162. #endif
  163. mStereoTargets[0] = NULL;
  164. mStereoTargets[1] = NULL;
  165. }
  166. GFXDrawUtil* GFXDevice::getDrawUtil()
  167. {
  168. if (!mDrawer)
  169. {
  170. mDrawer = new GFXDrawUtil(this);
  171. }
  172. return mDrawer;
  173. }
  174. void GFXDevice::deviceInited()
  175. {
  176. getDeviceEventSignal().trigger(deInit);
  177. mDeviceStatistics.setPrefix("$GFXDeviceStatistics::");
  178. // Initialize the static helper textures.
  179. GBitmap temp( 2, 2, false, GFXFormatR8G8B8A8 );
  180. temp.fill( ColorI::ONE );
  181. GFXTexHandle::ONE.set( &temp, &GFXStaticTextureSRGBProfile, false, "GFXTexHandle::ONE" );
  182. temp.fill( ColorI::ZERO );
  183. GFXTexHandle::ZERO.set( &temp, &GFXStaticTextureSRGBProfile, false, "GFXTexHandle::ZERO" );
  184. temp.fill( ColorI( 128, 128, 255 ) );
  185. GFXTexHandle::ZUP.set( &temp, &GFXNormalMapProfile, false, "GFXTexHandle::ZUP" );
  186. }
  187. bool GFXDevice::destroy()
  188. {
  189. // Cleanup the static helper textures.
  190. GFXTexHandle::ONE.free();
  191. GFXTexHandle::ZERO.free();
  192. GFXTexHandle::ZUP.free();
  193. // Make this release its buffer.
  194. PrimBuild::shutdown();
  195. // Let people know we are shutting down
  196. getDeviceEventSignal().trigger(deDestroy);
  197. if(smGFXDevice)
  198. smGFXDevice->preDestroy();
  199. SAFE_DELETE(smGFXDevice);
  200. return true;
  201. }
  202. void GFXDevice::preDestroy()
  203. {
  204. // Delete draw util
  205. SAFE_DELETE( mDrawer );
  206. }
  207. GFXDevice::~GFXDevice()
  208. {
  209. smGFXDevice = NULL;
  210. // Clean up our current buffers.
  211. mCurrentPrimitiveBuffer = NULL;
  212. for ( U32 i=0; i < VERTEX_STREAM_COUNT; i++ )
  213. mCurrentVertexBuffer[i] = NULL;
  214. // Clear out our current texture references
  215. for (U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
  216. {
  217. mCurrentTexture[i] = NULL;
  218. mNewTexture[i] = NULL;
  219. mCurrentCubemap[i] = NULL;
  220. mNewCubemap[i] = NULL;
  221. mCurrentCubemapArray[i] = NULL;
  222. mNewCubemapArray[i] = NULL;
  223. }
  224. mCurrentRT = NULL;
  225. // Release all the unreferenced textures in the cache.
  226. mTextureManager->cleanupCache();
  227. // Check for resource leaks
  228. #ifdef TORQUE_DEBUG
  229. AssertFatal( GFXTextureObject::dumpActiveTOs() == 0, "There is a texture object leak, check the log for more details." );
  230. GFXPrimitiveBuffer::dumpActivePBs();
  231. #endif
  232. SAFE_DELETE( mTextureManager );
  233. SAFE_DELETE( mFrameTime );
  234. // Clear out our state block references
  235. mCurrentStateBlocks.clear();
  236. mNewStateBlock = NULL;
  237. mCurrentStateBlock = NULL;
  238. mCurrentShaderConstBuffer = NULL;
  239. /// End Block above BTR
  240. // -- Clear out resource list
  241. // Note: our derived class destructor will have already released resources.
  242. // Clearing this list saves us from having our resources (which are not deleted
  243. // just released) turn around and try to remove themselves from this list.
  244. while (mResourceListHead)
  245. {
  246. GFXResource * head = mResourceListHead;
  247. mResourceListHead = head->mNextResource;
  248. head->mPrevResource = NULL;
  249. head->mNextResource = NULL;
  250. head->mOwningDevice = NULL;
  251. }
  252. }
  253. GFXStateBlockRef GFXDevice::createStateBlock(const GFXStateBlockDesc& desc)
  254. {
  255. PROFILE_SCOPE( GFXDevice_CreateStateBlock );
  256. U32 hashValue = desc.getHashValue();
  257. if (mCurrentStateBlocks[hashValue])
  258. return mCurrentStateBlocks[hashValue];
  259. GFXStateBlockRef result = createStateBlockInternal(desc);
  260. result->registerResourceWithDevice(this);
  261. mCurrentStateBlocks[hashValue] = result;
  262. return result;
  263. }
  264. void GFXDevice::setStateBlock(GFXStateBlock* block)
  265. {
  266. AssertFatal(block, "NULL state block!");
  267. AssertFatal(block->getOwningDevice() == this, "This state doesn't apply to this device!");
  268. if (block != mCurrentStateBlock)
  269. {
  270. mStateDirty = true;
  271. mStateBlockDirty = true;
  272. mNewStateBlock = block;
  273. } else {
  274. mStateBlockDirty = false;
  275. mNewStateBlock = mCurrentStateBlock;
  276. }
  277. }
  278. void GFXDevice::setStateBlockByDesc( const GFXStateBlockDesc &desc )
  279. {
  280. PROFILE_SCOPE( GFXDevice_SetStateBlockByDesc );
  281. GFXStateBlock *block = createStateBlock( desc );
  282. setStateBlock( block );
  283. }
  284. void GFXDevice::setShaderConstBuffer(GFXShaderConstBuffer* buffer)
  285. {
  286. mCurrentShaderConstBuffer = buffer;
  287. }
  288. void GFXDevice::updateStates(bool forceSetAll /*=false*/)
  289. {
  290. PROFILE_SCOPE(GFXDevice_updateStates);
  291. if(forceSetAll)
  292. {
  293. bool rememberToEndScene = false;
  294. if(!canCurrentlyRender())
  295. {
  296. if (!beginScene())
  297. {
  298. AssertFatal(false, "GFXDevice::updateStates: Unable to beginScene!");
  299. }
  300. rememberToEndScene = true;
  301. }
  302. setMatrix( GFXMatrixProjection, mProjectionMatrix );
  303. setMatrix( GFXMatrixWorld, mWorldMatrix[mWorldStackSize] );
  304. setMatrix( GFXMatrixView, mViewMatrix );
  305. setVertexDecl( mCurrVertexDecl );
  306. for ( U32 i=0; i < VERTEX_STREAM_COUNT; i++ )
  307. {
  308. setVertexStream( i, mCurrentVertexBuffer[i] );
  309. setVertexStreamFrequency( i, mVertexBufferFrequency[i] );
  310. }
  311. if( mCurrentPrimitiveBuffer.isValid() ) // This could be NULL when the device is initalizing
  312. mCurrentPrimitiveBuffer->prepare();
  313. /// Stateblocks
  314. if ( mNewStateBlock )
  315. setStateBlockInternal(mNewStateBlock, true);
  316. mCurrentStateBlock = mNewStateBlock;
  317. for(U32 i = 0; i < getNumSamplers(); i++)
  318. {
  319. switch (mTexType[i])
  320. {
  321. case GFXTDT_Normal :
  322. {
  323. mCurrentTexture[i] = mNewTexture[i];
  324. setTextureInternal(i, mCurrentTexture[i]);
  325. }
  326. break;
  327. case GFXTDT_Cube :
  328. {
  329. mCurrentCubemap[i] = mNewCubemap[i];
  330. if (mCurrentCubemap[i])
  331. mCurrentCubemap[i]->setToTexUnit(i);
  332. else
  333. setTextureInternal(i, NULL);
  334. }
  335. break;
  336. case GFXTDT_CubeArray:
  337. {
  338. mCurrentCubemapArray[i] = mNewCubemapArray[i];
  339. if (mCurrentCubemapArray[i])
  340. mCurrentCubemapArray[i]->setToTexUnit(i);
  341. else
  342. setTextureInternal(i, NULL);
  343. }
  344. break;
  345. default:
  346. AssertFatal(false, "Unknown texture type!");
  347. break;
  348. }
  349. }
  350. // Set our material
  351. setLightMaterialInternal(mCurrentLightMaterial);
  352. // Set our lights
  353. for(U32 i = 0; i < LIGHT_STAGE_COUNT; i++)
  354. {
  355. setLightInternal(i, mCurrentLight[i], mCurrentLightEnable[i]);
  356. }
  357. _updateRenderTargets();
  358. if(rememberToEndScene)
  359. endScene();
  360. return;
  361. }
  362. if (!mStateDirty)
  363. return;
  364. // Normal update logic begins here.
  365. mStateDirty = false;
  366. // Update Projection Matrix
  367. if( mProjectionMatrixDirty )
  368. {
  369. setMatrix( GFXMatrixProjection, mProjectionMatrix );
  370. mProjectionMatrixDirty = false;
  371. }
  372. // Update World Matrix
  373. if( mWorldMatrixDirty )
  374. {
  375. setMatrix( GFXMatrixWorld, mWorldMatrix[mWorldStackSize] );
  376. mWorldMatrixDirty = false;
  377. }
  378. // Update View Matrix
  379. if( mViewMatrixDirty )
  380. {
  381. setMatrix( GFXMatrixView, mViewMatrix );
  382. mViewMatrixDirty = false;
  383. }
  384. if( mTextureMatrixCheckDirty )
  385. {
  386. for( S32 i = 0; i < getNumSamplers(); i++ )
  387. {
  388. if( mTextureMatrixDirty[i] )
  389. {
  390. mTextureMatrixDirty[i] = false;
  391. setMatrix( (GFXMatrixType)(GFXMatrixTexture + i), mTextureMatrix[i] );
  392. }
  393. }
  394. mTextureMatrixCheckDirty = false;
  395. }
  396. // Update the vertex declaration.
  397. if ( mVertexDeclDirty )
  398. {
  399. setVertexDecl( mCurrVertexDecl );
  400. mVertexDeclDirty = false;
  401. }
  402. // Update the vertex buffers.
  403. for ( U32 i=0; i < VERTEX_STREAM_COUNT; i++ )
  404. {
  405. if ( mVertexBufferDirty[i] )
  406. {
  407. setVertexStream( i, mCurrentVertexBuffer[i] );
  408. mVertexBufferDirty[i] = false;
  409. }
  410. if ( mVertexBufferFrequencyDirty[i] )
  411. {
  412. setVertexStreamFrequency( i, mVertexBufferFrequency[i] );
  413. mVertexBufferFrequencyDirty[i] = false;
  414. }
  415. }
  416. // Update primitive buffer
  417. //
  418. // NOTE: It is very important to set the primitive buffer AFTER the vertex buffer
  419. // because in order to draw indexed primitives in DX8, the call to SetIndicies
  420. // needs to include the base vertex offset, and the DX8 GFXDevice relies on
  421. // having mCurrentVB properly assigned before the call to setIndices -patw
  422. if( mPrimitiveBufferDirty )
  423. {
  424. if( mCurrentPrimitiveBuffer.isValid() ) // This could be NULL when the device is initalizing
  425. mCurrentPrimitiveBuffer->prepare();
  426. mPrimitiveBufferDirty = false;
  427. }
  428. // NOTE: With state blocks, it's now important to update state before setting textures
  429. // some devices (e.g. OpenGL) set states on the texture and we need that information before
  430. // the texture is activated.
  431. if (mStateBlockDirty)
  432. {
  433. setStateBlockInternal(mNewStateBlock, false);
  434. mCurrentStateBlock = mNewStateBlock;
  435. mStateBlockDirty = false;
  436. }
  437. _updateRenderTargets();
  438. if( mTexturesDirty )
  439. {
  440. mTexturesDirty = false;
  441. for(U32 i = 0; i < getNumSamplers(); i++)
  442. {
  443. if(!mTextureDirty[i])
  444. continue;
  445. mTextureDirty[i] = false;
  446. switch (mTexType[i])
  447. {
  448. case GFXTDT_Normal :
  449. {
  450. mCurrentTexture[i] = mNewTexture[i];
  451. setTextureInternal(i, mCurrentTexture[i]);
  452. }
  453. break;
  454. case GFXTDT_Cube :
  455. {
  456. mCurrentCubemap[i] = mNewCubemap[i];
  457. if (mCurrentCubemap[i])
  458. mCurrentCubemap[i]->setToTexUnit(i);
  459. else
  460. setTextureInternal(i, NULL);
  461. }
  462. break;
  463. case GFXTDT_CubeArray:
  464. {
  465. mCurrentCubemapArray[i] = mNewCubemapArray[i];
  466. if (mCurrentCubemapArray[i])
  467. mCurrentCubemapArray[i]->setToTexUnit(i);
  468. else
  469. setTextureInternal(i, NULL);
  470. }
  471. break;
  472. default:
  473. AssertFatal(false, "Unknown texture type!");
  474. break;
  475. }
  476. }
  477. }
  478. // Set light material
  479. if(mLightMaterialDirty)
  480. {
  481. setLightMaterialInternal(mCurrentLightMaterial);
  482. mLightMaterialDirty = false;
  483. }
  484. // Set our lights
  485. if(mLightsDirty)
  486. {
  487. mLightsDirty = false;
  488. for(U32 i = 0; i < LIGHT_STAGE_COUNT; i++)
  489. {
  490. if(!mLightDirty[i])
  491. continue;
  492. mLightDirty[i] = false;
  493. setLightInternal(i, mCurrentLight[i], mCurrentLightEnable[i]);
  494. }
  495. }
  496. _updateRenderTargets();
  497. #ifdef TORQUE_DEBUG_RENDER
  498. doParanoidStateCheck();
  499. #endif
  500. }
  501. void GFXDevice::clearTextureStateImmediate(U32 stage)
  502. {
  503. mCurrentTexture[stage] = NULL;
  504. mCurrentCubemap[stage] = NULL;
  505. setTextureInternal(stage, NULL);
  506. }
  507. void GFXDevice::setPrimitiveBuffer( GFXPrimitiveBuffer *buffer )
  508. {
  509. if( buffer == mCurrentPrimitiveBuffer )
  510. return;
  511. mCurrentPrimitiveBuffer = buffer;
  512. mPrimitiveBufferDirty = true;
  513. mStateDirty = true;
  514. }
  515. void GFXDevice::drawPrimitive( U32 primitiveIndex )
  516. {
  517. AssertFatal( mCurrentPrimitiveBuffer.isValid(), "Trying to call drawPrimitive with no current primitive buffer, call setPrimitiveBuffer()" );
  518. AssertFatal( primitiveIndex < mCurrentPrimitiveBuffer->mPrimitiveCount, "Out of range primitive index.");
  519. drawPrimitive( mCurrentPrimitiveBuffer->mPrimitiveArray[primitiveIndex] );
  520. }
  521. void GFXDevice::drawPrimitive( const GFXPrimitive &prim )
  522. {
  523. // Do NOT add index buffer offset to this call, it will be added by drawIndexedPrimitive
  524. drawIndexedPrimitive( prim.type,
  525. prim.startVertex,
  526. prim.minIndex,
  527. prim.numVertices,
  528. prim.startIndex,
  529. prim.numPrimitives );
  530. }
  531. void GFXDevice::drawPrimitives()
  532. {
  533. AssertFatal( mCurrentPrimitiveBuffer.isValid(), "Trying to call drawPrimitive with no current primitive buffer, call setPrimitiveBuffer()" );
  534. GFXPrimitive *info = NULL;
  535. for( U32 i = 0; i < mCurrentPrimitiveBuffer->mPrimitiveCount; i++ ) {
  536. info = &mCurrentPrimitiveBuffer->mPrimitiveArray[i];
  537. // Do NOT add index buffer offset to this call, it will be added by drawIndexedPrimitive
  538. drawIndexedPrimitive( info->type,
  539. info->startVertex,
  540. info->minIndex,
  541. info->numVertices,
  542. info->startIndex,
  543. info->numPrimitives );
  544. }
  545. }
  546. DefineEngineFunction( getDisplayDeviceList, String, (),,
  547. "Returns a tab-seperated string of the detected devices across all adapters.\n"
  548. "@ingroup GFX\n" )
  549. {
  550. Vector<GFXAdapter*> adapters;
  551. GFXInit::getAdapters(&adapters);
  552. StringBuilder str;
  553. for (S32 i=0; i<adapters.size(); i++)
  554. {
  555. if (i)
  556. str.append( '\t' );
  557. str.append(adapters[i]->mName);
  558. }
  559. return str.end();
  560. }
  561. void GFXDevice::setFrustum( F32 left,
  562. F32 right,
  563. F32 bottom,
  564. F32 top,
  565. F32 nearPlane,
  566. F32 farPlane,
  567. bool bRotate )
  568. {
  569. // store values
  570. mFrustum.set(false, left, right, top, bottom, nearPlane, farPlane);
  571. // compute matrix
  572. MatrixF projection;
  573. mFrustum.getProjectionMatrix(&projection, bRotate);
  574. setProjectionMatrix( projection );
  575. }
  576. void GFXDevice::setFrustum( const Frustum& frust, bool bRotate )
  577. {
  578. // store values
  579. mFrustum = frust;
  580. // compute matrix
  581. MatrixF projection;
  582. mFrustum.getProjectionMatrix(&projection, bRotate);
  583. setProjectionMatrix( projection );
  584. }
  585. void GFXDevice::getFrustum( F32 *left, F32 *right, F32 *bottom, F32 *top, F32 *nearPlane, F32 *farPlane, bool *isOrtho ) const
  586. {
  587. if ( left ) *left = mFrustum.getNearLeft();
  588. if ( right ) *right = mFrustum.getNearRight();
  589. if ( bottom ) *bottom = mFrustum.getNearBottom();
  590. if ( top ) *top = mFrustum.getNearTop();
  591. if ( nearPlane ) *nearPlane = mFrustum.getNearDist();
  592. if ( farPlane ) *farPlane = mFrustum.getFarDist();
  593. if ( isOrtho ) *isOrtho = mFrustum.isOrtho();
  594. }
  595. void GFXDevice::setOrtho( F32 left,
  596. F32 right,
  597. F32 bottom,
  598. F32 top,
  599. F32 nearPlane,
  600. F32 farPlane,
  601. bool doRotate )
  602. {
  603. // store values
  604. mFrustum.set(true, left, right, top, bottom, nearPlane, farPlane);
  605. // compute matrix
  606. MatrixF projection;
  607. mFrustum.getProjectionMatrix(&projection, doRotate);
  608. setProjectionMatrix( projection );
  609. }
  610. Point2F GFXDevice::getWorldToScreenScale() const
  611. {
  612. Point2F scale;
  613. const RectI &viewport = getViewport();
  614. if ( mFrustum.isOrtho() )
  615. scale.set( viewport.extent.x / mFrustum.getWidth(),
  616. viewport.extent.y / mFrustum.getHeight() );
  617. else
  618. scale.set( ( mFrustum.getNearDist() * viewport.extent.x ) / mFrustum.getWidth(),
  619. ( mFrustum.getNearDist() * viewport.extent.y ) / mFrustum.getHeight() );
  620. return scale;
  621. }
  622. //-----------------------------------------------------------------------------
  623. // Set Light
  624. //-----------------------------------------------------------------------------
  625. void GFXDevice::setLight(U32 stage, GFXLightInfo* light)
  626. {
  627. AssertFatal(stage < LIGHT_STAGE_COUNT, "GFXDevice::setLight - out of range stage!");
  628. if(!mLightDirty[stage])
  629. {
  630. mStateDirty = true;
  631. mLightsDirty = true;
  632. mLightDirty[stage] = true;
  633. }
  634. mCurrentLightEnable[stage] = (light != NULL);
  635. if(mCurrentLightEnable[stage])
  636. mCurrentLight[stage] = *light;
  637. }
  638. //-----------------------------------------------------------------------------
  639. // Set Light Material
  640. //-----------------------------------------------------------------------------
  641. void GFXDevice::setLightMaterial(const GFXLightMaterial& mat)
  642. {
  643. mCurrentLightMaterial = mat;
  644. mLightMaterialDirty = true;
  645. mStateDirty = true;
  646. }
  647. void GFXDevice::setGlobalAmbientColor(const LinearColorF& color)
  648. {
  649. if(mGlobalAmbientColor != color)
  650. {
  651. mGlobalAmbientColor = color;
  652. mGlobalAmbientColorDirty = true;
  653. }
  654. }
  655. //-----------------------------------------------------------------------------
  656. // Set texture
  657. //-----------------------------------------------------------------------------
  658. void GFXDevice::setTexture( U32 stage, GFXTextureObject *texture )
  659. {
  660. AssertFatal(stage < getNumSamplers(), "GFXDevice::setTexture - out of range stage!");
  661. if ( mTexType[stage] == GFXTDT_Normal &&
  662. ( ( mTextureDirty[stage] && mNewTexture[stage].getPointer() == texture ) ||
  663. ( !mTextureDirty[stage] && mCurrentTexture[stage].getPointer() == texture ) ) )
  664. return;
  665. mStateDirty = true;
  666. mTexturesDirty = true;
  667. mTextureDirty[stage] = true;
  668. mNewTexture[stage] = texture;
  669. mTexType[stage] = GFXTDT_Normal;
  670. // Clear out the cubemaps
  671. mNewCubemap[stage] = NULL;
  672. mCurrentCubemap[stage] = NULL;
  673. mNewCubemapArray[stage] = NULL;
  674. mCurrentCubemapArray[stage] = NULL;
  675. }
  676. //-----------------------------------------------------------------------------
  677. // Set cube texture
  678. //-----------------------------------------------------------------------------
  679. void GFXDevice::setCubeTexture( U32 stage, GFXCubemap *cubemap )
  680. {
  681. AssertFatal(stage < getNumSamplers(), "GFXDevice::setTexture - out of range stage!");
  682. if ( mTexType[stage] == GFXTDT_Cube &&
  683. ( ( mTextureDirty[stage] && mNewCubemap[stage].getPointer() == cubemap) ||
  684. ( !mTextureDirty[stage] && mCurrentCubemap[stage].getPointer() == cubemap) ) )
  685. return;
  686. mStateDirty = true;
  687. mTexturesDirty = true;
  688. mTextureDirty[stage] = true;
  689. mNewCubemap[stage] = cubemap;
  690. mTexType[stage] = GFXTDT_Cube;
  691. // Clear out textures
  692. mNewTexture[stage] = NULL;
  693. mCurrentTexture[stage] = NULL;
  694. mNewCubemapArray[stage] = NULL;
  695. mCurrentCubemapArray[stage] = NULL;
  696. }
  697. //-----------------------------------------------------------------------------
  698. // Set cube texture array
  699. //-----------------------------------------------------------------------------
  700. void GFXDevice::setCubeArrayTexture(U32 stage, GFXCubemapArray *cubemapArray)
  701. {
  702. AssertFatal(stage < getNumSamplers(), "GFXDevice::setTexture - out of range stage!");
  703. if (mTexType[stage] == GFXTDT_CubeArray &&
  704. ((mTextureDirty[stage] && mNewCubemapArray[stage].getPointer() == cubemapArray) ||
  705. (!mTextureDirty[stage] && mCurrentCubemapArray[stage].getPointer() == cubemapArray)))
  706. return;
  707. mStateDirty = true;
  708. mTexturesDirty = true;
  709. mTextureDirty[stage] = true;
  710. mNewCubemapArray[stage] = cubemapArray;
  711. mTexType[stage] = GFXTDT_CubeArray;
  712. // Clear out textures
  713. mNewTexture[stage] = NULL;
  714. mCurrentTexture[stage] = NULL;
  715. mNewCubemap[stage] = NULL;
  716. mCurrentCubemap[stage] = NULL;
  717. }
  718. //------------------------------------------------------------------------------
  719. inline bool GFXDevice::beginScene()
  720. {
  721. AssertFatal( mCanCurrentlyRender == false, "GFXDevice::beginScene() - The scene has already begun!" );
  722. mDeviceStatistics.clear();
  723. // Send the start of frame signal.
  724. getDeviceEventSignal().trigger( GFXDevice::deStartOfFrame );
  725. mFrameTime->reset();
  726. return beginSceneInternal();
  727. }
  728. inline void GFXDevice::endScene()
  729. {
  730. AssertFatal( mCanCurrentlyRender == true, "GFXDevice::endScene() - The scene has already ended!" );
  731. // End frame signal
  732. getDeviceEventSignal().trigger( GFXDevice::deEndOfFrame );
  733. endSceneInternal();
  734. mDeviceStatistics.exportToConsole();
  735. }
  736. inline void GFXDevice::beginField()
  737. {
  738. AssertFatal( mCanCurrentlyRender == true, "GFXDevice::beginField() - The scene has not yet begun!" );
  739. // Send the start of field signal.
  740. getDeviceEventSignal().trigger( GFXDevice::deStartOfField );
  741. }
  742. inline void GFXDevice::endField()
  743. {
  744. AssertFatal( mCanCurrentlyRender == true, "GFXDevice::endField() - The scene has not yet begun!" );
  745. // Send the end of field signal.
  746. getDeviceEventSignal().trigger( GFXDevice::deEndOfField );
  747. }
  748. void GFXDevice::setViewport( const RectI &inRect )
  749. {
  750. // Clip the rect against the renderable size.
  751. Point2I size = mCurrentRT->getSize();
  752. RectI maxRect(Point2I(0,0), size);
  753. RectI rect = inRect;
  754. rect.intersect(maxRect);
  755. if ( mViewport != rect )
  756. {
  757. mViewport = rect;
  758. mViewportDirty = true;
  759. }
  760. }
  761. void GFXDevice::pushActiveRenderTarget()
  762. {
  763. // Push the current target on to the stack.
  764. mRTStack.push_back( mCurrentRT );
  765. }
  766. void GFXDevice::popActiveRenderTarget()
  767. {
  768. AssertFatal( mRTStack.size() > 0, "GFXDevice::popActiveRenderTarget() - stack is empty!" );
  769. // Restore the last item on the stack and pop.
  770. setActiveRenderTarget( mRTStack.last() );
  771. mRTStack.pop_back();
  772. }
  773. void GFXDevice::setActiveRenderTarget( GFXTarget *target, bool updateViewport )
  774. {
  775. AssertFatal( target,
  776. "GFXDevice::setActiveRenderTarget - must specify a render target!" );
  777. if ( target == mCurrentRT )
  778. return;
  779. // If we're not dirty then store the
  780. // current RT for deactivation later.
  781. if ( !mRTDirty )
  782. {
  783. // Deactivate the target queued for deactivation
  784. if(mRTDeactivate)
  785. mRTDeactivate->deactivate();
  786. mRTDeactivate = mCurrentRT;
  787. }
  788. mRTDirty = true;
  789. mCurrentRT = target;
  790. // When a target changes we also change the viewport
  791. // to match it. This causes problems when the viewport
  792. // has been modified for clipping to a GUI bounds.
  793. //
  794. // We should consider removing this and making it the
  795. // responsibility of the caller to set a proper viewport
  796. // when the target is changed.
  797. if ( updateViewport )
  798. {
  799. setViewport( RectI( Point2I::Zero, mCurrentRT->getSize() ) );
  800. }
  801. }
  802. /// Helper class for GFXDevice::describeResources.
  803. class DescriptionOutputter
  804. {
  805. /// Are we writing to a file?
  806. bool mWriteToFile;
  807. /// File if we are writing to a file
  808. FileStream mFile;
  809. public:
  810. DescriptionOutputter(const char* file)
  811. {
  812. mWriteToFile = false;
  813. // If we've been given what could be a valid file path, open it.
  814. if(file && file[0] != '\0')
  815. {
  816. mWriteToFile = mFile.open(file, Torque::FS::File::Write);
  817. // Note that it is safe to retry. If this is hit, we'll just write to the console instead of to the file.
  818. AssertFatal(mWriteToFile, avar("DescriptionOutputter::DescriptionOutputter - could not open file %s", file));
  819. }
  820. }
  821. ~DescriptionOutputter()
  822. {
  823. // Close the file
  824. if(mWriteToFile)
  825. mFile.close();
  826. }
  827. /// Writes line to the file or to the console, depending on what we want.
  828. void write(const char* line)
  829. {
  830. if(mWriteToFile)
  831. mFile.writeLine((const U8*)line);
  832. else
  833. Con::printf(line);
  834. }
  835. };
  836. #ifndef TORQUE_SHIPPING
  837. void GFXDevice::dumpStates( const char *fileName ) const
  838. {
  839. DescriptionOutputter output(fileName);
  840. output.write("Current state");
  841. if (!mCurrentStateBlock.isNull())
  842. output.write(mCurrentStateBlock->getDesc().describeSelf().c_str());
  843. else
  844. output.write("No state!");
  845. output.write("\nAll states:\n");
  846. GFXResource* walk = mResourceListHead;
  847. while(walk)
  848. {
  849. const GFXStateBlock* sb = dynamic_cast<const GFXStateBlock*>(walk);
  850. if (sb)
  851. {
  852. output.write(sb->getDesc().describeSelf().c_str());
  853. }
  854. walk = walk->getNextResource();
  855. }
  856. }
  857. #endif
  858. void GFXDevice::listResources(bool unflaggedOnly)
  859. {
  860. U32 numTextures = 0, numShaders = 0, numRenderToTextureTargs = 0, numWindowTargs = 0;
  861. U32 numCubemaps = 0, numVertexBuffers = 0, numPrimitiveBuffers = 0, numFences = 0;
  862. U32 numStateBlocks = 0;
  863. GFXResource* walk = mResourceListHead;
  864. while(walk)
  865. {
  866. if(unflaggedOnly && walk->isFlagged())
  867. {
  868. walk = walk->getNextResource();
  869. continue;
  870. }
  871. if(dynamic_cast<GFXTextureObject*>(walk))
  872. numTextures++;
  873. else if(dynamic_cast<GFXShader*>(walk))
  874. numShaders++;
  875. else if(dynamic_cast<GFXTextureTarget*>(walk))
  876. numRenderToTextureTargs++;
  877. else if(dynamic_cast<GFXWindowTarget*>(walk))
  878. numWindowTargs++;
  879. else if(dynamic_cast<GFXCubemap*>(walk))
  880. numCubemaps++;
  881. else if(dynamic_cast<GFXVertexBuffer*>(walk))
  882. numVertexBuffers++;
  883. else if(dynamic_cast<GFXPrimitiveBuffer*>(walk))
  884. numPrimitiveBuffers++;
  885. else if(dynamic_cast<GFXFence*>(walk))
  886. numFences++;
  887. else if (dynamic_cast<GFXStateBlock*>(walk))
  888. numStateBlocks++;
  889. else
  890. Con::warnf("Unknown resource: %x", walk);
  891. walk = walk->getNextResource();
  892. }
  893. const char* flag = unflaggedOnly ? "unflagged" : "allocated";
  894. Con::printf("GFX currently has:");
  895. Con::printf(" %i %s textures", numTextures, flag);
  896. Con::printf(" %i %s shaders", numShaders, flag);
  897. Con::printf(" %i %s texture targets", numRenderToTextureTargs, flag);
  898. Con::printf(" %i %s window targets", numWindowTargs, flag);
  899. Con::printf(" %i %s cubemaps", numCubemaps, flag);
  900. Con::printf(" %i %s vertex buffers", numVertexBuffers, flag);
  901. Con::printf(" %i %s primitive buffers", numPrimitiveBuffers, flag);
  902. Con::printf(" %i %s fences", numFences, flag);
  903. Con::printf(" %i %s state blocks", numStateBlocks, flag);
  904. }
  905. void GFXDevice::fillResourceVectors(const char* resNames, bool unflaggedOnly, Vector<GFXResource*> &textureObjects,
  906. Vector<GFXResource*> &textureTargets, Vector<GFXResource*> &windowTargets, Vector<GFXResource*> &vertexBuffers,
  907. Vector<GFXResource*> &primitiveBuffers, Vector<GFXResource*> &fences, Vector<GFXResource*> &cubemaps,
  908. Vector<GFXResource*> &shaders, Vector<GFXResource*> &stateblocks)
  909. {
  910. bool describeTexture = true, describeTextureTarget = true, describeWindowTarget = true, describeVertexBuffer = true,
  911. describePrimitiveBuffer = true, describeFence = true, describeCubemap = true, describeShader = true,
  912. describeStateBlock = true;
  913. // If we didn't specify a string of names, we'll print all of them
  914. if(resNames && resNames[0] != '\0')
  915. {
  916. // If we did specify a string of names, determine which names
  917. describeTexture = (dStrstr(resNames, "GFXTextureObject") != NULL);
  918. describeTextureTarget = (dStrstr(resNames, "GFXTextureTarget") != NULL);
  919. describeWindowTarget = (dStrstr(resNames, "GFXWindowTarget") != NULL);
  920. describeVertexBuffer = (dStrstr(resNames, "GFXVertexBuffer") != NULL);
  921. describePrimitiveBuffer = (dStrstr(resNames, "GFXPrimitiveBuffer") != NULL);
  922. describeFence = (dStrstr(resNames, "GFXFence") != NULL);
  923. describeCubemap = (dStrstr(resNames, "GFXCubemap") != NULL);
  924. describeShader = (dStrstr(resNames, "GFXShader") != NULL);
  925. describeStateBlock = (dStrstr(resNames, "GFXStateBlock") != NULL);
  926. }
  927. // Start going through the list
  928. GFXResource* walk = mResourceListHead;
  929. while(walk)
  930. {
  931. // If we only want unflagged resources, skip all flagged resources
  932. if(unflaggedOnly && walk->isFlagged())
  933. {
  934. walk = walk->getNextResource();
  935. continue;
  936. }
  937. // All of the following checks go through the same logic.
  938. // if(describingThisResource)
  939. // {
  940. // ResourceType* type = dynamic_cast<ResourceType*>(walk)
  941. // if(type)
  942. // {
  943. // typeVector.push_back(type);
  944. // walk = walk->getNextResource();
  945. // continue;
  946. // }
  947. // }
  948. if(describeTexture)
  949. {
  950. GFXTextureObject* tex = dynamic_cast<GFXTextureObject*>(walk);
  951. {
  952. if(tex)
  953. {
  954. textureObjects.push_back(tex);
  955. walk = walk->getNextResource();
  956. continue;
  957. }
  958. }
  959. }
  960. if(describeShader)
  961. {
  962. GFXShader* shd = dynamic_cast<GFXShader*>(walk);
  963. if(shd)
  964. {
  965. shaders.push_back(shd);
  966. walk = walk->getNextResource();
  967. continue;
  968. }
  969. }
  970. if(describeVertexBuffer)
  971. {
  972. GFXVertexBuffer* buf = dynamic_cast<GFXVertexBuffer*>(walk);
  973. if(buf)
  974. {
  975. vertexBuffers.push_back(buf);
  976. walk = walk->getNextResource();
  977. continue;
  978. }
  979. }
  980. if(describePrimitiveBuffer)
  981. {
  982. GFXPrimitiveBuffer* buf = dynamic_cast<GFXPrimitiveBuffer*>(walk);
  983. if(buf)
  984. {
  985. primitiveBuffers.push_back(buf);
  986. walk = walk->getNextResource();
  987. continue;
  988. }
  989. }
  990. if(describeTextureTarget)
  991. {
  992. GFXTextureTarget* targ = dynamic_cast<GFXTextureTarget*>(walk);
  993. if(targ)
  994. {
  995. textureTargets.push_back(targ);
  996. walk = walk->getNextResource();
  997. continue;
  998. }
  999. }
  1000. if(describeWindowTarget)
  1001. {
  1002. GFXWindowTarget* targ = dynamic_cast<GFXWindowTarget*>(walk);
  1003. if(targ)
  1004. {
  1005. windowTargets.push_back(targ);
  1006. walk = walk->getNextResource();
  1007. continue;
  1008. }
  1009. }
  1010. if(describeCubemap)
  1011. {
  1012. GFXCubemap* cube = dynamic_cast<GFXCubemap*>(walk);
  1013. if(cube)
  1014. {
  1015. cubemaps.push_back(cube);
  1016. walk = walk->getNextResource();
  1017. continue;
  1018. }
  1019. }
  1020. if(describeFence)
  1021. {
  1022. GFXFence* fence = dynamic_cast<GFXFence*>(walk);
  1023. if(fence)
  1024. {
  1025. fences.push_back(fence);
  1026. walk = walk->getNextResource();
  1027. continue;
  1028. }
  1029. }
  1030. if (describeStateBlock)
  1031. {
  1032. GFXStateBlock* sb = dynamic_cast<GFXStateBlock*>(walk);
  1033. if (sb)
  1034. {
  1035. stateblocks.push_back(sb);
  1036. walk = walk->getNextResource();
  1037. continue;
  1038. }
  1039. }
  1040. // Wasn't something we were looking for
  1041. walk = walk->getNextResource();
  1042. }
  1043. }
  1044. void GFXDevice::describeResources(const char* resNames, const char* filePath, bool unflaggedOnly)
  1045. {
  1046. const U32 numResourceTypes = 9;
  1047. Vector<GFXResource*> resVectors[numResourceTypes];
  1048. const char* reslabels[numResourceTypes] = { "texture", "texture target", "window target", "vertex buffers", "primitive buffers", "fences", "cubemaps", "shaders", "stateblocks" };
  1049. // Fill the vectors with the right resources
  1050. fillResourceVectors(resNames, unflaggedOnly, resVectors[0], resVectors[1], resVectors[2], resVectors[3],
  1051. resVectors[4], resVectors[5], resVectors[6], resVectors[7], resVectors[8]);
  1052. // Helper object
  1053. DescriptionOutputter output(filePath);
  1054. // Print the info to the file
  1055. // Note that we check if we have any objects of that type.
  1056. for (U32 i = 0; i < numResourceTypes; i++)
  1057. {
  1058. if (resVectors[i].size())
  1059. {
  1060. // Header
  1061. String header = String::ToString("--------Dumping GFX %s descriptions...----------", reslabels[i]);
  1062. output.write(header);
  1063. // Data
  1064. for (U32 j = 0; j < resVectors[i].size(); j++)
  1065. {
  1066. GFXResource* resource = resVectors[i][j];
  1067. String dataline = String::ToString("Addr: %x %s", resource, resource->describeSelf().c_str());
  1068. output.write(dataline.c_str());
  1069. }
  1070. // Footer
  1071. output.write("--------------------Done---------------------");
  1072. output.write("");
  1073. }
  1074. }
  1075. }
  1076. void GFXDevice::flagCurrentResources()
  1077. {
  1078. GFXResource* walk = mResourceListHead;
  1079. while(walk)
  1080. {
  1081. walk->setFlag();
  1082. walk = walk->getNextResource();
  1083. }
  1084. }
  1085. void GFXDevice::clearResourceFlags()
  1086. {
  1087. GFXResource* walk = mResourceListHead;
  1088. while(walk)
  1089. {
  1090. walk->clearFlag();
  1091. walk = walk->getNextResource();
  1092. }
  1093. }
  1094. DefineEngineFunction( listGFXResources, void, ( bool unflaggedOnly ), ( false ),
  1095. "Returns a list of the unflagged GFX resources. See flagCurrentGFXResources for usage details.\n"
  1096. "@ingroup GFX\n"
  1097. "@see flagCurrentGFXResources, clearGFXResourceFlags, describeGFXResources" )
  1098. {
  1099. GFX->listResources(unflaggedOnly);
  1100. }
  1101. DefineEngineFunction( flagCurrentGFXResources, void, (),,
  1102. "@brief Flags all currently allocated GFX resources.\n"
  1103. "Used for resource allocation and leak tracking by flagging "
  1104. "current resources then dumping a list of unflagged resources "
  1105. "at some later point in execution.\n"
  1106. "@ingroup GFX\n"
  1107. "@see listGFXResources, clearGFXResourceFlags, describeGFXResources" )
  1108. {
  1109. GFX->flagCurrentResources();
  1110. }
  1111. DefineEngineFunction( clearGFXResourceFlags, void, (),,
  1112. "Clears the flagged state on all allocated GFX resources. "
  1113. "See flagCurrentGFXResources for usage details.\n"
  1114. "@ingroup GFX\n"
  1115. "@see flagCurrentGFXResources, listGFXResources, describeGFXResources" )
  1116. {
  1117. GFX->clearResourceFlags();
  1118. }
  1119. DefineEngineFunction( describeGFXResources, void, ( const char *resourceTypes, const char *filePath, bool unflaggedOnly ), ( false ),
  1120. "@brief Dumps a description of GFX resources to a file or the console.\n"
  1121. "@param resourceTypes A space seperated list of resource types or an empty string for all resources.\n"
  1122. "@param filePath A file to dump the list to or an empty string to write to the console.\n"
  1123. "@param unflaggedOnly If true only unflagged resources are dumped. See flagCurrentGFXResources.\n"
  1124. "@note The resource types can be one or more of the following:\n\n"
  1125. " - texture\n"
  1126. " - texture target\n"
  1127. " - window target\n"
  1128. " - vertex buffers\n"
  1129. " - primitive buffers\n"
  1130. " - fences\n"
  1131. " - cubemaps\n"
  1132. " - shaders\n"
  1133. " - stateblocks\n\n"
  1134. "@ingroup GFX\n" )
  1135. {
  1136. GFX->describeResources( resourceTypes, filePath, unflaggedOnly );
  1137. }
  1138. DefineEngineFunction( describeGFXStateBlocks, void, ( const char *filePath ),,
  1139. "Dumps a description of all state blocks.\n"
  1140. "@param filePath A file to dump the state blocks to or an empty string to write to the console.\n"
  1141. "@ingroup GFX\n" )
  1142. {
  1143. GFX->dumpStates( filePath );
  1144. }
  1145. DefineEngineFunction( getPixelShaderVersion, F32, (),,
  1146. "Returns the pixel shader version for the active device.\n"
  1147. "@ingroup GFX\n" )
  1148. {
  1149. return GFX->getPixelShaderVersion();
  1150. }
  1151. DefineEngineFunction( setPixelShaderVersion, void, ( F32 version ),,
  1152. "@brief Sets the pixel shader version for the active device.\n"
  1153. "This can be used to force a lower pixel shader version than is supported by "
  1154. "the device for testing or performance optimization.\n"
  1155. "@param version The floating point shader version number.\n"
  1156. "@note This will only affect shaders/materials created after the call "
  1157. "and should be used before the game begins.\n"
  1158. "@see $pref::Video::forcedPixVersion\n"
  1159. "@ingroup GFX\n" )
  1160. {
  1161. GFX->setPixelShaderVersion( version );
  1162. }
  1163. DefineEngineFunction( getDisplayDeviceInformation, const char*, (),,
  1164. "Get the string describing the active GFX device.\n"
  1165. "@ingroup GFX\n" )
  1166. {
  1167. if (!GFXDevice::devicePresent())
  1168. return "(no device)";
  1169. const GFXAdapter& adapter = GFX->getAdapter();
  1170. return adapter.getName();
  1171. }
  1172. DefineEngineFunction( getBestHDRFormat, GFXFormat, (),,
  1173. "Returns the best texture format for storage of HDR data for the active device.\n"
  1174. "@ingroup GFX\n" )
  1175. {
  1176. // TODO: Maybe expose GFX::selectSupportedFormat() so that this
  1177. // specialized method can be moved to script.
  1178. // Figure out the best HDR format. This is the smallest
  1179. // format which supports blending and filtering.
  1180. Vector<GFXFormat> formats;
  1181. formats.push_back(GFXFormatR16G16B16A16F);
  1182. formats.push_back( GFXFormatR10G10B10A2 );
  1183. GFXFormat format = GFX->selectSupportedFormat( &GFXRenderTargetProfile,
  1184. formats,
  1185. true,
  1186. true,
  1187. true );
  1188. return format;
  1189. }
  1190. DefineConsoleFunction(ResetGFX, void, (), , "forces the gbuffer to be reinitialized in cases of improper/lack of buffer clears.")
  1191. {
  1192. GFX->beginReset();
  1193. }