From 7c0ebeee95cb72f086a261ed6c55f33571bb62db Mon Sep 17 00:00:00 2001 From: Kai-Hwa Yao Date: Mon, 10 Jul 2017 13:50:16 -0700 Subject: Refactored compile output to work with raw data instead of Strings --- source/slang/compiler.cpp | 100 +++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 64 deletions(-) (limited to 'source/slang/compiler.cpp') diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index 2f6204eb2..3225aafb2 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -197,6 +197,7 @@ namespace Slang 0, &codeBlob, &diagnosticsBlob); + List data; if (codeBlob) { @@ -243,7 +244,7 @@ namespace Slang } #endif - String EmitDXBytecodeAssemblyForEntryPoint( + List EmitDXBytecodeAssemblyForEntryPoint( EntryPointRequest* entryPoint) { static pD3DDisassemble D3DDisassemble_ = nullptr; @@ -259,7 +260,7 @@ namespace Slang List dxbc = EmitDXBytecodeForEntryPoint(entryPoint); if (!dxbc.Count()) { - return ""; + return List(); } ID3DBlob* codeBlob; @@ -270,10 +271,10 @@ namespace Slang nullptr, &codeBlob); - String result; + List result; if (codeBlob) { - result = String((char const*) codeBlob->GetBufferPointer()); + result.AddRange((uint8_t*)codeBlob->GetBufferPointer(), codeBlob->GetBufferSize()); codeBlob->Release(); } if (FAILED(hr)) @@ -314,8 +315,9 @@ namespace Slang } - String emitSPIRVAssemblyForEntryPoint( - EntryPointRequest* entryPoint) + List emitSPIRVForEntryPoint( + EntryPointRequest* entryPoint, + bool spirvAssembly) { String rawGLSL = emitGLSLForEntryPoint(entryPoint); @@ -329,34 +331,32 @@ namespace Slang assert(glslang_compile); } - StringBuilder diagnosticBuilder; - StringBuilder outputBuilder; + List diagnosticOutput; + List output; - auto outputFunc = [](char const* text, void* userData) + auto outputFunc = [](void const* data, size_t size, void* userData) { - *(StringBuilder*)userData << text; + ((List*)userData)->AddRange((uint8_t*)data, size); }; glslang_CompileRequest request; request.sourcePath = "slang"; request.sourceText = rawGLSL.begin(); - request.slangStage = (SlangStage) entryPoint->profile.GetStage(); + request.slangStage = (SlangStage)entryPoint->profile.GetStage(); + request.disassembleResult = spirvAssembly; request.diagnosticFunc = outputFunc; - request.diagnosticUserData = &diagnosticBuilder; + request.diagnosticUserData = &diagnosticOutput; request.outputFunc = outputFunc; - request.outputUserData = &outputBuilder; + request.outputUserData = &output; int err = glslang_compile(&request); - String diagnostics = diagnosticBuilder.ProduceString(); - String output = outputBuilder.ProduceString(); - - if(err) + if (err) { - OutputDebugStringA(diagnostics.Buffer()); - fprintf(stderr, "%s", diagnostics.Buffer()); + OutputDebugStringA((char const *)diagnosticOutput.Buffer()); + fwrite(diagnosticOutput.Buffer(), 1, diagnosticOutput.Count(), stderr); exit(1); } @@ -397,67 +397,42 @@ namespace Slang case CodeGenTarget::HLSL: { String code = emitHLSLForEntryPoint(entryPoint); - result.outputSource = code; + result.outputSource.AddRange((uint8_t*)code.Buffer(), code.Length()); } break; case CodeGenTarget::GLSL: { String code = emitGLSLForEntryPoint(entryPoint); - result.outputSource = code; + result.outputSource.AddRange((uint8_t*)code.Buffer(), code.Length()); } break; case CodeGenTarget::DXBytecode: { - auto code = EmitDXBytecodeForEntryPoint(entryPoint); - - // TODO(tfoley): Need to figure out an appropriate interface - // for returning binary code, in addition to source. -#if 0 - if (context.compileResult) - { - StringBuilder sb; - sb.Append((char*) code.begin(), code.Count()); - - String codeString = sb.ProduceString(); - result.outputSource = codeString; - } - else -#endif - { - int col = 0; - for(auto ii : code) - { - if(col != 0) fputs(" ", stdout); - fprintf(stdout, "%02X", ii); - col++; - if(col == 8) - { - fputs("\n", stdout); - col = 0; - } - } - if(col != 0) - { - fputs("\n", stdout); - } - } - return result; + List code = EmitDXBytecodeForEntryPoint(entryPoint); + result.outputSource.AddRange(code.Buffer(), code.Count()); } break; case CodeGenTarget::DXBytecodeAssembly: { - String code = EmitDXBytecodeAssemblyForEntryPoint(entryPoint); - result.outputSource = code; + List code = EmitDXBytecodeAssemblyForEntryPoint(entryPoint); + result.outputSource.AddRange(code.Buffer(), code.Count()); + } + break; + + case CodeGenTarget::SPIRV: + { + List code = emitSPIRVForEntryPoint(entryPoint, false); + result.outputSource.AddRange(code.Buffer(), code.Count()); } break; case CodeGenTarget::SPIRVAssembly: { - String code = emitSPIRVAssemblyForEntryPoint(entryPoint); - result.outputSource = code; + List code = emitSPIRVForEntryPoint(entryPoint, true); + result.outputSource.AddRange(code.Buffer(), code.Count()); } break; @@ -493,14 +468,11 @@ namespace Slang // The result for the translation unit will just be the concatenation // of the results for each entry point. This doesn't actually make // much sense, but it is good enough for now. - // - // TODO: Replace this with a packaged JSON and/or binary format. - StringBuilder sb; for (auto& entryPoint : translationUnit->entryPoints) { - sb << entryPoint->result.outputSource; + UInt size = entryPoint->result.outputSource.Count(); + result.outputSource.AddRange(entryPoint->result.outputSource.Buffer(), size); } - result.outputSource = sb.ProduceString(); return result; } -- cgit v1.2.3 From 22c7a4de0c3810fcfc1099843e42b315c366a7c5 Mon Sep 17 00:00:00 2001 From: Kai-Hwa Yao Date: Mon, 10 Jul 2017 17:44:14 -0700 Subject: Removed spGetTranslationUnitCode; Unified EntryPointResult/TranslationUnitResult, added helper functionality; Ensure null termination when printing raw data --- slang.h | 9 ------- source/slang/compiler.cpp | 68 ++++++++++++++++++++++++++++++++++------------- source/slang/compiler.h | 33 +++++++++++++++-------- source/slang/slang.cpp | 22 ++++----------- tools/glslang/glslang.cpp | 3 ++- 5 files changed, 78 insertions(+), 57 deletions(-) (limited to 'source/slang/compiler.cpp') diff --git a/slang.h b/slang.h index 56d962490..f5da206ce 100644 --- a/slang.h +++ b/slang.h @@ -322,15 +322,6 @@ extern "C" SlangCompileRequest* request, int translationUnitIndex); - /** Get the output bytecode associated with a specific translation unit. - - The lifetime of the output pointer is the same as `request`. - */ - SLANG_API void const* spGetTranslationUnitCode( - SlangCompileRequest* request, - int translationUnitIndex, - size_t* outSize); - /** Get the output source code associated with a specific entry point. The lifetime of the output pointer is the same as `request`. diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index 3225aafb2..c04c2150d 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -33,6 +33,33 @@ namespace Slang { + // CompileResult + + void CompileResult::append(CompileResult const& result) + { + // Find which to append to + ResultFormat appendTo = ResultFormat::None; + + if (format == ResultFormat::None) + { + format = result.format; + appendTo = result.format; + } + else if (format == result.format) + { + appendTo = format; + } + + if (appendTo == ResultFormat::Text) + { + outputString.append(result.outputString.Buffer()); + } + else if (appendTo == ResultFormat::Binary) + { + outputBinary.AddRange(result.outputBinary.Buffer(), result.outputBinary.Count()); + } + } + // EntryPointRequest TranslationUnitRequest* EntryPointRequest::getTranslationUnit() @@ -355,8 +382,11 @@ namespace Slang if (err) { - OutputDebugStringA((char const *)diagnosticOutput.Buffer()); - fwrite(diagnosticOutput.Buffer(), 1, diagnosticOutput.Count(), stderr); + char const* diagnosticString = (char const*)diagnosticOutput.Buffer(); + String debugStr(diagnosticString, diagnosticString + diagnosticOutput.Count()); + + OutputDebugStringA(debugStr.Buffer()); + fprintf(stderr, "%s", debugStr.Buffer()); exit(1); } @@ -385,10 +415,10 @@ namespace Slang #endif // Do emit logic for a single entry point - EntryPointResult emitEntryPoint( + CompileResult emitEntryPoint( EntryPointRequest* entryPoint) { - EntryPointResult result; + CompileResult result; auto compileRequest = entryPoint->compileRequest; @@ -397,42 +427,42 @@ namespace Slang case CodeGenTarget::HLSL: { String code = emitHLSLForEntryPoint(entryPoint); - result.outputSource.AddRange((uint8_t*)code.Buffer(), code.Length()); + result = CompileResult(code); } break; case CodeGenTarget::GLSL: { String code = emitGLSLForEntryPoint(entryPoint); - result.outputSource.AddRange((uint8_t*)code.Buffer(), code.Length()); + result = CompileResult(code); } break; case CodeGenTarget::DXBytecode: { List code = EmitDXBytecodeForEntryPoint(entryPoint); - result.outputSource.AddRange(code.Buffer(), code.Count()); + result = CompileResult(code); } break; case CodeGenTarget::DXBytecodeAssembly: { List code = EmitDXBytecodeAssemblyForEntryPoint(entryPoint); - result.outputSource.AddRange(code.Buffer(), code.Count()); + result = CompileResult(code); } break; case CodeGenTarget::SPIRV: { List code = emitSPIRVForEntryPoint(entryPoint, false); - result.outputSource.AddRange(code.Buffer(), code.Count()); + result = CompileResult(code); } break; case CodeGenTarget::SPIRVAssembly: { List code = emitSPIRVForEntryPoint(entryPoint, true); - result.outputSource.AddRange(code.Buffer(), code.Count()); + result = CompileResult(code); } break; @@ -449,18 +479,16 @@ namespace Slang } return result; - - } - TranslationUnitResult emitTranslationUnitEntryPoints( + CompileResult emitTranslationUnitEntryPoints( TranslationUnitRequest* translationUnit) { - TranslationUnitResult result; + CompileResult result; for (auto& entryPoint : translationUnit->entryPoints) { - EntryPointResult entryPointResult = emitEntryPoint(entryPoint.Ptr()); + CompileResult entryPointResult = emitEntryPoint(entryPoint.Ptr()); entryPoint->result = entryPointResult; } @@ -468,10 +496,11 @@ namespace Slang // The result for the translation unit will just be the concatenation // of the results for each entry point. This doesn't actually make // much sense, but it is good enough for now. + // + // TODO: Replace this with a packaged JSON and/or binary format. for (auto& entryPoint : translationUnit->entryPoints) { - UInt size = entryPoint->result.outputSource.Count(); - result.outputSource.AddRange(entryPoint->result.outputSource.Buffer(), size); + result.append(entryPoint->result); } return result; @@ -479,7 +508,7 @@ namespace Slang // Do emit logic for an entire translation unit, which might // have zero or more entry points - TranslationUnitResult emitTranslationUnit( + CompileResult emitTranslationUnit( TranslationUnitRequest* translationUnit) { return emitTranslationUnitEntryPoints(translationUnit); @@ -518,8 +547,9 @@ namespace Slang // For most targets, we will do things per-translation-unit for( auto translationUnit : compileRequest->translationUnits ) { - TranslationUnitResult translationUnitResult = emitTranslationUnit(translationUnit.Ptr()); + CompileResult translationUnitResult = emitTranslationUnit(translationUnit.Ptr()); translationUnit->result = translationUnitResult; } } + } diff --git a/source/slang/compiler.h b/source/slang/compiler.h index 3763faec7..2b440ad85 100644 --- a/source/slang/compiler.h +++ b/source/slang/compiler.h @@ -48,13 +48,30 @@ namespace Slang ReflectionJSON = SLANG_REFLECTION_JSON, }; + enum class ResultFormat + { + None, + Text, + Binary + }; + class CompileRequest; class TranslationUnitRequest; - // Result of compiling an entry point - struct EntryPointResult + // Result of compiling an entry point. + // Should only ever be string OR binary. + class CompileResult { - List outputSource; + public: + CompileResult() = default; + CompileResult(String const& str) : format(ResultFormat::Text), outputString(str) {} + CompileResult(List const& buffer) : format(ResultFormat::Binary), outputBinary(buffer) {} + + void append(CompileResult const& result); + + ResultFormat format = ResultFormat::None; + String outputString; + List outputBinary; }; // Describes an entry point that we've been requested to compile @@ -80,7 +97,7 @@ namespace Slang // The resulting output for the enry point // // TODO: low-level code generation should be a distinct step - EntryPointResult result; + CompileResult result; // The translation unit that this entry point came from TranslationUnitRequest* getTranslationUnit(); @@ -105,12 +122,6 @@ namespace Slang String content; }; - // Result of compiling a translation unit - struct TranslationUnitResult - { - List outputSource; - }; - // A single translation unit requested to be compiled. // class TranslationUnitRequest : public RefObject @@ -144,7 +155,7 @@ namespace Slang // The resulting output for the translation unit // // TODO: low-level code generation should be a distinct step - TranslationUnitResult result; + CompileResult result; }; // A directory to be searched when looking for files (e.g., `#include`) diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 7f30e91c2..0561f30a9 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -862,18 +862,7 @@ SLANG_API char const* spGetTranslationUnitSource( int translationUnitIndex) { auto req = REQ(request); - return (char const*)req->translationUnits[translationUnitIndex]->result.outputSource.Buffer(); -} - -SLANG_API void const* spGetTranslationUnitCode( - SlangCompileRequest* request, - int translationUnitIndex, - size_t* outSize) -{ - auto req = REQ(request); - Slang::TranslationUnitResult& result = req->translationUnits[translationUnitIndex]->result; - *outSize = (size_t)result.outputSource.Count(); - return result.outputSource.Buffer(); + return req->translationUnits[translationUnitIndex]->result.outputString.Buffer(); } SLANG_API char const* spGetEntryPointSource( @@ -881,8 +870,7 @@ SLANG_API char const* spGetEntryPointSource( int entryPointIndex) { auto req = REQ(request); - return (char const*)req->entryPoints[entryPointIndex]->result.outputSource.Buffer(); - + return req->entryPoints[entryPointIndex]->result.outputString.Buffer(); } SLANG_API void const* spGetEntryPointCode( @@ -891,9 +879,9 @@ SLANG_API void const* spGetEntryPointCode( size_t* outSize) { auto req = REQ(request); - Slang::EntryPointResult& result = req->entryPoints[entryPointIndex]->result; - *outSize = (size_t)result.outputSource.Count(); - return result.outputSource.Buffer(); + Slang::CompileResult& result = req->entryPoints[entryPointIndex]->result; + if(outSize) *outSize = result.outputBinary.Count(); + return result.outputBinary.Buffer(); } // Reflection API diff --git a/tools/glslang/glslang.cpp b/tools/glslang/glslang.cpp index e396528d9..f07937b97 100644 --- a/tools/glslang/glslang.cpp +++ b/tools/glslang/glslang.cpp @@ -66,7 +66,8 @@ static void dump( fwrite(data, 1, size, fallbackStream); // also output it for debug purposes - OutputDebugStringA((char const*)data); + std::string str((char const*)data, size); + OutputDebugStringA(str.c_str()); } } -- cgit v1.2.3