blob: 68ce104e9d70000409df45810f9817e3d3de52d5 [file] [log] [blame]
Jamie Madillea247592014-08-28 10:37:08 -04001//
2// Copyright 2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Geoff Langdad5ed32014-02-10 12:59:17 -05007#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
8#include "libGLESv2/Program.h"
9#include "libGLESv2/main.h"
10
11#include "common/utilities.h"
12
13#include "third_party/trace_event/trace_event.h"
14
15namespace rx
16{
17
Geoff Lang3935e512014-09-23 13:15:19 -040018CompileConfig::CompileConfig()
19 : flags(0),
20 name()
21{
22}
23
24CompileConfig::CompileConfig(UINT flags, const std::string &name)
25 : flags(flags),
26 name(name)
27{
28}
29
Geoff Langdad5ed32014-02-10 12:59:17 -050030HLSLCompiler::HLSLCompiler()
31 : mD3DCompilerModule(NULL),
32 mD3DCompileFunc(NULL)
33{
34}
35
36HLSLCompiler::~HLSLCompiler()
37{
38 release();
39}
40
41bool HLSLCompiler::initialize()
42{
43 TRACE_EVENT0("gpu", "initializeCompiler");
44#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
45 // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
Jamie Madill07d49ef2014-07-25 11:52:38 -040046 static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
Geoff Langdad5ed32014-02-10 12:59:17 -050047
48 for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
49 {
Jamie Madill07d49ef2014-07-25 11:52:38 -040050 if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule))
Geoff Langdad5ed32014-02-10 12:59:17 -050051 {
52 break;
53 }
54 }
55#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
56
57 if (!mD3DCompilerModule)
58 {
59 // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
60 mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
61 }
62
63 if (!mD3DCompilerModule)
64 {
65 ERR("No D3D compiler module found - aborting!\n");
66 return false;
67 }
68
Geoff Lang3935e512014-09-23 13:15:19 -040069 mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
Geoff Langdad5ed32014-02-10 12:59:17 -050070 ASSERT(mD3DCompileFunc);
71
72 return mD3DCompileFunc != NULL;
73}
74
75void HLSLCompiler::release()
76{
77 if (mD3DCompilerModule)
78 {
79 FreeLibrary(mD3DCompilerModule);
80 mD3DCompilerModule = NULL;
81 mD3DCompileFunc = NULL;
82 }
83}
84
Geoff Langb543aff2014-09-30 14:52:54 -040085gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
Nicolas Capens5e0c80a2014-10-10 10:11:54 -040086 const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
87 ID3DBlob **outCompiledBlob) const
Geoff Langdad5ed32014-02-10 12:59:17 -050088{
89 ASSERT(mD3DCompilerModule && mD3DCompileFunc);
90
Geoff Langf7ed7052014-09-23 13:39:31 -040091 if (gl::perfActive())
92 {
93 std::string sourcePath = getTempPath();
94 std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str());
95 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
96 }
97
Nicolas Capens5e0c80a2014-10-10 10:11:54 -040098 const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : NULL;
99
Geoff Lang3935e512014-09-23 13:15:19 -0400100 for (size_t i = 0; i < configs.size(); ++i)
Geoff Langdad5ed32014-02-10 12:59:17 -0500101 {
102 ID3DBlob *errorMessage = NULL;
103 ID3DBlob *binary = NULL;
104
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400105 HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, NULL, "main", profile.c_str(),
Geoff Lang3935e512014-09-23 13:15:19 -0400106 configs[i].flags, 0, &binary, &errorMessage);
Nicolas Capens93faad92014-05-10 12:14:13 -0400107
Geoff Langdad5ed32014-02-10 12:59:17 -0500108 if (errorMessage)
109 {
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400110 std::string message = (const char*)errorMessage->GetBufferPointer();
111 SafeRelease(errorMessage);
Geoff Langdad5ed32014-02-10 12:59:17 -0500112
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400113 infoLog.appendSanitized(message.c_str());
Geoff Langdad5ed32014-02-10 12:59:17 -0500114 TRACE("\n%s", hlsl);
115 TRACE("\n%s", message);
116
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400117 if (message.find("error X3531:") != std::string::npos) // "can't unroll loops marked with loop attribute"
118 {
119 macros = NULL; // Disable [loop] and [flatten]
120
121 // Retry without changing compiler flags
122 i--;
123 continue;
124 }
Geoff Langdad5ed32014-02-10 12:59:17 -0500125 }
126
127 if (SUCCEEDED(result))
128 {
Geoff Langb543aff2014-09-30 14:52:54 -0400129 *outCompiledBlob = binary;
130 return gl::Error(GL_NO_ERROR);
Geoff Langdad5ed32014-02-10 12:59:17 -0500131 }
132 else
133 {
134 if (result == E_OUTOFMEMORY)
135 {
Geoff Langb543aff2014-09-30 14:52:54 -0400136 *outCompiledBlob = NULL;
137 return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
Geoff Langdad5ed32014-02-10 12:59:17 -0500138 }
139
Geoff Lang3935e512014-09-23 13:15:19 -0400140 infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str());
Jamie Madill2c976a42014-08-04 11:37:53 -0400141
Geoff Lang3935e512014-09-23 13:15:19 -0400142 if (i + 1 < configs.size())
Geoff Langdad5ed32014-02-10 12:59:17 -0500143 {
Geoff Lang3935e512014-09-23 13:15:19 -0400144 infoLog.append(" Retrying with %s.\n", configs[i + 1].name.c_str());
Geoff Langdad5ed32014-02-10 12:59:17 -0500145 }
146 }
147 }
148
Geoff Langb543aff2014-09-30 14:52:54 -0400149 // None of the configurations succeeded in compiling this shader but the compiler is still intact
150 *outCompiledBlob = NULL;
151 return gl::Error(GL_NO_ERROR);
Geoff Langdad5ed32014-02-10 12:59:17 -0500152}
153
154}