1#include "precompiled.h"
2#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
3#include "libGLESv2/Program.h"
4#include "libGLESv2/main.h"
5
6#include "common/utilities.h"
7
8#include "third_party/trace_event/trace_event.h"
9
10namespace rx
11{
12
13HLSLCompiler::HLSLCompiler()
14    : mD3DCompilerModule(NULL),
15      mD3DCompileFunc(NULL)
16{
17}
18
19HLSLCompiler::~HLSLCompiler()
20{
21    release();
22}
23
24bool HLSLCompiler::initialize()
25{
26    TRACE_EVENT0("gpu", "initializeCompiler");
27#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
28    // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
29    static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
30
31    for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
32    {
33        if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3DCompilerModule))
34        {
35            break;
36        }
37    }
38#endif  // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
39
40    if (!mD3DCompilerModule)
41    {
42        // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
43        mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
44    }
45
46    if (!mD3DCompilerModule)
47    {
48        ERR("No D3D compiler module found - aborting!\n");
49        return false;
50    }
51
52    mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
53    ASSERT(mD3DCompileFunc);
54
55    return mD3DCompileFunc != NULL;
56}
57
58void HLSLCompiler::release()
59{
60    if (mD3DCompilerModule)
61    {
62        FreeLibrary(mD3DCompilerModule);
63        mD3DCompilerModule = NULL;
64        mD3DCompileFunc = NULL;
65    }
66}
67
68ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile,
69                                          const UINT optimizationFlags[], const char *flagNames[], int attempts) const
70{
71    ASSERT(mD3DCompilerModule && mD3DCompileFunc);
72
73    if (!hlsl)
74    {
75        return NULL;
76    }
77
78    pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc);
79    for (int i = 0; i < attempts; ++i)
80    {
81        ID3DBlob *errorMessage = NULL;
82        ID3DBlob *binary = NULL;
83
84        HRESULT result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, "main", profile, optimizationFlags[i], 0, &binary, &errorMessage);
85
86        if (errorMessage)
87        {
88            const char *message = (const char*)errorMessage->GetBufferPointer();
89
90            infoLog.appendSanitized(message);
91            TRACE("\n%s", hlsl);
92            TRACE("\n%s", message);
93
94            SafeRelease(errorMessage);
95        }
96
97        if (SUCCEEDED(result))
98        {
99            return (ShaderBlob*)binary;
100        }
101        else
102        {
103            if (result == E_OUTOFMEMORY)
104            {
105                return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL);
106            }
107
108            infoLog.append("Warning: D3D shader compilation failed with ");
109            infoLog.append(flagNames[i]);
110            infoLog.append(" flags.");
111            if (i + 1 < attempts)
112            {
113                infoLog.append(" Retrying with ");
114                infoLog.append(flagNames[i + 1]);
115                infoLog.append(".\n");
116            }
117        }
118    }
119
120    return NULL;
121}
122
123}
124