0
\$\begingroup\$

i'm reading the "3D game programming with directx 11 " book (Frank Luna) and i'm struggling becouse he uses the old D3DX11CompileFromFile() method, which can't be used anymore. So i searched on internet how to solve this problem and i found out i have to use D3DCompileFromFile instead, which is a little bit different, but not totally. Now this is my script

DWORD flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_DEBUG;
    ID3DBlob*compiledShader = nullptr;
    ID3DBlob*compilationMsgs = nullptr;

    HRESULT hr = D3DCompileFromFile(L"FX/effects.fx", 0, 0, 0, "fx_5_0", flags, 0,  &compiledShader, &compilationMsgs);

    if (FAILED(hr))
        MessageBox(0, L"Failed D3DCompileFromFile", 0, 0);  //THIS POPS OUT

I did this by myself and than i started copying things from internet to make it work. Could the problem be in entryPoint=0? What do i have to put there? This is the effect.fx file

cbuffer cbPerObject 
{ 
    float4x4 gWorldViewProj; 
}; 
struct VertexIn 
{   float3 Pos : POSITION; 
    float4 Color : COLOR; 
}; 

struct VertexOut { 
    float4 PosH : SV_POSITION; 
    float4 Color : COLOR; 
}; 
VertexOut VS(VertexIn vin) {
    VertexOut vout; // Transform to homogeneous clip space. 
    vout.PosH = mul(float4(vin.Pos, 1.0f), gWorldViewProj); // Just pass vertex color into the pixel shader. 
    vout.Color = vin.Color; return vout; } 

float4 PS(VertexOut pin) : SV_Target { 
    return pin.Color; 
}
technique11 ColorTech { 
    pass P0 { 
        SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetPixelShader( CompileShader( ps_5_0, PS() ) );
    } 
}

float3 iPosL; // local space 
float3 gEyePosW; // world space 
float3 normalV; // view space 
float4 posH; // homogeneous clip spac

Thanks

\$\endgroup\$
5
  • \$\begingroup\$ The compilationMsgs blob will contain error messages from the compile. You should print it out and see. Also, look at what the actual HRESULT is returning, not just whether or not it is FAILED. That will tell you something. \$\endgroup\$
    – user1430
    Jan 24, 2017 at 16:47
  • \$\begingroup\$ Josh Petrie♦ So the HRESULT gives me "impossible to find the specified path" so i guess it doesn't know where the FX/effects.fx is placed \$\endgroup\$
    – Emanuele
    Jan 24, 2017 at 17:17
  • \$\begingroup\$ Ok i solved it, thanks a lot, just needed to put the effects.fx in another folder. Now the HRESULT contains this. warning X4717: Effects deprecated for D3DCompiler_47 Is this a problem? \$\endgroup\$
    – Emanuele
    Jan 24, 2017 at 17:22
  • \$\begingroup\$ It means Effects are deprecated. They'll still work on that version, but if you move forward they will stop working; you'll have to write shaders directly, not .fx files. \$\endgroup\$
    – user1430
    Jan 24, 2017 at 17:25
  • \$\begingroup\$ See Is Effects 11 deprecated? for a fuller discussion of the Effects 11 and fx profile deprecation story. \$\endgroup\$ Jan 24, 2017 at 18:06

1 Answer 1

1
\$\begingroup\$

Here's a robust replacement for D3DX11CompileFromFile using the D3DCompile DLL instead:

The D3D_COMPILER_VERSION < 46 case is if you are using the legacy DirectX SDK, otherwise you should be using the Windows 8.x SDK or Windows 10 SDK version.

#if D3D_COMPILER_VERSION < 46
namespace
{

struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };

typedef public std::unique_ptr<void, handle_closer> ScopedHandle;

inline HANDLE safe_handle( HANDLE h ) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }

