Explorar el Código

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 hace 11 años
padre
commit
79e158d528

+ 17 - 1
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<GFXShaderConstDesc>& GFXD3D9Shader::getShaderConstDesc() const
 {
    return mShaderConsts;

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

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

+ 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_

+ 3 - 0
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;   
 

+ 114 - 2
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<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"
 

+ 15 - 0
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();