mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-21 12:25:30 +00:00
Merge pull request #925 from BeamNG/shaderdata_samplernames
Add sampler names to ShaderData
This commit is contained in:
commit
03ffa1ddd3
17 changed files with 314 additions and 26 deletions
|
|
@ -138,9 +138,25 @@ bool CustomMaterial::onAdd()
|
|||
return false;
|
||||
}
|
||||
|
||||
mSamplerNames[i] = entry->slotName + dStrlen(samplerDecl);
|
||||
mSamplerNames[i].insert(0, '$');
|
||||
mTexFilename[i] = entry->value;
|
||||
// Assert sampler names are defined on ShaderData
|
||||
S32 pos = -1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
if(filename.equal(String("$dynamiclight"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::DynamicLight;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -86,6 +87,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
if(filename.equal(String("$dynamiclightmask"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::DynamicLightMask;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -93,6 +95,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
if(filename.equal(String("$lightmap"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::Lightmap;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -102,6 +105,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
if( mCustomMaterial->mCubemapData )
|
||||
{
|
||||
rpd->mTexType[i] = Material::Cube;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
}
|
||||
else
|
||||
|
|
@ -114,6 +118,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
if(filename.equal(String("$dynamicCubemap"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::SGCube;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -121,6 +126,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
if(filename.equal(String("$backbuff"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::BackBuff;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -128,6 +134,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
if(filename.equal(String("$reflectbuff"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::ReflectBuff;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -135,6 +142,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
if(filename.equal(String("$miscbuff"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::Misc;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -151,6 +159,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
texTarget->getShaderMacros( &mConditionerMacros );
|
||||
|
||||
rpd->mTexType[i] = Material::TexTarget;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -162,6 +171,7 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
continue;
|
||||
}
|
||||
rpd->mTexType[i] = Material::Standard;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i+1;
|
||||
}
|
||||
|
||||
|
|
@ -232,6 +242,20 @@ bool ProcessedCustomMaterial::init( const FeatureSet &features,
|
|||
setMaterialParameters( mDefaultParameters, 0 );
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -384,14 +408,14 @@ void ProcessedCustomMaterial::setTextureStages( SceneRenderState *state, const S
|
|||
if ( !texObject )
|
||||
texObject = GFXTexHandle::ZERO;
|
||||
|
||||
if ( handles->mRTParamsSC[samplerRegister]->isValid() && texObject )
|
||||
if ( handles->mRTParamsSC[i]->isValid() && texObject )
|
||||
{
|
||||
const Point3I &targetSz = texObject->getSize();
|
||||
const RectI &targetVp = texTarget->getViewport();
|
||||
Point4F rtParams;
|
||||
|
||||
ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams);
|
||||
shaderConsts->set(handles->mRTParamsSC[samplerRegister], rtParams);
|
||||
shaderConsts->set(handles->mRTParamsSC[i], rtParams);
|
||||
}
|
||||
|
||||
GFX->setTexture( samplerRegister, texObject );
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ bool ProcessedShaderMaterial::init( const FeatureSet &features,
|
|||
{
|
||||
rpd->mTexSlot[0].texTarget = texTarget;
|
||||
rpd->mTexType[0] = Material::TexTarget;
|
||||
rpd->mSamplerNames[0] = "diffuseMap";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -516,8 +517,23 @@ bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures,
|
|||
|
||||
passData.mNumTexReg += numTexReg;
|
||||
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 );
|
||||
|
||||
#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
|
||||
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();
|
||||
if ( passFeatures.isNotEmpty() )
|
||||
{
|
||||
|
|
@ -587,9 +610,16 @@ bool ProcessedShaderMaterial::_addPass( ShaderRenderPassData &rpd,
|
|||
// Copy over 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
|
||||
GFXShader::setLogging( true, true );
|
||||
rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mVertexFormat, &mUserMacros );
|
||||
rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mVertexFormat, &mUserMacros, samplers );
|
||||
if( !rpd.shader )
|
||||
return false;
|
||||
rpd.shaderHandles.init( rpd.shader );
|
||||
|
|
@ -601,6 +631,30 @@ bool ProcessedShaderMaterial::_addPass( ShaderRenderPassData &rpd,
|
|||
ShaderRenderPassData *newPass = new ShaderRenderPassData( rpd );
|
||||
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.
|
||||
for( U32 i=0; i < FEATUREMGR->getFeatureCount(); i++ )
|
||||
{
|
||||
|
|
@ -705,6 +759,7 @@ void ProcessedShaderMaterial::setTextureStages( SceneRenderState *state, const S
|
|||
PROFILE_SCOPE( ProcessedShaderMaterial_SetTextureStages );
|
||||
|
||||
ShaderConstHandles *handles = _getShaderConstHandles(pass);
|
||||
AssertFatal(handles,"");
|
||||
|
||||
// Set all of the textures we need to render the give pass.
|
||||
#ifdef TORQUE_DEBUG
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ ShaderData::ShaderData()
|
|||
|
||||
mUseDevicePixVersion = false;
|
||||
mPixVersion = 1.0;
|
||||
|
||||
for( int i = 0; i < NumTextures; ++i)
|
||||
mRTParams[i] = false;
|
||||
}
|
||||
|
||||
void ShaderData::initPersistFields()
|
||||
|
|
@ -115,6 +118,14 @@ void ShaderData::initPersistFields()
|
|||
"@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();
|
||||
|
||||
// Make sure we get activation signals.
|
||||
|
|
@ -133,6 +144,12 @@ bool ShaderData::onAdd()
|
|||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
@ -190,6 +207,8 @@ GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> ¯os )
|
|||
if ( !shader )
|
||||
return NULL;
|
||||
|
||||
_checkDefinition(shader);
|
||||
|
||||
// Store the shader in the cache and return it.
|
||||
mShaders.insertUnique( cacheKey, shader );
|
||||
return shader;
|
||||
|
|
@ -207,6 +226,11 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os )
|
|||
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() )
|
||||
{
|
||||
|
|
@ -216,7 +240,8 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os )
|
|||
success = shader->init( mDXVertexShaderName,
|
||||
mDXPixelShaderName,
|
||||
pixver,
|
||||
macros );
|
||||
macros,
|
||||
samplers);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -225,7 +250,8 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os )
|
|||
success = shader->init( mOGLVertexShaderName,
|
||||
mOGLPixelShaderName,
|
||||
pixver,
|
||||
macros );
|
||||
macros,
|
||||
samplers);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -235,6 +261,29 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os )
|
|||
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 )
|
||||
|
|
@ -270,6 +319,69 @@ void ShaderData::_onLMActivate( const char *lm, bool activate )
|
|||
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, (),,
|
||||
"@brief Rebuilds all the vertex and pixel shader instances created from this ShaderData.\n\n"
|
||||
|
||||
|
|
|
|||
|
|
@ -91,8 +91,23 @@ protected:
|
|||
/// @see LightManager::smActivateSignal
|
||||
static void _onLMActivate( const char *lm, bool activate );
|
||||
|
||||
enum
|
||||
{
|
||||
NumTextures = 8
|
||||
};
|
||||
|
||||
String mSamplerNames[NumTextures];
|
||||
bool mRTParams[NumTextures];
|
||||
|
||||
bool _checkDefinition(GFXShader *shader);
|
||||
|
||||
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();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue