d3dcompiler_qt: Remove control file semantics

This simplifies the compiler control semantics by always using the
packaged compiler if it is available. With no packaged compiler, the
service is assumed to be running if the directory structure is present.
Use of a packaged library can be overridden by setting the environment
variable QT_D3DCOMPILER_DISABLE_DLL to 1.

When the runtime compiler is used, the source will no longer be
logged, and the compilation output will no longer be cached.

Change-Id: Ib07f517e7043d7785bdfa9da55abd34df518eeed
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
This commit is contained in:
Andrew Knight 2014-03-13 18:58:12 +02:00 committed by The Qt Project
parent bcfc68f9cd
commit 42afaa992a
2 changed files with 25 additions and 41 deletions

View File

@ -180,22 +180,32 @@ HRESULT WINAPI D3DCompile(
const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **errorMsgs)
{
// Shortcut to compile using the runtime compiler if it is available
static bool compilerAvailable =
!qgetenv("QT_D3DCOMPILER_DISABLE_DLL").toInt() && D3DCompiler::loadCompiler();
if (compilerAvailable) {
HRESULT hr = D3DCompiler::compile(data, data_size, filename, defines, include, entrypoint,
target, sflags, eflags, shader, errorMsgs);
return hr;
}
static bool initialized = false;
static bool serviceAvailable = false;
static QString binaryPath;
static QString sourcePath;
if (!initialized) {
QString base;
if (qEnvironmentVariableIsSet("QT_D3DCOMPILER_DIR")) {
if (qEnvironmentVariableIsSet("QT_D3DCOMPILER_DIR"))
base = QString::fromLocal8Bit(qgetenv("QT_D3DCOMPILER_DIR"));
} else {
if (base.isEmpty()) {
const QString location = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
if (!location.isEmpty())
base = location + QStringLiteral("/d3dcompiler");
}
// Unless the service has run, this directory won't exist.
QDir baseDir(base);
if (!base.isEmpty() && baseDir.exists()) {
if (baseDir.exists()) {
// Check if we have can read/write blobs
if (baseDir.exists(QStringLiteral("binary"))) {
binaryPath = baseDir.absoluteFilePath(QStringLiteral("binary/"));
@ -211,14 +221,10 @@ HRESULT WINAPI D3DCompile(
qCWarning(QT_D3DCOMPILER) << "D3D compiler base directory exists, but the source directory does not.\n"
"Check the compiler service.";
}
// Look for a file, "control", and check if it has been touched in the last 60 seconds
QFileInfo control(baseDir.absoluteFilePath(QStringLiteral("control")));
serviceAvailable = control.exists() && control.lastModified().secsTo(QDateTime::currentDateTime()) < 60;
} else {
qCWarning(QT_D3DCOMPILER) << "D3D compiler base directory does not exist:"
<< QDir::toNativeSeparators(base)
<< "\nThe compiler service won't be used.";
<< "\nCheck that the compiler service is running.";
}
initialized = true;
@ -259,8 +265,8 @@ HRESULT WINAPI D3DCompile(
}
}
// Shader blob is not available, compile with compilation service if possible
if (!sourcePath.isEmpty() && serviceAvailable) {
// Shader blob is not available; write out shader source
if (!sourcePath.isEmpty()) {
// Dump source to source path; wait for blob to appear
QFile source(sourcePath + fileName);
if (!source.open(QFile::WriteOnly)) {
@ -292,24 +298,6 @@ HRESULT WINAPI D3DCompile(
return E_ABORT;
}
// Fall back to compiler DLL
if (D3DCompiler::loadCompiler()) {
HRESULT hr = D3DCompiler::compile(data, data_size, filename, defines, include, entrypoint,
target, sflags, eflags, shader, errorMsgs);
// Cache shader
if (SUCCEEDED(hr) && !binaryPath.isEmpty()) {
const QByteArray blobContents = QByteArray::fromRawData(
reinterpret_cast<const char *>((*shader)->GetBufferPointer()), (*shader)->GetBufferSize());
QFile blob(binaryPath + fileName);
if (blob.open(QFile::WriteOnly) && blob.write(blobContents))
qCDebug(QT_D3DCOMPILER) << "Cached shader blob at" << blob.fileName();
else
qCDebug(QT_D3DCOMPILER) << "Unable to write shader blob at" << blob.fileName();
}
return hr;
}
*errorMsgs = new D3DCompiler::Blob("Unable to load D3D compiler DLL.");
*errorMsgs = new D3DCompiler::Blob("No shader compiler or service could be found.");
return E_FAIL;
}

View File

@ -170,6 +170,7 @@ void tst_d3dcompiler::init()
{
qunsetenv("QT_D3DCOMPILER_DIR");
qunsetenv("QT_D3DCOMPILER_TIMEOUT");
qunsetenv("QT_D3DCOMPILER_DISABLE_DLL");
}
void tst_d3dcompiler::cleanup()
@ -195,8 +196,8 @@ void tst_d3dcompiler::service_data()
// Don't test the default case, as it would clutter the AppData directory
//QTest::newRow("default") << QByteArrayLiteral("") << true << E_ABORT;
QTest::newRow("temporary") << QFile::encodeName(tempDir.path()) << true << E_ABORT;
QTest::newRow("invalid") << QByteArrayLiteral("ZZ:\\") << false << S_OK;
QTest::newRow("empty") << QByteArrayLiteral("") << false << S_OK;
QTest::newRow("invalid") << QByteArrayLiteral("ZZ:\\") << false << E_FAIL;
QTest::newRow("empty") << QByteArrayLiteral("") << false << E_FAIL;
}
void tst_d3dcompiler::service()
@ -205,16 +206,12 @@ void tst_d3dcompiler::service()
QFETCH(bool, exists);
QFETCH(HRESULT, result);
qputenv("QT_D3DCOMPILER_DIR", compilerDir);
qputenv("QT_D3DCOMPILER_DISABLE_DLL", QByteArrayLiteral("1"));
const QDir path = blobPath();
if (exists) {
// Activate service
QVERIFY(path.exists());
QFile control(path.absoluteFilePath(QStringLiteral("control")));
QVERIFY(control.open(QFile::WriteOnly));
control.close();
QVERIFY(control.exists());
} else {
QVERIFY(!path.exists());
}
@ -262,6 +259,7 @@ void tst_d3dcompiler::service()
void tst_d3dcompiler::offlineCompile()
{
qputenv("QT_D3DCOMPILER_DIR", QFile::encodeName(tempDir.path()));
qputenv("QT_D3DCOMPILER_DISABLE_DLL", QByteArrayLiteral("1"));
for (int i = 0; compilerDlls[i]; ++i) {
d3dcompiler_win = loadLibrary(compilerDlls[i]);
@ -302,6 +300,8 @@ void tst_d3dcompiler::offlineCompile()
void tst_d3dcompiler::onlineCompile()
{
qputenv("QT_D3DCOMPILER_DIR", QFile::encodeName(tempDir.path()));
qputenv("QT_D3DCOMPILER_TIMEOUT", QByteArray::number(3000));
qputenv("QT_D3DCOMPILER_DISABLE_DLL", QByteArrayLiteral("1"));
QByteArray data(hlsl);
@ -309,10 +309,6 @@ void tst_d3dcompiler::onlineCompile()
// Activate service
QVERIFY(path.exists());
QFile control(path.absoluteFilePath(QStringLiteral("control")));
QVERIFY(control.open(QFile::WriteOnly));
control.close();
QVERIFY(control.exists());
d3dcompiler_qt = loadLibrary(D3DCOMPILER_DLL);
QVERIFY(d3dcompiler_qt);