123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856 |
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // CompilerTest.cpp //
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- // This file is distributed under the University of Illinois Open Source //
- // License. See LICENSE.TXT for details. //
- // //
- // Provides tests for the compiler API. //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- #ifndef UNICODE
- #define UNICODE
- #endif
- #include <memory>
- #include <vector>
- #include <string>
- #include <map>
- #include <cassert>
- #include <sstream>
- #include <algorithm>
- #include <cfloat>
- #include "dxc/DxilContainer/DxilContainer.h"
- #include "dxc/Support/WinIncludes.h"
- #include "dxc/dxcapi.h"
- #ifdef _WIN32
- #include <atlfile.h>
- #include "dia2.h"
- #endif
- #include "HLSLTestData.h"
- #include "HlslTestUtils.h"
- #include "DxcTestUtils.h"
- #include "llvm/Support/raw_os_ostream.h"
- #include "dxc/Support/Global.h"
- #include "dxc/Support/dxcapi.use.h"
- #include "dxc/Support/microcom.h"
- #include "dxc/Support/HLSLOptions.h"
- #include "dxc/Support/Unicode.h"
- #include <fstream>
- #include "llvm/Support/FileSystem.h"
- #include "llvm/Support/MSFileSystem.h"
- #include "llvm/Support/Path.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/ADT/StringSwitch.h"
- using namespace std;
- using namespace hlsl_test;
- // Aligned to SymTagEnum.
- const char *SymTagEnumText[] =
- {
- "Null", // SymTagNull
- "Exe", // SymTagExe
- "Compiland", // SymTagCompiland
- "CompilandDetails", // SymTagCompilandDetails
- "CompilandEnv", // SymTagCompilandEnv
- "Function", // SymTagFunction
- "Block", // SymTagBlock
- "Data", // SymTagData
- "Annotation", // SymTagAnnotation
- "Label", // SymTagLabel
- "PublicSymbol", // SymTagPublicSymbol
- "UDT", // SymTagUDT
- "Enum", // SymTagEnum
- "FunctionType", // SymTagFunctionType
- "PointerType", // SymTagPointerType
- "ArrayType", // SymTagArrayType
- "BaseType", // SymTagBaseType
- "Typedef", // SymTagTypedef
- "BaseClass", // SymTagBaseClass
- "Friend", // SymTagFriend
- "FunctionArgType", // SymTagFunctionArgType
- "FuncDebugStart", // SymTagFuncDebugStart
- "FuncDebugEnd", // SymTagFuncDebugEnd
- "UsingNamespace", // SymTagUsingNamespace
- "VTableShape", // SymTagVTableShape
- "VTable", // SymTagVTable
- "Custom", // SymTagCustom
- "Thunk", // SymTagThunk
- "CustomType", // SymTagCustomType
- "ManagedType", // SymTagManagedType
- "Dimension", // SymTagDimension
- "CallSite", // SymTagCallSite
- "InlineSite", // SymTagInlineSite
- "BaseInterface", // SymTagBaseInterface
- "VectorType", // SymTagVectorType
- "MatrixType", // SymTagMatrixType
- "HLSLType", // SymTagHLSLType
- "Caller", // SymTagCaller
- "Callee", // SymTagCallee
- "Export", // SymTagExport
- "HeapAllocationSite", // SymTagHeapAllocationSite
- "CoffGroup", // SymTagCoffGroup
- };
- // Aligned to LocationType.
- const char *LocationTypeText[] =
- {
- "Null",
- "Static",
- "TLS",
- "RegRel",
- "ThisRel",
- "Enregistered",
- "BitField",
- "Slot",
- "IlRel",
- "MetaData",
- "Constant",
- };
- // Aligned to DataKind.
- const char *DataKindText[] =
- {
- "Unknown",
- "Local",
- "StaticLocal",
- "Param",
- "ObjectPtr",
- "FileStatic",
- "Global",
- "Member",
- "StaticMember",
- "Constant",
- };
- // Aligned to UdtKind.
- const char *UdtKindText[] =
- {
- "Struct",
- "Class",
- "Union",
- "Interface",
- };
- class TestIncludeHandler : public IDxcIncludeHandler {
- DXC_MICROCOM_REF_FIELD(m_dwRef)
- public:
- DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef)
- dxc::DxcDllSupport &m_dllSupport;
- HRESULT m_defaultErrorCode = E_FAIL;
- TestIncludeHandler(dxc::DxcDllSupport &dllSupport) : m_dwRef(0), m_dllSupport(dllSupport), callIndex(0) { }
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject) override {
- return DoBasicQueryInterface<IDxcIncludeHandler>(this, iid, ppvObject);
- }
- struct LoadSourceCallInfo {
- std::wstring Filename; // Filename as written in #include statement
- LoadSourceCallInfo(LPCWSTR pFilename) :
- Filename(pFilename) { }
- };
- std::vector<LoadSourceCallInfo> CallInfos;
- std::wstring GetAllFileNames() const {
- std::wstringstream s;
- for (size_t i = 0; i < CallInfos.size(); ++i) {
- s << CallInfos[i].Filename << ';';
- }
- return s.str();
- }
- struct LoadSourceCallResult {
- HRESULT hr;
- std::string source;
- UINT32 codePage;
- LoadSourceCallResult() : hr(E_FAIL), codePage(0) { }
- LoadSourceCallResult(const char *pSource, UINT32 codePage = CP_UTF8) : hr(S_OK), source(pSource), codePage(codePage) { }
- };
- std::vector<LoadSourceCallResult> CallResults;
- size_t callIndex;
- HRESULT STDMETHODCALLTYPE LoadSource(
- _In_ LPCWSTR pFilename, // Filename as written in #include statement
- _COM_Outptr_ IDxcBlob **ppIncludeSource // Resultant source object for included file
- ) override {
- CallInfos.push_back(LoadSourceCallInfo(pFilename));
- *ppIncludeSource = nullptr;
- if (callIndex >= CallResults.size()) {
- return m_defaultErrorCode;
- }
- if (FAILED(CallResults[callIndex].hr)) {
- return CallResults[callIndex++].hr;
- }
- MultiByteStringToBlob(m_dllSupport, CallResults[callIndex].source,
- CallResults[callIndex].codePage, ppIncludeSource);
- return CallResults[callIndex++].hr;
- }
- };
- #ifdef _WIN32
- class CompilerTest {
- #else
- class CompilerTest : public ::testing::Test {
- #endif
- public:
- BEGIN_TEST_CLASS(CompilerTest)
- TEST_CLASS_PROPERTY(L"Parallel", L"true")
- TEST_METHOD_PROPERTY(L"Priority", L"0")
- END_TEST_CLASS()
- TEST_CLASS_SETUP(InitSupport);
- TEST_METHOD(CompileWhenDebugThenDIPresent)
- TEST_METHOD(CompileDebugLines)
- TEST_METHOD(CompileWhenDefinesThenApplied)
- TEST_METHOD(CompileWhenDefinesManyThenApplied)
- TEST_METHOD(CompileWhenEmptyThenFails)
- TEST_METHOD(CompileWhenIncorrectThenFails)
- TEST_METHOD(CompileWhenWorksThenDisassembleWorks)
- TEST_METHOD(CompileWhenDebugWorksThenStripDebug)
- TEST_METHOD(CompileWhenWorksThenAddRemovePrivate)
- TEST_METHOD(CompileThenAddCustomDebugName)
- TEST_METHOD(CompileWithRootSignatureThenStripRootSignature)
- TEST_METHOD(CompileWhenIncludeThenLoadInvoked)
- TEST_METHOD(CompileWhenIncludeThenLoadUsed)
- TEST_METHOD(CompileWhenIncludeAbsoluteThenLoadAbsolute)
- TEST_METHOD(CompileWhenIncludeLocalThenLoadRelative)
- TEST_METHOD(CompileWhenIncludeSystemThenLoadNotRelative)
- TEST_METHOD(CompileWhenIncludeSystemMissingThenLoadAttempt)
- TEST_METHOD(CompileWhenIncludeFlagsThenIncludeUsed)
- TEST_METHOD(CompileWhenIncludeMissingThenFail)
- TEST_METHOD(CompileWhenIncludeHasPathThenOK)
- TEST_METHOD(CompileWhenIncludeEmptyThenOK)
- TEST_METHOD(CompileWhenODumpThenPassConfig)
- TEST_METHOD(CompileWhenODumpThenOptimizerMatch)
- TEST_METHOD(CompileWhenVdThenProducesDxilContainer)
- #if _ITERATOR_DEBUG_LEVEL==0
- // CompileWhenNoMemThenOOM can properly detect leaks only when debug iterators are disabled
- TEST_METHOD(CompileWhenNoMemThenOOM)
- #endif
- TEST_METHOD(CompileWhenShaderModelMismatchAttributeThenFail)
- TEST_METHOD(CompileBadHlslThenFail)
- TEST_METHOD(CompileLegacyShaderModelThenFail)
- TEST_METHOD(CompileWhenRecursiveAlbeitStaticTermThenFail)
- TEST_METHOD(CompileWhenRecursiveThenFail)
- TEST_METHOD(CompileHlsl2015ThenFail)
- TEST_METHOD(CompileHlsl2016ThenOK)
- TEST_METHOD(CompileHlsl2017ThenOK)
- TEST_METHOD(CompileHlsl2018ThenOK)
- TEST_METHOD(CompileHlsl2019ThenFail)
- TEST_METHOD(DiaLoadBadBitcodeThenFail)
- TEST_METHOD(DiaLoadDebugThenOK)
- TEST_METHOD(DiaTableIndexThenOK)
- TEST_METHOD(CodeGenAttributeAtVertex)
- TEST_METHOD(CodeGenAttributeAtVertexNoOpt)
- TEST_METHOD(CodeGenBarycentrics)
- TEST_METHOD(CodeGenBarycentrics1)
- TEST_METHOD(CodeGenBarycentricsThreeSV)
- TEST_METHOD(CodeGenBitCast16Bits)
- TEST_METHOD(CodeGenCbuffer64Types)
- TEST_METHOD(CodeGenCbufferHalf)
- TEST_METHOD(CodeGenCbufferHalfStruct)
- TEST_METHOD(CodeGenCbufferInt16)
- TEST_METHOD(CodeGenCbufferInt16Struct)
- TEST_METHOD(CodeGenDataLayoutHalf)
- TEST_METHOD(CodeGenEnum3)
- TEST_METHOD(CodeGenFloatingPointEnvironment)
- TEST_METHOD(CodeGenFixedWidthTypes)
- TEST_METHOD(CodeGenFixedWidthTypes16Bit)
- TEST_METHOD(CodeGenFunctionAttribute)
- TEST_METHOD(CodeGenInclude)
- TEST_METHOD(CodeGenInt16Op)
- TEST_METHOD(CodeGenInt16OpBits)
- TEST_METHOD(CodeGenLibCsEntry)
- TEST_METHOD(CodeGenLibCsEntry2)
- TEST_METHOD(CodeGenLibCsEntry3)
- TEST_METHOD(CodeGenLibEntries)
- TEST_METHOD(CodeGenLibEntries2)
- TEST_METHOD(CodeGenLibNoAlias)
- TEST_METHOD(CodeGenLibResource)
- TEST_METHOD(CodeGenLibUnusedFunc)
- TEST_METHOD(CodeGenMultiUAVLoad2)
- TEST_METHOD(CodeGenMultiUAVLoad4)
- TEST_METHOD(CodeGenMultiUAVLoad5)
- TEST_METHOD(CodeGenMultiUAVLoad6)
- TEST_METHOD(CodeGenMultiUAVLoad7)
- TEST_METHOD(CodeGenRaw_Buf2)
- TEST_METHOD(CodeGenRaw_Buf4)
- TEST_METHOD(CodeGenRaw_Buf5)
- TEST_METHOD(CodeGenSignaturePackingByWidth)
- TEST_METHOD(CodeGenStruct_Buf2)
- TEST_METHOD(CodeGenStruct_Buf3)
- TEST_METHOD(CodeGenStruct_Buf4)
- TEST_METHOD(CodeGenStruct_Buf5)
- TEST_METHOD(CodeGenStruct_Buf6)
- TEST_METHOD(CodeGenStruct_Buf_New_Layout)
- TEST_METHOD(CodeGenUav_Typed_Load_Store3)
- TEST_METHOD(CodeGenUint64_2)
- TEST_METHOD(CodeGenLiterals_Exact_Precision_Mod)
- TEST_METHOD(CodeGenTypedBufferHalf)
- TEST_METHOD(CodeGenRootSigProfile)
- TEST_METHOD(CodeGenRootSigProfile2)
- TEST_METHOD(CodeGenRootSigProfile5)
- TEST_METHOD(PreprocessWhenValidThenOK)
- TEST_METHOD(PreprocessWhenExpandTokenPastingOperandThenAccept)
- TEST_METHOD(WhenSigMismatchPCFunctionThenFail)
- TEST_METHOD(CodeGenSamples)
- TEST_METHOD(ViewID)
- TEST_METHOD(SubobjectCodeGenErrors)
- TEST_METHOD(DebugInfo)
- TEST_METHOD(QuickTest)
- BEGIN_TEST_METHOD(ManualFileCheckTest)
- TEST_METHOD_PROPERTY(L"Ignore", L"true")
- END_TEST_METHOD()
- // Batch directories
- TEST_METHOD(CodeGenBatch)
- dxc::DxcDllSupport m_dllSupport;
- VersionSupportInfo m_ver;
- void CreateBlobPinned(_In_bytecount_(size) LPCVOID data, SIZE_T size,
- UINT32 codePage, _Outptr_ IDxcBlobEncoding **ppBlob) {
- CComPtr<IDxcLibrary> library;
- IFT(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &library));
- IFT(library->CreateBlobWithEncodingFromPinned(data, size, codePage,
- ppBlob));
- }
- void CreateBlobFromFile(LPCWSTR name, _Outptr_ IDxcBlobEncoding **ppBlob) {
- CComPtr<IDxcLibrary> library;
- IFT(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &library));
- const std::wstring path = hlsl_test::GetPathToHlslDataFile(name);
- IFT(library->CreateBlobFromFile(path.c_str(), nullptr, ppBlob));
- }
- void CreateBlobFromText(_In_z_ const char *pText,
- _Outptr_ IDxcBlobEncoding **ppBlob) {
- CreateBlobPinned(pText, strlen(pText), CP_UTF8, ppBlob);
- }
- HRESULT CreateCompiler(IDxcCompiler **ppResult) {
- return m_dllSupport.CreateInstance(CLSID_DxcCompiler, ppResult);
- }
- #ifdef _WIN32 // No ContainerBuilder support yet
- HRESULT CreateContainerBuilder(IDxcContainerBuilder **ppResult) {
- return m_dllSupport.CreateInstance(CLSID_DxcContainerBuilder, ppResult);
- }
- #endif
- template <typename T, typename TDefault, typename TIface>
- void WriteIfValue(TIface *pSymbol, std::wstringstream &o,
- TDefault defaultValue, LPCWSTR valueLabel,
- HRESULT (__stdcall TIface::*pFn)(T *)) {
- T value;
- HRESULT hr = (pSymbol->*(pFn))(&value);
- if (SUCCEEDED(hr) && value != defaultValue) {
- o << L", " << valueLabel << L": " << value;
- }
- }
- #ifdef _WIN32 // exclude dia stuff
- template <typename TIface>
- void WriteIfValue(TIface *pSymbol, std::wstringstream &o,
- LPCWSTR valueLabel, HRESULT(__stdcall TIface::*pFn)(BSTR *)) {
- CComBSTR value;
- HRESULT hr = (pSymbol->*(pFn))(&value);
- if (SUCCEEDED(hr) && value.Length()) {
- o << L", " << valueLabel << L": " << (LPCWSTR)value;
- }
- }
- template <typename TIface>
- void WriteIfValue(TIface *pSymbol, std::wstringstream &o,
- LPCWSTR valueLabel, HRESULT(__stdcall TIface::*pFn)(VARIANT *)) {
- CComVariant value;
- HRESULT hr = (pSymbol->*(pFn))(&value);
- if (SUCCEEDED(hr) && value.vt != VT_NULL && value.vt != VT_EMPTY) {
- if (SUCCEEDED(value.ChangeType(VT_BSTR))) {
- o << L", " << valueLabel << L": " << (LPCWSTR)value.bstrVal;
- }
- }
- }
- template <typename TIface>
- void WriteIfValue(TIface *pSymbol, std::wstringstream &o,
- LPCWSTR valueLabel, HRESULT(__stdcall TIface::*pFn)(IDiaSymbol **)) {
- CComPtr<IDiaSymbol> value;
- HRESULT hr = (pSymbol->*(pFn))(&value);
- if (SUCCEEDED(hr) && value.p != nullptr) {
- DWORD symId;
- value->get_symIndexId(&symId);
- o << L", " << valueLabel << L": id=" << symId;
- }
- }
- std::wstring GetDebugInfoAsText(_In_ IDiaDataSource* pDataSource) {
- CComPtr<IDiaSession> pSession;
- CComPtr<IDiaTable> pTable;
- CComPtr<IDiaEnumTables> pEnumTables;
- std::wstringstream o;
- VERIFY_SUCCEEDED(pDataSource->openSession(&pSession));
- VERIFY_SUCCEEDED(pSession->getEnumTables(&pEnumTables));
- LONG count;
- VERIFY_SUCCEEDED(pEnumTables->get_Count(&count));
- for (LONG i = 0; i < count; ++i) {
- pTable.Release();
- ULONG fetched;
- VERIFY_SUCCEEDED(pEnumTables->Next(1, &pTable, &fetched));
- VERIFY_ARE_EQUAL(fetched, 1);
- CComBSTR tableName;
- VERIFY_SUCCEEDED(pTable->get_name(&tableName));
- o << L"Table: " << (LPWSTR)tableName << std::endl;
- LONG rowCount;
- IFT(pTable->get_Count(&rowCount));
- o << L" Row count: " << rowCount << std::endl;
- for (LONG rowIndex = 0; rowIndex < rowCount; ++rowIndex) {
- CComPtr<IUnknown> item;
- o << L'#' << rowIndex;
- IFT(pTable->Item(rowIndex, &item));
- CComPtr<IDiaSymbol> pSymbol;
- if (SUCCEEDED(item.QueryInterface(&pSymbol))) {
- DWORD symTag;
- DWORD dataKind;
- DWORD locationType;
- DWORD registerId;
- pSymbol->get_symTag(&symTag);
- pSymbol->get_dataKind(&dataKind);
- pSymbol->get_locationType(&locationType);
- pSymbol->get_registerId(®isterId);
- //pSymbol->get_value(&value);
- WriteIfValue(pSymbol.p, o, 0, L"symIndexId", &IDiaSymbol::get_symIndexId);
- o << L", " << SymTagEnumText[symTag];
- if (dataKind != 0) o << L", " << DataKindText[dataKind];
- WriteIfValue(pSymbol.p, o, L"name", &IDiaSymbol::get_name);
- WriteIfValue(pSymbol.p, o, L"lexicalParent", &IDiaSymbol::get_lexicalParent);
- WriteIfValue(pSymbol.p, o, L"type", &IDiaSymbol::get_type);
- WriteIfValue(pSymbol.p, o, 0, L"slot", &IDiaSymbol::get_slot);
- WriteIfValue(pSymbol.p, o, 0, L"platform", &IDiaSymbol::get_platform);
- WriteIfValue(pSymbol.p, o, 0, L"language", &IDiaSymbol::get_language);
- WriteIfValue(pSymbol.p, o, 0, L"frontEndMajor", &IDiaSymbol::get_frontEndMajor);
- WriteIfValue(pSymbol.p, o, 0, L"frontEndMinor", &IDiaSymbol::get_frontEndMinor);
- WriteIfValue(pSymbol.p, o, 0, L"token", &IDiaSymbol::get_token);
- WriteIfValue(pSymbol.p, o, L"value", &IDiaSymbol::get_value);
- WriteIfValue(pSymbol.p, o, 0, L"code", &IDiaSymbol::get_code);
- WriteIfValue(pSymbol.p, o, 0, L"function", &IDiaSymbol::get_function);
- WriteIfValue(pSymbol.p, o, 0, L"udtKind", &IDiaSymbol::get_udtKind);
- WriteIfValue(pSymbol.p, o, 0, L"hasDebugInfo", &IDiaSymbol::get_hasDebugInfo);
- WriteIfValue(pSymbol.p, o, L"compilerName", &IDiaSymbol::get_compilerName);
- WriteIfValue(pSymbol.p, o, 0, L"isLocationControlFlowDependent", &IDiaSymbol::get_isLocationControlFlowDependent);
- WriteIfValue(pSymbol.p, o, 0, L"numberOfRows", &IDiaSymbol::get_numberOfRows);
- WriteIfValue(pSymbol.p, o, 0, L"numberOfColumns", &IDiaSymbol::get_numberOfColumns);
- WriteIfValue(pSymbol.p, o, 0, L"length", &IDiaSymbol::get_length);
- WriteIfValue(pSymbol.p, o, 0, L"isMatrixRowMajor", &IDiaSymbol::get_isMatrixRowMajor);
- WriteIfValue(pSymbol.p, o, 0, L"builtInKind", &IDiaSymbol::get_builtInKind);
- WriteIfValue(pSymbol.p, o, 0, L"textureSlot", &IDiaSymbol::get_textureSlot);
- WriteIfValue(pSymbol.p, o, 0, L"memorySpaceKind", &IDiaSymbol::get_memorySpaceKind);
- WriteIfValue(pSymbol.p, o, 0, L"isHLSLData", &IDiaSymbol::get_isHLSLData);
- }
- CComPtr<IDiaSourceFile> pSourceFile;
- if (SUCCEEDED(item.QueryInterface(&pSourceFile))) {
- WriteIfValue(pSourceFile.p, o, 0, L"uniqueId", &IDiaSourceFile::get_uniqueId);
- WriteIfValue(pSourceFile.p, o, L"fileName", &IDiaSourceFile::get_fileName);
- }
- CComPtr<IDiaLineNumber> pLineNumber;
- if (SUCCEEDED(item.QueryInterface(&pLineNumber))) {
- WriteIfValue(pLineNumber.p, o, L"compiland", &IDiaLineNumber::get_compiland);
- //WriteIfValue(pLineNumber.p, o, L"sourceFile", &IDiaLineNumber::get_sourceFile);
- WriteIfValue(pLineNumber.p, o, 0, L"lineNumber", &IDiaLineNumber::get_lineNumber);
- WriteIfValue(pLineNumber.p, o, 0, L"lineNumberEnd", &IDiaLineNumber::get_lineNumberEnd);
- WriteIfValue(pLineNumber.p, o, 0, L"columnNumber", &IDiaLineNumber::get_columnNumber);
- WriteIfValue(pLineNumber.p, o, 0, L"columnNumberEnd", &IDiaLineNumber::get_columnNumberEnd);
- WriteIfValue(pLineNumber.p, o, 0, L"addressSection", &IDiaLineNumber::get_addressSection);
- WriteIfValue(pLineNumber.p, o, 0, L"addressOffset", &IDiaLineNumber::get_addressOffset);
- WriteIfValue(pLineNumber.p, o, 0, L"relativeVirtualAddress", &IDiaLineNumber::get_relativeVirtualAddress);
- WriteIfValue(pLineNumber.p, o, 0, L"virtualAddress", &IDiaLineNumber::get_virtualAddress);
- WriteIfValue(pLineNumber.p, o, 0, L"length", &IDiaLineNumber::get_length);
- WriteIfValue(pLineNumber.p, o, 0, L"sourceFileId", &IDiaLineNumber::get_sourceFileId);
- WriteIfValue(pLineNumber.p, o, 0, L"statement", &IDiaLineNumber::get_statement);
- WriteIfValue(pLineNumber.p, o, 0, L"compilandId", &IDiaLineNumber::get_compilandId);
- }
- CComPtr<IDiaSectionContrib> pSectionContrib;
- if (SUCCEEDED(item.QueryInterface(&pSectionContrib))) {
- WriteIfValue(pSectionContrib.p, o, L"compiland", &IDiaSectionContrib::get_compiland);
- WriteIfValue(pSectionContrib.p, o, 0, L"addressSection", &IDiaSectionContrib::get_addressSection);
- WriteIfValue(pSectionContrib.p, o, 0, L"addressOffset", &IDiaSectionContrib::get_addressOffset);
- WriteIfValue(pSectionContrib.p, o, 0, L"relativeVirtualAddress", &IDiaSectionContrib::get_relativeVirtualAddress);
- WriteIfValue(pSectionContrib.p, o, 0, L"virtualAddress", &IDiaSectionContrib::get_virtualAddress);
- WriteIfValue(pSectionContrib.p, o, 0, L"length", &IDiaSectionContrib::get_length);
- WriteIfValue(pSectionContrib.p, o, 0, L"notPaged", &IDiaSectionContrib::get_notPaged);
- WriteIfValue(pSectionContrib.p, o, 0, L"code", &IDiaSectionContrib::get_code);
- WriteIfValue(pSectionContrib.p, o, 0, L"initializedData", &IDiaSectionContrib::get_initializedData);
- WriteIfValue(pSectionContrib.p, o, 0, L"uninitializedData", &IDiaSectionContrib::get_uninitializedData);
- WriteIfValue(pSectionContrib.p, o, 0, L"remove", &IDiaSectionContrib::get_remove);
- WriteIfValue(pSectionContrib.p, o, 0, L"comdat", &IDiaSectionContrib::get_comdat);
- WriteIfValue(pSectionContrib.p, o, 0, L"discardable", &IDiaSectionContrib::get_discardable);
- WriteIfValue(pSectionContrib.p, o, 0, L"notCached", &IDiaSectionContrib::get_notCached);
- WriteIfValue(pSectionContrib.p, o, 0, L"share", &IDiaSectionContrib::get_share);
- WriteIfValue(pSectionContrib.p, o, 0, L"execute", &IDiaSectionContrib::get_execute);
- WriteIfValue(pSectionContrib.p, o, 0, L"read", &IDiaSectionContrib::get_read);
- WriteIfValue(pSectionContrib.p, o, 0, L"write", &IDiaSectionContrib::get_write);
- WriteIfValue(pSectionContrib.p, o, 0, L"dataCrc", &IDiaSectionContrib::get_dataCrc);
- WriteIfValue(pSectionContrib.p, o, 0, L"relocationsCrc", &IDiaSectionContrib::get_relocationsCrc);
- WriteIfValue(pSectionContrib.p, o, 0, L"compilandId", &IDiaSectionContrib::get_compilandId);
- }
- CComPtr<IDiaSegment> pSegment;
- if (SUCCEEDED(item.QueryInterface(&pSegment))) {
- WriteIfValue(pSegment.p, o, 0, L"frame", &IDiaSegment::get_frame);
- WriteIfValue(pSegment.p, o, 0, L"offset", &IDiaSegment::get_offset);
- WriteIfValue(pSegment.p, o, 0, L"length", &IDiaSegment::get_length);
- WriteIfValue(pSegment.p, o, 0, L"read", &IDiaSegment::get_read);
- WriteIfValue(pSegment.p, o, 0, L"write", &IDiaSegment::get_write);
- WriteIfValue(pSegment.p, o, 0, L"execute", &IDiaSegment::get_execute);
- WriteIfValue(pSegment.p, o, 0, L"addressSection", &IDiaSegment::get_addressSection);
- WriteIfValue(pSegment.p, o, 0, L"relativeVirtualAddress", &IDiaSegment::get_relativeVirtualAddress);
- WriteIfValue(pSegment.p, o, 0, L"virtualAddress", &IDiaSegment::get_virtualAddress);
- }
- CComPtr<IDiaInjectedSource> pInjectedSource;
- if (SUCCEEDED(item.QueryInterface(&pInjectedSource))) {
- WriteIfValue(pInjectedSource.p, o, 0, L"crc", &IDiaInjectedSource::get_crc);
- WriteIfValue(pInjectedSource.p, o, 0, L"length", &IDiaInjectedSource::get_length);
- WriteIfValue(pInjectedSource.p, o, L"filename", &IDiaInjectedSource::get_filename);
- WriteIfValue(pInjectedSource.p, o, L"objectFilename", &IDiaInjectedSource::get_objectFilename);
- WriteIfValue(pInjectedSource.p, o, L"virtualFilename", &IDiaInjectedSource::get_virtualFilename);
- WriteIfValue(pInjectedSource.p, o, 0, L"sourceCompression", &IDiaInjectedSource::get_sourceCompression);
- // get_source is also available
- }
- CComPtr<IDiaFrameData> pFrameData;
- if (SUCCEEDED(item.QueryInterface(&pFrameData))) {
- }
- o << std::endl;
- }
- }
- return o.str();
- }
- std::wstring GetDebugFileContent(_In_ IDiaDataSource *pDataSource) {
- CComPtr<IDiaSession> pSession;
- CComPtr<IDiaTable> pTable;
- CComPtr<IDiaTable> pSourcesTable;
- CComPtr<IDiaEnumTables> pEnumTables;
- std::wstringstream o;
- VERIFY_SUCCEEDED(pDataSource->openSession(&pSession));
- VERIFY_SUCCEEDED(pSession->getEnumTables(&pEnumTables));
- ULONG fetched = 0;
- while (pEnumTables->Next(1, &pTable, &fetched) == S_OK && fetched == 1) {
- CComBSTR name;
- IFT(pTable->get_name(&name));
- if (wcscmp(name, L"SourceFiles") == 0) {
- pSourcesTable = pTable.Detach();
- continue;
- }
- pTable.Release();
- }
- if (!pSourcesTable) {
- return L"cannot find source";
- }
- // Get source file contents.
- // NOTE: "SourceFiles" has the root file first while "InjectedSources" is in
- // alphabetical order.
- // It is important to keep the root file first for recompilation, so
- // iterate "SourceFiles" and look up the corresponding injected
- // source.
- LONG count;
- IFT(pSourcesTable->get_Count(&count));
- CComPtr<IDiaSourceFile> pSourceFile;
- CComBSTR pName;
- CComPtr<IUnknown> pSymbolUnk;
- CComPtr<IDiaEnumInjectedSources> pEnumInjectedSources;
- CComPtr<IDiaInjectedSource> pInjectedSource;
- std::wstring sourceText, sourceFilename;
- while (SUCCEEDED(pSourcesTable->Next(1, &pSymbolUnk, &fetched)) &&
- fetched == 1) {
- sourceText = sourceFilename = L"";
- IFT(pSymbolUnk->QueryInterface(&pSourceFile));
- IFT(pSourceFile->get_fileName(&pName));
- IFT(pSession->findInjectedSource(pName, &pEnumInjectedSources));
- if (SUCCEEDED(pEnumInjectedSources->get_Count(&count)) && count == 1) {
- IFT(pEnumInjectedSources->Item(0, &pInjectedSource));
- DWORD cbData = 0;
- std::string tempString;
- CComBSTR bstr;
- IFT(pInjectedSource->get_filename(&bstr));
- IFT(pInjectedSource->get_source(0, &cbData, nullptr));
- tempString.resize(cbData);
- IFT(pInjectedSource->get_source(
- cbData, &cbData, reinterpret_cast<BYTE *>(&tempString[0])));
- CA2W tempWString(tempString.data());
- o << tempWString.m_psz;
- }
- pSymbolUnk.Release();
- }
- return o.str();
- }
- struct LineNumber { DWORD line; DWORD rva; };
- std::vector<LineNumber> ReadLineNumbers(IDiaEnumLineNumbers *pEnumLineNumbers) {
- std::vector<LineNumber> lines;
- CComPtr<IDiaLineNumber> pLineNumber;
- DWORD lineCount;
- while (SUCCEEDED(pEnumLineNumbers->Next(1, &pLineNumber, &lineCount)) && lineCount == 1)
- {
- DWORD line;
- DWORD rva;
- VERIFY_SUCCEEDED(pLineNumber->get_lineNumber(&line));
- VERIFY_SUCCEEDED(pLineNumber->get_relativeVirtualAddress(&rva));
- lines.push_back({ line, rva });
- pLineNumber.Release();
- }
- return lines;
- }
- #endif // _WIN32 - exclude dia stuff
-
- std::string GetOption(std::string &cmd, char *opt) {
- std::string option = cmd.substr(cmd.find(opt));
- option = option.substr(option.find_first_of(' '));
- option = option.substr(option.find_first_not_of(' '));
- return option.substr(0, option.find_first_of(' '));
- }
- void CodeGenTest(std::wstring name) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- name.insert(0, L"..\\CodeGenHLSL\\");
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromFile(name.c_str(), &pSource);
- std::string cmdLine = GetFirstLine(name.c_str());
- llvm::StringRef argsRef = cmdLine;
- llvm::SmallVector<llvm::StringRef, 8> splitArgs;
- argsRef.split(splitArgs, " ");
- hlsl::options::MainArgs argStrings(splitArgs);
- std::string errorString;
- llvm::raw_string_ostream errorStream(errorString);
- hlsl::options::DxcOpts opts;
- IFT(ReadDxcOpts(hlsl::options::getHlslOptTable(), /*flagsToInclude*/ 0,
- argStrings, opts, errorStream));
- std::wstring entry =
- Unicode::UTF8ToUTF16StringOrThrow(opts.EntryPoint.str().c_str());
- std::wstring profile =
- Unicode::UTF8ToUTF16StringOrThrow(opts.TargetProfile.str().c_str());
- std::vector<std::wstring> argLists;
- CopyArgsToWStrings(opts.Args, hlsl::options::CoreOption, argLists);
- std::vector<LPCWSTR> args;
- args.reserve(argLists.size());
- for (const std::wstring &a : argLists)
- args.push_back(a.data());
- VERIFY_SUCCEEDED(pCompiler->Compile(
- pSource, name.c_str(), entry.c_str(), profile.c_str(), args.data(), args.size(),
- opts.Defines.data(), opts.Defines.size(), nullptr, &pResult));
- VERIFY_IS_NOT_NULL(pResult, L"Failed to compile - pResult NULL");
- HRESULT result;
- VERIFY_SUCCEEDED(pResult->GetStatus(&result));
- if (FAILED(result)) {
- CComPtr<IDxcBlobEncoding> pErr;
- IFT(pResult->GetErrorBuffer(&pErr));
- std::string errString(BlobToUtf8(pErr));
- CA2W errStringW(errString.c_str(), CP_UTF8);
- WEX::Logging::Log::Comment(L"Failed to compile - errors follow");
- WEX::Logging::Log::Comment(errStringW);
- }
- VERIFY_SUCCEEDED(result);
- CComPtr<IDxcBlob> pProgram;
- VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
- if (opts.IsRootSignatureProfile())
- return;
- CComPtr<IDxcBlobEncoding> pDisassembleBlob;
- VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembleBlob));
- std::string disassembleString(BlobToUtf8(pDisassembleBlob));
- VERIFY_ARE_NOT_EQUAL(0U, disassembleString.size());
- }
- void CodeGenTestCheckFullPath(LPCWSTR fullPath) {
- FileRunTestResult t = FileRunTestResult::RunFromFileCommands(fullPath);
- if (t.RunResult != 0) {
- CA2W commentWide(t.ErrorMessage.c_str(), CP_UTF8);
- WEX::Logging::Log::Comment(commentWide);
- WEX::Logging::Log::Error(L"Run result is not zero");
- }
- }
- void CodeGenTestCheck(LPCWSTR name, bool implicitDir = true) {
- std::wstring path = name;
- if (implicitDir) {
- path.insert(0, L"..\\CodeGenHLSL\\");
- path = hlsl_test::GetPathToHlslDataFile(path.c_str());
- }
- CodeGenTestCheckFullPath(path.c_str());
- }
- void CodeGenTestCheckBatchDir(std::wstring suitePath, bool implicitDir = true) {
- using namespace llvm;
- using namespace WEX::TestExecution;
- if (implicitDir) suitePath.insert(0, L"..\\CodeGenHLSL\\");
- ::llvm::sys::fs::MSFileSystem *msfPtr;
- VERIFY_SUCCEEDED(CreateMSFileSystemForDisk(&msfPtr));
- std::unique_ptr<::llvm::sys::fs::MSFileSystem> msf(msfPtr);
- ::llvm::sys::fs::AutoPerThreadSystem pts(msf.get());
- IFTLLVM(pts.error_code());
- CW2A pUtf8Filename(suitePath.c_str());
- if (!llvm::sys::path::is_absolute(pUtf8Filename.m_psz)) {
- suitePath = hlsl_test::GetPathToHlslDataFile(suitePath.c_str());
- }
- CW2A utf8SuitePath(suitePath.c_str());
- unsigned numTestsRun = 0;
- std::error_code EC;
- llvm::SmallString<128> DirNative;
- llvm::sys::path::native(utf8SuitePath.m_psz, DirNative);
- for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative, EC), DirEnd;
- Dir != DirEnd && !EC; Dir.increment(EC)) {
- // Check whether this entry has an extension typically associated with
- // headers.
- if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
- .Cases(".hlsl", ".ll", true).Default(false))
- continue;
- StringRef filename = Dir->path();
- CA2W wRelPath(filename.data());
- WEX::Logging::Log::StartGroup(wRelPath);
- CodeGenTestCheck(wRelPath, /*implicitDir*/ false);
- WEX::Logging::Log::EndGroup(wRelPath);
- numTestsRun++;
- }
- VERIFY_IS_GREATER_THAN(numTestsRun, (unsigned)0, L"No test files found in batch directory.");
- }
- std::string VerifyCompileFailed(LPCSTR pText, LPCWSTR pTargetProfile, LPCSTR pErrorMsg) {
- return VerifyCompileFailed(pText, pTargetProfile, pErrorMsg, L"main");
- }
- std::string VerifyCompileFailed(LPCSTR pText, LPCWSTR pTargetProfile, LPCSTR pErrorMsg, LPCWSTR pEntryPoint) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(pText, &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", pEntryPoint,
- pTargetProfile, nullptr, 0, nullptr, 0, nullptr, &pResult));
- HRESULT status;
- VERIFY_SUCCEEDED(pResult->GetStatus(&status));
- VERIFY_FAILED(status);
- VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&pErrors));
- if (pErrorMsg && *pErrorMsg) {
- CheckOperationResultMsgs(pResult, &pErrorMsg, 1, false, false);
- }
- return BlobToUtf8(pErrors);
- }
- void VerifyOperationSucceeded(IDxcOperationResult *pResult) {
- HRESULT result;
- VERIFY_SUCCEEDED(pResult->GetStatus(&result));
- if (FAILED(result)) {
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&pErrors));
- CA2W errorsWide(BlobToUtf8(pErrors).c_str(), CP_UTF8);
- WEX::Logging::Log::Comment(errorsWide);
- }
- VERIFY_SUCCEEDED(result);
- }
- std::string VerifyOperationFailed(IDxcOperationResult *pResult) {
- HRESULT result;
- VERIFY_SUCCEEDED(pResult->GetStatus(&result));
- VERIFY_FAILED(result);
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&pErrors));
- return BlobToUtf8(pErrors);
- }
- #ifdef _WIN32 // - exclude dia stuff
- HRESULT CreateDiaSourceForCompile(const char *hlsl, IDiaDataSource **ppDiaSource)
- {
- if (!ppDiaSource)
- return E_POINTER;
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlob> pProgram;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(hlsl, &pSource);
- LPCWSTR args[] = { L"/Zi" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, _countof(args), nullptr, 0, nullptr, &pResult));
- VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
- // Disassemble the compiled (stripped) program.
- {
- CComPtr<IDxcBlobEncoding> pDisassembly;
- VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
- std::string disText = BlobToUtf8(pDisassembly);
- CA2W disTextW(disText.c_str(), CP_UTF8);
- //WEX::Logging::Log::Comment(disTextW);
- }
- // CONSIDER: have the dia data source look for the part if passed a whole container.
- CComPtr<IDiaDataSource> pDiaSource;
- CComPtr<IStream> pProgramStream;
- CComPtr<IDxcLibrary> pLib;
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLib));
- const hlsl::DxilContainerHeader *pContainer = hlsl::IsDxilContainerLike(
- pProgram->GetBufferPointer(), pProgram->GetBufferSize());
- VERIFY_IS_NOT_NULL(pContainer);
- hlsl::DxilPartIterator partIter =
- std::find_if(hlsl::begin(pContainer), hlsl::end(pContainer),
- hlsl::DxilPartIsType(hlsl::DFCC_ShaderDebugInfoDXIL));
- const hlsl::DxilProgramHeader *pProgramHeader =
- (const hlsl::DxilProgramHeader *)hlsl::GetDxilPartData(*partIter);
- uint32_t bitcodeLength;
- const char *pBitcode;
- CComPtr<IDxcBlob> pProgramPdb;
- hlsl::GetDxilProgramBitcode(pProgramHeader, &pBitcode, &bitcodeLength);
- VERIFY_SUCCEEDED(pLib->CreateBlobFromBlob(
- pProgram, pBitcode - (char *)pProgram->GetBufferPointer(), bitcodeLength,
- &pProgramPdb));
- // Disassemble the program with debug information.
- {
- CComPtr<IDxcBlobEncoding> pDbgDisassembly;
- VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgramPdb, &pDbgDisassembly));
- std::string disText = BlobToUtf8(pDbgDisassembly);
- CA2W disTextW(disText.c_str(), CP_UTF8);
- //WEX::Logging::Log::Comment(disTextW);
- }
- // Create a short text dump of debug information.
- VERIFY_SUCCEEDED(pLib->CreateStreamFromBlobReadOnly(pProgramPdb, &pProgramStream));
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcDiaDataSource, &pDiaSource));
- VERIFY_SUCCEEDED(pDiaSource->loadDataFromIStream(pProgramStream));
- *ppDiaSource = pDiaSource.Detach();
- return S_OK;
- }
- #endif // _WIN32 - exclude dia stuff
- };
- // Useful for debugging.
- #if SUPPORT_FXC_PDB
- #include <d3dcompiler.h>
- #pragma comment(lib, "d3dcompiler.lib")
- HRESULT GetBlobPdb(IDxcBlob *pBlob, IDxcBlob **ppDebugInfo) {
- return D3DGetBlobPart(pBlob->GetBufferPointer(), pBlob->GetBufferSize(),
- D3D_BLOB_PDB, 0, (ID3DBlob **)ppDebugInfo);
- }
- std::string FourCCStr(uint32_t val) {
- std::stringstream o;
- char c[5];
- c[0] = val & 0xFF;
- c[1] = (val & 0xFF00) >> 8;
- c[2] = (val & 0xFF0000) >> 16;
- c[3] = (val & 0xFF000000) >> 24;
- c[4] = '\0';
- o << c << " (" << std::hex << val << std::dec << ")";
- return o.str();
- }
- std::string DumpParts(IDxcBlob *pBlob) {
- std::stringstream o;
- hlsl::DxilContainerHeader *pContainer = (hlsl::DxilContainerHeader *)pBlob->GetBufferPointer();
- o << "Container:" << std::endl
- << " Size: " << pContainer->ContainerSizeInBytes << std::endl
- << " FourCC: " << FourCCStr(pContainer->HeaderFourCC) << std::endl
- << " Part count: " << pContainer->PartCount << std::endl;
- for (uint32_t i = 0; i < pContainer->PartCount; ++i) {
- hlsl::DxilPartHeader *pPart = hlsl::GetDxilContainerPart(pContainer, i);
- o << "Part " << i << std::endl
- << " FourCC: " << FourCCStr(pPart->PartFourCC) << std::endl
- << " Size: " << pPart->PartSize << std::endl;
- }
- return o.str();
- }
- HRESULT CreateDiaSourceFromDxbcBlob(IDxcLibrary *pLib, IDxcBlob *pDxbcBlob,
- IDiaDataSource **ppDiaSource) {
- HRESULT hr = S_OK;
- CComPtr<IDxcBlob> pdbBlob;
- CComPtr<IStream> pPdbStream;
- CComPtr<IDiaDataSource> pDiaSource;
- IFR(GetBlobPdb(pDxbcBlob, &pdbBlob));
- IFR(pLib->CreateStreamFromBlobReadOnly(pdbBlob, &pPdbStream));
- IFR(CoCreateInstance(CLSID_DiaSource, NULL, CLSCTX_INPROC_SERVER,
- __uuidof(IDiaDataSource), (void **)&pDiaSource));
- IFR(pDiaSource->loadDataFromIStream(pPdbStream));
- *ppDiaSource = pDiaSource.Detach();
- return hr;
- }
- #endif
- bool CompilerTest::InitSupport() {
- if (!m_dllSupport.IsEnabled()) {
- VERIFY_SUCCEEDED(m_dllSupport.Initialize());
- m_ver.Initialize(m_dllSupport);
- }
- return true;
- }
- #if _WIN32 // - exclude dia stuff
- TEST_F(CompilerTest, CompileWhenDebugThenDIPresent) {
- // BUG: the first test written was of this form:
- // float4 local = 0; return local;
- //
- // However we get no numbers because of the _wrapper form
- // that exports the zero initialization from main into
- // a global can't be attributed to any particular location
- // within main, and everything in main is eventually folded away.
- //
- // Making the function do a bit more work by calling an intrinsic
- // helps this case.
- CComPtr<IDiaDataSource> pDiaSource;
- VERIFY_SUCCEEDED(CreateDiaSourceForCompile(
- "float4 main(float4 pos : SV_Position) : SV_Target {\r\n"
- " float4 local = abs(pos);\r\n"
- " return local;\r\n"
- "}", &pDiaSource));
- std::wstring diaDump = GetDebugInfoAsText(pDiaSource).c_str();
- //WEX::Logging::Log::Comment(GetDebugInfoAsText(pDiaSource).c_str());
- // Very basic tests - we have basic symbols, line numbers, and files with sources.
- VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"symIndexId: 5, CompilandEnv, name: hlslTarget, lexicalParent: id=2, value: ps_6_0"));
- VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"lineNumber: 2"));
- VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"length: 99, filename: source.hlsl"));
- std::wstring diaFileContent = GetDebugFileContent(pDiaSource).c_str();
- VERIFY_IS_NOT_NULL(wcsstr(diaFileContent.c_str(), L"loat4 main(float4 pos : SV_Position) : SV_Target"));
- #if SUPPORT_FXC_PDB
- // Now, fake it by loading from a .pdb!
- VERIFY_SUCCEEDED(CoInitializeEx(0, COINITBASE_MULTITHREADED));
- const wchar_t path[] = L"path-to-fxc-blob.bin";
- pDiaSource.Release();
- pProgramStream.Release();
- CComPtr<IDxcBlobEncoding> fxcBlob;
- CComPtr<IDxcBlob> pdbBlob;
- VERIFY_SUCCEEDED(pLib->CreateBlobFromFile(path, nullptr, &fxcBlob));
- std::string s = DumpParts(fxcBlob);
- CA2W sW(s.c_str(), CP_UTF8);
- WEX::Logging::Log::Comment(sW);
- VERIFY_SUCCEEDED(CreateDiaSourceFromDxbcBlob(pLib, fxcBlob, &pDiaSource));
- WEX::Logging::Log::Comment(GetDebugInfoAsText(pDiaSource).c_str());
- #endif
- }
- TEST_F(CompilerTest, CompileDebugLines) {
- CComPtr<IDiaDataSource> pDiaSource;
- VERIFY_SUCCEEDED(CreateDiaSourceForCompile(
- "float main(float pos : A) : SV_Target {\r\n"
- " float x = abs(pos);\r\n"
- " float y = sin(pos);\r\n"
- " float z = x + y;\r\n"
- " return z;\r\n"
- "}", &pDiaSource));
-
- static constexpr uint32_t numExpectedRVAs = 10;
- auto verifyLines = [=](const std::vector<LineNumber> lines) {
- VERIFY_ARE_EQUAL(lines.size(), numExpectedRVAs);
- // 0: loadInput
- VERIFY_ARE_EQUAL(lines[0].rva, 0);
- VERIFY_ARE_EQUAL(lines[0].line, 1);
- // 1: dbg.value
- VERIFY_ARE_EQUAL(lines[1].rva, 1);
- VERIFY_ARE_EQUAL(lines[1].line, 1);
- // 2: abs
- VERIFY_ARE_EQUAL(lines[2].rva, 2);
- VERIFY_ARE_EQUAL(lines[2].line, 2);
- // 3: dbg.value
- VERIFY_ARE_EQUAL(lines[3].rva, 3);
- VERIFY_ARE_EQUAL(lines[3].line, 2);
- // 4: sin
- VERIFY_ARE_EQUAL(lines[4].rva, 4);
- VERIFY_ARE_EQUAL(lines[4].line, 3);
- // 5: dbg.value
- VERIFY_ARE_EQUAL(lines[5].rva, 5);
- VERIFY_ARE_EQUAL(lines[5].line, 3);
- // 6: fadd
- VERIFY_ARE_EQUAL(lines[6].rva, 6);
- VERIFY_ARE_EQUAL(lines[6].line, 4);
- // 7: dbg.value
- VERIFY_ARE_EQUAL(lines[7].rva, 7);
- VERIFY_ARE_EQUAL(lines[7].line, 4);
- // 8: storeOutput
- VERIFY_ARE_EQUAL(lines[8].rva, 8);
- VERIFY_ARE_EQUAL(lines[8].line, 5);
- // 9: ret
- VERIFY_ARE_EQUAL(lines[9].rva, 9);
- VERIFY_ARE_EQUAL(lines[9].line, 5);
- };
-
- CComPtr<IDiaSession> pSession;
- CComPtr<IDiaEnumLineNumbers> pEnumLineNumbers;
- // Verify lines are ok when getting one RVA at a time.
- std::vector<LineNumber> linesOneByOne;
- VERIFY_SUCCEEDED(pDiaSource->openSession(&pSession));
- for (int i = 0; i < numExpectedRVAs; ++i) {
- VERIFY_SUCCEEDED(pSession->findLinesByRVA(i, 1, &pEnumLineNumbers));
- std::vector<LineNumber> lines = ReadLineNumbers(pEnumLineNumbers);
- std::copy(lines.begin(), lines.end(), std::back_inserter(linesOneByOne));
- pEnumLineNumbers.Release();
- }
- verifyLines(linesOneByOne);
- // Verify lines are ok when getting all RVAs at once.
- std::vector<LineNumber> linesAllAtOnce;
- pEnumLineNumbers.Release();
- VERIFY_SUCCEEDED(pSession->findLinesByRVA(0, numExpectedRVAs, &pEnumLineNumbers));
- linesAllAtOnce = ReadLineNumbers(pEnumLineNumbers);
- verifyLines(linesAllAtOnce);
- // Verify lines are ok when getting all lines through enum tables.
- std::vector<LineNumber> linesFromTable;
- pEnumLineNumbers.Release();
- CComPtr<IDiaEnumTables> pTables;
- CComPtr<IDiaTable> pTable;
- VERIFY_SUCCEEDED(pSession->getEnumTables(&pTables));
- DWORD celt;
- while (SUCCEEDED(pTables->Next(1, &pTable, &celt)) && celt == 1)
- {
- if (SUCCEEDED(pTable->QueryInterface(&pEnumLineNumbers))) {
- linesFromTable = ReadLineNumbers(pEnumLineNumbers);
- break;
- }
- pTable.Release();
- }
- verifyLines(linesFromTable);
-
- // Verify lines are ok when getting by address.
- std::vector<LineNumber> linesByAddr;
- pEnumLineNumbers.Release();
- VERIFY_SUCCEEDED(pSession->findLinesByAddr(0, 0, numExpectedRVAs, &pEnumLineNumbers));
- linesByAddr = ReadLineNumbers(pEnumLineNumbers);
- verifyLines(linesByAddr);
- // Verify findFileById.
- CComPtr<IDiaSourceFile> pFile;
- VERIFY_SUCCEEDED(pSession->findFileById(0, &pFile));
- CComBSTR pName;
- VERIFY_SUCCEEDED(pFile->get_fileName(&pName));
- VERIFY_ARE_EQUAL_WSTR(pName, L"source.hlsl");
- }
- #endif // _WIN32 - exclude dia stuff
- TEST_F(CompilerTest, CompileWhenDefinesThenApplied) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- DxcDefine defines[] = {{L"F4", L"float4"}};
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("F4 main() : SV_Target { return 0; }", &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, defines,
- _countof(defines), nullptr, &pResult));
- }
- TEST_F(CompilerTest, CompileWhenDefinesManyThenApplied) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- LPCWSTR args[] = {L"/DVAL1=1", L"/DVAL2=2", L"/DVAL3=3", L"/DVAL4=2",
- L"/DVAL5=4", L"/DNVAL1", L"/DNVAL2", L"/DNVAL3",
- L"/DNVAL4", L"/DNVAL5", L"/DCVAL1=1", L"/DCVAL2=2",
- L"/DCVAL3=3", L"/DCVAL4=2", L"/DCVAL5=4", L"/DCVALNONE="};
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main() : SV_Target {\r\n"
- "#ifndef VAL1\r\n"
- "#error VAL1 not defined\r\n"
- "#endif\r\n"
- "#ifndef NVAL5\r\n"
- "#error NVAL5 not defined\r\n"
- "#endif\r\n"
- "#ifndef CVALNONE\r\n"
- "#error CVALNONE not defined\r\n"
- "#endif\r\n"
- "return 0; }",
- &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, _countof(args), nullptr,
- 0, nullptr, &pResult));
- HRESULT compileStatus;
- VERIFY_SUCCEEDED(pResult->GetStatus(&compileStatus));
- if (FAILED(compileStatus)) {
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&pErrors));
- OutputDebugStringA((LPCSTR)pErrors->GetBufferPointer());
- }
- VERIFY_SUCCEEDED(compileStatus);
- }
- TEST_F(CompilerTest, CompileWhenEmptyThenFails) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlobEncoding> pSourceBad;
- LPCWSTR pProfile = L"ps_6_0";
- LPCWSTR pEntryPoint = L"main";
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
- CreateBlobFromText("float4 main() : SV_Target { return undef; }", &pSourceBad);
- // correct version
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", pEntryPoint,
- pProfile, nullptr, 0, nullptr, 0, nullptr,
- &pResult));
- pResult.Release();
- // correct version with compilation errors
- VERIFY_SUCCEEDED(pCompiler->Compile(pSourceBad, L"source.hlsl", pEntryPoint,
- pProfile, nullptr, 0, nullptr, 0, nullptr,
- &pResult));
- pResult.Release();
- // null source
- VERIFY_FAILED(pCompiler->Compile(nullptr, L"source.hlsl", pEntryPoint, pProfile,
- nullptr, 0, nullptr, 0, nullptr, &pResult));
- // null profile
- VERIFY_FAILED(pCompiler->Compile(pSourceBad, L"source.hlsl", pEntryPoint,
- nullptr, nullptr, 0, nullptr, 0, nullptr,
- &pResult));
- // null source name succeeds
- VERIFY_SUCCEEDED(pCompiler->Compile(pSourceBad, nullptr, pEntryPoint, pProfile,
- nullptr, 0, nullptr, 0, nullptr, &pResult));
- pResult.Release();
- // empty source name (as opposed to null) also suceeds
- VERIFY_SUCCEEDED(pCompiler->Compile(pSourceBad, L"", pEntryPoint, pProfile,
- nullptr, 0, nullptr, 0, nullptr,
- &pResult));
- pResult.Release();
- // null result
- VERIFY_FAILED(pCompiler->Compile(pSource, L"source.hlsl", pEntryPoint,
- pProfile, nullptr, 0, nullptr, 0, nullptr,
- nullptr));
- }
- TEST_F(CompilerTest, CompileWhenIncorrectThenFails) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4_undefined main() : SV_Target { return 0; }",
- &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main", L"ps_6_0",
- nullptr, 0, nullptr, 0, nullptr,
- &pResult));
- HRESULT result;
- VERIFY_SUCCEEDED(pResult->GetStatus(&result));
- VERIFY_FAILED(result);
- CComPtr<IDxcBlobEncoding> pErrorBuffer;
- VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&pErrorBuffer));
- std::string errorString(BlobToUtf8(pErrorBuffer));
- VERIFY_ARE_NOT_EQUAL(0U, errorString.size());
- // Useful for examining actual error message:
- // CA2W errorStringW(errorString.c_str(), CP_UTF8);
- // WEX::Logging::Log::Comment(errorStringW.m_psz);
- }
- TEST_F(CompilerTest, CompileWhenWorksThenDisassembleWorks) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0,
- nullptr, &pResult));
- HRESULT result;
- VERIFY_SUCCEEDED(pResult->GetStatus(&result));
- VERIFY_SUCCEEDED(result);
- CComPtr<IDxcBlob> pProgram;
- VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
- CComPtr<IDxcBlobEncoding> pDisassembleBlob;
- VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembleBlob));
- std::string disassembleString(BlobToUtf8(pDisassembleBlob));
- VERIFY_ARE_NOT_EQUAL(0U, disassembleString.size());
- // Useful for examining disassembly:
- // CA2W disassembleStringW(disassembleString.c_str(), CP_UTF8);
- // WEX::Logging::Log::Comment(disassembleStringW.m_psz);
- }
- #ifdef _WIN32 // Container builder unsupported
- TEST_F(CompilerTest, CompileWhenDebugWorksThenStripDebug) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlob> pProgram;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main(float4 pos : SV_Position) : SV_Target {\r\n"
- " float4 local = abs(pos);\r\n"
- " return local;\r\n"
- "}",
- &pSource);
- LPCWSTR args[] = {L"/Zi"};
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, _countof(args), nullptr,
- 0, nullptr, &pResult));
- VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
- // Check if it contains debug blob
- hlsl::DxilContainerHeader *pHeader =
- (hlsl::DxilContainerHeader *)(pProgram->GetBufferPointer());
- hlsl::DxilPartHeader *pPartHeader = hlsl::GetDxilPartByType(
- pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL);
- VERIFY_IS_NOT_NULL(pPartHeader);
- // Check debug info part does not exist after strip debug info
- CComPtr<IDxcBlob> pNewProgram;
- CComPtr<IDxcContainerBuilder> pBuilder;
- VERIFY_SUCCEEDED(CreateContainerBuilder(&pBuilder));
- VERIFY_SUCCEEDED(pBuilder->Load(pProgram));
- VERIFY_SUCCEEDED(pBuilder->RemovePart(hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL));
- pResult.Release();
- VERIFY_SUCCEEDED(pBuilder->SerializeContainer(&pResult));
- VERIFY_SUCCEEDED(pResult->GetResult(&pNewProgram));
- pHeader = (hlsl::DxilContainerHeader *)(pNewProgram->GetBufferPointer());
- pPartHeader = hlsl::GetDxilPartByType(
- pHeader, hlsl::DxilFourCC::DFCC_ShaderDebugInfoDXIL);
- VERIFY_IS_NULL(pPartHeader);
- }
- TEST_F(CompilerTest, CompileWhenWorksThenAddRemovePrivate) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlob> pProgram;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main() : SV_Target {\r\n"
- " return 0;\r\n"
- "}",
- &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0,
- nullptr, &pResult));
- VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
- // Append private data blob
- CComPtr<IDxcContainerBuilder> pBuilder;
- VERIFY_SUCCEEDED(CreateContainerBuilder(&pBuilder));
- std::string privateTxt("private data");
- CComPtr<IDxcBlobEncoding> pPrivate;
- CreateBlobFromText(privateTxt.c_str(), &pPrivate);
- VERIFY_SUCCEEDED(pBuilder->Load(pProgram));
- VERIFY_SUCCEEDED(pBuilder->AddPart(hlsl::DxilFourCC::DFCC_PrivateData, pPrivate));
- pResult.Release();
- VERIFY_SUCCEEDED(pBuilder->SerializeContainer(&pResult));
- CComPtr<IDxcBlob> pNewProgram;
- VERIFY_SUCCEEDED(pResult->GetResult(&pNewProgram));
- hlsl::DxilContainerHeader *pContainerHeader =
- (hlsl::DxilContainerHeader *)(pNewProgram->GetBufferPointer());
- hlsl::DxilPartHeader *pPartHeader = hlsl::GetDxilPartByType(
- pContainerHeader, hlsl::DxilFourCC::DFCC_PrivateData);
- VERIFY_IS_NOT_NULL(pPartHeader);
- // compare data
- std::string privatePart((const char *)(pPartHeader + 1), privateTxt.size());
- VERIFY_IS_TRUE(strcmp(privatePart.c_str(), privateTxt.c_str()) == 0);
- // Remove private data blob
- pBuilder.Release();
- VERIFY_SUCCEEDED(CreateContainerBuilder(&pBuilder));
- VERIFY_SUCCEEDED(pBuilder->Load(pNewProgram));
- VERIFY_SUCCEEDED(pBuilder->RemovePart(hlsl::DxilFourCC::DFCC_PrivateData));
- pResult.Release();
- VERIFY_SUCCEEDED(pBuilder->SerializeContainer(&pResult));
- pNewProgram.Release();
- VERIFY_SUCCEEDED(pResult->GetResult(&pNewProgram));
- pContainerHeader =
- (hlsl::DxilContainerHeader *)(pNewProgram->GetBufferPointer());
- pPartHeader = hlsl::GetDxilPartByType(
- pContainerHeader, hlsl::DxilFourCC::DFCC_PrivateData);
- VERIFY_IS_NULL(pPartHeader);
- }
- TEST_F(CompilerTest, CompileThenAddCustomDebugName) {
- // container builders prior to 1.3 did not support adding debug name parts
- if (m_ver.SkipDxilVersion(1, 3)) return;
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlob> pProgram;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main() : SV_Target {\r\n"
- " return 0;\r\n"
- "}",
- &pSource);
- LPCWSTR args[] = { L"/Zi", L"/Zss" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, _countof(args), nullptr, 0,
- nullptr, &pResult));
- VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
- // Append private data blob
- CComPtr<IDxcContainerBuilder> pBuilder;
- VERIFY_SUCCEEDED(CreateContainerBuilder(&pBuilder));
- const char pNewName[] = "MyOwnUniqueName.lld";
- //include null terminator:
- size_t nameBlobPartSize = sizeof(hlsl::DxilShaderDebugName) + _countof(pNewName);
- // round up to four-byte size:
- size_t allocatedSize = (nameBlobPartSize + 3) & ~3;
- auto pNameBlobContent = reinterpret_cast<hlsl::DxilShaderDebugName*>(malloc(allocatedSize));
- ZeroMemory(pNameBlobContent, allocatedSize); //just to make sure trailing nulls are nulls.
- pNameBlobContent->Flags = 0;
- pNameBlobContent->NameLength = _countof(pNewName) - 1; //this is not supposed to include null terminator
- memcpy(pNameBlobContent + 1, pNewName, _countof(pNewName));
- CComPtr<IDxcBlobEncoding> pDebugName;
- CreateBlobPinned(pNameBlobContent, allocatedSize, CP_UTF8, &pDebugName);
- VERIFY_SUCCEEDED(pBuilder->Load(pProgram));
- // should fail since it already exists:
- VERIFY_FAILED(pBuilder->AddPart(hlsl::DxilFourCC::DFCC_ShaderDebugName, pDebugName));
- VERIFY_SUCCEEDED(pBuilder->RemovePart(hlsl::DxilFourCC::DFCC_ShaderDebugName));
- VERIFY_SUCCEEDED(pBuilder->AddPart(hlsl::DxilFourCC::DFCC_ShaderDebugName, pDebugName));
- pResult.Release();
- VERIFY_SUCCEEDED(pBuilder->SerializeContainer(&pResult));
- CComPtr<IDxcBlob> pNewProgram;
- VERIFY_SUCCEEDED(pResult->GetResult(&pNewProgram));
- hlsl::DxilContainerHeader *pContainerHeader =
- (hlsl::DxilContainerHeader *)(pNewProgram->GetBufferPointer());
- hlsl::DxilPartHeader *pPartHeader = hlsl::GetDxilPartByType(
- pContainerHeader, hlsl::DxilFourCC::DFCC_ShaderDebugName);
- VERIFY_IS_NOT_NULL(pPartHeader);
- // compare data
- VERIFY_IS_TRUE(memcmp(pPartHeader + 1, pNameBlobContent, allocatedSize) == 0);
- free(pNameBlobContent);
- // Remove private data blob
- pBuilder.Release();
- VERIFY_SUCCEEDED(CreateContainerBuilder(&pBuilder));
- VERIFY_SUCCEEDED(pBuilder->Load(pNewProgram));
- VERIFY_SUCCEEDED(pBuilder->RemovePart(hlsl::DxilFourCC::DFCC_ShaderDebugName));
- pResult.Release();
- VERIFY_SUCCEEDED(pBuilder->SerializeContainer(&pResult));
- pNewProgram.Release();
- VERIFY_SUCCEEDED(pResult->GetResult(&pNewProgram));
- pContainerHeader =
- (hlsl::DxilContainerHeader *)(pNewProgram->GetBufferPointer());
- pPartHeader = hlsl::GetDxilPartByType(
- pContainerHeader, hlsl::DxilFourCC::DFCC_ShaderDebugName);
- VERIFY_IS_NULL(pPartHeader);
- }
- TEST_F(CompilerTest, CompileWithRootSignatureThenStripRootSignature) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlob> pProgram;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("[RootSignature(\"\")] \r\n"
- "float4 main(float a : A) : SV_Target {\r\n"
- " return a;\r\n"
- "}",
- &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr,
- 0, nullptr, &pResult));
- VERIFY_IS_NOT_NULL(pResult);
- HRESULT status;
- VERIFY_SUCCEEDED(pResult->GetStatus(&status));
- VERIFY_SUCCEEDED(status);
- VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
- VERIFY_IS_NOT_NULL(pProgram);
- hlsl::DxilContainerHeader *pContainerHeader =
- (hlsl::DxilContainerHeader *)(pProgram->GetBufferPointer());
- hlsl::DxilPartHeader *pPartHeader = hlsl::GetDxilPartByType(
- pContainerHeader, hlsl::DxilFourCC::DFCC_RootSignature);
- VERIFY_IS_NOT_NULL(pPartHeader);
-
- // Remove root signature
- CComPtr<IDxcBlob> pNewProgram;
- CComPtr<IDxcContainerBuilder> pBuilder;
- VERIFY_SUCCEEDED(CreateContainerBuilder(&pBuilder));
- VERIFY_SUCCEEDED(pBuilder->Load(pProgram));
- VERIFY_SUCCEEDED(pBuilder->RemovePart(hlsl::DxilFourCC::DFCC_RootSignature));
- pResult.Release();
- VERIFY_SUCCEEDED(pBuilder->SerializeContainer(&pResult));
- VERIFY_SUCCEEDED(pResult->GetResult(&pNewProgram));
- pContainerHeader = (hlsl::DxilContainerHeader *)(pNewProgram->GetBufferPointer());
- pPartHeader = hlsl::GetDxilPartByType(pContainerHeader,
- hlsl::DxilFourCC::DFCC_RootSignature);
- VERIFY_IS_NULL(pPartHeader);
- }
- #endif // Container builder unsupported
- TEST_F(CompilerTest, CompileWhenIncludeThenLoadInvoked) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "#include \"helper.h\"\r\n"
- "float4 main() : SV_Target { return 0; }", &pSource);
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("");
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0, pInclude, &pResult));
- VerifyOperationSucceeded(pResult);
- VERIFY_ARE_EQUAL_WSTR(L"./helper.h;", pInclude->GetAllFileNames().c_str());
- }
- TEST_F(CompilerTest, CompileWhenIncludeThenLoadUsed) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "#include \"helper.h\"\r\n"
- "float4 main() : SV_Target { return ZERO; }", &pSource);
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("#define ZERO 0");
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0, pInclude, &pResult));
- VerifyOperationSucceeded(pResult);
- VERIFY_ARE_EQUAL_WSTR(L"./helper.h;", pInclude->GetAllFileNames().c_str());
- }
- TEST_F(CompilerTest, CompileWhenIncludeAbsoluteThenLoadAbsolute) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- #ifdef _WIN32 // OS-specific root
- CreateBlobFromText(
- "#include \"C:\\helper.h\"\r\n"
- "float4 main() : SV_Target { return ZERO; }", &pSource);
- #else
- CreateBlobFromText(
- "#include \"/helper.h\"\n"
- "float4 main() : SV_Target { return ZERO; }", &pSource);
- #endif
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("#define ZERO 0");
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0, pInclude, &pResult));
- VerifyOperationSucceeded(pResult);
- #ifdef _WIN32 // OS-specific root
- VERIFY_ARE_EQUAL_WSTR(L"C:\\helper.h;", pInclude->GetAllFileNames().c_str());
- #else
- VERIFY_ARE_EQUAL_WSTR(L"/helper.h;", pInclude->GetAllFileNames().c_str());
- #endif
- }
- TEST_F(CompilerTest, CompileWhenIncludeLocalThenLoadRelative) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "#include \"..\\helper.h\"\r\n"
- "float4 main() : SV_Target { return ZERO; }", &pSource);
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("#define ZERO 0");
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0, pInclude, &pResult));
- VerifyOperationSucceeded(pResult);
- #ifdef _WIN32 // OS-specific directory dividers
- VERIFY_ARE_EQUAL_WSTR(L"./..\\helper.h;", pInclude->GetAllFileNames().c_str());
- #else
- VERIFY_ARE_EQUAL_WSTR(L"./../helper.h;", pInclude->GetAllFileNames().c_str());
- #endif
- }
- TEST_F(CompilerTest, CompileWhenIncludeSystemThenLoadNotRelative) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "#include \"subdir/other/file.h\"\r\n"
- "float4 main() : SV_Target { return ZERO; }", &pSource);
- LPCWSTR args[] = {
- L"-Ifoo"
- };
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("#include <helper.h>");
- pInclude->CallResults.emplace_back("#define ZERO 0");
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, _countof(args), nullptr, 0, pInclude, &pResult));
- VerifyOperationSucceeded(pResult);
- #ifdef _WIN32 // OS-specific directory dividers
- VERIFY_ARE_EQUAL_WSTR(L"./subdir/other/file.h;./foo\\helper.h;", pInclude->GetAllFileNames().c_str());
- #else
- VERIFY_ARE_EQUAL_WSTR(L"./subdir/other/file.h;./foo/helper.h;", pInclude->GetAllFileNames().c_str());
- #endif
- }
- TEST_F(CompilerTest, CompileWhenIncludeSystemMissingThenLoadAttempt) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "#include \"subdir/other/file.h\"\r\n"
- "float4 main() : SV_Target { return ZERO; }", &pSource);
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("#include <helper.h>");
- pInclude->CallResults.emplace_back("#define ZERO 0");
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0, pInclude, &pResult));
- std::string failLog(VerifyOperationFailed(pResult));
- VERIFY_ARE_NOT_EQUAL(std::string::npos, failLog.find("<angled>")); // error message should prompt to use <angled> rather than "quotes"
- VERIFY_ARE_EQUAL_WSTR(L"./subdir/other/file.h;./subdir/other/helper.h;", pInclude->GetAllFileNames().c_str());
- }
- TEST_F(CompilerTest, CompileWhenIncludeFlagsThenIncludeUsed) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "#include <helper.h>\r\n"
- "float4 main() : SV_Target { return ZERO; }", &pSource);
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("#define ZERO 0");
- #ifdef _WIN32 // OS-specific root
- LPCWSTR args[] = { L"-I\\\\server\\share" };
- #else
- LPCWSTR args[] = { L"-I/server/share" };
- #endif
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, _countof(args), nullptr, 0, pInclude, &pResult));
- VerifyOperationSucceeded(pResult);
- #ifdef _WIN32 // OS-specific root
- VERIFY_ARE_EQUAL_WSTR(L"\\\\server\\share\\helper.h;", pInclude->GetAllFileNames().c_str());
- #else
- VERIFY_ARE_EQUAL_WSTR(L"/server/share/helper.h;", pInclude->GetAllFileNames().c_str());
- #endif
- }
- TEST_F(CompilerTest, CompileWhenIncludeMissingThenFail) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "#include \"file.h\"\r\n"
- "float4 main() : SV_Target { return 0; }", &pSource);
- pInclude = new TestIncludeHandler(m_dllSupport);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0, pInclude, &pResult));
- HRESULT hr;
- VERIFY_SUCCEEDED(pResult->GetStatus(&hr));
- VERIFY_FAILED(hr);
- }
- TEST_F(CompilerTest, CompileWhenIncludeHasPathThenOK) {
- CComPtr<IDxcCompiler> pCompiler;
- LPCWSTR Source = L"c:\\temp\\OddIncludes\\main.hlsl";
- LPCWSTR Args[] = { L"/I", L"c:\\temp" };
- LPCWSTR ArgsUp[] = { L"/I", L"c:\\Temp" };
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- bool useUpValues[] = { false, true };
- for (bool useUp : useUpValues) {
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- #if TEST_ON_DISK
- CComPtr<IDxcLibrary> pLibrary;
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
- VERIFY_SUCCEEDED(pLibrary->CreateIncludeHandler(&pInclude));
- VERIFY_SUCCEEDED(pLibrary->CreateBlobFromFile(Source, nullptr, &pSource));
- #else
- CComPtr<TestIncludeHandler> pInclude;
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("// Empty");
- CreateBlobFromText("#include \"include.hlsl\"\r\n"
- "float4 main() : SV_Target { return 0; }",
- &pSource);
- #endif
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, Source, L"main",
- L"ps_6_0", useUp ? ArgsUp : Args, _countof(Args), nullptr, 0, pInclude, &pResult));
- HRESULT hr;
- VERIFY_SUCCEEDED(pResult->GetStatus(&hr));
- VERIFY_SUCCEEDED(hr);
- }
- }
- TEST_F(CompilerTest, CompileWhenIncludeEmptyThenOK) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<TestIncludeHandler> pInclude;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("#include \"empty.h\"\r\n"
- "float4 main() : SV_Target { return 0; }",
- &pSource);
- pInclude = new TestIncludeHandler(m_dllSupport);
- pInclude->CallResults.emplace_back("", CP_ACP); // An empty file would get detected as ACP code page
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0,
- pInclude, &pResult));
- VerifyOperationSucceeded(pResult);
- VERIFY_ARE_EQUAL_WSTR(L"./empty.h;", pInclude->GetAllFileNames().c_str());
- }
- static const char EmptyCompute[] = "[numthreads(8,8,1)] void main() { }";
- TEST_F(CompilerTest, CompileWhenODumpThenPassConfig) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(EmptyCompute, &pSource);
- LPCWSTR Args[] = { L"/Odump" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"cs_6_0", Args, _countof(Args), nullptr, 0, nullptr, &pResult));
- VerifyOperationSucceeded(pResult);
- CComPtr<IDxcBlob> pResultBlob;
- VERIFY_SUCCEEDED(pResult->GetResult(&pResultBlob));
- string passes((char *)pResultBlob->GetBufferPointer(), pResultBlob->GetBufferSize());
- VERIFY_ARE_NOT_EQUAL(string::npos, passes.find("inline"));
- }
- TEST_F(CompilerTest, CompileWhenVdThenProducesDxilContainer) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(EmptyCompute, &pSource);
- LPCWSTR Args[] = { L"/Vd" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"cs_6_0", Args, _countof(Args), nullptr, 0, nullptr, &pResult));
- VerifyOperationSucceeded(pResult);
- CComPtr<IDxcBlob> pResultBlob;
- VERIFY_SUCCEEDED(pResult->GetResult(&pResultBlob));
- VERIFY_IS_TRUE(hlsl::IsValidDxilContainer(reinterpret_cast<hlsl::DxilContainerHeader *>(pResultBlob->GetBufferPointer()), pResultBlob->GetBufferSize()));
- }
- TEST_F(CompilerTest, CompileWhenODumpThenOptimizerMatch) {
- LPCWSTR OptLevels[] = { L"/Od", L"/O1", L"/O2" };
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOptimizer> pOptimizer;
- CComPtr<IDxcAssembler> pAssembler;
- CComPtr<IDxcValidator> pValidator;
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcAssembler, &pAssembler));
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcOptimizer, &pOptimizer));
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcValidator, &pValidator));
- for (LPCWSTR OptLevel : OptLevels) {
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlob> pHighLevelBlob;
- CComPtr<IDxcBlob> pOptimizedModule;
- CComPtr<IDxcBlob> pAssembledBlob;
- // Could use EmptyCompute and cs_6_0, but there is an issue where properties
- // don't round-trip properly at high-level, so validation fails because
- // dimensions are set to zero. Workaround by using pixel shader instead.
- LPCWSTR Target = L"ps_6_0";
- CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
- LPCWSTR Args[2] = { OptLevel, L"/Odump" };
- // Get the passes for this optimization level.
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- Target, Args, _countof(Args), nullptr, 0, nullptr, &pResult));
- VerifyOperationSucceeded(pResult);
- CComPtr<IDxcBlob> pResultBlob;
- VERIFY_SUCCEEDED(pResult->GetResult(&pResultBlob));
- string passes((char *)pResultBlob->GetBufferPointer(), pResultBlob->GetBufferSize());
- // Get wchar_t version and prepend hlsl-hlensure, to do a split high-level/opt compilation pass.
- CA2W passesW(passes.c_str(), CP_UTF8);
- std::vector<LPCWSTR> Options;
- SplitPassList(passesW.m_psz, Options);
- // Now compile directly.
- pResult.Release();
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- Target, Args, 1, nullptr, 0, nullptr, &pResult));
- VerifyOperationSucceeded(pResult);
- // Now compile via a high-level compile followed by the optimization passes.
- pResult.Release();
- Args[_countof(Args)-1] = L"/fcgl";
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- Target, Args, _countof(Args), nullptr, 0, nullptr, &pResult));
- VerifyOperationSucceeded(pResult);
- VERIFY_SUCCEEDED(pResult->GetResult(&pHighLevelBlob));
- VERIFY_SUCCEEDED(pOptimizer->RunOptimizer(pHighLevelBlob, Options.data(),
- Options.size(), &pOptimizedModule,
- nullptr));
- string text = DisassembleProgram(m_dllSupport, pOptimizedModule);
- WEX::Logging::Log::Comment(L"Final program:");
- WEX::Logging::Log::Comment(CA2W(text.c_str()));
- // At the very least, the module should be valid.
- pResult.Release();
- VERIFY_SUCCEEDED(pAssembler->AssembleToContainer(pOptimizedModule, &pResult));
- VerifyOperationSucceeded(pResult);
- VERIFY_SUCCEEDED(pResult->GetResult(&pAssembledBlob));
- pResult.Release();
- VERIFY_SUCCEEDED(pValidator->Validate(pAssembledBlob, DxcValidatorFlags_Default, &pResult));
- VerifyOperationSucceeded(pResult);
- }
- }
- static const UINT CaptureStacks = 0; // Set to 1 to enable captures
- static const UINT StackFrameCount = 12;
- struct InstrumentedHeapMalloc : public IMalloc {
- private:
- HANDLE m_Handle; // Heap handle.
- ULONG m_RefCount = 0; // Reference count. Used for reference leaks, not for lifetime.
- ULONG m_AllocCount = 0; // Total # of alloc and realloc requests.
- ULONG m_AllocSize = 0; // Total # of alloc and realloc bytes.
- ULONG m_Size = 0; // Current # of alloc'ed bytes.
- ULONG m_FailAlloc = 0; // If nonzero, the alloc/realloc call to fail.
- // Each allocation also tracks the following information:
- // - allocation callstack
- // - deallocation callstack
- // - prior/next blocks in a list of allocated blocks
- LIST_ENTRY AllocList;
- struct PtrData {
- LIST_ENTRY Entry;
- LPVOID AllocFrames[CaptureStacks ? StackFrameCount * CaptureStacks : 1];
- LPVOID FreeFrames[CaptureStacks ? StackFrameCount * CaptureStacks : 1];
- UINT64 AllocAtCount;
- DWORD AllocFrameCount;
- DWORD FreeFrameCount;
- SIZE_T Size;
- PtrData *Self;
- };
- PtrData *DataFromPtr(void *p) {
- if (p == nullptr) return nullptr;
- PtrData *R = ((PtrData *)p) - 1;
- if (R != R->Self) {
- VERIFY_FAIL(); // p is invalid or underrun
- }
- return R;
- }
- public:
- InstrumentedHeapMalloc() : m_Handle(nullptr) {
- ResetCounts();
- }
- ~InstrumentedHeapMalloc() {
- if (m_Handle)
- HeapDestroy(m_Handle);
- }
- void ResetHeap() {
- if (m_Handle) {
- HeapDestroy(m_Handle);
- m_Handle = nullptr;
- }
- m_Handle = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
- }
- ULONG GetRefCount() const { return m_RefCount; }
- ULONG GetAllocCount() const { return m_AllocCount; }
- ULONG GetAllocSize() const { return m_AllocSize; }
- ULONG GetSize() const { return m_Size; }
- void ResetCounts() {
- m_RefCount = m_AllocCount = m_AllocSize = m_Size = 0;
- AllocList.Blink = AllocList.Flink = &AllocList;
- }
- void SetFailAlloc(ULONG index) {
- m_FailAlloc = index;
- }
- ULONG STDMETHODCALLTYPE AddRef() {
- return ++m_RefCount;
- }
- ULONG STDMETHODCALLTYPE Release() {
- if (m_RefCount == 0) VERIFY_FAIL();
- return --m_RefCount;
- }
- STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) {
- return DoBasicQueryInterface<IMalloc>(this, iid, ppvObject);
- }
- virtual void *STDMETHODCALLTYPE Alloc(_In_ SIZE_T cb) {
- ++m_AllocCount;
- if (m_FailAlloc && m_AllocCount >= m_FailAlloc) {
- return nullptr; // breakpoint for i failure - m_FailAlloc == 1+VAL
- }
- m_AllocSize += cb;
- m_Size += cb;
- PtrData *P = (PtrData *)HeapAlloc(m_Handle, HEAP_ZERO_MEMORY, sizeof(PtrData) + cb);
- P->Entry.Flink = AllocList.Flink;
- P->Entry.Blink = &AllocList;
- AllocList.Flink->Blink = &(P->Entry);
- AllocList.Flink = &(P->Entry);
- // breakpoint for i failure on NN alloc - m_FailAlloc == 1+VAL && m_AllocCount == NN
- // breakpoint for happy path for NN alloc - m_AllocCount == NN
- P->AllocAtCount = m_AllocCount;
- if (CaptureStacks)
- P->AllocFrameCount = CaptureStackBackTrace(1, StackFrameCount, P->AllocFrames, nullptr);
- P->Size = cb;
- P->Self = P;
- return P + 1;
- }
- virtual void *STDMETHODCALLTYPE Realloc(_In_opt_ void *pv, _In_ SIZE_T cb) {
- SIZE_T priorSize = pv == nullptr ? (SIZE_T)0 : GetSize(pv);
- void *R = Alloc(cb);
- if (!R)
- return nullptr;
- SIZE_T copySize = std::min(cb, priorSize);
- memcpy(R, pv, copySize);
- Free(pv);
- return R;
- }
- virtual void STDMETHODCALLTYPE Free(_In_opt_ void *pv) {
- if (!pv)
- return;
- PtrData *P = DataFromPtr(pv);
- if (P->FreeFrameCount)
- VERIFY_FAIL(); // double-free detected
- m_Size -= P->Size;
- P->Entry.Flink->Blink = P->Entry.Blink;
- P->Entry.Blink->Flink = P->Entry.Flink;
- if (CaptureStacks)
- P->FreeFrameCount =
- CaptureStackBackTrace(1, StackFrameCount, P->FreeFrames, nullptr);
- }
- virtual SIZE_T STDMETHODCALLTYPE GetSize(
- /* [annotation][in] */
- _In_opt_ _Post_writable_byte_size_(return) void *pv)
- {
- if (pv == nullptr) return 0;
- return DataFromPtr(pv)->Size;
- }
- virtual int STDMETHODCALLTYPE DidAlloc(
- _In_opt_ void *pv) {
- return -1; // don't know
- }
- virtual void STDMETHODCALLTYPE HeapMinimize(void) {}
- void DumpLeaks() {
- PtrData *ptr = (PtrData*)AllocList.Flink;;
- PtrData *end = (PtrData*)AllocList.Blink;;
- WEX::Logging::Log::Comment(FormatToWString(L"Leaks total size: %d", (signed int)m_Size).data());
- while (ptr != end) {
- WEX::Logging::Log::Comment(FormatToWString(L"Memory leak at 0x0%X, size %d, alloc# %d", ptr + 1, ptr->Size, ptr->AllocAtCount).data());
- ptr = (PtrData*)ptr->Entry.Flink;
- }
- }
- };
- #if _ITERATOR_DEBUG_LEVEL==0
- // CompileWhenNoMemThenOOM can properly detect leaks only when debug iterators are disabled
- TEST_F(CompilerTest, CompileWhenNoMemThenOOM) {
- WEX::TestExecution::SetVerifyOutput verifySettings(WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures);
- CComPtr<IDxcBlobEncoding> pSource;
- CreateBlobFromText(EmptyCompute, &pSource);
- InstrumentedHeapMalloc InstrMalloc;
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- ULONG allocCount = 0;
- ULONG allocSize = 0;
- ULONG initialRefCount;
- InstrMalloc.ResetHeap();
- VERIFY_IS_TRUE(m_dllSupport.HasCreateWithMalloc());
- // Verify a simple object creation.
- initialRefCount = InstrMalloc.GetRefCount();
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance2(&InstrMalloc, CLSID_DxcCompiler, &pCompiler));
- pCompiler.Release();
- VERIFY_IS_TRUE(0 == InstrMalloc.GetSize());
- VERIFY_ARE_EQUAL(initialRefCount, InstrMalloc.GetRefCount());
- InstrMalloc.ResetCounts();
- InstrMalloc.ResetHeap();
- // First time, run to completion and capture stats.
- initialRefCount = InstrMalloc.GetRefCount();
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance2(&InstrMalloc, CLSID_DxcCompiler, &pCompiler));
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"cs_6_0", nullptr, 0, nullptr, 0, nullptr, &pResult));
- allocCount = InstrMalloc.GetAllocCount();
- allocSize = InstrMalloc.GetAllocSize();
- HRESULT hrWithMemory;
- VERIFY_SUCCEEDED(pResult->GetStatus(&hrWithMemory));
- VERIFY_SUCCEEDED(hrWithMemory);
- pCompiler.Release();
- pResult.Release();
- VERIFY_IS_TRUE(allocSize > allocCount);
- // Ensure that after all resources are released, there are no outstanding
- // allocations or references.
- //
- // First leak is in ((InstrumentedHeapMalloc::PtrData *)InstrMalloc.AllocList.Flink)
- if (InstrMalloc.GetSize() != 0) {
- WEX::Logging::Log::Comment(L"Memory leak(s) detected");
- InstrMalloc.DumpLeaks();
- VERIFY_IS_TRUE(0 == InstrMalloc.GetSize());
- }
- VERIFY_ARE_EQUAL(initialRefCount, InstrMalloc.GetRefCount());
- // In Debug, without /D_ITERATOR_DEBUG_LEVEL=0, debug iterators will be used;
- // this causes a problem where std::string is specified as noexcept, and yet
- // a sentinel is allocated that may fail and throw.
- if (m_ver.SkipOutOfMemoryTest()) return;
- // Now, fail each allocation and make sure we get an error.
- for (ULONG i = 0; i <= allocCount; ++i) {
- // LogCommentFmt(L"alloc fail %u", i);
- bool isLast = i == allocCount;
- InstrMalloc.ResetCounts();
- InstrMalloc.ResetHeap();
- InstrMalloc.SetFailAlloc(i + 1);
- HRESULT hrOp = m_dllSupport.CreateInstance2(&InstrMalloc, CLSID_DxcCompiler, &pCompiler);
- if (SUCCEEDED(hrOp)) {
- hrOp = pCompiler->Compile(pSource, L"source.hlsl", L"main", L"cs_6_0",
- nullptr, 0, nullptr, 0, nullptr, &pResult);
- if (SUCCEEDED(hrOp)) {
- pResult->GetStatus(&hrOp);
- }
- }
- if (FAILED(hrOp)) {
- // This is true in *almost* every case. When the OOM happens during stream
- // handling, there is no specific error set; by the time it's detected,
- // it propagates as E_FAIL.
- //VERIFY_ARE_EQUAL(hrOp, E_OUTOFMEMORY);
- VERIFY_IS_TRUE(hrOp == E_OUTOFMEMORY || hrOp == E_FAIL);
- }
- if (isLast)
- VERIFY_SUCCEEDED(hrOp);
- else
- VERIFY_FAILED(hrOp);
- pCompiler.Release();
- pResult.Release();
-
- if (InstrMalloc.GetSize() != 0) {
- WEX::Logging::Log::Comment(FormatToWString(L"Memory leak(s) detected, allocCount = %d", i).data());
- InstrMalloc.DumpLeaks();
- VERIFY_IS_TRUE(0 == InstrMalloc.GetSize());
- }
- VERIFY_ARE_EQUAL(initialRefCount, InstrMalloc.GetRefCount());
- }
- }
- #endif
- TEST_F(CompilerTest, CompileWhenShaderModelMismatchAttributeThenFail) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(EmptyCompute, &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0, nullptr, &pResult));
- std::string failLog(VerifyOperationFailed(pResult));
- VERIFY_ARE_NOT_EQUAL(string::npos, failLog.find("attribute numthreads only valid for CS"));
- }
- TEST_F(CompilerTest, CompileBadHlslThenFail) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "bad hlsl", &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", nullptr, 0, nullptr, 0, nullptr, &pResult));
- HRESULT status;
- VERIFY_SUCCEEDED(pResult->GetStatus(&status));
- VERIFY_FAILED(status);
- }
- TEST_F(CompilerTest, CompileLegacyShaderModelThenFail) {
- VerifyCompileFailed(
- "float4 main(float4 pos : SV_Position) : SV_Target { return pos; }", L"ps_5_1", nullptr);
- }
- TEST_F(CompilerTest, CompileWhenRecursiveAlbeitStaticTermThenFail) {
- // This shader will compile under fxc because if execution is
- // simulated statically, it does terminate. dxc changes this behavior
- // to avoid imposing the requirement on the compiler.
- const char ShaderText[] =
- "static int i = 10;\r\n"
- "float4 f(); // Forward declaration\r\n"
- "float4 g() { if (i > 10) { i--; return f(); } else return 0; } // Recursive call to 'f'\r\n"
- "float4 f() { return g(); } // First call to 'g'\r\n"
- "float4 VS() : SV_Position{\r\n"
- " return f(); // First call to 'f'\r\n"
- "}\r\n";
- VerifyCompileFailed(ShaderText, L"vs_6_0", "recursive functions not allowed", L"VS");
- }
- TEST_F(CompilerTest, CompileWhenRecursiveThenFail) {
- const char ShaderTextSimple[] =
- "float4 f(); // Forward declaration\r\n"
- "float4 g() { return f(); } // Recursive call to 'f'\r\n"
- "float4 f() { return g(); } // First call to 'g'\r\n"
- "float4 main() : SV_Position{\r\n"
- " return f(); // First call to 'f'\r\n"
- "}\r\n";
- VerifyCompileFailed(ShaderTextSimple, L"vs_6_0", "recursive functions not allowed");
- const char ShaderTextIndirect[] =
- "float4 f(); // Forward declaration\r\n"
- "float4 g() { return f(); } // Recursive call to 'f'\r\n"
- "float4 f() { return g(); } // First call to 'g'\r\n"
- "float4 main() : SV_Position{\r\n"
- " return f(); // First call to 'f'\r\n"
- "}\r\n";
- VerifyCompileFailed(ShaderTextIndirect, L"vs_6_0", "recursive functions not allowed");
- const char ShaderTextSelf[] =
- "float4 main() : SV_Position{\r\n"
- " return main();\r\n"
- "}\r\n";
- VerifyCompileFailed(ShaderTextSelf, L"vs_6_0", "recursive functions not allowed");
- const char ShaderTextMissing[] =
- "float4 mainz() : SV_Position{\r\n"
- " return 1;\r\n"
- "}\r\n";
- VerifyCompileFailed(ShaderTextMissing, L"vs_6_0", "missing entry point definition");
- }
- TEST_F(CompilerTest, CompileHlsl2015ThenFail) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main(float4 pos : SV_Position) : SV_Target { return pos; }", &pSource);
- LPCWSTR args[2] = { L"-HV", L"2015" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, 2, nullptr, 0, nullptr, &pResult));
- HRESULT status;
- VERIFY_SUCCEEDED(pResult->GetStatus(&status));
- VERIFY_ARE_EQUAL(status, E_INVALIDARG);
- VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&pErrors));
- LPCSTR pErrorMsg = "HLSL Version 2015 is only supported for language services";
- CheckOperationResultMsgs(pResult, &pErrorMsg, 1, false, false);
- }
- TEST_F(CompilerTest, CompileHlsl2016ThenOK) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main(float4 pos : SV_Position) : SV_Target { return pos; }", &pSource);
- LPCWSTR args[2] = { L"-HV", L"2016" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, 2, nullptr, 0, nullptr, &pResult));
- HRESULT status;
- VERIFY_SUCCEEDED(pResult->GetStatus(&status));
- VERIFY_SUCCEEDED(status);
- }
- TEST_F(CompilerTest, CompileHlsl2017ThenOK) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main(float4 pos : SV_Position) : SV_Target { return pos; }", &pSource);
- LPCWSTR args[2] = { L"-HV", L"2017" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, 2, nullptr, 0, nullptr, &pResult));
- HRESULT status;
- VERIFY_SUCCEEDED(pResult->GetStatus(&status));
- VERIFY_SUCCEEDED(status);
- }
- TEST_F(CompilerTest, CompileHlsl2018ThenOK) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main(float4 pos : SV_Position) : SV_Target { return pos; }", &pSource);
- LPCWSTR args[2] = { L"-HV", L"2018" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, 2, nullptr, 0, nullptr, &pResult));
- HRESULT status;
- VERIFY_SUCCEEDED(pResult->GetStatus(&status));
- VERIFY_SUCCEEDED(status);
- }
- TEST_F(CompilerTest, CompileHlsl2019ThenFail) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- CComPtr<IDxcBlobEncoding> pErrors;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText("float4 main(float4 pos : SV_Position) : SV_Target { return pos; }", &pSource);
- LPCWSTR args[2] = { L"-HV", L"2019" };
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"ps_6_0", args, 2, nullptr, 0, nullptr, &pResult));
- HRESULT status;
- VERIFY_SUCCEEDED(pResult->GetStatus(&status));
- VERIFY_ARE_EQUAL(status, E_INVALIDARG);
- VERIFY_SUCCEEDED(pResult->GetErrorBuffer(&pErrors));
- LPCSTR pErrorMsg = "Unknown HLSL version";
- CheckOperationResultMsgs(pResult, &pErrorMsg, 1, false, false);
- }
- #ifdef _WIN32 // - exclude dia stuff
- TEST_F(CompilerTest, DiaLoadBadBitcodeThenFail) {
- CComPtr<IDxcBlob> pBadBitcode;
- CComPtr<IDiaDataSource> pDiaSource;
- CComPtr<IStream> pStream;
- CComPtr<IDxcLibrary> pLib;
- Utf8ToBlob(m_dllSupport, "badcode", &pBadBitcode);
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLib));
- VERIFY_SUCCEEDED(pLib->CreateStreamFromBlobReadOnly(pBadBitcode, &pStream));
- VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcDiaDataSource, &pDiaSource));
- VERIFY_FAILED(pDiaSource->loadDataFromIStream(pStream));
- }
- static void CompileTestAndLoadDia(dxc::DxcDllSupport &dllSupport, IDiaDataSource **ppDataSource) {
- CComPtr<IDxcBlob> pContainer;
- CComPtr<IDxcBlob> pDebugContent;
- CComPtr<IDiaDataSource> pDiaSource;
- CComPtr<IStream> pStream;
- CComPtr<IDxcLibrary> pLib;
- CComPtr<IDxcContainerReflection> pReflection;
- UINT32 index;
- VerifyCompileOK(dllSupport, EmptyCompute, L"cs_6_0", L"/Zi", &pContainer);
- VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLib));
- VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcContainerReflection, &pReflection));
- VERIFY_SUCCEEDED(pReflection->Load(pContainer));
- VERIFY_SUCCEEDED(pReflection->FindFirstPartKind(hlsl::DFCC_ShaderDebugInfoDXIL, &index));
- VERIFY_SUCCEEDED(pReflection->GetPartContent(index, &pDebugContent));
- VERIFY_SUCCEEDED(pLib->CreateStreamFromBlobReadOnly(pDebugContent, &pStream));
- VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcDiaDataSource, &pDiaSource));
- VERIFY_SUCCEEDED(pDiaSource->loadDataFromIStream(pStream));
- if (ppDataSource) {
- *ppDataSource = pDiaSource.Detach();
- }
- }
- TEST_F(CompilerTest, DiaLoadDebugThenOK) {
- CompileTestAndLoadDia(m_dllSupport, nullptr);
- }
- TEST_F(CompilerTest, DiaTableIndexThenOK) {
- CComPtr<IDiaDataSource> pDiaSource;
- CComPtr<IDiaSession> pDiaSession;
- CComPtr<IDiaEnumTables> pEnumTables;
- CComPtr<IDiaTable> pTable;
- VARIANT vtIndex;
- CompileTestAndLoadDia(m_dllSupport, &pDiaSource);
- VERIFY_SUCCEEDED(pDiaSource->openSession(&pDiaSession));
- VERIFY_SUCCEEDED(pDiaSession->getEnumTables(&pEnumTables));
- vtIndex.vt = VT_EMPTY;
- VERIFY_FAILED(pEnumTables->Item(vtIndex, &pTable));
- vtIndex.vt = VT_I4;
- vtIndex.intVal = 1;
- VERIFY_SUCCEEDED(pEnumTables->Item(vtIndex, &pTable));
- VERIFY_IS_NOT_NULL(pTable.p);
- pTable.Release();
- vtIndex.vt = VT_UI4;
- vtIndex.uintVal = 1;
- VERIFY_SUCCEEDED(pEnumTables->Item(vtIndex, &pTable));
- VERIFY_IS_NOT_NULL(pTable.p);
- pTable.Release();
- vtIndex.uintVal = 100;
- VERIFY_FAILED(pEnumTables->Item(vtIndex, &pTable));
- }
- #endif // _WIN32 - exclude dia stuff
- TEST_F(CompilerTest, CodeGenAttributeAtVertex) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"attributeAtVertex.hlsl");
- }
- TEST_F(CompilerTest, CodeGenAttributeAtVertexNoOpt) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"attributeAtVertexNoOpt.hlsl");
- }
- TEST_F(CompilerTest, CodeGenBarycentrics) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"barycentrics.hlsl");
- }
- TEST_F(CompilerTest, CodeGenBarycentrics1) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"barycentrics1.hlsl");
- }
- TEST_F(CompilerTest, CodeGenBarycentricsThreeSV) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"barycentricsThreeSV.hlsl");
- }
- TEST_F(CompilerTest, CodeGenBitCast16Bits) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"bitcast_16bits.hlsl");
- }
- TEST_F(CompilerTest, CodeGenCbuffer64Types) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"cbuffer64Types.hlsl");
- }
- TEST_F(CompilerTest, CodeGenCbufferHalf) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"cbufferHalf.hlsl");
- }
- TEST_F(CompilerTest, CodeGenCbufferHalfStruct) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"cbufferHalf-struct.hlsl");
- }
- TEST_F(CompilerTest, CodeGenCbufferInt16) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"cbufferInt16.hlsl");
- }
- TEST_F(CompilerTest, CodeGenCbufferInt16Struct) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"cbufferInt16-struct.hlsl");
- }
- TEST_F(CompilerTest, CodeGenDataLayoutHalf) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"dataLayoutHalf.hlsl");
- }
- TEST_F(CompilerTest, CodeGenEnum3) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"enum3.hlsl");
- }
- #ifdef _WIN32
- #pragma fenv_access(on)
- #pragma optimize("", off)
- #pragma warning(disable : 4723)
- // Define test state as something weird that we can verify was restored
- static const unsigned int fpTestState =
- (_MCW_EM & (~_EM_ZERODIVIDE)) | // throw on div by zero
- _DN_FLUSH_OPERANDS_SAVE_RESULTS | // denorm flush operands & save results
- _RC_UP; // round up
- static const unsigned int fpTestMask = _MCW_EM | _MCW_DN | _MCW_RC;
- struct FPTestScope
- {
- // _controlfp_s is non-standard and <cfenv> doesn't have a function to enable exceptions
- unsigned int fpSavedState;
- FPTestScope() {
- VERIFY_IS_TRUE(_controlfp_s(&fpSavedState, 0, 0) == 0);
- unsigned int newValue;
- VERIFY_IS_TRUE(_controlfp_s(&newValue, fpTestState, fpTestMask) == 0);
- }
- ~FPTestScope() {
- unsigned int newValue;
- errno_t error = _controlfp_s(&newValue, fpSavedState, fpTestMask);
- DXASSERT_LOCALVAR(error, error == 0, "Failed to restore floating-point environment.");
- }
- };
- void VerifyDivByZeroThrows() {
- bool bCaughtExpectedException = false;
- __try {
- float one = 1.0;
- float zero = 0.0;
- float val = one / zero;
- (void)val;
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- bCaughtExpectedException = true;
- }
- VERIFY_IS_TRUE(bCaughtExpectedException);
- }
- TEST_F(CompilerTest, CodeGenFloatingPointEnvironment) {
- unsigned int fpOriginal;
- VERIFY_IS_TRUE(_controlfp_s(&fpOriginal, 0, 0) == 0);
- {
- FPTestScope fpTestScope;
- // Get state before/after compilation, making sure it's our test state,
- // and that it is restored after the compile.
- unsigned int fpBeforeCompile;
- VERIFY_IS_TRUE(_controlfp_s(&fpBeforeCompile, 0, 0) == 0);
- VERIFY_ARE_EQUAL((fpBeforeCompile & fpTestMask), fpTestState);
- CodeGenTestCheck(L"fpexcept.hlsl");
- // Verify excpetion environment was restored
- unsigned int fpAfterCompile;
- VERIFY_IS_TRUE(_controlfp_s(&fpAfterCompile, 0, 0) == 0);
- VERIFY_ARE_EQUAL((fpBeforeCompile & fpTestMask), (fpAfterCompile & fpTestMask));
- // Make sure round up is set
- VERIFY_ARE_EQUAL(rint(12.25), 13);
- // Make sure we actually enabled div-by-zero exception
- VerifyDivByZeroThrows();
- }
- // Verify original state has been restored
- unsigned int fpLocal;
- VERIFY_IS_TRUE(_controlfp_s(&fpLocal, 0, 0) == 0);
- VERIFY_ARE_EQUAL(fpLocal, fpOriginal);
- }
- #pragma optimize("", on)
- #else // _WIN32
- // Only implemented on Win32
- TEST_F(CompilerTest, CodeGenFloatingPointEnvironment) {
- VERIFY_IS_TRUE(true);
- }
- #endif // _WIN32
- TEST_F(CompilerTest, CodeGenFixedWidthTypes) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"fixedWidth.hlsl");
- }
- TEST_F(CompilerTest, CodeGenFixedWidthTypes16Bit) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"fixedWidth16Bit.hlsl");
- }
- TEST_F(CompilerTest, CodeGenFunctionAttribute) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"functionAttribute.hlsl");
- }
- TEST_F(CompilerTest, CodeGenInclude) {
- CodeGenTestCheck(L"Include.hlsl");
- }
- TEST_F(CompilerTest, CodeGenInt16Op) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"int16Op.hlsl");
- }
- TEST_F(CompilerTest, CodeGenInt16OpBits) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"int16OpBits.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLibCsEntry) {
- CodeGenTestCheck(L"lib_cs_entry.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLibCsEntry2) {
- CodeGenTestCheck(L"lib_cs_entry2.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLibCsEntry3) {
- CodeGenTestCheck(L"lib_cs_entry3.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLibEntries) {
- CodeGenTestCheck(L"lib_entries.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLibEntries2) {
- CodeGenTestCheck(L"lib_entries2.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLibNoAlias) {
- CodeGenTestCheck(L"lib_no_alias.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLibResource) {
- CodeGenTestCheck(L"lib_resource.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLibUnusedFunc) {
- CodeGenTestCheck(L"lib_unused_func.hlsl");
- }
- TEST_F(CompilerTest, CodeGenMultiUAVLoad2) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"multiUAVLoad2.hlsl");
- }
- TEST_F(CompilerTest, CodeGenMultiUAVLoad4) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"multiUAVLoad4.hlsl");
- }
- TEST_F(CompilerTest, CodeGenMultiUAVLoad5) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"multiUAVLoad5.hlsl");
- }
- TEST_F(CompilerTest, CodeGenMultiUAVLoad6) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"multiUAVLoad6.hlsl");
- }
- TEST_F(CompilerTest, CodeGenMultiUAVLoad7) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"multiUAVLoad7.hlsl");
- }
- TEST_F(CompilerTest, CodeGenRaw_Buf2) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"raw_buf2.hlsl");
- }
- TEST_F(CompilerTest, CodeGenRaw_Buf4) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"raw_buf4.hlsl");
- }
- TEST_F(CompilerTest, CodeGenRaw_Buf5) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"raw_buf5.hlsl");
- }
- TEST_F(CompilerTest, CodeGenSignaturePackingByWidth) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"signature_packing_by_width.hlsl");
- }
- TEST_F(CompilerTest, CodeGenStruct_Buf2) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"struct_buf2.hlsl");
- }
- TEST_F(CompilerTest, CodeGenStruct_Buf3) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"struct_buf3.hlsl");
- }
- TEST_F(CompilerTest, CodeGenStruct_Buf4) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"struct_buf4.hlsl");
- }
- TEST_F(CompilerTest, CodeGenStruct_Buf5) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"struct_buf5.hlsl");
- }
- TEST_F(CompilerTest, CodeGenStruct_Buf6) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"struct_buf6.hlsl");
- }
- TEST_F(CompilerTest, CodeGenStruct_Buf_New_Layout) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"struct_buf_new_layout.hlsl");
- }
- TEST_F(CompilerTest, CodeGenUav_Typed_Load_Store3) {
- if (m_ver.SkipDxilVersion(1,2)) return;
- CodeGenTestCheck(L"uav_typed_load_store3.hlsl");
- }
- TEST_F(CompilerTest, CodeGenUint64_2) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheck(L"uint64_2.hlsl");
- }
- TEST_F(CompilerTest, CodeGenLiterals_Exact_Precision_Mod) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"literals_exact_precision_Mod.hlsl");
- }
- TEST_F(CompilerTest, CodeGenTypedBufferHalf) {
- if (m_ver.SkipDxilVersion(1, 2)) return;
- CodeGenTestCheck(L"typed_buffer_half.hlsl");
- }
- TEST_F(CompilerTest, CodeGenRootSigProfile) {
- CodeGenTest(L"rootSigProfile.hlsl");
- }
- TEST_F(CompilerTest, CodeGenRootSigProfile2) {
- // TODO: Verify the result when reflect the structures.
- CodeGenTest(L"rootSigProfile2.hlsl");
- }
- TEST_F(CompilerTest, CodeGenRootSigProfile5) {
- CodeGenTest(L"rootSigProfile5.hlsl");
- }
- TEST_F(CompilerTest, CodeGenSamples){
- CodeGenTestCheckBatchDir(L"Samples");
- }
- TEST_F(CompilerTest, PreprocessWhenValidThenOK) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- DxcDefine defines[2];
- defines[0].Name = L"MYDEF";
- defines[0].Value = L"int";
- defines[1].Name = L"MYOTHERDEF";
- defines[1].Value = L"123";
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "// First line\r\n"
- "MYDEF g_int = MYOTHERDEF;\r\n"
- "#define FOO BAR\r\n"
- "int FOO;", &pSource);
- VERIFY_SUCCEEDED(pCompiler->Preprocess(pSource, L"file.hlsl", nullptr, 0,
- defines, _countof(defines), nullptr,
- &pResult));
- HRESULT hrOp;
- VERIFY_SUCCEEDED(pResult->GetStatus(&hrOp));
- VERIFY_SUCCEEDED(hrOp);
- CComPtr<IDxcBlob> pOutText;
- VERIFY_SUCCEEDED(pResult->GetResult(&pOutText));
- std::string text(BlobToUtf8(pOutText));
- VERIFY_ARE_EQUAL_STR(
- "#line 1 \"file.hlsl\"\n"
- "\n"
- "int g_int = 123;\n"
- "\n"
- "int BAR;\n", text.c_str());
- }
- TEST_F(CompilerTest, PreprocessWhenExpandTokenPastingOperandThenAccept) {
- // Tests that we can turn on fxc's behavior (pre-expanding operands before
- // performing token-pasting) using -flegacy-macro-expansion
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- LPCWSTR expandOption = L"-flegacy-macro-expansion";
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(R"(
- #define SET_INDEX0 10
- #define BINDING_INDEX0 5
- #define SET(INDEX) SET_INDEX##INDEX
- #define BINDING(INDEX) BINDING_INDEX##INDEX
- #define SET_BIND(NAME,SET,BIND) resource_set_##SET##_bind_##BIND##_##NAME
- #define RESOURCE(NAME,INDEX) SET_BIND(NAME, SET(INDEX), BINDING(INDEX))
- Texture2D<float4> resource_set_10_bind_5_tex;
- float4 main() : SV_Target{
- return RESOURCE(tex, 0)[uint2(1, 2)];
- }
- )",
- &pSource);
- VERIFY_SUCCEEDED(pCompiler->Preprocess(pSource, L"file.hlsl", &expandOption,
- 1, nullptr, 0, nullptr, &pResult));
- HRESULT hrOp;
- VERIFY_SUCCEEDED(pResult->GetStatus(&hrOp));
- VERIFY_SUCCEEDED(hrOp);
- CComPtr<IDxcBlob> pOutText;
- VERIFY_SUCCEEDED(pResult->GetResult(&pOutText));
- std::string text(BlobToUtf8(pOutText));
- VERIFY_ARE_EQUAL_STR(R"(#line 1 "file.hlsl"
- #line 12 "file.hlsl"
- Texture2D<float4> resource_set_10_bind_5_tex;
- float4 main() : SV_Target{
- return resource_set_10_bind_5_tex[uint2(1, 2)];
- }
- )",
- text.c_str());
- }
- TEST_F(CompilerTest, WhenSigMismatchPCFunctionThenFail) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(
- "struct PSSceneIn \n\
- { \n\
- float4 pos : SV_Position; \n\
- float2 tex : TEXCOORD0; \n\
- float3 norm : NORMAL; \n\
- }; \n"
- "struct HSPerPatchData { \n\
- float edges[ 3 ] : SV_TessFactor; \n\
- float inside : SV_InsideTessFactor; \n\
- float foo : FOO; \n\
- }; \n"
- "HSPerPatchData HSPerPatchFunc( InputPatch< PSSceneIn, 3 > points, \n\
- OutputPatch<PSSceneIn, 3> outpoints) { \n\
- HSPerPatchData d = (HSPerPatchData)0; \n\
- d.edges[ 0 ] = points[0].tex.x + outpoints[0].tex.x; \n\
- d.edges[ 1 ] = 1; \n\
- d.edges[ 2 ] = 1; \n\
- d.inside = 1; \n\
- return d; \n\
- } \n"
- "[domain(\"tri\")] \n\
- [partitioning(\"fractional_odd\")] \n\
- [outputtopology(\"triangle_cw\")] \n\
- [patchconstantfunc(\"HSPerPatchFunc\")] \n\
- [outputcontrolpoints(3)] \n"
- "void main(const uint id : SV_OutputControlPointID, \n\
- const InputPatch< PSSceneIn, 3 > points ) { \n\
- } \n"
- , &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
- L"hs_6_0", nullptr, 0, nullptr, 0, nullptr, &pResult));
- std::string failLog(VerifyOperationFailed(pResult));
- VERIFY_ARE_NOT_EQUAL(string::npos, failLog.find(
- "Signature element SV_Position, referred to by patch constant function, is not found in corresponding hull shader output."));
- }
- TEST_F(CompilerTest, ViewID) {
- if (m_ver.SkipDxilVersion(1,1)) return;
- CodeGenTestCheckBatchDir(L"viewid");
- }
- TEST_F(CompilerTest, SubobjectCodeGenErrors) {
- struct SubobjectErrorTestCase {
- const char *shaderText;
- const char *expectedError;
- };
- SubobjectErrorTestCase testCases[] = {
- { "GlobalRootSignature grs;", "1:1: error: subobject needs to be initialized" },
- { "StateObjectConfig soc;", "1:1: error: subobject needs to be initialized" },
- { "LocalRootSignature lrs;", "1:1: error: subobject needs to be initialized" },
- { "SubobjectToExportsAssociation sea;", "1:1: error: subobject needs to be initialized" },
- { "RaytracingShaderConfig rsc;", "1:1: error: subobject needs to be initialized" },
- { "RaytracingPipelineConfig rpc;", "1:1: error: subobject needs to be initialized" },
- { "TriangleHitGroup hitGt;", "1:1: error: subobject needs to be initialized" },
- { "ProceduralPrimitiveHitGroup hitGt;", "1:1: error: subobject needs to be initialized" },
- { "GlobalRootSignature grs2 = {\"\"};", "1:29: error: empty string not expected here" },
- { "LocalRootSignature lrs2 = {\"\"};", "1:28: error: empty string not expected here" },
- { "SubobjectToExportsAssociation sea2 = { \"\", \"x\" };", "1:40: error: empty string not expected here" },
- { "string s; SubobjectToExportsAssociation sea4 = { \"x\", s };", "1:55: error: cannot convert to constant string" },
- { "extern int v; RaytracingPipelineConfig rpc2 = { v + 16 };", "1:49: error: cannot convert to constant unsigned int" },
- { "string s; TriangleHitGroup trHitGt2_8 = { s, \"foo\" };", "1:43: error: cannot convert to constant string" },
- { "string s; ProceduralPrimitiveHitGroup ppHitGt2_8 = { s, \"\", s };", "1:54: error: cannot convert to constant string" },
- { "ProceduralPrimitiveHitGroup ppHitGt2_9 = { \"a\", \"b\", \"\"};", "1:54: error: empty string not expected here" }
- };
- for (unsigned i = 0; i < _countof(testCases); i++) {
- CComPtr<IDxcCompiler> pCompiler;
- CComPtr<IDxcOperationResult> pResult;
- CComPtr<IDxcBlobEncoding> pSource;
- VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
- CreateBlobFromText(testCases[i].shaderText, &pSource);
- VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"", L"lib_6_4", nullptr, 0, nullptr, 0, nullptr, &pResult));
- std::string failLog(VerifyOperationFailed(pResult));
- VERIFY_ARE_NOT_EQUAL(string::npos, failLog.find(testCases[i].expectedError));
- }
- }
- TEST_F(CompilerTest, DebugInfo) {
- CodeGenTestCheckBatchDir(L"debug");
- }
- TEST_F(CompilerTest, QuickTest) {
- CodeGenTestCheckBatchDir(L"quick-test");
- }
- #ifdef _WIN32
- TEST_F(CompilerTest, ManualFileCheckTest) {
- #else
- TEST_F(CompilerTest, DISABLED_ManualFileCheckTest) {
- #endif
- using namespace llvm;
- using namespace WEX::TestExecution;
- WEX::Common::String value;
- VERIFY_SUCCEEDED(RuntimeParameters::TryGetValue(L"InputPath", value));
- std::wstring path = value;
- if (!llvm::sys::path::is_absolute(CW2A(path.c_str()).m_psz)) {
- path = hlsl_test::GetPathToHlslDataFile(path.c_str());
- }
- bool isDirectory;
- {
- // Temporarily setup the filesystem for testing whether the path is a directory.
- // If it is, CodeGenTestCheckBatchDir will create its own instance.
- llvm::sys::fs::MSFileSystem *msfPtr;
- VERIFY_SUCCEEDED(CreateMSFileSystemForDisk(&msfPtr));
- std::unique_ptr<llvm::sys::fs::MSFileSystem> msf(msfPtr);
- llvm::sys::fs::AutoPerThreadSystem pts(msf.get());
- IFTLLVM(pts.error_code());
- isDirectory = llvm::sys::fs::is_directory(CW2A(path.c_str()).m_psz);
- }
- if (isDirectory) {
- CodeGenTestCheckBatchDir(path, /*implicitDir*/ false);
- } else {
- CodeGenTestCheck(path.c_str(), /*implicitDir*/ false);
- }
- }
- TEST_F(CompilerTest, CodeGenBatch) {
- CodeGenTestCheckBatchDir(L"batch");
- }
|