#if _MSC_VER >= 1700
#pragma warning( disable: 4005 )
#endif
#include <maya/MString.h>
#include <maya/MGlobal.h>
#include <maya/MFileObject.h>
#include <maya/MSceneMessage.h>
#include "dx11ShaderCompileHelper.h"
#include "dx11ShaderStrings.h"
#define WIN32_LEAN_AND_MEAN
#include <d3d11.h>
#if _MSC_VER < 1700
#include <d3dx11.h>
#endif
#if defined(JAMBUILD)
#include <maya/d3dx11effect.h>
#else
#include <../Samples/C++/Effects11/Inc/d3dx11effect.h>
#ifndef USE_BOOL
#define USE_BOOL // use BOOL instead of bool
#endif
#endif
#include <d3dcompiler.h>
#include <sys/stat.h>
#include <string.h>
#include <map>
#include <set>
#include <list>
namespace CDX11EffectCompileHelper
{
    class CFileReferenceHelper
    {
    public:
        MString resolveFileName(
const char* fileName) 
const;
 
        void setReferencePath(
MString fileName);
 
    protected:
        MString findFile(
const char* fileName) 
const;
 
    };
    MString CFileReferenceHelper::resolveFileName(
const char* fileName)
 const 
    {
        
        int hasFile = file.
length() > 0;
 
        if (hasFile == 0)
        {
            
            int idx = currFileName.
rindex(
'/');
 
            if (idx == -1)
                idx = currFileName.
rindex(
'\\');
            if (idx != -1)
            {
                file = findFile(currFileName.
asChar());
            }
        }
        {
            MString expandedFileName(
MString(fileName).expandEnvironmentVariablesAndTilde());
 
            file = findFile(expandedFileName.
asChar());
        }
        return file;
    }
    void CFileReferenceHelper::setReferencePath(
MString fileName)
 