class CIncludeHandler : public ID3DInclude
    // Not as robust as D3D_COMPILE_STANDARD_FILE_INCLUDE, but it works in most cases
{
private:
    static const unsigned int MAX_INCLUDES = 9;

    struct sInclude
    {
        HANDLE         hFile;
        HANDLE         hFileMap;
        LARGE_INTEGER  FileSize;
        void           *pMapData;
    };

    struct sInclude     m_includeFiles[MAX_INCLUDES];
    size_t              m_nIncludes;
    bool                m_reset;
    WCHAR               m_workingPath[MAX_PATH];

public:
    CIncludeHandler() : m_nIncludes(0), m_reset(false)
    {
        if ( !GetCurrentDirectoryW( MAX_PATH, m_workingPath ) )
            *m_workingPath = 0;

        for ( size_t i = 0; i < MAX_INCLUDES; ++i )
        {
            m_includeFiles[i].hFile = INVALID_HANDLE_VALUE;
            m_includeFiles[i].hFileMap = INVALID_HANDLE_VALUE;
            m_includeFiles[i].pMapData = nullptr;
        }
    }
    virtual ~CIncludeHandler()
    {
        for ( size_t i = 0; i < m_nIncludes; ++i )
        {
            UnmapViewOfFile( m_includeFiles[i].pMapData );

            if ( m_includeFiles[i].hFileMap != INVALID_HANDLE_VALUE)
                CloseHandle( m_includeFiles[i].hFileMap );

            if ( m_includeFiles[i].hFile != INVALID_HANDLE_VALUE)
                CloseHandle( m_includeFiles[i].hFile );
        }

        m_nIncludes = 0;

        if ( m_reset && *m_workingPath )
        {
            SetCurrentDirectoryW( m_workingPath );
        }
    }

    STDMETHOD(Open( D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes ) )
    {
        UNREFERENCED_PARAMETER(IncludeType);
        UNREFERENCED_PARAMETER(pParentData);

        size_t incIndex = m_nIncludes+1;

        // Make sure we have enough room for this include file
        if ( incIndex >= MAX_INCLUDES )
            return E_FAIL;

        // try to open the file
        m_includeFiles[incIndex].hFile  = CreateFileA( pFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr );
        if( INVALID_HANDLE_VALUE == m_includeFiles[incIndex].hFile )
        {
            return E_FAIL;
        }

        // Get the file size
        GetFileSizeEx( m_includeFiles[incIndex].hFile, &m_includeFiles[incIndex].FileSize );

        // Use Memory Mapped File I/O for the header data
        m_includeFiles[incIndex].hFileMap = CreateFileMappingA( m_includeFiles[incIndex].hFile, nullptr, PAGE_READONLY, m_includeFiles[incIndex].FileSize.HighPart, m_includeFiles[incIndex].FileSize.LowPart, pFileName);
        if( !m_includeFiles[incIndex].hFileMap )
        {
            if (m_includeFiles[incIndex].hFile != INVALID_HANDLE_VALUE)
                CloseHandle( m_includeFiles[incIndex].hFile );
            return E_FAIL;
        }

        // Create Map view
        *ppData = MapViewOfFile( m_includeFiles[incIndex].hFileMap, FILE_MAP_READ, 0, 0, 0 );
        *pBytes = m_includeFiles[incIndex].FileSize.LowPart;

        // Success - Increment the include file count
        m_nIncludes = incIndex;

        return S_OK;
    }

    STDMETHOD(Close( LPCVOID pData ))
    {
        UNREFERENCED_PARAMETER(pData);
        // Defer Closure until the container destructor 
        return S_OK;
    }

    void SetCWD( LPCWSTR pFileName )
    {
        WCHAR filePath[MAX_PATH];
        wcscpy_s( filePath, MAX_PATH, pFileName );

        WCHAR *strLastSlash = wcsrchr( filePath, L'\\' );
        if( strLastSlash )
        {
            // Chop the exe name from the exe path
            *strLastSlash = 0;
            m_reset = true;
            SetCurrentDirectoryW( filePath );
        }
    }
};

}; // namespace

#endif

