mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-20 11:01:08 +00:00
Allow using shader processing tools for custom shaders
* This is primarily useful for HLSL on Vulkan, but could be used with any other combination. If multiple tools can perform the conversion, the highest priority one is used.
This commit is contained in:
27 files changed
+607
-421
No files matched your search
@@ -6,7 +6,9 @@ This page details how to set up a custom shader for visualisation. This can be u
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The basic process of setting up the custom shader involves writing a ``.hlsl`` or ``.glsl`` file that will be compiled and used by RenderDoc. Note that the type used matches the API used, and RenderDoc will automatically list only the hlsl shaders you have if you load a log with D3D11 or D3D12, and glsl for OpenGL or Vulkan.
|
||||
The basic process of setting up the custom shader involves writing a shader file that will be compiled and used by RenderDoc. Note that you can use any language that is either natively accepted by the graphics API used, or any language that can be compiled to an accepted shader.
|
||||
|
||||
For example on D3D11 or D3D12, hlsl is the only language usable by default, but on Vulkan you can use hlsl or glsl as long as a compiler is available.
|
||||
|
||||
There are several special global variables that can be specified and will be filled in with values by RenderDoc.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ How to edit a custom shader
|
||||
|
||||
:doc:`Custom visualisation shaders <how_custom_visualisation>` allow you to define your own transformation on any texture you're viewing before it is displayed. Mostly this is useful for decoding packed or custom-format data, or displaying some data in a more visually intuitive fashion.
|
||||
|
||||
These shaders live as ``.hlsl`` or ``.glsl`` files in the application storage directory ( ``%APPDATA%/qrenderdoc/`` on windows or ``~/.local/share/qrenderdoc`` elsewhere), and can be edited in your editor of choice, any changes saved will be reloaded. Note however that there is currently no way to see the compile warnings or errors produced when editing externally.
|
||||
These shaders live as files in the application storage directory ( ``%APPDATA%/qrenderdoc/`` on windows or ``~/.local/share/qrenderdoc`` elsewhere), and can be edited in your editor of choice, any changes saved will be reloaded. Note however that there is currently no way to see the compile warnings or errors produced when editing externally.
|
||||
|
||||
To edit a shader inside RenderDoc simply click the edit button |page_white_edit| when you have selected your custom shader for use. This will launch a new window with the custom shader and any changes you make to this shader will be saved to the file and compiled and reflected in the texture viewer as long as you have that custom shader selected.
|
||||
|
||||
|
||||
+321
-198
@@ -193,6 +193,8 @@ void ShaderViewer::editShader(bool customShader, ShaderStage stage, const QStrin
|
||||
m_Stage = stage;
|
||||
m_Flags = flags;
|
||||
|
||||
m_CustomShader = customShader;
|
||||
|
||||
// set up compilation parameters
|
||||
for(ShaderEncoding i : values<ShaderEncoding>())
|
||||
if(IsTextRepresentation(i) || shaderEncoding == i)
|
||||
@@ -2611,7 +2613,9 @@ void ShaderViewer::AddWatch(const rdcstr &variable)
|
||||
|
||||
int ShaderViewer::snippetPos()
|
||||
{
|
||||
if(IsD3D(m_Ctx.APIProps().pipelineType))
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
|
||||
if(encoding != ShaderEncoding::GLSL)
|
||||
return 0;
|
||||
|
||||
if(m_Scintillas.isEmpty())
|
||||
@@ -2626,283 +2630,402 @@ int ShaderViewer::snippetPos()
|
||||
return ver.second + 1;
|
||||
}
|
||||
|
||||
void ShaderViewer::insertVulkanUBO()
|
||||
void ShaderViewer::insertSnippet(const QString &text)
|
||||
{
|
||||
if(text.isEmpty())
|
||||
return;
|
||||
|
||||
if(m_Scintillas.isEmpty())
|
||||
return;
|
||||
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"layout(binding = 0, std140) uniform RENDERDOC_Uniforms\n"
|
||||
"{\n"
|
||||
" uvec4 TexDim;\n"
|
||||
" uint SelectedMip;\n"
|
||||
" int TextureType;\n"
|
||||
" uint SelectedSliceFace;\n"
|
||||
" int SelectedSample;\n"
|
||||
" uvec4 YUVDownsampleRate;\n"
|
||||
" uvec4 YUVAChannels;\n"
|
||||
"} RENDERDOC;\n\n");
|
||||
m_Scintillas[0]->insertText(snippetPos(), text.toUtf8().data());
|
||||
|
||||
m_Scintillas[0]->setSelection(0, 0);
|
||||
}
|
||||
|
||||
QString ShaderViewer::vulkanUBO()
|
||||
{
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
|
||||
if(encoding == ShaderEncoding::GLSL)
|
||||
{
|
||||
return lit(R"(
|
||||
layout(binding = 0, std140) uniform RENDERDOC_Uniforms
|
||||
{
|
||||
uvec4 TexDim;
|
||||
uint SelectedMip;
|
||||
int TextureType;
|
||||
uint SelectedSliceFace;
|
||||
int SelectedSample;
|
||||
uvec4 YUVDownsampleRate;
|
||||
uvec4 YUVAChannels;
|
||||
} RENDERDOC;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(encoding == ShaderEncoding::HLSL)
|
||||
{
|
||||
return lit(R"(
|
||||
cbuffer RENDERDOC_Constants : register(b0)
|
||||
{
|
||||
uint4 RENDERDOC_TexDim;
|
||||
uint RENDERDOC_SelectedMip;
|
||||
int RENDERDOC_TextureType;
|
||||
uint RENDERDOC_SelectedSliceFace;
|
||||
int RENDERDOC_SelectedSample;
|
||||
uint4 RENDERDOC_YUVDownsampleRate;
|
||||
uint4 RENDERDOC_YUVAChannels;
|
||||
};
|
||||
|
||||
)");
|
||||
}
|
||||
else if(encoding == ShaderEncoding::SPIRVAsm)
|
||||
{
|
||||
return lit("; Can't insert snippets for SPIR-V ASM");
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void ShaderViewer::snippet_textureDimensions()
|
||||
{
|
||||
if(m_Scintillas.isEmpty())
|
||||
return;
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
GraphicsAPI api = m_Ctx.APIProps().localRenderer;
|
||||
|
||||
GraphicsAPI api = m_Ctx.APIProps().pipelineType;
|
||||
QString text;
|
||||
|
||||
if(IsD3D(api))
|
||||
if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// xyz == width, height, depth. w == # mips\n"
|
||||
"uint4 RENDERDOC_TexDim;\n"
|
||||
"uint4 RENDERDOC_YUVDownsampleRate;\n"
|
||||
"uint4 RENDERDOC_YUVAChannels; \n\n");
|
||||
text = vulkanUBO();
|
||||
}
|
||||
else if(api == GraphicsAPI::OpenGL)
|
||||
else if(encoding == ShaderEncoding::HLSL)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// xyz == width, height, depth. w == # mips\n"
|
||||
"uniform uvec4 RENDERDOC_TexDim;\n\n");
|
||||
text = lit(R"(
|
||||
// xyz == width, height, depth. w == # mips
|
||||
uint4 RENDERDOC_TexDim;
|
||||
uint4 RENDERDOC_YUVDownsampleRate;
|
||||
uint4 RENDERDOC_YUVAChannels;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(api == GraphicsAPI::Vulkan)
|
||||
else if(encoding == ShaderEncoding::GLSL)
|
||||
{
|
||||
insertVulkanUBO();
|
||||
text = lit(R"(
|
||||
// xyz == width, height, depth. w == # mips
|
||||
uniform uvec4 RENDERDOC_TexDim;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(encoding == ShaderEncoding::SPIRVAsm)
|
||||
{
|
||||
text = lit("; Can't insert snippets for SPIR-V ASM");
|
||||
}
|
||||
|
||||
m_Scintillas[0]->setSelection(0, 0);
|
||||
insertSnippet(text);
|
||||
}
|
||||
|
||||
void ShaderViewer::snippet_selectedMip()
|
||||
{
|
||||
if(m_Scintillas.isEmpty())
|
||||
return;
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
GraphicsAPI api = m_Ctx.APIProps().localRenderer;
|
||||
|
||||
GraphicsAPI api = m_Ctx.APIProps().pipelineType;
|
||||
QString text;
|
||||
|
||||
if(IsD3D(api))
|
||||
if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// selected mip in UI\n"
|
||||
"uint RENDERDOC_SelectedMip;\n\n");
|
||||
text = vulkanUBO();
|
||||
}
|
||||
else if(api == GraphicsAPI::OpenGL)
|
||||
else if(encoding == ShaderEncoding::HLSL)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// selected mip in UI\n"
|
||||
"uniform uint RENDERDOC_SelectedMip;\n\n");
|
||||
text = lit(R"(
|
||||
// selected mip in UI
|
||||
uint RENDERDOC_SelectedMip;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(api == GraphicsAPI::Vulkan)
|
||||
else if(encoding == ShaderEncoding::GLSL)
|
||||
{
|
||||
insertVulkanUBO();
|
||||
text = lit(R"(
|
||||
// selected mip in UI
|
||||
uniform uint RENDERDOC_SelectedMip;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(encoding == ShaderEncoding::SPIRVAsm)
|
||||
{
|
||||
text = lit("; Can't insert snippets for SPIR-V ASM");
|
||||
}
|
||||
|
||||
m_Scintillas[0]->setSelection(0, 0);
|
||||
insertSnippet(text);
|
||||
}
|
||||
|
||||
void ShaderViewer::snippet_selectedSlice()
|
||||
{
|
||||
if(m_Scintillas.isEmpty())
|
||||
return;
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
GraphicsAPI api = m_Ctx.APIProps().localRenderer;
|
||||
|
||||
GraphicsAPI api = m_Ctx.APIProps().pipelineType;
|
||||
QString text;
|
||||
|
||||
if(IsD3D(api))
|
||||
if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// selected array slice or cubemap face in UI\n"
|
||||
"uint RENDERDOC_SelectedSliceFace;\n\n");
|
||||
text = vulkanUBO();
|
||||
}
|
||||
else if(api == GraphicsAPI::OpenGL)
|
||||
else if(encoding == ShaderEncoding::HLSL)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// selected array slice or cubemap face in UI\n"
|
||||
"uniform uint RENDERDOC_SelectedSliceFace;\n\n");
|
||||
text = lit(R"(
|
||||
// selected array slice or cubemap face in UI
|
||||
uint RENDERDOC_SelectedSliceFace;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(api == GraphicsAPI::Vulkan)
|
||||
else if(encoding == ShaderEncoding::GLSL)
|
||||
{
|
||||
insertVulkanUBO();
|
||||
text = lit(R"(
|
||||
// selected array slice or cubemap face in UI
|
||||
uniform uint RENDERDOC_SelectedSliceFace;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(encoding == ShaderEncoding::SPIRVAsm)
|
||||
{
|
||||
text = lit("; Can't insert snippets for SPIR-V ASM");
|
||||
}
|
||||
|
||||
m_Scintillas[0]->setSelection(0, 0);
|
||||
insertSnippet(text);
|
||||
}
|
||||
|
||||
void ShaderViewer::snippet_selectedSample()
|
||||
{
|
||||
if(m_Scintillas.isEmpty())
|
||||
return;
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
GraphicsAPI api = m_Ctx.APIProps().localRenderer;
|
||||
|
||||
GraphicsAPI api = m_Ctx.APIProps().pipelineType;
|
||||
QString text;
|
||||
|
||||
if(IsD3D(api))
|
||||
if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// selected MSAA sample or -numSamples for resolve. See docs\n"
|
||||
"int RENDERDOC_SelectedSample;\n\n");
|
||||
text = vulkanUBO();
|
||||
}
|
||||
else if(api == GraphicsAPI::OpenGL)
|
||||
else if(encoding == ShaderEncoding::HLSL)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// selected MSAA sample or -numSamples for resolve. See docs\n"
|
||||
"uniform int RENDERDOC_SelectedSample;\n\n");
|
||||
text = lit(R"(
|
||||
// selected MSAA sample or -numSamples for resolve. See docs
|
||||
int RENDERDOC_SelectedSample;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(api == GraphicsAPI::Vulkan)
|
||||
else if(encoding == ShaderEncoding::GLSL)
|
||||
{
|
||||
insertVulkanUBO();
|
||||
text = lit(R"(
|
||||
// selected MSAA sample or -numSamples for resolve. See docs
|
||||
uniform int RENDERDOC_SelectedSample;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(encoding == ShaderEncoding::SPIRVAsm)
|
||||
{
|
||||
text = lit("; Can't insert snippets for SPIR-V ASM");
|
||||
}
|
||||
|
||||
m_Scintillas[0]->setSelection(0, 0);
|
||||
insertSnippet(text);
|
||||
}
|
||||
|
||||
void ShaderViewer::snippet_selectedType()
|
||||
{
|
||||
if(m_Scintillas.isEmpty())
|
||||
return;
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
GraphicsAPI api = m_Ctx.APIProps().localRenderer;
|
||||
|
||||
GraphicsAPI api = m_Ctx.APIProps().pipelineType;
|
||||
QString text;
|
||||
|
||||
if(IsD3D(api))
|
||||
if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// 1 = 1D, 2 = 2D, 3 = 3D, 4 = Depth, 5 = Depth + Stencil\n"
|
||||
"// 6 = Depth (MS), 7 = Depth + Stencil (MS)\n"
|
||||
"uint RENDERDOC_TextureType;\n\n");
|
||||
text = vulkanUBO();
|
||||
}
|
||||
else if(api == GraphicsAPI::OpenGL)
|
||||
else if(encoding == ShaderEncoding::HLSL)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// 1 = 1D, 2 = 2D, 3 = 3D, 4 = Cube\n"
|
||||
"// 5 = 1DArray, 6 = 2DArray, 7 = CubeArray\n"
|
||||
"// 8 = Rect, 9 = Buffer, 10 = 2DMS\n"
|
||||
"uniform uint RENDERDOC_TextureType;\n\n");
|
||||
text = lit(R"(
|
||||
// 1 = 1D, 2 = 2D, 3 = 3D, 4 = Depth, 5 = Depth + Stencil
|
||||
// 6 = Depth (MS), 7 = Depth + Stencil (MS)
|
||||
uint RENDERDOC_TextureType;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(api == GraphicsAPI::Vulkan)
|
||||
else if(encoding == ShaderEncoding::GLSL)
|
||||
{
|
||||
insertVulkanUBO();
|
||||
text = lit(R"(
|
||||
// 1 = 1D, 2 = 2D, 3 = 3D, 4 = Cube
|
||||
// 5 = 1DArray, 6 = 2DArray, 7 = CubeArray
|
||||
// 8 = Rect, 9 = Buffer, 10 = 2DMS
|
||||
uniform uint RENDERDOC_TextureType;
|
||||
|
||||
)");
|
||||
}
|
||||
else if(encoding == ShaderEncoding::SPIRVAsm)
|
||||
{
|
||||
text = lit("; Can't insert snippets for SPIR-V ASM");
|
||||
}
|
||||
|
||||
m_Scintillas[0]->setSelection(0, 0);
|
||||
insertSnippet(text);
|
||||
}
|
||||
|
||||
void ShaderViewer::snippet_samplers()
|
||||
{
|
||||
if(m_Scintillas.isEmpty())
|
||||
return;
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
GraphicsAPI api = m_Ctx.APIProps().localRenderer;
|
||||
|
||||
GraphicsAPI api = m_Ctx.APIProps().pipelineType;
|
||||
|
||||
if(IsD3D(api))
|
||||
if(encoding == ShaderEncoding::HLSL)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// Samplers\n"
|
||||
"SamplerState pointSampler : register(s0);\n"
|
||||
"SamplerState linearSampler : register(s1);\n"
|
||||
"// End Samplers\n\n");
|
||||
|
||||
m_Scintillas[0]->setSelection(0, 0);
|
||||
if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
insertSnippet(lit(R"(
|
||||
// Samplers
|
||||
SamplerState pointSampler : register(s50);
|
||||
SamplerState linearSampler : register(s51);
|
||||
// End Samplers
|
||||
)"));
|
||||
}
|
||||
else
|
||||
{
|
||||
insertSnippet(lit(R"(
|
||||
// Samplers
|
||||
SamplerState pointSampler : register(s0);
|
||||
SamplerState linearSampler : register(s1);
|
||||
// End Samplers
|
||||
)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderViewer::snippet_resources()
|
||||
{
|
||||
if(m_Scintillas.isEmpty())
|
||||
return;
|
||||
ShaderEncoding encoding = currentEncoding();
|
||||
GraphicsAPI api = m_Ctx.APIProps().localRenderer;
|
||||
|
||||
GraphicsAPI api = m_Ctx.APIProps().pipelineType;
|
||||
if(encoding == ShaderEncoding::HLSL)
|
||||
{
|
||||
if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
insertSnippet(lit(R"(
|
||||
// Textures
|
||||
// Floating point
|
||||
Texture1DArray<float4> texDisplayTex1DArray : register(t6);
|
||||
Texture2DArray<float4> texDisplayTex2DArray : register(t7);
|
||||
Texture3D<float4> texDisplayTex3D : register(t8);
|
||||
Texture2DMSArray<float4> texDisplayTex2DMSArray : register(t9);
|
||||
Texture2DArray<float4> texDisplayYUVArray : register(t10);
|
||||
|
||||
if(IsD3D(api))
|
||||
{
|
||||
m_Scintillas[0]->insertText(
|
||||
snippetPos(),
|
||||
"// Textures\n"
|
||||
"Texture1DArray<float4> texDisplayTex1DArray : register(t1);\n"
|
||||
"Texture2DArray<float4> texDisplayTex2DArray : register(t2);\n"
|
||||
"Texture3D<float4> texDisplayTex3D : register(t3);\n"
|
||||
"Texture2DArray<float2> texDisplayTexDepthArray : register(t4);\n"
|
||||
"Texture2DArray<uint2> texDisplayTexStencilArray : register(t5);\n"
|
||||
"Texture2DMSArray<float2> texDisplayTexDepthMSArray : register(t6);\n"
|
||||
"Texture2DMSArray<uint2> texDisplayTexStencilMSArray : register(t7);\n"
|
||||
"Texture2DMSArray<float4> texDisplayTex2DMSArray : register(t9);\n"
|
||||
"Texture2DArray<float4> texDisplayYUVArray : register(t10);\n"
|
||||
"\n"
|
||||
"Texture1DArray<uint4> texDisplayUIntTex1DArray : register(t11);\n"
|
||||
"Texture2DArray<uint4> texDisplayUIntTex2DArray : register(t12);\n"
|
||||
"Texture3D<uint4> texDisplayUIntTex3D : register(t13);\n"
|
||||
"Texture2DMSArray<uint4> texDisplayUIntTex2DMSArray : register(t19);\n"
|
||||
"\n"
|
||||
"Texture1DArray<int4> texDisplayIntTex1DArray : register(t21);\n"
|
||||
"Texture2DArray<int4> texDisplayIntTex2DArray : register(t22);\n"
|
||||
"Texture3D<int4> texDisplayIntTex3D : register(t23);\n"
|
||||
"Texture2DMSArray<int4> texDisplayIntTex2DMSArray : register(t29);\n"
|
||||
"// End Textures\n\n\n");
|
||||
}
|
||||
else if(api == GraphicsAPI::OpenGL)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// Textures\n"
|
||||
"// Unsigned int samplers\n"
|
||||
"layout (binding = 1) uniform usampler1D texUInt1D;\n"
|
||||
"layout (binding = 2) uniform usampler2D texUInt2D;\n"
|
||||
"layout (binding = 3) uniform usampler3D texUInt3D;\n"
|
||||
"// cube = 4\n"
|
||||
"layout (binding = 5) uniform usampler1DArray texUInt1DArray;\n"
|
||||
"layout (binding = 6) uniform usampler2DArray texUInt2DArray;\n"
|
||||
"// cube array = 7\n"
|
||||
"layout (binding = 8) uniform usampler2DRect texUInt2DRect;\n"
|
||||
"layout (binding = 9) uniform usamplerBuffer texUIntBuffer;\n"
|
||||
"layout (binding = 10) uniform usampler2DMS texUInt2DMS;\n"
|
||||
"\n"
|
||||
"// Int samplers\n"
|
||||
"layout (binding = 1) uniform isampler1D texSInt1D;\n"
|
||||
"layout (binding = 2) uniform isampler2D texSInt2D;\n"
|
||||
"layout (binding = 3) uniform isampler3D texSInt3D;\n"
|
||||
"// cube = 4\n"
|
||||
"layout (binding = 5) uniform isampler1DArray texSInt1DArray;\n"
|
||||
"layout (binding = 6) uniform isampler2DArray texSInt2DArray;\n"
|
||||
"// cube array = 7\n"
|
||||
"layout (binding = 8) uniform isampler2DRect texSInt2DRect;\n"
|
||||
"layout (binding = 9) uniform isamplerBuffer texSIntBuffer;\n"
|
||||
"layout (binding = 10) uniform isampler2DMS texSInt2DMS;\n"
|
||||
"\n"
|
||||
"// Floating point samplers\n"
|
||||
"layout (binding = 1) uniform sampler1D tex1D;\n"
|
||||
"layout (binding = 2) uniform sampler2D tex2D;\n"
|
||||
"layout (binding = 3) uniform sampler3D tex3D;\n"
|
||||
"layout (binding = 4) uniform samplerCube texCube;\n"
|
||||
"layout (binding = 5) uniform sampler1DArray tex1DArray;\n"
|
||||
"layout (binding = 6) uniform sampler2DArray tex2DArray;\n"
|
||||
"layout (binding = 7) uniform samplerCubeArray texCubeArray;\n"
|
||||
"layout (binding = 8) uniform sampler2DRect tex2DRect;\n"
|
||||
"layout (binding = 9) uniform samplerBuffer texBuffer;\n"
|
||||
"layout (binding = 10) uniform sampler2DMS tex2DMS;\n"
|
||||
"// End Textures\n\n\n");
|
||||
}
|
||||
else if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
m_Scintillas[0]->insertText(snippetPos(),
|
||||
"// Textures\n"
|
||||
"// Floating point samplers\n"
|
||||
"layout(binding = 6) uniform sampler1DArray tex1DArray;\n"
|
||||
"layout(binding = 7) uniform sampler2DArray tex2DArray;\n"
|
||||
"layout(binding = 8) uniform sampler3D tex3D;\n"
|
||||
"layout(binding = 9) uniform sampler2DMS tex2DMS;\n"
|
||||
"layout(binding = 10) uniform sampler2DArray texYUVArray[2];\n"
|
||||
"\n"
|
||||
"// Unsigned int samplers\n"
|
||||
"layout(binding = 11) uniform usampler1DArray texUInt1DArray;\n"
|
||||
"layout(binding = 12) uniform usampler2DArray texUInt2DArray;\n"
|
||||
"layout(binding = 13) uniform usampler3D texUInt3D;\n"
|
||||
"layout(binding = 14) uniform usampler2DMS texUInt2DMS;\n"
|
||||
"\n"
|
||||
"// Int samplers\n"
|
||||
"layout(binding = 16) uniform isampler1DArray texSInt1DArray;\n"
|
||||
"layout(binding = 17) uniform isampler2DArray texSInt2DArray;\n"
|
||||
"layout(binding = 18) uniform isampler3D texSInt3D;\n"
|
||||
"layout(binding = 19) uniform isampler2DMS texSInt2DMS;\n"
|
||||
"// End Textures\n\n\n");
|
||||
}
|
||||
// Unsigned int samplers
|
||||
Texture1DArray<uint4> texDisplayUIntTex1DArray : register(t11);
|
||||
Texture2DArray<uint4> texDisplayUIntTex2DArray : register(t12);
|
||||
Texture3D<uint4> texDisplayUIntTex3D : register(t13);
|
||||
Texture2DMSArray<uint4> texDisplayUIntTex2DMSArray : register(t14);
|
||||
|
||||
m_Scintillas[0]->setSelection(0, 0);
|
||||
// Int samplers
|
||||
Texture1DArray<int4> texDisplayIntTex1DArray : register(t16);
|
||||
Texture2DArray<int4> texDisplayIntTex2DArray : register(t17);
|
||||
Texture3D<int4> texDisplayIntTex3D : register(t18);
|
||||
Texture2DMSArray<int4> texDisplayIntTex2DMSArray : register(t19);
|
||||
// End Textures
|
||||
)"));
|
||||
}
|
||||
else
|
||||
{
|
||||
insertSnippet(lit(R"(
|
||||
// Textures
|
||||
Texture1DArray<float4> texDisplayTex1DArray : register(t1);
|
||||
Texture2DArray<float4> texDisplayTex2DArray : register(t2);
|
||||
Texture3D<float4> texDisplayTex3D : register(t3);
|
||||
Texture2DArray<float2> texDisplayTexDepthArray : register(t4);
|
||||
Texture2DArray<uint2> texDisplayTexStencilArray : register(t5);
|
||||
Texture2DMSArray<float2> texDisplayTexDepthMSArray : register(t6);
|
||||
Texture2DMSArray<uint2> texDisplayTexStencilMSArray : register(t7);
|
||||
Texture2DMSArray<float4> texDisplayTex2DMSArray : register(t9);
|
||||
Texture2DArray<float4> texDisplayYUVArray : register(t10);
|
||||
|
||||
// Unsigned int samplers
|
||||
Texture1DArray<uint4> texDisplayUIntTex1DArray : register(t11);
|
||||
Texture2DArray<uint4> texDisplayUIntTex2DArray : register(t12);
|
||||
Texture3D<uint4> texDisplayUIntTex3D : register(t13);
|
||||
Texture2DMSArray<uint4> texDisplayUIntTex2DMSArray : register(t19);
|
||||
|
||||
// Int samplers
|
||||
Texture1DArray<int4> texDisplayIntTex1DArray : register(t21);
|
||||
Texture2DArray<int4> texDisplayIntTex2DArray : register(t22);
|
||||
Texture3D<int4> texDisplayIntTex3D : register(t23);
|
||||
Texture2DMSArray<int4> texDisplayIntTex2DMSArray : register(t29);
|
||||
// End Textures
|
||||
)"));
|
||||
}
|
||||
}
|
||||
else if(encoding == ShaderEncoding::GLSL)
|
||||
{
|
||||
if(api == GraphicsAPI::Vulkan)
|
||||
{
|
||||
insertSnippet(lit(R"(
|
||||
// Textures
|
||||
// Floating point samplers
|
||||
layout(binding = 6) uniform sampler1DArray tex1DArray;
|
||||
layout(binding = 7) uniform sampler2DArray tex2DArray;
|
||||
layout(binding = 8) uniform sampler3D tex3D;
|
||||
layout(binding = 9) uniform sampler2DMS tex2DMS;
|
||||
layout(binding = 10) uniform sampler2DArray texYUVArray[2];
|
||||
|
||||
// Unsigned int samplers
|
||||
layout(binding = 11) uniform usampler1DArray texUInt1DArray;
|
||||
layout(binding = 12) uniform usampler2DArray texUInt2DArray;
|
||||
layout(binding = 13) uniform usampler3D texUInt3D;
|
||||
layout(binding = 14) uniform usampler2DMS texUInt2DMS;
|
||||
|
||||
// Int samplers
|
||||
layout(binding = 16) uniform isampler1DArray texSInt1DArray;
|
||||
layout(binding = 17) uniform isampler2DArray texSInt2DArray;
|
||||
layout(binding = 18) uniform isampler3D texSInt3D;
|
||||
layout(binding = 19) uniform isampler2DMS texSInt2DMS;
|
||||
// End Textures
|
||||
)"));
|
||||
}
|
||||
else
|
||||
{
|
||||
insertSnippet(lit(R"(
|
||||
// Textures
|
||||
// Unsigned int samplers
|
||||
layout (binding = 1) uniform usampler1D texUInt1D;
|
||||
layout (binding = 2) uniform usampler2D texUInt2D;
|
||||
layout (binding = 3) uniform usampler3D texUInt3D;
|
||||
// cube = 4
|
||||
layout (binding = 5) uniform usampler1DArray texUInt1DArray;
|
||||
layout (binding = 6) uniform usampler2DArray texUInt2DArray;
|
||||
// cube array = 7
|
||||
layout (binding = 8) uniform usampler2DRect texUInt2DRect;
|
||||
layout (binding = 9) uniform usamplerBuffer texUIntBuffer;
|
||||
layout (binding = 10) uniform usampler2DMS texUInt2DMS;
|
||||
|
||||
// Int samplers
|
||||
layout (binding = 1) uniform isampler1D texSInt1D;
|
||||
layout (binding = 2) uniform isampler2D texSInt2D;
|
||||
layout (binding = 3) uniform isampler3D texSInt3D;
|
||||
// cube = 4
|
||||
layout (binding = 5) uniform isampler1DArray texSInt1DArray;
|
||||
layout (binding = 6) uniform isampler2DArray texSInt2DArray;
|
||||
// cube array = 7
|
||||
layout (binding = 8) uniform isampler2DRect texSInt2DRect;
|
||||
layout (binding = 9) uniform isamplerBuffer texSIntBuffer;
|
||||
layout (binding = 10) uniform isampler2DMS texSInt2DMS;
|
||||
|
||||
// Floating point samplers
|
||||
layout (binding = 1) uniform sampler1D tex1D;
|
||||
layout (binding = 2) uniform sampler2D tex2D;
|
||||
layout (binding = 3) uniform sampler3D tex3D;
|
||||
layout (binding = 4) uniform samplerCube texCube;
|
||||
layout (binding = 5) uniform sampler1DArray tex1DArray;
|
||||
layout (binding = 6) uniform sampler2DArray tex2DArray;
|
||||
layout (binding = 7) uniform samplerCubeArray texCubeArray;
|
||||
layout (binding = 8) uniform sampler2DRect tex2DRect;
|
||||
layout (binding = 9) uniform samplerBuffer texBuffer;
|
||||
layout (binding = 10) uniform sampler2DMS tex2DMS;
|
||||
// End Textures
|
||||
)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderViewer::eventFilter(QObject *watched, QEvent *event)
|
||||
@@ -3457,7 +3580,7 @@ void ShaderViewer::on_refresh_clicked()
|
||||
|
||||
// if we don't have any compile tools - even the 'builtin' one, this compilation is not going to
|
||||
// succeed.
|
||||
if(ui->compileTool->count() == 0)
|
||||
if(ui->compileTool->count() == 0 && !m_CustomShader)
|
||||
{
|
||||
ShowErrors(tr("No compilation tool found that takes %1 as input and produces compatible output")
|
||||
.arg(ToQStr(encoding)));
|
||||
@@ -3488,8 +3611,8 @@ void ShaderViewer::on_refresh_clicked()
|
||||
|
||||
rdcarray<ShaderEncoding> accepted = m_Ctx.TargetShaderEncodings();
|
||||
|
||||
if(accepted.indexOf(encoding) >= 0 &&
|
||||
ui->compileTool->currentIndex() == ui->compileTool->count() - 1)
|
||||
if(m_CustomShader || (accepted.indexOf(encoding) >= 0 &&
|
||||
ui->compileTool->currentIndex() == ui->compileTool->count() - 1))
|
||||
{
|
||||
// if using the builtin compiler, just pass through
|
||||
}
|
||||
|
||||
@@ -171,6 +171,8 @@ private:
|
||||
void gotoSourceDebugging();
|
||||
void gotoDisassemblyDebugging();
|
||||
|
||||
void insertSnippet(const QString &text);
|
||||
|
||||
void showVariableTooltip(VariableCategory varCat, int varIdx, int arrayIdx);
|
||||
void showVariableTooltip(QString name);
|
||||
void updateVariableTooltip();
|
||||
@@ -190,6 +192,7 @@ private:
|
||||
ICaptureContext &m_Ctx;
|
||||
const ShaderBindpointMapping *m_Mapping = NULL;
|
||||
const ShaderReflection *m_ShaderDetails = NULL;
|
||||
bool m_CustomShader = false;
|
||||
ShaderCompileFlags m_Flags;
|
||||
QList<ShaderEncoding> m_Encodings;
|
||||
ShaderStage m_Stage;
|
||||
@@ -255,7 +258,7 @@ private:
|
||||
ScintillaEdit *nextScintilla(ScintillaEdit *cur);
|
||||
|
||||
int snippetPos();
|
||||
void insertVulkanUBO();
|
||||
QString vulkanUBO();
|
||||
|
||||
int instructionForLine(sptr_t line);
|
||||
|
||||
|
||||
@@ -54,6 +54,13 @@ float aspect(const QSizeF &s)
|
||||
return s.width() / s.height();
|
||||
}
|
||||
|
||||
static QMap<QString, ShaderEncoding> encodingExtensions = {
|
||||
{lit("hlsl"), ShaderEncoding::HLSL},
|
||||
{lit("glsl"), ShaderEncoding::GLSL},
|
||||
{lit("frag"), ShaderEncoding::GLSL},
|
||||
{lit("spvasm"), ShaderEncoding::SPIRVAsm},
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Following);
|
||||
|
||||
const Following Following::Default = Following();
|
||||
@@ -1470,6 +1477,13 @@ void TextureViewer::UI_UpdateChannels()
|
||||
const bool yuvDecodeDisplay = ui->channels->currentIndex() == 2;
|
||||
const bool customDisplay = ui->channels->currentIndex() == 3;
|
||||
|
||||
if(customDisplay && m_NeedCustomReload)
|
||||
{
|
||||
m_NeedCustomReload = false;
|
||||
|
||||
reloadCustomShaders(QString());
|
||||
}
|
||||
|
||||
ui->channels->setItemText(0, yuv ? lit("YUVA") : lit("RGBA"));
|
||||
ui->channelRed->setText(lit("R"));
|
||||
ui->channelGreen->setText(lit("G"));
|
||||
@@ -2671,7 +2685,8 @@ void TextureViewer::OnCaptureLoaded()
|
||||
&TextureViewer::customShaderModified);
|
||||
QObject::connect(m_Watcher, &QFileSystemWatcher::directoryChanged, this,
|
||||
&TextureViewer::customShaderModified);
|
||||
reloadCustomShaders(QString());
|
||||
|
||||
m_NeedCustomReload = true;
|
||||
}
|
||||
|
||||
void TextureViewer::Reset()
|
||||
@@ -3743,6 +3758,28 @@ void TextureViewer::on_textureList_clicked(const QModelIndex &index)
|
||||
ViewTexture(id, false);
|
||||
}
|
||||
|
||||
bool TextureViewer::canCompileCustomShader(ShaderEncoding encoding)
|
||||
{
|
||||
rdcarray<ShaderEncoding> supported = m_Ctx.CustomShaderEncodings();
|
||||
|
||||
// if it's directly supported, we can trivially compile it
|
||||
if(supported.contains(encoding))
|
||||
return true;
|
||||
|
||||
// otherwise see if we have a tool that can compile it for us
|
||||
|
||||
for(const ShaderProcessingTool &tool : m_Ctx.Config().ShaderProcessors)
|
||||
{
|
||||
// if this tool transforms from the encoding to one we support, we can compile a shader of this
|
||||
// encoding
|
||||
if(tool.input == encoding && supported.contains(tool.output))
|
||||
return true;
|
||||
}
|
||||
|
||||
// all options exhausted, we can't compile this
|
||||
return false;
|
||||
}
|
||||
|
||||
void TextureViewer::reloadCustomShaders(const QString &filter)
|
||||
{
|
||||
if(!m_Ctx.IsCaptureLoaded())
|
||||
@@ -3766,7 +3803,7 @@ void TextureViewer::reloadCustomShaders(const QString &filter)
|
||||
}
|
||||
else
|
||||
{
|
||||
QString fn = QFileInfo(filter).baseName();
|
||||
QString fn = QFileInfo(filter).fileName();
|
||||
QString key = fn.toUpper();
|
||||
|
||||
if(m_CustomShaders.contains(key))
|
||||
@@ -3794,10 +3831,18 @@ void TextureViewer::reloadCustomShaders(const QString &filter)
|
||||
}
|
||||
}
|
||||
|
||||
QStringList filters;
|
||||
for(auto it = encodingExtensions.begin(); it != encodingExtensions.end(); ++it)
|
||||
{
|
||||
if(!canCompileCustomShader(it.value()))
|
||||
continue;
|
||||
|
||||
filters.push_back(lit("*.") + it.key());
|
||||
}
|
||||
|
||||
QStringList files =
|
||||
QDir(configFilePath(QString()))
|
||||
.entryList({QFormatStr("*.%1").arg(m_Ctx.CurPipelineState().GetShaderExtension())},
|
||||
QDir::Files | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase);
|
||||
.entryList(filters, QDir::Files | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase);
|
||||
|
||||
QStringList watchedFiles = m_Watcher->files();
|
||||
if(!watchedFiles.isEmpty())
|
||||
@@ -3805,8 +3850,13 @@ void TextureViewer::reloadCustomShaders(const QString &filter)
|
||||
|
||||
for(const QString &f : files)
|
||||
{
|
||||
QString fn = QFileInfo(f).baseName();
|
||||
QFileInfo fileInfo(f);
|
||||
QString fn = fileInfo.fileName();
|
||||
QString key = fn.toUpper();
|
||||
ShaderEncoding encoding = encodingExtensions[fileInfo.completeSuffix()];
|
||||
|
||||
if(!filter.isEmpty() && filter.toUpper() != key)
|
||||
continue;
|
||||
|
||||
m_Watcher->addPath(configFilePath(f));
|
||||
|
||||
@@ -3818,36 +3868,87 @@ void TextureViewer::reloadCustomShaders(const QString &filter)
|
||||
QTextStream stream(&fileHandle);
|
||||
QString source = stream.readAll();
|
||||
|
||||
bytebuf shaderBytes(source.toUtf8());
|
||||
|
||||
rdcarray<ShaderEncoding> supported = m_Ctx.TargetShaderEncodings();
|
||||
|
||||
rdcstr errors;
|
||||
|
||||
// we don't accept this encoding directly, need to compile
|
||||
if(!supported.contains(encoding))
|
||||
{
|
||||
for(const ShaderProcessingTool &tool : m_Ctx.Config().ShaderProcessors)
|
||||
{
|
||||
// pick the first tool that can convert to an accepted format
|
||||
if(tool.input == encoding && supported.contains(tool.output))
|
||||
{
|
||||
ShaderToolOutput out =
|
||||
tool.CompileShader(this, source, "main", ShaderStage::Pixel, "");
|
||||
|
||||
errors = out.log;
|
||||
|
||||
if(m_CustomShaderEditor.contains(key))
|
||||
m_CustomShaderEditor[key]->ShowErrors(errors);
|
||||
|
||||
if(out.result.isEmpty())
|
||||
break;
|
||||
|
||||
encoding = tool.output;
|
||||
shaderBytes = out.result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the encoding still isn't supported, all tools failed. Bail out now
|
||||
if(!supported.contains(encoding))
|
||||
{
|
||||
if(m_CustomShaderEditor.contains(key))
|
||||
m_CustomShaderEditor[key]->ShowErrors(errors);
|
||||
|
||||
m_CustomShaders[key] = ResourceId();
|
||||
|
||||
QString prevtext = ui->customShader->currentText();
|
||||
ui->customShader->addItem(fn);
|
||||
ui->customShader->setCurrentText(prevtext);
|
||||
continue;
|
||||
}
|
||||
|
||||
ANALYTIC_SET(UIFeatures.CustomTextureVisualise, true);
|
||||
|
||||
fileHandle.close();
|
||||
|
||||
m_CustomShaders[key] = ResourceId();
|
||||
m_CustomShadersBusy.push_back(key);
|
||||
m_Ctx.Replay().AsyncInvoke([this, fn, key, source](IReplayController *r) {
|
||||
rdcstr errors;
|
||||
m_Ctx.Replay().AsyncInvoke(
|
||||
[this, fn, key, shaderBytes, encoding, errors](IReplayController *r) {
|
||||
rdcstr buildErrors;
|
||||
|
||||
ResourceId id;
|
||||
rdctie(id, errors) = r->BuildCustomShader("main", source.toUtf8().data(),
|
||||
ShaderCompileFlags(), ShaderStage::Pixel);
|
||||
ResourceId id;
|
||||
rdctie(id, buildErrors) = r->BuildCustomShader(
|
||||
"main", encoding, shaderBytes, ShaderCompileFlags(), ShaderStage::Pixel);
|
||||
|
||||
if(m_CustomShaderEditor.contains(key))
|
||||
{
|
||||
IShaderViewer *editor = m_CustomShaderEditor[key];
|
||||
GUIInvoke::call(editor->Widget(), [editor, errors]() { editor->ShowErrors(errors); });
|
||||
}
|
||||
if(!errors.empty())
|
||||
buildErrors = errors + "\n\n" + buildErrors;
|
||||
|
||||
GUIInvoke::call(this, [this, fn, key, id]() {
|
||||
QString prevtext = ui->customShader->currentText();
|
||||
ui->customShader->addItem(fn);
|
||||
ui->customShader->setCurrentText(prevtext);
|
||||
if(m_CustomShaderEditor.contains(key))
|
||||
{
|
||||
IShaderViewer *editor = m_CustomShaderEditor[key];
|
||||
GUIInvoke::call(editor->Widget(),
|
||||
[editor, buildErrors]() { editor->ShowErrors(buildErrors); });
|
||||
}
|
||||
|
||||
m_CustomShaders[key] = id;
|
||||
m_CustomShadersBusy.removeOne(key);
|
||||
GUIInvoke::call(this, [this, fn, key, id]() {
|
||||
QString prevtext = ui->customShader->currentText();
|
||||
ui->customShader->addItem(fn);
|
||||
ui->customShader->setCurrentText(prevtext);
|
||||
|
||||
UI_UpdateChannels();
|
||||
});
|
||||
});
|
||||
m_CustomShaders[key] = id;
|
||||
m_CustomShadersBusy.removeOne(key);
|
||||
|
||||
UI_UpdateChannels();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3873,11 +3974,34 @@ void TextureViewer::on_customCreate_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = configFilePath(filename + lit(".") + m_Ctx.CurPipelineState().GetShaderExtension());
|
||||
ShaderEncoding enc = encodingExtensions[QFileInfo(filename).completeSuffix()];
|
||||
|
||||
if(enc == ShaderEncoding::Unknown)
|
||||
{
|
||||
QString extString;
|
||||
|
||||
for(auto it = encodingExtensions.begin(); it != encodingExtensions.end(); ++it)
|
||||
{
|
||||
if(!canCompileCustomShader(it.value()))
|
||||
continue;
|
||||
|
||||
if(!extString.isEmpty())
|
||||
extString += lit(", ");
|
||||
extString += it.key();
|
||||
}
|
||||
|
||||
RDDialog::critical(this, tr("Error Creating Shader"),
|
||||
tr("No file extension specified, unknown shading language.\n"
|
||||
"Filename must contain one of: %1")
|
||||
.arg(extString));
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = configFilePath(filename);
|
||||
|
||||
QString src;
|
||||
|
||||
if(IsD3D(m_Ctx.APIProps().pipelineType))
|
||||
if(enc == ShaderEncoding::HLSL)
|
||||
{
|
||||
src =
|
||||
lit("float4 main(float4 pos : SV_Position, float4 uv : TEXCOORD0) : SV_Target0\n"
|
||||
@@ -3885,7 +4009,7 @@ void TextureViewer::on_customCreate_clicked()
|
||||
" return float4(0,0,0,1);\n"
|
||||
"}\n");
|
||||
}
|
||||
else
|
||||
else if(enc == ShaderEncoding::GLSL)
|
||||
{
|
||||
src =
|
||||
lit("#version 420 core\n\n"
|
||||
@@ -3896,6 +4020,14 @@ void TextureViewer::on_customCreate_clicked()
|
||||
" color_out = vec4(0,0,0,1);\n"
|
||||
"}\n");
|
||||
}
|
||||
else if(enc == ShaderEncoding::SPIRVAsm)
|
||||
{
|
||||
src = lit("; SPIR-V");
|
||||
}
|
||||
else
|
||||
{
|
||||
src = tr("Unknown format - no template available");
|
||||
}
|
||||
|
||||
QFile fileHandle(path);
|
||||
if(fileHandle.open(QFile::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
||||
@@ -3928,7 +4060,7 @@ void TextureViewer::on_customEdit_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = configFilePath(filename + lit(".") + m_Ctx.CurPipelineState().GetShaderExtension());
|
||||
QString path = configFilePath(filename);
|
||||
|
||||
QString src;
|
||||
|
||||
@@ -3954,13 +4086,15 @@ void TextureViewer::on_customEdit_clicked()
|
||||
|
||||
IShaderViewer *s = m_Ctx.EditShader(
|
||||
true, ShaderStage::Fragment, lit("main"), files,
|
||||
IsD3D(m_Ctx.APIProps().localRenderer) ? ShaderEncoding::HLSL : ShaderEncoding::GLSL,
|
||||
ShaderCompileFlags(),
|
||||
encodingExtensions[QFileInfo(filename).completeSuffix()], ShaderCompileFlags(),
|
||||
// Save Callback
|
||||
[thisPointer, key, filename, path](ICaptureContext *ctx, IShaderViewer *viewer,
|
||||
ShaderEncoding encoding, ShaderCompileFlags flags,
|
||||
rdcstr entryFunc, bytebuf bytes) {
|
||||
ShaderEncoding, ShaderCompileFlags, rdcstr, bytebuf bytes) {
|
||||
{
|
||||
// don't trigger a full refresh
|
||||
if(thisPointer)
|
||||
thisPointer->m_CustomShaderWriteTime = thisPointer->m_CustomShaderTimer.elapsed();
|
||||
|
||||
QFile fileHandle(path);
|
||||
if(fileHandle.open(QFile::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
||||
{
|
||||
@@ -4018,8 +4152,7 @@ void TextureViewer::on_customDelete_clicked()
|
||||
|
||||
if(res == QMessageBox::Yes)
|
||||
{
|
||||
QString path =
|
||||
configFilePath(shaderName + lit(".") + m_Ctx.CurPipelineState().GetShaderExtension());
|
||||
QString path = configFilePath(shaderName);
|
||||
if(!QFileInfo::exists(path))
|
||||
{
|
||||
RDDialog::critical(
|
||||
@@ -4043,8 +4176,22 @@ void TextureViewer::on_customDelete_clicked()
|
||||
|
||||
void TextureViewer::customShaderModified(const QString &path)
|
||||
{
|
||||
static bool recurse = false;
|
||||
|
||||
if(recurse)
|
||||
return;
|
||||
|
||||
// if we just wrote a shader less than 100ms ago, don't refresh - this will have been handled
|
||||
// internally at a finer granularity than 'all shaders'
|
||||
if(m_CustomShaderWriteTime > m_CustomShaderTimer.elapsed() - 100)
|
||||
return;
|
||||
|
||||
recurse = true;
|
||||
|
||||
// allow time for modifications to finish
|
||||
QThread::msleep(15);
|
||||
|
||||
reloadCustomShaders(QString());
|
||||
|
||||
recurse = false;
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <QFrame>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QTime>
|
||||
#include "Code/Interface/QRDInterface.h"
|
||||
|
||||
namespace Ui
|
||||
@@ -322,15 +323,21 @@ private:
|
||||
|
||||
TextureSave m_SaveConfig;
|
||||
|
||||
bool m_NeedCustomReload = false;
|
||||
|
||||
TextureDescription *m_CachedTexture;
|
||||
Following m_Following = Following::Default;
|
||||
QMap<ResourceId, TexSettings> m_TextureSettings;
|
||||
|
||||
QTime m_CustomShaderTimer;
|
||||
int m_CustomShaderWriteTime = 0;
|
||||
|
||||
QFileSystemWatcher *m_Watcher = NULL;
|
||||
QStringList m_CustomShadersBusy;
|
||||
QMap<QString, ResourceId> m_CustomShaders;
|
||||
QMap<QString, IShaderViewer *> m_CustomShaderEditor;
|
||||
|
||||
bool canCompileCustomShader(ShaderEncoding encoding);
|
||||
void reloadCustomShaders(const QString &filter);
|
||||
|
||||
TextureDisplay m_TexDisplay;
|
||||
|
||||
@@ -650,7 +650,7 @@
|
||||
<rect>
|
||||
<x>3</x>
|
||||
<y>3</y>
|
||||
<width>696</width>
|
||||
<width>746</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -848,7 +848,7 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
|
||||
@@ -184,15 +184,6 @@ requirements.
|
||||
)");
|
||||
rdcstr OutputAbbrev() const;
|
||||
|
||||
DOCUMENT(R"(Retrieves the common file extension for high level shaders in the current API.
|
||||
|
||||
Typically this is ``glsl`` or ``hlsl``.
|
||||
|
||||
:return: The file extension with no ``.``.
|
||||
:rtype: ``str``
|
||||
)");
|
||||
rdcstr GetShaderExtension() const;
|
||||
|
||||
DOCUMENT(R"(Retrieves the viewport for a given index.
|
||||
|
||||
:param int index: The index to retrieve.
|
||||
|
||||
@@ -166,16 +166,6 @@ const VKPipe::Shader &PipeState::GetVulkanStage(ShaderStage stage) const
|
||||
return m_Vulkan->computeShader;
|
||||
}
|
||||
|
||||
rdcstr PipeState::GetShaderExtension() const
|
||||
{
|
||||
if(IsCaptureGL() || IsCaptureVK())
|
||||
{
|
||||
return "glsl";
|
||||
}
|
||||
|
||||
return "hlsl";
|
||||
}
|
||||
|
||||
Viewport PipeState::GetViewport(int index) const
|
||||
{
|
||||
Viewport ret = {};
|
||||
|
||||
@@ -982,19 +982,19 @@ or hardware-specific ISA formats.
|
||||
|
||||
DOCUMENT(R"(Builds a shader suitable for running on the local replay instance as a custom shader.
|
||||
|
||||
The language used is native to the local renderer - HLSL for D3D based renderers, GLSL otherwise.
|
||||
|
||||
See :data:`TextureDisplay.customShaderId`.
|
||||
|
||||
:param str entry: The entry point to use when compiling.
|
||||
:param str source: The source file.
|
||||
:param ShaderEncoding sourceEncoding: The encoding of the source data.
|
||||
:param bytes source: The source data itself.
|
||||
:param int compileFlags: API-specific compilation flags.
|
||||
:param ShaderStage type: The stage that this shader will be executed at.
|
||||
:return: A ``tuple`` with the id of the new shader if compilation was successful,
|
||||
:meth:`ResourceId.Null` otherwise, and a ``str`` with any warnings/errors from compilation.
|
||||
:rtype: ``tuple`` of :class:`ResourceId` and ``str``.
|
||||
)");
|
||||
virtual rdcpair<ResourceId, rdcstr> BuildCustomShader(const char *entry, const char *source,
|
||||
virtual rdcpair<ResourceId, rdcstr> BuildCustomShader(const char *entry,
|
||||
ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type) = 0;
|
||||
|
||||
@@ -1008,8 +1008,6 @@ See :meth:`BuildCustomShader`.
|
||||
|
||||
DOCUMENT(R"(Builds a shader suitable for running in the capture's API as a replacement shader.
|
||||
|
||||
The language used is native to the API's renderer - HLSL for D3D based renderers, GLSL otherwise.
|
||||
|
||||
:param str entry: The entry point to use when compiling.
|
||||
:param ShaderEncoding sourceEncoding: The encoding of the source data.
|
||||
:param bytes source: The source data itself.
|
||||
|
||||
@@ -145,11 +145,11 @@ public:
|
||||
{
|
||||
return m_Proxy->GetCustomShaderEncodings();
|
||||
}
|
||||
void BuildCustomShader(std::string source, std::string entry,
|
||||
void BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors)
|
||||
{
|
||||
m_Proxy->BuildCustomShader(source, entry, compileFlags, type, id, errors);
|
||||
m_Proxy->BuildCustomShader(sourceEncoding, source, entry, compileFlags, type, id, errors);
|
||||
}
|
||||
void FreeCustomShader(ResourceId id) { m_Proxy->FreeTargetResource(id); }
|
||||
ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip, uint32_t arrayIdx,
|
||||
@@ -269,7 +269,7 @@ public:
|
||||
RDCEraseEl(ret);
|
||||
return ret;
|
||||
}
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors)
|
||||
{
|
||||
|
||||
@@ -1266,7 +1266,8 @@ rdcarray<ShaderEncoding> ReplayProxy::GetTargetShaderEncodings()
|
||||
template <typename ParamSerialiser, typename ReturnSerialiser>
|
||||
void ReplayProxy::Proxied_BuildTargetShader(ParamSerialiser ¶mser, ReturnSerialiser &retser,
|
||||
ShaderEncoding sourceEncoding, bytebuf source,
|
||||
std::string entry, const ShaderCompileFlags &compileFlags,
|
||||
const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
const ReplayProxyPacket expectedPacket = eReplayProxy_BuildTargetShader;
|
||||
@@ -1309,7 +1310,7 @@ void ReplayProxy::Proxied_BuildTargetShader(ParamSerialiser ¶mser, ReturnSer
|
||||
}
|
||||
|
||||
void ReplayProxy::BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
std::string entry, const ShaderCompileFlags &compileFlags,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
PROXY_FUNCTION(BuildTargetShader, sourceEncoding, source, entry, compileFlags, type, id, errors);
|
||||
@@ -2614,9 +2615,12 @@ bool ReplayProxy::Tick(int type)
|
||||
}
|
||||
case eReplayProxy_GetPostVS: GetPostVSBuffers(0, 0, 0, MeshDataStage::Unknown); break;
|
||||
case eReplayProxy_BuildTargetShader:
|
||||
BuildTargetShader(ShaderEncoding::Unknown, bytebuf(), "", ShaderCompileFlags(),
|
||||
{
|
||||
std::string entry;
|
||||
BuildTargetShader(ShaderEncoding::Unknown, bytebuf(), entry, ShaderCompileFlags(),
|
||||
ShaderStage::Vertex, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
case eReplayProxy_ReplaceResource: ReplaceResource(ResourceId(), ResourceId()); break;
|
||||
case eReplayProxy_RemoveReplacement: RemoveReplacement(ResourceId()); break;
|
||||
case eReplayProxy_DebugVertex: DebugVertex(0, 0, 0, 0, 0, 0); break;
|
||||
|
||||
@@ -401,13 +401,13 @@ public:
|
||||
return ~0U;
|
||||
}
|
||||
|
||||
void BuildCustomShader(std::string source, std::string entry,
|
||||
void BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors)
|
||||
{
|
||||
if(m_Proxy)
|
||||
{
|
||||
m_Proxy->BuildCustomShader(source, entry, compileFlags, type, id, errors);
|
||||
m_Proxy->BuildCustomShader(sourceEncoding, source, entry, compileFlags, type, id, errors);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -531,7 +531,7 @@ public:
|
||||
|
||||
IMPLEMENT_FUNCTION_PROXIED(rdcarray<ShaderEncoding>, GetTargetShaderEncodings);
|
||||
IMPLEMENT_FUNCTION_PROXIED(void, BuildTargetShader, ShaderEncoding sourceEncoding, bytebuf source,
|
||||
std::string entry, const ShaderCompileFlags &compileFlags,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors);
|
||||
IMPLEMENT_FUNCTION_PROXIED(void, ReplaceResource, ResourceId from, ResourceId to);
|
||||
IMPLEMENT_FUNCTION_PROXIED(void, RemoveReplacement, ResourceId id);
|
||||
|
||||
@@ -833,6 +833,9 @@ void D3D11Replay::InitPostVSBuffers(uint32_t eventId)
|
||||
drawcall->instanceOffset);
|
||||
m_pImmediateContext->End(m_SOStatsQueries[inst - 1]);
|
||||
}
|
||||
|
||||
if((inst % 2000) == 0)
|
||||
SerializeImmediateContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2292,9 +2292,9 @@ D3D11DebugManager *D3D11Replay::GetDebugManager()
|
||||
return m_pDevice->GetDebugManager();
|
||||
}
|
||||
|
||||
void D3D11Replay::BuildShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors)
|
||||
void D3D11Replay::BuildShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
if(id == NULL || errors == NULL)
|
||||
{
|
||||
@@ -2449,7 +2449,7 @@ void D3D11Replay::BuildShader(ShaderEncoding sourceEncoding, bytebuf source, std
|
||||
}
|
||||
|
||||
void D3D11Replay::BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
std::string entry, const ShaderCompileFlags &compileFlags,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
ShaderCompileFlags debugCompileFlags =
|
||||
@@ -2458,14 +2458,11 @@ void D3D11Replay::BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf sourc
|
||||
BuildShader(sourceEncoding, source, entry, debugCompileFlags, type, id, errors);
|
||||
}
|
||||
|
||||
void D3D11Replay::BuildCustomShader(std::string source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors)
|
||||
void D3D11Replay::BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
bytebuf buf;
|
||||
buf.resize(source.size());
|
||||
memcpy(buf.data(), source.c_str(), buf.size());
|
||||
BuildShader(ShaderEncoding::HLSL, buf, entry, compileFlags, type, id, errors);
|
||||
BuildTargetShader(sourceEncoding, source, entry, compileFlags, type, id, errors);
|
||||
}
|
||||
|
||||
bool D3D11Replay::RenderTexture(TextureDisplay cfg)
|
||||
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
{
|
||||
return {ShaderEncoding::DXBC, ShaderEncoding::HLSL};
|
||||
}
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
void ReplaceResource(ResourceId from, ResourceId to);
|
||||
@@ -237,7 +237,7 @@ public:
|
||||
ResourceId RenderOverlay(ResourceId texid, CompType typeHint, DebugOverlay overlay,
|
||||
uint32_t eventId, const std::vector<uint32_t> &passEvents);
|
||||
|
||||
void BuildCustomShader(std::string source, std::string entry,
|
||||
void BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip, uint32_t arrayIdx,
|
||||
@@ -252,7 +252,7 @@ private:
|
||||
|
||||
D3D11DebugManager *GetDebugManager();
|
||||
// shared by BuildCustomShader and BuildTargetShader
|
||||
void BuildShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
void BuildShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
|
||||
|
||||
@@ -2736,9 +2736,9 @@ std::vector<DebugMessage> D3D12Replay::GetDebugMessages()
|
||||
return m_pDevice->GetDebugMessages();
|
||||
}
|
||||
|
||||
void D3D12Replay::BuildShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors)
|
||||
void D3D12Replay::BuildShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
if(id == NULL || errors == NULL)
|
||||
{
|
||||
@@ -2796,7 +2796,7 @@ void D3D12Replay::BuildShader(ShaderEncoding sourceEncoding, bytebuf source, std
|
||||
}
|
||||
|
||||
void D3D12Replay::BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
std::string entry, const ShaderCompileFlags &compileFlags,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
ShaderCompileFlags debugCompileFlags =
|
||||
@@ -3425,14 +3425,11 @@ void D3D12Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip
|
||||
SAFE_RELEASE(tmpTexture);
|
||||
}
|
||||
|
||||
void D3D12Replay::BuildCustomShader(std::string source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors)
|
||||
void D3D12Replay::BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
bytebuf buf;
|
||||
buf.resize(source.size());
|
||||
memcpy(buf.data(), source.c_str(), buf.size());
|
||||
BuildShader(ShaderEncoding::HLSL, buf, entry, compileFlags, type, id, errors);
|
||||
BuildShader(sourceEncoding, source, entry, compileFlags, type, id, errors);
|
||||
}
|
||||
|
||||
ResourceId D3D12Replay::ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip,
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
{
|
||||
return {ShaderEncoding::DXBC, ShaderEncoding::HLSL};
|
||||
}
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
void ReplaceResource(ResourceId from, ResourceId to);
|
||||
@@ -198,7 +198,7 @@ public:
|
||||
ResourceId RenderOverlay(ResourceId texid, CompType typeHint, DebugOverlay overlay,
|
||||
uint32_t eventId, const std::vector<uint32_t> &passEvents);
|
||||
|
||||
void BuildCustomShader(std::string source, std::string entry,
|
||||
void BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip, uint32_t arrayIdx,
|
||||
@@ -219,7 +219,7 @@ private:
|
||||
|
||||
void CreateSOBuffers();
|
||||
|
||||
void BuildShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
void BuildShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
|
||||
|
||||
@@ -2727,64 +2727,11 @@ void GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
|
||||
drv.glDeleteTextures(1, &tempTex);
|
||||
}
|
||||
|
||||
void GLReplay::BuildCustomShader(std::string source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors)
|
||||
void GLReplay::BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
if(id == NULL || errors == NULL)
|
||||
{
|
||||
if(id)
|
||||
*id = ResourceId();
|
||||
return;
|
||||
}
|
||||
|
||||
WrappedOpenGL &drv = *m_pDriver;
|
||||
|
||||
MakeCurrentReplayContext(m_DebugCtx);
|
||||
|
||||
GLenum shtype = eGL_VERTEX_SHADER;
|
||||
switch(type)
|
||||
{
|
||||
case ShaderStage::Vertex: shtype = eGL_VERTEX_SHADER; break;
|
||||
case ShaderStage::Tess_Control: shtype = eGL_TESS_CONTROL_SHADER; break;
|
||||
case ShaderStage::Tess_Eval: shtype = eGL_TESS_EVALUATION_SHADER; break;
|
||||
case ShaderStage::Geometry: shtype = eGL_GEOMETRY_SHADER; break;
|
||||
case ShaderStage::Fragment: shtype = eGL_FRAGMENT_SHADER; break;
|
||||
case ShaderStage::Compute: shtype = eGL_COMPUTE_SHADER; break;
|
||||
default:
|
||||
{
|
||||
RDCERR("Unknown shader type %u", type);
|
||||
if(id)
|
||||
*id = ResourceId();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char *src = source.c_str();
|
||||
GLuint shader = drv.glCreateShader(shtype);
|
||||
|
||||
drv.glShaderSource(shader, 1, &src, NULL);
|
||||
|
||||
drv.glCompileShader(shader);
|
||||
|
||||
GLint status = 0;
|
||||
drv.glGetShaderiv(shader, eGL_COMPILE_STATUS, &status);
|
||||
|
||||
if(errors)
|
||||
{
|
||||
GLint len = 1024;
|
||||
drv.glGetShaderiv(shader, eGL_INFO_LOG_LENGTH, &len);
|
||||
char *buffer = new char[len + 1];
|
||||
drv.glGetShaderInfoLog(shader, len, NULL, buffer);
|
||||
buffer[len] = 0;
|
||||
*errors = buffer;
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
if(status == 0)
|
||||
*id = ResourceId();
|
||||
else
|
||||
*id = m_pDriver->GetResourceManager()->GetID(ShaderRes(m_pDriver->GetCtx(), shader));
|
||||
BuildTargetShader(sourceEncoding, source, entry, compileFlags, type, id, errors);
|
||||
}
|
||||
|
||||
ResourceId GLReplay::ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip,
|
||||
@@ -2882,9 +2829,9 @@ void GLReplay::FreeCustomShader(ResourceId id)
|
||||
m_pDriver->glDeleteShader(m_pDriver->GetResourceManager()->GetCurrentResource(id).name);
|
||||
}
|
||||
|
||||
void GLReplay::BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors)
|
||||
void GLReplay::BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
if(id == NULL || errors == NULL)
|
||||
{
|
||||
|
||||
@@ -173,10 +173,10 @@ public:
|
||||
|
||||
rdcarray<ShaderEncoding> GetCustomShaderEncodings() { return {ShaderEncoding::GLSL}; }
|
||||
rdcarray<ShaderEncoding> GetTargetShaderEncodings() { return {ShaderEncoding::GLSL}; }
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
void BuildCustomShader(std::string source, std::string entry,
|
||||
void BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
void FreeCustomShader(ResourceId id);
|
||||
|
||||
@@ -3478,7 +3478,11 @@ void MakeOnlineShaderReflection(ShaderStage stage, const std::string &source,
|
||||
|
||||
ResourceId id;
|
||||
std::string errors;
|
||||
driver->BuildCustomShader(source, "main", ShaderCompileFlags(), stage, &id, &errors);
|
||||
bytebuf buf;
|
||||
buf.resize(source.size());
|
||||
memcpy(buf.data(), source.data(), source.size());
|
||||
driver->BuildCustomShader(ShaderEncoding::GLSL, buf, "main", ShaderCompileFlags(), stage, &id,
|
||||
&errors);
|
||||
|
||||
if(id == ResourceId())
|
||||
{
|
||||
|
||||
@@ -1690,6 +1690,7 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
|
||||
|
||||
VulkanShaderCache *shaderCache = driver->GetShaderCache();
|
||||
|
||||
CREATE_OBJECT(PointSampler, VK_FILTER_NEAREST);
|
||||
CREATE_OBJECT(LinearSampler, VK_FILTER_LINEAR);
|
||||
|
||||
CREATE_OBJECT(DescSetLayout,
|
||||
@@ -1711,6 +1712,8 @@ void VulkanReplay::TextureRendering::Init(WrappedVulkan *driver, VkDescriptorPoo
|
||||
{18, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, NULL},
|
||||
{19, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, NULL},
|
||||
{20, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, NULL},
|
||||
{50, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, &PointSampler},
|
||||
{51, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, &LinearSampler},
|
||||
});
|
||||
|
||||
CREATE_OBJECT(PipeLayout, DescSetLayout, 0);
|
||||
@@ -2003,6 +2006,7 @@ void VulkanReplay::TextureRendering::Destroy(WrappedVulkan *driver)
|
||||
UBO.Destroy();
|
||||
HeatmapUBO.Destroy();
|
||||
|
||||
driver->vkDestroySampler(driver->GetDev(), PointSampler, NULL);
|
||||
driver->vkDestroySampler(driver->GetDev(), LinearSampler, NULL);
|
||||
|
||||
for(size_t i = 0; i < ARRAY_COUNT(DummyImages); i++)
|
||||
|
||||
@@ -3434,54 +3434,11 @@ void VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mi
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanReplay::BuildCustomShader(std::string source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors)
|
||||
void VulkanReplay::BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
SPIRVShaderStage stage = SPIRVShaderStage::Invalid;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ShaderStage::Vertex: stage = SPIRVShaderStage::Vertex; break;
|
||||
case ShaderStage::Hull: stage = SPIRVShaderStage::TessControl; break;
|
||||
case ShaderStage::Domain: stage = SPIRVShaderStage::TessEvaluation; break;
|
||||
case ShaderStage::Geometry: stage = SPIRVShaderStage::Geometry; break;
|
||||
case ShaderStage::Pixel: stage = SPIRVShaderStage::Fragment; break;
|
||||
case ShaderStage::Compute: stage = SPIRVShaderStage::Compute; break;
|
||||
default:
|
||||
RDCERR("Unexpected type in BuildShader!");
|
||||
*id = ResourceId();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> sources;
|
||||
sources.push_back(source);
|
||||
std::vector<uint32_t> spirv;
|
||||
|
||||
SPIRVCompilationSettings settings(SPIRVSourceLanguage::VulkanGLSL, stage);
|
||||
|
||||
std::string output = CompileSPIRV(settings, sources, spirv);
|
||||
|
||||
if(spirv.empty())
|
||||
{
|
||||
*id = ResourceId();
|
||||
*errors = output;
|
||||
return;
|
||||
}
|
||||
|
||||
VkShaderModuleCreateInfo modinfo = {
|
||||
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
NULL,
|
||||
0,
|
||||
spirv.size() * sizeof(uint32_t),
|
||||
&spirv[0],
|
||||
};
|
||||
|
||||
VkShaderModule module;
|
||||
VkResult vkr = m_pDriver->vkCreateShaderModule(m_pDriver->GetDev(), &modinfo, NULL, &module);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
*id = GetResID(module);
|
||||
BuildTargetShader(sourceEncoding, source, entry, compileFlags, type, id, errors);
|
||||
}
|
||||
|
||||
void VulkanReplay::FreeCustomShader(ResourceId id)
|
||||
@@ -3549,7 +3506,7 @@ ResourceId VulkanReplay::ApplyCustomShader(ResourceId shader, ResourceId texid,
|
||||
}
|
||||
|
||||
void VulkanReplay::BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
std::string entry, const ShaderCompileFlags &compileFlags,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors)
|
||||
{
|
||||
std::vector<uint32_t> spirv;
|
||||
|
||||
@@ -320,10 +320,10 @@ public:
|
||||
{
|
||||
return {ShaderEncoding::SPIRV, ShaderEncoding::GLSL};
|
||||
}
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
void BuildCustomShader(std::string source, std::string entry,
|
||||
void BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source, const std::string &entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type, ResourceId *id,
|
||||
std::string *errors);
|
||||
void FreeCustomShader(ResourceId id);
|
||||
@@ -523,6 +523,7 @@ private:
|
||||
VkDescriptorSet DescSet[16] = {VK_NULL_HANDLE};
|
||||
uint32_t NextSet = 0;
|
||||
|
||||
VkSampler PointSampler = VK_NULL_HANDLE;
|
||||
VkSampler LinearSampler = VK_NULL_HANDLE;
|
||||
|
||||
// descriptors must be valid even if they're skipped dynamically in the shader, so we create
|
||||
|
||||
@@ -1958,7 +1958,8 @@ rdcpair<ResourceId, rdcstr> ReplayController::BuildTargetShader(
|
||||
}
|
||||
|
||||
rdcpair<ResourceId, rdcstr> ReplayController::BuildCustomShader(
|
||||
const char *entry, const char *source, const ShaderCompileFlags &compileFlags, ShaderStage type)
|
||||
const char *entry, ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type)
|
||||
{
|
||||
CHECK_REPLAY_THREAD();
|
||||
|
||||
@@ -1976,10 +1977,19 @@ rdcpair<ResourceId, rdcstr> ReplayController::BuildCustomShader(
|
||||
default: RDCERR("Unexpected type in BuildShader!"); return rdcpair<ResourceId, rdcstr>();
|
||||
}
|
||||
|
||||
m_pDevice->BuildCustomShader(source, entry, compileFlags, type, &id, &errs);
|
||||
RDCLOG("Building custom shader");
|
||||
|
||||
m_pDevice->BuildCustomShader(sourceEncoding, source, entry, compileFlags, type, &id, &errs);
|
||||
|
||||
if(id != ResourceId())
|
||||
{
|
||||
RDCLOG("Successfully built custom shader");
|
||||
m_CustomShaders.insert(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCLOG("Failed to build custom shader");
|
||||
}
|
||||
|
||||
return rdcpair<ResourceId, rdcstr>(id, errs);
|
||||
}
|
||||
|
||||
@@ -153,7 +153,8 @@ public:
|
||||
rdcarray<rdcstr> GetDisassemblyTargets();
|
||||
rdcstr DisassembleShader(ResourceId pipeline, const ShaderReflection *refl, const char *target);
|
||||
|
||||
rdcpair<ResourceId, rdcstr> BuildCustomShader(const char *entry, const char *source,
|
||||
rdcpair<ResourceId, rdcstr> BuildCustomShader(const char *entry, ShaderEncoding sourceEncoding,
|
||||
bytebuf source,
|
||||
const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type);
|
||||
void FreeCustomShader(ResourceId id);
|
||||
|
||||
@@ -137,9 +137,9 @@ public:
|
||||
virtual void GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
|
||||
const GetTextureDataParams ¶ms, bytebuf &data) = 0;
|
||||
|
||||
virtual void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors) = 0;
|
||||
virtual void BuildTargetShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors) = 0;
|
||||
virtual rdcarray<ShaderEncoding> GetTargetShaderEncodings() = 0;
|
||||
virtual void ReplaceResource(ResourceId from, ResourceId to) = 0;
|
||||
virtual void RemoveReplacement(ResourceId id) = 0;
|
||||
@@ -214,9 +214,9 @@ public:
|
||||
const MeshDisplay &cfg) = 0;
|
||||
virtual bool RenderTexture(TextureDisplay cfg) = 0;
|
||||
|
||||
virtual void BuildCustomShader(std::string source, std::string entry,
|
||||
const ShaderCompileFlags &compileFlags, ShaderStage type,
|
||||
ResourceId *id, std::string *errors) = 0;
|
||||
virtual void BuildCustomShader(ShaderEncoding sourceEncoding, bytebuf source,
|
||||
const std::string &entry, const ShaderCompileFlags &compileFlags,
|
||||
ShaderStage type, ResourceId *id, std::string *errors) = 0;
|
||||
virtual rdcarray<ShaderEncoding> GetCustomShaderEncodings() = 0;
|
||||
virtual ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip,
|
||||
uint32_t arrayIdx, uint32_t sampleIdx, CompType typeHint) = 0;
|
||||
|
||||
Reference in new issue
Block a user