Match SPIR-V version as much as possible when rebuilding shaders

This commit is contained in:
baldurk
2023-08-22 13:38:50 +01:00
parent 02933fb6a6
commit e7430226e9
9 changed files with 60 additions and 10 deletions
+2
View File
@@ -241,6 +241,8 @@ Other custom tools can be configured, but for those the command line arguments m
* ``{entry_point}`` will be replaced by the entry point name, only when compiling a shader.
* ``{glsl_stage4}`` will be replaced by the glsl stage short-hand, one of: vert, tesc, tese, geom, frag, or comp.
* ``{hlsl_stage2}`` will be replaced by the hlsl stage short-hand, one of: vs, hs, ds, gs, ps, or cs.
* ``{spirv_ver}`` will be replaced by the SPIR-V version in use, e.g. spirv1.2 or spirv1.6.
* ``{vulkan_ver}`` will be replaced by the Vulkan-identified SPIR-V version in use, e.g. vulkan1.0 or vulkan1.3. This value may be lossy, and will pick the next *lowest* version that compiles with a given SPIR-V version. E.g. SPIR-V 1.2 was not used by a vulkan version, so will be rounded down to vulkan1.0.
You must also select the input and output format of the tool, such as HLSL input and SPIR-V output. This will be used to match the tool against a given need at runtime with different types of shaders.
@@ -699,15 +699,15 @@ rdcstr ShaderProcessingTool::DefaultArguments() const
else if(tool == KnownShaderTool::spirv_dis || tool == KnownShaderTool::spirv_dis_OpenGL)
return "--no-color";
else if(tool == KnownShaderTool::glslangValidatorGLSL)
return "-g -V -S {glsl_stage4}";
return "-g -V -S {glsl_stage4} --target-env {spirv_ver}";
else if(tool == KnownShaderTool::glslangValidatorGLSL_OpenGL)
return "-g -G -S {glsl_stage4}";
return "-g -G -S {glsl_stage4} --target-env {spirv_ver}";
else if(tool == KnownShaderTool::glslangValidatorHLSL)
return "-D -g -V -S {glsl_stage4} -e {entry_point}";
return "-D -g -V -S {glsl_stage4} -e {entry_point} --target-env {spirv_ver}";
else if(tool == KnownShaderTool::spirv_as || tool == KnownShaderTool::spirv_as_OpenGL)
return "";
else if(tool == KnownShaderTool::dxcSPIRV)
return "-T {hlsl_stage2}_6_0 -E {entry_point} -spirv";
return "-T {hlsl_stage2}_6_0 -E {entry_point} -spirv -fspv-target-env={vulkan_ver}";
else if(tool == KnownShaderTool::dxcDXIL)
return "-T {hlsl_stage2}_6_0 -E {entry_point}";
else if(tool == KnownShaderTool::fxc)
+3 -1
View File
@@ -113,6 +113,8 @@ struct ShaderProcessingTool
:param str source: The source code, preprocessed into a single file.
:param str entryPoint: The name of the entry point in the shader to compile.
:param renderdoc.ShaderStage stage: The pipeline stage that this shader represents.
:param str spirvVer: The version of SPIR-V in use for this shader, or an empty string for defaults.
The current version can be obtained from reflection data via the ``@spirver`` compile flag.
:param str args: arguments to pass to the tool. The default arguments can be obtained using
:meth:`DefaultArguments` which can then be customised as desired. Passing an empty string uses the
default arguments.
@@ -120,7 +122,7 @@ struct ShaderProcessingTool
:rtype: ShaderToolOutput
)");
ShaderToolOutput CompileShader(QWidget *window, rdcstr source, rdcstr entryPoint,
ShaderStage stage, rdcstr args) const;
ShaderStage stage, rdcstr spirvVer, rdcstr args) const;
private:
DOCUMENT("Internal function");
@@ -41,6 +41,22 @@ static QString tmpPath(const QString &filename)
return QDir(QDir::tempPath()).absoluteFilePath(filename);
}
QString vulkanVerForSpirVer(QString spirvVer)
{
if(spirvVer == lit("spirv1.0") || spirvVer == lit("spirv1.1") || spirvVer == lit("spirv1.2"))
return lit("vulkan1.0");
if(spirvVer == lit("spirv1.3"))
return lit("vulkan1.1");
if(spirvVer == lit("spirv1.4"))
return lit("vulkan1.1spirv1.4");
if(spirvVer == lit("spirv1.5"))
return lit("vulkan1.2");
if(spirvVer == lit("spirv1.6"))
return lit("vulkan1.3");
else
return lit("vulkan1.3");
}
static ShaderToolOutput RunTool(const ShaderProcessingTool &tool, QWidget *window,
QString input_file, QString output_file, QStringList &argList)
{
@@ -243,6 +259,11 @@ ShaderToolOutput ShaderProcessingTool::DisassembleShader(QWidget *window,
input_file = tmpPath(lit("shader_input"));
QString spirvVer = lit("spirv1.0");
for(const ShaderCompileFlag &flag : shaderDetails->debugInfo.compileFlags.flags)
if(flag.name == "@spirver")
spirvVer = flag.value;
// replace arguments after expansion to avoid problems with quoting paths etc
for(QString &arg : argList)
{
@@ -262,6 +283,10 @@ ShaderToolOutput ShaderProcessingTool::DisassembleShader(QWidget *window,
arg.replace(0, 13, glsl_stage4[int(shaderDetails->stage)]);
if(arg.left(13) == lit("{hlsl_stage2}"))
arg.replace(0, 13, hlsl_stage2[int(shaderDetails->stage)]);
if(arg.left(11) == lit("{spirv_ver}"))
arg.replace(0, 11, spirvVer);
if(arg.left(12) == lit("{vulkan_ver}"))
arg.replace(0, 12, vulkanVerForSpirVer(spirvVer));
}
QFile binHandle(input_file);
@@ -287,7 +312,7 @@ ShaderToolOutput ShaderProcessingTool::DisassembleShader(QWidget *window,
ShaderToolOutput ShaderProcessingTool::CompileShader(QWidget *window, rdcstr source,
rdcstr entryPoint, ShaderStage stage,
rdcstr arguments) const
rdcstr spirvVer, rdcstr arguments) const
{
QStringList argList = ParseArgsList(arguments.isEmpty() ? DefaultArguments() : arguments);
// always append IO arguments for known tools, so we read/write to our own files and override any
@@ -298,6 +323,9 @@ ShaderToolOutput ShaderProcessingTool::CompileShader(QWidget *window, rdcstr sou
input_file = tmpPath(lit("shader_input"));
if(spirvVer.isEmpty())
spirvVer = "spirv1.0";
// replace arguments after expansion to avoid problems with quoting paths etc
for(QString &arg : argList)
{
@@ -313,6 +341,10 @@ ShaderToolOutput ShaderProcessingTool::CompileShader(QWidget *window, rdcstr sou
arg.replace(0, 13, glsl_stage4[int(stage)]);
if(arg.left(13) == lit("{hlsl_stage2}"))
arg.replace(0, 13, hlsl_stage2[int(stage)]);
if(arg.left(11) == lit("{spirv_ver}"))
arg.replace(0, 11, spirvVer);
if(arg.left(12) == lit("{vulkan_ver}"))
arg.replace(0, 12, vulkanVerForSpirVer(spirvVer));
}
QFile binHandle(input_file);
@@ -88,7 +88,7 @@ ShaderToolOutput ShaderProcessingTool::DisassembleShader(QWidget *window,
ShaderToolOutput ShaderProcessingTool::CompileShader(QWidget *window, rdcstr source,
rdcstr entryPoint, ShaderStage stage,
rdcstr arguments) const
rdcstr spirvVer, rdcstr arguments) const
{
return {};
}
@@ -1043,7 +1043,13 @@ IShaderViewer *PipelineStateViewer::EditDecompiledSource(const ShaderProcessingT
rdcstrpairs files;
files.push_back(rdcpair<rdcstr, rdcstr>("decompiled", source));
IShaderViewer *sv = EditShader(id, shaderDetails->stage, shaderDetails->entryPoint, {},
ShaderCompileFlags flags;
for(const ShaderCompileFlag &flag : shaderDetails->debugInfo.compileFlags.flags)
if(flag.name == "@spirver")
flags.flags.push_back(flag);
IShaderViewer *sv = EditShader(id, shaderDetails->stage, shaderDetails->entryPoint, flags,
KnownShaderTool::Unknown, tool.output, files);
sv->ShowErrors(out.log);
+6 -1
View File
@@ -6029,6 +6029,11 @@ void ShaderViewer::on_refresh_clicked()
rdcarray<ShaderEncoding> accepted = m_Ctx.TargetShaderEncodings();
rdcstr spirvVer = "spirv1.0";
for(const ShaderCompileFlag &flag : m_Flags.flags)
if(flag.name == "@spirver")
spirvVer = flag.value;
if(m_CustomShader || (accepted.indexOf(encoding) >= 0 &&
ui->compileTool->currentIndex() == ui->compileTool->count() - 1))
{
@@ -6041,7 +6046,7 @@ void ShaderViewer::on_refresh_clicked()
if(QString(tool.name) == ui->compileTool->currentText())
{
ShaderToolOutput out = tool.CompileShader(this, source, ui->entryFunc->text(), m_Stage,
ui->toolCommandLine->toPlainText());
spirvVer, ui->toolCommandLine->toPlainText());
ShowErrors(out.log);
+1 -1
View File
@@ -4415,7 +4415,7 @@ void TextureViewer::reloadCustomShaders(const QString &filter)
}
ShaderToolOutput out =
tool.CompileShader(this, source, "main", ShaderStage::Pixel, "");
tool.CompileShader(this, source, "main", ShaderStage::Pixel, "", "");
errors = out.log;
@@ -936,6 +936,9 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st
if(!cmdline.empty())
reflection.debugInfo.compileFlags.flags = {{"@cmdline", cmdline}};
reflection.debugInfo.compileFlags.flags.push_back(
{"@spirver", StringFormat::Fmt("spirv%d.%d", m_MajorVersion, m_MinorVersion)});
{
auto it = funcToDebugFunc.find(entry->id);
if(it != funcToDebugFunc.end())