diff --git a/tools/clang/test/CMakeLists.txt b/tools/clang/test/CMakeLists.txt index ba3843f8d3..51edbd7670 100644 --- a/tools/clang/test/CMakeLists.txt +++ b/tools/clang/test/CMakeLists.txt @@ -77,7 +77,11 @@ endif() set(CLANG_TEST_DEPS dxc dxa dxopt dxl dxv dxr dxcompiler clang-tblgen llvm-config opt FileCheck count not ClangUnitTests) if (WIN32) list(APPEND CLANG_TEST_DEPS - dxc_batch ExecHLSLTests + dxc_batch ExecHLSLTests dxildll + ) +else() +list(APPEND CLANG_TEST_DEPS + dxildll ) endif() add_custom_target(clang-test-depends DEPENDS ${CLANG_TEST_DEPS}) diff --git a/tools/clang/tools/CMakeLists.txt b/tools/clang/tools/CMakeLists.txt index 595687c23d..9991de0308 100644 --- a/tools/clang/tools/CMakeLists.txt +++ b/tools/clang/tools/CMakeLists.txt @@ -27,6 +27,7 @@ add_subdirectory(dxcompiler) add_subdirectory(dxclib) add_subdirectory(dxc) add_subdirectory(dxcvalidator) +add_subdirectory(dxildll) add_subdirectory(dxa) add_subdirectory(dxopt) add_subdirectory(dxl) diff --git a/tools/clang/tools/dxcvalidator/CMakeLists.txt b/tools/clang/tools/dxcvalidator/CMakeLists.txt index 4991c9f97b..28e56ab7ac 100644 --- a/tools/clang/tools/dxcvalidator/CMakeLists.txt +++ b/tools/clang/tools/dxcvalidator/CMakeLists.txt @@ -9,6 +9,8 @@ set( LLVM_LINK_COMPONENTS DxilContainer DxilHash DxilValidation + DxilRootSignature + HLSL # for gcc link error on AreDxilResourcesDense and DxilSignatureAllocator which are used in DxilValidation Option # option library Support # just for assert and raw streams ) diff --git a/tools/clang/tools/dxildll/CMakeLists.txt b/tools/clang/tools/dxildll/CMakeLists.txt new file mode 100644 index 0000000000..67a24d1107 --- /dev/null +++ b/tools/clang/tools/dxildll/CMakeLists.txt @@ -0,0 +1,86 @@ +# Copyright (C) Microsoft Corporation. All rights reserved. +# This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. + +set(SHARED_LIBRARY TRUE) + +set(DXCComponents + LLVMBitWriter + LLVMDxcSupport + LLVMDXIL + LLVMDxilContainer + LLVMDxilHash + LLVMDxilRootSignature + LLVMDxilValidation + LLVMHLSL # for AreDxilResourcesDense and DxilSignatureAllocator which are used in DxilValidation + LLVMMSSupport + LLVMSupport + LLVMTransformUtils + LLVMAnalysis + LLVMDxcBindingTable + LLVMipa +) + +foreach(C ${DXCComponents}) +if (WIN32) + list(APPEND DXCLibs ${C}) + list(APPEND DXCDependencies ${C}) +else() + list(APPEND DXCLibs ${C}) + list(APPEND DXCDependencies ${C}) +endif() +endforeach(C ${DXCComponents}) + +include_directories( + ${LLVM_SOURCE_DIR}/tools/clang/tools/dxcvalidator + ${LLVM_BINARY_DIR}/projects/include +) + +set(sources + dxildll.cpp + dxildll.def + dxcvalidator.cpp +) + +if (WIN32) +add_clang_library(dxildll SHARED ${sources}) +list(APPEND DXCLibs + kernel32.lib + atls.lib + advapi32.lib + ole32.lib) +else() +add_clang_library(dxildll SHARED ${sources}) +endif() + +target_link_libraries(dxildll PRIVATE + ${DXCLibs} + clangBasic # for clang::getGitCommitHash. + dxcvalidator +) + +if (WIN32) +add_dependencies(dxildll + ${DXCDependencies} + DxcEtw + DxcRuntimeEtw +) +else() +add_dependencies(dxildll + ${DXCDependencies} +) +endif() + +if (WIN32) + get_target_property(sources dxildll SOURCES) + + list(APPEND sources dxildll.rc) + set_target_properties(${target_name} PROPERTIES SOURCES "${sources}") + + set_property(SOURCE dxildll.rc PROPERTY COMPILE_DEFINITIONS "INCLUDE_HLSL_VERSION_FILE=1") + set_property(SOURCE dxildll.rc PROPERTY COMPILE_OPTIONS "/I" "${HLSL_VERSION_LOCATION}" "/I" "${LLVM_MAIN_SRC_DIR}") +endif() + +set_target_properties(dxildll + PROPERTIES + OUTPUT_NAME "dxil" +) diff --git a/tools/clang/tools/dxildll/dxcvalidator.cpp b/tools/clang/tools/dxildll/dxcvalidator.cpp new file mode 100644 index 0000000000..5048356618 --- /dev/null +++ b/tools/clang/tools/dxildll/dxcvalidator.cpp @@ -0,0 +1,140 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// dxcvalidator.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. // +// // +// Implements the DirectX Validator object, including hashing support. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "dxcvalidator.h" + +#include "dxc/Support/WinIncludes.h" + +#include "dxc/Support/Global.h" +#include "dxc/Support/microcom.h" +#include "dxc/dxcapi.h" + +#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO +#include "clang/Basic/Version.h" +#endif // SUPPORT_QUERY_GIT_COMMIT_INFO + +using namespace llvm; +using namespace hlsl; + +class DxcValidator : public IDxcValidator2, +#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO + public IDxcVersionInfo2 +#else + public IDxcVersionInfo +#endif // SUPPORT_QUERY_GIT_COMMIT_INFO +{ +private: + DXC_MICROCOM_TM_REF_FIELDS() + +public: + DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() + DXC_MICROCOM_TM_CTOR(DxcValidator) + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, + void **ppvObject) override { + + return DoBasicQueryInterface(this, iid, ppvObject); + } + + HRESULT STDMETHODCALLTYPE Validate( + IDxcBlob *pShader, // Shader to validate. + UINT32 Flags, // Validation flags. + IDxcOperationResult * + *ppResult // Validation output status, buffer, and errors + ) override; + + // IDxcValidator2 + HRESULT STDMETHODCALLTYPE ValidateWithDebug( + IDxcBlob *pShader, // Shader to validate. + UINT32 Flags, // Validation flags. + DxcBuffer *pDebugModule, // Debug module bitcode to provide line numbers + IDxcOperationResult * + *ppResult // Validation output status, buffer, and errors + ) override; + + // IDxcVersionInfo + HRESULT STDMETHODCALLTYPE GetVersion(UINT32 *pMajor, UINT32 *pMinor) override; + HRESULT STDMETHODCALLTYPE GetFlags(UINT32 *pFlags) override; + +#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO + // IDxcVersionInfo2 + HRESULT STDMETHODCALLTYPE GetCommitInfo(UINT32 *pCommitCount, + char **pCommitHash) override; +#endif +}; + +// Compile a single entry point to the target shader model +HRESULT STDMETHODCALLTYPE DxcValidator::Validate( + IDxcBlob *pShader, // Shader to validate. + UINT32 Flags, // Validation flags. + IDxcOperationResult * + *ppResult // Validation output status, buffer, and errors +) { + return hlsl::validateWithDebug(pShader, Flags, nullptr, ppResult); +} + +HRESULT STDMETHODCALLTYPE DxcValidator::ValidateWithDebug( + IDxcBlob *pShader, // Shader to validate. + UINT32 Flags, // Validation flags. + DxcBuffer *pOptDebugBitcode, // Optional debug module bitcode to provide + // line numbers + IDxcOperationResult * + *ppResult // Validation output status, buffer, and errors +) { + return hlsl::validateWithDebug(pShader, Flags, pOptDebugBitcode, ppResult); +} + +HRESULT STDMETHODCALLTYPE DxcValidator::GetVersion(UINT32 *pMajor, + UINT32 *pMinor) { + return hlsl::getValidationVersion(pMajor, pMinor); +} + +#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO +HRESULT STDMETHODCALLTYPE DxcValidator::GetCommitInfo(UINT32 *pCommitCount, + char **pCommitHash) { + if (pCommitCount == nullptr || pCommitHash == nullptr) + return E_INVALIDARG; + + char *const hash = (char *)CoTaskMemAlloc( + 8 + 1); // 8 is guaranteed by utils/GetCommitInfo.py + if (hash == nullptr) + return E_OUTOFMEMORY; + std::strcpy(hash, clang::getGitCommitHash()); + + *pCommitHash = hash; + *pCommitCount = clang::getGitCommitCount(); + + return S_OK; +} +#endif // SUPPORT_QUERY_GIT_COMMIT_INFO + +HRESULT STDMETHODCALLTYPE DxcValidator::GetFlags(UINT32 *pFlags) { + DxcThreadMalloc TM(m_pMalloc); + if (pFlags == nullptr) + return E_INVALIDARG; + *pFlags = DxcVersionInfoFlags_None; +#ifdef _DEBUG + *pFlags |= DxcVersionInfoFlags_Debug; +#endif + return S_OK; +} + +HRESULT CreateDxcValidator(REFIID riid, LPVOID *ppv) { + try { + CComPtr result( + DxcValidator::Alloc(DxcGetThreadMallocNoRef())); + if (result.p == nullptr) + return E_OUTOFMEMORY; + return result.p->QueryInterface(riid, ppv); + } + CATCH_CPP_RETURN_HRESULT(); +} diff --git a/tools/clang/tools/dxildll/dxildll.cpp b/tools/clang/tools/dxildll/dxildll.cpp new file mode 100644 index 0000000000..12ca2026ca --- /dev/null +++ b/tools/clang/tools/dxildll/dxildll.cpp @@ -0,0 +1,152 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// dxildll.cpp // +// Copyright (C) Microsoft. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +// Implements the DxcCreateInstanceand DllMain functions // +// for the dxil.dll module. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _WIN32 +#define DXC_API_IMPORT +#else +#define DXC_API_IMPORT __attribute__((visibility("default"))) +#endif + +#include "dxc/DxilContainer/DxcContainerBuilder.h" +#include "dxc/Support/Global.h" +#include "dxc/Support/WinIncludes.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ManagedStatic.h" +#include +#ifdef _WIN32 +#include "Tracing/DxcRuntimeEtw.h" +#include "dxc/Tracing/dxcetw.h" +#endif + +#include "dxc/dxcisense.h" +#include "dxc/dxctools.h" + +HRESULT CreateDxcValidator(REFIID, LPVOID *); + +// C++ exception specification ignored except to indicate a function is not +// __declspec(nothrow) +static HRESULT InitMaybeFail() throw() { + bool MemSetup = false; + HRESULT HR = (DxcInitThreadMalloc()); + if (!DXC_FAILED(HR)) { + DxcSetThreadMallocToDefault(); + MemSetup = true; + if (::llvm::sys::fs::SetupPerThreadFileSystem()) + HR = E_FAIL; + } + if (FAILED(HR)) { + if (MemSetup) { + DxcClearThreadMalloc(); + DxcCleanupThreadMalloc(); + } + } else + DxcClearThreadMalloc(); + return HR; +} + +#if defined(LLVM_ON_UNIX) +HRESULT __attribute__((constructor)) DllMain() { return InitMaybeFail(); } + +void __attribute__((destructor)) DllShutdown() { + DxcSetThreadMallocToDefault(); + ::llvm::sys::fs::CleanupPerThreadFileSystem(); + ::llvm::llvm_shutdown(); + DxcClearThreadMalloc(); + DxcCleanupThreadMalloc(); +} +#else + +#pragma warning(disable : 4290) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD Reason, LPVOID) { + if (Reason == DLL_PROCESS_ATTACH) { + EventRegisterMicrosoft_Windows_DxcRuntime_API(); + DxcRuntimeEtw_DxcRuntimeInitialization_Start(); + HRESULT HR = InitMaybeFail(); + DxcRuntimeEtw_DxcRuntimeInitialization_Stop(HR); + if (FAILED(HR)) { + EventUnregisterMicrosoft_Windows_DxcRuntime_API(); + return HR; + } + } else if (Reason == DLL_PROCESS_DETACH) { + DxcRuntimeEtw_DxcRuntimeShutdown_Start(); + DxcSetThreadMallocToDefault(); + ::llvm::sys::fs::CleanupPerThreadFileSystem(); + ::llvm::llvm_shutdown(); + DxcClearThreadMalloc(); + DxcCleanupThreadMalloc(); + DxcRuntimeEtw_DxcRuntimeShutdown_Stop(S_OK); + EventUnregisterMicrosoft_Windows_DxcRuntime_API(); + } + + return TRUE; +} + +void *__CRTDECL operator new(std::size_t Size) noexcept(false) { + void *PTR = DxcNew(Size); + if (PTR == nullptr) + throw std::bad_alloc(); + return PTR; +} +void *__CRTDECL operator new(std::size_t Size, const std::nothrow_t &) throw() { + return DxcNew(Size); +} +void __CRTDECL operator delete(void *PTR) throw() { DxcDelete(PTR); } +void __CRTDECL operator delete(void *PTR, + const std::nothrow_t ¬hrow_constant) throw() { + DxcDelete(PTR); +} +#endif + +static HRESULT CreateDxcHashingContainerBuilder(REFIID RRID, LPVOID *V) { + // Call dxil.dll's containerbuilder + *V = nullptr; + CComPtr Result( + DxcContainerBuilder::Alloc(DxcGetThreadMallocNoRef())); + if (nullptr == Result.p) + return E_OUTOFMEMORY; + + Result->Init(); + return Result->QueryInterface(RRID, V); +} + +static HRESULT ThreadMallocDxcCreateInstance(REFCLSID RCLSID, REFIID RIID, + LPVOID *V) { + *V = nullptr; + if (IsEqualCLSID(RCLSID, CLSID_DxcValidator)) + return CreateDxcValidator(RIID, V); + if (IsEqualCLSID(RCLSID, CLSID_DxcContainerBuilder)) + return CreateDxcHashingContainerBuilder(RIID, V); + return REGDB_E_CLASSNOTREG; +} + +DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance(REFCLSID RCLSID, REFIID RIID, + LPVOID *V) { + HRESULT HR = S_OK; + DxcEtw_DXCompilerCreateInstance_Start(); + DxcThreadMalloc TM(nullptr); + HR = ThreadMallocDxcCreateInstance(RCLSID, RIID, V); + DxcEtw_DXCompilerCreateInstance_Stop(HR); + return HR; +} + +DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance2(IMalloc *Malloc, + REFCLSID RCLSID, + REFIID RIID, LPVOID *V) { + if (V == nullptr) + return E_POINTER; + HRESULT HR = S_OK; + DxcEtw_DXCompilerCreateInstance_Start(); + DxcThreadMalloc TM(Malloc); + HR = ThreadMallocDxcCreateInstance(RCLSID, RIID, V); + DxcEtw_DXCompilerCreateInstance_Stop(HR); + return HR; +} diff --git a/tools/clang/tools/dxildll/dxildll.def b/tools/clang/tools/dxildll/dxildll.def new file mode 100644 index 0000000000..4a333d2c48 --- /dev/null +++ b/tools/clang/tools/dxildll/dxildll.def @@ -0,0 +1,5 @@ +LIBRARY dxil + +EXPORTS + DxcCreateInstance + DxcCreateInstance2 diff --git a/tools/clang/tools/dxildll/dxildll.rc b/tools/clang/tools/dxildll/dxildll.rc new file mode 100644 index 0000000000..7f77c543af --- /dev/null +++ b/tools/clang/tools/dxildll/dxildll.rc @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. + +#define RC_FILE_DESCRIPTION "DirectX IL for Redistribution" +#define RC_INTERNAL_NAME "DirectX IL for Redistribution" +#define RC_ORIGINAL_FILENAME "dxil.dll" + +#include "resources\windows_version_resource.rc"