GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros ) { PROFILE_SCOPE( ShaderGen_GetShader ); const FeatureSet &features = featureData.codify(); // Build a description string from the features // and vertex format combination ( and macros ). String shaderDescription = vertexFormat->getDescription() + features.getDescription(); if ( macros && !macros->empty() ) { String macroStr; GFXShaderMacro::stringize( *macros, ¯oStr ); shaderDescription += macroStr; } // Generate a single 64bit hash from the description string. // // Don't get paranoid! This has 1 in 18446744073709551616 // chance for collision... it won't happen in this lifetime. // U64 hash = Torque::hash64( (const U8*)shaderDescription.c_str(), shaderDescription.length(), 0 ); hash = convertHostToLEndian(hash); U32 high = (U32)( hash >> 32 ); U32 low = (U32)( hash & 0x00000000FFFFFFFF ); String cacheKey = String::ToString( "%x%x", high, low ); // return shader if exists GFXShader *match = mProcShaders[cacheKey]; if ( match ) return match; // if not, then create it char vertFile[256]; char pixFile[256]; F32 pixVersion; Vector<GFXShaderMacro> shaderMacros; shaderMacros.push_back( GFXShaderMacro( "TORQUE_SHADERGEN" ) ); if ( macros ) shaderMacros.merge( *macros ); generateShader( featureData, vertFile, pixFile, &pixVersion, vertexFormat, cacheKey, shaderMacros ); GFXShader *shader = GFX->createShader(); shader->mInstancingFormat.copy( mInstancingFormat ); // TODO: Move to init() below! if ( !shader->init( vertFile, pixFile, pixVersion, shaderMacros ) ) { delete shader; return NULL; } mProcShaders[cacheKey] = shader; return shader; }
GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os ) { F32 pixver = mPixVersion; if ( mUseDevicePixVersion ) pixver = getMax( pixver, GFX->getPixelShaderVersion() ); // Enable shader error logging. GFXShader::setLogging( true, true ); GFXShader *shader = GFX->createShader(); bool success = false; // Initialize the right shader type. switch( GFX->getAdapterType() ) { case Direct3D9_360: case Direct3D9: { success = shader->init( mDXVertexShaderName, mDXPixelShaderName, pixver, macros ); break; } case OpenGL: { success = shader->init( mOGLVertexShaderName, mOGLPixelShaderName, pixver, macros ); break; } default: // Other device types are assumed to not support shaders. success = false; break; } // If we failed to load the shader then // cleanup and return NULL. if ( !success ) SAFE_DELETE( shader ); return shader; }
GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os ) { F32 pixver = mPixVersion; if ( mUseDevicePixVersion ) pixver = getMax( pixver, GFX->getPixelShaderVersion() ); // Enable shader error logging. GFXShader::setLogging( true, true ); GFXShader *shader = GFX->createShader(); bool success = false; Vector<String> samplers; samplers.setSize(ShaderData::NumTextures); for(int i = 0; i < ShaderData::NumTextures; ++i) samplers[i] = mSamplerNames[i][0] == '$' ? mSamplerNames[i] : "$"+mSamplerNames[i]; // Initialize the right shader type. switch( GFX->getAdapterType() ) { case Direct3D9_360: case Direct3D9: case Direct3D11: { success = shader->init( mDXVertexShaderName, mDXPixelShaderName, pixver, macros, samplers); break; } case OpenGL: { success = shader->init( mOGLVertexShaderName, mOGLPixelShaderName, pixver, macros, samplers); break; } default: // Other device types are assumed to not support shaders. success = false; break; } #if defined(TORQUE_DEBUG) //Assert Sampler registers const Vector<GFXShaderConstDesc>& descs = shader->getShaderConstDesc(); for(int i = 0; i < descs.size(); ++i) { if(descs[i].constType != GFXSCT_Sampler && descs[i].constType != GFXSCT_SamplerCube) continue; GFXShaderConstHandle *handle = shader->findShaderConstHandle(descs[i].name); if(!handle || !handle->isValid()) continue; int reg = handle->getSamplerRegister(); if( descs[i].name != samplers[reg] ) { const char *err = avar("ShaderData(%s): samplerNames[%d] = \"%s\" are diferent to sampler in shader: %s : register(S%d)" ,getName(), reg, samplers[reg].c_str(), handle->getName().c_str(), reg); Con::printf(err); GFXAssertFatal(0, err); } } #endif // If we failed to load the shader then // cleanup and return NULL. if ( !success ) SAFE_DELETE( shader ); return shader; }