HRESULT _gfxD3DXInclude::Open(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes, LPSTR pFullPath, DWORD cbFullPath) { // First try making the path relative to the parent. Torque::Path path = Torque::Path::Join( mLastPath.last(), '/', pFileName ); path = Torque::Path::CompressPath( path ); if ( !Torque::FS::ReadFile( path, (void *&)*ppData, *pBytes, true ) ) { // Ok... now try using the path as is. path = String( pFileName ); path = Torque::Path::CompressPath( path ); if ( !Torque::FS::ReadFile( path, (void *&)*ppData, *pBytes, true ) ) { AssertISV(false, avar( "Failed to open include '%s'.", pFileName)); return E_FAIL; } } // If the data was of zero size then we cannot recurse // into this file and DX won't call Close() below. // // So in this case don't push on the path. if ( *pBytes > 0 ) mLastPath.push_back( path.getRootAndPath() ); return S_OK; }
bool GFXD3D9Shader::_compileShader( const Torque::Path &filePath, const String& target, const D3DXMACRO *defines, GenericConstBufferLayout* bufferLayoutF, GenericConstBufferLayout* bufferLayoutI, Vector<GFXShaderConstDesc> &samplerDescriptions ) { PROFILE_SCOPE( GFXD3D9Shader_CompileShader ); HRESULT res = D3DERR_INVALIDCALL; LPD3DXBUFFER code = NULL; LPD3DXBUFFER errorBuff = NULL; #ifdef TORQUE_DEBUG U32 flags = D3DXSHADER_DEBUG; #else U32 flags = 0; #endif #ifdef TORQUE_OS_XENON flags |= D3DXSHADER_PREFER_FLOW_CONTROL; #endif #ifdef D3DXSHADER_USE_LEGACY_D3DX9_31_DLL if( D3DX_SDK_VERSION >= 32 ) { // will need to use old compiler for 1_1 shaders - check for pixel // or vertex shader with appropriate version. if ((target.compare("vs1", 3) == 0) || (target.compare("vs_1", 4) == 0)) flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL; if ((target.compare("ps1", 3) == 0) || (target.compare("ps_1", 4) == 0)) flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL; } #endif #if !defined(TORQUE_OS_XENON) && (D3DX_SDK_VERSION <= 40) #error This version of the DirectX SDK is too old. Please install a newer version of the DirectX SDK: http://msdn.microsoft.com/en-us/directx/default.aspx #endif ID3DXConstantTable* table = NULL; static String sHLSLStr( "hlsl" ); static String sOBJStr( "obj" ); // Is it an HLSL shader? if ( filePath.getExtension().equal(sHLSLStr, String::NoCase) ) { FrameAllocatorMarker fam; char *buffer = NULL; // Set this so that the D3DXInclude::Open will have this // information for relative paths. smD3DXInclude->setPath( filePath.getRootAndPath() ); FileStream s; if ( !s.open( filePath, Torque::FS::File::Read ) ) { AssertISV(false, avar("GFXD3D9Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str())); if ( smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Failed to open shader file '%s'.", filePath.getFullPath().c_str() ); return false; } // Convert the path which might have virtualized // mount paths to a real file system path. Torque::Path realPath; if ( !FS::GetFSPath( filePath, realPath ) ) realPath = filePath; // Add a #line pragma so that error and warning messages // returned by the HLSL compiler report the right file. String linePragma = String::ToString( "#line 1 \"%s\"\r\n", realPath.getFullPath().c_str() ); U32 linePragmaLen = linePragma.length(); U32 bufSize = s.getStreamSize(); buffer = (char *)fam.alloc( bufSize + linePragmaLen + 1 ); dStrncpy( buffer, linePragma.c_str(), linePragmaLen ); s.read( bufSize, buffer + linePragmaLen ); buffer[bufSize+linePragmaLen] = 0; res = GFXD3DX.D3DXCompileShader( buffer, bufSize + linePragmaLen, defines, smD3DXInclude, "main", target, flags, &code, &errorBuff, &table ); } // Is it a precompiled obj shader? else if ( filePath.getExtension().equal( sOBJStr, String::NoCase ) ) { FileStream s; if(!s.open(filePath, Torque::FS::File::Read)) { AssertISV(false, avar("GFXD3D9Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str())); if ( smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Failed to open shader file '%s'.", filePath.getFullPath().c_str() ); return false; } res = GFXD3DX.D3DXCreateBuffer(s.getStreamSize(), &code); AssertISV(res == D3D_OK, "Unable to create buffer!"); s.read(s.getStreamSize(), code->GetBufferPointer()); if (res == D3D_OK) { DWORD* data = (DWORD*) code->GetBufferPointer(); res = GFXD3DX.D3DXGetShaderConstantTable(data, &table); } } else { if ( smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Unsupported shader file type '%s'.", filePath.getFullPath().c_str() ); return false; } if ( res != D3D_OK && smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Error compiling shader: %s: %s (%x)", DXGetErrorStringA(res), DXGetErrorDescriptionA(res), res ); if ( errorBuff ) { // remove \n at end of buffer U8 *buffPtr = (U8*) errorBuff->GetBufferPointer(); U32 len = dStrlen( (const char*) buffPtr ); buffPtr[len-1] = '\0'; if( res != D3D_OK ) { if ( smLogErrors ) Con::errorf( " %s", (const char*) errorBuff->GetBufferPointer() ); } else { if ( smLogWarnings ) Con::warnf( "%s", (const char*) errorBuff->GetBufferPointer() ); } } else if ( code == NULL && smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - no compiled code produced; possibly missing file '%s'.", filePath.getFullPath().c_str() ); // Create the proper shader if we have code if( code != NULL ) { #ifndef TORQUE_SHIPPING LPD3DXBUFFER disassem = NULL; D3DXDisassembleShader( (DWORD*)code->GetBufferPointer(), false, NULL, &disassem ); mDissasembly = (const char*)disassem->GetBufferPointer(); SAFE_RELEASE( disassem ); if ( gDisassembleAllShaders ) { String filename = filePath.getFullPath(); filename.replace( ".hlsl", "_dis.txt" ); FileStream *fstream = FileStream::createAndOpen( filename, Torque::FS::File::Write ); if ( fstream ) { fstream->write( mDissasembly ); fstream->close(); delete fstream; } } #endif if (target.compare("ps_", 3) == 0) res = mD3D9Device->CreatePixelShader( (DWORD*)code->GetBufferPointer(), &mPixShader ); else res = mD3D9Device->CreateVertexShader( (DWORD*)code->GetBufferPointer(), &mVertShader ); if (res == S_OK) _getShaderConstants(table, bufferLayoutF, bufferLayoutI, samplerDescriptions); #ifdef TORQUE_ENABLE_CSF_GENERATION // Ok, we've got a valid shader and constants, let's write them all out. if ( !_saveCompiledOutput(filePath, code, bufferLayoutF, bufferLayoutI) && smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Unable to save shader compile output for: %s", filePath.getFullPath().c_str() ); #endif SAFE_RELEASE(table); if ( res != S_OK && smLogErrors ) Con::errorf( "GFXD3D9Shader::_compileShader - Unable to create shader for '%s'.", filePath.getFullPath().c_str() ); } bool result = code != NULL && res == S_OK; SAFE_RELEASE( code ); SAFE_RELEASE( errorBuff ); return result; }