예제 #1
0
//------------------------------------------------------------------------------
// Check for texture mis-match between GFX internal state and what is on the card
// This function is expensive because of the readbacks from DX, and additionally
// won't work unless it's a non-pure device.
//
// This function can crash or give false positives when the game
// is shutting down or returning to the main menu as some of the textures
// present in the mCurrentTexture array will have been freed.
//
// This function is best used as a quick check for mismatched state when it is
// suspected.
//------------------------------------------------------------------------------
void GFXD3D9Device::doParanoidStateCheck()
{
#ifdef TORQUE_DEBUG
   // Read back all states and make sure they match what we think they should be.

   // For now just do texture binds.
   for(U32 i = 0; i < getNumSamplers(); i++)
   {
      IDirect3DBaseTexture9 *b=NULL;
      getDevice()->GetTexture(i, &b);
      if ((mCurrentTexture[i].isNull()) && (mCurrentCubemap[i].isNull()))
      {
         AssertFatal(b == NULL, "GFXD3D9Device::doParanoidStateCheck - got non-null texture in expected NULL slot!");
         getDevice()->SetTexture(i, NULL);
      }
      else
      {
         AssertFatal(mCurrentTexture[i] || mCurrentCubemap[i], "GFXD3D9Device::doParanoidStateCheck - got null texture in expected non-null slot!");
         if (mCurrentCubemap[i])         
         {
            IDirect3DCubeTexture9 *cur= static_cast<GFXD3D9Cubemap*>(mCurrentCubemap[i].getPointer())->mCubeTex;
            AssertFatal(cur == b, "GFXD3D9Device::doParanoidStateCheck - mismatched cubemap!");
         }
         else
         {
            IDirect3DBaseTexture9 *cur= static_cast<GFXD3D9TextureObject*>(mCurrentTexture[i].getPointer())->getTex();
            AssertFatal(cur == b, "GFXD3D9Device::doParanoidStateCheck - mismatched 2d texture!");
         }
      }

      SAFE_RELEASE(b);
   }
#endif
}
예제 #2
0
//-----------------------------------------------------------------------------
// Reset D3D device
//-----------------------------------------------------------------------------
void GFXPCD3D9Device::reset( D3DPRESENT_PARAMETERS &d3dpp )
{
   if(!mD3DDevice)
      return;

   mInitialized = false;

   mMultisampleType = d3dpp.MultiSampleType;
   mMultisampleLevel = d3dpp.MultiSampleQuality;
   _validateMultisampleParams(d3dpp.BackBufferFormat, mMultisampleType, mMultisampleLevel);

   // Clean up some commonly dangling state. This helps prevents issues with
   // items that are destroyed by the texture manager callbacks and recreated
   // later, but still left bound.
   setVertexBuffer(NULL);
   setPrimitiveBuffer(NULL);
   for(S32 i=0; i<getNumSamplers(); i++)
      setTexture(i, NULL);

   // Deal with the depth/stencil buffer.
   if(mDeviceDepthStencil)
   {
      Con::printf("GFXPCD3D9Device::reset - depthstencil %x has %d ref's", mDeviceDepthStencil, mDeviceDepthStencil->AddRef()-1);
      mDeviceDepthStencil->Release();
   }

   // First release all the stuff we allocated from D3DPOOL_DEFAULT
   releaseDefaultPoolResources();

   // reset device
   Con::printf( "--- Resetting D3D Device ---" );
   HRESULT hres = S_OK;
   hres = mD3DDevice->Reset( &d3dpp );

   if( FAILED( hres ) )
   {
      while( mD3DDevice->TestCooperativeLevel() == D3DERR_DEVICELOST )
      {
         Sleep( 100 );
      }

      hres = mD3DDevice->Reset( &d3dpp );
   }

   D3D9Assert( hres, "GFXD3D9Device::reset - Failed to create D3D Device!" );
   mInitialized = true;

   // Setup default states
   initStates();

   // Now re aquire all the resources we trashed earlier
   reacquireDefaultPoolResources();

   // Mark everything dirty and flush to card, for sanity.
   updateStates(true);
}
예제 #3
0
void GFXDevice::updateStates(bool forceSetAll /*=false*/)
{
   PROFILE_SCOPE(GFXDevice_updateStates);

   if(forceSetAll)
   {
      bool rememberToEndScene = false;
      if(!canCurrentlyRender())
      {
         if (!beginScene())
         {
            AssertFatal(false, "GFXDevice::updateStates:  Unable to beginScene!");
         }
         rememberToEndScene = true;
      }

      setMatrix( GFXMatrixProjection, mProjectionMatrix );
      setMatrix( GFXMatrixWorld, mWorldMatrix[mWorldStackSize] );
      setMatrix( GFXMatrixView, mViewMatrix );

      setVertexDecl( mCurrVertexDecl );

      for ( U32 i=0; i < VERTEX_STREAM_COUNT; i++ )
      {
         setVertexStream( i, mCurrentVertexBuffer[i] );
         setVertexStreamFrequency( i, mVertexBufferFrequency[i] );
      }

      if( mCurrentPrimitiveBuffer.isValid() ) // This could be NULL when the device is initalizing
         mCurrentPrimitiveBuffer->prepare();

      /// Stateblocks
      if ( mNewStateBlock )
         setStateBlockInternal(mNewStateBlock, true);
      mCurrentStateBlock = mNewStateBlock;

      for(U32 i = 0; i < getNumSamplers(); i++)
      {
         switch (mTexType[i])
         {
            case GFXTDT_Normal :
               {
                  mCurrentTexture[i] = mNewTexture[i];
                  setTextureInternal(i, mCurrentTexture[i]);
               }  
               break;
            case GFXTDT_Cube :
               {
                  mCurrentCubemap[i] = mNewCubemap[i];
                  if (mCurrentCubemap[i])
                     mCurrentCubemap[i]->setToTexUnit(i);
                  else
                     setTextureInternal(i, NULL);
               }
               break;
            default:
               AssertFatal(false, "Unknown texture type!");
               break;
         }
      }

      // Set our material
      setLightMaterialInternal(mCurrentLightMaterial);

      // Set our lights
      for(U32 i = 0; i < LIGHT_STAGE_COUNT; i++)
      {
         setLightInternal(i, mCurrentLight[i], mCurrentLightEnable[i]);
      }

       _updateRenderTargets();

      if(rememberToEndScene)
         endScene();

      return;
   }

   if (!mStateDirty)
      return;

   // Normal update logic begins here.
   mStateDirty = false;

   // Update Projection Matrix
   if( mProjectionMatrixDirty )
   {
      setMatrix( GFXMatrixProjection, mProjectionMatrix );
      mProjectionMatrixDirty = false;
   }
   
   // Update World Matrix
   if( mWorldMatrixDirty )
   {
      setMatrix( GFXMatrixWorld, mWorldMatrix[mWorldStackSize] );
      mWorldMatrixDirty = false;
   }
   
   // Update View Matrix
   if( mViewMatrixDirty )
   {
      setMatrix( GFXMatrixView, mViewMatrix );
      mViewMatrixDirty = false;
   }


   if( mTextureMatrixCheckDirty )
   {
      for( S32 i = 0; i < getNumSamplers(); i++ )
      {
         if( mTextureMatrixDirty[i] )
         {
            mTextureMatrixDirty[i] = false;
            setMatrix( (GFXMatrixType)(GFXMatrixTexture + i), mTextureMatrix[i] );
         }
      }

      mTextureMatrixCheckDirty = false;
   }

   // Update the vertex declaration.
   if ( mVertexDeclDirty )
   {
      setVertexDecl( mCurrVertexDecl );
      mVertexDeclDirty = false;
   }

   // Update the vertex buffers.
   for ( U32 i=0; i < VERTEX_STREAM_COUNT; i++ )
   {
      if ( mVertexBufferDirty[i] )
      {
         setVertexStream( i, mCurrentVertexBuffer[i] );
         mVertexBufferDirty[i] = false;
      }

      if ( mVertexBufferFrequencyDirty[i] )
      {
         setVertexStreamFrequency( i, mVertexBufferFrequency[i] );
         mVertexBufferFrequencyDirty[i] = false;
      }
   }

   // Update primitive buffer
   //
   // NOTE: It is very important to set the primitive buffer AFTER the vertex buffer
   // because in order to draw indexed primitives in DX8, the call to SetIndicies
   // needs to include the base vertex offset, and the DX8 GFXDevice relies on
   // having mCurrentVB properly assigned before the call to setIndices -patw
   if( mPrimitiveBufferDirty )
   {
      if( mCurrentPrimitiveBuffer.isValid() ) // This could be NULL when the device is initalizing
         mCurrentPrimitiveBuffer->prepare();
      mPrimitiveBufferDirty = false;
   }

   // NOTE: With state blocks, it's now important to update state before setting textures
   // some devices (e.g. OpenGL) set states on the texture and we need that information before
   // the texture is activated.
   if (mStateBlockDirty)
   {
      setStateBlockInternal(mNewStateBlock, false);
      mCurrentStateBlock = mNewStateBlock;
      mStateBlockDirty = false;
   }

   if( mTexturesDirty )
   {
      mTexturesDirty = false;
      for(U32 i = 0; i < getNumSamplers(); i++)
      {
         if(!mTextureDirty[i])
            continue;
         mTextureDirty[i] = false;

         switch (mTexType[i])
         {
         case GFXTDT_Normal :
            {
               mCurrentTexture[i] = mNewTexture[i];
               setTextureInternal(i, mCurrentTexture[i]);
            }  
            break;
         case GFXTDT_Cube :
            {
               mCurrentCubemap[i] = mNewCubemap[i];
               if (mCurrentCubemap[i])
                  mCurrentCubemap[i]->setToTexUnit(i);
               else
                  setTextureInternal(i, NULL);
            }
            break;
         default:
            AssertFatal(false, "Unknown texture type!");
            break;
         }
      }
   }
   
   // Set light material
   if(mLightMaterialDirty)
   {
      setLightMaterialInternal(mCurrentLightMaterial);
      mLightMaterialDirty = false;
   }

   // Set our lights
   if(mLightsDirty)
   {
      mLightsDirty = false;
      for(U32 i = 0; i < LIGHT_STAGE_COUNT; i++)
      {
         if(!mLightDirty[i])
            continue;

         mLightDirty[i] = false;
         setLightInternal(i, mCurrentLight[i], mCurrentLightEnable[i]);
      }
   }

   _updateRenderTargets();

#ifdef TORQUE_DEBUG_RENDER
   doParanoidStateCheck();
#endif
}