Add loading of custom shipped d3dcompiler_47.dll.
This commit is contained in:
parent
9176409d97
commit
46a49caa21
4 changed files with 243 additions and 2 deletions
82
validate_d3d_compiler.cmake
Normal file
82
validate_d3d_compiler.cmake
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# This file is part of Desktop App Toolkit,
|
||||
# a set of libraries for developing nice desktop applications.
|
||||
#
|
||||
# For license and copyright information please follow this link:
|
||||
# https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
|
||||
function(validate_d3d_error text)
|
||||
if (NOT DESKTOP_APP_SPECIAL_TARGET STREQUAL "")
|
||||
message(FATAL_ERROR ${text})
|
||||
else()
|
||||
message(WARNING ${text})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(validate_d3d_compiler target_name)
|
||||
if (build_win64)
|
||||
set(modules_subdir x64)
|
||||
else()
|
||||
set(modules_subdir x86)
|
||||
endif()
|
||||
set(modules_hash_loc ${CMAKE_BINARY_DIR}/modules/${modules_subdir})
|
||||
set(modules_debug_loc ${CMAKE_BINARY_DIR}/Debug/modules/${modules_subdir})
|
||||
set(modules_release_loc ${CMAKE_BINARY_DIR}/Release/modules/${modules_subdir})
|
||||
|
||||
set(key_path ${modules_hash_loc}/d3d/d3dcompiler_47)
|
||||
set(module_debug_path ${modules_debug_loc}/d3d)
|
||||
set(module_release_path ${modules_release_loc}/d3d)
|
||||
|
||||
set(key "")
|
||||
if (EXISTS ${key_path})
|
||||
file(READ ${key_path} key)
|
||||
endif()
|
||||
|
||||
if (NOT "$ENV{WindowsSdkDir}" STREQUAL "")
|
||||
set(windows_sdk_loc $ENV{WindowsSdkDir} CACHE INTERNAL "Windows SDK Path" FORCE)
|
||||
endif()
|
||||
|
||||
string(LENGTH "${key}" key_length)
|
||||
if (NOT "${key_length}" STREQUAL "32"
|
||||
OR NOT EXISTS ${module_debug_path}/d3dcompiler_47.dll
|
||||
OR NOT EXISTS ${module_release_path}/d3dcompiler_47.dll)
|
||||
|
||||
if ("${windows_sdk_loc}" STREQUAL "")
|
||||
validate_d3d_error("Could not find Windows SDK.")
|
||||
return()
|
||||
endif()
|
||||
set(sdk_compiler ${windows_sdk_loc}/Redist/D3D/${modules_subdir}/d3dcompiler_47.dll)
|
||||
|
||||
find_package(Python REQUIRED)
|
||||
execute_process(
|
||||
COMMAND
|
||||
${Python_EXECUTABLE}
|
||||
${cmake_helpers_loc}/validate_d3d_compiler.py
|
||||
${sdk_compiler}
|
||||
OUTPUT_VARIABLE key
|
||||
ERROR_VARIABLE error
|
||||
)
|
||||
if (NOT "${error}" STREQUAL "")
|
||||
validate_d3d_error(${error})
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY ${modules_debug_loc}/d3d)
|
||||
file(COPY ${sdk_compiler} DESTINATION ${module_debug_path})
|
||||
|
||||
file(MAKE_DIRECTORY ${modules_release_loc}/d3d)
|
||||
file(COPY ${sdk_compiler} DESTINATION ${module_release_path})
|
||||
|
||||
file(MAKE_DIRECTORY ${modules_hash_loc}/d3d)
|
||||
file(WRITE ${key_path} ${key})
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${target_name}
|
||||
PRIVATE
|
||||
DESKTOP_APP_D3DCOMPILER_HASH=${key}
|
||||
)
|
||||
|
||||
target_link_libraries(${target_name}
|
||||
PRIVATE
|
||||
desktop-app::external_openssl
|
||||
)
|
||||
endfunction()
|
||||
35
validate_d3d_compiler.py
Normal file
35
validate_d3d_compiler.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# This file is part of Desktop App Toolkit,
|
||||
# a set of libraries for developing nice desktop applications.
|
||||
#
|
||||
# For license and copyright information please follow this link:
|
||||
# https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
|
||||
from __future__ import print_function
|
||||
import sys, os, re, hashlib
|
||||
|
||||
def error(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
from win32api import GetFileVersionInfo
|
||||
except ImportError:
|
||||
error('Python module "pywin32" is not installed.\n\nTry "' + sys.executable + ' -m pip install pywin32".')
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
error('Expected input path to "d3dcompiler_47.dll".')
|
||||
|
||||
inputPath = sys.argv[1]
|
||||
if not os.path.exists(inputPath):
|
||||
error('File "' + inputPath + '" doesn\'t exist.')
|
||||
|
||||
info = GetFileVersionInfo(inputPath, '\\')
|
||||
version = [ info['FileVersionMS'] // 65536, info['FileVersionMS'] % 65536, info['FileVersionLS'] // 65536, info['FileVersionLS'] % 65536 ]
|
||||
if (version != [10, 0, 20348, 1 ]):
|
||||
error('Bad "d3dcompiler_47.dll" version: ' + '.'.join(str(x) for x in version))
|
||||
|
||||
bufferSize = 1024 * 1024
|
||||
sha256 = hashlib.sha256()
|
||||
|
||||
with open(inputPath, 'rb') as f:
|
||||
print(hashlib.sha256(f.read()).hexdigest())
|
||||
|
|
@ -12,3 +12,5 @@ nice_target_sources(win_directx_helper ${CMAKE_CURRENT_SOURCE_DIR}
|
|||
PRIVATE
|
||||
win_directx_helper.cpp
|
||||
)
|
||||
|
||||
validate_d3d_compiler(win_directx_helper)
|
||||
|
|
|
|||
|
|
@ -7,15 +7,43 @@
|
|||
|
||||
#include <d3d9.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#define LOAD_SYMBOL(handle, func) LoadSymbol(handle, #func, func)
|
||||
|
||||
namespace DirectX {
|
||||
namespace {
|
||||
|
||||
constexpr auto kMaxPathLong = 32767;
|
||||
|
||||
using Handle = HINSTANCE;
|
||||
|
||||
// d3dcompiler_47.dll
|
||||
|
||||
HRESULT (__stdcall *D3DCompile)(
|
||||
LPCVOID pSrcData,
|
||||
SIZE_T SrcDataSize,
|
||||
LPCSTR pFileName,
|
||||
CONST D3D_SHADER_MACRO* pDefines,
|
||||
ID3DInclude* pInclude,
|
||||
LPCSTR pEntrypoint,
|
||||
LPCSTR pTarget,
|
||||
UINT Flags1,
|
||||
UINT Flags2,
|
||||
ID3DBlob** ppCode,
|
||||
ID3DBlob** ppErrorMsgs);
|
||||
|
||||
HRESULT (__stdcall *D3DDisassemble)(
|
||||
_In_reads_bytes_(SrcDataSize) LPCVOID pSrcData,
|
||||
_In_ SIZE_T SrcDataSize,
|
||||
_In_ UINT Flags,
|
||||
_In_opt_ LPCSTR szComments,
|
||||
_Out_ ID3DBlob** ppDisassembly);
|
||||
|
||||
// d3d9.dll
|
||||
|
||||
IDirect3D9 * (__stdcall *Direct3DCreate9)(UINT SDKVersion);
|
||||
|
|
@ -56,6 +84,100 @@ inline bool LoadSymbol(Handle handle, const char *name, Function &func) {
|
|||
return (func != nullptr);
|
||||
}
|
||||
|
||||
// For win_directx_helper.
|
||||
std::string FileSha256(const wchar_t *path) {
|
||||
using uchar = unsigned char;
|
||||
constexpr auto kLimit = 10 * 1024 * 1024;
|
||||
auto buffer = std::vector<uchar>(kLimit);
|
||||
auto size = DWORD();
|
||||
|
||||
const auto file = CreateFile(
|
||||
path,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr);
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
return {};
|
||||
}
|
||||
const auto read = ReadFile(file, buffer.data(), kLimit, &size, nullptr);
|
||||
CloseHandle(file);
|
||||
|
||||
if (!read || !size || size >= kLimit) {
|
||||
return {};
|
||||
}
|
||||
auto binary = std::array<uchar, SHA256_DIGEST_LENGTH>{};
|
||||
SHA256(buffer.data(), size, binary.data());
|
||||
const auto hex = [](uchar value) {
|
||||
return (value >= 10) ? ('a' + (value - 10)) : ('0' + value);
|
||||
};
|
||||
auto result = std::string();
|
||||
result.reserve(binary.size() * 2);
|
||||
auto index = 0;
|
||||
for (const auto byte : binary) {
|
||||
result.push_back(hex(byte / 16));
|
||||
result.push_back(hex(byte % 16));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ResolveD3DCompiler(const wchar_t *path) {
|
||||
const auto d3dcompiler = LoadLibrary(path);
|
||||
return true
|
||||
&& LOAD_SYMBOL(d3dcompiler, D3DCompile)
|
||||
&& LOAD_SYMBOL(d3dcompiler, D3DDisassemble);
|
||||
}
|
||||
|
||||
bool ResolveD3DCompiler() {
|
||||
static const auto loaded = [] {
|
||||
#ifdef DESKTOP_APP_D3DCOMPILER_HASH
|
||||
auto exePath = std::array<WCHAR, kMaxPathLong + 1>{ 0 };
|
||||
const auto exeLength = GetModuleFileName(
|
||||
nullptr,
|
||||
exePath.data(),
|
||||
kMaxPathLong + 1);
|
||||
if (!exeLength || exeLength >= kMaxPathLong + 1) {
|
||||
return false;
|
||||
}
|
||||
const auto exe = std::wstring(exePath.data());
|
||||
const auto last1 = exe.find_last_of('\\');
|
||||
const auto last2 = exe.find_last_of('/');
|
||||
const auto last = std::max(
|
||||
(last1 == std::wstring::npos) ? -1 : int(last1),
|
||||
(last2 == std::wstring::npos) ? -1 : int(last2));
|
||||
if (last < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined _WIN32
|
||||
const auto arch = L"x86";
|
||||
#elif defined _WIN64 // _WIN32
|
||||
const auto arch = L"x64";
|
||||
#else // _WIN32 || _WIN64
|
||||
#error "Invalid configuration."
|
||||
#endif // _WIN32 || _WIN64
|
||||
|
||||
#define DESKTOP_APP_STRINGIFY2(x) #x
|
||||
#define DESKTOP_APP_STRINGIFY(x) DESKTOP_APP_STRINGIFY2(x)
|
||||
const auto hash = DESKTOP_APP_STRINGIFY(DESKTOP_APP_D3DCOMPILER_HASH);
|
||||
#undef DESKTOP_APP_STRINGIFY
|
||||
#undef DESKTOP_APP_STRINGIFY2
|
||||
|
||||
const auto compiler = exe.substr(0, last + 1)
|
||||
+ L"modules\\" + arch + L"\\d3d\\d3dcompiler_47.dll";
|
||||
const auto path = compiler.c_str();
|
||||
if (FileSha256(path) == hash && ResolveD3DCompiler(path)) {
|
||||
return true;
|
||||
}
|
||||
#endif // DESKTOP_APP_D3DCOMPILER_HASH
|
||||
|
||||
return ResolveD3DCompiler(L"d3dcompiler_47.dll");
|
||||
}();
|
||||
return loaded;
|
||||
}
|
||||
|
||||
bool ResolveD3D9() {
|
||||
static const auto loaded = [] {
|
||||
const auto d3d9 = LoadLibrary(L"d3d9.dll");
|
||||
|
|
@ -63,7 +185,7 @@ bool ResolveD3D9() {
|
|||
LOAD_SYMBOL(d3d9, D3DPERF_EndEvent);
|
||||
LOAD_SYMBOL(d3d9, D3DPERF_SetMarker);
|
||||
LOAD_SYMBOL(d3d9, D3DPERF_GetStatus);
|
||||
return true
|
||||
return ResolveD3DCompiler()
|
||||
&& LOAD_SYMBOL(d3d9, Direct3DCreate9);
|
||||
}();
|
||||
return loaded;
|
||||
|
|
@ -72,7 +194,7 @@ bool ResolveD3D9() {
|
|||
bool ResolveD3D11() {
|
||||
static const auto loaded = [] {
|
||||
const auto d3d11 = LoadLibrary(L"d3d11.dll");
|
||||
return true
|
||||
return ResolveD3DCompiler()
|
||||
&& LOAD_SYMBOL(d3d11, D3D11CreateDevice);
|
||||
}();
|
||||
return loaded;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue