Merge pull request #925 from BeamNG/shaderdata_samplernames

Add sampler names to ShaderData
This commit is contained in:
LuisAntonRebollo 2014-11-30 02:21:30 +01:00
commit 03ffa1ddd3
17 changed files with 314 additions and 26 deletions

View file

@ -1101,11 +1101,13 @@ void GFXD3D9Shader::_getShaderConstants( ID3DXConstantTable *table,
desc.constType = GFXSCT_Sampler; desc.constType = GFXSCT_Sampler;
desc.arraySize = constantDesc.RegisterIndex; desc.arraySize = constantDesc.RegisterIndex;
samplerDescriptions.push_back( desc ); samplerDescriptions.push_back( desc );
mShaderConsts.push_back(desc);
break; break;
case D3DXPT_SAMPLERCUBE : case D3DXPT_SAMPLERCUBE :
desc.constType = GFXSCT_SamplerCube; desc.constType = GFXSCT_SamplerCube;
desc.arraySize = constantDesc.RegisterIndex; desc.arraySize = constantDesc.RegisterIndex;
samplerDescriptions.push_back( desc ); samplerDescriptions.push_back( desc );
mShaderConsts.push_back(desc);
break; break;
} }
} }
@ -1371,7 +1373,7 @@ GFXShaderConstBufferRef GFXD3D9Shader::allocConstBuffer()
} }
} }
/// Returns a shader constant handle for name, if the variable doesn't exist NULL is returned. /// Returns a shader constant handle for name
GFXShaderConstHandle* GFXD3D9Shader::getShaderConstHandle(const String& name) GFXShaderConstHandle* GFXD3D9Shader::getShaderConstHandle(const String& name)
{ {
HandleMap::Iterator i = mHandles.find(name); HandleMap::Iterator i = mHandles.find(name);
@ -1390,6 +1392,20 @@ GFXShaderConstHandle* GFXD3D9Shader::getShaderConstHandle(const String& name)
} }
} }
/// Returns a shader constant handle for name, if the variable doesn't exist NULL is returned.
GFXShaderConstHandle* GFXD3D9Shader::findShaderConstHandle(const String& name)
{
HandleMap::Iterator i = mHandles.find(name);
if ( i != mHandles.end() )
{
return i->value;
}
else
{
return NULL;
}
}
const Vector<GFXShaderConstDesc>& GFXD3D9Shader::getShaderConstDesc() const const Vector<GFXShaderConstDesc>& GFXD3D9Shader::getShaderConstDesc() const
{ {
return mShaderConsts; return mShaderConsts;

View file

@ -205,6 +205,7 @@ public:
virtual GFXShaderConstBufferRef allocConstBuffer(); virtual GFXShaderConstBufferRef allocConstBuffer();
virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const; virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;
virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); virtual GFXShaderConstHandle* getShaderConstHandle(const String& name);
virtual GFXShaderConstHandle* findShaderConstHandle(const String& name);
virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; virtual U32 getAlignmentValue(const GFXShaderConstType constType) const;
virtual bool getDisassembly( String &outStr ) const; virtual bool getDisassembly( String &outStr ) const;

View file

@ -1117,4 +1117,10 @@ inline void GFXDevice::setVertexFormat( const GFXVertexFormat *vertexFormat )
} }
#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
#define GFXAssertFatal(x, error) AssertFatal(x, error)
#else
#define GFXAssertFatal(x, error)
#endif
#endif // _GFXDEVICE_H_ #endif // _GFXDEVICE_H_

View file

@ -332,6 +332,9 @@ public:
/// if the constant doesn't exist at this time. /// if the constant doesn't exist at this time.
virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0; virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0;
/// Returns a shader constant handle for the name constant, if the variable doesn't exist NULL is returned.
virtual GFXShaderConstHandle* findShaderConstHandle( const String& name ) = 0;
/// Returns the alignment value for constType /// Returns the alignment value for constType
virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0; virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0;

View file

@ -98,7 +98,7 @@ void DeferredRTLightingFeatHLSL::processPix( Vector<ShaderComponent*> &component
uvScene->setName( "uvScene" ); uvScene->setName( "uvScene" );
LangElement *uvSceneDecl = new DecOp( uvScene ); LangElement *uvSceneDecl = new DecOp( uvScene );
String rtParamName = String::ToString( "rtParams%d", mLastTexIndex ); String rtParamName = String::ToString( "rtParams%s", "lightInfoBuffer" );
Var *rtParams = (Var*) LangElement::find( rtParamName ); Var *rtParams = (Var*) LangElement::find( rtParamName );
if( !rtParams ) if( !rtParams )
{ {
@ -207,6 +207,7 @@ void DeferredRTLightingFeatHLSL::setTexData( Material::StageData &stageDat,
mLastTexIndex = texIndex; mLastTexIndex = texIndex;
passData.mTexType[ texIndex ] = Material::TexTarget; passData.mTexType[ texIndex ] = Material::TexTarget;
passData.mSamplerNames[ texIndex ]= "lightInfoBuffer";
passData.mTexSlot[ texIndex++ ].texTarget = texTarget; passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
} }
} }
@ -402,12 +403,14 @@ void DeferredBumpFeatHLSL::setTexData( Material::StageData &stageDat,
fd.features[MFT_PixSpecular] ) ) fd.features[MFT_PixSpecular] ) )
{ {
passData.mTexType[ texIndex ] = Material::Bump; passData.mTexType[ texIndex ] = Material::Bump;
passData.mSamplerNames[ texIndex ] = "bumpMap";
passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap );
if ( fd.features[MFT_PrePassConditioner] && if ( fd.features[MFT_PrePassConditioner] &&
fd.features.hasFeature( MFT_DetailNormalMap ) ) fd.features.hasFeature( MFT_DetailNormalMap ) )
{ {
passData.mTexType[ texIndex ] = Material::DetailBump; passData.mTexType[ texIndex ] = Material::DetailBump;
passData.mSamplerNames[ texIndex ] = "detailBumpMap";
passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap );
} }
} }

View file

@ -138,9 +138,25 @@ bool CustomMaterial::onAdd()
return false; return false;
} }
mSamplerNames[i] = entry->slotName + dStrlen(samplerDecl); // Assert sampler names are defined on ShaderData
mSamplerNames[i].insert(0, '$'); S32 pos = -1;
mTexFilename[i] = entry->value; String samplerName = entry->slotName + dStrlen(samplerDecl);
samplerName.insert(0, '$');
mShaderData->hasSamplerDef(samplerName, pos);
if(pos == -1)
{
const char *error = (avar("CustomMaterial(%s) bind sampler[%s] and is not present on ShaderData(%s)",
getName(), samplerName.c_str(), mShaderDataName.c_str() ));
Con::errorf(error);
#if TORQUE_OPENGL
GFXAssertFatal(0, error);
continue;
#endif
}
mSamplerNames[pos] = samplerName;
mTexFilename[pos] = entry->value;
++i; ++i;
} }
} }

View file

