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; }
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; }
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; }
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 }
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; }