Exemple #1
0
bool Shader::BeginLoad(Deserializer& source)
{
    Graphics* graphics = GetSubsystem<Graphics>();
    if (!graphics)
        return false;
    
    // Load the shader source code and resolve any includes
    timeStamp_ = 0;
    String shaderCode;
    if (!ProcessSource(shaderCode, source))
        return false;
    
    // Comment out the unneeded shader function
    vsSourceCode_ = shaderCode;
    psSourceCode_ = shaderCode;
    CommentOutFunction(vsSourceCode_, "void PS(");
    CommentOutFunction(psSourceCode_, "void VS(");
    
    // OpenGL: rename either VS() or PS() to main(), comment out vertex attributes in pixel shaders
    #ifdef URHO3D_OPENGL
    vsSourceCode_.Replace("void VS(", "void main(");
    psSourceCode_.Replace("void PS(", "void main(");
    psSourceCode_.Replace("attribute ", "// attribute ");
    #endif
    
    RefreshMemoryUse();
    return true;
}
Exemple #2
0
bool Shader::ProcessSource(String& code, Deserializer& source)
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    
    // If the source if a non-packaged file, store the timestamp
    File* file = dynamic_cast<File*>(&source);
    if (file && !file->IsPackaged())
    {
        FileSystem* fileSystem = GetSubsystem<FileSystem>();
        String fullName = cache->GetResourceFileName(file->GetName());
        unsigned fileTimeStamp = fileSystem->GetLastModifiedTime(fullName);
        if (fileTimeStamp > timeStamp_)
            timeStamp_ = fileTimeStamp;
    }
    
    // Store resource dependencies for includes so that we know to reload if any of them changes
    if (source.GetName() != GetName())
        cache->StoreResourceDependency(this, source.GetName());
    
    while (!source.IsEof())
    {
        String line = source.ReadLine();
        
        if (line.StartsWith("#include"))
        {
            String includeFileName = GetPath(source.GetName()) + line.Substring(9).Replaced("\"", "").Trimmed();
            
            SharedPtr<File> includeFile = cache->GetFile(includeFileName);
            if (!includeFile)
                return false;
            
            // Add the include file into the current code recursively
            if (!ProcessSource(code, *includeFile))
                return false;
        }
        else
        {
            code += line;
            code += "\n";
        }
    }

    // Finally insert an empty line to mark the space between files
    code += "\n";
    
    return true;
}
Exemple #3
0
bool Shader::Load(Deserializer& source)
{
    PROFILE(LoadShader);
    
    Graphics* graphics = GetSubsystem<Graphics>();
    if (!graphics)
        return false;
    
    // Load the shader source code and resolve any includes
    timeStamp_ = 0;
    String shaderCode;
    if (!ProcessSource(shaderCode, source))
        return false;
    
    // Comment out the unneeded shader function
    vsSourceCode_ = shaderCode;
    psSourceCode_ = shaderCode;
    CommentOutFunction(vsSourceCode_, "void PS(");
    CommentOutFunction(psSourceCode_, "void VS(");
    
    // OpenGL: rename either VS() or PS() to main(), comment out vertex attributes in pixel shaders
    #ifdef USE_OPENGL
    vsSourceCode_.Replace("void VS(", "void main(");
    psSourceCode_.Replace("void PS(", "void main(");
    psSourceCode_.Replace("attribute ", "// attribute ");
    #endif
    
    // If variations had already been created, release them and require recompile
    for (HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = vsVariations_.Begin(); i != vsVariations_.End(); ++i)
        i->second_->Release();
    for (HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = psVariations_.Begin(); i != psVariations_.End(); ++i)
        i->second_->Release();
    
    RefreshMemoryUse();
    return true;
}
Exemple #4
0
int main(               // MAIN-LINE
    int argc,           // - # arguments
    char *argv[] )      // - arguments list
{
#define src_file param[ count ]         // - name of source file
#define tgt_file param[ arg_count-1 ]   // - name of modifications file
    int                 count;              // - current source file #
    char                *p;                // - generic pointer
    SEGMENT             *seg;           // - segment structure
    struct utimbuf      dest_time;
    struct stat         src_time;
    char                *src = NULL;
    char                *tgt = NULL;
    char                *param[32];
    int                 arg_count = 0;

    for( count = 0; count < argc; count++ ) {
        if( argv[count][0] != '@' ) {
            param[arg_count] = malloc( strlen( argv[count] ) + 1 );
            strcpy( param[arg_count++], argv[count] );
        } else {
            FILE        *f;
            char        st[512], separator;
            int         i, j, k;
            size_t      len;

            f = fopen( argv[count] + 1, "r" );
            if( f == NULL ) {
                Error( "Unable to open indirect argument file" );
                continue;
            }

            fgets( st, 512, f );
            fclose( f );

            len = strlen( st );
            if( st[len - 1] == '\n' ) {
                --len;
                st[len] = 0;
            }

            i = 0;
            while( i < len ) {
                while( st[i] == ' ' )
                    i++;
                if( st[i] == 0 )
                    break;
                if( st[i] == '"' ) {
                    separator = '"';
                    i++;
                } else {
                    separator = ' ';
                }
                j = i;
                while( ( st[j] != separator ) && ( st[j] != 0 ) ) {
                    if( ( separator == '"' ) && ( st[j] == '\\' ) )
                        j++;
                    j++;
                }

                param[arg_count] = malloc( j - i + 1 );
                for( k = 0; k < j - i; k++ ) {
                    if( ( separator == '"' ) && ( st[i + k] == '\\' ) )
                        i++;
                    param[arg_count][k] = st[i + k];
                }
                param[arg_count][k] = 0;
                arg_count++;

                i = j;
                if( st[i] == '"' )
                    i++;
            }
        }
    }

    ErrCount = 0;
    if( arg_count < 3 ) {
        puts( "Usage: wsplice {src-file|option} tgt-file\n" );
        puts( "options are:" );
        puts( "    -i path\t\tcheck <path> for included files" );
        puts( "    -k seg_name\t\tSame as :KEEP" );
        puts( "    -r seg_name\t\tSame as :REMOVE" );
        puts( "    -f string\t\tSet output format to be <string>" );
        puts( "    -o string\t\tOutput <string> to tgt-file" );
        puts( "    -t tabstop\t\tSet tab character spacing" );
        puts( "    -u\t\t\tUse Unix style newlines for output file" );
        puts( "    -p\t\t\tpreserve same time stamp as src-file on tgt-file" );
    } else {
        if( 0 == stricmp( tgt_file, "-" ) ) {
            OutputFile = stdout;
        } else {
            OutputFile = fopen( tgt_file, "wb" );
            tgt = tgt_file;
        }
        if( OutputFile == NULL ) {
            Error( "Unable to open output file" );
        } else {
#define get_value() ( (src_file[2]=='\0') ? (++count,src_file) : &src_file[2])
            OutBufferLen = 0;
            for( count = 1; count < arg_count - 1; ++count ) {
                if( src_file[0] == '-' ) {
                    switch( src_file[1] ) {
                    case 'i':
                        p = get_value();
                        AddIncludePathList( p );
                        break;
                    case 'k':
                        p = get_value();
                        seg = SegmentLookUp( p );
                        if( seg != NULL )
                            seg->seg_type = SEG_KEEP;
                        break;
                    case 'r':
                        p = get_value();
                        seg = SegmentLookUp( p );
                        if( seg != NULL )
                            seg->seg_type = SEG_REMOVE;
                        break;
                    case 'f':
                        OutFmt = get_value();
                        break;
                    case 'o':
                        p = get_value();
                        OutputString( p, "" );
                        break;
                    case 't':
                        p = get_value();
                        TabStop = strtoul( p, &p, 0 );
                        if( TabStop == 0 || *p != '\0' ) {
                            Error( "Illegal tab value" );
                            exit( 1 );
                        }
                        break;
                    case 'u':
                        UnixStyle = TRUE;
                        break;
                    case 'p':
                        RestoreTime = TRUE;
                        break;
                    default:
                        Error( "Unknown option '%c'", src_file[1] );
                        break;
                    }
                } 
                else {
                    src = src_file;
                    ProcessSource( src_file );
                }
            }
            if( OutBufferLen > 0 )
                fwrite( OutBuffer, OutBufferLen, 1, OutputFile );
            fclose( OutputFile );
        }
    }
    if( RestoreTime ) {
        if( stat( src, &src_time ) == 0 ) {
            dest_time.actime = src_time.st_atime;
            dest_time.modtime = src_time.st_mtime;
            utime( tgt, &dest_time );
        }
    }

    return( ErrCount );

#undef src_file
#undef tgt_file
}
Exemple #5
0
bool Shader::Load(Deserializer& source)
{
    PROFILE(LoadShader);
    
    Graphics* graphics = GetSubsystem<Graphics>();
    if (!graphics)
        return false;
    
    vsSourceCodeLength_ = 0;
    psSourceCodeLength_ = 0;
    
    SharedPtr<XMLFile> xml(new XMLFile(context_));
    if (!xml->Load(source))
        return false;

    XMLElement shaders = xml->GetRoot("shaders");
    if (!shaders)
    {
        LOGERROR("No shaders element in " + source.GetName());
        return false;
    }
    
    {
        PROFILE(ParseShaderDefinition);
        
        if (!vsParser_.Parse(VS, shaders))
        {
            LOGERROR("VS: " + vsParser_.GetErrorMessage());
            return false;
        }
        if (!psParser_.Parse(PS, shaders))
        {
            LOGERROR("PS: " + psParser_.GetErrorMessage());
            return false;
        }
    }
    
    String path, fileName, extension;
    SplitPath(GetName(), path, fileName, extension);
    
    {
        PROFILE(LoadShaderSource);
        
        if (!ProcessSource(vsSourceCode_, vsSourceCodeLength_, path + fileName + ".vert"))
            return false;
        if (!ProcessSource(psSourceCode_, psSourceCodeLength_, path + fileName + ".frag"))
            return false;
    }
    
    // If variations had already been created, release them and set new source code
    /// \todo Should also update defines
    for (HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = vsVariations_.Begin(); i != vsVariations_.End(); ++i)
    {
        i->second_->Release();
        i->second_->SetSourceCode(vsSourceCode_, vsSourceCodeLength_);
    }
    for (HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = psVariations_.Begin(); i != psVariations_.End(); ++i)
    {
        i->second_->Release();
        i->second_->SetSourceCode(psSourceCode_, psSourceCodeLength_);
    }
    
    SetMemoryUse(sizeof(Shader) + 2 * sizeof(ShaderParser) + (vsVariations_.Size() + psVariations_.Size()) *
        sizeof(ShaderVariation));
    
    return true;
}