ソースを参照

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

LuisAntonRebollo 11 年 前
コミット
79e158d528

+ 17 - 1
Engine/source/gfx/D3D9/gfxD3D9Shader.cpp

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

+ 1 - 0
Engine/source/gfx/D3D9/gfxD3D9Shader.h

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

+ 6 - 0
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_
 #endif // _GFXDEVICE_H_

+ 3 - 0
Engine/source/gfx/gfxShader.h

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

+ 114 - 2
Engine/source/materials/shaderData.cpp

@@ -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"
 
 

+ 15 - 0
Engine/source/materials/shaderData.h

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