@ -79,6 +79,7 @@ void ProcessedCustomMaterial::_setStageData()
if(filename.equal(String("$dynamiclight"), String::NoCase)) if(filename.equal(String("$dynamiclight"), String::NoCase))
{ {
rpd->mTexType[i] = Material::DynamicLight; rpd->mTexType[i] = Material::DynamicLight;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
continue; continue;
} }
@ -86,6 +87,7 @@ void ProcessedCustomMaterial::_setStageData()
if(filename.equal(String("$dynamiclightmask"), String::NoCase)) if(filename.equal(String("$dynamiclightmask"), String::NoCase))
{ {
rpd->mTexType[i] = Material::DynamicLightMask; rpd->mTexType[i] = Material::DynamicLightMask;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
continue; continue;
} }
@ -93,6 +95,7 @@ void ProcessedCustomMaterial::_setStageData()
if(filename.equal(String("$lightmap"), String::NoCase)) if(filename.equal(String("$lightmap"), String::NoCase))
{ {
rpd->mTexType[i] = Material::Lightmap; rpd->mTexType[i] = Material::Lightmap;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
continue; continue;
} }
@ -102,6 +105,7 @@ void ProcessedCustomMaterial::_setStageData()
if( mCustomMaterial->mCubemapData ) if( mCustomMaterial->mCubemapData )
{ {
rpd->mTexType[i] = Material::Cube; rpd->mTexType[i] = Material::Cube;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
} }
else else
@ -114,6 +118,7 @@ void ProcessedCustomMaterial::_setStageData()
if(filename.equal(String("$dynamicCubemap"), String::NoCase)) if(filename.equal(String("$dynamicCubemap"), String::NoCase))
{ {
rpd->mTexType[i] = Material::SGCube; rpd->mTexType[i] = Material::SGCube;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
continue; continue;
} }
@ -121,6 +126,7 @@ void ProcessedCustomMaterial::_setStageData()
if(filename.equal(String("$backbuff"), String::NoCase)) if(filename.equal(String("$backbuff"), String::NoCase))
{ {
rpd->mTexType[i] = Material::BackBuff; rpd->mTexType[i] = Material::BackBuff;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
continue; continue;
} }
@ -128,6 +134,7 @@ void ProcessedCustomMaterial::_setStageData()
if(filename.equal(String("$reflectbuff"), String::NoCase)) if(filename.equal(String("$reflectbuff"), String::NoCase))
{ {
rpd->mTexType[i] = Material::ReflectBuff; rpd->mTexType[i] = Material::ReflectBuff;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
continue; continue;
} }
@ -135,6 +142,7 @@ void ProcessedCustomMaterial::_setStageData()
if(filename.equal(String("$miscbuff"), String::NoCase)) if(filename.equal(String("$miscbuff"), String::NoCase))
{ {
rpd->mTexType[i] = Material::Misc; rpd->mTexType[i] = Material::Misc;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
continue; continue;
} }
@ -151,6 +159,7 @@ void ProcessedCustomMaterial::_setStageData()
texTarget->getShaderMacros( &mConditionerMacros ); texTarget->getShaderMacros( &mConditionerMacros );
rpd->mTexType[i] = Material::TexTarget; rpd->mTexType[i] = Material::TexTarget;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
continue; continue;
} }
@ -162,6 +171,7 @@ void ProcessedCustomMaterial::_setStageData()
continue; continue;
} }
rpd->mTexType[i] = Material::Standard; rpd->mTexType[i] = Material::Standard;
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
mMaxTex = i+1; mMaxTex = i+1;
} }
@ -232,6 +242,20 @@ bool ProcessedCustomMaterial::init( const FeatureSet &features,
setMaterialParameters( mDefaultParameters, 0 ); setMaterialParameters( mDefaultParameters, 0 );
mStateHint.init( this ); mStateHint.init( this );
for(int i = 0; i < mMaxTex; i++)
{
ShaderConstHandles *handles = _getShaderConstHandles( mPasses.size()-1 );
AssertFatal(handles,"");
if(rpd->mSamplerNames[i].isEmpty())
continue;
String samplerName = rpd->mSamplerNames[i].startsWith("$") ? rpd->mSamplerNames[i] : String("$") + rpd->mSamplerNames[i];
GFXShaderConstHandle *handle = rpd->shader->getShaderConstHandle( samplerName );
AssertFatal(handle,"");
handles->mTexHandlesSC[i] = handle;
}
return true; return true;
} }
@ -384,14 +408,14 @@ void ProcessedCustomMaterial::setTextureStages( SceneRenderState *state, const S
if ( !texObject ) if ( !texObject )
texObject = GFXTexHandle::ZERO; texObject = GFXTexHandle::ZERO;
if ( handles->mRTParamsSC[samplerRegister]->isValid() && texObject ) if ( handles->mRTParamsSC[i]->isValid() && texObject )
{ {
const Point3I &targetSz = texObject->getSize(); const Point3I &targetSz = texObject->getSize();
const RectI &targetVp = texTarget->getViewport(); const RectI &targetVp = texTarget->getViewport();
Point4F rtParams; Point4F rtParams;
ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams); ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams);
shaderConsts->set(handles->mRTParamsSC[samplerRegister], rtParams); shaderConsts->set(handles->mRTParamsSC[i], rtParams);
} }
GFX->setTexture( samplerRegister, texObject ); GFX->setTexture( samplerRegister, texObject );

