summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/angle/src/d3dcompiler/main.cpp94
-rw-r--r--tests/auto/other/d3dcompiler/tst_d3dcompiler.cpp29
2 files changed, 66 insertions, 57 deletions
diff --git a/src/angle/src/d3dcompiler/main.cpp b/src/angle/src/d3dcompiler/main.cpp
index 70a8f30fb0..3f00df63eb 100644
--- a/src/angle/src/d3dcompiler/main.cpp
+++ b/src/angle/src/d3dcompiler/main.cpp
@@ -161,31 +161,11 @@ static bool loadCompiler()
return bool(compile);
}
-static bool serviceAvailable(const QString &path)
-{
- if (path.isEmpty())
- return false;
-
- // Look for a file, "control", and check if it has been touched in the last 60 seconds
- QFileInfo control(path + QStringLiteral("control"));
- return control.exists() && control.lastModified().secsTo(QDateTime::currentDateTime()) < 60;
-}
-
static QString cacheKeyFor(const void *data)
{
return QString::fromUtf8(QCryptographicHash::hash(reinterpret_cast<const char *>(data), QCryptographicHash::Sha1).toHex());
}
-static QString makePath(const QDir &parent, const QString &child)
-{
- const QString path = parent.absoluteFilePath(child);
- if (!parent.mkpath(child)) {
- qCWarning(QT_D3DCOMPILER) << "Path is inaccessible: " << path;
- return QString();
- }
- return path;
-}
-
} // namespace D3DCompiler
#ifdef __MINGW32__
@@ -200,37 +180,56 @@ HRESULT WINAPI D3DCompile(
const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint,
const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **errorMsgs)
{
- static QString basePath;
+ static bool initialized = false;
+ static bool serviceAvailable = false;
static QString binaryPath;
static QString sourcePath;
- if (basePath.isEmpty()) {
- QDir base;
- if (qEnvironmentVariableIsSet("QT_D3DCOMPILER_DIR"))
- base.setPath(QString::fromUtf8(qgetenv("QT_D3DCOMPILER_DIR")));
- else
- base.setPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
-
- if (!base.exists() && !base.mkdir(QStringLiteral("."))) {
- qCWarning(QT_D3DCOMPILER) << "D3D compiler base directory does not exist: " << QDir::toNativeSeparators(base.path());
+ if (!initialized) {
+ QString base;
+ if (qEnvironmentVariableIsSet("QT_D3DCOMPILER_DIR")) {
+ base = QString::fromLocal8Bit(qgetenv("QT_D3DCOMPILER_DIR"));
} else {
- const QString path = base.absoluteFilePath(QStringLiteral("d3dcompiler/"));
- if (!QFile::exists(path) && !base.mkdir(QStringLiteral("d3dcompiler")))
- qCWarning(QT_D3DCOMPILER) << "D3D compiler path could not be created: " << QDir::toNativeSeparators(path);
- else
- basePath = path;
+ const QString location = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
+ if (!location.isEmpty())
+ base = location + QStringLiteral("/d3dcompiler");
}
- }
- if (!basePath.isEmpty()) {
- binaryPath = D3DCompiler::makePath(basePath, QStringLiteral("binary/"));
- sourcePath = D3DCompiler::makePath(basePath, QStringLiteral("source/"));
+ QDir baseDir(base);
+ if (!base.isEmpty() && baseDir.exists()) {
+ // Check if we have can read/write blobs
+ if (baseDir.exists(QStringLiteral("binary"))) {
+ binaryPath = baseDir.absoluteFilePath(QStringLiteral("binary/"));
+ } else {
+ qCWarning(QT_D3DCOMPILER) << "D3D compiler base directory exists, but the binary directory does not.\n"
+ "Check the compiler service.";
+ }
+
+ // Check if we can write shader source
+ if (baseDir.exists(QStringLiteral("source"))) {
+ sourcePath = baseDir.absoluteFilePath(QStringLiteral("source/"));
+ } else {
+ 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.";
+ }
+
+ initialized = true;
}
- // Check if pre-compiled shader blob is available
const QByteArray sourceData = QByteArray::fromRawData(reinterpret_cast<const char *>(data), data_size);
const QString cacheKey = D3DCompiler::cacheKeyFor(sourceData);
- QFile blob(binaryPath + cacheKey);
- if (!binaryPath.isEmpty() && blob.exists()) {
+
+ // Check if pre-compiled shader blob is available
+ if (!binaryPath.isEmpty()) {
+ QFile blob(binaryPath + cacheKey);
if (blob.open(QFile::ReadOnly)) {
qCDebug(QT_D3DCOMPILER) << "Opening precompiled shader blob at" << blob.fileName();
*shader = new D3DCompiler::Blob(blob.readAll());
@@ -240,13 +239,7 @@ HRESULT WINAPI D3DCompile(
}
// Shader blob is not available, compile with compilation service if possible
- if (D3DCompiler::serviceAvailable(basePath)) {
-
- if (sourcePath.isEmpty()) {
- qCWarning(QT_D3DCOMPILER) << "Compiler service is available, but source directory is not writable.";
- return E_ACCESSDENIED;
- }
-
+ if (!sourcePath.isEmpty() && serviceAvailable) {
// Dump source to source path; wait for blob to appear
QFile source(sourcePath + cacheKey);
if (!source.open(QFile::WriteOnly)) {
@@ -264,6 +257,7 @@ HRESULT WINAPI D3DCompile(
QElapsedTimer timer;
timer.start();
+ QFile blob(binaryPath + cacheKey);
while (!(blob.exists() && blob.open(QFile::ReadOnly)) && timer.elapsed() < timeout)
QThread::msleep(100);
@@ -285,6 +279,8 @@ HRESULT WINAPI D3DCompile(
if (SUCCEEDED(hr) && !binaryPath.isEmpty()) {
const QByteArray blobContents = QByteArray::fromRawData(
reinterpret_cast<const char *>((*shader)->GetBufferPointer()), (*shader)->GetBufferSize());
+
+ QFile blob(binaryPath + cacheKey);
if (blob.open(QFile::WriteOnly) && blob.write(blobContents))
qCDebug(QT_D3DCOMPILER) << "Cached shader blob at" << blob.fileName();
else
diff --git a/tests/auto/other/d3dcompiler/tst_d3dcompiler.cpp b/tests/auto/other/d3dcompiler/tst_d3dcompiler.cpp
index 1a3f4f4592..f86c965d84 100644
--- a/tests/auto/other/d3dcompiler/tst_d3dcompiler.cpp
+++ b/tests/auto/other/d3dcompiler/tst_d3dcompiler.cpp
@@ -153,11 +153,12 @@ QString tst_d3dcompiler::blobPath()
if (qEnvironmentVariableIsSet("QT_D3DCOMPILER_DIR"))
path.setPath(qgetenv("QT_D3DCOMPILER_DIR"));
else
- path.setPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
+ path.setPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QStringLiteral("/d3dcompiler"));
- path.mkdir(QStringLiteral("d3dcompiler"));
+ path.mkdir(QStringLiteral("binary"));
+ path.mkdir(QStringLiteral("source"));
- return path.absoluteFilePath(QStringLiteral("d3dcompiler/"));
+ return path.absolutePath();
}
void tst_d3dcompiler::initTestCase()
@@ -177,7 +178,12 @@ void tst_d3dcompiler::cleanup()
FreeLibrary(d3dcompiler_win);
QDir path(blobPath());
- path.removeRecursively();
+ foreach (const QString &entry, path.entryList(QStringList(), QDir::Files|QDir::NoDotAndDotDot))
+ path.remove(entry);
+ foreach (const QString &entry, path.entryList(QStringList(), QDir::Dirs|QDir::NoDotAndDotDot)) {
+ QDir dir(path.absoluteFilePath(entry + QStringLiteral("/")));
+ dir.removeRecursively();
+ }
}
void tst_d3dcompiler::service_data()
@@ -188,8 +194,9 @@ 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") << tempDir.path().toUtf8() << 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;
}
void tst_d3dcompiler::service()
@@ -254,6 +261,8 @@ void tst_d3dcompiler::service()
void tst_d3dcompiler::offlineCompile()
{
+ qputenv("QT_D3DCOMPILER_DIR", QFile::encodeName(tempDir.path()));
+
for (int i = 0; compilerDlls[i]; ++i) {
d3dcompiler_win = loadLibrary(compilerDlls[i]);
if (d3dcompiler_win)
@@ -271,7 +280,8 @@ void tst_d3dcompiler::offlineCompile()
QVERIFY(shader);
QDir outputPath(blobPath());
- QVERIFY(outputPath.mkpath(QStringLiteral("binary")));
+ QVERIFY(outputPath.exists());
+ QVERIFY(outputPath.exists(QStringLiteral("binary")));
outputPath.cd(QStringLiteral("binary"));
QFile output(outputPath.absoluteFilePath(QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex()));
QVERIFY(output.open(QFile::WriteOnly));
@@ -291,6 +301,8 @@ void tst_d3dcompiler::offlineCompile()
void tst_d3dcompiler::onlineCompile()
{
+ qputenv("QT_D3DCOMPILER_DIR", QFile::encodeName(tempDir.path()));
+
QByteArray data(hlsl);
const QDir path = blobPath();
@@ -313,8 +325,9 @@ void tst_d3dcompiler::onlineCompile()
runner.start();
// Wait for source to appear
- QVERIFY(path.mkpath(QStringLiteral("source")));
- QVERIFY(path.mkpath(QStringLiteral("binary")));
+ QVERIFY(path.exists());
+ QVERIFY(path.exists(QStringLiteral("source")));
+ QVERIFY(path.exists(QStringLiteral("binary")));
const QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex();
QFile input(path.absoluteFilePath(QStringLiteral("source/") + hash));