Ticket #3640: preprocessor_include_with_hotload_impl_fixed.patch

File preprocessor_include_with_hotload_impl_fixed.patch, 9.8 KB (added by wraitii, 5 years ago)
  • source/graphics/ShaderProgram.h

     
    193193     */
    194194    void AssertPointersBound();
    195195
     196    /**
     197    * Register observer to be notified on each included file
     198    */
     199    void RegisterIncludedFilesObserver(std::function<void(const VfsPath&)>);
     200
    196201protected:
    197202    CShaderProgram(int streamflags);
    198203
     
    203208    void BindClientStates();
    204209    void UnbindClientStates();
    205210    int m_ValidStreams; // which streams have been specified via VertexPointer etc since the last Bind
     211
     212    std::function<void(const VfsPath&)> IncludedFileObserver;
    206213};
    207214
    208215#endif // INCLUDED_SHADERPROGRAM
  • source/graphics/ShaderProgram.cpp

     
    432432
    433433        CPreprocessorWrapper preprocessor;
    434434        preprocessor.AddDefines(m_Defines);
     435        preprocessor.RegisterIncludedFilesObserver(IncludedFileObserver);
    435436
    436437#if CONFIG2_GLES
    437438        // GLES defines the macro "GL_ES" in its GLSL preprocessor,
     
    890891{
    891892    ENSURE((m_StreamFlags & ~m_ValidStreams) == 0);
    892893}
     894
     895void CShaderProgram::RegisterIncludedFilesObserver(std::function<void(const VfsPath&)> fileObserver)
     896{
     897    IncludedFileObserver = fileObserver;
     898}
  • source/graphics/ShaderManager.h

     
    7272     */
    7373    size_t GetNumEffectsLoaded();
    7474
     75    /**
     76    * Associates file with program to be reloaded if file has changed
     77    */
     78    void AddHotloadFile(const VfsPath&, CShaderProgramPtr program);
     79
    7580private:
    7681
    7782    struct CacheKey
  • source/graphics/ShaderManager.cpp

     
    265265    else
    266266        program = CShaderProgramPtr(CShaderProgram::ConstructARB(vertexFile, fragmentFile, defines, vertexUniforms, fragmentUniforms, streamFlags));
    267267
     268    // add included file listener
     269    program->RegisterIncludedFilesObserver(std::bind(&CShaderManager::AddHotloadFile, this, std::placeholders::_1, program));
     270
    268271    program->Reload();
    269272
    270273//  m_HotloadFiles[xmlFilename].insert(program); // TODO: should reload somehow when the XML changes
     
    556559    return m_EffectCache.size();
    557560}
    558561
     562void CShaderManager::AddHotloadFile(const VfsPath& filename, CShaderProgramPtr program)
     563{
     564    m_HotloadFiles[filename].insert(program);
     565}
     566
    559567/*static*/ Status CShaderManager::ReloadChangedFileCB(void* param, const VfsPath& path)
    560568{
    561569    return static_cast<CShaderManager*>(param)->ReloadChangedFile(path);
     
    568576    if (files != m_HotloadFiles.end())
    569577    {
    570578        // 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)
    572580        {
    573             if (std::shared_ptr<CShaderProgram> program = it->lock())
     581            std::shared_ptr<CShaderProgram> program = p.lock();
     582            if (program != NULL)
    574583                program->Reload();
    575584        }
    576585    }
  • source/ps/PreprocessorWrapper.h

     
    3737
    3838    CStr Preprocess(const CStr& input);
    3939
     40    void RegisterIncludedFilesObserver(std::function<void(const VfsPath&)>);
     41
    4042private:
    4143    CPreprocessor m_Preprocessor;
    4244};
  • source/ps/PreprocessorWrapper.cpp

     
    8484
    8585    return ret;
    8686}
     87
     88void CPreprocessorWrapper::RegisterIncludedFilesObserver(std::function<void(const VfsPath&)> observer)
     89{
     90    m_Preprocessor.RegisterIncludedFilesObserver(observer);
     91}
  • source/ps/Preprocessor.h

     
    3535#ifndef INCLUDED_CPREPROCESSOR
    3636#define INCLUDED_CPREPROCESSOR
    3737
     38#include <functional>
     39
     40// Forward declare VfsPath, which is typedefed Path
     41class Path;
     42typedef Path VfsPath;
     43
    3844/**
    3945 * This is a simplistic C/C++-like preprocessor.
    4046 * It takes an non-zero-terminated string on input and outputs a
     
    200206
    201207        /// Expand the macro value (will not work for functions)
    202208        Token Expand (int iNumArgs, Token *iArgs, Macro *iMacros);
     209
     210        /// Performs deep copy of this macro
     211        Macro *Copy() const;
    203212    };
    204213
    205214    friend class CPreprocessor::Macro;
     
    217226    /// The list of macros defined so far
    218227    Macro *MacroList;
    219228
     229    /// Listener to be notified about new included files
     230    std::function<void(const VfsPath&)> IncludedFileObserver;
     231
    220232    /**
    221233     * Private constructor to re-parse a single token.
    222234     */
     
    278290     */
    279291    bool HandleIfDef (Token &iBody, int iLine);
    280292
     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
    281305    /**
    282306     * Handle an \#if directive.
    283307     * @param iBody
     
    508532     */
    509533    char *Parse (const char *iSource, size_t iLength, size_t &oLength);
    510534
     535    /**
     536    * Register observer to be notified on each included file
     537    */
     538    void RegisterIncludedFilesObserver (std::function<void(const VfsPath&)>);
     539
    511540    /**
    512541     * An error handler function type.
    513542     * The default implementation just drops a note to stderr and
  • source/ps/Preprocessor.cpp

     
    3838
    3939#include "ps/CLogger.h"
    4040
     41#include "ps/Filesystem.h" // to handle #include
     42
    4143// Limit max number of macro arguments to this
    4244#define MAX_MACRO_ARGS 16
    4345
     
    224226    return xt;
    225227}
    226228
     229CPreprocessor::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
    227257//---------------------------------------------------------------------------//
    228258
    229259static void DefaultError (void *iData, int iLine, const char *iError,
     
    9791009    return true;
    9801010}
    9811011
     1012CPreprocessor::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
    9821071CPreprocessor::Token CPreprocessor::ExpandDefined (CPreprocessor *iParent, int iNumArgs, Token *iArgs)
    9831072{
    9841073    if (iNumArgs != 1)
     
    11251214        if (rc)
    11261215            EnableOutput ^= 1;
    11271216    }
     1217    else if (IS_DIRECTIVE ("include"))
     1218        return HandleInclude (t, iLine);
    11281219    else if (IS_DIRECTIVE ("if"))
    11291220        rc = HandleIf (t, iLine);
    11301221    else if (IS_DIRECTIVE ("else"))
     
    13111402    retval.Allocated = 0;
    13121403    return retval.Buffer;
    13131404}
     1405
     1406void CPreprocessor::RegisterIncludedFilesObserver(std::function<void(const VfsPath&)> fileObserver)
     1407{
     1408    IncludedFileObserver = fileObserver;
     1409}