From 203dca84348c6abfdad7828176bb03a288acf5b2 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 22 Dec 2017 16:42:36 +0000 Subject: [PATCH] Split out invocation of SPIRVDisassembler into member function --- qrenderdoc/Code/Interface/PersistantConfig.h | 10 +- .../Code/Interface/SPIRVDisassembler.cpp | 119 ++++++++++++++++++ .../Code/pyrenderdoc/qrenderdoc_stub.cpp | 6 + .../VulkanPipelineStateViewer.cpp | 86 +------------ .../PipelineState/VulkanPipelineStateViewer.h | 2 - qrenderdoc/qrenderdoc.pro | 1 + qrenderdoc/qrenderdoc_local.vcxproj | 1 + qrenderdoc/qrenderdoc_local.vcxproj.filters | 3 + 8 files changed, 140 insertions(+), 88 deletions(-) create mode 100644 qrenderdoc/Code/Interface/SPIRVDisassembler.cpp diff --git a/qrenderdoc/Code/Interface/PersistantConfig.h b/qrenderdoc/Code/Interface/PersistantConfig.h index 7554605c2..3edb8cb2c 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.h +++ b/qrenderdoc/Code/Interface/PersistantConfig.h @@ -48,13 +48,21 @@ struct SPIRVDisassembler return args < o.args; return false; } - DOCUMENT("The human-readable name of the program."); rdcstr name; DOCUMENT("The path to the executable to run for this program."); rdcstr executable; DOCUMENT("The command line argmuents to pass to the program."); rdcstr args; + + DOCUMENT(R"(Runs this disassembler for a given shader reflection. + +:param QWidget window: A handle to the window to use when showing a progress bar or error messages. +:param ~renderdoc.ShaderReflection shader: The shader to disassemble. +:return: The disassembly, or an empty string if something went wrong. +:rtype: ``str`` +)"); + QString DisassembleShader(QWidget *window, const ShaderReflection *reflection) const; }; DECLARE_REFLECTION_STRUCT(SPIRVDisassembler); diff --git a/qrenderdoc/Code/Interface/SPIRVDisassembler.cpp b/qrenderdoc/Code/Interface/SPIRVDisassembler.cpp new file mode 100644 index 000000000..b35dfbe22 --- /dev/null +++ b/qrenderdoc/Code/Interface/SPIRVDisassembler.cpp @@ -0,0 +1,119 @@ +#/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2016-2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include +#include +#include "Code/QRDUtils.h" +#include "QRDInterface.h" + +QString SPIRVDisassembler::DisassembleShader(QWidget *window, + const ShaderReflection *shaderDetails) const +{ + if(executable.isEmpty()) + return QString(); + + QString spv_bin_file = QDir(QDir::tempPath()).absoluteFilePath(lit("spv_bin.spv")); + + QFile binHandle(spv_bin_file); + if(binHandle.open(QFile::WriteOnly | QIODevice::Truncate)) + { + binHandle.write( + QByteArray((const char *)shaderDetails->rawBytes.data(), shaderDetails->rawBytes.count())); + binHandle.close(); + } + else + { + RDDialog::critical( + window, QApplication::translate("SPIRVDisassembler", "Error writing temp file"), + QApplication::translate("SPIRVDisassembler", "Couldn't write temporary SPIR-V file %1.") + .arg(spv_bin_file)); + return QString(); + } + + if(!QString(args).contains(lit("{spv_bin}"))) + { + RDDialog::critical( + window, QApplication::translate("SPIRVDisassembler", "Wrongly configured disassembler"), + QApplication::translate( + "SPIRVDisassembler", + "Please use {spv_bin} in the disassembler arguments to specify the input file.")); + return QString(); + } + + QString glsl; + + LambdaThread *thread = new LambdaThread([this, window, &glsl, spv_bin_file]() { + QString spv_disas_file = QDir(QDir::tempPath()).absoluteFilePath(lit("spv_disas.txt")); + + QString expandedargs = args; + + bool writesToFile = expandedargs.contains(lit("{spv_disas}")); + + expandedargs.replace(lit("{spv_bin}"), spv_bin_file); + expandedargs.replace(lit("{spv_disas}"), spv_disas_file); + + QStringList argList = ParseArgsList(expandedargs); + + QProcess process; + process.start(executable, argList); + process.waitForFinished(); + + if(process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) + { + GUIInvoke::call([window]() { + RDDialog::critical( + window, QApplication::translate("SPIRVDisassembler", "Error running disassembler"), + QApplication::translate( + "SPIRVDisassembler", + "There was an error invoking the external SPIR-V disassembler.")); + }); + } + + if(writesToFile) + { + QFile outputHandle(spv_disas_file); + if(outputHandle.open(QFile::ReadOnly | QIODevice::Text)) + { + glsl = QString::fromUtf8(outputHandle.readAll()); + outputHandle.close(); + } + } + else + { + glsl = QString::fromUtf8(process.readAll()); + } + + QFile::remove(spv_bin_file); + QFile::remove(spv_disas_file); + }); + thread->start(); + + ShowProgressDialog(window, QApplication::translate("SPIRVDisassembler", + "Please wait - running external disassembler"), + [thread]() { return !thread->isRunning(); }); + + thread->deleteLater(); + + return glsl; +} diff --git a/qrenderdoc/Code/pyrenderdoc/qrenderdoc_stub.cpp b/qrenderdoc/Code/pyrenderdoc/qrenderdoc_stub.cpp index 9db782096..7f46c99d5 100644 --- a/qrenderdoc/Code/pyrenderdoc/qrenderdoc_stub.cpp +++ b/qrenderdoc/Code/pyrenderdoc/qrenderdoc_stub.cpp @@ -61,3 +61,9 @@ PyObject *PythonContext::QtObjectToPython(const char *typeName, QObject *object) { return NULL; } + +QString SPIRVDisassembler::DisassembleShader(QWidget *window, + const ShaderReflection *shaderDetails) const +{ + return QString(); +} diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index fd3be1abf..84edcee19 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -2343,7 +2343,7 @@ void VulkanPipelineStateViewer::shaderEdit_clicked() QString glsl; if(!m_Ctx.Config().SPIRVDisassemblers.isEmpty()) - glsl = disassembleSPIRV(shaderDetails); + glsl = m_Ctx.Config().SPIRVDisassemblers[0].DisassembleShader(this, shaderDetails); if(!glsl.isEmpty()) { @@ -2368,90 +2368,6 @@ void VulkanPipelineStateViewer::shaderEdit_clicked() m_Common.EditShader(stage->stage, stage->resourceId, shaderDetails, entryFunc, files); } -QString VulkanPipelineStateViewer::disassembleSPIRV(const ShaderReflection *shaderDetails) -{ - QString glsl; - - const SPIRVDisassembler &disasm = m_Ctx.Config().SPIRVDisassemblers[0]; - - if(disasm.executable.isEmpty()) - return QString(); - - QString spv_bin_file = QDir(QDir::tempPath()).absoluteFilePath(lit("spv_bin.spv")); - - QFile binHandle(spv_bin_file); - if(binHandle.open(QFile::WriteOnly | QIODevice::Truncate)) - { - binHandle.write( - QByteArray((const char *)shaderDetails->rawBytes.data(), shaderDetails->rawBytes.count())); - binHandle.close(); - } - else - { - RDDialog::critical(this, tr("Error writing temp file"), - tr("Couldn't write temporary SPIR-V file %1.").arg(spv_bin_file)); - return QString(); - } - - if(!QString(disasm.args).contains(lit("{spv_bin}"))) - { - RDDialog::critical( - this, tr("Wrongly configured disassembler"), - tr("Please use {spv_bin} in the disassembler arguments to specify the input file.")); - return QString(); - } - - LambdaThread *thread = new LambdaThread([this, &glsl, &disasm, spv_bin_file]() { - QString spv_disas_file = QDir(QDir::tempPath()).absoluteFilePath(lit("spv_disas.txt")); - - QString args = disasm.args; - - bool writesToFile = args.contains(lit("{spv_disas}")); - - args.replace(lit("{spv_bin}"), spv_bin_file); - args.replace(lit("{spv_disas}"), spv_disas_file); - - QStringList argList = ParseArgsList(args); - - QProcess process; - process.start(disasm.executable, argList); - process.waitForFinished(); - - if(process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) - { - GUIInvoke::call([this]() { - RDDialog::critical(this, tr("Error running disassembler"), - tr("There was an error invoking the external SPIR-V disassembler.")); - }); - } - - if(writesToFile) - { - QFile outputHandle(spv_disas_file); - if(outputHandle.open(QFile::ReadOnly | QIODevice::Text)) - { - glsl = QString::fromUtf8(outputHandle.readAll()); - outputHandle.close(); - } - } - else - { - glsl = QString::fromUtf8(process.readAll()); - } - - QFile::remove(spv_bin_file); - QFile::remove(spv_disas_file); - }); - thread->start(); - - ShowProgressDialog(this, tr("Please wait - running external disassembler"), - [thread]() { return !thread->isRunning(); }); - - thread->deleteLater(); - - return glsl; -} - void VulkanPipelineStateViewer::shaderSave_clicked() { const VKPipe::Shader *stage = stageForSender(qobject_cast(QObject::sender())); diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h index 075b81373..c1c4cc8a3 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.h @@ -107,8 +107,6 @@ private: QString formatMembers(int indent, const QString &nameprefix, const rdcarray &vars); const VKPipe::Shader *stageForSender(QWidget *widget); - QString disassembleSPIRV(const ShaderReflection *shaderDetails); - template void setViewDetails(RDTreeWidgetItem *node, const viewType &view, TextureDescription *tex); diff --git a/qrenderdoc/qrenderdoc.pro b/qrenderdoc/qrenderdoc.pro index 4857abe0b..0376bab41 100644 --- a/qrenderdoc/qrenderdoc.pro +++ b/qrenderdoc/qrenderdoc.pro @@ -165,6 +165,7 @@ SOURCES += Code/qrenderdoc.cpp \ Code/Interface/QRDInterface.cpp \ Code/Interface/Analytics.cpp \ Code/Interface/CommonPipelineState.cpp \ + Code/Interface/SPIRVDisassembler.cpp \ Code/Interface/PersistantConfig.cpp \ Code/Interface/RemoteHost.cpp \ Styles/StyleData.cpp \ diff --git a/qrenderdoc/qrenderdoc_local.vcxproj b/qrenderdoc/qrenderdoc_local.vcxproj index d5d3ab6e0..bc19b9082 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj +++ b/qrenderdoc/qrenderdoc_local.vcxproj @@ -566,6 +566,7 @@ + Create diff --git a/qrenderdoc/qrenderdoc_local.vcxproj.filters b/qrenderdoc/qrenderdoc_local.vcxproj.filters index 6c414817e..abc106382 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj.filters +++ b/qrenderdoc/qrenderdoc_local.vcxproj.filters @@ -702,6 +702,9 @@ Windows\Dialogs + + Code\Interface +