View file

@ -221,6 +221,7 @@ bool ProcessedShaderMaterial::init( const FeatureSet &features,
{ {
rpd->mTexSlot[0].texTarget = texTarget; rpd->mTexSlot[0].texTarget = texTarget;
rpd->mTexType[0] = Material::TexTarget; rpd->mTexType[0] = Material::TexTarget;
rpd->mSamplerNames[0] = "diffuseMap";
} }
} }
@ -516,8 +517,23 @@ bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures,
passData.mNumTexReg += numTexReg; passData.mNumTexReg += numTexReg;
passData.mFeatureData.features.addFeature( *info.type ); passData.mFeatureData.features.addFeature( *info.type );
#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL)
U32 oldTexNumber = texIndex;
#endif
info.feature->setTexData( mStages[stageNum], stageFeatures, passData, texIndex ); info.feature->setTexData( mStages[stageNum], stageFeatures, passData, texIndex );
#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL)
if(oldTexNumber != texIndex)
{
for(int i = oldTexNumber; i < texIndex; i++)
{
AssertFatal(passData.mSamplerNames[ oldTexNumber ].isNotEmpty(), avar( "ERROR: ShaderGen feature %s don't set used sampler name", info.feature->getName().c_str()) );
}
}
#endif
// Add pass if tex units are maxed out // Add pass if tex units are maxed out
if( texIndex > GFX->getNumSamplers() ) if( texIndex > GFX->getNumSamplers() )
{ {
@ -527,6 +543,13 @@ bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures,
} }
} }
#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL)
for(int i = 0; i < texIndex; i++)
{
AssertFatal(passData.mSamplerNames[ i ].isNotEmpty(),"");
}
#endif
const FeatureSet &passFeatures = passData.mFeatureData.codify(); const FeatureSet &passFeatures = passData.mFeatureData.codify();
if ( passFeatures.isNotEmpty() ) if ( passFeatures.isNotEmpty() )
{ {
@ -587,9 +610,16 @@ bool ProcessedShaderMaterial::_addPass( ShaderRenderPassData &rpd,
// Copy over features // Copy over features
rpd.mFeatureData.materialFeatures = fd.features; rpd.mFeatureData.materialFeatures = fd.features;
Vector<String> samplers;
samplers.setSize(Material::MAX_TEX_PER_PASS);
for(int i = 0; i < Material::MAX_TEX_PER_PASS; ++i)
{
samplers[i] = (rpd.mSamplerNames[i].isEmpty() || rpd.mSamplerNames[i][0] == '$') ? rpd.mSamplerNames[i] : "$" + rpd.mSamplerNames[i];
}
// Generate shader // Generate shader
GFXShader::setLogging( true, true ); GFXShader::setLogging( true, true );
rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mVertexFormat, &mUserMacros ); rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mVertexFormat, &mUserMacros, samplers );
if( !rpd.shader ) if( !rpd.shader )
return false; return false;
rpd.shaderHandles.init( rpd.shader ); rpd.shaderHandles.init( rpd.shader );
@ -601,6 +631,30 @@ bool ProcessedShaderMaterial::_addPass( ShaderRenderPassData &rpd,
ShaderRenderPassData *newPass = new ShaderRenderPassData( rpd ); ShaderRenderPassData *newPass = new ShaderRenderPassData( rpd );
mPasses.push_back( newPass ); mPasses.push_back( newPass );
//initSamplerHandles
ShaderConstHandles *handles = _getShaderConstHandles( mPasses.size()-1 );
AssertFatal(handles,"");
for(int i = 0; i < rpd.mNumTex; i++)
{
if(rpd.mSamplerNames[i].isEmpty())
{
handles->mTexHandlesSC[i] = newPass->shader->getShaderConstHandle( String::EmptyString );
handles->mRTParamsSC[i] = newPass->shader->getShaderConstHandle( String::EmptyString );
continue;
}
String samplerName = rpd.mSamplerNames[i];
if( !samplerName.startsWith("$"))
samplerName.insert(0, "$");
GFXShaderConstHandle *handle = newPass->shader->getShaderConstHandle( samplerName );
handles->mTexHandlesSC[i] = handle;
handles->mRTParamsSC[i] = newPass->shader->getShaderConstHandle( String::ToString( "$rtParams%s", samplerName.c_str()+1 ) );
AssertFatal( handle,"");
}
// Give each active feature a chance to create specialized shader consts. // Give each active feature a chance to create specialized shader consts.
for( U32 i=0; i < FEATUREMGR->getFeatureCount(); i++ ) for( U32 i=0; i < FEATUREMGR->getFeatureCount(); i++ )
{ {
@ -705,6 +759,7 @@ void ProcessedShaderMaterial::setTextureStages( SceneRenderState *state, const S
PROFILE_SCOPE( ProcessedShaderMaterial_SetTextureStages ); PROFILE_SCOPE( ProcessedShaderMaterial_SetTextureStages );
ShaderConstHandles *handles = _getShaderConstHandles(pass); ShaderConstHandles *handles = _getShaderConstHandles(pass);
AssertFatal(handles,"");
// Set all of the textures we need to render the give pass. // Set all of the textures we need to render the give pass.
#ifdef TORQUE_DEBUG #ifdef TORQUE_DEBUG

View file

@ -64,6 +64,9 @@ ShaderData::ShaderData()
mUseDevicePixVersion = false; mUseDevicePixVersion = false;
mPixVersion = 1.0; mPixVersion = 1.0;
for( int i = 0; i < NumTextures; ++i)
mRTParams[i] = false;
} }
void ShaderData::initPersistFields() void ShaderData::initPersistFields()
@ -115,6 +118,14 @@ void ShaderData::initPersistFields()
"@endtsexample\n\n" "@endtsexample\n\n"
); );
addField("samplerNames", TypeRealString, Offset(mSamplerNames, ShaderData), NumTextures,
"@brief Indicates names of samplers present in shader. Order is important.\n\n"
"Order of sampler names are used to assert correct sampler register/location"
"Other objects (GFXStateBlockData, PostEffect...) use index number to link samplers."
);
addField("rtParams", TypeBool, Offset(mRTParams, ShaderData), NumTextures, "");
Parent::initPersistFields(); Parent::initPersistFields();
// Make sure we get activation signals. // Make sure we get activation signals.
@ -133,6 +144,12 @@ bool ShaderData::onAdd()
// NOTE: We initialize the shader on request. // NOTE: We initialize the shader on request.
for(int i = 0; i < NumTextures; ++i)
{
if( mSamplerNames[i].isNotEmpty() && !mSamplerNames[i].startsWith("$") )
mSamplerNames[i].insert(0, "$");
}
return true; return true;
} }
@ -190,6 +207,8 @@ GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> &macros )
if ( !shader ) if ( !shader )
return NULL; return NULL;
_checkDefinition(shader);
// Store the shader in the cache and return it. // Store the shader in the cache and return it.
mShaders.insertUnique( cacheKey, shader ); mShaders.insertUnique( cacheKey, shader );
return shader; return shader;
@ -207,6 +226,11 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
GFXShader *shader = GFX->createShader(); GFXShader *shader = GFX->createShader();
bool success = false; 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. // Initialize the right shader type.
switch( GFX->getAdapterType() ) switch( GFX->getAdapterType() )
{ {
@ -216,7 +240,8 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
success = shader->init( mDXVertexShaderName, success = shader->init( mDXVertexShaderName,
mDXPixelShaderName, mDXPixelShaderName,
pixver, pixver,
macros ); macros,
samplers);
break; break;
} }
@ -225,7 +250,8 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
success = shader->init( mOGLVertexShaderName, success = shader->init( mOGLVertexShaderName,
mOGLPixelShaderName, mOGLPixelShaderName,
pixver, pixver,
macros ); macros,
samplers);
break; break;
} }
@ -235,6 +261,29 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
break; 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 // If we failed to load the shader then
// cleanup and return NULL. // cleanup and return NULL.
if ( !success ) if ( !success )
@ -270,6 +319,69 @@ void ShaderData::_onLMActivate( const char *lm, bool activate )
reloadAllShaders(); reloadAllShaders();
} }
bool ShaderData::hasSamplerDef(const String &_samplerName, int &pos) const
{
String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName;
for(int i = 0; i < NumTextures; ++i)
{
if( mSamplerNames[i].equal(samplerName, String::NoCase ) )
{
pos = i;
return true;
}
}
pos = -1;
return false;
}
bool ShaderData::_checkDefinition(GFXShader *shader)
{
bool error = false;
Vector<String> samplers;
samplers.reserve(NumTextures);
bool rtParams[NumTextures];
for(int i = 0; i < NumTextures; ++i)
rtParams[i] = false;
const Vector<GFXShaderConstDesc> &shaderConstDesc = shader->getShaderConstDesc();
for(int i = 0; i < shaderConstDesc.size(); ++i)
{
const GFXShaderConstDesc &desc = shaderConstDesc[i];
if(desc.constType == GFXSCT_Sampler)
{
samplers.push_back(desc.name );
}
}
for(int i = 0; i < samplers.size(); ++i)
{
int pos;
bool find = hasSamplerDef(samplers[i], pos);
if(find && pos >= 0 && mRTParams[pos])
{
if( !shader->findShaderConstHandle( String::ToString("$rtParams%d", pos)) )
{
String error = String::ToString("ShaderData(%s) sampler[%d] used but rtParams%d not used in shader compilation. Possible error", getName(), pos, pos);
Con::errorf( error );
error = true;
}
}
if(!find)
{
String error = String::ToString("ShaderData(%s) sampler %s not defined", getName(), samplers[i].c_str());
Con::errorf(error );
GFXAssertFatal(0, error );
error = true;
}
}
return !error;
}
DefineEngineMethod( ShaderData, reload, void, (),, DefineEngineMethod( ShaderData, reload, void, (),,
"@brief Rebuilds all the vertex and pixel shader instances created from this ShaderData.\n\n" "@brief Rebuilds all the vertex and pixel shader instances created from this ShaderData.\n\n"

View file

@ -91,8 +91,23 @@ protected:
/// @see LightManager::smActivateSignal /// @see LightManager::smActivateSignal
static void _onLMActivate( const char *lm, bool activate ); static void _onLMActivate( const char *lm, bool activate );
enum
{
NumTextures = 8
};
String mSamplerNames[NumTextures];
bool mRTParams[NumTextures];
bool _checkDefinition(GFXShader *shader);
public: public:
void setSamplerName(const String &name, int idx) { mSamplerNames[idx] = name; }
String getSamplerName(int idx) const { return mSamplerNames[idx]; }
bool hasSamplerDef(const String &samplerName, int &pos) const;
bool hasRTParamsDef(const int pos) const { return mRTParams[pos]; }
ShaderData(); ShaderData();

View file

@ -222,12 +222,14 @@ void BumpFeatHLSL::setTexData( Material::StageData &stageDat,
if ( fd.features[MFT_NormalMap] ) if ( fd.features[MFT_NormalMap] )
{ {
passData.mTexType[ texIndex ] = Material::Bump; passData.mTexType[ texIndex ] = Material::Bump;
passData.mSamplerNames[ texIndex ] = "bumpMap";
passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap );
} }
if ( fd.features[ MFT_DetailNormalMap ] ) if ( fd.features[ MFT_DetailNormalMap ] )
{ {
passData.mTexType[ texIndex ] = Material::DetailBump; passData.mTexType[ texIndex ] = Material::DetailBump;
passData.mSamplerNames[ texIndex ] = "detailBumpMap";
passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap );
} }
} }
@ -382,6 +384,7 @@ void ParallaxFeatHLSL::setTexData( Material::StageData &stageDat,
GFXTextureObject *tex = stageDat.getTex( MFT_NormalMap ); GFXTextureObject *tex = stageDat.getTex( MFT_NormalMap );
if ( tex ) if ( tex )
{ {
passData.mSamplerNames[ texIndex ] = "bumpMap";
passData.mTexType[ texIndex ] = Material::Bump; passData.mTexType[ texIndex ] = Material::Bump;
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
} }

View file

@ -147,6 +147,7 @@ void SpecularMapHLSL::setTexData( Material::StageData &stageDat,
if ( tex ) if ( tex )
{ {
passData.mTexType[ texIndex ] = Material::Standard; passData.mTexType[ texIndex ] = Material::Standard;
passData.mSamplerNames[ texIndex ] = "specularMap";
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
} }
} }