    {
        
        
        int idx = fileName.
rindex(
'/');
 
        if (idx == -1)
        if (idx != -1)
        {
        }
    }
    MString CFileReferenceHelper::findFile(
const char* fileName)
 const 
    {
        struct stat statBuf;
        const bool fullyQualified = name.index('/') == 0 || name.index('\\') == 0 || name.index(':') == 1;
        if (fullyQualified && stat(name.asChar(), &statBuf) != -1) 
        {
            return name;
        }
        
        char path[MAX_PATH];
        MString searchPaths = getSearchPaths();
 
        const char * psearchpath = searchPaths.
asChar();
 
        
        if(name.index('/') == 0 || name.index('\\') == 0)
            resolvedName = name.
substring(1, name.length() - 1);
        else
            resolvedName = name;
        while (psearchpath < searchPaths.
asChar() + searchPaths.
length())
 
        {
            const char * endpath = strchr(psearchpath,';');
            if (endpath)
            {
                strncpy(path,psearchpath, endpath - psearchpath);
                path[endpath - psearchpath] = '\0';
            }
            else
            {
                strcpy(path,psearchpath);
            }
            psearchpath += strlen(path)+1;
            bool fullPath = (path[0] == '/' || path[0] == '\\');
            if (strlen(path) > 2)
            {
                fullPath = fullPath ||
                    (path[1] == ':' &&
                    (path[2] == '/' ||
                    path[2] == '\\'));
            }
            
            if(path[strlen(path) - 1] != '/')
                file = 
MString(path) + 
"/" + resolvedName;
            else
                file = 
MString(path) + resolvedName;
        
            if (stat(file.
asChar(), &statBuf) != -1) 
 
            {
                return file;
            }
        }
    }
    MString CFileReferenceHelper::getSearchPaths()
 const 
    {
        
        
        {
            searchPaths += workspace;
            searchPaths += ";";
            searchPaths += workspace;
            searchPaths += "/renderData/shaders";
            {
                searchPaths += ";";
                searchPaths += workspace;
                searchPaths += shadersRelativePath;
            }
        }
        if(referencePath.length() > 0)
        {
            {
                searchPaths += ";";
            }
            searchPaths += referencePath;
        }
        static char * dx11ShaderRoot = getenv("DX11SHADER_ROOT");
        if (dx11ShaderRoot)
        {
            {
                searchPaths += ";";
            }
            searchPaths += dx11ShaderRoot;
            searchPaths += ";";
            searchPaths += dx11ShaderRoot;
            searchPaths += "/shaders";
        }
        searchPaths += ";";
        return searchPaths;
    }
    class CIncludeHelper: public ID3D10Include, public CFileReferenceHelper
    {
    public:
        STDMETHOD(Open)(D3D10_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
        {
            MString resolvedFileName = resolveFileName(pFileName);
 
            
            FILE* file = fopen(resolvedFileName.
asChar(), 
"rb");
            if(file == NULL)
            {
                return E_FAIL;
            }
            
            fseek(file, 0, SEEK_END);
            long size = ftell(file);
            fseek(file, 0, SEEK_SET);
            
            char *buffer = new char[size];
            fread(buffer, 1, size, file);
            fclose(file);
            
            *ppData = buffer;
            *pBytes = UINT(size);
            return S_OK;
        }
        STDMETHOD(Close)(LPCVOID pData)
        {
            char* pChar = (char*)pData;
            delete [] pChar;
            return S_OK;
        }
    };
    D3D10_SHADER_MACRO* getD3DMacros()
    {
        static D3D10_SHADER_MACRO macros[] = {  { "DIRECT3D_VERSION", "0xb00" },
                                                { "_MAYA_", "1"},                   
                                                { "MAYA_DX11", "1"},
                                                { NULL, NULL } };
        return macros;
    }
    unsigned int getShaderCompileFlags(bool useStrictness)
    {
        unsigned int flags = 0;
#ifdef _DEBUG
        
        flags |= D3DCOMPILE_DEBUG;
        flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
        if(useStrictness)
        {
            
            flags |= D3DCOMPILE_ENABLE_STRICTNESS;
        }
        else
        {
            
            flags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
        }
        return flags;
    }
    bool effectHasHullShader(ID3DX11Effect* effect)
    {
        if(effect)
        {
            D3DX11_EFFECT_DESC effectDesc;
            effect->GetDesc(&effectDesc);
            for(unsigned int i = 0; i < effectDesc.Techniques; ++i)
            {
                ID3DX11EffectTechnique* technique = effect->GetTechniqueByIndex(i);
                if(technique && technique->IsValid())
                {
                    D3DX11_TECHNIQUE_DESC techniqueDesc;
                    technique->GetDesc(&techniqueDesc);
                    for(unsigned int j = 0;j < techniqueDesc.Passes;++j)
                    {
                        ID3DX11EffectPass* pass = technique->GetPassByIndex(j); 
                        if(pass && pass->IsValid())
                        {
                            D3DX11_PASS_SHADER_DESC shaderDesc;
                            HRESULT hr = pass->GetHullShaderDesc(&shaderDesc);
                            if(hr == S_OK && shaderDesc.pShaderVariable && shaderDesc.pShaderVariable->IsValid())
                            {
                                ID3D11HullShader* pHullShader = NULL;
                                shaderDesc.pShaderVariable->GetHullShader(shaderDesc.ShaderIndex,&pHullShader);
                                if(pHullShader)
                                {
                                    
                                    pHullShader->Release();
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
    bool isValidEffectFile(
const MString& fileName, 
bool& isCompiled)
 
    {
        if(idx > 0)
        {
        }
        isCompiled = (extension == "fxo");
        return (extension == "fx" || extension == "fxo");
    }
    void pushError(
const MString& fileName, 
MString &errorLog, ID3DBlob* error)
 
    {
        char* pMessage = (error && error->GetBufferSize() > 0) ? (char*) error->GetBufferPointer() : NULL;
        MString msg = dx11ShaderStrings::getString( dx11ShaderStrings::kErrorEffectCompile, args );
 
        errorLog += msg;
    }
    void pushError(
MString &errorLog, ID3DBlob* error)
 
    {
        char* pMessage = (error && error->GetBufferSize() > 0) ? (char*) error->GetBufferPointer() : NULL;
        MString msg = dx11ShaderStrings::getString( dx11ShaderStrings::kErrorEffectBuffer, args );
 
        errorLog += msg;
    }
    time_t fileTimeStamp(
const MString& fileName)
    {
        struct stat statBuf;
        if( stat(fileName.
asChar(), &statBuf) != 0 )
 
            return 0;
        return statBuf.st_mtime;
    }
    struct EffectKey
    {
        ID3D11Device* device;
        time_t timeStamp;
    };
    bool operator< (const EffectKey& lhs, const EffectKey& rhs)
    {
        return (lhs.device <  rhs.device) ||
               (lhs.device == rhs.device && ( (lhs.timeStamp <  rhs.timeStamp) ||
                                              (lhs.timeStamp == rhs.timeStamp && strcmp(lhs.fileName.asChar(), rhs.fileName.asChar()) < 0) ) );
    }
    struct MStringSorter {
        {
        }
    };
    class EffectCollection
    {
    public:
        ID3DX11Effect* acquire(dx11ShaderNode* node, ID3D11Device* device, 
const MString& fileName);
        ID3DX11Effect* acquire(dx11ShaderNode* node, ID3D11Device* device, 
const MString& fileName, ID3DX11Effect* reference, ID3DX11Effect* source = NULL);
        void release(dx11ShaderNode* node, ID3DX11Effect *effect, 
const MString& fileName);
 
        void getNodesUsingEffect(
const MString& fileName, ShaderNodeList &nodes) 
const;
 
        ID3DX11Effect* getReferenceEffectAndFileName(ID3DX11Effect *effect, 
MString& fileName) 
const;
    private:
        typedef std::map< EffectKey, ID3DX11Effect* > Key2ReferenceEffectMap;
        Key2ReferenceEffectMap key2ReferenceEffectMap;
        typedef std::pair< EffectKey, unsigned int > EffectKeyCountPair;
        typedef std::map< ID3DX11Effect*, EffectKeyCountPair > ReferenceCountMap;
        ReferenceCountMap referenceCountMap;
        typedef std::map< ID3DX11Effect*, ID3DX11Effect* > Clone2ReferenceMap;
        Clone2ReferenceMap clone2ReferenceMap;
        
        
        
        
        typedef std::set< dx11ShaderNode* > NodeSet;
        typedef std::map< MString, NodeSet, MStringSorter > Path2NodesMap;
        Path2NodesMap path2NodesMap;
    };
    ID3DX11Effect* EffectCollection::acquire(dx11ShaderNode* node, ID3D11Device* device, 
const MString& fileName)
    {
        ID3DX11Effect* effect = NULL;
        EffectKey key = { device, fileName, fileTimeStamp(fileName) } ;
        
        Key2ReferenceEffectMap::const_iterator it = key2ReferenceEffectMap.find(key);
        if(it != key2ReferenceEffectMap.end())
        {
            ID3DX11Effect* reference = it->second;
            effect = acquire(node, device, fileName, reference);
        }
        return effect;
    }
    ID3DX11Effect* EffectCollection::acquire(dx11ShaderNode* node, ID3D11Device* device, 
const MString& fileName, ID3DX11Effect* reference, ID3DX11Effect* source )
    {
        
        path2NodesMap[fileName].insert(node);
        if( reference == NULL )
            return NULL;
        if( source == NULL)
            source = reference;
        
        EffectKey key = { device, fileName, fileTimeStamp(fileName) } ;
        {
            Key2ReferenceEffectMap::const_iterator it = key2ReferenceEffectMap.find(key);
            if(it == key2ReferenceEffectMap.end()) {
                key2ReferenceEffectMap.insert( std::make_pair(key, reference) );
            }
        }
        
        ID3DX11Effect* effect = NULL;
        HRESULT hr = source->CloneEffect(0, &effect);
        if( FAILED( hr ) || effect == NULL )
            return NULL;
        
        
        {
            ReferenceCountMap::iterator it = referenceCountMap.find(reference);
            if(it == referenceCountMap.end())
            {
                
                referenceCountMap.insert( std::make_pair(reference, std::make_pair(key, 1) ) );
            }
            else
            {
                
                ++(it->second.second);
            }
        }
        
        clone2ReferenceMap.insert( std::make_pair(effect, reference) );
        return effect;
    }
    void EffectCollection::release(dx11ShaderNode* node, ID3DX11Effect *effect, 
const MString& fileName)
 
    {
        if (effect)
        {
            Clone2ReferenceMap::iterator it = clone2ReferenceMap.find(effect);
            if(it != clone2ReferenceMap.end())
            {
                ID3DX11Effect* reference = it->second;
                ReferenceCountMap::iterator it2 = referenceCountMap.find(reference);
                if(it2 != referenceCountMap.end())
                {
                    
                    if(it2->second.second == 1)
                    {
                        EffectKey &key = it2->second.first;
                        key2ReferenceEffectMap.erase(key);
                        referenceCountMap.erase(it2);
                        reference->Release();
                    }
                    else
                    {
                        --(it2->second.second);
                    }
                }
                clone2ReferenceMap.erase(it);
            }
            effect->Release();
        }
        
        path2NodesMap[fileName].erase(node);
        
        if (path2NodesMap[fileName].empty())
            path2NodesMap.erase(fileName);
    }
    ID3DX11Effect* EffectCollection::getReferenceEffectAndFileName(ID3DX11Effect *effect, 
MString& fileName)
 const    {
        ID3DX11Effect* reference = NULL;
        Clone2ReferenceMap::const_iterator it = clone2ReferenceMap.find(effect);
        if(it != clone2ReferenceMap.end())
        {
            reference = it->second;
            Key2ReferenceEffectMap::const_iterator it2 = key2ReferenceEffectMap.begin();
            Key2ReferenceEffectMap::const_iterator it2End = key2ReferenceEffectMap.end();
            for(; it2 != it2End; ++it2)
            {
                if(it2->second == reference)
                {
                    fileName = it2->first.fileName;
                    break;
                }
            }
        }
        return reference;
    }
    void EffectCollection::getNodesUsingEffect(
const MString& fileName, ShaderNodeList &nodes)
 const 
    {
        Path2NodesMap::const_iterator itNodeSet = path2NodesMap.find(fileName);
        if (itNodeSet != path2NodesMap.end())
        {
            const NodeSet& nodeSet = itNodeSet->second;
            for (NodeSet::const_iterator itNode = nodeSet.begin(); itNode != nodeSet.end(); ++itNode)
            {
                nodes.push_back(*itNode);
            }
        }
    }
    static EffectCollection gEffectCollection;
    class CompiledEffectCache {
        
    public:
        CompiledEffectCache();
        ~CompiledEffectCache();
        static CompiledEffectCache* get();
        ID3DX11Effect* find( ID3D11Device* device, 
const MString& fileName );
        void add(ID3D11Device* device, 
const MString& fileName, ID3DX11Effect* effect );
 
    private:
        struct CacheData {
            CacheData(ID3D11Device* device, 
const MString& fileName, ID3DX11Effect* effect, 
int firstAccess);
            ~CacheData();
            ID3D11Device* mDevice;
            time_t mTimeStamp;
            ID3DX11Effect* mEffect;
            int mLastAccess;
        private:
            CacheData(const CacheData&);
            const CacheData& operator=(const CacheData&);
        };
        std::list<CacheData*> mCached;
        int mAccessClock;
        static const size_t kCacheSize = 8;
        MCallbackId mExitCallback;
        MCallbackId mFileNewCallback;
        static void flushCache( void *data);
        static CompiledEffectCache* sCachePtr;
    };
    CompiledEffectCache::CacheData::CacheData(ID3D11Device* device, 
const MString& fileName, ID3DX11Effect* effect, 
int firstAccess)
        : mDevice(device)
        , mFileName(fileName)
        , mEffect(NULL)
        , mLastAccess(firstAccess)
    {
        if (effect)
            effect->CloneEffect(0, &mEffect);
        mTimeStamp = fileTimeStamp(fileName);
    }
    CompiledEffectCache::CacheData::~CacheData()
    {
        if (mEffect)
            mEffect->Release();
    }
    CompiledEffectCache::CompiledEffectCache() : mAccessClock(0) {
    }
    CompiledEffectCache::~CompiledEffectCache()
    {
        std::list<CacheData*>::iterator itCache = mCached.begin();
        for ( ; itCache != mCached.end(); ++itCache )
        {
            delete *itCache;
        }
    }
    void CompiledEffectCache::flushCache( void *data)
    {
        delete sCachePtr;
        sCachePtr = NULL;
    }
    CompiledEffectCache* CompiledEffectCache::get()
    {
        if (!sCachePtr)
            sCachePtr = new CompiledEffectCache();
        return sCachePtr;
    }
    CompiledEffectCache* CompiledEffectCache::sCachePtr = NULL;
    ID3DX11Effect* CompiledEffectCache::find( ID3D11Device* device, 
const MString& fileName )
    {
        ID3DX11Effect* effect = NULL;
        
        std::list<CacheData*>::iterator itCache = mCached.begin();
        for ( ; itCache != mCached.end(); ++itCache )
        {
            CompiledEffectCache::CacheData *cacheItem(*itCache);
            if ( cacheItem->mDevice == device &&
                 cacheItem->mFileName == fileName &&
                 cacheItem->mTimeStamp == fileTimeStamp(fileName) ) 
            {
                cacheItem->mLastAccess = ++mAccessClock;
                cacheItem->mEffect->CloneEffect(0, &effect);
                break;
            }
        }
        return effect;
    }
    void CompiledEffectCache::add(ID3D11Device* device, 
const MString& fileName, ID3DX11Effect* effect )
 
    {
        if (mCached.size() > kCacheSize)
        {
            std::list<CacheData*>::iterator itCache = mCached.begin();
            std::list<CacheData*>::iterator oldestItem = itCache;
            itCache++;
            for ( ; itCache != mCached.end(); ++itCache )
            {
                if ( (*itCache)->mLastAccess < (*oldestItem)->mLastAccess )
                    oldestItem = itCache;
            }
            CacheData* oldData(*oldestItem);
            mCached.erase(oldestItem);
            delete oldData;
        }
        CacheData* newData(new CacheData(device, fileName, effect, ++mAccessClock));
        if (newData->mEffect)
            mCached.push_back( newData );
        else
            delete newData;
    }
}
void CDX11EffectCompileHelper::releaseEffect(dx11ShaderNode* node, ID3DX11Effect* effect, 
const MString& fileName)
 
{
    MString resolvedFileName = CDX11EffectCompileHelper::resolveShaderFileName(fileName);
 
    gEffectCollection.release(node, effect, resolvedFileName);
}
MString CDX11EffectCompileHelper::resolveShaderFileName(
const MString& fileName, 
bool* fileExists)
 
{
    MString resolvedFileName = fileName;
 
    
    {
        CIncludeHelper includeHelper;
        resolvedFileName = includeHelper.resolveFileName(fileName.
asChar());
    }
    if( fileExists != NULL )
    {
    }
    return resolvedFileName;
}
ID3DX11Effect* CDX11EffectCompileHelper::build(dx11ShaderNode* node, ID3D11Device* device, 
const MString& fileName, 
MString &errorLog, 
bool useStrictness)
{
    bool fileExits = false;
    MString resolvedFileName = CDX11EffectCompileHelper::resolveShaderFileName(fileName, &fileExits);
 
    if(fileExits == false)
    {
        MString msg = dx11ShaderStrings::getString( dx11ShaderStrings::kErrorFileNotFound, resolvedFileName );
 
        errorLog += msg;
        return NULL;
    }
    bool compiledEffect = false;
    if( isValidEffectFile(resolvedFileName, compiledEffect) == false )
    {
        MString msg = dx11ShaderStrings::getString( dx11ShaderStrings::kErrorInvalidEffectFile, resolvedFileName );
 
        errorLog += msg;
        return NULL;
    }
    
    ID3DX11Effect *effect = gEffectCollection.acquire(node, device, resolvedFileName);
    if( effect == NULL ) {
        effect = CompiledEffectCache::get()->find(device, resolvedFileName);
        if( effect == NULL ) {
            {
                args.
append(resolvedFileName);
                MString msg = dx11ShaderStrings::getString( dx11ShaderStrings::kErrorAbsolutePathNotFound, args );
 
                errorLog += msg;
            }
            CIncludeHelper includeHelper;
            includeHelper.setReferencePath(resolvedFileName);
            ID3DBlob *shader = NULL;
            ID3DBlob *error = NULL;
            HRESULT hr = S_FALSE;
            if( compiledEffect )
            {
                FILE* file = fopen(resolvedFileName.
asChar(), 
"rb");
                if(file)
                {
                    
                    fseek(file, 0, SEEK_END);
                    long size = ftell(file);
                    fseek(file, 0, SEEK_SET);
                    
                    hr = D3DCreateBlob(size, &shader);
                    if( SUCCEEDED( hr ) ) 
                    {
                        fread(shader->GetBufferPointer(), 1, size, file);
                    }
                    fclose(file);
                }
            }
            else
            {
                unsigned int compileFlags = getShaderCompileFlags(useStrictness);
                D3D10_SHADER_MACRO* macros = getD3DMacros();
#if _MSC_VER < 1700
                hr = D3DX11CompileFromFile(resolvedFileName.
asChar(), macros, &includeHelper, NULL, 
"fx_5_0", compileFlags, 0, NULL, &shader, &error, NULL);
#else
                hr = D3DCompileFromFile(resolvedFileName.
asWChar(), macros, &includeHelper, NULL, 
"fx_5_0", compileFlags, 0, &shader, &error);
#endif
            }
            if( FAILED( hr ) || shader == NULL )
            {
                pushError(fileName, errorLog, error);
            }
            else if( shader )
            {
                hr = D3DX11CreateEffectFromMemory(shader->GetBufferPointer(), shader->GetBufferSize(), 0, device, &effect);
                if( FAILED( hr ) || effect == NULL )
                {
                    pushError(fileName, errorLog, error);
                }
            }
            if( shader ) {
                shader->Release();
            }
            if( compiledEffect == false && useStrictness == false && effect != NULL && effectHasHullShader(effect) ) {
                
                
                
                effect->Release();
                effect = CDX11EffectCompileHelper::build(node, device, fileName, errorLog, true );
                
                return effect;
            }
            
            
            CompiledEffectCache::get()->add(device, resolvedFileName, effect);
        }  
        
        
        effect = gEffectCollection.acquire(node, device, resolvedFileName, effect);
    } 
    return effect;
}
ID3DX11Effect* CDX11EffectCompileHelper::build(dx11ShaderNode* node, ID3D11Device* device, 
const MString& fileName, ID3DX11Effect* effectSource, 
MString &errorLog)
{
    MString resolvedFileName = CDX11EffectCompileHelper::resolveShaderFileName(fileName);
 
    ID3DX11Effect *effect = NULL;
    
    
    ID3DX11Effect *reference = gEffectCollection.getReferenceEffectAndFileName(effectSource, referenceResolvedFileName);
    if(reference != NULL && resolvedFileName == referenceResolvedFileName)
    {
        
        effect = gEffectCollection.acquire(node, device, resolvedFileName, reference, effectSource);
    }
    return effect;
}
ID3DX11Effect* CDX11EffectCompileHelper::build(dx11ShaderNode* node, ID3D11Device* device, 
const void* buffer, 
unsigned int dataSize, 
MString &errorLog, 
bool useStrictness)
{
    unsigned int compileFlags = getShaderCompileFlags(useStrictness);
    D3D10_SHADER_MACRO* macros = getD3DMacros();
    CIncludeHelper includeHelper;
    ID3DX11Effect *effect = NULL;
    ID3DBlob *shader = NULL;
    ID3DBlob *error = NULL;
    HRESULT hr = S_FALSE;
#if _MSC_VER < 1700
    hr = D3DX11CompileFromMemory((char*)buffer, dataSize, NULL, macros, &includeHelper, "", "fx_5_0", compileFlags, 0, NULL, &shader, &error, NULL);
#else
    hr = D3DCompile((char*)buffer, dataSize, NULL, macros, &includeHelper, "", "fx_5_0", compileFlags, 0, &shader, &error);
#endif
    if( FAILED( hr ) || shader == NULL )
    {
        pushError(errorLog, error);
    }
    else if( shader )
    {
        hr = D3DX11CreateEffectFromMemory(shader->GetBufferPointer(), shader->GetBufferSize(), 0, device, &effect);
        if( FAILED( hr ) || effect == NULL )
        {
            pushError(errorLog, error);
        }
    }
    if( shader ) {
        shader->Release();
    }
    if( useStrictness == false && effect != NULL && effectHasHullShader(effect) ) {
        
        
        
        effect->Release();
        effect = CDX11EffectCompileHelper::build(node, device, buffer, dataSize, errorLog, true );
    }
    return effect;
}
void CDX11EffectCompileHelper::getNodesUsingEffect(
const MString& fileName, ShaderNodeList &nodes)
 
{
    MString resolvedFileName = CDX11EffectCompileHelper::resolveShaderFileName(fileName);
 
    gEffectCollection.getNodesUsingEffect(resolvedFileName, nodes);
}