From 4b64521ff047906f7d2c88aeb90bc02630e647a0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 4 Aug 2017 16:14:32 +0100 Subject: [PATCH 01/91] Add README mention of v0.x branch --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 956ec02b07..e2669f60a7 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ If you have any questions, suggestions or problems or you can [create an issue]( * **Information for developing/contributing**: [CONTRIBUTING.md](CONTRIBUTING.md), [Compilation instructions](CONTRIBUTING.md#compiling), [Roadmap](https://github.com/baldurk/renderdoc/wiki/Roadmap) * **Code of Conduct**: [Contributor Covenant](CODE_OF_CONDUCT.md) +### v0.x branch + +You are currently viewing the default v0.x branch. This branch is not seeing feature development and only limited bugfix cherry-picking, while development completes on v1.0. You can switch to the v1.x branch to get a (potentially unstable) preview of the current v1.0 build, or choose a v1.x nightly build above. + Screenshots -------------- From c8dd41cdef487be82052992bacc67d2d78105d82 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 4 Aug 2017 16:15:12 +0100 Subject: [PATCH 02/91] Mark v0.90 build --- renderdoc/api/replay/version.h | 2 +- renderdocui/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/renderdoc/api/replay/version.h b/renderdoc/api/replay/version.h index bd2a642088..9878268270 100644 --- a/renderdoc/api/replay/version.h +++ b/renderdoc/api/replay/version.h @@ -94,7 +94,7 @@ // upstream and should not be modified downstream. You can set DISTRIBUTION_VERSION to include any // arbitrary release marker or package version you wish. #define RENDERDOC_VERSION_MAJOR 0 -#define RENDERDOC_VERSION_MINOR 35 +#define RENDERDOC_VERSION_MINOR 90 #define RDOC_INTERNAL_VERSION_STRINGIZE2(a) #a #define RDOC_INTERNAL_VERSION_STRINGIZE(a) RDOC_INTERNAL_VERSION_STRINGIZE2(a) diff --git a/renderdocui/Properties/AssemblyInfo.cs b/renderdocui/Properties/AssemblyInfo.cs index 0020a9d4c8..3880bbd0f4 100644 --- a/renderdocui/Properties/AssemblyInfo.cs +++ b/renderdocui/Properties/AssemblyInfo.cs @@ -59,8 +59,8 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.35.0.0")] -[assembly: AssemblyFileVersion("0.35.0.0")] +[assembly: AssemblyVersion("0.90.0.0")] +[assembly: AssemblyFileVersion("0.90.0.0")] // this can be replaced with the git hash of the commit being built from e.g. in a script [assembly: AssemblyInformationalVersion("NO_GIT_COMMIT_HASH_DEFINED")] From b7795f562d6b147b59f1857a863d133deab542a2 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sun, 6 Aug 2017 09:58:30 +0100 Subject: [PATCH 03/91] Search up the parent heirarchy for a DockContent * Fixes a crash debugging a shader that has embedded source available (i.e. compiled with D3DCOMPILE_DEBUG). --- renderdocui/Windows/ShaderViewer.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/renderdocui/Windows/ShaderViewer.cs b/renderdocui/Windows/ShaderViewer.cs index 5f63cbb33f..ffd0c206bf 100644 --- a/renderdocui/Windows/ShaderViewer.cs +++ b/renderdocui/Windows/ShaderViewer.cs @@ -580,7 +580,19 @@ public ShaderViewer(Core core, ShaderReflection shader, ShaderStageType stage, S AddFileList(); if (trace != null || sel == null) - sel = (DockContent)m_DisassemblyView.Parent; + { + Control p = m_DisassemblyView.Parent; + while (p != null) + { + if (p is DockContent) + { + sel = (DockContent)p; + break; + } + + p = p.Parent; + } + } sel.Show(); } From 11a47bfbe4934e862885fe670fdf2ec358f614f0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 14 Aug 2017 10:54:19 +0100 Subject: [PATCH 04/91] Don't set-up table layout with disasm type selector in debug case * Otherwise it hangs around and breaks the layout when we don't want it to be visible at all --- renderdocui/Windows/ShaderViewer.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/renderdocui/Windows/ShaderViewer.cs b/renderdocui/Windows/ShaderViewer.cs index ffd0c206bf..fcb155e0dd 100644 --- a/renderdocui/Windows/ShaderViewer.cs +++ b/renderdocui/Windows/ShaderViewer.cs @@ -490,12 +490,7 @@ public ShaderViewer(Core core, ShaderReflection shader, ShaderStageType stage, S disasmToolStrip.Items.AddRange(new ToolStripItem[] { disasmTypeLabel, disasmType }); disasmToolStrip.Margin = new Padding(0, 0, 12, 0); - disasmLayoutPanel.ColumnCount = 1; - disasmLayoutPanel.Controls.Add(disasmToolStrip, 0, 0); - disasmLayoutPanel.Controls.Add(m_DisassemblyView, 0, 1); - disasmLayoutPanel.RowCount = 2; - disasmLayoutPanel.RowStyles.Add(new RowStyle()); - disasmLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); + disasmLayoutPanel.Dock = DockStyle.Fill; if (m_Trace == null) { From 643edbe8a780eb241f4f6ecb81fa70214b865af6 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 14 Aug 2017 11:18:11 +0100 Subject: [PATCH 05/91] Fix cases where find results or file list were breaking * The change to make the disassembly view not directly a child of a DockContent but instead a table layout (to add the disassembly type drop-down) were causing some casts of 'thing.Parent' to fail. --- renderdocui/Windows/ShaderViewer.cs | 65 +++++++++++++++++++---------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/renderdocui/Windows/ShaderViewer.cs b/renderdocui/Windows/ShaderViewer.cs index fcb155e0dd..7a85bd5042 100644 --- a/renderdocui/Windows/ShaderViewer.cs +++ b/renderdocui/Windows/ShaderViewer.cs @@ -575,21 +575,10 @@ public ShaderViewer(Core core, ShaderReflection shader, ShaderStageType stage, S AddFileList(); if (trace != null || sel == null) - { - Control p = m_DisassemblyView.Parent; - while (p != null) - { - if (p is DockContent) - { - sel = (DockContent)p; - break; - } + sel = DockContentFor(m_DisassemblyView); - p = p.Parent; - } - } - - sel.Show(); + if(sel != null) + sel.Show(); } ShowConstants(); @@ -712,7 +701,11 @@ void list_SelectedIndexChanged(object sender, EventArgs e) int idx = m_FileList.SelectedIndex; if (idx >= 0 && idx < m_Scintillas.Count) - (m_Scintillas[idx].Parent as DockContent).Show(); + { + DockContent dock = DockContentFor(m_Scintillas[idx]); + if (dock != null) + dock.Show(); + } } private void AddFileList() @@ -727,7 +720,11 @@ private void AddFileList() m_FileList.SelectedIndexChanged += new EventHandler(list_SelectedIndexChanged); foreach (ScintillaNET.Scintilla s in m_Scintillas) - m_FileList.Items.Add((s.Parent as DockContent).Text); + { + DockContent dock = DockContentFor(s); + if(dock != null) + m_FileList.Items.Add(dock.Text); + } var w = Helpers.WrapDockContent(dockPanel, m_FileList, "File List"); w.DockState = DockState.DockLeft; @@ -839,7 +836,11 @@ void FindAllFiles() w.DockAreas |= DockAreas.Float; w.DockState = DockState.DockBottom; w.HideOnClose = true; - w.Show((m_Scintillas[0].Parent as DockContent).Pane, DockAlignment.Bottom, 0.5); + DockContent dock = DockContentFor(m_Scintillas[0]); + if(dock != null) + w.Show(dock.Pane, DockAlignment.Bottom, 0.5); + else + w.Show(); } else { @@ -886,7 +887,11 @@ void FindAllFiles() foreach (var kv in findResultsByEd) { - string filename = (kv.Key.Parent as DockContent).Text; + DockContent dock = DockContentFor(kv.Key); + if (dock == null) + continue; + + string filename = dock.Text; if (kv.Value.Count > 0) fileCount++; @@ -935,10 +940,13 @@ void findResults_DoubleClick(object sender, EventArgs e) int idx = line - 1; - DockContent dc = (m_FindResults[idx].Key.Parent as DockContent); + DockContent dc = DockContentFor(m_FindResults[idx].Key); - dc.Activate(); - dc.Show(); + if (dc != null) + { + dc.Activate(); + dc.Show(); + } m_FindResults[idx].Key.GoTo.Line(m_FindResults[idx].Value.StartingLine.Number); @@ -2391,5 +2399,20 @@ private void findinall_Click(object sender, EventArgs e) { ShowFindAll(); } + + private DockContent DockContentFor(Control c) + { + Control p = c.Parent; + while (p != null) + { + if (p is DockContent) + return (DockContent)p; + + p = p.Parent; + } + + return null; + } + } } \ No newline at end of file From a658a1a38b4d501ee488b49acbf159a96c770f7d Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 14 Aug 2017 11:36:36 +0100 Subject: [PATCH 06/91] Add a note about the v0.x branch to the top of CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f412a4ded2..0820023d52 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,7 @@ +# Soft-locked branch + +This branch (v0.x) is soft-locked. Active development is continuing on the v1.x branch, and v0.x will only get cherry-picked fixes. Please open all PRs against v1.x, and changes will be manually moved across to v0.x as and when needed. + # Contributing to RenderDoc ---- From 965d5bbcfb5cda1973d921b73782ada33afaff18 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 14 Aug 2017 12:57:14 +0100 Subject: [PATCH 07/91] Mark v0.91 build --- renderdoc/api/replay/version.h | 2 +- renderdocui/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/renderdoc/api/replay/version.h b/renderdoc/api/replay/version.h index 9878268270..5d602ab2eb 100644 --- a/renderdoc/api/replay/version.h +++ b/renderdoc/api/replay/version.h @@ -94,7 +94,7 @@ // upstream and should not be modified downstream. You can set DISTRIBUTION_VERSION to include any // arbitrary release marker or package version you wish. #define RENDERDOC_VERSION_MAJOR 0 -#define RENDERDOC_VERSION_MINOR 90 +#define RENDERDOC_VERSION_MINOR 91 #define RDOC_INTERNAL_VERSION_STRINGIZE2(a) #a #define RDOC_INTERNAL_VERSION_STRINGIZE(a) RDOC_INTERNAL_VERSION_STRINGIZE2(a) diff --git a/renderdocui/Properties/AssemblyInfo.cs b/renderdocui/Properties/AssemblyInfo.cs index 3880bbd0f4..fbc36ed586 100644 --- a/renderdocui/Properties/AssemblyInfo.cs +++ b/renderdocui/Properties/AssemblyInfo.cs @@ -59,8 +59,8 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.90.0.0")] -[assembly: AssemblyFileVersion("0.90.0.0")] +[assembly: AssemblyVersion("0.91.0.0")] +[assembly: AssemblyFileVersion("0.91.0.0")] // this can be replaced with the git hash of the commit being built from e.g. in a script [assembly: AssemblyInformationalVersion("NO_GIT_COMMIT_HASH_DEFINED")] From 2d8b2cf818746b6a2add54e2fef449398816a40c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 11 Aug 2017 23:06:19 -0700 Subject: [PATCH 08/91] Update README.md to reflect OS support for Linux --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2669f60a7..530d226a09 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ RenderDoc [![Coverity Scan](https://scan.coverity.com/projects/8525/badge.svg)](https://scan.coverity.com/projects/baldurk-renderdoc) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.md) -RenderDoc - a graphics debugger, currently available for Vulkan, D3D11, D3D12, and OpenGL development on windows. +RenderDoc - a graphics debugger, currently available for Vulkan, D3D11, D3D12, and OpenGL development on Windows 7 - 10 and Linux. If you have any questions, suggestions or problems or you can [create an issue](https://github.com/baldurk/renderdoc/issues/new) here on github, [email me directly](mailto:baldurk@baldurk.org) or [come into IRC](https://kiwiirc.com/client/irc.freenode.net/#renderdoc) to discuss it. From 110e510bd24ee108eb31da40072bfb8e5a97c467 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 14 Aug 2017 16:33:31 +0100 Subject: [PATCH 09/91] Don't try to break apart single float values that were merged --- renderdoc/driver/d3d11/d3d11_analyse.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index c3977f93f1..7a463535bf 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -1554,7 +1554,8 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t eventID, uint32_t x, uin { const SigParameter &prev = dxbc->m_InputSig[i - 1]; - if(prev.compCount <= 2 && prev.regChannelMask <= 0x3) + if(prev.regIndex != dxbc->m_InputSig[i].regIndex && prev.compCount <= 2 && + prev.regChannelMask <= 0x3) arrayLength = 1; } From 74e989dbde0d5e7c6ec82df11f4de68cda4605c0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 14 Aug 2017 16:33:49 +0100 Subject: [PATCH 10/91] Fix broken implementation of round_ne opcode rounding to nearest even --- renderdoc/driver/shaders/dxbc/dxbc_debug.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index ccac64b471..28f5573229 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -39,12 +39,12 @@ namespace ShaderDebug { static float round_ne(float x) { - // if on 0.5 boundary - if(int(x + 0.5f) != int(x)) - return int(x) % 2 == 0 ? float(int(x)) : float(int(x + 1)); + if(!_finitef(x) || _isnanf(x)) + return x; - // normal round - return x < 0 ? x + 0.5f : x; + float rem = remainderf(x, 1.0f); + + return x - rem; } VarType State::OperationType(const OpcodeType &op) const From a45f7f5ab04598f96a1d6072a285ee42b47a176f Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 14 Aug 2017 19:09:38 +0100 Subject: [PATCH 11/91] Fix 32-bit compilation, _finitef is not available on x86 --- renderdoc/driver/shaders/dxbc/dxbc_debug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 28f5573229..16c9d88a63 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -39,7 +39,7 @@ namespace ShaderDebug { static float round_ne(float x) { - if(!_finitef(x) || _isnanf(x)) + if(!_finite(x) || _isnan(x)) return x; float rem = remainderf(x, 1.0f); From eb7d343fbc5aeb44dc15e0f2e70d947758347101 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 15 Aug 2017 11:14:01 +0100 Subject: [PATCH 12/91] Only add an extra access chain index before looping, not each time * This would cause an extra index every time for every array element leading to far too long access chains for arrayed outputs longer than 1 element. --- renderdoc/driver/shaders/spirv/spirv_disassemble.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp index 1ce4fb1932..ff3a1bc2df 100644 --- a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp @@ -3825,14 +3825,14 @@ void AddSignatureParameter(bool isInput, ShaderStage stage, uint32_t id, sig.regChannelMask = sig.channelUsedMask = (1 << type->vectorSize) - 1; + // arrays will need an extra access chain index + if(isArray) + patch.accessChain.push_back(0U); + for(uint32_t a = 0; a < arraySize; a++) { string n = varName; - // arrays will need an extra access chain index - if(arraySize > 1) - patch.accessChain.push_back(0U); - if(isArray) { n = StringFormat::Fmt("%s[%u]", varName.c_str(), a); @@ -3866,7 +3866,7 @@ void AddSignatureParameter(bool isInput, ShaderStage stage, uint32_t id, } sig.regIndex += RDCMAX(1U, type->matrixSize); - if(arraySize > 1) + if(isArray) patch.accessChain.back()++; } } From 58359e42accedd0c6eb7d2991314e30eaa85b819 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 15 Aug 2017 12:57:20 +0100 Subject: [PATCH 13/91] Fetch SRV buffer format descriptor from declaration if not in SRV * It's seemingly possible to bind a structured SRV with no format given, to a Buffer declaration in the shader. In this case we can't get the buffer stride/format type from the SRV itself so we have to go to what's declared in the reflection data itself. --- renderdoc/driver/d3d11/d3d11_analyse.cpp | 39 +++++++++++++++++++ renderdoc/driver/shaders/dxbc/dxbc_debug.cpp | 3 +- renderdoc/driver/shaders/dxbc/dxbc_debug.h | 20 ++++------ .../driver/shaders/dxbc/dxbc_inspect.cpp | 4 ++ 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index 7a463535bf..834421fe84 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -833,6 +833,45 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global sdesc.Format == DXGI_FORMAT_R10G10B10A2_UNORM) global.srvs[i].format.byteWidth = 10; } + else + { + D3D11_RESOURCE_DIMENSION dim; + res->GetType(&dim); + + if(dim == D3D11_RESOURCE_DIMENSION_BUFFER) + { + ID3D11Buffer *buf = (ID3D11Buffer *)res; + D3D11_BUFFER_DESC bufdesc; + buf->GetDesc(&bufdesc); + + global.srvs[i].format.stride = bufdesc.StructureByteStride; + + // if we didn't get a type from the SRV description, try to pull it from the declaration + for(const DXBC::ShaderInputBind &bind : dxbc->m_Resources) + { + if(bind.reg == (uint32_t)i && bind.dimension == DXBC::ShaderInputBind::DIM_BUFFER && + bind.retType < DXBC::ShaderInputBind::RETTYPE_MIXED && + bind.retType != DXBC::ShaderInputBind::RETTYPE_UNKNOWN) + { + global.srvs[i].format.byteWidth = 4; + global.srvs[i].format.numComps = bind.numSamples; + + if(bind.retType == DXBC::ShaderInputBind::RETTYPE_UNORM) + global.srvs[i].format.fmt = CompType::UNorm; + else if(bind.retType == DXBC::ShaderInputBind::RETTYPE_SNORM) + global.srvs[i].format.fmt = CompType::SNorm; + else if(bind.retType == DXBC::ShaderInputBind::RETTYPE_UINT) + global.srvs[i].format.fmt = CompType::UInt; + else if(bind.retType == DXBC::ShaderInputBind::RETTYPE_SINT) + global.srvs[i].format.fmt = CompType::SInt; + else + global.srvs[i].format.fmt = CompType::Float; + + break; + } + } + } + } if(sdesc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER) { diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 16c9d88a63..a059a4fa40 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -2545,6 +2545,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const fmt.byteWidth = 4; fmt.numComps = global.groupshared[resIndex].bytestride / 4; fmt.reversed = false; + fmt.stride = 0; } texData = false; } @@ -2555,7 +2556,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const if(texData) { - texOffset += texCoords[0] * fmt.byteWidth * fmt.numComps; + texOffset += texCoords[0] * fmt.Stride(); texOffset += texCoords[1] * rowPitch; texOffset += texCoords[2] * depthPitch; } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.h b/renderdoc/driver/shaders/dxbc/dxbc_debug.h index 183f2f0d46..4c462d2a5c 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.h @@ -57,21 +57,17 @@ struct GlobalState struct ViewFmt { - ViewFmt() - { - byteWidth = 0; - numComps = 0; - reversed = false; - fmt = CompType::Typeless; - } - - int byteWidth; - int numComps; - bool reversed; - CompType fmt; + int byteWidth = 0; + int numComps = 0; + bool reversed = false; + CompType fmt = CompType::Typeless; + int stride = 0; int Stride() { + if(stride != 0) + return stride; + if(byteWidth == 10 || byteWidth == 11) return 32; // 10 10 10 2 or 11 11 10 diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp index 8468eee53d..a7d84cd80b 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp @@ -1087,6 +1087,10 @@ void DXBCFile::GuessResources() } desc.numSamples = dcl.sampleCount; + // can't tell, fxc seems to default to 4 + if(desc.dimension == ShaderInputBind::DIM_BUFFER) + desc.numSamples = 4; + RDCASSERT(desc.dimension != ShaderInputBind::DIM_UNKNOWN); if(dcl.operand.indices.size() == 3) From cb52d2de6d19094d6961b87a981c16311bdccb96 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 15 Aug 2017 13:09:58 +0100 Subject: [PATCH 14/91] Flush texture overlay cache whenever texture ID or type hint changes * Even if the overlay didn't change, a new texture ID requires a re-draw of the overlay. --- renderdoc/replay/replay_output.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/renderdoc/replay/replay_output.cpp b/renderdoc/replay/replay_output.cpp index 32ebad8825..1b18351937 100644 --- a/renderdoc/replay/replay_output.cpp +++ b/renderdoc/replay/replay_output.cpp @@ -119,7 +119,8 @@ ReplayOutput::~ReplayOutput() void ReplayOutput::SetTextureDisplay(const TextureDisplay &o) { - if(o.overlay != m_RenderData.texDisplay.overlay) + if(o.overlay != m_RenderData.texDisplay.overlay || + o.typeHint != m_RenderData.texDisplay.typeHint || o.texid != m_RenderData.texDisplay.texid) { if(m_RenderData.texDisplay.overlay == DebugOverlay::ClearBeforeDraw || m_RenderData.texDisplay.overlay == DebugOverlay::ClearBeforePass) From dc8a962eb6cdda8a2f5a63314ac9d9afac467702 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 15 Aug 2017 16:40:52 +0100 Subject: [PATCH 15/91] Add handling for min precision in DXBC bytecode. Refs #720 * This includes ISG1 and OSG1 chunk types which have an extra enum on the end for the minimum precision type. * Also add extra casing for min precision types (although anywhere they are on an externally-facing interface, they're not actually min precision). --- renderdoc/driver/d3d11/d3d11_analyse.cpp | 8 +++- renderdoc/driver/d3d11/d3d11_common.cpp | 6 +++ renderdoc/driver/d3d12/d3d12_common.cpp | 6 +++ renderdoc/driver/d3d12/d3d12_debug.cpp | 8 +++- .../driver/shaders/dxbc/dxbc_disassemble.cpp | 8 +++- .../driver/shaders/dxbc/dxbc_disassemble.h | 3 ++ .../driver/shaders/dxbc/dxbc_inspect.cpp | 46 +++++++++++++++++-- renderdoc/driver/shaders/dxbc/dxbc_inspect.h | 6 +++ 8 files changed, 82 insertions(+), 9 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index 834421fe84..0fc0ab2a90 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -162,11 +162,17 @@ void D3D11DebugManager::FillCBufferVariables(const string &prefix, size_t &offse VarType type = VarType::Float; switch(invars[v].type.descriptor.type) { + case VARTYPE_MIN12INT: + case VARTYPE_MIN16INT: case VARTYPE_INT: type = VarType::Int; break; + case VARTYPE_MIN8FLOAT: + case VARTYPE_MIN10FLOAT: + case VARTYPE_MIN16FLOAT: case VARTYPE_FLOAT: type = VarType::Float; break; case VARTYPE_BOOL: case VARTYPE_UINT: - case VARTYPE_UINT8: type = VarType::UInt; break; + case VARTYPE_UINT8: + case VARTYPE_MIN16UINT: type = VarType::UInt; break; case VARTYPE_DOUBLE: elemByteSize = 8; type = VarType::Double; diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index c23c27d4f9..233138215d 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -661,11 +661,17 @@ static ShaderVariableType MakeShaderVariableType(DXBC::CBufferVariableType type, switch(type.descriptor.type) { + case DXBC::VARTYPE_MIN12INT: + case DXBC::VARTYPE_MIN16INT: case DXBC::VARTYPE_INT: ret.descriptor.type = VarType::Int; break; case DXBC::VARTYPE_BOOL: + case DXBC::VARTYPE_MIN16UINT: case DXBC::VARTYPE_UINT: ret.descriptor.type = VarType::UInt; break; case DXBC::VARTYPE_DOUBLE: ret.descriptor.type = VarType::Double; break; case DXBC::VARTYPE_FLOAT: + case DXBC::VARTYPE_MIN8FLOAT: + case DXBC::VARTYPE_MIN10FLOAT: + case DXBC::VARTYPE_MIN16FLOAT: default: ret.descriptor.type = VarType::Float; break; } ret.descriptor.rows = type.descriptor.rows; diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index fb4ffccd59..05f8947919 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -371,11 +371,17 @@ static ShaderVariableType MakeShaderVariableType(DXBC::CBufferVariableType type, switch(type.descriptor.type) { + case DXBC::VARTYPE_MIN12INT: + case DXBC::VARTYPE_MIN16INT: case DXBC::VARTYPE_INT: ret.descriptor.type = VarType::Int; break; case DXBC::VARTYPE_BOOL: + case DXBC::VARTYPE_MIN16UINT: case DXBC::VARTYPE_UINT: ret.descriptor.type = VarType::UInt; break; case DXBC::VARTYPE_DOUBLE: ret.descriptor.type = VarType::Double; break; case DXBC::VARTYPE_FLOAT: + case DXBC::VARTYPE_MIN8FLOAT: + case DXBC::VARTYPE_MIN10FLOAT: + case DXBC::VARTYPE_MIN16FLOAT: default: ret.descriptor.type = VarType::Float; break; } ret.descriptor.rows = type.descriptor.rows; diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 8f5e9e3851..7f695e1404 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -2916,11 +2916,17 @@ void D3D12DebugManager::FillCBufferVariables(const string &prefix, size_t &offse VarType type = VarType::Float; switch(invars[v].type.descriptor.type) { + case VARTYPE_MIN12INT: + case VARTYPE_MIN16INT: case VARTYPE_INT: type = VarType::Int; break; + case VARTYPE_MIN8FLOAT: + case VARTYPE_MIN10FLOAT: + case VARTYPE_MIN16FLOAT: case VARTYPE_FLOAT: type = VarType::Float; break; case VARTYPE_BOOL: case VARTYPE_UINT: - case VARTYPE_UINT8: type = VarType::UInt; break; + case VARTYPE_UINT8: + case VARTYPE_MIN16UINT: type = VarType::UInt; break; case VARTYPE_DOUBLE: elemByteSize = 8; type = VarType::Double; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp index e4edd019d6..efd17d1bc8 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp @@ -1338,13 +1338,17 @@ string ASMOperand::toString(DXBCFile *dxbc, ToString flags) const { str += " {"; if(precision == PRECISION_FLOAT10) - str += "min2_8f as def32"; + str += "min10f"; if(precision == PRECISION_FLOAT16) - str += "min16f as def32"; + str += "min16f"; if(precision == PRECISION_UINT16) str += "min16u"; if(precision == PRECISION_SINT16) str += "min16i"; + if(precision == PRECISION_ANY16) + str += "any16"; + if(precision == PRECISION_ANY10) + str += "any10"; str += "}"; } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.h b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.h index 262952ad8b..b43d8b3828 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.h @@ -490,8 +490,11 @@ enum MinimumPrecision PRECISION_DEFAULT, PRECISION_FLOAT16, PRECISION_FLOAT10, + PRECISION_UNUSED, PRECISION_SINT16, PRECISION_UINT16, + PRECISION_ANY16, + PRECISION_ANY10, NUM_PRECISIONS, }; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp index a7d84cd80b..97a472afb1 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp @@ -205,6 +205,13 @@ struct SIGNElement7 SIGNElement elem; }; +struct SIGNElement1 +{ + uint32_t stream; + SIGNElement elem; + MinimumPrecision precision; +}; + static const uint32_t STATSizeDX10 = 29 * 4; // either 29 uint32s static const uint32_t STATSizeDX11 = 37 * 4; // or 37 uint32s @@ -218,6 +225,8 @@ static const uint32_t FOURCC_SDBG = MAKE_FOURCC('S', 'D', 'B', 'G'); static const uint32_t FOURCC_SPDB = MAKE_FOURCC('S', 'P', 'D', 'B'); static const uint32_t FOURCC_ISGN = MAKE_FOURCC('I', 'S', 'G', 'N'); static const uint32_t FOURCC_OSGN = MAKE_FOURCC('O', 'S', 'G', 'N'); +static const uint32_t FOURCC_ISG1 = MAKE_FOURCC('I', 'S', 'G', '1'); +static const uint32_t FOURCC_OSG1 = MAKE_FOURCC('O', 'S', 'G', '1'); static const uint32_t FOURCC_OSG5 = MAKE_FOURCC('O', 'S', 'G', '5'); static const uint32_t FOURCC_PCSG = MAKE_FOURCC('P', 'C', 'S', 'G'); static const uint32_t FOURCC_Aon9 = MAKE_FOURCC('A', 'o', 'n', '9'); @@ -231,7 +240,16 @@ int TypeByteSize(VariableType t) case VARTYPE_BOOL: case VARTYPE_INT: case VARTYPE_FLOAT: - case VARTYPE_UINT: return 4; + case VARTYPE_UINT: + return 4; + // we pretend for our purposes that the 'min' formats round up to 4 bytes. For any external + // interfaces they are treated as regular types, only using lower precision internally. + case VARTYPE_MIN8FLOAT: + case VARTYPE_MIN10FLOAT: + case VARTYPE_MIN16FLOAT: + case VARTYPE_MIN12INT: + case VARTYPE_MIN16INT: + case VARTYPE_MIN16UINT: return 4; case VARTYPE_DOUBLE: return 8; // 'virtual' type. Just return 1 @@ -286,6 +304,12 @@ string TypeName(CBufferVariableType::Descriptor desc) case VARTYPE_UINT8: type = "ubyte"; break; case VARTYPE_VOID: type = "void"; break; case VARTYPE_INTERFACE_POINTER: type = "interface"; break; + case VARTYPE_MIN8FLOAT: type = "min8float"; break; + case VARTYPE_MIN10FLOAT: type = "min10float"; break; + case VARTYPE_MIN16FLOAT: type = "min16float"; break; + case VARTYPE_MIN12INT: type = "min12int"; break; + case VARTYPE_MIN16INT: type = "min16int"; break; + case VARTYPE_MIN16UINT: type = "min16uint"; break; default: RDCERR("Unexpected type in RDEF variable type %d", type); } @@ -830,8 +854,8 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength) char *chunkContents = (char *)(data + chunkOffsets[chunkIdx] + sizeof(uint32_t) * 2); - if(*fourcc == FOURCC_ISGN || *fourcc == FOURCC_OSGN || *fourcc == FOURCC_OSG5 || - *fourcc == FOURCC_PCSG) + if(*fourcc == FOURCC_ISGN || *fourcc == FOURCC_OSGN || *fourcc == FOURCC_ISG1 || + *fourcc == FOURCC_OSG1 || *fourcc == FOURCC_OSG5 || *fourcc == FOURCC_PCSG) { SIGNHeader *sign = (SIGNHeader *)fourcc; @@ -841,12 +865,12 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength) bool output = false; bool patch = false; - if(*fourcc == FOURCC_ISGN) + if(*fourcc == FOURCC_ISGN || *fourcc == FOURCC_ISG1) { sig = &m_InputSig; input = true; } - if(*fourcc == FOURCC_OSGN || *fourcc == FOURCC_OSG5) + if(*fourcc == FOURCC_OSGN || *fourcc == FOURCC_OSG1 || *fourcc == FOURCC_OSG5) { sig = &m_OutputSig; output = true; @@ -861,11 +885,22 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength) SIGNElement *el = (SIGNElement *)(sign + 1); SIGNElement7 *el7 = (SIGNElement7 *)el; + SIGNElement1 *el1 = (SIGNElement1 *)el; for(uint32_t signIdx = 0; signIdx < sign->numElems; signIdx++) { SigParameter desc; + if(*fourcc == FOURCC_ISG1 || *fourcc == FOURCC_OSG1) + { + desc.stream = el1->stream; + + // discard el1->precision as we don't use it and don't want to pollute the common API + // structures + + el = &el1->elem; + } + if(*fourcc == FOURCC_OSG5) { desc.stream = el7->stream; @@ -956,6 +991,7 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength) sig->push_back(desc); el++; + el1++; el7++; } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.h b/renderdoc/driver/shaders/dxbc/dxbc_inspect.h index 0ff2daaf5a..74218029f4 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.h @@ -109,6 +109,12 @@ enum VariableType VARTYPE_RWSTRUCTURED_BUFFER, VARTYPE_APPEND_STRUCTURED_BUFFER, VARTYPE_CONSUME_STRUCTURED_BUFFER, + VARTYPE_MIN8FLOAT, + VARTYPE_MIN10FLOAT, + VARTYPE_MIN16FLOAT, + VARTYPE_MIN12INT, + VARTYPE_MIN16INT, + VARTYPE_MIN16UINT, }; struct ShaderInputBind From 5d100c2f624fe244dec6255d0bf6bf8fda54c687 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 15 Aug 2017 17:10:02 +0100 Subject: [PATCH 16/91] Use glXGetProcAddress to fetch glXCreateContextAttribsARB. Refs #716 * Most functions we hook and then jump to the real driver we can fetch just with dlsym to the library, but the ARB context creation function is an extension and may not be directly exported. * It's safe to call glXGetProcAddress(ARB) without a context current though and it's guaranteed to be directly exported, so we can use this to fetch the function if we don't find it with dlsym. --- renderdoc/driver/gl/gl_hooks_linux.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/renderdoc/driver/gl/gl_hooks_linux.cpp b/renderdoc/driver/gl/gl_hooks_linux.cpp index ed79f2935c..ba8acef334 100644 --- a/renderdoc/driver/gl/gl_hooks_linux.cpp +++ b/renderdoc/driver/gl/gl_hooks_linux.cpp @@ -42,6 +42,7 @@ typedef XVisualInfo *(*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display *dpy, GLXFBConfi typedef int (*PFNGLXGETCONFIGPROC)(Display *dpy, XVisualInfo *vis, int attrib, int *value); typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display *dpy, int *errorBase, int *eventBase); typedef Bool (*PFNGLXISDIRECTPROC)(Display *dpy, GLXContext ctx); +typedef __GLXextFuncPtr (*PFNGLXGETPROCADDRESSARBPROC)(const GLubyte *procName); class OpenGLHook : LibraryHook, public GLPlatform { @@ -363,6 +364,7 @@ class OpenGLHook : LibraryHook, public GLPlatform PFNGLXDESTROYCONTEXTPROC glXDestroyContext_real; PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB_real; PFNGLXGETPROCADDRESSPROC glXGetProcAddress_real; + PFNGLXGETPROCADDRESSARBPROC glXGetProcAddressARB_real; PFNGLXMAKECURRENTPROC glXMakeCurrent_real; PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent_real; PFNGLXSWAPBUFFERSPROC glXSwapBuffers_real; @@ -388,6 +390,9 @@ class OpenGLHook : LibraryHook, public GLPlatform if(glXGetProcAddress_real == NULL) glXGetProcAddress_real = (PFNGLXGETPROCADDRESSPROC)dlsym(libGLdlsymHandle, "glXGetProcAddress"); + if(glXGetProcAddressARB_real == NULL) + glXGetProcAddressARB_real = + (PFNGLXGETPROCADDRESSPROC)dlsym(libGLdlsymHandle, "glXGetProcAddressARB"); if(glXCreateContext_real == NULL) glXCreateContext_real = (PFNGLXCREATECONTEXTPROC)dlsym(libGLdlsymHandle, "glXCreateContext"); if(glXDestroyContext_real == NULL) @@ -418,6 +423,15 @@ class OpenGLHook : LibraryHook, public GLPlatform if(glXQueryDrawable_real == NULL) glXQueryDrawable_real = (PFNGLXQUERYDRAWABLEPROC)dlsym(RTLD_NEXT, "glXQueryDrawable"); + // glXCreateContextAttribsARB may not be directly exported by libGL.so, so try to fetch it + // through the glXGetProcAddress function, favouring the ARB variant. + if(glXCreateContextAttribsARB_real == NULL && glXGetProcAddressARB_real) + glXCreateContextAttribsARB_real = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddressARB_real( + (const GLubyte *)"glXCreateContextAttribsARB"); + if(glXCreateContextAttribsARB_real == NULL && glXGetProcAddress_real) + glXCreateContextAttribsARB_real = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress_real( + (const GLubyte *)"glXCreateContextAttribsARB"); + return success; } From d5d51aa516c80cf6bc695d077e13e627412b7b86 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 15 Aug 2017 17:26:36 +0100 Subject: [PATCH 17/91] Only unwrap elements in VkDescriptorImageInfo that should be valid * In particular for e.g. elements that don't require a sampler, the VkSampler may point to a random address if it's uninitialised, and we shouldn't try to access it at all. --- .../vulkan/wrappers/vk_descriptor_funcs.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp index b5a859547c..e7315056c3 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp @@ -663,6 +663,11 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, VkBufferView *bufViews = (VkBufferView *)bufInfos; nextDescriptors += pDescriptorWrites[i].descriptorCount; + RDCCOMPILE_ASSERT(sizeof(VkDescriptorBufferInfo) >= sizeof(VkDescriptorImageInfo), + "Structure sizes mean not enough space is allocated for write data"); + RDCCOMPILE_ASSERT(sizeof(VkDescriptorBufferInfo) >= sizeof(VkBufferView), + "Structure sizes mean not enough space is allocated for write data"); + // unwrap and assign the appropriate array if(pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER || pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) @@ -677,11 +682,22 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount, pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE || pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) { + bool hasSampler = + (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || + pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + bool hasImage = + (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || + pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || + pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE || + pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT); + unwrappedWrites[i].pImageInfo = (VkDescriptorImageInfo *)bufInfos; for(uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++) { - imInfos[j].imageView = Unwrap(pDescriptorWrites[i].pImageInfo[j].imageView); - imInfos[j].sampler = Unwrap(pDescriptorWrites[i].pImageInfo[j].sampler); + if(hasImage) + imInfos[j].imageView = Unwrap(pDescriptorWrites[i].pImageInfo[j].imageView); + if(hasSampler) + imInfos[j].sampler = Unwrap(pDescriptorWrites[i].pImageInfo[j].sampler); imInfos[j].imageLayout = pDescriptorWrites[i].pImageInfo[j].imageLayout; } } From 3d9a26cd8fc2a42aad3dda80ab065812ce8e2d13 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 16 Aug 2017 16:24:43 +0100 Subject: [PATCH 18/91] Fall back to creating a non-SRGB capable fbconfig. Refs #721 * In some cases it seems that no sRGB fbconfigs are available, so we fall back and create a non-SRGB one. This may render incorrectly but at least it should run without crashing. --- renderdoc/driver/gl/gl_hooks_linux.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/renderdoc/driver/gl/gl_hooks_linux.cpp b/renderdoc/driver/gl/gl_hooks_linux.cpp index ba8acef334..0c632121c0 100644 --- a/renderdoc/driver/gl/gl_hooks_linux.cpp +++ b/renderdoc/driver/gl/gl_hooks_linux.cpp @@ -253,6 +253,8 @@ class OpenGLHook : LibraryHook, public GLPlatform RDCERR("Unexpected window system %u", system); } + // GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB MUST be the last attrib so that we can remove it to retry + // if we find no srgb fbconfigs static int visAttribs[] = {GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, @@ -272,9 +274,26 @@ class OpenGLHook : LibraryHook, public GLPlatform GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, True, 0}; + int numCfgs = 0; GLXFBConfig *fbcfg = glXChooseFBConfig_real(dpy, DefaultScreen(dpy), visAttribs, &numCfgs); + if(fbcfg == NULL) + { + const size_t len = ARRAY_COUNT(visAttribs); + if(visAttribs[len - 3] != GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB) + { + RDCERR( + "GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB isn't the last attribute, and no SRGB fbconfigs were " + "found!"); + } + else + { + visAttribs[len - 3] = 0; + fbcfg = glXChooseFBConfig_real(dpy, DefaultScreen(dpy), visAttribs, &numCfgs); + } + } + if(fbcfg == NULL) { RDCERR("Couldn't choose default framebuffer config"); From 58cf0cd7fd4e14e4e350d62066d31af6e3189267 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 16 Aug 2017 16:25:29 +0100 Subject: [PATCH 19/91] Add default initialisation for tag object, fixes a warning on gcc --- qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp index 8867a1bc1c..a04eff10a6 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp @@ -1829,7 +1829,7 @@ void D3D11PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in } else if(buf) { - D3D11ViewTag view; + D3D11ViewTag view = {}; if(tag.canConvert()) view = tag.value(); From 83e1e1506ba5ad1df2ef0133cacfc24789f52f50 Mon Sep 17 00:00:00 2001 From: Cody Northrop Date: Mon, 24 Jul 2017 20:15:30 -0600 Subject: [PATCH 20/91] android: Update packaging to work with latest SDK This removes dependencies on deprecated tools "ant" and "android project" The new method relies on JAVA_HOME and ANDROID_SDK being set. It also requires specific versions of the Android build-tools (26.0.1) and platforms (android-23). See updates to CONTRIBUTING.md and our Travis-CI config for details. Travis-CI and documentation also roll forward to latest public NDK r14b. --- renderdoccmd/CMakeLists.txt | 42 +++++++++++++++++++++++++-------- scripts/travis/android_setup.sh | 1 + 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/renderdoccmd/CMakeLists.txt b/renderdoccmd/CMakeLists.txt index c748dccd53..6cbf8a1d24 100644 --- a/renderdoccmd/CMakeLists.txt +++ b/renderdoccmd/CMakeLists.txt @@ -57,23 +57,45 @@ target_link_libraries(renderdoccmd ${libraries}) install (TARGETS renderdoccmd DESTINATION bin) if(ANDROID) + if(NOT DEFINED ENV{JAVA_HOME}) + message(FATAL_ERROR "JAVA_HOME environment variable must be defined for Android build") + endif() + if(NOT DEFINED ENV{ANDROID_SDK}) + message(FATAL_ERROR "ANDROID_SDK environment variable must be defined for Android build") + endif() + + set(BUILD_TOOLS "$ENV{ANDROID_SDK}/build-tools/26.0.1") + set(ANDROID_JAR "$ENV{ANDROID_SDK}/platforms/android-23/android.jar") + set(RT_JAR "$ENV{JAVA_HOME}/jre/lib/rt.jar") + set(JAVA_BIN "$ENV{JAVA_HOME}/bin") + set(APK_TARGET_ID "android-23" CACHE STRING "The Target ID to build the APK for, use to choose another one.") + set(KEYSTORE ${CMAKE_CURRENT_BINARY_DIR}/debug.keystore) + add_custom_command(OUTPUT ${KEYSTORE} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${JAVA_BIN}/keytool -genkey -keystore ${KEYSTORE} -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=, OU=, O=, L=, S=, C=") set(APK_FILE ${CMAKE_BINARY_DIR}/bin/RenderDocCmd.apk) add_custom_target(apk ALL - DEPENDS ${APK_FILE}) + DEPENDS ${APK_FILE} + DEPENDS ${KEYSTORE}) + add_custom_command(OUTPUT ${APK_FILE} DEPENDS renderdoc DEPENDS renderdoccmd WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/android ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E make_directory libs/${ANDROID_ABI} - COMMAND ${CMAKE_COMMAND} -E copy $ libs/${ANDROID_ABI}/libVkLayer_GLES_RenderDoc.so - COMMAND ${CMAKE_COMMAND} -E copy $ libs/${ANDROID_ABI}/$ - COMMAND android update project --path . --name RenderDocCmd --target ${APK_TARGET_ID} - COMMAND ant debug - COMMAND ${CMAKE_COMMAND} -E copy bin/RenderDocCmd-debug.apk ${APK_FILE} - COMMAND ${CMAKE_COMMAND} -E make_directory libs/lib - COMMAND ${CMAKE_COMMAND} -E copy_directory libs/${ANDROID_ABI} libs/lib/${ANDROID_ABI} - COMMAND ${CMAKE_COMMAND} -E remove_directory libs/${ANDROID_ABI}) + COMMAND ${CMAKE_COMMAND} -E make_directory libs/lib/${ANDROID_ABI} + COMMAND ${CMAKE_COMMAND} -E make_directory obj + COMMAND ${CMAKE_COMMAND} -E make_directory bin + COMMAND ${CMAKE_COMMAND} -E copy $ libs/lib/${ANDROID_ABI}/libVkLayer_GLES_RenderDoc.so + COMMAND ${CMAKE_COMMAND} -E copy $ libs/lib/${ANDROID_ABI}/$ + COMMAND ${BUILD_TOOLS}/aapt package -f -m -S res -J src -M AndroidManifest.xml -I ${ANDROID_JAR} + COMMAND ${JAVA_BIN}/javac -d ./obj -source 1.7 -target 1.7 -bootclasspath ${RT_JAR} -classpath ${ANDROID_JAR}:obj -sourcepath src src/org/renderdoc/renderdoccmd/*.java + COMMAND ${BUILD_TOOLS}/dx --dex --output=bin/classes.dex ./obj + COMMAND ${BUILD_TOOLS}/aapt package -f -M AndroidManifest.xml -S res -I ${ANDROID_JAR} -F RenderDocCmd-unaligned.apk bin libs + COMMAND ${BUILD_TOOLS}/zipalign -f 4 RenderDocCmd-unaligned.apk RenderDocCmd.apk + COMMAND ${BUILD_TOOLS}/apksigner sign --ks ${KEYSTORE} --ks-pass pass:android --key-pass pass:android --ks-key-alias androiddebugkey RenderDocCmd.apk + COMMAND ${CMAKE_COMMAND} -E copy RenderDocCmd.apk ${APK_FILE}) + endif() diff --git a/scripts/travis/android_setup.sh b/scripts/travis/android_setup.sh index a884b82568..7a9a9b4ed0 100644 --- a/scripts/travis/android_setup.sh +++ b/scripts/travis/android_setup.sh @@ -23,6 +23,7 @@ mv android-7.1.1/* build-tools/25.0.2/ export ANDROID_HOME=`pwd`/tools export JAVA_HOME="/usr/lib/jvm/java-8-oracle" export ANDROID_NDK=`pwd`/android-ndk-r13b +export ANDROID_SDK=`pwd` export PATH=`pwd`/android-ndk-r13b:$PATH export PATH=`pwd`/tools:$PATH export PATH=`pwd`/platform-tools:$PATH From 52e6af97a19e7462357851c86d624c4d6562e628 Mon Sep 17 00:00:00 2001 From: Cody Northrop Date: Wed, 2 Aug 2017 14:44:19 -0600 Subject: [PATCH 21/91] travis: Update config for Android with latest SDK/NDK --- scripts/travis/android_setup.sh | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/scripts/travis/android_setup.sh b/scripts/travis/android_setup.sh index 7a9a9b4ed0..aa49545366 100644 --- a/scripts/travis/android_setup.sh +++ b/scripts/travis/android_setup.sh @@ -6,28 +6,17 @@ sudo apt-get install -y cmake export ARCH=`uname -m` -# Pull known working tools toward the end of 2016 -wget http://dl.google.com/android/repository/android-ndk-r13b-linux-${ARCH}.zip -wget https://dl.google.com/android/repository/tools_r25.2.5-linux.zip -wget https://dl.google.com/android/repository/platform-tools_r25.0.3-linux.zip -wget https://dl.google.com/android/repository/build-tools_r25.0.2-linux.zip -unzip -u -q android-ndk-r13b-linux-${ARCH}.zip -unzip -u -q tools_r25.2.5-linux.zip -unzip -u -q platform-tools_r25.0.3-linux.zip -unzip -u -q build-tools_r25.0.2-linux.zip +# Pull known working tools August 2017 +wget http://dl.google.com/android/repository/sdk-tools-linux-3859397.zip +wget http://dl.google.com/android/repository/android-ndk-r14b-linux-${ARCH}.zip +unzip -u -q android-ndk-r14b-linux-${ARCH}.zip +unzip -u -q sdk-tools-linux-3859397.zip -# Munge the build-tools layout -mkdir -p build-tools/25.0.2 -mv android-7.1.1/* build-tools/25.0.2/ - -export ANDROID_HOME=`pwd`/tools export JAVA_HOME="/usr/lib/jvm/java-8-oracle" -export ANDROID_NDK=`pwd`/android-ndk-r13b -export ANDROID_SDK=`pwd` -export PATH=`pwd`/android-ndk-r13b:$PATH -export PATH=`pwd`/tools:$PATH -export PATH=`pwd`/platform-tools:$PATH -export PATH=`pwd`/build-tools/25.0.2:$PATH +export ANDROID_NDK=$TRAVIS_BUILD_DIR/android-ndk-r14b +export ANDROID_SDK=$TRAVIS_BUILD_DIR # Answer "yes" to any license acceptance requests -(while sleep 3; do echo "y"; done) | android update sdk --no-ui -s -t android-23 +pushd tools/bin +(while sleep 3; do echo "y"; done) | ./sdkmanager --sdk_root=$TRAVIS_BUILD_DIR "build-tools;26.0.1" "platforms;android-23" +popd From 7044961970159aaf35ea18619e4b1f230ca2dfdc Mon Sep 17 00:00:00 2001 From: Cody Northrop Date: Wed, 2 Aug 2017 15:22:11 -0600 Subject: [PATCH 22/91] docs: Add setup and build steps for Android on Ubuntu --- CONTRIBUTING.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0820023d52..936d708726 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,6 +44,16 @@ Configuration is available for cmake, [documented elsewhere](https://cmake.org/d Mac support is pretty early and while it will compile, it's not usable for debugging yet. Builds happen with cmake the same way as Linux. +### Android + +To build the components required to debug an Android target, first gather everything from [Dependencies](#dependencies) below, then run: +``` +mkdir build-android +cd build-android +cmake -DBUILD_ANDROID=On -DANDROID_ABI=armeabi-v7a -DANDROID_NATIVE_API_LEVEL=23 .. +make +``` + # Code of Conduct I want to ensure that anyone can contribute to RenderDoc with only the next bug to worry about. For that reason the project has adopted the [contributor covenent](CODE_OF_CONDUCT.md) as a code of conduct to be enforced for anyone taking part in RenderDoc development. If you have any queries in this regard you can get in touch with me [directly over email](mailto:baldurk@baldurk.org). @@ -153,6 +163,42 @@ brew install cmake qt5 brew link qt5 --force ``` +### Android + +To build for Android, you must download components of the Android SDK, the Android NDK, and Java Development Kit. + +If you've already got the tools required, simply set the following three environment variables: +``` +export ANDROID_SDK= +export ANDROID_NDK= +export JAVA_HOME= +``` +Otherwise, below are steps to acquire the tools for Ubuntu. + +The Java Development Kit can be installed with: +``` +sudo apt-get install openjdk-8-jdk +export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 +``` + +The Android SDK and NDK can be set up with the following steps. They are also mirrored in our Travis-CI [setup script](scripts/travis/android_setup.sh) for Android. We are currently targeting build-tools 26.0.1 and NDK r14b. +``` +# Set up Android SDK and NDK +export ANDROID_SDK= +pushd $ANDROID_SDK +wget http://dl.google.com/android/repository/sdk-tools-linux-3859397.zip +unzip sdk-tools-linux-3859397.zip +cd tools/bin/ +./sdkmanager --sdk_root=$ANDROID_SDK "build-tools;26.0.1" "platforms;android-23" +# Accept the license + +# Set up Android NDK +pushd $ANDROID_SDK +wget http://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip +unzip android-ndk-r14b-linux-x86_64.zip +export ANDROID_NDK=$ANDROID_SDK/android-ndk-r14b +``` + # Where to Start There are always plenty of things to do, if you'd like to chip in! Check out the [Roadmap](https://github.com/baldurk/renderdoc/wiki/Roadmap) page in the wiki for future tasks to tackle, or have a look at the [issues](https://github.com/baldurk/renderdoc/issues) for outstanding bugs. I'll try and tag things that seem like small changes that would be a good way for someone to get started with. From 18be4d91b2a0a847eca450cc5b8d483fec3a0099 Mon Sep 17 00:00:00 2001 From: Cody Northrop Date: Thu, 3 Aug 2017 12:31:09 -0600 Subject: [PATCH 23/91] cmake: Add control over Android build-tools version Specify -DANDROID_BUILD_TOOLS_VERSION= to change from the default of 26.0.1. Also respect the selected Android platform version. --- renderdoccmd/CMakeLists.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/renderdoccmd/CMakeLists.txt b/renderdoccmd/CMakeLists.txt index 6cbf8a1d24..0f4837d11e 100644 --- a/renderdoccmd/CMakeLists.txt +++ b/renderdoccmd/CMakeLists.txt @@ -64,12 +64,18 @@ if(ANDROID) message(FATAL_ERROR "ANDROID_SDK environment variable must be defined for Android build") endif() - set(BUILD_TOOLS "$ENV{ANDROID_SDK}/build-tools/26.0.1") - set(ANDROID_JAR "$ENV{ANDROID_SDK}/platforms/android-23/android.jar") + set(ANDROID_BUILD_TOOLS_VERSION "" CACHE STRING "Version of Android build-tools to use instead of the default") + if(ANDROID_BUILD_TOOLS_VERSION STREQUAL "") + set(ANDROID_BUILD_TOOLS_VERSION "26.0.1") + endif() + message(STATUS "Using Android build-tools version ${ANDROID_BUILD_TOOLS_VERSION}") + + set(BUILD_TOOLS "$ENV{ANDROID_SDK}/build-tools/${ANDROID_BUILD_TOOLS_VERSION}") set(RT_JAR "$ENV{JAVA_HOME}/jre/lib/rt.jar") set(JAVA_BIN "$ENV{JAVA_HOME}/bin") set(APK_TARGET_ID "android-23" CACHE STRING "The Target ID to build the APK for, use to choose another one.") + set(ANDROID_JAR "$ENV{ANDROID_SDK}/platforms/${APK_TARGET_ID}/android.jar") set(KEYSTORE ${CMAKE_CURRENT_BINARY_DIR}/debug.keystore) add_custom_command(OUTPUT ${KEYSTORE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} From 88587f8c5d94e31037726d7c392438d5508fa611 Mon Sep 17 00:00:00 2001 From: Cody Northrop Date: Mon, 14 Aug 2017 11:22:55 -0600 Subject: [PATCH 24/91] docs: Update CONTRIBUTING.md for Windows and macOS --- CONTRIBUTING.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 936d708726..d9accbf604 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,6 +53,10 @@ cd build-android cmake -DBUILD_ANDROID=On -DANDROID_ABI=armeabi-v7a -DANDROID_NATIVE_API_LEVEL=23 .. make ``` +On Windows, you need to specify the 'generator' type to the cmake invocation. The exact parameter will depend on your bash shell, but options are e.g. -G "MSYS Makefiles" or -G "MinGW Makefiles", i.e.: +``` +cmake -DBUILD_ANDROID=On -DANDROID_ABI=armeabi-v7a -DANDROID_NATIVE_API_LEVEL=23 -G"MSYS Makefiles" .. +``` # Code of Conduct @@ -173,8 +177,8 @@ export ANDROID_SDK= export ANDROID_NDK= export JAVA_HOME= ``` -Otherwise, below are steps to acquire the tools for Ubuntu. - +Otherwise, below are steps to acquire the tools for each platform. +#### Ubuntu The Java Development Kit can be installed with: ``` sudo apt-get install openjdk-8-jdk @@ -182,8 +186,12 @@ export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 ``` The Android SDK and NDK can be set up with the following steps. They are also mirrored in our Travis-CI [setup script](scripts/travis/android_setup.sh) for Android. We are currently targeting build-tools 26.0.1 and NDK r14b. + +SDK links are pulled from [here](https://developer.android.com/studio/index.html). + +NDK links are pulled from [here](https://developer.android.com/ndk/downloads/older_releases.html). ``` -# Set up Android SDK and NDK +# Set up Android SDK export ANDROID_SDK= pushd $ANDROID_SDK wget http://dl.google.com/android/repository/sdk-tools-linux-3859397.zip @@ -198,6 +206,51 @@ wget http://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip unzip android-ndk-r14b-linux-x86_64.zip export ANDROID_NDK=$ANDROID_SDK/android-ndk-r14b ``` +#### macOS +JDK can be installed with brew: +``` +brew cask install java +export JAVA_HOME="$(/usr/libexec/java_home)" +``` +Android NDK and SDK: +``` +# Set up Android SDK +export ANDROID_SDK= +pushd $ANDROID_SDK +wget https://dl.google.com/android/repository/sdk-tools-darwin-3859397.zip +unzip sdk-tools-darwin-3859397.zip +cd tools/bin/ +./sdkmanager --sdk_root=$ANDROID_SDK "build-tools;26.0.1" "platforms;android-23" +# Accept the license + +# Set up Android NDK +pushd $ANDROID_SDK +wget https://dl.google.com/android/repository/android-ndk-r14b-darwin-x86_64.zip +unzip android-ndk-r14b-darwin-x86_64.zip +export ANDROID_NDK=$ANDROID_SDK/android-ndk-r14b +``` +#### Windows +JDK can be installed from the following [link](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html). +``` +set JAVA_HOME= +``` +Android NDK and SDK: +``` +# Set up the Android SDK +set ANDROID_SDK= +cd %ANDROID_SDK% +wget https://dl.google.com/android/repository/sdk-tools-windows-3859397.zip +unzip sdk-tools-windows-3859397.zip +cd tools\bin +sdkmanager --sdk_root=%ANDROID_SDK% "build-tools;26.0.1" "platforms;android-23" +# Accept the license + +# Set up the Android NDK +cd %ANDROID_SDK% +wget http://dl.google.com/android/repository/android-ndk-r14b-windows-x86_64.zip +unzip android-ndk-r14b-windows-x86_64.zip +set ANDROID_NDK=%ANDROID_SDK%\android-ndk-r14b +``` # Where to Start From e42f883d260beaee3115b784771cad4752977d74 Mon Sep 17 00:00:00 2001 From: Cody Northrop Date: Mon, 14 Aug 2017 12:47:03 -0600 Subject: [PATCH 25/91] cmake: Update javac classpath to work on Windows --- renderdoccmd/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/renderdoccmd/CMakeLists.txt b/renderdoccmd/CMakeLists.txt index 0f4837d11e..0b44b442c3 100644 --- a/renderdoccmd/CMakeLists.txt +++ b/renderdoccmd/CMakeLists.txt @@ -76,6 +76,11 @@ if(ANDROID) set(APK_TARGET_ID "android-23" CACHE STRING "The Target ID to build the APK for, use to choose another one.") set(ANDROID_JAR "$ENV{ANDROID_SDK}/platforms/${APK_TARGET_ID}/android.jar") + if(CMAKE_HOST_WIN32) + set(CLASS_PATH "${ANDROID_JAR}\;obj") + else() + set(CLASS_PATH "${ANDROID_JAR}:obj") + endif() set(KEYSTORE ${CMAKE_CURRENT_BINARY_DIR}/debug.keystore) add_custom_command(OUTPUT ${KEYSTORE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -97,7 +102,7 @@ if(ANDROID) COMMAND ${CMAKE_COMMAND} -E copy $ libs/lib/${ANDROID_ABI}/libVkLayer_GLES_RenderDoc.so COMMAND ${CMAKE_COMMAND} -E copy $ libs/lib/${ANDROID_ABI}/$ COMMAND ${BUILD_TOOLS}/aapt package -f -m -S res -J src -M AndroidManifest.xml -I ${ANDROID_JAR} - COMMAND ${JAVA_BIN}/javac -d ./obj -source 1.7 -target 1.7 -bootclasspath ${RT_JAR} -classpath ${ANDROID_JAR}:obj -sourcepath src src/org/renderdoc/renderdoccmd/*.java + COMMAND ${JAVA_BIN}/javac -d ./obj -source 1.7 -target 1.7 -bootclasspath ${RT_JAR} -classpath "${CLASS_PATH}" -sourcepath src src/org/renderdoc/renderdoccmd/*.java COMMAND ${BUILD_TOOLS}/dx --dex --output=bin/classes.dex ./obj COMMAND ${BUILD_TOOLS}/aapt package -f -M AndroidManifest.xml -S res -I ${ANDROID_JAR} -F RenderDocCmd-unaligned.apk bin libs COMMAND ${BUILD_TOOLS}/zipalign -f 4 RenderDocCmd-unaligned.apk RenderDocCmd.apk From 31107b3a1a8d19b68f9b472f081f5f414873aeed Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 17 Aug 2017 13:03:19 +0100 Subject: [PATCH 26/91] Make sure not to offset secondary cmd buf submissions multiple times * When a primary command buffer is submitted that contained some secondary executes, we offset their executes to be 'absolute' root-relative events so they know when they're being partially replayed. * If the same secondary is executed in multiple primaries that are submitted separately, we don't want to apply the same offset over and over, instead we mark an execute as updated and only offset 'new' executions. --- renderdoc/driver/vulkan/vk_core.h | 15 +++++++++++++-- renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp | 12 ++++++------ .../driver/vulkan/wrappers/vk_queue_funcs.cpp | 12 +++++++++--- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 4e126092d0..e6ffe2bde0 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -472,6 +472,13 @@ class WrappedVulkan : public IFrameCapturer ePartialNum }; + struct Submission + { + Submission(uint32_t eid) : baseEvent(eid), rebased(false) {} + uint32_t baseEvent = 0; + bool rebased = false; + }; + struct PartialReplayData { PartialReplayData() { Reset(); } @@ -512,8 +519,12 @@ class WrappedVulkan : public IFrameCapturer // vkCmd chunks) is NOT unique. // However, a single baked command list can be submitted multiple // times - so we have to have a list of base events - // Map from bakeID -> vector - map > cmdBufferSubmits; + // Note in the case of secondary command buffers we mark when these + // are rebased to 'absolute' event IDs, since they could be submitted + // multiple times in the frame and we don't want to rebase all of + // them each time. + // Map from bakeID -> vector + map > cmdBufferSubmits; // This is just the ResourceId of the original parent command buffer // and it's baked id. diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index 2a1135c943..f72fc1d9c8 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -513,19 +513,19 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(Serialiser *localSerialiser, // check for partial execution of this command buffer for(int p = 0; p < ePartialNum; p++) { - const vector &baseEvents = m_Partial[p].cmdBufferSubmits[bakeId]; + const vector &submissions = m_Partial[p].cmdBufferSubmits[bakeId]; - for(auto it = baseEvents.begin(); it != baseEvents.end(); ++it) + for(auto it = submissions.begin(); it != submissions.end(); ++it) { - if(*it <= m_LastEventID && m_LastEventID < (*it + length)) + if(it->baseEvent <= m_LastEventID && m_LastEventID < (it->baseEvent + length)) { #if ENABLED(VERBOSE_PARTIAL_REPLAY) - RDCDEBUG("vkBegin - partial detected %u < %u < %u, %llu -> %llu", *it, m_LastEventID, - *it + length, cmdId, bakeId); + RDCDEBUG("vkBegin - partial detected %u < %u < %u, %llu -> %llu", it->baseEvent, + m_LastEventID, it->baseEvent + length, cmdId, bakeId); #endif m_Partial[p].partialParent = cmdId; - m_Partial[p].baseEvent = *it; + m_Partial[p].baseEvent = it->baseEvent; m_Partial[p].renderPassActive = false; m_Partial[p].partialDevice = device; m_Partial[p].resultPartialCmdPool = diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index 89a83c6ff0..29e2baf1f0 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -228,11 +228,17 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(Serialiser *localSerialiser, VkQueue for(size_t e = 0; e < cmdBufInfo.draw->executedCmds.size(); e++) { - vector &submits = + vector &submits = m_Partial[Secondary].cmdBufferSubmits[cmdBufInfo.draw->executedCmds[e]]; for(size_t s = 0; s < submits.size(); s++) - submits[s] += m_RootEventID; + { + if(!submits[s].rebased) + { + submits[s].baseEvent += m_RootEventID; + submits[s].rebased = true; + } + } } for(size_t i = 0; i < cmdBufInfo.debugMessages.size(); i++) @@ -242,7 +248,7 @@ bool WrappedVulkan::Serialise_vkQueueSubmit(Serialiser *localSerialiser, VkQueue } // only primary command buffers can be submitted - m_Partial[Primary].cmdBufferSubmits[cmdIds[c]].push_back(m_RootEventID); + m_Partial[Primary].cmdBufferSubmits[cmdIds[c]].push_back(Submission(m_RootEventID)); m_RootEventID += cmdBufInfo.eventCount; m_RootDrawcallID += cmdBufInfo.drawCount; From 5e519f58c3e6318ad5e9e6cc1e56d7c9e1faf3d4 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 17 Aug 2017 13:06:22 +0100 Subject: [PATCH 27/91] Create an equivalent 'loadFB' framebuffer for every 'loadRP' renderpass * In order to be able to split apart and partially replay every render pass, we change them to always STORE instead of DONT_CARE, and then create a patched version that only has a single subpass (for each subpass in the original) and has LOAD/STORE semantics. * However because of the requirements for framebuffer <-> renderpass we have to now multiply up the framebuffer to make a patched fb to correspond to each patched renderpass. --- renderdoc/driver/vulkan/vk_info.h | 3 + renderdoc/driver/vulkan/vk_state.cpp | 2 +- .../driver/vulkan/wrappers/vk_misc_funcs.cpp | 66 ++++++++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index 20c072a2bd..5e4b0cec88 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -254,6 +254,9 @@ struct VulkanCreationInfo vector attachments; uint32_t width, height, layers; + + // See above in loadRPs - we need to duplicate and make framebuffer equivalents for each + vector loadFBs; }; map m_Framebuffer; diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp index f4a186e413..0e6efabb0f 100644 --- a/renderdoc/driver/vulkan/vk_state.cpp +++ b/renderdoc/driver/vulkan/vk_state.cpp @@ -99,7 +99,7 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, Pipeli VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, NULL, Unwrap(m_CreationInfo->m_RenderPass[renderPass].loadRPs[subpass]), - Unwrap(GetResourceManager()->GetCurrentHandle(framebuffer)), + Unwrap(m_CreationInfo->m_Framebuffer[framebuffer].loadFBs[subpass]), renderArea, (uint32_t)m_CreationInfo->m_RenderPass[renderPass].attachments.size(), empty, diff --git a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp index 44749ff180..682b611450 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp @@ -497,7 +497,46 @@ bool WrappedVulkan::Serialise_vkCreateFramebuffer(Serialiser *localSerialiser, V live = GetResourceManager()->WrapResource(Unwrap(device), fb); GetResourceManager()->AddLiveResource(id, fb); - m_CreationInfo.m_Framebuffer[live].Init(GetResourceManager(), m_CreationInfo, &info); + VulkanCreationInfo::Framebuffer fbinfo; + fbinfo.Init(GetResourceManager(), m_CreationInfo, &info); + + const VulkanCreationInfo::RenderPass &rpinfo = + m_CreationInfo.m_RenderPass[GetResourceManager()->GetNonDispWrapper(info.renderPass)->id]; + + fbinfo.loadFBs.resize(rpinfo.loadRPs.size()); + + // create a render pass for each subpass that maintains attachment layouts + for(size_t s = 0; s < fbinfo.loadFBs.size(); s++) + { + info.renderPass = Unwrap(rpinfo.loadRPs[s]); + + ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), &info, NULL, &fbinfo.loadFBs[s]); + RDCASSERTEQUAL(ret, VK_SUCCESS); + + // handle the loadRP being a duplicate + if(GetResourceManager()->HasWrapper(ToTypedHandle(fbinfo.loadFBs[s]))) + { + // just fetch the existing wrapped object + fbinfo.loadFBs[s] = + (VkFramebuffer)(uint64_t)GetResourceManager()->GetNonDispWrapper(fbinfo.loadFBs[s]); + + // destroy this instance of the duplicate, as we must have matching create/destroy + // calls and there won't be a wrapped resource hanging around to destroy this one. + ObjDisp(device)->DestroyFramebuffer(Unwrap(device), fbinfo.loadFBs[s], NULL); + + // don't need to ReplaceResource as no IDs are involved + } + else + { + ResourceId loadFBid = + GetResourceManager()->WrapResource(Unwrap(device), fbinfo.loadFBs[s]); + + // register as a live-only resource, so it is cleaned up properly + GetResourceManager()->AddLiveResource(loadFBid, fbinfo.loadFBs[s]); + } + } + + m_CreationInfo.m_Framebuffer[live] = fbinfo; } } } @@ -567,7 +606,30 @@ VkResult WrappedVulkan::vkCreateFramebuffer(VkDevice device, { GetResourceManager()->AddLiveResource(id, *pFramebuffer); - m_CreationInfo.m_Framebuffer[id].Init(GetResourceManager(), m_CreationInfo, &unwrappedInfo); + VulkanCreationInfo::Framebuffer fbinfo; + fbinfo.Init(GetResourceManager(), m_CreationInfo, &unwrappedInfo); + + const VulkanCreationInfo::RenderPass &rpinfo = + m_CreationInfo.m_RenderPass[GetResID(pCreateInfo->renderPass)]; + + fbinfo.loadFBs.resize(rpinfo.loadRPs.size()); + + // create a render pass for each subpass that maintains attachment layouts + for(size_t s = 0; s < fbinfo.loadFBs.size(); s++) + { + unwrappedInfo.renderPass = Unwrap(rpinfo.loadRPs[s]); + + ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), &unwrappedInfo, NULL, + &fbinfo.loadFBs[s]); + RDCASSERTEQUAL(ret, VK_SUCCESS); + + ResourceId loadFBid = GetResourceManager()->WrapResource(Unwrap(device), fbinfo.loadFBs[s]); + + // register as a live-only resource, so it is cleaned up properly + GetResourceManager()->AddLiveResource(loadFBid, fbinfo.loadFBs[s]); + } + + m_CreationInfo.m_Framebuffer[id] = fbinfo; } } From 9a409eb4139afcc425222f38ffe087d539eab49b Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 17 Aug 2017 18:05:47 +0100 Subject: [PATCH 28/91] Don't look up offset in serialised data as it's already been applied * Fixes a crash reading off the end of the serialised buffer --- renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index c31ab7bff9..5bebc719f9 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -731,7 +731,7 @@ bool WrappedVulkan::Serialise_vkFlushMappedMemoryRanges(Serialiser *localSeriali byte *serialisedData = localSerialiser->GetRawPtr(offs); - memcpy(state->refData, serialisedData + (size_t)memOffset, (size_t)memSize); + memcpy(state->refData, serialisedData, (size_t)memSize); } if(m_State < WRITING) From 177d595d4fadfcff72d7dc351647b1726aabc4e6 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 18 Aug 2017 18:49:02 +0100 Subject: [PATCH 29/91] Ensure to always use wrapped resources when constructing resource ranges * If we don't consistently use wrapped resources then we could get false negatives. * For example, views always constructed with the *unwrapped* object, but when unbinding a backbuffer before a swapchain resize, we used the *wrapped* backbuffer texture to search for clashes. This meant some bindings went un-noticed, and left references dangling. --- renderdoc/driver/d3d11/d3d11_analyse.cpp | 16 ++---- renderdoc/driver/d3d11/d3d11_common.cpp | 68 +++++++++++++++++++++++- renderdoc/driver/d3d11/d3d11_common.h | 47 +++++++--------- renderdoc/driver/d3d11/d3d11_resources.h | 2 +- 4 files changed, 91 insertions(+), 42 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index 0fc0ab2a90..4f362f91f3 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -5879,36 +5879,28 @@ vector D3D11DebugManager::PixelHistory(vector eve { WrappedID3D11RenderTargetView1 *rtv = (WrappedID3D11RenderTargetView1 *)view; - ResourceRange viewRange(rtv); - - if(viewRange.Intersects(resourceRange)) + if(rtv->GetResourceRange().Intersects(resourceRange)) used = true; } else if(WrappedID3D11DepthStencilView::IsAlloc(view)) { WrappedID3D11DepthStencilView *dsv = (WrappedID3D11DepthStencilView *)view; - ResourceRange viewRange(dsv); - - if(viewRange.Intersects(resourceRange)) + if(dsv->GetResourceRange().Intersects(resourceRange)) used = true; } else if(WrappedID3D11ShaderResourceView1::IsAlloc(view)) { WrappedID3D11ShaderResourceView1 *srv = (WrappedID3D11ShaderResourceView1 *)view; - ResourceRange viewRange(srv); - - if(viewRange.Intersects(resourceRange)) + if(srv->GetResourceRange().Intersects(resourceRange)) used = true; } else if(WrappedID3D11UnorderedAccessView1::IsAlloc(view)) { WrappedID3D11UnorderedAccessView1 *uav = (WrappedID3D11UnorderedAccessView1 *)view; - ResourceRange viewRange(uav); - - if(viewRange.Intersects(resourceRange)) + if(uav->GetResourceRange().Intersects(resourceRange)) used = true; } else diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index 233138215d..246c6a87f4 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -75,7 +75,7 @@ void D3D11MarkerRegion::End() annot->EndEvent(); } -ResourceRange ResourceRange::Null = ResourceRange(NULL, 0, 0); +ResourceRange ResourceRange::Null = ResourceRange(ResourceRange::empty); ResourceRange::ResourceRange(ID3D11ShaderResourceView *srv) { @@ -92,6 +92,13 @@ ResourceRange::ResourceRange(ID3D11ShaderResourceView *srv) return; } +// in non-release make sure we always consistently check wrapped resources/views. Otherwise we could +// end up in a situation where we're comparing two resource ranges that do overlap, but one was +// constructed with the wrapped view and one wasn't - so they compare differently +#if ENABLED(RDOC_DEVEL) + RDCASSERT(WrappedID3D11ShaderResourceView1::IsAlloc(srv)); +#endif + ID3D11Resource *res = NULL; srv->GetResource(&res); res->Release(); @@ -214,6 +221,10 @@ ResourceRange::ResourceRange(ID3D11UnorderedAccessView *uav) return; } +#if ENABLED(RDOC_DEVEL) + RDCASSERT(WrappedID3D11UnorderedAccessView1::IsAlloc(uav)); +#endif + ID3D11Resource *res = NULL; uav->GetResource(&res); res->Release(); @@ -274,6 +285,10 @@ ResourceRange::ResourceRange(ID3D11RenderTargetView *rtv) return; } +#if ENABLED(RDOC_DEVEL) + RDCASSERT(WrappedID3D11RenderTargetView1::IsAlloc(rtv)); +#endif + ID3D11Resource *res = NULL; rtv->GetResource(&res); res->Release(); @@ -339,6 +354,10 @@ ResourceRange::ResourceRange(ID3D11DepthStencilView *dsv) return; } +#if ENABLED(RDOC_DEVEL) + RDCASSERT(WrappedID3D11DepthStencilView::IsAlloc(dsv)); +#endif + ID3D11Resource *res = NULL; dsv->GetResource(&res); res->Release(); @@ -387,6 +406,53 @@ ResourceRange::ResourceRange(ID3D11DepthStencilView *dsv) SetMaxes(numMips, numSlices); } +ResourceRange::ResourceRange(ID3D11Buffer *res) +{ +#if ENABLED(RDOC_DEVEL) + RDCASSERT(!res || WrappedID3D11Buffer::IsAlloc(res)); +#endif + + resource = res; + minMip = minSlice = 0; + maxMip = allMip; + maxSlice = allSlice; + fullRange = true; + depthReadOnly = false; + stencilReadOnly = false; +} + +ResourceRange::ResourceRange(ID3D11Texture2D *res) +{ +#if ENABLED(RDOC_DEVEL) + RDCASSERT(!res || WrappedID3D11Texture2D1::IsAlloc(res)); +#endif + + resource = res; + minMip = minSlice = 0; + maxMip = allMip; + maxSlice = allSlice; + fullRange = true; + depthReadOnly = false; + stencilReadOnly = false; +} + +ResourceRange::ResourceRange(ID3D11Resource *res, UINT mip, UINT slice) +{ +#if ENABLED(RDOC_DEVEL) + RDCASSERT(!res || WrappedID3D11Texture1D::IsAlloc(res) || WrappedID3D11Texture2D1::IsAlloc(res) || + WrappedID3D11Texture3D1::IsAlloc(res) || WrappedID3D11Buffer::IsAlloc(res)); +#endif + + resource = res; + minMip = mip; + maxMip = mip; + minSlice = slice; + maxSlice = slice; + fullRange = false; + depthReadOnly = false; + stencilReadOnly = false; +} + TextureDim MakeTextureDim(D3D11_SRV_DIMENSION dim) { switch(dim) diff --git a/renderdoc/driver/d3d11/d3d11_common.h b/renderdoc/driver/d3d11/d3d11_common.h index 00a9bec360..05d8d298bc 100644 --- a/renderdoc/driver/d3d11/d3d11_common.h +++ b/renderdoc/driver/d3d11/d3d11_common.h @@ -51,43 +51,34 @@ struct D3D11MarkerRegion struct ResourceRange { - static ResourceRange Null; - - ResourceRange(ID3D11Buffer *res) +private: + enum Empty { - resource = res; - minMip = minSlice = 0; - maxMip = allMip; - maxSlice = allSlice; - fullRange = true; - depthReadOnly = false; - stencilReadOnly = false; - } + empty + }; - ResourceRange(ID3D11Texture2D *res) + // used to initialise Null below + ResourceRange(Empty) { - resource = res; - minMip = minSlice = 0; - maxMip = allMip; - maxSlice = allSlice; - fullRange = true; + resource = NULL; + minMip = 0; + maxMip = 0; + minSlice = 0; + maxSlice = 0; + fullRange = false; depthReadOnly = false; stencilReadOnly = false; } +public: + static ResourceRange Null; + + ResourceRange(ID3D11Buffer *res); + ResourceRange(ID3D11Texture2D *res); + // construct a range for a specific mip/slice. Used for easily checking if // a view includes this mip/slice - ResourceRange(ID3D11Resource *res, UINT mip, UINT slice) - { - resource = res; - minMip = mip; - maxMip = mip; - minSlice = slice; - maxSlice = slice; - fullRange = false; - depthReadOnly = false; - stencilReadOnly = false; - } + ResourceRange(ID3D11Resource *res, UINT mip, UINT slice); // initialises the range with the contents of the view ResourceRange(ID3D11ShaderResourceView *srv); diff --git a/renderdoc/driver/d3d11/d3d11_resources.h b/renderdoc/driver/d3d11/d3d11_resources.h index f1244941c0..108781dbfb 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.h +++ b/renderdoc/driver/d3d11/d3d11_resources.h @@ -747,7 +747,7 @@ class WrappedView1 : public WrappedDeviceChild11 ResourceRange m_ResourceRange; WrappedView1(NestedType *real, WrappedID3D11Device *device, ID3D11Resource *res) - : WrappedDeviceChild11(real, device), m_pResource(res), m_ResourceRange(real) + : WrappedDeviceChild11(real, device), m_pResource(res), m_ResourceRange(this) { m_ResourceResID = GetIDForResource(m_pResource); // cast is potentially invalid but functions in WrappedResource will be identical across each From 92855d37493338874a0d3563050290ed05d1024e Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 29 Aug 2017 14:47:23 +0100 Subject: [PATCH 30/91] Fix remapping 3D textures on vulkan, for fetching texture data to save --- renderdoc/driver/vulkan/vk_replay.cpp | 33 +++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index fed463d8f8..743367d376 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -4352,6 +4352,14 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m imCreateInfo.extent.height = RDCMAX(1U, imCreateInfo.extent.height >> mip); imCreateInfo.extent.depth = RDCMAX(1U, imCreateInfo.extent.depth >> mip); + // convert a 3D texture into a 2D array, so we can render to the slices without needing + // KHR_maintenance1 + if(imCreateInfo.extent.depth > 1) + { + imCreateInfo.arrayLayers = imCreateInfo.extent.depth; + imCreateInfo.extent.depth = 1; + } + // create render texture similar to readback texture vt->CreateImage(Unwrap(dev), &imCreateInfo, NULL, &tmpImage); @@ -4427,7 +4435,7 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m }; vt->CreateRenderPass(Unwrap(dev), &rpinfo, NULL, &tmpRP); - numFBs = (imCreateInfo.imageType == VK_IMAGE_TYPE_3D ? (imCreateInfo.extent.depth >> mip) : 1); + numFBs = imCreateInfo.arrayLayers; tmpFB = new VkFramebuffer[numFBs]; tmpView = new VkImageView[numFBs]; @@ -4439,6 +4447,12 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m // if 3d texture, render each slice separately, otherwise render once for(uint32_t i = 0; i < numFBs; i++) { + if(numFBs > 1 && (i % GetDebugManager()->m_TexDisplayUBO.GetRingCount()) == 0) + { + m_pDriver->SubmitCmds(); + m_pDriver->FlushQ(); + } + TextureDisplay texDisplay; texDisplay.Red = texDisplay.Green = texDisplay.Blue = texDisplay.Alpha = true; @@ -4447,10 +4461,9 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m texDisplay.overlay = DebugOverlay::NoOverlay; texDisplay.FlipY = false; texDisplay.mip = mip; - texDisplay.sampleIdx = - imCreateInfo.imageType == VK_IMAGE_TYPE_3D ? 0 : (params.resolve ? ~0U : arrayIdx); + texDisplay.sampleIdx = imInfo.type == VK_IMAGE_TYPE_3D ? 0 : (params.resolve ? ~0U : arrayIdx); texDisplay.CustomShader = ResourceId(); - texDisplay.sliceFace = imCreateInfo.imageType == VK_IMAGE_TYPE_3D ? i : arrayIdx; + texDisplay.sliceFace = imInfo.type == VK_IMAGE_TYPE_3D ? i : arrayIdx; texDisplay.rangemin = params.blackPoint; texDisplay.rangemax = params.whitePoint; texDisplay.scale = 1.0f; @@ -4872,6 +4885,18 @@ byte *VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t m vt->CmdCopyImageToBuffer(Unwrap(cmd), srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, readbackBuf, 2, copyregion); } + else if(imInfo.type == VK_IMAGE_TYPE_3D && params.remap) + { + // copy in each slice from the 2D array we created to render out the 3D texture + for(uint32_t i = 0; i < imCreateInfo.arrayLayers; i++) + { + copyregion[0].imageSubresource.baseArrayLayer = i; + copyregion[0].bufferOffset = + i * GetByteSize(imInfo.extent.width, imInfo.extent.height, 1, imCreateInfo.format, mip); + vt->CmdCopyImageToBuffer(Unwrap(cmd), srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + readbackBuf, 1, copyregion); + } + } else { // copy from desired subresource in srcImage to buffer From 8d7b4d2f8150759b152d3e7257370c5780e5641b Mon Sep 17 00:00:00 2001 From: michaelrgb Date: Mon, 4 Sep 2017 16:47:37 +0100 Subject: [PATCH 31/91] Set TF mode for all initProg varyings, to stop driver culling uniforms. --- renderdoc/driver/gl/gl_manager.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index f889d731e7..7d835f085a 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -1069,12 +1069,19 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res) GLuint initProg = gl.glCreateProgram(); + std::vector vertexOutputs; for(size_t i = 0; i < details.shaders.size(); i++) { const auto &shadDetails = m_GL->m_Shaders[details.shaders[i]]; GLuint shad = gl.glCreateShader(shadDetails.type); + if(shadDetails.type == eGL_VERTEX_SHADER) + { + for(int s = 0; s < shadDetails.reflection.OutputSig.count; s++) + vertexOutputs.push_back(shadDetails.reflection.OutputSig[s].varName.c_str()); + } + char **srcs = new char *[shadDetails.sources.size()]; for(size_t s = 0; s < shadDetails.sources.size(); s++) srcs[s] = (char *)shadDetails.sources[s].c_str(); @@ -1086,6 +1093,12 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res) gl.glDeleteShader(shad); } + // Some drivers optimize out uniforms if they dont change any active vertex shader outputs. + // This resulted in initProg locationTranslate table being -1 for a particular shader where + // some uniforms were only intended to affect TF. Therefore set a TF mode for all varyings. + // As the initial state program is never used for TF, this wont adversely affect anything. + gl.glTransformFeedbackVaryings(initProg, (GLsizei)vertexOutputs.size(), &vertexOutputs[0], + eGL_INTERLEAVED_ATTRIBS); gl.glLinkProgram(initProg); GLint status = 0; From d6c03f58bc7bf27cb631a780fd19b410ae967b82 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 15 Aug 2017 15:21:09 +0100 Subject: [PATCH 32/91] Select the next highest event when replaying from an event * Searching down from the end for the next lowest event causes us to sometimes replay backwards when a marker is selected (and has no event in the array to replay directly). This can crash on vulkan, and is unintuitive/wrong on other APIs. Instead we follow the behaviour that we have elsewhere so that when a marker is selected we move _forward_ in the frame to select the next event after it. * Checking the history there doesn't seem to be any strong reason for this direction of search. --- renderdoc/driver/d3d11/d3d11_context.cpp | 8 ++++---- renderdoc/driver/d3d11/d3d11_context.h | 2 +- renderdoc/driver/d3d12/d3d12_command_queue.h | 2 +- renderdoc/driver/d3d12/d3d12_commands.cpp | 8 ++++---- renderdoc/driver/gl/gl_driver.cpp | 8 ++++---- renderdoc/driver/gl/gl_driver.h | 2 +- renderdoc/driver/vulkan/vk_core.cpp | 8 ++++---- renderdoc/driver/vulkan/vk_core.h | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_context.cpp b/renderdoc/driver/d3d11/d3d11_context.cpp index 69ec0235fb..17ce14c9ba 100644 --- a/renderdoc/driver/d3d11/d3d11_context.cpp +++ b/renderdoc/driver/d3d11/d3d11_context.cpp @@ -1030,12 +1030,12 @@ void WrappedID3D11DeviceContext::AddEvent(string description) m_Events.push_back(apievent); } -APIEvent WrappedID3D11DeviceContext::GetEvent(uint32_t eventID) +const APIEvent &WrappedID3D11DeviceContext::GetEvent(uint32_t eventID) { - for(size_t i = m_Events.size() - 1; i > 0; i--) + for(const APIEvent &e : m_Events) { - if(m_Events[i].eventID <= eventID) - return m_Events[i]; + if(e.eventID >= eventID) + return e; } return m_Events[0]; diff --git a/renderdoc/driver/d3d11/d3d11_context.h b/renderdoc/driver/d3d11/d3d11_context.h index 2d6b0386c9..d88577e929 100644 --- a/renderdoc/driver/d3d11/d3d11_context.h +++ b/renderdoc/driver/d3d11/d3d11_context.h @@ -316,7 +316,7 @@ class WrappedID3D11DeviceContext : public RefCounter, public ID3D11DeviceContext void ClearMaps(); uint32_t GetEventID() { return m_CurEventID; } - APIEvent GetEvent(uint32_t eventID); + const APIEvent &GetEvent(uint32_t eventID); const DrawcallTreeNode &GetRootDraw() { return m_ParentDrawcall; } void ThreadSafe_SetMarker(uint32_t col, const wchar_t *name); diff --git a/renderdoc/driver/d3d12/d3d12_command_queue.h b/renderdoc/driver/d3d12/d3d12_command_queue.h index adcd8f301e..538a812462 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue.h +++ b/renderdoc/driver/d3d12/d3d12_command_queue.h @@ -118,7 +118,7 @@ class WrappedID3D12CommandQueue : public ID3D12CommandQueue, WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; } const vector &GetCmdLists() { return m_CmdListRecords; } D3D12DrawcallTreeNode &GetParentDrawcall() { return m_Cmd.m_ParentDrawcall; } - APIEvent GetEvent(uint32_t eventID); + const APIEvent &GetEvent(uint32_t eventID); uint32_t GetMaxEID() { return m_Cmd.m_Events.back().eventID; } ResourceId GetBackbufferResourceID() { return m_BackbufferID; } void ClearAfterCapture(); diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index 42a5fc2995..e23ec5815c 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -254,12 +254,12 @@ void WrappedID3D12CommandQueue::ClearAfterCapture() m_QueueRecord->DeleteChunks(); } -APIEvent WrappedID3D12CommandQueue::GetEvent(uint32_t eventID) +const APIEvent &WrappedID3D12CommandQueue::GetEvent(uint32_t eventID) { - for(size_t i = m_Cmd.m_Events.size() - 1; i > 0; i--) + for(const APIEvent &e : m_Cmd.m_Events) { - if(m_Cmd.m_Events[i].eventID <= eventID) - return m_Cmd.m_Events[i]; + if(e.eventID >= eventID) + return e; } return m_Cmd.m_Events[0]; diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 3254e9f4ef..369ba1eb5b 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -4462,12 +4462,12 @@ void WrappedOpenGL::AddEvent(string description) m_Events.push_back(apievent); } -APIEvent WrappedOpenGL::GetEvent(uint32_t eventID) +const APIEvent &WrappedOpenGL::GetEvent(uint32_t eventID) { - for(size_t i = m_Events.size() - 1; i > 0; i--) + for(const APIEvent &e : m_Events) { - if(m_Events[i].eventID <= eventID) - return m_Events[i]; + if(e.eventID >= eventID) + return e; } return m_Events[0]; diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 4ac92f760d..3bcd70ae97 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -574,7 +574,7 @@ class WrappedOpenGL : public IFrameCapturer GLuint GetFakeBBFBO() { return m_FakeBB_FBO; } GLuint GetFakeVAO() { return m_FakeVAO; } FrameRecord &GetFrameRecord() { return m_FrameRecord; } - APIEvent GetEvent(uint32_t eventID); + const APIEvent &GetEvent(uint32_t eventID); const DrawcallTreeNode &GetRootDraw() { return m_ParentDrawcall; } const DrawcallDescription *GetDrawcall(uint32_t eventID); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 52d3563e50..b8f9b466d0 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -3108,12 +3108,12 @@ void WrappedVulkan::AddEvent(string description) m_EventMessages.clear(); } -APIEvent WrappedVulkan::GetEvent(uint32_t eventID) +const APIEvent &WrappedVulkan::GetEvent(uint32_t eventID) { - for(size_t i = m_Events.size() - 1; i > 0; i--) + for(const APIEvent &e : m_Events) { - if(m_Events[i].eventID <= eventID) - return m_Events[i]; + if(e.eventID >= eventID) + return e; } return m_Events[0]; diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index e6ffe2bde0..d75cffaf71 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -724,7 +724,7 @@ class WrappedVulkan : public IFrameCapturer void ReadLogInitialisation(); FrameRecord &GetFrameRecord() { return m_FrameRecord; } - APIEvent GetEvent(uint32_t eventID); + const APIEvent &GetEvent(uint32_t eventID); uint32_t GetMaxEID() { return m_Events.back().eventID; } const DrawcallDescription *GetDrawcall(uint32_t eventID); From dd5590f8e5d46313e3716a3e8a1914f4ab663fad Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Sep 2017 10:46:40 +0100 Subject: [PATCH 33/91] Fetch dispatch thread dimension always even if we don't disassemble * We need the dispatch thread dimension to be valid when creating the shader reflection data, which may happen before we've disassembled the bytecode. * We do a minimal pass just to skip to that opcode and extract the dims. --- .../driver/shaders/dxbc/dxbc_disassemble.cpp | 41 +++++++++++++++++++ .../driver/shaders/dxbc/dxbc_inspect.cpp | 6 +++ renderdoc/driver/shaders/dxbc/dxbc_inspect.h | 1 + 3 files changed, 48 insertions(+) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp index efd17d1bc8..8c46450851 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp @@ -294,6 +294,47 @@ void DXBCFile::FetchTypeVersion() m_Version.Minor = VersionToken::MinorVersion.Get(cur[0]); } +void DXBCFile::FetchThreadDim() +{ + if(m_HexDump.empty()) + return; + + uint32_t *begin = &m_HexDump.front(); + uint32_t *cur = begin; + uint32_t *end = &m_HexDump.back(); + + // skip header dword above + cur++; + + // skip length dword + cur++; + + while(cur < end) + { + uint32_t OpcodeToken0 = cur[0]; + + OpcodeType op = Opcode::Type.Get(OpcodeToken0); + + if(op == OPCODE_DCL_THREAD_GROUP) + { + DispatchThreadsDimension[0] = cur[1]; + DispatchThreadsDimension[1] = cur[2]; + DispatchThreadsDimension[2] = cur[3]; + break; + } + + if(op == OPCODE_CUSTOMDATA) + { + // length in opcode token is 0, full length is in second dword + cur += cur[1]; + } + else + { + cur += Opcode::Length.Get(OpcodeToken0); + } + } +} + void DXBCFile::DisassembleHexDump() { if(m_Disassembled) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp index 97a472afb1..f068b5d137 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp @@ -847,6 +847,12 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength) m_GuessedResources = true; } + // make sure to fetch the dispatch threads dimension from disassembly + if(!m_Disassembled && m_Type == D3D11_ShaderType_Compute) + { + FetchThreadDim(); + } + for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++) { uint32_t *fourcc = (uint32_t *)(data + chunkOffsets[chunkIdx]); diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.h b/renderdoc/driver/shaders/dxbc/dxbc_inspect.h index 74218029f4..c621d75409 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.h @@ -405,6 +405,7 @@ class DXBCFile DXBCFile(const DXBCFile &o); DXBCFile &operator=(const DXBCFile &o); + void FetchThreadDim(); void FetchTypeVersion(); void DisassembleHexDump(); void MakeDisassemblyString(); From cf95e7a3f68d0b4d765cd216db278cd7c03ba8cf Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Sep 2017 11:08:39 +0100 Subject: [PATCH 34/91] VK_KHR_get_memory_requirements2 is a device, not instance, extension --- renderdoc/driver/vulkan/vk_hookset_defs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index 7f2867b0d1..832c1cf1c5 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -282,8 +282,7 @@ CheckExt(VK_EXT_direct_mode_display); \ CheckExt(VK_EXT_acquire_xlib_display); \ CheckExt(VK_KHR_external_memory_capabilities); \ - CheckExt(VK_KHR_external_semaphore_capabilities); \ - CheckExt(VK_KHR_get_memory_requirements2); + CheckExt(VK_KHR_external_semaphore_capabilities); #define CheckDeviceExts() \ CheckExt(VK_EXT_debug_marker); \ @@ -299,7 +298,8 @@ CheckExt(VK_KHR_external_memory_fd); \ CheckExt(VK_KHR_external_semaphore); \ CheckExt(VK_KHR_external_semaphore_win32); \ - CheckExt(VK_KHR_external_semaphore_fd); + CheckExt(VK_KHR_external_semaphore_fd); \ + CheckExt(VK_KHR_get_memory_requirements2); #define HookInitVulkanInstanceExts() \ HookInitExtension(VK_KHR_surface, DestroySurfaceKHR); \ From 6c4f407b62872b13ec704769243a2eb64a7f6a2c Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Sep 2017 13:56:12 +0100 Subject: [PATCH 35/91] When applying TF varyings workaround, handle matrix variables with :row * The vertex output signature is split into vectors only, so we need to go back to the base matrix name. --- renderdoc/driver/gl/gl_manager.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 7d835f085a..7065477f8d 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -24,6 +24,7 @@ ******************************************************************************/ #include "driver/gl/gl_manager.h" +#include #include "driver/gl/gl_driver.h" struct VertexAttribInitialData @@ -1069,7 +1070,7 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res) GLuint initProg = gl.glCreateProgram(); - std::vector vertexOutputs; + std::vector vertexOutputs; for(size_t i = 0; i < details.shaders.size(); i++) { const auto &shadDetails = m_GL->m_Shaders[details.shaders[i]]; @@ -1079,7 +1080,20 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res) if(shadDetails.type == eGL_VERTEX_SHADER) { for(int s = 0; s < shadDetails.reflection.OutputSig.count; s++) - vertexOutputs.push_back(shadDetails.reflection.OutputSig[s].varName.c_str()); + { + std::string name = shadDetails.reflection.OutputSig[s].varName.c_str(); + + // look for :row added to split up matrix variables + size_t colon = name.find(":row"); + + // remove it, if present + if(colon != std::string::npos) + name.resize(colon); + + // only push matrix variables once + if(std::find(vertexOutputs.begin(), vertexOutputs.end(), name) == vertexOutputs.end()) + vertexOutputs.push_back(name); + } } char **srcs = new char *[shadDetails.sources.size()]; @@ -1097,8 +1111,13 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res) // This resulted in initProg locationTranslate table being -1 for a particular shader where // some uniforms were only intended to affect TF. Therefore set a TF mode for all varyings. // As the initial state program is never used for TF, this wont adversely affect anything. - gl.glTransformFeedbackVaryings(initProg, (GLsizei)vertexOutputs.size(), &vertexOutputs[0], - eGL_INTERLEAVED_ATTRIBS); + + std::vector vertexOutputsPtr; + vertexOutputsPtr.resize(vertexOutputs.size()); + for(size_t i = 0; i < vertexOutputs.size(); i++) + vertexOutputsPtr[i] = vertexOutputs[i].c_str(); + gl.glTransformFeedbackVaryings(initProg, (GLsizei)vertexOutputsPtr.size(), + &vertexOutputsPtr[0], eGL_INTERLEAVED_ATTRIBS); gl.glLinkProgram(initProg); GLint status = 0; From e25af7685ba72aa50df86fd464f63c1eb9a6c10c Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Sep 2017 15:32:09 +0100 Subject: [PATCH 36/91] Add a fallback if TF varyings cause program not to link --- renderdoc/driver/gl/gl_manager.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 7065477f8d..2e46e98dbf 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -1123,6 +1123,16 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res) GLint status = 0; gl.glGetProgramiv(initProg, eGL_LINK_STATUS, &status); + // if it failed to link, first remove the varyings hack above as maybe the driver is barfing + // on trying to make some output a varying + if(status == 0) + { + gl.glTransformFeedbackVaryings(initProg, 0, NULL, eGL_INTERLEAVED_ATTRIBS); + gl.glLinkProgram(initProg); + + gl.glGetProgramiv(initProg, eGL_LINK_STATUS, &status); + } + // if it failed to link, try again as a separable program. // we can't do this by default because of the silly rules meaning // shaders need fixup to be separable-compatible. From 7a34ebb93419889ae67f279f204b7efceca1556b Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Sep 2017 18:19:29 +0100 Subject: [PATCH 37/91] Use correct IsDrawInRenderPass() for vkCmdDraw validity check --- renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp index 34c8bcabd2..6fc09bf04d 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp @@ -82,7 +82,7 @@ bool WrappedVulkan::Serialise_vkCmdDraw(Serialiser *localSerialiser, VkCommandBu if(m_State == EXECUTING) { - if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid) && m_RenderState.renderPass != ResourceId()) + if(ShouldRerecordCmd(cmdid) && InRerecordRange(cmdid) && IsDrawInRenderPass()) { commandBuffer = RerecordCmdBuf(cmdid); From 456f8bbf0cf25377377292758e22da099a615ff2 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Sep 2017 18:22:44 +0100 Subject: [PATCH 38/91] Don't perform occlusion/statistics queries that aren't needed --- renderdoc/driver/vulkan/vk_counters.cpp | 27 +++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_counters.cpp b/renderdoc/driver/vulkan/vk_counters.cpp index ab3d3449ee..79ed298107 100644 --- a/renderdoc/driver/vulkan/vk_counters.cpp +++ b/renderdoc/driver/vulkan/vk_counters.cpp @@ -281,15 +281,38 @@ vector VulkanReplay::FetchCounters(const vector &coun ObjDisp(dev)->CreateQueryPool(Unwrap(dev), &timeStampPoolCreateInfo, NULL, &timeStampPool); RDCASSERTEQUAL(vkr, VK_SUCCESS); + bool occlNeeded = false; + bool statsNeeded = false; + + for(size_t c = 0; c < counters.size(); c++) + { + switch(counters[c]) + { + case GPUCounter::InputVerticesRead: + case GPUCounter::IAPrimitives: + case GPUCounter::GSPrimitives: + case GPUCounter::RasterizerInvocations: + case GPUCounter::RasterizedPrimitives: + case GPUCounter::VSInvocations: + case GPUCounter::TCSInvocations: + case GPUCounter::TESInvocations: + case GPUCounter::GSInvocations: + case GPUCounter::PSInvocations: + case GPUCounter::CSInvocations: statsNeeded = true; break; + case GPUCounter::SamplesWritten: occlNeeded = true; break; + default: break; + } + } + VkQueryPool occlusionPool = VK_NULL_HANDLE; - if(availableFeatures.occlusionQueryPrecise) + if(availableFeatures.occlusionQueryPrecise && occlNeeded) { vkr = ObjDisp(dev)->CreateQueryPool(Unwrap(dev), &occlusionPoolCreateInfo, NULL, &occlusionPool); RDCASSERTEQUAL(vkr, VK_SUCCESS); } VkQueryPool pipeStatsPool = VK_NULL_HANDLE; - if(availableFeatures.pipelineStatisticsQuery) + if(availableFeatures.pipelineStatisticsQuery && statsNeeded) { vkr = ObjDisp(dev)->CreateQueryPool(Unwrap(dev), &pipeStatsPoolCreateInfo, NULL, &pipeStatsPool); RDCASSERTEQUAL(vkr, VK_SUCCESS); From 4c2a4512e725baa7206f48b514e90f10f6b622c4 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 11:11:23 +0100 Subject: [PATCH 39/91] Only set graphics dynamic state on binding graphics pipeline. Refs #740 --- .../driver/vulkan/wrappers/vk_cmd_funcs.cpp | 92 ++++++++++--------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index f72fc1d9c8..f56a0e5366 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -1166,53 +1166,57 @@ bool WrappedVulkan::Serialise_vkCmdBindPipeline(Serialiser *localSerialiser, ResourceId liveid = GetResID(pipeline); - if(bind == VK_PIPELINE_BIND_POINT_GRAPHICS) - m_RenderState.graphics.pipeline = liveid; - else - m_RenderState.compute.pipeline = liveid; - - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_VIEWPORT]) - { - m_RenderState.views = m_CreationInfo.m_Pipeline[liveid].viewports; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_SCISSOR]) - { - m_RenderState.scissors = m_CreationInfo.m_Pipeline[liveid].scissors; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_LINE_WIDTH]) - { - m_RenderState.lineWidth = m_CreationInfo.m_Pipeline[liveid].lineWidth; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BIAS]) + if(bind == VK_PIPELINE_BIND_POINT_COMPUTE) { - m_RenderState.bias.depth = m_CreationInfo.m_Pipeline[liveid].depthBiasConstantFactor; - m_RenderState.bias.biasclamp = m_CreationInfo.m_Pipeline[liveid].depthBiasClamp; - m_RenderState.bias.slope = m_CreationInfo.m_Pipeline[liveid].depthBiasSlopeFactor; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_BLEND_CONSTANTS]) - { - memcpy(m_RenderState.blendConst, m_CreationInfo.m_Pipeline[liveid].blendConst, - sizeof(float) * 4); - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BOUNDS]) - { - m_RenderState.mindepth = m_CreationInfo.m_Pipeline[liveid].minDepthBounds; - m_RenderState.maxdepth = m_CreationInfo.m_Pipeline[liveid].maxDepthBounds; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK]) - { - m_RenderState.front.compare = m_CreationInfo.m_Pipeline[liveid].front.compareMask; - m_RenderState.back.compare = m_CreationInfo.m_Pipeline[liveid].back.compareMask; - } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_WRITE_MASK]) - { - m_RenderState.front.write = m_CreationInfo.m_Pipeline[liveid].front.writeMask; - m_RenderState.back.write = m_CreationInfo.m_Pipeline[liveid].back.writeMask; + m_RenderState.compute.pipeline = liveid; } - if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_REFERENCE]) + else { - m_RenderState.front.ref = m_CreationInfo.m_Pipeline[liveid].front.reference; - m_RenderState.back.ref = m_CreationInfo.m_Pipeline[liveid].back.reference; + m_RenderState.graphics.pipeline = liveid; + + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_VIEWPORT]) + { + m_RenderState.views = m_CreationInfo.m_Pipeline[liveid].viewports; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_SCISSOR]) + { + m_RenderState.scissors = m_CreationInfo.m_Pipeline[liveid].scissors; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_LINE_WIDTH]) + { + m_RenderState.lineWidth = m_CreationInfo.m_Pipeline[liveid].lineWidth; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BIAS]) + { + m_RenderState.bias.depth = m_CreationInfo.m_Pipeline[liveid].depthBiasConstantFactor; + m_RenderState.bias.biasclamp = m_CreationInfo.m_Pipeline[liveid].depthBiasClamp; + m_RenderState.bias.slope = m_CreationInfo.m_Pipeline[liveid].depthBiasSlopeFactor; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_BLEND_CONSTANTS]) + { + memcpy(m_RenderState.blendConst, m_CreationInfo.m_Pipeline[liveid].blendConst, + sizeof(float) * 4); + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_DEPTH_BOUNDS]) + { + m_RenderState.mindepth = m_CreationInfo.m_Pipeline[liveid].minDepthBounds; + m_RenderState.maxdepth = m_CreationInfo.m_Pipeline[liveid].maxDepthBounds; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK]) + { + m_RenderState.front.compare = m_CreationInfo.m_Pipeline[liveid].front.compareMask; + m_RenderState.back.compare = m_CreationInfo.m_Pipeline[liveid].back.compareMask; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_WRITE_MASK]) + { + m_RenderState.front.write = m_CreationInfo.m_Pipeline[liveid].front.writeMask; + m_RenderState.back.write = m_CreationInfo.m_Pipeline[liveid].back.writeMask; + } + if(!m_CreationInfo.m_Pipeline[liveid].dynamicStates[VK_DYNAMIC_STATE_STENCIL_REFERENCE]) + { + m_RenderState.front.ref = m_CreationInfo.m_Pipeline[liveid].front.reference; + m_RenderState.back.ref = m_CreationInfo.m_Pipeline[liveid].back.reference; + } } } } From 0a215a03eadb06663e4706e50c5aa4c923544f52 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 11:11:36 +0100 Subject: [PATCH 40/91] Set proper 3D texture resolution for histogram calculations --- renderdoc/driver/vulkan/vk_replay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 743367d376..2e31e82d15 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -3820,7 +3820,7 @@ bool VulkanReplay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, data->HistogramTextureResolution.x = (float)RDCMAX(uint32_t(iminfo.extent.width) >> mip, 1U); data->HistogramTextureResolution.y = (float)RDCMAX(uint32_t(iminfo.extent.height) >> mip, 1U); - data->HistogramTextureResolution.z = (float)RDCMAX(uint32_t(iminfo.arrayLayers) >> mip, 1U); + data->HistogramTextureResolution.z = (float)RDCMAX(uint32_t(iminfo.extent.depth) >> mip, 1U); if(iminfo.type != VK_IMAGE_TYPE_3D) data->HistogramSlice = (float)sliceFace + 0.001f; else @@ -4065,7 +4065,7 @@ bool VulkanReplay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t m data->HistogramTextureResolution.x = (float)RDCMAX(uint32_t(iminfo.extent.width) >> mip, 1U); data->HistogramTextureResolution.y = (float)RDCMAX(uint32_t(iminfo.extent.height) >> mip, 1U); - data->HistogramTextureResolution.z = (float)RDCMAX(uint32_t(iminfo.arrayLayers) >> mip, 1U); + data->HistogramTextureResolution.z = (float)RDCMAX(uint32_t(iminfo.extent.depth) >> mip, 1U); if(iminfo.type != VK_IMAGE_TYPE_3D) data->HistogramSlice = (float)sliceFace + 0.001f; else From 41ba1dcba5b55421a664f14a365d3a1538696b1e Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 12:26:22 +0100 Subject: [PATCH 41/91] Use sudo to update pip packages --- .travis.yml | 12 ++---------- scripts/travis/docs_setup.sh | 4 ++-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 980b46cf29..29a55e8387 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: cpp +sudo: required +dist: trusty branches: only: @@ -28,27 +30,17 @@ matrix: include: # only build docs on linux - os: linux - dist: trusty - sudo: false env: DOCS_BUILD=1 - os: linux - dist: trusty - sudo: required env: LINUX_BUILD=1 compiler: gcc - os: linux - dist: trusty - sudo: required env: LINUX_BUILD=1 compiler: clang - os: linux - dist: trusty - sudo: required env: LINUX_BUILD=1 RELEASE_BUILD=1 compiler: clang - os: linux - dist: trusty - sudo: required env: ANDROID_BUILD=1 compiler: clang - os: osx diff --git a/scripts/travis/docs_setup.sh b/scripts/travis/docs_setup.sh index d766b5520c..ca38ad8e0a 100644 --- a/scripts/travis/docs_setup.sh +++ b/scripts/travis/docs_setup.sh @@ -1,5 +1,5 @@ #!/bin/sh set -ev -pip install --upgrade pip setuptools -pip install Sphinx sphinx-rtd-theme +sudo pip install --upgrade pip setuptools +sudo pip install Sphinx sphinx-rtd-theme From 2ae8fb960257218f8a11ffec0ae6d5a44a559a71 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 12 Sep 2017 16:16:26 +0100 Subject: [PATCH 42/91] Fix tracking of dynamic offsets when binding multiple descriptor sets Before this, when binding multiple sets that use dynamic offsets, the wrong offsets would be stored for all sets other than the first. This caused the wrong offsets to be used when replaying individual draws. --- renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index f56a0e5366..320c35f7e2 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -1334,6 +1334,7 @@ bool WrappedVulkan::Serialise_vkCmdBindDescriptorSets( descsets[first + i].descSet = descriptorIDs[i]; uint32_t dynCount = m_CreationInfo.m_DescSetLayout[descSetLayouts[first + i]].dynamicCount; descsets[first + i].offsets.assign(offsIter, offsIter + dynCount); + offsIter += dynCount; dynConsumed += dynCount; RDCASSERT(dynConsumed <= offsCount); } From 43c3bf5cf8e8f78c06de94deb292d01ea4c7cc4a Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 14:16:15 +0100 Subject: [PATCH 43/91] Don't select unused bindings over a valid bind in vk pipeline state * If there's a variable which is unused and has no binding declared, it will be sorted to the end of the list and given a binding of 0. We don't want to let this override a valid binding for 0, so make sure we prioritise any variable which is marked as used over one that is unused. --- .../VulkanPipelineStateViewer.cpp | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index 4115bd537c..22d23e9936 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -672,6 +672,26 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails, if(shaderDetails != NULL) { + // we find the matching binding for this set/binding. + // The spec requires that there are no overlapping definitions, or if there are they have + // compatible types so we can just pick the first one we come across. + // The spec also doesn't require variables which are statically unused to have valid bindings, + // so they may be overlapping or possibly just defaulted to 0. + // Any variables with no binding declared at all were set to 0 and sorted to the end at + // reflection time, so we can just use a single algorithm to select the best candidate: + // + // 1. Search for matching bindset/bind resources. It doesn't matter which 'namespace' (sampler/ + // read-only/read-write) we search in, because if there's a conflict the behaviour is + // illegal and if there's no conflict we won't get any ambiguity. + // 2. If we find a match, select it for use. + // 3. If we find a second match, use it in preference only if the old one was !used, and the new + // one is used. + // + // This will make us select the best possible option - the first declared used resource + // at a particular binding, ignoring any unused resources at that binding before/after. Or if + // there's no used resource at all, the first declared unused resource (which will prefer + // resources with proper bindings over those without, as with the sorting mentioned above). + for(int i = 0; i < shaderDetails->ReadOnlyResources.count; i++) { const ShaderResource &ro = shaderDetails->ReadOnlyResources[i]; @@ -679,9 +699,15 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails, if(stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].bindset == bindset && stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].bind == bind) { - bindPoint = (uint)i; - shaderRes = &ro; - bindMap = &stage.BindpointMapping.ReadOnlyResources[ro.bindPoint]; + // use this one either if we have no candidate, or the candidate we have is unused and this + // one is used + if(bindMap == NULL || + (!bindMap->used && stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].used)) + { + bindPoint = (uint)i; + shaderRes = &ro; + bindMap = &stage.BindpointMapping.ReadOnlyResources[ro.bindPoint]; + } } } @@ -692,10 +718,16 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails, if(stage.BindpointMapping.ReadWriteResources[rw.bindPoint].bindset == bindset && stage.BindpointMapping.ReadWriteResources[rw.bindPoint].bind == bind) { - bindPoint = (uint)i; - isrw = true; - shaderRes = &rw; - bindMap = &stage.BindpointMapping.ReadWriteResources[rw.bindPoint]; + // use this one either if we have no candidate, or the candidate we have is unused and this + // one is used + if(bindMap == NULL || + (!bindMap->used && stage.BindpointMapping.ReadWriteResources[rw.bindPoint].used)) + { + bindPoint = (uint)i; + isrw = true; + shaderRes = &rw; + bindMap = &stage.BindpointMapping.ReadWriteResources[rw.bindPoint]; + } } } } From 7a38f9d853acd46fffcaccfd93254670278c7c2c Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 14:24:48 +0100 Subject: [PATCH 44/91] Add alpha2coverage to VK state view, move it & alpha2one to MSAA group --- .../VulkanPipelineStateViewer.cpp | 3 +- .../VulkanPipelineStateViewer.ui | 97 ++++++++++--------- 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index 22d23e9936..12c465077d 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -1736,6 +1736,8 @@ void VulkanPipelineStateViewer::setState() ui->sampleShading->setPixmap(state.MSAA.sampleShadingEnable ? tick : cross); ui->minSampleShading->setText(Formatter::Format(state.MSAA.minSampleShading)); ui->sampleMask->setText(Formatter::Format(state.MSAA.sampleMask, true)); + ui->alphaToOne->setPixmap(state.CB.alphaToOneEnable ? tick : cross); + ui->alphaToCoverage->setPixmap(state.CB.alphaToCoverageEnable ? tick : cross); //////////////////////////////////////////////// // Output Merger @@ -1912,7 +1914,6 @@ void VulkanPipelineStateViewer::setState() .arg(state.CB.blendConst[2], 0, 'f', 2) .arg(state.CB.blendConst[3], 0, 'f', 2)); ui->logicOp->setText(state.CB.logicOpEnable ? ToQStr(state.CB.logic) : lit("-")); - ui->alphaToOne->setPixmap(state.CB.alphaToOneEnable ? tick : cross); ui->depthEnabled->setPixmap(state.DS.depthTestEnable ? tick : cross); ui->depthFunc->setText(ToQStr(state.DS.depthCompareOp)); diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.ui b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.ui index 79026fc29d..1f714a7f6e 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.ui +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.ui @@ -2162,22 +2162,6 @@ - - - - Qt::Vertical - - - QSizePolicy::Preferred - - - - 0 - 0 - - - - @@ -2210,6 +2194,58 @@ + + + + Alpha to 1: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + :/cross.png + + + Qt::AlignCenter + + + 4 + + + + + + + Alpha to Coverage: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + :/cross.png + + + Qt::AlignCenter + + + 4 + + + @@ -2755,35 +2791,6 @@ - - - - Alpha to 1: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - true - - - - - - - - - - :/cross.png - - - Qt::AlignCenter - - - 4 - - - From 809217ec60c97c0eafc58122689c6d403b55c0b9 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 14:49:42 +0100 Subject: [PATCH 45/91] Fix formatting of string to not append an int interpreted as a QChar --- qrenderdoc/Windows/TextureViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 75374cf744..50d05931c6 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -3188,7 +3188,7 @@ void TextureViewer::on_mipLevel_currentIndexChanged(int index) ui->sliceFace->clear(); for(uint32_t i = 0; i < numSlices; i++) - ui->sliceFace->addItem(tr("Slice ") + i); + ui->sliceFace->addItem(tr("Slice %1").arg(i)); // changing sliceFace index will handle updating range & re-picking ui->sliceFace->setCurrentIndex((int)qBound(0U, newSlice, numSlices - 1)); From 8617a7fad3125f8dfcbc8fa1542d02a1afc6a0ea Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 14:50:02 +0100 Subject: [PATCH 46/91] Fix display of 3D textures not applying mip offset to slice --- renderdoc/driver/d3d11/d3d11_debug.cpp | 2 +- renderdoc/driver/d3d12/d3d12_debug.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index 6eb0847441..9dfb1a0104 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -3584,7 +3584,7 @@ bool D3D11DebugManager::RenderTexture(TextureDisplay cfg, bool blendAlpha) if(details.texType == eTexType_3D) { pixelData.OutputDisplayFormat = RESTYPE_TEX3D; - pixelData.Slice = float(cfg.sliceFace); + pixelData.Slice = float(cfg.sliceFace >> cfg.mip); } else if(details.texType == eTexType_1D) { diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 7f695e1404..bf6a4f8d23 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -8032,7 +8032,7 @@ bool D3D12DebugManager::RenderTextureInternal(D3D12_CPU_DESCRIPTOR_HANDLE rtv, T pixelData.Slice = float(RDCCLAMP(cfg.sliceFace, 0U, uint32_t(resourceDesc.DepthOrArraySize - 1))); if(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) - pixelData.Slice = float(cfg.sliceFace); + pixelData.Slice = float(cfg.sliceFace >> cfg.mip); vector barriers; int resType = 0; From 9d54cf6b797384d9b734f7ec0e37bea2ecd118f8 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 14:52:18 +0100 Subject: [PATCH 47/91] Special case - manually backport "Don't select unused bindings..." to C# --- .../VulkanPipelineStateViewer.cs | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs b/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs index cc90e87089..5bc57232a0 100644 --- a/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs @@ -381,6 +381,26 @@ private void AddResourceRow(ShaderReflection shaderDetails, VulkanPipelineState. if (shaderDetails != null) { + // we find the matching binding for this set/binding. + // The spec requires that there are no overlapping definitions, or if there are they have + // compatible types so we can just pick the first one we come across. + // The spec also doesn't require variables which are statically unused to have valid bindings, + // so they may be overlapping or possibly just defaulted to 0. + // Any variables with no binding declared at all were set to 0 and sorted to the end at + // reflection time, so we can just use a single algorithm to select the best candidate: + // + // 1. Search for matching bindset/bind resources. It doesn't matter which 'namespace' (sampler/ + // read-only/read-write) we search in, because if there's a conflict the behaviour is + // illegal and if there's no conflict we won't get any ambiguity. + // 2. If we find a match, select it for use. + // 3. If we find a second match, use it in preference only if the old one was !used, and the new + // one is used. + // + // This will make us select the best possible option - the first declared used resource + // at a particular binding, ignoring any unused resources at that binding before/after. Or if + // there's no used resource at all, the first declared unused resource (which will prefer + // resources with proper bindings over those without, as with the sorting mentioned above). + for (int i = 0; i < shaderDetails.ReadOnlyResources.Length; i++) { var ro = shaderDetails.ReadOnlyResources[i]; @@ -388,9 +408,12 @@ private void AddResourceRow(ShaderReflection shaderDetails, VulkanPipelineState. if (stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].bindset == bindset && stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].bind == bind) { - bindPoint = (uint)i; - shaderRes = ro; - bindMap = stage.BindpointMapping.ReadOnlyResources[ro.bindPoint]; + if (bindMap == null || (!bindMap.used && stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].used)) + { + bindPoint = (uint)i; + shaderRes = ro; + bindMap = stage.BindpointMapping.ReadOnlyResources[ro.bindPoint]; + } } } @@ -401,10 +424,13 @@ private void AddResourceRow(ShaderReflection shaderDetails, VulkanPipelineState. if (stage.BindpointMapping.ReadWriteResources[rw.bindPoint].bindset == bindset && stage.BindpointMapping.ReadWriteResources[rw.bindPoint].bind == bind) { - bindPoint = (uint)i; - isrw = true; - shaderRes = rw; - bindMap = stage.BindpointMapping.ReadWriteResources[rw.bindPoint]; + if (bindMap == null || (!bindMap.used && stage.BindpointMapping.ReadWriteResources[rw.bindPoint].used)) + { + bindPoint = (uint)i; + isrw = true; + shaderRes = rw; + bindMap = stage.BindpointMapping.ReadWriteResources[rw.bindPoint]; + } } } } From e588b496e5861d386c71f5c122c319d0636a980c Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 11:10:35 +0100 Subject: [PATCH 48/91] Immediately delete any open LiveCapture windows when closing --- qrenderdoc/Windows/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qrenderdoc/Windows/MainWindow.cpp b/qrenderdoc/Windows/MainWindow.cpp index a7df0be841..61776734e0 100644 --- a/qrenderdoc/Windows/MainWindow.cpp +++ b/qrenderdoc/Windows/MainWindow.cpp @@ -1682,7 +1682,7 @@ void MainWindow::closeEvent(QCloseEvent *event) for(LiveCapture *live : m_LiveCaptures) { live->cleanItems(); - live->close(); + delete live; } SaveLayout(0); From 9e6cee3f5c67da993f696bf80fa8525c1bd24b84 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 11 Sep 2017 10:45:32 +0100 Subject: [PATCH 49/91] Turn off tracing after execution finishes * This means the tracing isn't still lingering around when we shutdown and the context is destroyed. --- qrenderdoc/Code/pyrenderdoc/PythonContext.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp b/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp index 2a1945903d..ef93a6e7bd 100644 --- a/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp +++ b/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp @@ -519,6 +519,8 @@ void PythonContext::executeString(const QString &filename, const QString &source // catch any output outputTick(); + PyEval_SetTrace(NULL, NULL); + Py_XDECREF(thisobj); Py_XDECREF(traceContext); } From d129222464d8119bfd20278c482cd38d440d1793 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 31 Aug 2017 15:14:29 +0100 Subject: [PATCH 50/91] Make sure to refresh model if only children were added --- qrenderdoc/Widgets/Extended/RDTreeWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp b/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp index 43a5419787..dfd5fa8088 100644 --- a/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp +++ b/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp @@ -455,7 +455,7 @@ void RDTreeWidget::endUpdate() { m_queueUpdates = false; - if(m_queuedRoles) + if(m_queuedRoles || m_queuedChildren) { // if we updated multiple different trees we can't issue a single dataChanged for everything // under a parent. Refresh the whole model. From b6032300234888245f46b053fdc8a4c686cfe093 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 29 Aug 2017 13:29:25 +0100 Subject: [PATCH 51/91] Fix texture saving not propagating the right settings --- qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp | 9 +++++++++ qrenderdoc/Windows/TextureViewer.cpp | 1 + 2 files changed, 10 insertions(+) diff --git a/qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp b/qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp index f95265e831..716abb84d0 100644 --- a/qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp +++ b/qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp @@ -77,11 +77,17 @@ TextureSaveDialog::TextureSaveDialog(const TextureDescription &t, const TextureS ui->mipSelect->addItem( QFormatStr("%1 - %2x%3").arg(i).arg(qMax(1U, tex.width >> i)).arg(qMax(1U, tex.height >> i))); + // reset as it might have been changed by adding items + saveData.mip = s.mip; + ui->mipSelect->setCurrentIndex(saveData.mip >= 0 ? saveData.mip : 0); for(uint32_t i = 0; i < tex.msSamp; i++) ui->sampleSelect->addItem(tr("Sample %1").arg(i)); + // reset as it might have been changed by adding items + saveData.sample = s.sample; + ui->sampleSelect->setCurrentIndex(qMin( (int)tex.msSamp, (saveData.sample.sampleIndex == ~0U ? 0 : (int)saveData.sample.sampleIndex))); @@ -114,6 +120,9 @@ TextureSaveDialog::TextureSaveDialog(const TextureDescription &t, const TextureS } } + // reset as it might have been changed by adding items + saveData.slice = s.slice; + ui->sliceSelect->setCurrentIndex(saveData.slice.sliceIndex >= 0 ? saveData.slice.sliceIndex : 0); ui->gridWidth->setMaximum(tex.depth * tex.arraysize * tex.msSamp); diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 50d05931c6..62d59160d5 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -3343,6 +3343,7 @@ void TextureViewer::on_saveTex_clicked() TextureSave config; memset(&config, 0, sizeof(config)); + config.jpegQuality = 90; config.id = m_TexDisplay.texid; config.typeHint = m_TexDisplay.typeHint; From 4e275421bbbc1d79280178a2b201124c6b751516 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 25 Aug 2017 12:26:54 +0100 Subject: [PATCH 52/91] Set basevertex to 0 when calculating column data width --- qrenderdoc/Windows/BufferViewer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index e8fffee0b8..6d84974b25 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -2698,6 +2698,7 @@ void BufferViewer::CalcColumnWidth(int maxNumRows) FormatElement(headerText, 0, 16, false, 1, false, 1, intFmt, false, false)); m_ModelVSIn->numRows = 2; + m_ModelVSIn->baseVertex = 0; if(m_ModelVSIn->indices) m_ModelVSIn->indices->deref(); From e8d9efb84472d4f49c85f1f6aad1b46cb4aaab4a Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 25 Aug 2017 12:26:45 +0100 Subject: [PATCH 53/91] Reset hover index when widget is cleared, don't leave it to be stale --- qrenderdoc/Widgets/Extended/RDTreeWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp b/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp index dfd5fa8088..217db82218 100644 --- a/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp +++ b/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp @@ -559,6 +559,7 @@ void RDTreeWidget::scrollToItem(RDTreeWidgetItem *node) void RDTreeWidget::clear() { m_root->clear(); + m_currentHoverIndex = QModelIndex(); } void RDTreeWidget::mouseMoveEvent(QMouseEvent *e) From c7dda154ab9b416c1a737403623792516d1d5160 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 17 Aug 2017 13:00:41 +0100 Subject: [PATCH 54/91] Fix format string --- qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index 12c465077d..70af8ab122 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -1409,7 +1409,7 @@ void VulkanPipelineStateViewer::setShaderState(const VKPipe::Shader &stage, RDTreeWidgetItem *node = new RDTreeWidgetItem({QString(), QString(), ToQStr(cblock.name), tr("Push constants"), - QString(), tr("%1 Variable(s)", "", cblock.variables.count)}); + QString(), tr("%1 Variables").arg(cblock.variables.count)}); node->setTag(QVariant::fromValue(VulkanCBufferTag(cb, 0))); From 04b715890c2f2e4199af8aa475e53e257f034fe5 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 15 Aug 2017 13:08:34 +0100 Subject: [PATCH 55/91] find previous button should be left of the find next button --- qrenderdoc/Windows/EventBrowser.ui | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/qrenderdoc/Windows/EventBrowser.ui b/qrenderdoc/Windows/EventBrowser.ui index ad82120be8..42e64a3587 100644 --- a/qrenderdoc/Windows/EventBrowser.ui +++ b/qrenderdoc/Windows/EventBrowser.ui @@ -358,13 +358,14 @@ - + - :/arrow_right.png:/arrow_right.png + :/arrow_left.png:/arrow_left.png + true @@ -372,13 +373,13 @@ - + - :/arrow_left.png:/arrow_left.png + :/arrow_right.png:/arrow_right.png true From 7a78ae67ff9cd5d17a58fc30f6263e13a4237986 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 13 Sep 2017 16:00:55 +0100 Subject: [PATCH 56/91] Revert mistakenly cherry-picked follow up to change not on v0.x This reverts commit d129222464d8119bfd20278c482cd38d440d1793. --- qrenderdoc/Widgets/Extended/RDTreeWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp b/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp index 217db82218..01161e1796 100644 --- a/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp +++ b/qrenderdoc/Widgets/Extended/RDTreeWidget.cpp @@ -455,7 +455,7 @@ void RDTreeWidget::endUpdate() { m_queueUpdates = false; - if(m_queuedRoles || m_queuedChildren) + if(m_queuedRoles) { // if we updated multiple different trees we can't issue a single dataChanged for everything // under a parent. Refresh the whole model. From 2a8cb39ef7445a682829fb46074ac00002067d37 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 14 Sep 2017 10:47:43 +0100 Subject: [PATCH 57/91] Use GL_DEPTH_ATTACHMENT when attaching depth-only texture to FBO --- renderdoc/driver/gl/gl_debug.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index 1c3d1fab13..acd61bb239 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -3149,7 +3149,13 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeHint, DebugOve gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_S, eGL_CLAMP_TO_EDGE); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_WRAP_T, eGL_CLAMP_TO_EDGE); - gl.glFramebufferTexture(eGL_FRAMEBUFFER, eGL_DEPTH_STENCIL_ATTACHMENT, quadtexs[1], 0); + + GLenum dsAttach = eGL_DEPTH_STENCIL_ATTACHMENT; + + if(GetBaseFormat(fmt) == eGL_DEPTH_COMPONENT) + dsAttach = eGL_DEPTH_ATTACHMENT; + + gl.glFramebufferTexture(eGL_FRAMEBUFFER, dsAttach, quadtexs[1], 0); if(overlay == DebugOverlay::QuadOverdrawPass) ReplayLog(events[0], eReplay_WithoutDraw); From 022188c4b77987f8e0615ab3e2bc61f5e13fb553 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 14 Sep 2017 10:48:44 +0100 Subject: [PATCH 58/91] Fix assertion to allow 8 color attachments. Refs #743 --- renderdoc/driver/vulkan/vk_core.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index b8f9b466d0..252ac4d8ae 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -2809,9 +2809,9 @@ void WrappedVulkan::AddDrawcall(const DrawcallDescription &d, bool hasEvents) vector &colAtt = m_CreationInfo.m_RenderPass[rp].subpasses[sp].colorAttachments; int32_t dsAtt = m_CreationInfo.m_RenderPass[rp].subpasses[sp].depthstencilAttachment; - RDCASSERT(colAtt.size() < 8); + RDCASSERT(colAtt.size() <= ARRAY_COUNT(draw.outputs)); - for(int i = 0; i < 8 && i < (int)colAtt.size(); i++) + for(size_t i = 0; i < ARRAY_COUNT(draw.outputs) && i < colAtt.size(); i++) { if(colAtt[i] == VK_ATTACHMENT_UNUSED) continue; From 9e102f801a14de504ff1468ce943abbb4c7065ca Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 19 Sep 2017 16:56:38 +0100 Subject: [PATCH 59/91] Add a warning if only CMAKE_INSTALL_PREFIX is customised * VULKAN_LAYER_FOLDER points outside the prefix to /etc in absolute, so usually if you customise one you'll want to customise the other. * This is especially true if you're pointing the install prefix at some non-root location, and you want make install to succeed instead of failing to write to /etc. --- renderdoc/driver/vulkan/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/renderdoc/driver/vulkan/CMakeLists.txt b/renderdoc/driver/vulkan/CMakeLists.txt index 9ddd2ba7de..b5d52c67b9 100644 --- a/renderdoc/driver/vulkan/CMakeLists.txt +++ b/renderdoc/driver/vulkan/CMakeLists.txt @@ -40,11 +40,17 @@ set(sources set(definitions ${RDOC_DEFINITIONS}) +set(VULKAN_LAYER_FOLDER_DEFAULT /etc/vulkan/implicit_layer.d) + +if(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND NOT DEFINED VULKAN_LAYER_FOLDER) + message(WARNING "*** CMAKE_INSTALL_PREFIX has been customised to ${CMAKE_INSTALL_PREFIX}, but VULKAN_LAYER_FOLDER is not customised and defaults to ${VULKAN_LAYER_FOLDER_DEFAULT}. This may not do what you expect, e.g. installing to a non-root location ***") +endif() + # This must be specified separately because it needs to go in /etc regardless of what the install # prefix is, since the loader only looks in a set location (and /usr/share is reserved for distribution # packages). For people who want to 'make install' to another folder, perhaps for preparing a package, # they can set this variable to make sure it stays local -set(VULKAN_LAYER_FOLDER /etc/vulkan/implicit_layer.d CACHE PATH "Path to install the vulkan layer file") +set(VULKAN_LAYER_FOLDER ${VULKAN_LAYER_FOLDER_DEFAULT} CACHE PATH "Path to install the vulkan layer file") if(ANDROID) list(APPEND sources vk_posix.cpp vk_android.cpp vk_layer_android.cpp) From 3f2d82acfb31429cdfd34529e4b47cce21bf37ee Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 19 Sep 2017 16:57:40 +0100 Subject: [PATCH 60/91] Fixes for compiling with disabled xcb, or disabled xlib & xcb --- renderdoc/api/replay/renderdoc_replay.h | 2 +- renderdoc/driver/vulkan/vk_posix.cpp | 6 +++++- renderdoc/os/posix/linux/linux_stringio.cpp | 7 ++++++- renderdoccmd/renderdoccmd_linux.cpp | 2 ++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index f94f3c724e..eaaacef6aa 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -118,7 +118,7 @@ struct XlibWindowData #else -typedef void *Display; +typedef struct _XDisplay Display; #endif diff --git a/renderdoc/driver/vulkan/vk_posix.cpp b/renderdoc/driver/vulkan/vk_posix.cpp index af7ed30e82..ec54320623 100644 --- a/renderdoc/driver/vulkan/vk_posix.cpp +++ b/renderdoc/driver/vulkan/vk_posix.cpp @@ -157,7 +157,6 @@ VkBool32 WrappedVulkan::vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalD namespace Keyboard { void UseConnection(xcb_connection_t *conn); -void CloneDisplay(Display *dpy); } VkResult WrappedVulkan::vkCreateXcbSurfaceKHR(VkInstance instance, @@ -199,6 +198,11 @@ VkBool32 WrappedVulkan::vkGetPhysicalDeviceXlibPresentationSupportKHR( visualID); } +namespace Keyboard +{ +void CloneDisplay(Display *dpy); +} + VkResult WrappedVulkan::vkCreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, diff --git a/renderdoc/os/posix/linux/linux_stringio.cpp b/renderdoc/os/posix/linux/linux_stringio.cpp index 0948bcbe29..37de5366e8 100644 --- a/renderdoc/os/posix/linux/linux_stringio.cpp +++ b/renderdoc/os/posix/linux/linux_stringio.cpp @@ -42,6 +42,7 @@ #endif #if ENABLED(RDOC_XCB) +#include #include #endif @@ -137,6 +138,10 @@ bool GetXlibKeyState(int key) // if RENDERDOC_WINDOWING_XLIB is not enabled +void CloneDisplay(Display *dpy) +{ +} + bool GetXlibKeyState(int key) { return false; @@ -160,7 +165,7 @@ bool GetXCBKeyState(int key) if(symbols == NULL) return false; - KeySym ks = 0; + xcb_keysym_t ks = 0; if(key >= eRENDERDOC_Key_A && key <= eRENDERDOC_Key_Z) ks = key; diff --git a/renderdoccmd/renderdoccmd_linux.cpp b/renderdoccmd/renderdoccmd_linux.cpp index 99a129ccf5..48e5e7b5a3 100644 --- a/renderdoccmd/renderdoccmd_linux.cpp +++ b/renderdoccmd/renderdoccmd_linux.cpp @@ -372,11 +372,13 @@ int main(int argc, char *argv[]) GlobalEnvironment env; +#if defined(RENDERDOC_WINDOWING_XLIB) || defined(RENDERDOC_WINDOWING_XCB) // call XInitThreads - although we don't use xlib concurrently the driver might need to. XInitThreads(); // we don't check if display successfully opened, it's only a problem if it's needed later. display = env.xlibDisplay = XOpenDisplay(NULL); +#endif #if defined(RENDERDOC_SUPPORT_VULKAN) VerifyVulkanLayer(env, argc, argv); From 4d5ab22e977362fe5fc4a55fd21353bd764711d5 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 19 Sep 2017 17:04:33 +0100 Subject: [PATCH 61/91] Don't display a register/slot index for built-in shader variables --- qrenderdoc/Windows/ShaderViewer.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/qrenderdoc/Windows/ShaderViewer.cpp b/qrenderdoc/Windows/ShaderViewer.cpp index 8629e58a26..d8c5e01323 100644 --- a/qrenderdoc/Windows/ShaderViewer.cpp +++ b/qrenderdoc/Windows/ShaderViewer.cpp @@ -515,8 +515,11 @@ void ShaderViewer::debugShader(const ShaderBindpointMapping *bind, const ShaderR QString semIdx = s.needSemanticIndex ? QString::number(s.semanticIndex) : QString(); + QString regIdx = + s.systemValue == ShaderBuiltin::Undefined ? QString::number(s.regIndex) : lit("-"); + ui->inputSig->addTopLevelItem(new RDTreeWidgetItem( - {name, semIdx, s.regIndex, TypeString(s), ToQStr(s.systemValue), + {name, semIdx, QString::number(s.regIndex), TypeString(s), ToQStr(s.systemValue), GetComponentString(s.regChannelMask), GetComponentString(s.channelUsedMask)})); } @@ -543,8 +546,11 @@ void ShaderViewer::debugShader(const ShaderBindpointMapping *bind, const ShaderR QString semIdx = s.needSemanticIndex ? QString::number(s.semanticIndex) : QString(); + QString regIdx = + s.systemValue == ShaderBuiltin::Undefined ? QString::number(s.regIndex) : lit("-"); + ui->outputSig->addTopLevelItem(new RDTreeWidgetItem( - {name, semIdx, s.regIndex, TypeString(s), ToQStr(s.systemValue), + {name, semIdx, regIdx, TypeString(s), ToQStr(s.systemValue), GetComponentString(s.regChannelMask), GetComponentString(s.channelUsedMask)})); } } From fad2ce69640bc44ba793737f9fb7b459bf2cec1a Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 19 Sep 2017 17:06:52 +0100 Subject: [PATCH 62/91] Don't strip capture's device extensions away with backwards strcmp --- renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index a5001abb41..d6536a854b 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -888,13 +888,12 @@ bool WrappedVulkan::Serialise_vkCreateDevice(Serialiser *localSerialiser, for(uint32_t i = 0; i < createInfo.enabledExtensionCount; i++) { // don't include the debug marker extension - if(strcmp(createInfo.ppEnabledExtensionNames[i], VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) + if(!strcmp(createInfo.ppEnabledExtensionNames[i], VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) continue; // don't include direct-display WSI extensions - if(strcmp(createInfo.ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) || - strcmp(createInfo.ppEnabledExtensionNames[i], VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME) || - strcmp(createInfo.ppEnabledExtensionNames[i], VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME)) + if(!strcmp(createInfo.ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) || + !strcmp(createInfo.ppEnabledExtensionNames[i], VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME)) continue; Extensions.push_back(createInfo.ppEnabledExtensionNames[i]); From 57a897c5b038fb900c9bde98f260c7c802a5b83d Mon Sep 17 00:00:00 2001 From: michaelrgb Date: Mon, 18 Sep 2017 17:32:12 +0100 Subject: [PATCH 63/91] Use ES color-renderable SRGB8_ALPHA8 for output window backbuffer. --- renderdoc/driver/gl/gl_replay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index f05b551e50..88a31111f1 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -223,8 +223,8 @@ void GLReplay::CreateOutputWindowBackbuffer(OutputWindow &outwin, bool depth) gl.glGenTextures(1, &outwin.BlitData.backbuffer); gl.glBindTexture(eGL_TEXTURE_2D, outwin.BlitData.backbuffer); - gl.glTextureImage2DEXT(outwin.BlitData.backbuffer, eGL_TEXTURE_2D, 0, eGL_SRGB8, outwin.width, - outwin.height, 0, eGL_RGB, eGL_UNSIGNED_BYTE, NULL); + gl.glTextureImage2DEXT(outwin.BlitData.backbuffer, eGL_TEXTURE_2D, 0, eGL_SRGB8_ALPHA8, + outwin.width, outwin.height, 0, eGL_RGBA, eGL_UNSIGNED_BYTE, NULL); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAX_LEVEL, 0); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST); gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER, eGL_NEAREST); From 04df0d60cd6c50f02cd7b4c00f1f9de09c0738c5 Mon Sep 17 00:00:00 2001 From: michaelrgb Date: Tue, 19 Sep 2017 12:04:50 +0100 Subject: [PATCH 64/91] Fix offscreen render setting GLWindowingData::wnd=0, an error condition. --- renderdoc/driver/gl/gl_common.h | 8 +++++--- renderdoc/driver/gl/gl_hooks_egl.cpp | 3 --- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 8197452071..33204fe0a3 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -161,7 +161,6 @@ struct GLWindowingData egl_ctx = 0; egl_dpy = 0; egl_wnd = 0; - wnd = 0; } void SetCtx(void *c) { egl_ctx = (void *)c; } @@ -172,8 +171,11 @@ struct GLWindowingData EGLContext egl_ctx; }; EGLDisplay egl_dpy; - EGLSurface egl_wnd; - ANativeWindow *wnd; + union + { + EGLSurface egl_wnd; + void *wnd; + }; }; #else diff --git a/renderdoc/driver/gl/gl_hooks_egl.cpp b/renderdoc/driver/gl/gl_hooks_egl.cpp index bc5cf90d29..832475c706 100644 --- a/renderdoc/driver/gl/gl_hooks_egl.cpp +++ b/renderdoc/driver/gl/gl_hooks_egl.cpp @@ -276,9 +276,6 @@ class EGLHook : LibraryHook, public GLPlatform ret.egl_dpy = eglDisplay; ret.egl_ctx = ctx; ret.egl_wnd = surface; -#if ENABLED(RDOC_ANDROID) - ret.wnd = (ANativeWindow *)window; -#endif return ret; } From 8bf32ac5608af28e3adecc9d1b9b0aa4939a0082 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 19 Sep 2017 19:43:59 +0100 Subject: [PATCH 65/91] Disable CMAKE_INSTALL_PREFIX message for android builds --- renderdoc/driver/vulkan/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderdoc/driver/vulkan/CMakeLists.txt b/renderdoc/driver/vulkan/CMakeLists.txt index b5d52c67b9..27f913f4a9 100644 --- a/renderdoc/driver/vulkan/CMakeLists.txt +++ b/renderdoc/driver/vulkan/CMakeLists.txt @@ -42,7 +42,7 @@ set(definitions ${RDOC_DEFINITIONS}) set(VULKAN_LAYER_FOLDER_DEFAULT /etc/vulkan/implicit_layer.d) -if(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND NOT DEFINED VULKAN_LAYER_FOLDER) +if(NOT ANDROID AND NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND NOT DEFINED VULKAN_LAYER_FOLDER) message(WARNING "*** CMAKE_INSTALL_PREFIX has been customised to ${CMAKE_INSTALL_PREFIX}, but VULKAN_LAYER_FOLDER is not customised and defaults to ${VULKAN_LAYER_FOLDER_DEFAULT}. This may not do what you expect, e.g. installing to a non-root location ***") endif() From 9c1de3a876b50e7cfef9374e83172cce7ae9c8b6 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 26 Sep 2017 10:12:05 +0100 Subject: [PATCH 66/91] Get NULL-check the right way around in ?: operator. Refs #754 --- renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp index fbfa8273c4..323dbd7ec0 100644 --- a/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp @@ -4181,8 +4181,8 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexBuffers(GLuint vaobj, GLuint fi buffers && buffers[i] ? GetResourceManager()->GetID(BufferRes(GetCtx(), buffers[i])) : ResourceId()); - SERIALISE_ELEMENT(uint64_t, offset, buffers ? 0 : (uint64_t)offsets[i]); - SERIALISE_ELEMENT(uint64_t, stride, buffers ? 0 : (uint64_t)strides[i]); + SERIALISE_ELEMENT(uint64_t, offset, buffers ? (uint64_t)offsets[i] : 0); + SERIALISE_ELEMENT(uint64_t, stride, buffers ? (uint64_t)strides[i] : 0); if(m_State <= EXECUTING) { From e037ac02ffc31fb898f44cf1ed0ff666cae51697 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 26 Sep 2017 10:16:18 +0100 Subject: [PATCH 67/91] Add note to error message about possible startup fault - missing DLLs --- renderdoc/os/win32/win32_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderdoc/os/win32/win32_process.cpp b/renderdoc/os/win32/win32_process.cpp index 4d62434ba4..b5370058c1 100644 --- a/renderdoc/os/win32/win32_process.cpp +++ b/renderdoc/os/win32/win32_process.cpp @@ -326,7 +326,7 @@ uintptr_t FindRemoteDLL(DWORD pid, wstring libName) { RDCERR( "Error injecting into remote process with PID %u which is no longer available.\n" - "Possibly the process has crashed during early startup?", + "Possibly the process has crashed during early startup, or is missing DLLs to run?", pid); } else From 5ccc62f1fe0a7cea886fe240b0ee22bcc7c82267 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 20 Sep 2017 17:05:34 +0100 Subject: [PATCH 68/91] Auto-guess format of thumbnail from .jpg file extension --- renderdoccmd/renderdoccmd.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/renderdoccmd/renderdoccmd.cpp b/renderdoccmd/renderdoccmd.cpp index d3727bb8e1..9d29bbcc10 100644 --- a/renderdoccmd/renderdoccmd.cpp +++ b/renderdoccmd/renderdoccmd.cpp @@ -270,6 +270,8 @@ struct ThumbCommand : public Command type = FileType::TGA; else if(dot != NULL && strstr(dot, "bmp")) type = FileType::BMP; + else if(dot != NULL && strstr(dot, "jpg")) + type = FileType::JPG; else std::cerr << "Couldn't guess format from '" << outfile << "', defaulting to jpg." << std::endl; From 50f03de69bfae75a77cba3f32750e291c3e98441 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 18 Sep 2017 15:38:55 +0100 Subject: [PATCH 69/91] Add reference to SPIR-V library in AMD library --- renderdoc/driver/ihv/amd/AMD.vcxproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/renderdoc/driver/ihv/amd/AMD.vcxproj b/renderdoc/driver/ihv/amd/AMD.vcxproj index b8875c3348..1999bd24f2 100644 --- a/renderdoc/driver/ihv/amd/AMD.vcxproj +++ b/renderdoc/driver/ihv/amd/AMD.vcxproj @@ -127,6 +127,11 @@ + + + {0aae0ad1-371b-4a36-9ed1-80e10e960605} + + From 019b3072a1ef805a9bbaa6a76c1e5ad155066a2b Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 29 Sep 2017 12:05:09 +0100 Subject: [PATCH 70/91] When no event is found on >= search, fallback to *last* event not first. --- renderdoc/driver/d3d11/d3d11_context.cpp | 2 +- renderdoc/driver/d3d12/d3d12_commands.cpp | 2 +- renderdoc/driver/gl/gl_driver.cpp | 2 +- renderdoc/driver/vulkan/vk_core.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_context.cpp b/renderdoc/driver/d3d11/d3d11_context.cpp index 17ce14c9ba..c7baf02b49 100644 --- a/renderdoc/driver/d3d11/d3d11_context.cpp +++ b/renderdoc/driver/d3d11/d3d11_context.cpp @@ -1038,7 +1038,7 @@ const APIEvent &WrappedID3D11DeviceContext::GetEvent(uint32_t eventID) return e; } - return m_Events[0]; + return m_Events.back(); } void WrappedID3D11DeviceContext::ReplayFakeContext(ResourceId id) diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index e23ec5815c..46f261b99d 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -262,7 +262,7 @@ const APIEvent &WrappedID3D12CommandQueue::GetEvent(uint32_t eventID) return e; } - return m_Cmd.m_Events[0]; + return m_Cmd.m_Events.back(); } void WrappedID3D12CommandQueue::ProcessChunk(uint64_t offset, D3D12ChunkType chunk) diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 369ba1eb5b..1d625ed76e 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -4470,7 +4470,7 @@ const APIEvent &WrappedOpenGL::GetEvent(uint32_t eventID) return e; } - return m_Events[0]; + return m_Events.back(); } const DrawcallDescription *WrappedOpenGL::GetDrawcall(uint32_t eventID) diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 252ac4d8ae..65c544f7c3 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -3116,7 +3116,7 @@ const APIEvent &WrappedVulkan::GetEvent(uint32_t eventID) return e; } - return m_Events[0]; + return m_Events.back(); } const DrawcallDescription *WrappedVulkan::GetDrawcall(uint32_t eventID) From f62f281415d81bee8728b7530335ce01e707d801 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 11 Oct 2017 11:11:52 +0100 Subject: [PATCH 71/91] Fix handling of D3D11_KEEP_{RTs/UAVs} in some edge cases --- renderdoc/driver/d3d11/d3d11_context.cpp | 48 +++++++++++-------- renderdoc/driver/d3d11/d3d11_context_wrap.cpp | 21 ++++++-- 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_context.cpp b/renderdoc/driver/d3d11/d3d11_context.cpp index c7baf02b49..9fdeb50f10 100644 --- a/renderdoc/driver/d3d11/d3d11_context.cpp +++ b/renderdoc/driver/d3d11/d3d11_context.cpp @@ -1969,38 +1969,48 @@ void WrappedID3D11DeviceContext::RecordOutputMergerStats(UINT NumRTVs, ID3D11Ren // #mivance is an elaborate redundancy here even useful? // const D3D11RenderState::outmerger* Current = &m_CurrentPipelineState->OM; - if(RTVs != NULL) + if(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) { - for(UINT index = 0; index < NumRTVs; index++) + if(RTVs != NULL) { - outputs.sets += (RTVs[index] != NULL); - outputs.nulls += (RTVs[index] == NULL); + for(UINT index = 0; index < NumRTVs; index++) + { + outputs.sets += (RTVs[index] != NULL); + outputs.nulls += (RTVs[index] == NULL); + } + } + else + { + outputs.nulls += NumRTVs; } - } - else if(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) - { - outputs.nulls += NumRTVs; } outputs.sets += (DSV != NULL); outputs.nulls += (DSV == NULL); - if(UAVs != NULL) + if(NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) { - for(UINT index = 0; index < NumUAVs; index++) + if(UAVs != NULL) { - outputs.sets += (UAVs[index] != NULL); - outputs.nulls += (UAVs[index] == NULL); + for(UINT index = 0; index < NumUAVs; index++) + { + outputs.sets += (UAVs[index] != NULL); + outputs.nulls += (UAVs[index] == NULL); + } + } + else + { + outputs.nulls += NumUAVs; } } - else - { - outputs.nulls += NumUAVs; - } - UINT NumSlots = NumRTVs + NumUAVs; - if(NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) - NumSlots = NumUAVs; + UINT NumSlots = 0; + + if(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) + NumSlots += NumRTVs; + if(NumRTVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) + NumSlots += NumUAVs; + RDCASSERT(NumSlots < outputs.bindslots.size()); outputs.bindslots[NumSlots] += 1; } diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index 206f557bad..91a700059e 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -3392,7 +3392,12 @@ void WrappedID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews( // D3D11 doesn't seem to complain about this case, but it messes our render state tracking so // ensure we don't blat over any RTs with 'empty' UAVs. if(NumUAVs == 0) - UAVStartSlot = RDCMAX(NumRTVs, UAVStartSlot); + { + if(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) + UAVStartSlot = RDCMAX(NumRTVs, UAVStartSlot); + else + UAVStartSlot = RDCMAX(m_CurrentPipelineState->OM.UAVStartSlot, UAVStartSlot); + } if(m_State == WRITING_CAPFRAME) { @@ -3408,10 +3413,13 @@ void WrappedID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews( ID3D11RenderTargetView *RTs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0}; ID3D11UnorderedAccessView *UAVs[D3D11_1_UAV_SLOT_COUNT] = {0}; - for(UINT i = 0; ppRenderTargetViews && i < NumRTVs; i++) + for(UINT i = 0; + ppRenderTargetViews && NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL && i < NumRTVs; + i++) RTs[i] = ppRenderTargetViews[i]; - for(UINT i = 0; ppUnorderedAccessViews && i < NumUAVs; i++) + for(UINT i = 0; + ppUnorderedAccessViews && NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS && i < NumUAVs; i++) UAVs[i] = ppUnorderedAccessViews[i]; if(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) @@ -3478,7 +3486,9 @@ void WrappedID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews( RDCMIN(NumUAVs, D3D11_1_UAV_SLOT_COUNT - StartSlot)); } - for(UINT i = 0; ppRenderTargetViews && i < NumRTVs; i++) + for(UINT i = 0; + ppRenderTargetViews && NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL && i < NumRTVs; + i++) { if(ppRenderTargetViews[i] && m_State >= WRITING) { @@ -3494,7 +3504,8 @@ void WrappedID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews( RTs[i] = UNWRAP(WrappedID3D11RenderTargetView1, ppRenderTargetViews[i]); } - for(UINT i = 0; ppUnorderedAccessViews && i < NumUAVs; i++) + for(UINT i = 0; + ppUnorderedAccessViews && NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS && i < NumUAVs; i++) { if(ppUnorderedAccessViews[i] && m_State >= WRITING) { From b6b7946d3ac276d164385b3c30fcf65e9ef9503a Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 29 Sep 2017 12:20:04 +0100 Subject: [PATCH 72/91] Don't pass internal GL shaders through reflection queries pointlessly * Intel's drivers in particular seem buggy when trying to reflect shaders, so there's no point in reflecting shaders that aren't from the capture as all we do is add the potential for crashes. --- renderdoc/driver/gl/gl_debug.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index acd61bb239..d54d0708e3 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -45,7 +45,7 @@ GLuint GLReplay::CreateCShaderProgram(const vector &csSources) MakeCurrentReplayContext(m_DebugCtx); - WrappedOpenGL &gl = *m_pDriver; + const GLHookSet &gl = m_pDriver->GetHookset(); GLuint cs = gl.glCreateShader(eGL_COMPUTE_SHADER); @@ -102,7 +102,7 @@ GLuint GLReplay::CreateShaderProgram(const vector &vsSources, MakeCurrentReplayContext(m_DebugCtx); - WrappedOpenGL &gl = *m_pDriver; + const GLHookSet &gl = m_pDriver->GetHookset(); GLuint vs = 0; GLuint fs = 0; From e275bae307a8488210ebb941ab0e7a7d7f06a851 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 9 Oct 2017 16:06:52 +0100 Subject: [PATCH 73/91] Add `brew update` to try and fix OSX intermittent errors on travis --- scripts/travis/osx_setup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/travis/osx_setup.sh b/scripts/travis/osx_setup.sh index 07cf25668b..b8a1278808 100644 --- a/scripts/travis/osx_setup.sh +++ b/scripts/travis/osx_setup.sh @@ -1,5 +1,6 @@ #!/bin/sh +brew update brew install qt5 brew link qt5 --force brew install python3 From 02fc28a36a76a582854e5f992d1a81b77f0ad2ea Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 11 Oct 2017 12:13:18 +0100 Subject: [PATCH 74/91] Try updating travis osx_image to fix intermittent qmake errors :(. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 29a55e8387..fccac6dc0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ matrix: env: ANDROID_BUILD=1 compiler: clang - os: osx - osx_image: xcode8.2 + osx_image: xcode9.1 env: APPLE_BUILD=1 compiler: clang From 9b56227e509d52bcf0eb1d6da5257534a7a050e0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 23 Oct 2017 13:38:53 +0100 Subject: [PATCH 75/91] Don't multiply mesh output size by num instances twice in GL --- renderdoc/driver/gl/gl_debug.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index d54d0708e3..d7631a5715 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -3628,7 +3628,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventID) if(!(drawcall->flags & DrawFlags::UseIBuffer)) { - uint32_t outputSize = drawcall->numIndices * drawcall->numInstances * stride; + uint32_t outputSize = drawcall->numIndices * stride; if(drawcall->flags & DrawFlags::Instanced) outputSize *= drawcall->numInstances; @@ -3741,7 +3741,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventID) gl.glNamedBufferDataEXT(indexSetBuffer, sizeof(uint32_t) * indices.size(), &indices[0], eGL_STATIC_DRAW); - uint32_t outputSize = (uint32_t)indices.size() * drawcall->numInstances * stride; + uint32_t outputSize = (uint32_t)indices.size() * stride; if(drawcall->flags & DrawFlags::Instanced) outputSize *= drawcall->numInstances; From 078efb8915185acb7c409f9bf16c54b75b354e86 Mon Sep 17 00:00:00 2001 From: michaelrgb Date: Wed, 11 Oct 2017 14:17:40 +0100 Subject: [PATCH 76/91] Resample thumbnails to fix JPEG shear distortion if(width % 4 != 0) --- renderdoc/driver/gl/gl_driver.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 1d625ed76e..265e7c514d 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -2975,15 +2975,17 @@ WrappedOpenGL::BackbufferImage *WrappedOpenGL::SaveBackbufferImage() m_Real.glPixelStorei(eGL_PACK_ALIGNMENT, prevPackAlignment); // scale down if necessary using simple point sampling - if(thwidth > maxSize) + uint32_t resample_width = RDCMIN(maxSize, thwidth); + resample_width &= ~3; // JPEG encoder gives shear distortion if width is not divisible by 4. + if(thwidth != resample_width) { float widthf = float(thwidth); float heightf = float(thheight); float aspect = widthf / heightf; - // clamp dimensions to a width of maxSize - thwidth = maxSize; + // clamp dimensions to a width of resample_width + thwidth = resample_width; thheight = uint32_t(float(thwidth) / aspect); byte *src = thpixels; From 6fd1a82454310fa04b986a081dbf9410c15dce85 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 23 Oct 2017 13:49:16 +0100 Subject: [PATCH 77/91] D3D11 context state is cleared before executing a command list. * Not doing this could taint the state and even cause invalid read-write conflicts to change bindings vs. what should happen, if a RT is left bound when it shouldn't, and then an SRV is bound as NULL because it would conflict. --- renderdoc/driver/d3d11/d3d11_context_wrap.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index 91a700059e..b773473955 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -4854,6 +4854,11 @@ bool WrappedID3D11DeviceContext::Serialise_ExecuteCommandList(ID3D11CommandList { SAFE_DELETE(m_DeferredSavedState); m_DeferredSavedState = new D3D11RenderState(this); + + // From the Docs: + // "Immediate context state is cleared before and after a command list is executed. A command + // list has no concept of inheritance." + ClearState(); } if(m_State == READING) From 400b9487e1f03572d214d8c19804bde81576a2e8 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 24 Oct 2017 23:01:03 +0100 Subject: [PATCH 78/91] Check for renderdoc.dll precisely when injecting, not just close match * This means we don't call into a random dll if it happens to contain the substring 'renderdoc.dll' somewhere. --- renderdoc/os/win32/win32_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderdoc/os/win32/win32_process.cpp b/renderdoc/os/win32/win32_process.cpp index b5370058c1..bd60c13637 100644 --- a/renderdoc/os/win32/win32_process.cpp +++ b/renderdoc/os/win32/win32_process.cpp @@ -307,7 +307,7 @@ uintptr_t FindRemoteDLL(DWORD pid, wstring libName) numModules++; - if(wcsstr(modnameLower, libName.c_str())) + if(wcsstr(modnameLower, libName.c_str()) == modnameLower) { ret = (uintptr_t)me32.modBaseAddr; } From d887e25b8d7ec76dddca7d42fa8ed890f4042737 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 24 Oct 2017 23:01:36 +0100 Subject: [PATCH 79/91] Ignore format truncation warning on utf8printf.cpp * We deliberately truncate in some tests, to check our printf behaves correctly. --- renderdoc/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/renderdoc/CMakeLists.txt b/renderdoc/CMakeLists.txt index 6f997ab41b..c3a90fd47f 100644 --- a/renderdoc/CMakeLists.txt +++ b/renderdoc/CMakeLists.txt @@ -205,6 +205,9 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR APPLE) if(CMAKE_COMPILER_IS_GNUCXX) set_property(SOURCE 3rdparty/jpeg-compressor/jpgd.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-unknown-warning -Wno-implicit-fallthrough") + + set_property(SOURCE serialise/utf8printf.cpp + APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-unknown-warning -Wno-format-truncation") endif() endif() From e23ddb98b34bef77ddcf7a7b3aa7427cc8fdf46b Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 24 Oct 2017 12:56:31 +0100 Subject: [PATCH 80/91] Clamp currentIndex from Qt which can come back as -1 in some cases * If this gets propagated far enough and used as an index it can cause crashes, so we clamp to 0 when we know the value should be non-negative. --- qrenderdoc/Windows/BufferViewer.cpp | 2 +- .../Windows/Dialogs/EnvironmentEditor.cpp | 2 +- qrenderdoc/Windows/Dialogs/SettingsDialog.cpp | 2 +- .../Windows/Dialogs/TextureSaveDialog.cpp | 20 +++++++++---------- qrenderdoc/Windows/TextureViewer.cpp | 14 ++++++------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index 6d84974b25..3310c16108 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -3191,7 +3191,7 @@ void BufferViewer::on_solidShading_currentIndexChanged(int index) m_Config.wireframeDraw = true; } - m_Config.solidShadeMode = (SolidShade)index; + m_Config.solidShadeMode = (SolidShade)qMax(0, index); m_ModelVSIn->setSecondaryColumn(m_ModelVSIn->secondaryColumn(), m_Config.solidShadeMode == SolidShade::Secondary, diff --git a/qrenderdoc/Windows/Dialogs/EnvironmentEditor.cpp b/qrenderdoc/Windows/Dialogs/EnvironmentEditor.cpp index 6dcf3a5cc4..7ae37105d1 100644 --- a/qrenderdoc/Windows/Dialogs/EnvironmentEditor.cpp +++ b/qrenderdoc/Windows/Dialogs/EnvironmentEditor.cpp @@ -149,7 +149,7 @@ void EnvironmentEditor::on_addUpdate_clicked() EnvironmentModification mod; mod.name = ui->name->text().toUtf8().data(); mod.value = ui->value->text().toUtf8().data(); - mod.sep = (EnvSep)ui->separator->currentIndex(); + mod.sep = (EnvSep)qMax(0, ui->separator->currentIndex()); if(ui->appendValue->isChecked()) mod.mod = EnvMod::Append; diff --git a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp index 817e89f703..7e41131b79 100644 --- a/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp +++ b/qrenderdoc/Windows/Dialogs/SettingsDialog.cpp @@ -294,7 +294,7 @@ void SettingsDialog::on_EventBrowser_TimeUnit_currentIndexChanged(int index) if(m_Init) return; - m_Ctx.Config().EventBrowser_TimeUnit = (TimeUnit)ui->EventBrowser_TimeUnit->currentIndex(); + m_Ctx.Config().EventBrowser_TimeUnit = (TimeUnit)qMax(0, ui->EventBrowser_TimeUnit->currentIndex()); if(m_Ctx.HasEventBrowser()) m_Ctx.GetEventBrowser()->UpdateDurationColumn(); diff --git a/qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp b/qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp index 716abb84d0..08daedde48 100644 --- a/qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp +++ b/qrenderdoc/Windows/Dialogs/TextureSaveDialog.cpp @@ -191,7 +191,7 @@ void TextureSaveDialog::SetFilenameFromFiletype() void TextureSaveDialog::on_fileFormat_currentIndexChanged(int index) { - saveData.destType = (FileType)ui->fileFormat->currentIndex(); + saveData.destType = (FileType)qMax(0, ui->fileFormat->currentIndex()); ui->jpegCompression->setEnabled(saveData.destType == FileType::JPG); @@ -273,7 +273,7 @@ void TextureSaveDialog::on_oneMip_toggled(bool checked) void TextureSaveDialog::on_mipSelect_currentIndexChanged(int index) { - saveData.mip = index; + saveData.mip = qMax(0, index); } void TextureSaveDialog::on_mapSampleArray_toggled(bool checked) @@ -344,7 +344,7 @@ void TextureSaveDialog::on_oneSample_toggled(bool checked) void TextureSaveDialog::on_sampleSelect_currentIndexChanged(int index) { - saveData.sample.sampleIndex = (uint32_t)index; + saveData.sample.sampleIndex = (uint32_t)qMax(0, index); } void TextureSaveDialog::on_exportAllSlices_toggled(bool checked) @@ -466,7 +466,7 @@ void TextureSaveDialog::on_cubeCruciform_toggled(bool checked) void TextureSaveDialog::on_sliceSelect_currentIndexChanged(int index) { - saveData.slice.sliceIndex = index; + saveData.slice.sliceIndex = qMax(0, index); } void TextureSaveDialog::on_gridWidth_valueChanged(double arg1) @@ -488,7 +488,7 @@ void TextureSaveDialog::on_alphaCol_clicked() void TextureSaveDialog::on_alphaMap_currentIndexChanged(int index) { - saveData.alpha = (AlphaMapping)index; + saveData.alpha = (AlphaMapping)qMax(0, index); ui->alphaCol->setEnabled(saveData.alpha == AlphaMapping::BlendToColor); } @@ -546,7 +546,7 @@ void TextureSaveDialog::on_filename_textEdited(const QString &arg1) void TextureSaveDialog::on_saveCancelButtons_accepted() { - saveData.alpha = (AlphaMapping)ui->alphaMap->currentIndex(); + saveData.alpha = (AlphaMapping)qMax(0, ui->alphaMap->currentIndex()); if(saveData.alpha == AlphaMapping::BlendToCheckerboard) { @@ -556,7 +556,7 @@ void TextureSaveDialog::on_saveCancelButtons_accepted() if(ui->exportAllMips->isChecked()) saveData.mip = -1; else - saveData.mip = (int)ui->mipSelect->currentIndex(); + saveData.mip = (int)qMax(0, ui->mipSelect->currentIndex()); if(ui->resolveSamples->isChecked()) { @@ -570,7 +570,7 @@ void TextureSaveDialog::on_saveCancelButtons_accepted() } else { - saveData.sample.sampleIndex = (uint)ui->sampleSelect->currentIndex(); + saveData.sample.sampleIndex = (uint)qMax(0, ui->sampleSelect->currentIndex()); saveData.sample.mapToArray = false; } @@ -578,7 +578,7 @@ void TextureSaveDialog::on_saveCancelButtons_accepted() { saveData.slice.cubeCruciform = saveData.slice.slicesAsGrid = false; saveData.slice.sliceGridWidth = 1; - saveData.slice.sliceIndex = (int)ui->sliceSelect->currentIndex(); + saveData.slice.sliceIndex = (int)qMax(0, ui->sliceSelect->currentIndex()); } else { @@ -597,7 +597,7 @@ void TextureSaveDialog::on_saveCancelButtons_accepted() } } - saveData.destType = (FileType)ui->fileFormat->currentIndex(); + saveData.destType = (FileType)qMax(0, ui->fileFormat->currentIndex()); saveData.jpegQuality = (int)ui->jpegCompression->value(); bool ok = false; diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 62d59160d5..d40cac9d7a 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -1058,14 +1058,14 @@ void TextureViewer::UI_OnTextureSelectionChanged(bool newdraw) m_TextureSettings[m_TexDisplay.texid].b = ui->channelBlue->isChecked(); m_TextureSettings[m_TexDisplay.texid].a = ui->channelAlpha->isChecked(); - m_TextureSettings[m_TexDisplay.texid].displayType = ui->channels->currentIndex(); + m_TextureSettings[m_TexDisplay.texid].displayType = qMax(0, ui->channels->currentIndex()); m_TextureSettings[m_TexDisplay.texid].customShader = ui->customShader->currentText(); m_TextureSettings[m_TexDisplay.texid].depth = ui->depthDisplay->isChecked(); m_TextureSettings[m_TexDisplay.texid].stencil = ui->stencilDisplay->isChecked(); - m_TextureSettings[m_TexDisplay.texid].mip = ui->mipLevel->currentIndex(); - m_TextureSettings[m_TexDisplay.texid].slice = ui->sliceFace->currentIndex(); + m_TextureSettings[m_TexDisplay.texid].mip = qMax(0, ui->mipLevel->currentIndex()); + m_TextureSettings[m_TexDisplay.texid].slice = qMax(0, ui->sliceFace->currentIndex()); m_TextureSettings[m_TexDisplay.texid].minrange = ui->rangeHistogram->blackPoint(); m_TextureSettings[m_TexDisplay.texid].maxrange = ui->rangeHistogram->whitePoint(); @@ -3167,13 +3167,13 @@ void TextureViewer::on_mipLevel_currentIndexChanged(int index) if(tex.mips > 1) { - m_TexDisplay.mip = (uint32_t)index; + m_TexDisplay.mip = (uint32_t)qMax(0, index); m_TexDisplay.sampleIdx = 0; } else { m_TexDisplay.mip = 0; - m_TexDisplay.sampleIdx = (uint32_t)index; + m_TexDisplay.sampleIdx = (uint32_t)qMax(0, index); if(m_TexDisplay.sampleIdx == tex.msSamp) m_TexDisplay.sampleIdx = ~0U; } @@ -3213,10 +3213,10 @@ void TextureViewer::on_sliceFace_currentIndexChanged(int index) return; TextureDescription &tex = *texptr; - m_TexDisplay.sliceFace = (uint32_t)index; + m_TexDisplay.sliceFace = (uint32_t)qMax(0, index); if(tex.depth > 1) - m_TexDisplay.sliceFace = (uint32_t)(index << (int)m_TexDisplay.mip); + m_TexDisplay.sliceFace = (uint32_t)(qMax(0, index) << (int)m_TexDisplay.mip); INVOKE_MEMFN(RT_UpdateVisualRange); From 6589e1fa9a6b2cb798ef508fe0643099661110ed Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 24 Oct 2017 11:36:33 +0100 Subject: [PATCH 81/91] Make sure to set refData to NULL whenever it's released --- renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index 5bebc719f9..5eac8d686a 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -501,7 +501,10 @@ void WrappedVulkan::vkFreeMemory(VkDevice device, VkDeviceMemory memory, { // there is an implicit unmap on free, so make sure to tidy up if(wrapped->record->memMapState && wrapped->record->memMapState->refData) + { Serialiser::FreeAlignedBuffer(wrapped->record->memMapState->refData); + wrapped->record->memMapState->refData = NULL; + } { SCOPED_LOCK(m_CoherentMapsLock); @@ -668,6 +671,7 @@ void WrappedVulkan::vkUnmapMemory(VkDevice device, VkDeviceMemory mem) } Serialiser::FreeAlignedBuffer(state.refData); + state.refData = NULL; if(state.mapCoherent) { From 4befa9dd223fd393eae53c0735927a937e7044f3 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 25 Oct 2017 00:12:09 +0100 Subject: [PATCH 82/91] If a resource is NULL, make sure we don't use an invalid descriptor * This can happen if the resource was not included in the capture, but there was a descriptor passed (i.e. not NULL desc which is handled separately) which specifies some parameters, but leaves the format as UNKNOWN. --- renderdoc/driver/d3d12/d3d12_manager.cpp | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/renderdoc/driver/d3d12/d3d12_manager.cpp b/renderdoc/driver/d3d12/d3d12_manager.cpp index e044f03cc1..76a2b2ea43 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.cpp +++ b/renderdoc/driver/d3d12/d3d12_manager.cpp @@ -164,6 +164,12 @@ void D3D12Descriptor::Create(D3D12_DESCRIPTOR_HEAP_TYPE heapType, WrappedID3D12D return; } } + else if(!nonsamp.resource) + { + // if we don't have a resource (which is possible if the descriptor is unused), use a + // default descriptor + desc = defaultSRV(); + } // it's possible to end up with invalid resource and descriptor combinations: // 1. descriptor is created for ResID_1234 BC1_TYPELESS and a view BC1_UNORM @@ -235,6 +241,12 @@ void D3D12Descriptor::Create(D3D12_DESCRIPTOR_HEAP_TYPE heapType, WrappedID3D12D return; } } + else if(!nonsamp.resource) + { + // if we don't have a resource (which is possible if the descriptor is unused), use a + // default descriptor + desc = defaultRTV(); + } // see comment above in SRV case for what this code is doing if(nonsamp.resource && desc) @@ -270,7 +282,15 @@ void D3D12Descriptor::Create(D3D12_DESCRIPTOR_HEAP_TYPE heapType, WrappedID3D12D { D3D12_DEPTH_STENCIL_VIEW_DESC *desc = &nonsamp.dsv; if(desc->ViewDimension == D3D12_DSV_DIMENSION_UNKNOWN) + { desc = nonsamp.resource ? NULL : defaultDSV(); + } + else if(!nonsamp.resource) + { + // if we don't have a resource (which is possible if the descriptor is unused), use a + // default descriptor + desc = defaultDSV(); + } // see comment above in SRV case for what this code is doing if(nonsamp.resource && desc) @@ -325,6 +345,12 @@ void D3D12Descriptor::Create(D3D12_DESCRIPTOR_HEAP_TYPE heapType, WrappedID3D12D return; } } + else if(!nonsamp.resource) + { + // if we don't have a resource (which is possible if the descriptor is unused), use a + // default descriptor + desc = defaultUAV(); + } // don't create a UAV with a counter resource but no main resource. This is fine because // if the main resource wasn't present in the capture, this UAV isn't present - the counter From 155571eecfa3db7a1e449a6cfaafa4ba024a19a0 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 25 Oct 2017 00:22:40 +0100 Subject: [PATCH 83/91] Ensure descriptors for multi-plane images are valid on replay --- renderdoc/driver/d3d12/d3d12_manager.cpp | 132 +++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/renderdoc/driver/d3d12/d3d12_manager.cpp b/renderdoc/driver/d3d12/d3d12_manager.cpp index 76a2b2ea43..1ff1e717f1 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.cpp +++ b/renderdoc/driver/d3d12/d3d12_manager.cpp @@ -217,6 +217,50 @@ void D3D12Descriptor::Create(D3D12_DESCRIPTOR_HEAP_TYPE heapType, WrappedID3D12D } } + D3D12_SHADER_RESOURCE_VIEW_DESC planeDesc; + // ensure that multi-plane formats have a valid plane slice specified. This shouldn't be + // possible as it should be the application's responsibility to be valid too, but we fix it up + // here anyway. + if(nonsamp.resource) + { + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {}; + formatInfo.Format = desc->Format; + dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)); + + // if this format is multi-plane + if(formatInfo.PlaneCount > 1) + { + planeDesc = *desc; + desc = &planeDesc; + + // detect formats that only read plane 1 and set the planeslice to 1 + if(desc->Format == DXGI_FORMAT_X24_TYPELESS_G8_UINT || + desc->Format == DXGI_FORMAT_X32_TYPELESS_G8X24_UINT) + { + switch(planeDesc.ViewDimension) + { + case D3D12_SRV_DIMENSION_TEXTURE2D: planeDesc.Texture2D.PlaneSlice = 1; break; + case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: + planeDesc.Texture2DArray.PlaneSlice = 1; + break; + default: break; + } + } + else + { + // otherwise set it to 0 + switch(planeDesc.ViewDimension) + { + case D3D12_SRV_DIMENSION_TEXTURE2D: planeDesc.Texture2D.PlaneSlice = 0; break; + case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: + planeDesc.Texture2DArray.PlaneSlice = 0; + break; + default: break; + } + } + } + } + dev->CreateShaderResourceView(nonsamp.resource, desc, handle); break; } @@ -275,6 +319,50 @@ void D3D12Descriptor::Create(D3D12_DESCRIPTOR_HEAP_TYPE heapType, WrappedID3D12D } } + D3D12_RENDER_TARGET_VIEW_DESC planeDesc; + // ensure that multi-plane formats have a valid plane slice specified. This shouldn't be + // possible as it should be the application's responsibility to be valid too, but we fix it up + // here anyway. + if(nonsamp.resource) + { + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {}; + formatInfo.Format = desc->Format; + dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)); + + // if this format is multi-plane + if(formatInfo.PlaneCount > 1) + { + planeDesc = *desc; + desc = &planeDesc; + + // detect formats that only read plane 1 and set the planeslice to 1 + if(desc->Format == DXGI_FORMAT_X24_TYPELESS_G8_UINT || + desc->Format == DXGI_FORMAT_X32_TYPELESS_G8X24_UINT) + { + switch(planeDesc.ViewDimension) + { + case D3D12_RTV_DIMENSION_TEXTURE2D: planeDesc.Texture2D.PlaneSlice = 1; break; + case D3D12_RTV_DIMENSION_TEXTURE2DARRAY: + planeDesc.Texture2DArray.PlaneSlice = 1; + break; + default: break; + } + } + else + { + // otherwise set it to 0 + switch(planeDesc.ViewDimension) + { + case D3D12_RTV_DIMENSION_TEXTURE2D: planeDesc.Texture2D.PlaneSlice = 0; break; + case D3D12_RTV_DIMENSION_TEXTURE2DARRAY: + planeDesc.Texture2DArray.PlaneSlice = 0; + break; + default: break; + } + } + } + } + dev->CreateRenderTargetView(nonsamp.resource, desc, handle); break; } @@ -389,6 +477,50 @@ void D3D12Descriptor::Create(D3D12_DESCRIPTOR_HEAP_TYPE heapType, WrappedID3D12D } } + D3D12_UNORDERED_ACCESS_VIEW_DESC planeDesc; + // ensure that multi-plane formats have a valid plane slice specified. This shouldn't be + // possible as it should be the application's responsibility to be valid too, but we fix it up + // here anyway. + if(nonsamp.resource) + { + D3D12_FEATURE_DATA_FORMAT_INFO formatInfo = {}; + formatInfo.Format = desc->Format; + dev->CheckFeatureSupport(D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof(formatInfo)); + + // if this format is multi-plane + if(formatInfo.PlaneCount > 1) + { + planeDesc = *desc; + desc = &planeDesc; + + // detect formats that only read plane 1 and set the planeslice to 1 + if(desc->Format == DXGI_FORMAT_X24_TYPELESS_G8_UINT || + desc->Format == DXGI_FORMAT_X32_TYPELESS_G8X24_UINT) + { + switch(planeDesc.ViewDimension) + { + case D3D12_UAV_DIMENSION_TEXTURE2D: planeDesc.Texture2D.PlaneSlice = 1; break; + case D3D12_UAV_DIMENSION_TEXTURE2DARRAY: + planeDesc.Texture2DArray.PlaneSlice = 1; + break; + default: break; + } + } + else + { + // otherwise set it to 0 + switch(planeDesc.ViewDimension) + { + case D3D12_UAV_DIMENSION_TEXTURE2D: planeDesc.Texture2D.PlaneSlice = 0; break; + case D3D12_UAV_DIMENSION_TEXTURE2DARRAY: + planeDesc.Texture2DArray.PlaneSlice = 0; + break; + default: break; + } + } + } + } + dev->CreateUnorderedAccessView(nonsamp.resource, counter, desc, handle); break; } From c016855dcecde513227d10324f95078acf6c3a76 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sat, 28 Oct 2017 14:11:58 +0100 Subject: [PATCH 84/91] Fix copy-paste error checking wrong count for validity. Refs #789 --- renderdoc/driver/d3d11/d3d11_context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderdoc/driver/d3d11/d3d11_context.cpp b/renderdoc/driver/d3d11/d3d11_context.cpp index 9fdeb50f10..d1438a7def 100644 --- a/renderdoc/driver/d3d11/d3d11_context.cpp +++ b/renderdoc/driver/d3d11/d3d11_context.cpp @@ -2008,7 +2008,7 @@ void WrappedID3D11DeviceContext::RecordOutputMergerStats(UINT NumRTVs, ID3D11Ren if(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) NumSlots += NumRTVs; - if(NumRTVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) + if(NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) NumSlots += NumUAVs; RDCASSERT(NumSlots < outputs.bindslots.size()); From 93efdf46e1f1c7a05194414e870f84082e4435cf Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 3 Nov 2017 10:13:08 +0000 Subject: [PATCH 85/91] Fix remapping multiple capture vulkan phys. devs to 1 replay phys. dev --- .../driver/vulkan/wrappers/vk_device_funcs.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index d6536a854b..2458f1c6af 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -672,7 +672,11 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(Serialiser *localSerial pd = m_ReplayPhysicalDevices[bestIdx]; - GetResourceManager()->AddLiveResource(physId, pd); + if(!m_ReplayPhysicalDevicesUsed[bestIdx]) + GetResourceManager()->AddLiveResource(physId, pd); + else + GetResourceManager()->ReplaceResource(physId, + GetResourceManager()->GetOriginalID(GetResID(pd))); if(physIndex >= m_PhysicalDevices.size()) m_PhysicalDevices.resize(physIndex + 1); @@ -682,16 +686,22 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(Serialiser *localSerial { // error if we're remapping multiple physical devices to the same best match RDCERR( - "Mappnig multiple capture-time physical devices to a single replay-time physical device." + "Mapping multiple capture-time physical devices to a single replay-time physical device." "This means the HW has changed between capture and replay and may cause bugs."); } - else + else if(m_MemIdxMaps[bestIdx] == NULL) { // the first physical device 'wins' for the memory index map uint32_t *storedMap = new uint32_t[32]; memcpy(storedMap, memIdxMap, sizeof(memIdxMap)); - m_MemIdxMaps[physIndex] = storedMap; + + for(uint32_t i = 0; i < 32; i++) + storedMap[i] = i; + + m_MemIdxMaps[bestIdx] = storedMap; } + + m_ReplayPhysicalDevicesUsed[bestIdx] = true; } return true; From 423938801be707713d477fee10a29847cb1d1116 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 3 Nov 2017 15:31:43 +0000 Subject: [PATCH 86/91] Disable buggy and user-hostile NV optimus layer --- renderdoc/driver/vulkan/vk_replay.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 2e31e82d15..d707cd262d 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -5302,6 +5302,12 @@ ReplayStatus Vulkan_CreateReplayDevice(const char *logfile, IReplayDriver **driv // disable the layer env var, just in case the user left it set from a previous capture run Process::RegisterEnvironmentModification( EnvironmentModification(EnvMod::Set, EnvSep::NoSep, "ENABLE_VULKAN_RENDERDOC_CAPTURE", "0")); + + // disable buggy and user-hostile NV optimus layer, which can completely delete physical devices + // (not just rearrange them) and cause problems between capture and replay. + Process::RegisterEnvironmentModification( + EnvironmentModification(EnvMod::Set, EnvSep::NoSep, "DISABLE_LAYER_NV_OPTIMUS_1", "")); + Process::ApplyEnvironmentModification(); void *module = Process::LoadModule(VulkanLibraryName); From 522dba19813915e406457e03afdf30ecfc07d6fc Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 3 Nov 2017 14:50:12 +0000 Subject: [PATCH 87/91] Handle vulkan base pipelines properly, creating record dependencies --- .../vulkan/wrappers/vk_shader_funcs.cpp | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp index e3aa7e8079..50075703ae 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp @@ -438,6 +438,20 @@ VkResult WrappedVulkan::vkCreateGraphicsPipelines(VkDevice device, VkPipelineCac VkResourceRecord *record = GetResourceManager()->AddResourceRecord(pPipelines[i]); record->AddChunk(chunk); + if(pCreateInfos[i].basePipelineHandle != VK_NULL_HANDLE) + { + VkResourceRecord *baserecord = GetRecord(pCreateInfos[i].basePipelineHandle); + record->AddParent(baserecord); + + RDCLOG("Creating pipeline %llu base is %llu", record->GetResourceID(), + baserecord->GetResourceID()); + } + else if(pCreateInfos[i].basePipelineIndex != -1 && pCreateInfos[i].basePipelineIndex < (int)i) + { + VkResourceRecord *baserecord = GetRecord(pPipelines[pCreateInfos[i].basePipelineIndex]); + record->AddParent(baserecord); + } + if(pipelineCache != VK_NULL_HANDLE) { VkResourceRecord *cacherecord = GetRecord(pipelineCache); @@ -553,9 +567,21 @@ VkResult WrappedVulkan::vkCreateComputePipelines(VkDevice device, VkPipelineCach { CACHE_THREAD_SERIALISER(); + VkComputePipelineCreateInfo modifiedCreateInfo; + const VkComputePipelineCreateInfo *createInfo = &pCreateInfos[i]; + + // since we serialise one by one, we need to fixup basePipelineIndex + if(createInfo->basePipelineIndex != -1 && createInfo->basePipelineIndex < (int)i) + { + modifiedCreateInfo = *createInfo; + modifiedCreateInfo.basePipelineHandle = pPipelines[modifiedCreateInfo.basePipelineIndex]; + modifiedCreateInfo.basePipelineIndex = -1; + createInfo = &modifiedCreateInfo; + } + SCOPED_SERIALISE_CONTEXT(CREATE_COMPUTE_PIPE); Serialise_vkCreateComputePipelines(localSerialiser, device, pipelineCache, 1, - &pCreateInfos[i], NULL, &pPipelines[i]); + createInfo, NULL, &pPipelines[i]); chunk = scope.Get(); } @@ -569,6 +595,17 @@ VkResult WrappedVulkan::vkCreateComputePipelines(VkDevice device, VkPipelineCach record->AddParent(cacherecord); } + if(pCreateInfos[i].basePipelineHandle != VK_NULL_HANDLE) + { + VkResourceRecord *baserecord = GetRecord(pCreateInfos[i].basePipelineHandle); + record->AddParent(baserecord); + } + else if(pCreateInfos[i].basePipelineIndex != -1 && pCreateInfos[i].basePipelineIndex < (int)i) + { + VkResourceRecord *baserecord = GetRecord(pPipelines[pCreateInfos[i].basePipelineIndex]); + record->AddParent(baserecord); + } + VkResourceRecord *layoutrecord = GetRecord(pCreateInfos[i].layout); record->AddParent(layoutrecord); From fecd7dd31881fb0401edea0f59f78bf95c9b6ecc Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 3 Nov 2017 20:02:48 +0000 Subject: [PATCH 88/91] Fix formatting from bad git cherry-pick * Apparently git cherry-pick doesn't apply commit hooks :(. --- renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp index 50075703ae..76a34b53c9 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp @@ -580,8 +580,8 @@ VkResult WrappedVulkan::vkCreateComputePipelines(VkDevice device, VkPipelineCach } SCOPED_SERIALISE_CONTEXT(CREATE_COMPUTE_PIPE); - Serialise_vkCreateComputePipelines(localSerialiser, device, pipelineCache, 1, - createInfo, NULL, &pPipelines[i]); + Serialise_vkCreateComputePipelines(localSerialiser, device, pipelineCache, 1, createInfo, + NULL, &pPipelines[i]); chunk = scope.Get(); } From d4225b22626edab0b4eba785dfecd0769a9dddd8 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 9 Nov 2017 12:03:31 +0000 Subject: [PATCH 89/91] Add some hefty padding to reported image required size on AMD. Refs #795 * AMD reports image required sizes with some variation even for the same creation parameters. This can mean the same image is reported with less required size during capture compared to replay, meaning memory binds won't work. * To get around this, we pad up the requirements to alignment * 4 and fudge to try and encompass any possible variation. --- .../driver/vulkan/wrappers/vk_get_funcs.cpp | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp index 3ca68405c4..cb4ec7ed82 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp @@ -160,6 +160,30 @@ void WrappedVulkan::vkGetImageMemoryRequirements(VkDevice device, VkImage image, for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) if(memIdxMap[i] < 32U && (bits & (1U << memIdxMap[i]))) pMemoryRequirements->memoryTypeBits |= (1U << i); + + // AMD can have some variability in the returned size, so we need to pad the reported size to + // allow for this. The variability isn't quite clear, but for now we assume aligning size to + // alignment * 4 should be sufficient (adding on a fixed padding won't help the problem as it + // won't remove the variability, nor will adding then aligning for the same reason). + if(GetDriverVersion().IsAMD()) + { + VkMemoryRequirements &memreq = *pMemoryRequirements; + + VkDeviceSize oldsize = memreq.size; + memreq.size = AlignUp(memreq.size, memreq.alignment * 4); + + // if it's already 'super aligned', then bump it up a little. We assume that this case + // represents the low-end of the variation range, and other variations will be a little higher. + // The other alternative is the variations are all lower and this one happened to be super + // aligned, which I think (arbitrarily really) is less likely. + if(oldsize == memreq.size) + memreq.size = AlignUp(memreq.size + 1, memreq.alignment * 4); + + RDCDEBUG( + "Padded image memory requirements from %llu to %llu (base alignment %llu) (%f%% increase)", + oldsize, memreq.size, memreq.alignment, + (100.0 * double(memreq.size - oldsize)) / double(oldsize)); + } } void WrappedVulkan::vkGetImageSparseMemoryRequirements( @@ -218,6 +242,30 @@ void WrappedVulkan::vkGetImageMemoryRequirements2KHR(VkDevice device, for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) if(memIdxMap[i] < 32U && (bits & (1U << memIdxMap[i]))) pMemoryRequirements->memoryRequirements.memoryTypeBits |= (1U << i); + + // AMD can have some variability in the returned size, so we need to pad the reported size to + // allow for this. The variability isn't quite clear, but for now we assume aligning size to + // alignment * 4 should be sufficient (adding on a fixed padding won't help the problem as it + // won't remove the variability, nor will adding then aligning for the same reason). + if(GetDriverVersion().IsAMD()) + { + VkMemoryRequirements &memreq = pMemoryRequirements->memoryRequirements; + + VkDeviceSize oldsize = memreq.size; + memreq.size = AlignUp(memreq.size, memreq.alignment * 4); + + // if it's already 'super aligned', then bump it up a little. We assume that this case + // represents the low-end of the variation range, and other variations will be a little higher. + // The other alternative is the variations are all lower and this one happened to be super + // aligned, which I think (arbitrarily really) is less likely. + if(oldsize == memreq.size) + memreq.size = AlignUp(memreq.size + 1, memreq.alignment * 4); + + RDCDEBUG( + "Padded image memory requirements from %llu to %llu (base alignment %llu) (%f%% increase)", + oldsize, memreq.size, memreq.alignment, + (100.0 * double(memreq.size - oldsize)) / double(oldsize)); + } } void WrappedVulkan::vkGetImageSparseMemoryRequirements2KHR( From 0e0921271b047561b60b0371a894aa7a5e60ecf7 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 8 Nov 2017 17:03:16 +0000 Subject: [PATCH 90/91] Fix emulation of glMapNamedBuffer - pass correct map access bits --- renderdoc/driver/gl/wrappers/gl_emulated.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/renderdoc/driver/gl/wrappers/gl_emulated.cpp b/renderdoc/driver/gl/wrappers/gl_emulated.cpp index c01b34677d..36a9ce4104 100644 --- a/renderdoc/driver/gl/wrappers/gl_emulated.cpp +++ b/renderdoc/driver/gl/wrappers/gl_emulated.cpp @@ -379,7 +379,15 @@ void *APIENTRY _glMapNamedBufferEXT(GLuint buffer, GLenum access) PushPopBuffer(eGL_COPY_READ_BUFFER, buffer); GLint size; hookset->glGetBufferParameteriv(eGL_COPY_READ_BUFFER, eGL_BUFFER_SIZE, &size); - return hookset->glMapBufferRange(eGL_COPY_READ_BUFFER, 0, size, eGL_MAP_READ_BIT); + + GLbitfield accessBits = eGL_MAP_READ_BIT | eGL_MAP_WRITE_BIT; + + if(access == eGL_READ_ONLY) + accessBits = eGL_MAP_READ_BIT; + else if(access == eGL_WRITE_ONLY) + accessBits = eGL_MAP_WRITE_BIT; + + return hookset->glMapBufferRange(eGL_COPY_READ_BUFFER, 0, size, accessBits); } void *APIENTRY _glMapNamedBufferRangeEXT(GLuint buffer, GLintptr offset, GLsizeiptr length, From 1d0d49f694335cf0a128f7a141c27417c9654714 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 10 Nov 2017 13:01:40 +0000 Subject: [PATCH 91/91] Clear PostVS cache when a resource is replaced. Refs #729 * For now, resource replacement implicitly means shader edits, but other replacements could also affect the results of PostVS (e.g. buffer or state changes). Trying to capture all this state in the cache key is not very useful. * The PostVS cache will be re-filled immediately after, as any replacement does a force-refresh of the current event. --- renderdoc/driver/d3d11/d3d11_debug.cpp | 24 ++++++++++++++---------- renderdoc/driver/d3d11/d3d11_debug.h | 1 + renderdoc/driver/d3d11/d3d11_replay.cpp | 1 + renderdoc/driver/d3d12/d3d12_debug.cpp | 21 +++++++++++++-------- renderdoc/driver/d3d12/d3d12_debug.h | 1 + renderdoc/driver/d3d12/d3d12_replay.cpp | 2 ++ renderdoc/driver/gl/gl_debug.cpp | 25 ++++++++++++++++--------- renderdoc/driver/gl/gl_replay.cpp | 1 + renderdoc/driver/gl/gl_replay.h | 2 ++ renderdoc/driver/vulkan/vk_debug.cpp | 25 ++++++++++++++++--------- renderdoc/driver/vulkan/vk_debug.h | 2 ++ renderdoc/driver/vulkan/vk_replay.cpp | 1 + 12 files changed, 70 insertions(+), 36 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index 9dfb1a0104..e37e94f5c6 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -213,16 +213,7 @@ D3D11DebugManager::~D3D11DebugManager() elem.Release(); m_ShaderItemCache.pop_back(); } - - for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) - { - SAFE_RELEASE(it->second.vsout.buf); - SAFE_RELEASE(it->second.vsout.idxBuf); - SAFE_RELEASE(it->second.gsout.buf); - SAFE_RELEASE(it->second.gsout.idxBuf); - } - - m_PostVSData.clear(); + ClearPostVSCache(); SAFE_RELEASE(m_pImmediateContext); m_WrappedDevice->InternalRelease(); @@ -3809,6 +3800,19 @@ void D3D11DebugManager::RenderCheckerboard(Vec3f light, Vec3f dark) } } +void D3D11DebugManager::ClearPostVSCache() +{ + for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) + { + SAFE_RELEASE(it->second.vsout.buf); + SAFE_RELEASE(it->second.vsout.idxBuf); + SAFE_RELEASE(it->second.gsout.buf); + SAFE_RELEASE(it->second.gsout.idxBuf); + } + + m_PostVSData.clear(); +} + MeshFormat D3D11DebugManager::GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage) { D3D11PostVSData postvs; diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index 084ed3f3ba..9b9808737d 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -130,6 +130,7 @@ class D3D11DebugManager int GetHeight() { return m_height; } void InitPostVSBuffers(uint32_t eventID); MeshFormat GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage); + void ClearPostVSCache(); uint32_t GetStructCount(ID3D11UnorderedAccessView *uav); void GetBufferData(ResourceId buff, uint64_t offset, uint64_t length, vector &retData); diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 72541e66d9..d3cae9c3a3 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -1498,6 +1498,7 @@ byte *D3D11Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mi void D3D11Replay::ReplaceResource(ResourceId from, ResourceId to) { m_pDevice->GetResourceManager()->ReplaceResource(from, to); + m_pDevice->GetDebugManager()->ClearPostVSCache(); } void D3D11Replay::RemoveReplacement(ResourceId id) diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index bf6a4f8d23..a50ead5317 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -1279,14 +1279,6 @@ D3D12DebugManager::~D3D12DebugManager() for(size_t p = 0; p < MeshDisplayPipelines::ePipe_Count; p++) SAFE_RELEASE(it->second.pipes[p]); - for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) - { - SAFE_RELEASE(it->second.vsout.buf); - SAFE_RELEASE(it->second.vsout.idxBuf); - SAFE_RELEASE(it->second.gsout.buf); - SAFE_RELEASE(it->second.gsout.idxBuf); - } - SAFE_RELEASE(m_pFactory); SAFE_RELEASE(dsvHeap); @@ -3802,6 +3794,19 @@ byte *D3D12DebugManager::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint3 return ret; } +void D3D12DebugManager::ClearPostVSCache() +{ + for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) + { + SAFE_RELEASE(it->second.vsout.buf); + SAFE_RELEASE(it->second.vsout.idxBuf); + SAFE_RELEASE(it->second.gsout.buf); + SAFE_RELEASE(it->second.gsout.idxBuf); + } + + m_PostVSData.clear(); +} + void D3D12DebugManager::InitPostVSBuffers(uint32_t eventID) { // go through any aliasing diff --git a/renderdoc/driver/d3d12/d3d12_debug.h b/renderdoc/driver/d3d12/d3d12_debug.h index 8c59660fe6..f0512a0a40 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.h +++ b/renderdoc/driver/d3d12/d3d12_debug.h @@ -100,6 +100,7 @@ class D3D12DebugManager // indicates that EID alias is the same as eventID void AliasPostVSBuffers(uint32_t eventID, uint32_t alias) { m_PostVSAlias[alias] = eventID; } MeshFormat GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage); + void ClearPostVSCache(); void GetBufferData(ResourceId buff, uint64_t offset, uint64_t length, vector &retData); void GetBufferData(ID3D12Resource *buff, uint64_t offset, uint64_t length, vector &retData); diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 2e4044e5b8..5756e81a18 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -1645,6 +1645,8 @@ void D3D12Replay::ReplaceResource(ResourceId from, ResourceId to) rm->ReplaceResource(from, to); } + + m_pDevice->GetDebugManager()->ClearPostVSCache(); } void D3D12Replay::RemoveReplacement(ResourceId id) diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index d7631a5715..4914cec8b5 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -734,15 +734,7 @@ void GLReplay::DeleteDebugData() MakeCurrentReplayContext(m_DebugCtx); - for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) - { - gl.glDeleteBuffers(1, &it->second.vsout.buf); - gl.glDeleteBuffers(1, &it->second.vsout.idxBuf); - gl.glDeleteBuffers(1, &it->second.gsout.buf); - gl.glDeleteBuffers(1, &it->second.gsout.idxBuf); - } - - m_PostVSData.clear(); + ClearPostVSCache(); gl.glDeleteFramebuffers(1, &DebugData.overlayFBO); gl.glDeleteTextures(1, &DebugData.overlayTex); @@ -3312,6 +3304,21 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeHint, DebugOve return m_pDriver->GetResourceManager()->GetID(TextureRes(ctx, DebugData.overlayTex)); } +void GLReplay::ClearPostVSCache() +{ + WrappedOpenGL &gl = *m_pDriver; + + for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) + { + gl.glDeleteBuffers(1, &it->second.vsout.buf); + gl.glDeleteBuffers(1, &it->second.vsout.idxBuf); + gl.glDeleteBuffers(1, &it->second.gsout.buf); + gl.glDeleteBuffers(1, &it->second.gsout.idxBuf); + } + + m_PostVSData.clear(); +} + void GLReplay::InitPostVSBuffers(uint32_t eventID) { if(m_PostVSData.find(eventID) != m_PostVSData.end()) diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 88a31111f1..d07f25796f 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -2948,6 +2948,7 @@ void GLReplay::ReplaceResource(ResourceId from, ResourceId to) { MakeCurrentReplayContext(&m_ReplayCtx); m_pDriver->ReplaceResource(from, to); + ClearPostVSCache(); } void GLReplay::RemoveReplacement(ResourceId id) diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 78ea2a4e2d..70eebbc953 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -370,6 +370,8 @@ class GLReplay : public IReplayDriver // eventID -> data map m_PostVSData; + void ClearPostVSCache(); + // cache the previous data returned ResourceId m_GetTexturePrevID; byte *m_GetTexturePrevData[16]; diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 3f87339be6..f38c1cb99e 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -2507,15 +2507,7 @@ VulkanDebugManager::~VulkanDebugManager() ShaderCacheCallbacks.Destroy(it->second); } - for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) - { - m_pDriver->vkDestroyBuffer(dev, it->second.vsout.buf, NULL); - m_pDriver->vkDestroyBuffer(dev, it->second.vsout.idxBuf, NULL); - m_pDriver->vkFreeMemory(dev, it->second.vsout.bufmem, NULL); - m_pDriver->vkFreeMemory(dev, it->second.vsout.idxBufMem, NULL); - } - - m_PostVSData.clear(); + ClearPostVSCache(); // since we don't have properly registered resources, releasing our descriptor // pool here won't remove the descriptor sets, so we need to free our own @@ -7917,6 +7909,21 @@ static void AddOutputDumping(const ShaderReflection &refl, const SPIRVPatchData spirv[3] = idBound; } +void VulkanDebugManager::ClearPostVSCache() +{ + VkDevice dev = m_Device; + + for(auto it = m_PostVSData.begin(); it != m_PostVSData.end(); ++it) + { + m_pDriver->vkDestroyBuffer(dev, it->second.vsout.buf, NULL); + m_pDriver->vkDestroyBuffer(dev, it->second.vsout.idxBuf, NULL); + m_pDriver->vkFreeMemory(dev, it->second.vsout.bufmem, NULL); + m_pDriver->vkFreeMemory(dev, it->second.vsout.idxBufMem, NULL); + } + + m_PostVSData.clear(); +} + void VulkanDebugManager::InitPostVSBuffers(uint32_t eventID) { // go through any aliasing diff --git a/renderdoc/driver/vulkan/vk_debug.h b/renderdoc/driver/vulkan/vk_debug.h index ff1a8d6c0a..c376246fcd 100644 --- a/renderdoc/driver/vulkan/vk_debug.h +++ b/renderdoc/driver/vulkan/vk_debug.h @@ -120,6 +120,8 @@ class VulkanDebugManager // indicates that EID alias is the same as eventID void AliasPostVSBuffers(uint32_t eventID, uint32_t alias) { m_PostVSAlias[alias] = eventID; } MeshFormat GetPostVSBuffers(uint32_t eventID, uint32_t instID, MeshDataStage stage); + void ClearPostVSCache(); + void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &ret); uint32_t PickVertex(uint32_t eventID, const MeshDisplay &cfg, uint32_t x, uint32_t y, uint32_t w, diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index d707cd262d..8db0ae5194 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -5217,6 +5217,7 @@ void VulkanReplay::BuildTargetShader(string source, string entry, const uint32_t void VulkanReplay::ReplaceResource(ResourceId from, ResourceId to) { GetDebugManager()->ReplaceResource(from, to); + GetDebugManager()->ClearPostVSCache(); } void VulkanReplay::RemoveReplacement(ResourceId id)