View file

@ -985,7 +985,10 @@ void DiffuseMapFeatHLSL::setTexData( Material::StageData &stageDat,
{ {
GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap ); GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap );
if ( tex ) if ( tex )
{
passData.mSamplerNames[ texIndex ] = "diffuseMap";
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
}
} }
@ -1069,7 +1072,10 @@ void OverlayTexFeatHLSL::setTexData( Material::StageData &stageDat,
{ {
GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap ); GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap );
if ( tex ) if ( tex )
{
passData.mSamplerNames[texIndex] = "overlayMap";
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
}
} }
@ -1257,6 +1263,7 @@ void LightmapFeatHLSL::setTexData( Material::StageData &stageDat,
U32 &texIndex ) U32 &texIndex )
{ {
GFXTextureObject *tex = stageDat.getTex( MFT_LightMap ); GFXTextureObject *tex = stageDat.getTex( MFT_LightMap );
passData.mSamplerNames[ texIndex ] = "lightMap";
if ( tex ) if ( tex )
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
else else
@ -1386,6 +1393,7 @@ void TonemapFeatHLSL::setTexData( Material::StageData &stageDat,
if ( tex ) if ( tex )
{ {
passData.mTexType[ texIndex ] = Material::ToneMapTex; passData.mTexType[ texIndex ] = Material::ToneMapTex;
passData.mSamplerNames[ texIndex ] = "toneMap";
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
} }
} }
@ -1576,7 +1584,10 @@ void DetailFeatHLSL::setTexData( Material::StageData &stageDat,
{ {
GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap );
if ( tex ) if ( tex )
{
passData.mSamplerNames[texIndex] = "detailMap";
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
}
} }
@ -1846,22 +1857,27 @@ void ReflectCubeFeatHLSL::setTexData( Material::StageData &stageDat,
!passData.mFeatureData.features[MFT_NormalMap] ) !passData.mFeatureData.features[MFT_NormalMap] )
{ {
GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap );
if ( tex && if ( tex && stageFeatures.features[MFT_DiffuseMap] )
stageFeatures.features[MFT_DiffuseMap] ) {
passData.mSamplerNames[ texIndex ] = "diffuseMap";
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
}
else else
{ {
tex = stageDat.getTex( MFT_NormalMap ); tex = stageDat.getTex( MFT_NormalMap );
if ( tex && if ( tex && stageFeatures.features[ MFT_NormalMap ] )
stageFeatures.features[ MFT_NormalMap ] ) {
passData.mSamplerNames[ texIndex ] = "bumpMap";
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
} }
} }
}
if( stageDat.getCubemap() ) if( stageDat.getCubemap() )
{ {
passData.mCubeMap = stageDat.getCubemap(); passData.mCubeMap = stageDat.getCubemap();
passData.mSamplerNames[texIndex] = "cubeMap";
passData.mTexType[texIndex++] = Material::Cube; passData.mTexType[texIndex++] = Material::Cube;
} }
else else
@ -1869,6 +1885,7 @@ void ReflectCubeFeatHLSL::setTexData( Material::StageData &stageDat,
if( stageFeatures.features[MFT_CubeMap] ) if( stageFeatures.features[MFT_CubeMap] )
{ {
// assuming here that it is a scenegraph cubemap // assuming here that it is a scenegraph cubemap
passData.mSamplerNames[texIndex] = "cubeMap";
passData.mTexType[texIndex++] = Material::SGCube; passData.mTexType[texIndex++] = Material::SGCube;
} }
} }

