Ticket #3640: preprocessor_include_with_hotload_impl_fixed.patch
File preprocessor_include_with_hotload_impl_fixed.patch, 9.8 KB (added by , 8 years ago) |
---|
-
source/graphics/ShaderProgram.h
193 193 */ 194 194 void AssertPointersBound(); 195 195 196 /** 197 * Register observer to be notified on each included file 198 */ 199 void RegisterIncludedFilesObserver(std::function<void(const VfsPath&)>); 200 196 201 protected: 197 202 CShaderProgram(int streamflags); 198 203 … … 203 208 void BindClientStates(); 204 209 void UnbindClientStates(); 205 210 int m_ValidStreams; // which streams have been specified via VertexPointer etc since the last Bind 211 212 std::function<void(const VfsPath&)> IncludedFileObserver; 206 213 }; 207 214 208 215 #endif // INCLUDED_SHADERPROGRAM -
source/graphics/ShaderProgram.cpp
432 432 433 433 CPreprocessorWrapper preprocessor; 434 434 preprocessor.AddDefines(m_Defines); 435 preprocessor.RegisterIncludedFilesObserver(IncludedFileObserver); 435 436 436 437 #if CONFIG2_GLES 437 438 // GLES defines the macro "GL_ES" in its GLSL preprocessor, … … 890 891 { 891 892 ENSURE((m_StreamFlags & ~m_ValidStreams) == 0); 892 893 } 894 895 void CShaderProgram::RegisterIncludedFilesObserver(std::function<void(const VfsPath&)> fileObserver) 896 { 897 IncludedFileObserver = fileObserver; 898 } -
source/graphics/ShaderManager.h
72 72 */ 73 73 size_t GetNumEffectsLoaded(); 74 74 75 /** 76 * Associates file with program to be reloaded if file has changed 77 */ 78 void AddHotloadFile(const VfsPath&, CShaderProgramPtr program); 79 75 80 private: 76 81 77 82 struct CacheKey -
source/graphics/ShaderManager.cpp
265 265 else 266 266 program = CShaderProgramPtr(CShaderProgram::ConstructARB(vertexFile, fragmentFile, defines, vertexUniforms, fragmentUniforms, streamFlags)); 267 267 268 // add included file listener 269 program->RegisterIncludedFilesObserver(std::bind(&CShaderManager::AddHotloadFile, this, std::placeholders::_1, program)); 270 268 271 program->Reload(); 269 272 270 273 // m_HotloadFiles[xmlFilename].insert(program); // TODO: should reload somehow when the XML changes … … 556 559 return m_EffectCache.size(); 557 560 } 558 561 562 void CShaderManager::AddHotloadFile(const VfsPath& filename, CShaderProgramPtr program) 563 { 564 m_HotloadFiles[filename].insert(program); 565 } 566 559 567 /*static*/ Status CShaderManager::ReloadChangedFileCB(void* param, const VfsPath& path) 560 568 { 561 569 return static_cast<CShaderManager*>(param)->ReloadChangedFile(path); … … 568 576 if (files != m_HotloadFiles.end()) 569 577 { 570 578 // Reload all shaders using this file 571 for (std:: set<std::weak_ptr<CShaderProgram> >::iterator it = files->second.begin(); it != files->second.end(); ++it)579 for (std::weak_ptr<CShaderProgram> p : files->second) 572 580 { 573 if (std::shared_ptr<CShaderProgram> program = it->lock()) 581 std::shared_ptr<CShaderProgram> program = p.lock(); 582 if (program != NULL) 574 583 program->Reload(); 575 584 } 576 585 } -
source/ps/PreprocessorWrapper.h
37 37 38 38 CStr Preprocess(const CStr& input); 39 39 40 void RegisterIncludedFilesObserver(std::function<void(const VfsPath&)>); 41 40 42 private: 41 43 CPreprocessor m_Preprocessor; 42 44 }; -
source/ps/PreprocessorWrapper.cpp
84 84 85 85 return ret; 86 86 } 87 88 void CPreprocessorWrapper::RegisterIncludedFilesObserver(std::function<void(const VfsPath&)> observer) 89 { 90 m_Preprocessor.RegisterIncludedFilesObserver(observer); 91 } -
source/ps/Preprocessor.h
35 35 #ifndef INCLUDED_CPREPROCESSOR 36 36 #define INCLUDED_CPREPROCESSOR 37 37 38 #include <functional> 39 40 // Forward declare VfsPath, which is typedefed Path 41 class Path; 42 typedef Path VfsPath; 43 38 44 /** 39 45 * This is a simplistic C/C++-like preprocessor. 40 46 * It takes an non-zero-terminated string on input and outputs a … … 200 206 201 207 /// Expand the macro value (will not work for functions) 202 208 Token Expand (int iNumArgs, Token *iArgs, Macro *iMacros); 209 210 /// Performs deep copy of this macro 211 Macro *Copy() const; 203 212 }; 204 213 205 214 friend class CPreprocessor::Macro; … … 217 226 /// The list of macros defined so far 218 227 Macro *MacroList; 219 228 229 /// Listener to be notified about new included files 230 std::function<void(const VfsPath&)> IncludedFileObserver; 231 220 232 /** 221 233 * Private constructor to re-parse a single token. 222 234 */ … … 278 290 */ 279 291 bool HandleIfDef (Token &iBody, int iLine); 280 292 293 /** 294 * Handle a \#include directive. 295 * @param iBody 296 * The body of the directive (everything after the directive 297 * until end of line). 298 * @param iLine 299 * The line where the directive begins (for error reports) 300 * @return 301 * Included text enclosed in a token 302 */ 303 Token HandleInclude (Token &iBody, int iLine); 304 281 305 /** 282 306 * Handle an \#if directive. 283 307 * @param iBody … … 508 532 */ 509 533 char *Parse (const char *iSource, size_t iLength, size_t &oLength); 510 534 535 /** 536 * Register observer to be notified on each included file 537 */ 538 void RegisterIncludedFilesObserver (std::function<void(const VfsPath&)>); 539 511 540 /** 512 541 * An error handler function type. 513 542 * The default implementation just drops a note to stderr and -
source/ps/Preprocessor.cpp
38 38 39 39 #include "ps/CLogger.h" 40 40 41 #include "ps/Filesystem.h" // to handle #include 42 41 43 // Limit max number of macro arguments to this 42 44 #define MAX_MACRO_ARGS 16 43 45 … … 224 226 return xt; 225 227 } 226 228 229 CPreprocessor::Macro *CPreprocessor::Macro::Copy () const 230 { 231 Token mainCopy; 232 233 // Copy buffer once 234 size_t maxLength = this->Body.Length; 235 if (this->Name.Length > maxLength) 236 maxLength = this->Name.Length; 237 if (this->Value.Length > maxLength) 238 maxLength = this->Value.Length; 239 240 char *buffer = new char[maxLength]; 241 strncpy(buffer, this->Body.String, maxLength); 242 243 // Copy each subcomponent of Macro 244 Token body = Token(this->Body.Type, buffer, this->Body.Length); 245 Token name = Token(this->Name.Type, buffer, this->Name.Length); 246 Token value = Token(this->Value.Type, buffer + (this->Value.Buffer - this->Body.Buffer), this->Value.Length); 247 248 // TODO: Ignore Args for now 249 250 Macro *macroCopy = new Macro(name); 251 macroCopy->Body = body; 252 macroCopy->Value = value; 253 254 return macroCopy; 255 } 256 227 257 //---------------------------------------------------------------------------// 228 258 229 259 static void DefaultError (void *iData, int iLine, const char *iError, … … 979 1009 return true; 980 1010 } 981 1011 1012 CPreprocessor::Token CPreprocessor::HandleInclude (Token &iBody, int iLine) 1013 { 1014 CPreprocessor cpp(iBody, iLine); 1015 1016 Token t = cpp.GetToken(false); 1017 1018 if (t.Type != Token::TK_STRING) 1019 { 1020 Error(iLine, "Expecting a file name after #include, got", &t); 1021 return Token(); 1022 } 1023 1024 std::string filename = std::string(t.String).substr(0, t.Length); 1025 ENSURE(filename.at(0) == '"' && filename.at(t.Length-1) == '"'); 1026 filename = filename.substr(1, t.Length - 2); // remove '"' symbols from the beginning and from the end of token 1027 1028 CVFSFile includedFile; 1029 const VfsPath includedFilePath(L"shaders/" + wstring_from_utf8(filename)); 1030 if (includedFile.Load(g_VFS, includedFilePath) != PSRETURN_OK) 1031 Error(iLine, "Warning: File not found", &t); 1032 IncludedFileObserver(includedFilePath); 1033 const CStr& input = includedFile.GetAsString(); 1034 1035 size_t len = 0; 1036 CPreprocessor preprocessor; 1037 ENSURE(input.size() > 0); 1038 std::string includedSources = preprocessor.Parse(input.c_str(), input.size(), len); 1039 char *result = new char[len]; 1040 includedSources.copy(result, len); 1041 1042 // Copy macros 1043 Macro *m = preprocessor.MacroList; 1044 while (m) 1045 { 1046 Macro *copy = m->Copy(); 1047 copy->Next = MacroList; 1048 MacroList = copy; 1049 m = m->Next; 1050 } 1051 1052 if (!result) 1053 { 1054 Error(iLine, "Problem during preprocessing of included file", &t); 1055 return Token(); 1056 } 1057 1058 do 1059 { 1060 t = cpp.GetToken(false); 1061 } while (t.Type == Token::TK_WHITESPACE || 1062 t.Type == Token::TK_COMMENT || 1063 t.Type == Token::TK_LINECOMMENT); 1064 1065 if (t.Type != Token::TK_EOS) 1066 Error(iLine, "Warning: Ignoring garbage after directive", &t); 1067 1068 return Token(Token::TK_STRING, result, len);; 1069 } 1070 982 1071 CPreprocessor::Token CPreprocessor::ExpandDefined (CPreprocessor *iParent, int iNumArgs, Token *iArgs) 983 1072 { 984 1073 if (iNumArgs != 1) … … 1125 1214 if (rc) 1126 1215 EnableOutput ^= 1; 1127 1216 } 1217 else if (IS_DIRECTIVE ("include")) 1218 return HandleInclude (t, iLine); 1128 1219 else if (IS_DIRECTIVE ("if")) 1129 1220 rc = HandleIf (t, iLine); 1130 1221 else if (IS_DIRECTIVE ("else")) … … 1311 1402 retval.Allocated = 0; 1312 1403 return retval.Buffer; 1313 1404 } 1405 1406 void CPreprocessor::RegisterIncludedFilesObserver(std::function<void(const VfsPath&)> fileObserver) 1407 { 1408 IncludedFileObserver = fileObserver; 1409 }