/** MCPP callback for retrieving file contents. */ static int GetFileContents(void* InUserData, const ANSICHAR* InFilename, const ANSICHAR** OutContents, size_t* OutContentSize) { FMcppFileLoader* This = (FMcppFileLoader*)InUserData; FString Filename = GetRelativeShaderFilename(ANSI_TO_TCHAR(InFilename)); FShaderContents* CachedContents = This->CachedFileContents.Find(Filename); if (!CachedContents) { FString FileContents; if (This->ShaderInput.Environment.IncludeFileNameToContentsMap.Contains(Filename)) { FileContents = This->ShaderInput.Environment.IncludeFileNameToContentsMap.FindRef(Filename); } else { LoadShaderSourceFile(*Filename,FileContents); } if (FileContents.Len() > 0) { CachedContents = &This->CachedFileContents.Add(Filename,StringToArray<ANSICHAR>(*FileContents, FileContents.Len())); } } if (OutContents) { *OutContents = CachedContents ? CachedContents->GetTypedData() : NULL; } if (OutContentSize) { *OutContentSize = CachedContents ? CachedContents->Num() : 0; } return !!CachedContents; }
GLuint ShaderCompiler::LoadShader(GLenum eShaderType, char* cFilename) { GLuint uiShader; const char* cShaderBuffer; if (!(cShaderBuffer = LoadShaderSourceFile(cFilename))) return false; this->m_OpenGL->CreateShader(uiShader, eShaderType, cShaderBuffer); delete[] cShaderBuffer; cShaderBuffer = 0; return uiShader; }
/** Initialization constructor. */ explicit FMcppFileLoader(const FShaderCompilerInput& InShaderInput) : ShaderInput(InShaderInput) { FString ShaderDir = FPlatformProcess::ShaderDir(); InputShaderFile = ShaderDir / FPaths::GetCleanFilename(ShaderInput.SourceFilename); if (FPaths::GetExtension(InputShaderFile) != TEXT("usf")) { InputShaderFile += TEXT(".usf"); } FString InputShaderSource; if (LoadShaderSourceFile(*ShaderInput.SourceFilename,InputShaderSource)) { InputShaderSource = FString::Printf(TEXT("%s\n#line 1\n%s"), *ShaderInput.SourceFilePrefix, *InputShaderSource); CachedFileContents.Add(GetRelativeShaderFilename(InputShaderFile),StringToArray<ANSICHAR>(*InputShaderSource, InputShaderSource.Len())); } }
STDMETHOD(Open)(D3DXINCLUDE_TYPE Type, LPCSTR Name, LPCVOID ParentData, LPCVOID* Data, UINT* NumBytes) { FString Filename(ANSI_TO_TCHAR(Name)); FString ShaderCode; map<FString, FString>::iterator it = _Environment.IncludeFiles.find(Filename); if( it != _Environment.IncludeFiles.end() ) { ShaderCode = it->second; } else { ShaderCode = LoadShaderSourceFile(Filename.c_str()); } ANSICHAR* Code = new ANSICHAR[ShaderCode.length() + 1]; appStrncpyANSI(Code, TCHAR_TO_ANSI(ShaderCode.c_str()), ShaderCode.length() + 1); *Data = (LPCVOID)Code; *NumBytes = ShaderCode.length(); return D3D_OK; }
bool RenderShader::InitializeShader(char* vsFilename, char* fsFilename) { const char* vertexShaderBuffer; const char* fragmentShaderBuffer; int status; // Load the vertex shader source file into a text buffer. vertexShaderBuffer = LoadShaderSourceFile(vsFilename); if(!vertexShaderBuffer) { return false; } // Load the fragment shader source file into a text buffer. fragmentShaderBuffer = LoadShaderSourceFile(fsFilename); if(!fragmentShaderBuffer) { return false; } // Create a vertex and fragment shader object. m_vertexShader = g_openGL->glCreateShader(GL_VERTEX_SHADER); m_fragmentShader = g_openGL->glCreateShader(GL_FRAGMENT_SHADER); // Copy the shader source code strings into the vertex and fragment shader objects. g_openGL->glShaderSource(m_vertexShader, 1, &vertexShaderBuffer, NULL); g_openGL->glShaderSource(m_fragmentShader, 1, &fragmentShaderBuffer, NULL); // Release the vertex and fragment shader buffers. delete [] vertexShaderBuffer; vertexShaderBuffer = 0; delete [] fragmentShaderBuffer; fragmentShaderBuffer = 0; // Compile the shaders. g_openGL->glCompileShader(m_vertexShader); g_openGL->glCompileShader(m_fragmentShader); // Check to see if the vertex shader compiled successfully. g_openGL->glGetShaderiv(m_vertexShader, GL_COMPILE_STATUS, &status); if(status != 1) { // If it did not compile then write the syntax error message out to a text file for review. OutputShaderErrorMessage(m_vertexShader, vsFilename); return false; } // Check to see if the fragment shader compiled successfully. g_openGL->glGetShaderiv(m_fragmentShader, GL_COMPILE_STATUS, &status); if(status != 1) { // If it did not compile then write the syntax error message out to a text file for review. OutputShaderErrorMessage(m_fragmentShader, fsFilename); return false; } // Create a shader program object. m_shaderProgram = g_openGL->glCreateProgram(); // Attach the vertex and fragment shader to the program object. g_openGL->glAttachShader(m_shaderProgram, m_vertexShader); g_openGL->glAttachShader(m_shaderProgram, m_fragmentShader); // Bind the shader input variables. g_openGL->glBindAttribLocation(m_shaderProgram, 0, "inputPosition"); g_openGL->glBindAttribLocation(m_shaderProgram, 1, "inputNormal"); g_openGL->glBindAttribLocation(m_shaderProgram, 2, "inputColor"); g_openGL->glBindAttribLocation(m_shaderProgram, 3, "inputUV"); // Link the shader program. g_openGL->glLinkProgram(m_shaderProgram); // Check the status of the link. g_openGL->glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &status); if(status != 1) { // If it did not link then write the syntax error message out to a text file for review. OutputLinkerErrorMessage(m_shaderProgram); return false; } return true; }
static UBOOL D3D9CompileShaderWrapper( const TCHAR* ShaderFilename, const TCHAR* FunctionName, const TCHAR* ShaderProfile, DWORD CompileFlags, const FShaderCompilerEnvironment& InEnvironment, const vector<D3DXMACRO>& Macros, FShaderCompilerOutput& Output, vector<FD3D9ConstantDesc>& Constants, FString& DisassemblyString, FString& ErrorString ) { const FString& SourceFile = LoadShaderSourceFile(ShaderFilename); TRefCountPtr<ID3DXBuffer> Shader; TRefCountPtr<ID3DXBuffer> Errors; FD3DIncludeEnvironment Environment(InEnvironment); TRefCountPtr<ID3DXConstantTable> ConstantTable; FTCHARToANSI AnsiSourceFile(SourceFile.c_str()); HRESULT Result = D3DXCompileShader( AnsiSourceFile, SourceFile.size(), &Macros[0], &Environment, TCHAR_TO_ANSI(FunctionName), TCHAR_TO_ANSI(ShaderProfile), CompileFlags, Shader.GetInitReference(), Errors.GetInitReference(), ConstantTable.GetInitReference()); if( FAILED(Result) ) { ErrorString = TEXT("Compile Failed without warnings!"); void* ErrorBuffer = Errors ? Errors->GetBufferPointer() : NULL; if( ErrorBuffer ) { FANSIToTCHAR Convert((ANSICHAR*)ErrorBuffer); ErrorString = Convert; } } else { // get the ShaderCode INT NumShaderBytes = Shader->GetBufferSize(); Output.ShaderCode.resize(NumShaderBytes); appMemcpy(&Output.ShaderCode[0], Shader->GetBufferPointer(), NumShaderBytes); // collect the constant table D3DXCONSTANTTABLE_DESC ConstantTableDesc; VERIFYD3DRESULT(ConstantTable->GetDesc(&ConstantTableDesc)); for(UINT ConstantIndex = 0; ConstantIndex < ConstantTableDesc.Constants; ++ConstantIndex) { D3DXHANDLE ConstantHandle = ConstantTable->GetConstant(NULL, ConstantIndex); D3DXCONSTANT_DESC ConstantDesc; UINT NumConstants = 1; VERIFYD3DRESULT(ConstantTable->GetConstantDesc(ConstantHandle, &ConstantDesc, &NumConstants)); FD3D9ConstantDesc NamedConstantDesc; appStrcpyANSI(NamedConstantDesc.Name, ConstantDesc.Name); NamedConstantDesc.bIsSampler = ConstantDesc.RegisterSet == D3DXRS_SAMPLER; NamedConstantDesc.RegisterIndex = ConstantDesc.RegisterIndex; NamedConstantDesc.RegisterCount = ConstantDesc.RegisterCount; Constants.push_back(NamedConstantDesc); } // disassemble a shader TRefCountPtr<ID3DXBuffer> DisassemblyBuffer; VERIFYD3DRESULT(D3DXDisassembleShader((const DWORD*)Shader->GetBufferPointer(), FALSE, NULL, DisassemblyBuffer.GetInitReference())); DisassemblyString = ANSI_TO_TCHAR((ANSICHAR*)DisassemblyBuffer->GetBufferPointer()); } return TRUE; }
// vps编译接口 UBOOL D3D9CompileShader( const TCHAR* ShaderFilename, const TCHAR* FunctionName, FShaderTarget Target, const FShaderCompilerEnvironment& Environment, FShaderCompilerOutput& Output, UBOOL bDebugDump = FALSE ) { // translate the input Environment's defines to D3DXMACROs vector<D3DXMACRO> Macros; for( map<FString, FString>::const_iterator it = Environment.Definitions.begin(); it != Environment.Definitions.end(); ++it ) { FString Name = it->first; FString Definition = it->second; D3DXMACRO Macro; Macro.Name = new ANSICHAR[Name.size()+1]; appStrncpyANSI((ANSICHAR*)Macro.Name, TCHAR_TO_ANSI(Name.c_str()), Name.size()+1); Macro.Definition = new ANSICHAR[Definition.size()+1]; appStrncpyANSI((ANSICHAR*)Macro.Definition, TCHAR_TO_ANSI(Definition.c_str()), Definition.size()+1); Macros.push_back(Macro); } DWORD CompileFlags = D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY; const TCHAR* ShaderPath = appShaderDir(); TCHAR Profile[32]; if( Target.Platform == SP_SM3 ) { if( Target.Frequency == SF_Pixel ) { appStrcpy(Profile, TEXT("ps_3_0")); } else if( Target.Frequency == SF_Vertex ) { appStrcpy(Profile, TEXT("vs_3_0")); } } else if( Target.Platform == SP_SM2 ) { if( Target.Frequency == SF_Pixel ) { appStrcpy(Profile, TEXT("ps_2_0")); } else if( Target.Frequency == SF_Vertex ) { appStrcpy(Profile, TEXT("vs_2_0")); } } vector<FD3D9ConstantDesc> Constants; FString DisassemblyString; FString ErrorString; UBOOL bCompileFailed = TRUE; bCompileFailed = !D3D9CompileShaderWrapper( ShaderFilename, FunctionName, Profile, CompileFlags, Environment, Macros, Output, Constants, DisassemblyString, ErrorString ); if( bCompileFailed ) { FString ErrorShaderFile = FStringUtil::Sprintf(TEXT("%sErrorShader-%s.vps"), ShaderPath, ShaderFilename); appSaveStringToFile(ErrorString, ErrorShaderFile.c_str()); } if( bCompileFailed || bDebugDump ) { const FString SourceFile = LoadShaderSourceFile(ShaderFilename); D3D9PreProcessShader(ShaderFilename, SourceFile, Macros, Environment, ShaderPath); } for(UINT i = 0; i < Macros.size(); ++i) { delete Macros[i].Name; delete Macros[i].Definition; } Macros.clear(); UINT NumInstructions = 0; if( !bCompileFailed ) { // fetch the number of instruction Parse(DisassemblyString.c_str(), TEXT("// approximately"), (DWORD&)NumInstructions); // 在ShaderModel3.0下支持的指令数,最少为512,最多至D3DCAPS9.MaxVertexShader30InstructionSlots // 因指令数在运行时刻检查,所以在编译器给出提示 if( NumInstructions > 512 && Target.Platform == SP_SM3 ) { bCompileFailed = TRUE; debugf(NAME_Warning, TEXT("Shader use too many instructions for Shader Model 3.0 (Used %u, Minimum guaranteed in SM3.0 is 512)"), NumInstructions); } } if( bCompileFailed ) { return FALSE; } check(Output.ShaderCode.size() > 0); for(UINT ConstantIndex = 0; ConstantIndex < Constants.size(); ++ConstantIndex) { const FD3D9ConstantDesc& Desc = Constants.at(ConstantIndex); if( Desc.bIsSampler ) { Output.ParameterMap.AddParameter( ANSI_TO_TCHAR(Desc.Name), Desc.RegisterIndex, Desc.RegisterCount, 1 ); } else { Output.ParameterMap.AddParameter( ANSI_TO_TCHAR(Desc.Name), Desc.RegisterIndex * sizeof(FLOAT) * 4, Desc.RegisterCount * sizeof(FLOAT) * 4, 0 ); } } Output.Target = Target; Output.NumInstructions = NumInstructions; if( bDebugDump ) { FString ASMShaderFile = FStringUtil::Sprintf(TEXT("%s%s.asm"), ShaderPath, ShaderFilename); appSaveStringToFile(DisassemblyString, ASMShaderFile.c_str()); } return TRUE; }
bool Shader::InitializeShader(string shaderVSFileName, string shaderPSFileName) { const char* shaderBuffer_VS = LoadShaderSourceFile("Shaders/" + shaderVSFileName); const char* shaderBuffer_PS = LoadShaderSourceFile("Shaders/" + shaderPSFileName); if (!shaderBuffer_VS) { cout << "Shader: " << shaderVSFileName << " could not be loaded" << endl; return false; } if (!shaderBuffer_PS) { cout << "Shader: " << shaderVSFileName << " could not be loaded" << endl; return false; } m_vertexID = glCreateShader(GL_VERTEX_SHADER); m_fragID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(m_vertexID, 1, &shaderBuffer_VS, NULL); glShaderSource(m_fragID, 1, &shaderBuffer_PS, NULL); delete[] shaderBuffer_VS; delete[] shaderBuffer_PS; glCompileShader(m_vertexID); glCompileShader(m_fragID); int status; glGetShaderiv(m_vertexID, GL_COMPILE_STATUS, &status); if (status != 1) { OutputShaderErrorMessage(m_vertexID, (char*)shaderVSFileName.c_str()); return false; } glGetShaderiv(m_fragID, GL_COMPILE_STATUS, &status); if (status != 1) { OutputShaderErrorMessage(m_fragID, (char*)shaderPSFileName.c_str()); return false; } m_programID = glCreateProgram();//set the Program ID to the first element by default glAttachShader(m_programID, m_vertexID); glAttachShader(m_programID, m_fragID); glLinkProgram(m_programID); glGetProgramiv(m_programID, GL_LINK_STATUS, &status); if(status != 1) { // If it did not link then write the syntax error message out to a text file for review. OutputLinkerErrorMessage(m_programID); DeleteProgram(); return false; } return true; }