From 79e158d528ed7a1c6737671ea1f194cac7220975 Mon Sep 17 00:00:00 2001 From: LuisAntonRebollo Date: Sat, 8 Nov 2014 00:46:09 +0100 Subject: [PATCH] Add sampler names to ShaderData for use on old versions of OpenGL and Opengl ES2 that not support explicit sampler location on shader files. --- Engine/source/gfx/D3D9/gfxD3D9Shader.cpp | 18 +++- Engine/source/gfx/D3D9/gfxD3D9Shader.h | 1 + Engine/source/gfx/gfxDevice.h | 6 ++ Engine/source/gfx/gfxShader.h | 3 + Engine/source/materials/shaderData.cpp | 116 ++++++++++++++++++++++- Engine/source/materials/shaderData.h | 15 +++ 6 files changed, 156 insertions(+), 3 deletions(-) diff --git a/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp b/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp index a7ff68a78..2af7a9abd 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp @@ -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& GFXD3D9Shader::getShaderConstDesc() const { return mShaderConsts; diff --git a/Engine/source/gfx/D3D9/gfxD3D9Shader.h b/Engine/source/gfx/D3D9/gfxD3D9Shader.h index 1db493cf7..ccc3af282 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Shader.h +++ b/Engine/source/gfx/D3D9/gfxD3D9Shader.h @@ -205,6 +205,7 @@ public: virtual GFXShaderConstBufferRef allocConstBuffer(); virtual const Vector& 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; diff --git a/Engine/source/gfx/gfxDevice.h b/Engine/source/gfx/gfxDevice.h index 13620755e..75db6be69 100644 --- a/Engine/source/gfx/gfxDevice.h +++ b/Engine/source/gfx/gfxDevice.h @@ -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_ diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 4b2c10f46..318ab5ec0 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -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; diff --git a/Engine/source/materials/shaderData.cpp b/Engine/source/materials/shaderData.cpp index d0c526383..36e0a3994 100644 --- a/Engine/source/materials/shaderData.cpp +++ b/Engine/source/materials/shaderData.cpp @@ -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 ¯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 ¯os ) GFXShader *shader = GFX->createShader(); bool success = false; + Vector 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 ¯os ) success = shader->init( mDXVertexShaderName, mDXPixelShaderName, pixver, - macros ); + macros, + samplers); break; } @@ -225,7 +250,8 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) success = shader->init( mOGLVertexShaderName, mOGLPixelShaderName, pixver, - macros ); + macros, + samplers); break; } @@ -235,6 +261,29 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) break; } +#if defined(TORQUE_DEBUG) + //Assert Sampler registers + const Vector& 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 samplers; + samplers.reserve(NumTextures); + bool rtParams[NumTextures]; + for(int i = 0; i < NumTextures; ++i) + rtParams[i] = false; + + const Vector &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" diff --git a/Engine/source/materials/shaderData.h b/Engine/source/materials/shaderData.h index cc896e23f..cce62f324 100644 --- a/Engine/source/materials/shaderData.h +++ b/Engine/source/materials/shaderData.h @@ -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();