HRESULT WINAPI DXUTCompileFromFile( LPCWSTR pFileName,
                                    const D3D_SHADER_MACRO* pDefines,
                                    LPCSTR pEntrypoint, LPCSTR pTarget,
                                    UINT Flags1, UINT Flags2,
                                    ID3DBlob** ppCode )
{
    HRESULT hr;
    WCHAR str[MAX_PATH];
    V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, pFileName ) );

#if defined( DEBUG ) || defined( _DEBUG )
    // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
    // Setting this flag improves the shader debugging experience, but still allows 
    // the shaders to be optimized and to run exactly the way they will run in 
    // the release configuration of this program.
    Flags1 |= D3DCOMPILE_DEBUG;
#endif

    ID3DBlob* pErrorBlob = nullptr;

#if D3D_COMPILER_VERSION >= 46

    hr = D3DCompileFromFile( str, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE,
                             pEntrypoint, pTarget, Flags1, Flags2,
                             ppCode, &pErrorBlob );

#else

    ScopedHandle hFile( safe_handle( CreateFileW( str, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ) ) );

    if ( !hFile )
        return HRESULT_FROM_WIN32( GetLastError() );

    LARGE_INTEGER FileSize = { 0 };

#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    FILE_STANDARD_INFO fileInfo;
    if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo) ) )
    {
        return HRESULT_FROM_WIN32( GetLastError() );
    }
    FileSize = fileInfo.EndOfFile;
#else
    GetFileSizeEx( hFile.get(), &FileSize );
#endif

    if (!FileSize.LowPart || FileSize.HighPart > 0)
        return E_FAIL;

    std::unique_ptr<char[]> fxData;
    fxData.reset( new (std::nothrow) char[ FileSize.LowPart ] );
    if ( !fxData )
        return E_OUTOFMEMORY;

    DWORD BytesRead = 0;
    if ( !ReadFile( hFile.get(), fxData.get(), FileSize.LowPart, &BytesRead, nullptr ) )
        return HRESULT_FROM_WIN32( GetLastError() );

    if (BytesRead < FileSize.LowPart)
        return E_FAIL;

    char pSrcName[MAX_PATH];
    int result = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, str, -1, pSrcName, MAX_PATH, nullptr, FALSE );
    if ( !result )
        return E_FAIL;

    const CHAR* pstrName = strrchr( pSrcName, '\\' );
    if (!pstrName)
    {
        pstrName = pSrcName;
    }
    else
    {
        pstrName++;
    }

    std::unique_ptr<CIncludeHandler> includes( new (std::nothrow) CIncludeHandler );
    if ( !includes )
        return E_OUTOFMEMORY;

    includes->SetCWD( str );

    hr = D3DCompile( fxData.get(), BytesRead, pstrName, pDefines, includes.get(),
                     pEntrypoint, pTarget, Flags1, Flags2,
                     ppCode, &pErrorBlob );

#endif

#pragma warning( suppress : 6102 )
    if ( pErrorBlob )
    {
        OutputDebugStringA( reinterpret_cast<const char*>( pErrorBlob->GetBufferPointer() ) );
        pErrorBlob->Release();
    }

    return hr;
}

This code is from the GitHub open source version of DXUT for Direct3D 11.

See HLSL, FXC, and D3DCompile

As you are using the legacy Effects for Direct3D 11 system constructs, you should use the GitHub version of Effects11 in which case you might as well just use D3DX11CompileEffectFromFile that version provides:

HRESULT hr = D3DX11CompileEffectFromFile(
    L"FX/effects.fx",
    nullptr, nullptr,
    flags, 0, device, &effect, &compilationMsgs);

if (FAILED(hr))
    // error

Since it has no include handler use of #include in your fx file will fail. The best solution is to use the default include handler that is part of D3DCompiler #46 or later:

HRESULT hr = D3DX11CompileEffectFromFile(
    L"FX/effects.fx",
    nullptr,  D3D_COMPILE_STANDARD_FILE_INCLUDE,
    flags, 0, device, &effect, &compilationMsgs);

if (FAILED(hr))
    // error

See D3DX11CompileEffectFromFile

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .