summaryrefslogtreecommitdiffstats
path: root/source/slang/compiler.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-07-13 12:10:08 -0700
committerTim Foley <tfoley@nvidia.com>2017-07-13 13:00:38 -0700
commit6d7be3694fbaae525b2f4463630c35bed487cd5b (patch)
treea9bac151f79bba23df11c90d5906a3009dad29bd /source/slang/compiler.cpp
parent4bc59f896c9df970ec27a57c397977fc4721d3cd (diff)
Add support for dumping intermediates for debugging.
Calling: spSetDumpIntermedites(compileRequest, true); will set up a mode where Slang tries to dump every intermediate HLSL, GLSL, DXBC, SPIR-V, etc. file it generates. If SPIR-V or DXBC is requested then we also dump assembly of those. Right now the files are all named as `slang-<counter>.<ext>`, and get dropped in whatever the working directory is, but I'm open to ideas on how to improve that. Note: this change introduces a new binary interface to `glslang`, so pulling it requires an updated `glslang.dll`.
Diffstat (limited to 'source/slang/compiler.cpp')
-rw-r--r--source/slang/compiler.cpp213
1 files changed, 181 insertions, 32 deletions
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp
index 4c3885ebf..96fccced1 100644
--- a/source/slang/compiler.cpp
+++ b/source/slang/compiler.cpp
@@ -26,6 +26,10 @@
#include <d3dcompiler.h>
#endif
+#ifdef _MSC_VER
+#pragma warning(disable: 4996)
+#endif
+
#ifdef CreateDirectory
#undef CreateDirectory
#endif
@@ -78,8 +82,6 @@ namespace Slang
return Profile::Unknown;
}
-
-
//
String emitHLSLForEntryPoint(
@@ -209,6 +211,7 @@ namespace Slang
}
auto hlslCode = emitHLSLForEntryPoint(entryPoint);
+ maybeDumpIntermediate(entryPoint->compileRequest, hlslCode.Buffer(), CodeGenTarget::HLSL);
ID3DBlob* codeBlob;
ID3DBlob* diagnosticsBlob;
@@ -270,8 +273,10 @@ namespace Slang
}
#endif
- String EmitDXBytecodeAssemblyForEntryPoint(
- EntryPointRequest* entryPoint)
+ String dissassembleDXBC(
+ CompileRequest*,
+ void const* data,
+ size_t size)
{
static pD3DDisassemble D3DDisassemble_ = nullptr;
if (!D3DDisassemble_)
@@ -283,16 +288,15 @@ namespace Slang
assert(D3DDisassemble_);
}
- List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(entryPoint);
- if (!dxbc.Count())
+ if (!data || !size)
{
return String();
}
ID3DBlob* codeBlob;
HRESULT hr = D3DDisassemble_(
- &dxbc[0],
- dxbc.Count(),
+ data,
+ size,
0,
nullptr,
&codeBlob);
@@ -312,6 +316,21 @@ namespace Slang
return result;
}
+ String EmitDXBytecodeAssemblyForEntryPoint(
+ EntryPointRequest* entryPoint)
+ {
+
+ List<uint8_t> dxbc = EmitDXBytecodeForEntryPoint(entryPoint);
+ if (!dxbc.Count())
+ {
+ return String();
+ }
+
+ String result = dissassembleDXBC(entryPoint->compileRequest, dxbc.Buffer(), dxbc.Count());
+
+ return result;
+ }
+
#if 0
String EmitDXBytecodeAssembly(
ExtraContext& context)
@@ -332,7 +351,6 @@ namespace Slang
}
#endif
-
HMODULE getGLSLCompilerDLL()
{
// TODO(tfoley): let user specify version of glslang DLL to use.
@@ -342,11 +360,11 @@ namespace Slang
return glslCompiler;
}
- int invokeGLSLCompilerForEntryPoint(
- EntryPointRequest* entryPoint,
+
+ int invokeGLSLCompiler(
+ CompileRequest* slangCompileRequest,
glslang_CompileRequest& request)
{
- String rawGLSL = emitGLSLForEntryPoint(entryPoint);
static glslang_CompileFunc glslang_compile = nullptr;
if (!glslang_compile)
@@ -364,10 +382,6 @@ namespace Slang
(*(String*)userData).append((char const*)data, (char const*)data + size);
};
- request.sourcePath = "slang";
- request.sourceText = rawGLSL.begin();
- request.slangStage = (SlangStage)entryPoint->profile.GetStage();
-
request.diagnosticFunc = diagnosticOutputFunc;
request.diagnosticUserData = &diagnosticOutput;
@@ -375,7 +389,7 @@ namespace Slang
if (err)
{
- entryPoint->compileRequest->mSink.diagnoseRaw(
+ slangCompileRequest->mSink.diagnoseRaw(
Severity::Error,
diagnosticOutput.begin());
return err;
@@ -384,54 +398,79 @@ namespace Slang
return 0;
}
-
- List<uint8_t> emitSPIRVForEntryPoint(
- EntryPointRequest* entryPoint)
+ String dissassembleSPIRV(
+ CompileRequest* slangRequest,
+ void const* data,
+ size_t size)
{
- List<uint8_t> output;
+ String output;
auto outputFunc = [](void const* data, size_t size, void* userData)
{
- ((List<uint8_t>*)userData)->AddRange((uint8_t*)data, size);
+ (*(String*)userData).append((char const*)data, (char const*)data + size);
};
glslang_CompileRequest request;
+ request.action = GLSLANG_ACTION_DISSASSEMBLE_SPIRV;
+
+ request.inputBegin = data;
+ request.inputEnd = (char*)data + size;
+
request.outputFunc = outputFunc;
request.outputUserData = &output;
- request.disassembleResult = false;
- int err = invokeGLSLCompilerForEntryPoint(entryPoint, request);
+ int err = invokeGLSLCompiler(slangRequest, request);
if (err)
{
- return List<uint8_t>();
+ String();
}
return output;
}
- String emitSPIRVAssemblyForEntryPoint(
+ List<uint8_t> emitSPIRVForEntryPoint(
EntryPointRequest* entryPoint)
{
- String output;
+ String rawGLSL = emitGLSLForEntryPoint(entryPoint);
+ maybeDumpIntermediate(entryPoint->compileRequest, rawGLSL.Buffer(), CodeGenTarget::GLSL);
+
+ List<uint8_t> output;
auto outputFunc = [](void const* data, size_t size, void* userData)
{
- (*(String*)userData).append((char const*)data, (char const*)data + size);
+ ((List<uint8_t>*)userData)->AddRange((uint8_t*)data, size);
};
glslang_CompileRequest request;
+ request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV;
+ request.sourcePath = "slang";
+ request.slangStage = (SlangStage)entryPoint->profile.GetStage();
+
+ request.inputBegin = rawGLSL.begin();
+ request.inputEnd = rawGLSL.end();
+
request.outputFunc = outputFunc;
request.outputUserData = &output;
- request.disassembleResult = true;
- int err = invokeGLSLCompilerForEntryPoint(entryPoint, request);
+ int err = invokeGLSLCompiler(entryPoint->compileRequest, request);
if (err)
{
- String();
+ return List<uint8_t>();
}
return output;
}
+
+ String emitSPIRVAssemblyForEntryPoint(
+ EntryPointRequest* entryPoint)
+ {
+ List<uint8_t> spirv = emitSPIRVForEntryPoint(entryPoint);
+ if (spirv.Count() == 0)
+ return String();
+
+ String result = dissassembleSPIRV(entryPoint->compileRequest, spirv.begin(), spirv.Count());
+ return result;
+ }
#endif
#if 0
@@ -461,12 +500,14 @@ namespace Slang
CompileResult result;
auto compileRequest = entryPoint->compileRequest;
+ auto target = compileRequest->Target;
- switch (compileRequest->Target)
+ switch (target)
{
case CodeGenTarget::HLSL:
{
String code = emitHLSLForEntryPoint(entryPoint);
+ maybeDumpIntermediate(compileRequest, code.Buffer(), target);
result = CompileResult(code);
}
break;
@@ -474,6 +515,7 @@ namespace Slang
case CodeGenTarget::GLSL:
{
String code = emitGLSLForEntryPoint(entryPoint);
+ maybeDumpIntermediate(compileRequest, code.Buffer(), target);
result = CompileResult(code);
}
break;
@@ -481,6 +523,7 @@ namespace Slang
case CodeGenTarget::DXBytecode:
{
List<uint8_t> code = EmitDXBytecodeForEntryPoint(entryPoint);
+ maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
result = CompileResult(code);
}
break;
@@ -488,6 +531,7 @@ namespace Slang
case CodeGenTarget::DXBytecodeAssembly:
{
String code = EmitDXBytecodeAssemblyForEntryPoint(entryPoint);
+ maybeDumpIntermediate(compileRequest, code.Buffer(), target);
result = CompileResult(code);
}
break;
@@ -495,6 +539,7 @@ namespace Slang
case CodeGenTarget::SPIRV:
{
List<uint8_t> code = emitSPIRVForEntryPoint(entryPoint);
+ maybeDumpIntermediate(compileRequest, code.Buffer(), code.Count(), target);
result = CompileResult(code);
}
break;
@@ -502,6 +547,7 @@ namespace Slang
case CodeGenTarget::SPIRVAssembly:
{
String code = emitSPIRVAssemblyForEntryPoint(entryPoint);
+ maybeDumpIntermediate(compileRequest, code.Buffer(), target);
result = CompileResult(code);
}
break;
@@ -604,4 +650,107 @@ namespace Slang
}
+ // Debug logic for dumping intermediate outputs
+
+ //
+
+ void dumpIntermediate(
+ CompileRequest*,
+ void const* data,
+ size_t size,
+ char const* ext,
+ bool isBinary)
+ {
+ static int counter = 0;
+ int id = counter++;
+
+ String path;
+ path.append("slang-");
+ path.append(id);
+ path.append(ext);
+
+ FILE* file = fopen(path.Buffer(), isBinary ? "wb" : "w");
+ if (!file) return;
+
+ fwrite(data, size, 1, file);
+ fclose(file);
+ }
+
+ void dumpIntermediateText(
+ CompileRequest* compileRequest,
+ void const* data,
+ size_t size,
+ char const* ext)
+ {
+ dumpIntermediate(compileRequest, data, size, ext, false);
+ }
+
+ void dumpIntermediateBinary(
+ CompileRequest* compileRequest,
+ void const* data,
+ size_t size,
+ char const* ext)
+ {
+ dumpIntermediate(compileRequest, data, size, ext, true);
+ }
+
+ void maybeDumpIntermediate(
+ CompileRequest* compileRequest,
+ void const* data,
+ size_t size,
+ CodeGenTarget target)
+ {
+ if (!compileRequest->shouldDumpIntermediates)
+ return;
+
+ switch (target)
+ {
+ default:
+ break;
+
+ case CodeGenTarget::HLSL:
+ dumpIntermediateText(compileRequest, data, size, ".hlsl");
+ break;
+
+ case CodeGenTarget::GLSL:
+ dumpIntermediateText(compileRequest, data, size, ".glsl");
+ break;
+
+ case CodeGenTarget::SPIRVAssembly:
+ dumpIntermediateText(compileRequest, data, size, ".spv.asm");
+ break;
+
+ case CodeGenTarget::DXBytecodeAssembly:
+ dumpIntermediateText(compileRequest, data, size, ".dxbc.asm");
+ break;
+
+ case CodeGenTarget::SPIRV:
+ dumpIntermediateBinary(compileRequest, data, size, ".spv");
+ {
+ String spirvAssembly = dissassembleSPIRV(compileRequest, data, size);
+ dumpIntermediateText(compileRequest, spirvAssembly.begin(), spirvAssembly.Length(), ".spv.asm");
+ }
+ break;
+
+ case CodeGenTarget::DXBytecode:
+ dumpIntermediateBinary(compileRequest, data, size, ".dxbc");
+ {
+ String dxbcAssembly = dissassembleDXBC(compileRequest, data, size);
+ dumpIntermediateText(compileRequest, dxbcAssembly.begin(), dxbcAssembly.Length(), ".dxbc.asm");
+ }
+ break;
+ }
+ }
+
+ void maybeDumpIntermediate(
+ CompileRequest* compileRequest,
+ char const* text,
+ CodeGenTarget target)
+ {
+ if (!compileRequest->shouldDumpIntermediates)
+ return;
+
+ maybeDumpIntermediate(compileRequest, text, strlen(text), target);
+ }
+
}