Add sampler names to ShaderData for use on old versions of OpenGL and Opengl ES2 that not support explicit sampler location on shader files.

This commit is contained in:
LuisAntonRebollo 2014-11-08 00:46:09 +01:00
parent c354f59b72
commit 79e158d528
6 changed files with 156 additions and 3 deletions

View file

@ -1101,11 +1101,13 @@ void GFXD3D9Shader::_getShaderConstants( ID3DXConstantTable *table,
desc.constType = GFXSCT_Sampler;
desc.arraySize = constantDesc.RegisterIndex;
samplerDescriptions.push_back( desc );
mShaderConsts.push_back(desc);
break;
case D3DXPT_SAMPLERCUBE :
desc.constType = GFXSCT_SamplerCube;
desc.arraySize = constantDesc.RegisterIndex;
samplerDescriptions.push_back( desc );
mShaderConsts.push_back(desc);
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)
{
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
{
return mShaderConsts;

View file

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

View file

@ -332,6 +332,9 @@ public:
/// if the constant doesn't exist at this time.
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
virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0;

View file

@ -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> &macros )
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> &macros )
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> &macros )
success = shader->init( mDXVertexShaderName,
mDXPixelShaderName,
pixver,
macros );
macros,
samplers);
break;
}
@ -225,7 +250,8 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
success = shader->init( mOGLVertexShaderName,
mOGLPixelShaderName,
pixver,
macros );
macros,
samplers);
break;
}
@ -235,6 +261,29 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
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"

View file

@ -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();