blob: d74d0033545e585e2ebf1eb675d689cc836d3600 [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),
Tibor den Ouden97049c62014-10-06 21:39:16 +020032 mD3DCompileFunc(NULL),
33 mD3DDisassembleFunc(NULL)
Geoff Langdad5ed32014-02-10 12:59:17 -050034{
35}
36
37HLSLCompiler::~HLSLCompiler()
38{
39 release();
40}
41
42bool HLSLCompiler::initialize()
43{
44 TRACE_EVENT0("gpu", "initializeCompiler");
Cooper Partin88d3b8c2014-10-08 10:41:56 -070045#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
Geoff Langdad5ed32014-02-10 12:59:17 -050046#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
47 // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
Jamie Madill07d49ef2014-07-25 11:52:38 -040048 static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
Geoff Langdad5ed32014-02-10 12:59:17 -050049
50 for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
51 {
Jamie Madill07d49ef2014-07-25 11:52:38 -040052 if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule))
Geoff Langdad5ed32014-02-10 12:59:17 -050053 {
54 break;
55 }
56 }
57#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
58
59 if (!mD3DCompilerModule)
60 {
61 // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
62 mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
63 }
64
65 if (!mD3DCompilerModule)
66 {
67 ERR("No D3D compiler module found - aborting!\n");
68 return false;
69 }
70
Geoff Lang3935e512014-09-23 13:15:19 -040071 mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
Geoff Langdad5ed32014-02-10 12:59:17 -050072 ASSERT(mD3DCompileFunc);
Cooper Partin88d3b8c2014-10-08 10:41:56 -070073#else
74 // D3D Shader compiler is linked already into this module, so the export
75 // can be directly assigned.
76 mD3DCompilerModule = NULL;
77 mD3DCompileFunc = reinterpret_cast<pD3DCompile>(D3DCompile);
78#endif
Geoff Langdad5ed32014-02-10 12:59:17 -050079
Tibor den Ouden97049c62014-10-06 21:39:16 +020080 mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(GetProcAddress(mD3DCompilerModule, "D3DDisassemble"));
81 ASSERT(mD3DDisassembleFunc);
82
Geoff Langdad5ed32014-02-10 12:59:17 -050083 return mD3DCompileFunc != NULL;
84}
85
86void HLSLCompiler::release()
87{
88 if (mD3DCompilerModule)
89 {
90 FreeLibrary(mD3DCompilerModule);
91 mD3DCompilerModule = NULL;
92 mD3DCompileFunc = NULL;
Tibor den Ouden97049c62014-10-06 21:39:16 +020093 mD3DDisassembleFunc = NULL;
Geoff Langdad5ed32014-02-10 12:59:17 -050094 }
95}
96
Geoff Langb543aff2014-09-30 14:52:54 -040097gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile,
Nicolas Capens5e0c80a2014-10-10 10:11:54 -040098 const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
Tibor den Ouden97049c62014-10-06 21:39:16 +020099 ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const
Geoff Langdad5ed32014-02-10 12:59:17 -0500100{
Cooper Partin88d3b8c2014-10-08 10:41:56 -0700101#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
102 ASSERT(mD3DCompilerModule);
103#endif
104 ASSERT(mD3DCompileFunc);
Geoff Langdad5ed32014-02-10 12:59:17 -0500105
Geoff Langf7ed7052014-09-23 13:39:31 -0400106 if (gl::perfActive())
107 {
108 std::string sourcePath = getTempPath();
109 std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str());
110 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
111 }
112
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400113 const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : NULL;
114
Geoff Lang3935e512014-09-23 13:15:19 -0400115 for (size_t i = 0; i < configs.size(); ++i)
Geoff Langdad5ed32014-02-10 12:59:17 -0500116 {
117 ID3DBlob *errorMessage = NULL;
118 ID3DBlob *binary = NULL;
119
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400120 HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, NULL, "main", profile.c_str(),
Geoff Lang3935e512014-09-23 13:15:19 -0400121 configs[i].flags, 0, &binary, &errorMessage);
Nicolas Capens93faad92014-05-10 12:14:13 -0400122
Geoff Langdad5ed32014-02-10 12:59:17 -0500123 if (errorMessage)
124 {
Tibor den Ouden97049c62014-10-06 21:39:16 +0200125 std::string message = reinterpret_cast<const char*>(errorMessage->GetBufferPointer());
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400126 SafeRelease(errorMessage);
Geoff Langdad5ed32014-02-10 12:59:17 -0500127
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400128 infoLog.appendSanitized(message.c_str());
Tibor den Ouden97049c62014-10-06 21:39:16 +0200129 TRACE("\n%s", hlsl.c_str());
130 TRACE("\n%s", message.c_str());
Geoff Langdad5ed32014-02-10 12:59:17 -0500131
Nicolas Capens5e0c80a2014-10-10 10:11:54 -0400132 if (message.find("error X3531:") != std::string::npos) // "can't unroll loops marked with loop attribute"
133 {
134 macros = NULL; // Disable [loop] and [flatten]
135
136 // Retry without changing compiler flags
137 i--;
138 continue;
139 }
Geoff Langdad5ed32014-02-10 12:59:17 -0500140 }
141
142 if (SUCCEEDED(result))
143 {
Geoff Langb543aff2014-09-30 14:52:54 -0400144 *outCompiledBlob = binary;
Tibor den Ouden97049c62014-10-06 21:39:16 +0200145
146#ifdef ANGLE_GENERATE_SHADER_DEBUG_INFO
147 (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n";
148 (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n";
149 (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n";
150 (*outDebugInfo) += "\n" + disassembleBinary(binary) + "\n// ASSEMBLY END\n";
151#endif
152
Geoff Langb543aff2014-09-30 14:52:54 -0400153 return gl::Error(GL_NO_ERROR);
Geoff Langdad5ed32014-02-10 12:59:17 -0500154 }
155 else
156 {
157 if (result == E_OUTOFMEMORY)
158 {
Geoff Langb543aff2014-09-30 14:52:54 -0400159 *outCompiledBlob = NULL;
160 return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
Geoff Langdad5ed32014-02-10 12:59:17 -0500161 }
162
Geoff Lang3935e512014-09-23 13:15:19 -0400163 infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str());
Jamie Madill2c976a42014-08-04 11:37:53 -0400164
Geoff Lang3935e512014-09-23 13:15:19 -0400165 if (i + 1 < configs.size())
Geoff Langdad5ed32014-02-10 12:59:17 -0500166 {
Geoff Lang3935e512014-09-23 13:15:19 -0400167 infoLog.append(" Retrying with %s.\n", configs[i + 1].name.c_str());
Geoff Langdad5ed32014-02-10 12:59:17 -0500168 }
169 }
170 }
171
Geoff Langb543aff2014-09-30 14:52:54 -0400172 // None of the configurations succeeded in compiling this shader but the compiler is still intact
173 *outCompiledBlob = NULL;
174 return gl::Error(GL_NO_ERROR);
Geoff Langdad5ed32014-02-10 12:59:17 -0500175}
176
Tibor den Ouden97049c62014-10-06 21:39:16 +0200177std::string HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary) const
178{
179 // Retrieve disassembly
180 UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING;
181 ID3DBlob *disassembly = NULL;
182 pD3DDisassemble disassembleFunc = reinterpret_cast<pD3DDisassemble>(mD3DDisassembleFunc);
183 LPCVOID buffer = shaderBinary->GetBufferPointer();
184 SIZE_T bufSize = shaderBinary->GetBufferSize();
185 HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly);
186
187 std::string asmSrc;
188 if (SUCCEEDED(result))
189 {
190 asmSrc = reinterpret_cast<const char*>(disassembly->GetBufferPointer());
191 }
192
193 SafeRelease(disassembly);
194
195 return asmSrc;
196}
197
Geoff Langdad5ed32014-02-10 12:59:17 -0500198}