void ComputeShader::WatchShaderModifications() { if ( !Lock() ) return; // Someone else is locking it ! // Check if the shader file changed since last time time_t LastModificationTime = GetFileModTime( m_pShaderFileName ); if ( LastModificationTime <= m_LastShaderModificationTime ) { // No change ! Unlock(); return; } m_LastShaderModificationTime = LastModificationTime; // We're up to date Unlock(); #ifdef COMPUTE_SHADER_COMPILE_THREADED ASSERT( m_hCompileThread == 0, "Compilation thread already exists !" ); DWORD ThreadID; m_hCompileThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) ThreadCompileComputeShader, this, 0, &ThreadID ); SetThreadPriority( m_hCompileThread, THREAD_PRIORITY_HIGHEST ); }
Tweakable *AddTweakableValue( const eastl::string &filename, size_t counter, Tweakable *twk ) { // First, see if this file is in the files list bool found = false; for( TweakFileList::iterator ti = g_tweakableFile.begin(); ti != g_tweakableFile.end(); ++ti ) { if (ti->filename == filename) { found = true; break; } } // if it's not found, add to the list of tweakable files, // assume it's unmodified since the program has been built if (!found) { TweakableSourceFile srcFile; srcFile.filename = filename; // use the initial modification time srcFile.modTime = GetFileModTime( filename ); g_tweakableFile.pushBack( srcFile ); } // add to the tweakables g_tweakVals.insert(eastl::pair<TweakValKey, Tweakable*>(TweakValKey( filename, counter), twk)); return twk; }
Tweakable& AddTweakableValue( const char* _pFilename, size_t _Counter ) { // First, see if this file is in the files list U32 Key = DictionaryString<int>::Hash( _pFilename ); TweakableSourceFile* pFileEntry = g_TweakableFiles.Get( Key ); if ( pFileEntry == NULL ) { // if it's not found, add to the list of tweakable files, assume it's unmodified since the program has been built TweakableSourceFile& Value = g_TweakableFiles.Add( Key ); // strcpy( Value.pFilename, _pFilename ); Value.pFilename = _pFilename; Value.LastModificationTime = GetFileModTime( _pFilename ); } // Add to the tweakables Key = HashKey( _pFilename, _Counter ); return g_TweakableValues.Add( Key ); }
ComputeShader::ComputeShader( Device& _Device, const char* _pShaderFileName, const char* _pShaderCode, D3D_SHADER_MACRO* _pMacros, const char* _pEntryPoint, ID3DInclude* _pIncludeOverride ) : Component( _Device ) , m_pCS( NULL ) , m_pShaderPath( NULL ) #if defined(_DEBUG) || !defined(GODCOMPLEX) , m_LastShaderModificationTime( 0 ) #endif #ifdef COMPUTE_SHADER_COMPILE_THREADED , m_hCompileThread( 0 ) #endif { ASSERT( Shader::ms_LoadFromBinary || _pShaderCode != NULL, "Shader code is NULL!" ); m_pIncludeOverride = _pIncludeOverride; m_bHasErrors = false; // Store the default NULL pointer to point to the shader path #if defined(_DEBUG) || !defined(GODCOMPLEX) m_pShaderFileName = CopyString( _pShaderFileName ); #endif #ifndef GODCOMPLEX m_pShaderPath = GetShaderPath( _pShaderFileName ); m_Pointer2FileName.Add( NULL, m_pShaderPath ); #endif #if defined(_DEBUG) && defined(WATCH_SHADER_MODIFICATIONS) if ( _pShaderFileName != NULL ) { // Just ensure the file exists ! FILE* pFile; fopen_s( &pFile, _pShaderFileName, "rb" ); ASSERT( pFile != NULL, "Compute Shader file not found => You can ignore this assert but compute shader file will NOT be watched for modification!" ); fclose( pFile ); // Register as a watched shader ms_WatchedShaders.Add( _pShaderFileName, this ); #ifndef COMPUTE_SHADER_COMPILE_AT_RUNTIME m_LastShaderModificationTime = GetFileModTime( _pShaderFileName ); #endif } #endif m_pEntryPointCS = _pEntryPoint; if ( _pMacros != NULL ) { D3D_SHADER_MACRO* pMacro = _pMacros; while ( pMacro->Name != NULL ) pMacro++; int MacrosCount = int( 1 + pMacro - _pMacros ); m_pMacros = new D3D_SHADER_MACRO[MacrosCount]; memcpy( m_pMacros, _pMacros, MacrosCount*sizeof(D3D_SHADER_MACRO) ); } else m_pMacros = NULL; #ifdef COMPUTE_SHADER_COMPILE_THREADED // Create the mutex for compilation exclusivity m_hCompileMutex = CreateMutexA( NULL, false, m_pShaderFileName ); if ( m_hCompileMutex == NULL ) m_hCompileMutex = OpenMutexA( SYNCHRONIZE, false, m_pShaderFileName ); // Try and reuse any existing mutex ASSERT( m_hCompileMutex != 0, "Failed to create compilation mutex!" ); #endif #ifndef COMPUTE_SHADER_COMPILE_AT_RUNTIME #ifdef COMPUTE_SHADER_COMPILE_THREADED ASSERT( false, "The COMPUTE_SHADER_COMPILE_THREADED option should only work in pair with the COMPUTE_SHADER_COMPILE_AT_RUNTIME option! (i.e. You CANNOT define COMPUTE_SHADER_COMPILE_THREADED without defining COMPUTE_SHADER_COMPILE_AT_RUNTIME at the same time!)" ); #endif // Compile immediately CompileShaders( _pShaderCode ); #endif }