Skip to content

Commit

Permalink
Allow libdxcompiler.so and dxc to find libdxil.so (#5004)
Browse files Browse the repository at this point in the history
When present in the library search path, linux builds of
libdxcompiler.so and the dxc executable should load libdxil.so and use
it for validation and signing. However, the code to do that was still
searching for dxil.dll even on these platforms.

This change creates appropriate names for the dxcompiler and dxil
libraries for each platform and uses them where appropriate.

In addition, this changes some of the internal interfaces from wide
chars to simple chars as the wide interface wasn't useful here.

(cherry picked from commit ae51624)
  • Loading branch information
pow2clk committed Feb 24, 2023
1 parent d751bd8 commit 6d480fd
Show file tree
Hide file tree
Showing 14 changed files with 68 additions and 36 deletions.
21 changes: 8 additions & 13 deletions include/dxc/Support/dxcapi.use.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,23 @@

namespace dxc {

extern const char* kDxCompilerLib;
extern const char* kDxilLib;

// Helper class to dynamically load the dxcompiler or a compatible libraries.
class DxcDllSupport {
protected:
HMODULE m_dll;
DxcCreateInstanceProc m_createFn;
DxcCreateInstance2Proc m_createFn2;

HRESULT InitializeInternal(LPCWSTR dllName, LPCSTR fnName) {
HRESULT InitializeInternal(LPCSTR dllName, LPCSTR fnName) {
if (m_dll != nullptr) return S_OK;

#ifdef _WIN32
m_dll = LoadLibraryW(dllName);
m_dll = LoadLibraryA(dllName);
#else
char nameStr[256];
std::wcstombs(nameStr, dllName, 256);
m_dll = ::dlopen(nameStr, RTLD_LAZY);
m_dll = ::dlopen(dllName, RTLD_LAZY);
#endif

if (m_dll == nullptr) return HRESULT_FROM_WIN32(GetLastError());
Expand Down Expand Up @@ -86,16 +87,10 @@ class DxcDllSupport {
}

HRESULT Initialize() {
#ifdef _WIN32
return InitializeInternal(L"dxcompiler.dll", "DxcCreateInstance");
#elif __APPLE__
return InitializeInternal(L"libdxcompiler.dylib", "DxcCreateInstance");
#else
return InitializeInternal(L"libdxcompiler.so", "DxcCreateInstance");
#endif
return InitializeInternal(kDxCompilerLib, "DxcCreateInstance");
}

HRESULT InitializeForDll(_In_z_ const wchar_t* dll, _In_z_ const char* entryPoint) {
HRESULT InitializeForDll(_In_z_ LPCSTR dll, _In_z_ LPCSTR entryPoint) {
return InitializeInternal(dll, entryPoint);
}

Expand Down
8 changes: 8 additions & 0 deletions lib/DxcSupport/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,12 @@ add_llvm_library(LLVMDxcSupport
WinFunctions.cpp
)

#generate header with platform-specific library name
configure_file(
${LLVM_MAIN_SRC_DIR}/lib/DxcSupport/SharedLibAffix.inc
SharedLibAffix.h
)

include_directories( ${LLVM_INCLUDE_DIR}/DxcSupport) #needed to find the generated header

add_dependencies(LLVMDxcSupport TablegenHLSLOptions)
3 changes: 1 addition & 2 deletions lib/DxcSupport/HLSLOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1183,9 +1183,8 @@ int SetupDxcDllSupport(const DxcOpts &opts, dxc::DxcDllSupport &dxcSupport,
llvm::raw_ostream &errors) {
if (!opts.ExternalLib.empty()) {
DXASSERT(!opts.ExternalFn.empty(), "else ReadDxcOpts should have failed");
StringRefWide externalLib(opts.ExternalLib);
HRESULT hrLoad =
dxcSupport.InitializeForDll(externalLib, opts.ExternalFn.data());
dxcSupport.InitializeForDll(opts.ExternalLib.data(), opts.ExternalFn.data());
if (DXC_FAILED(hrLoad)) {
errors << "Unable to load support for external DLL " << opts.ExternalLib
<< " with function " << opts.ExternalFn << " - error 0x";
Expand Down
24 changes: 24 additions & 0 deletions lib/DxcSupport/SharedLibAffix.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
///////////////////////////////////////////////////////////////////////////////
// //
// SharedLibAffix.inc //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// Defines shared library prefixes and suffixes for the build platform. //
// //
///////////////////////////////////////////////////////////////////////////////


#pragma once

#cmakedefine CMAKE_SHARED_LIBRARY_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@"
#cmakedefine CMAKE_SHARED_LIBRARY_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@"

#ifndef CMAKE_SHARED_LIBRARY_PREFIX
#define CMAKE_SHARED_LIBRARY_PREFIX
#endif

#ifndef CMAKE_SHARED_LIBRARY_SUFFIX
#define CMAKE_SHARED_LIBRARY_SUFFIX
#endif
4 changes: 4 additions & 0 deletions lib/DxcSupport/dxcapi.use.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
#include "dxc/Support/Unicode.h"
#include "dxc/Support/FileIOHelper.h"
#include "dxc/Support/WinFunctions.h"
#include "SharedLibAffix.h"

namespace dxc {

const char* kDxCompilerLib = CMAKE_SHARED_LIBRARY_PREFIX "dxcompiler" CMAKE_SHARED_LIBRARY_SUFFIX;
const char* kDxilLib = CMAKE_SHARED_LIBRARY_PREFIX "dxil" CMAKE_SHARED_LIBRARY_SUFFIX;

#ifdef _WIN32
static void TrimEOL(_Inout_z_ char *pMsg) {
char *pEnd = pMsg + strlen(pMsg);
Expand Down
2 changes: 1 addition & 1 deletion projects/dxilconv/unittests/DxilConvTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ class DxilConvTest {

bool DxilConvTest::InitSupport() {
if (!m_dllSupport.IsEnabled()) {
VERIFY_SUCCEEDED(m_dllSupport.InitializeForDll(L"dxilconv.dll", "DxcCreateInstance"));
VERIFY_SUCCEEDED(m_dllSupport.InitializeForDll("dxilconv.dll", "DxcCreateInstance"));
}

if (!FindToolInBinDir("%dxbc2dxil", "dxbc2dxil.exe")) {
Expand Down
10 changes: 5 additions & 5 deletions tools/clang/tools/dxclib/dxc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ void WriteDxCompilerVersionInfo(llvm::raw_ostream &OS,
CComPtr<IDxcVersionInfo2> VerInfo2;
#endif // SUPPORT_QUERY_GIT_COMMIT_INFO

const char *dllName = !ExternalLib ? "dxcompiler.dll" : ExternalLib;
const char *dllName = !ExternalLib ? kDxCompilerLib : ExternalLib;
std::string compilerName(dllName);
if (ExternalFn)
compilerName = compilerName + "!" + ExternalFn;
Expand Down Expand Up @@ -1244,17 +1244,17 @@ void WriteDXILVersionInfo(llvm::raw_ostream &OS,
UINT32 validatorMajor, validatorMinor = 0;
VerInfo->GetVersion(&validatorMajor, &validatorMinor);
OS << "; "
<< "dxil.dll"
<< kDxilLib
<< ": " << validatorMajor << "." << validatorMinor;

}
// dxil.dll 1.0 did not support IdxcVersionInfo
else {
OS << "; "
<< "dxil.dll: " << 1 << "." << 0;
<< kDxilLib << ": " << 1 << "." << 0;
}
unsigned int version[4];
if (GetDLLFileVersionInfo("dxil.dll", version)) {
if (GetDLLFileVersionInfo(kDxilLib, version)) {
OS << "(" << version[0] << "." << version[1] << "." << version[2] << "."
<< version[3] << ")";
}
Expand All @@ -1272,7 +1272,7 @@ void DxcContext::GetCompilerVersionInfo(llvm::raw_string_ostream &OS) {

// Print validator if exists
DxcDllSupport DxilSupport;
DxilSupport.InitializeForDll(L"dxil.dll", "DxcCreateInstance");
DxilSupport.InitializeForDll(kDxilLib, "DxcCreateInstance");
WriteDXILVersionInfo(OS, DxilSupport);
}

Expand Down
2 changes: 1 addition & 1 deletion tools/clang/tools/dxcompiler/dxcutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ HRESULT ValidateAndAssembleToContainer(AssembleInputs &inputs) {
if (inputs.pDiag) {
unsigned diagID =
inputs.pDiag->getCustomDiagID(clang::DiagnosticsEngine::Level::Warning,
"DXIL.dll not found. Resulting DXIL will not be "
"DXIL signing library (dxil.dll,libdxil.so) not found. Resulting DXIL will not be "
"signed for use in release environments.\r\n");
inputs.pDiag->Report(diagID);
}
Expand Down
11 changes: 2 additions & 9 deletions tools/clang/tools/dxcompiler/dxillib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ static llvm::sys::Mutex *cs = nullptr;
// This function is to prevent multiple attempts to load dxil.dll
HRESULT DxilLibInitialize() {
cs = new llvm::sys::Mutex;
#if LLVM_ON_WIN32
cs->lock();
g_DllLibResult = g_DllSupport.InitializeForDll(L"dxil.dll", "DxcCreateInstance");
g_DllLibResult = g_DllSupport.InitializeForDll(kDxilLib, "DxcCreateInstance");
cs->unlock();
#endif
return S_OK;
}

Expand All @@ -53,19 +51,14 @@ HRESULT DxilLibCleanup(DxilLibCleanUpType type) {
// If we fail to load dxil.dll, set g_DllLibResult to E_FAIL so that we don't
// have multiple attempts to load dxil.dll
bool DxilLibIsEnabled() {
#if LLVM_ON_WIN32
cs->lock();
if (SUCCEEDED(g_DllLibResult)) {
if (!g_DllSupport.IsEnabled()) {
g_DllLibResult = g_DllSupport.InitializeForDll(L"dxil.dll", "DxcCreateInstance");
g_DllLibResult = g_DllSupport.InitializeForDll(kDxilLib, "DxcCreateInstance");
}
}
cs->unlock();
return SUCCEEDED(g_DllLibResult);
#else
g_DllLibResult = (HRESULT)-1;
return false;
#endif
}


Expand Down
3 changes: 2 additions & 1 deletion tools/clang/tools/dxopt/dxopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ int __cdecl wmain(int argc, const wchar_t **argv_) {

if (externalLib) {
CW2A externalFnA(externalFn, CP_UTF8);
IFT(g_DxcSupport.InitializeForDll(externalLib, externalFnA));
CW2A externalLibA(externalFn, CP_UTF8);
IFT(g_DxcSupport.InitializeForDll(externalLibA, externalFnA));
}
else {
IFT(g_DxcSupport.Initialize());
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/tools/dxrfallbackcompiler/dxcutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ HRESULT ValidateAndAssembleToContainer(AssembleInputs &inputs) {
if (inputs.pDiag) {
unsigned diagID =
inputs.pDiag->getCustomDiagID(clang::DiagnosticsEngine::Level::Warning,
"DXIL.dll not found. Resulting DXIL will not be "
"DXIL signing library (dxil.dll,libdxil.so) not found. Resulting DXIL will not be "
"signed for use in release environments.\r\n");
inputs.pDiag->Report(diagID);
}
Expand Down
4 changes: 2 additions & 2 deletions tools/clang/tools/dxrfallbackcompiler/dxillib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ bool DxilLibIsEnabled() {
EnterCriticalSection(&cs);
if (SUCCEEDED(g_DllLibResult)) {
if (!g_DllSupport.IsEnabled()) {
g_DllLibResult = g_DllSupport.InitializeForDll(L"dxil.dll", "DxcCreateInstance");
g_DllLibResult = g_DllSupport.InitializeForDll(kDxilLib, "DxcCreateInstance");
}
}
LeaveCriticalSection(&cs);
Expand All @@ -65,4 +65,4 @@ HRESULT DxilLibCreateInstance(_In_ REFCLSID rclsid, _In_ REFIID riid, _In_ IUnkn
LeaveCriticalSection(&cs);
}
return hr;
}
}
2 changes: 1 addition & 1 deletion tools/clang/unittests/DxrFallback/test_DxrFallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class Tester
, m_path(path)
{
dxc::EnsureEnabled(m_dxcSupport);
m_dxrFallbackSupport.InitializeForDll(L"DxrFallbackCompiler.dll", "DxcCreateDxrFallbackCompiler");
m_dxrFallbackSupport.InitializeForDll("DxrFallbackCompiler.dll", "DxcCreateDxrFallbackCompiler");
}

void setFiles(const std::vector<std::string>& files)
Expand Down
8 changes: 8 additions & 0 deletions tools/clang/unittests/HLSL/ShaderOpTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
#include <xmllite.h>
#pragma comment(lib, "xmllite.lib")


// Duplicate definition of kDxCompilerLib to that in dxcapi.use.cpp
// These tests need the header, but don't want to depend on the source
// Since this is windows only, we only need the windows variant
namespace dxc {
const char* kDxCompilerLib = "dxcompiler.dll";
}

///////////////////////////////////////////////////////////////////////////////
// Useful helper functions.

Expand Down

0 comments on commit 6d480fd

Please sign in to comment.