View file

@ -443,7 +443,7 @@ void ShaderGen::_printPixShader( Stream &stream )
mPrinter->printPixelShaderCloser(stream); mPrinter->printPixelShaderCloser(stream);
} }
GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros ) GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros, const Vector<String> &samplers )
{ {
PROFILE_SCOPE( ShaderGen_GetShader ); PROFILE_SCOPE( ShaderGen_GetShader );
@ -488,7 +488,7 @@ GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const G
GFXShader *shader = GFX->createShader(); GFXShader *shader = GFX->createShader();
shader->mInstancingFormat.copy( mInstancingFormat ); // TODO: Move to init() below! shader->mInstancingFormat.copy( mInstancingFormat ); // TODO: Move to init() below!
if ( !shader->init( vertFile, pixFile, pixVersion, shaderMacros ) ) if ( !shader->init( vertFile, pixFile, pixVersion, shaderMacros, samplers ) )
{ {
delete shader; delete shader;
return NULL; return NULL;

View file

@ -155,7 +155,7 @@ public:
Vector<GFXShaderMacro> &macros ); Vector<GFXShaderMacro> &macros );
// Returns a shader that implements the features listed by dat. // Returns a shader that implements the features listed by dat.
GFXShader* getShader( const MaterialFeatureData &dat, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros ); GFXShader* getShader( const MaterialFeatureData &dat, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros, const Vector<String> &samplers );
// This will delete all of the procedural shaders that we have. Used to regenerate shaders when // This will delete all of the procedural shaders that we have. Used to regenerate shaders when
// the ShaderFeatures have changed (due to lighting system change, or new plugin) // the ShaderFeatures have changed (due to lighting system change, or new plugin)

View file

@ -46,6 +46,27 @@ AFTER_MODULE_INIT( MaterialManager )
Vector<TerrainCellMaterial*> TerrainCellMaterial::smAllMaterials; Vector<TerrainCellMaterial*> TerrainCellMaterial::smAllMaterials;
Vector<String> _initSamplerNames()
{
Vector<String> samplerNames;
samplerNames.push_back("$baseTexMap");
samplerNames.push_back("$layerTex");
samplerNames.push_back("$macrolayerTex");
samplerNames.push_back("$lightMapTex");
samplerNames.push_back("$lightInfoBuffer");
for(int i = 0; i < 3; ++i)
{
samplerNames.push_back(avar("$normalMap%d",i));
samplerNames.push_back(avar("$detailMap%d",i));
samplerNames.push_back(avar("$macroMap%d",i));
}
return samplerNames;
}
const Vector<String> TerrainCellMaterial::mSamplerNames = _initSamplerNames();
TerrainCellMaterial::TerrainCellMaterial() TerrainCellMaterial::TerrainCellMaterial()
: mCurrPass( 0 ), : mCurrPass( 0 ),
mTerrain( NULL ), mTerrain( NULL ),
@ -460,7 +481,7 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
const bool logErrors = matCount == 1; const bool logErrors = matCount == 1;
GFXShader::setLogging( logErrors, true ); GFXShader::setLogging( logErrors, true );
pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat<TerrVertex>(), NULL ); pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames );
} }
// If we got a shader then we can continue. // If we got a shader then we can continue.
@ -499,14 +520,7 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
pass->oneOverTerrainSize = pass->shader->getShaderConstHandle( "$oneOverTerrainSize" ); pass->oneOverTerrainSize = pass->shader->getShaderConstHandle( "$oneOverTerrainSize" );
pass->squareSize = pass->shader->getShaderConstHandle( "$squareSize" ); pass->squareSize = pass->shader->getShaderConstHandle( "$squareSize" );
// NOTE: We're assuming rtParams0 here as we know its the only pass->lightParamsConst = pass->shader->getShaderConstHandle( "$rtParamslightInfoBuffer" );
// render target we currently get in a terrain material and the
// DeferredRTLightingFeatHLSL will always use 0.
//
// This could change in the future and we would need to fix
// the ShaderFeature API to allow us to do this right.
//
pass->lightParamsConst = pass->shader->getShaderConstHandle( "$rtParams0" );
// Now prepare the basic stateblock. // Now prepare the basic stateblock.
GFXStateBlockDesc desc; GFXStateBlockDesc desc;

View file

@ -144,6 +144,8 @@ protected:
U32 mCurrPass; U32 mCurrPass;
static const Vector<String> mSamplerNames;
GFXTexHandle mBaseMapTexture; GFXTexHandle mBaseMapTexture;
GFXTexHandle mLayerMapTexture; GFXTexHandle mLayerMapTexture;