diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 44dbd3705..53bb77260 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -784,7 +784,7 @@ bool ProxySerialiser::Tick() RemoveReplacement(ResourceId()); break; case eCommand_RenderOverlay: - RenderOverlay(ResourceId(), eTexOverlay_None, 0, 0); + RenderOverlay(ResourceId(), eTexOverlay_None, 0, 0, vector()); break; case eCommand_PixelHistory: PixelHistory(0, vector(), ResourceId(), 0, 0); @@ -1270,18 +1270,21 @@ PostVSMeshData ProxySerialiser::GetPostVSBuffers(uint32_t frameID, uint32_t even return ret; } -ResourceId ProxySerialiser::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID) +ResourceId ProxySerialiser::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents) { ResourceId ret; - + + vector events = passEvents; + m_ToReplaySerialiser->Serialise("", texid); m_ToReplaySerialiser->Serialise("", overlay); m_ToReplaySerialiser->Serialise("", frameID); m_ToReplaySerialiser->Serialise("", eventID); + m_ToReplaySerialiser->Serialise("", events); if(m_ReplayHost) { - ret = m_Remote->RenderOverlay(texid, overlay, frameID, eventID); + ret = m_Remote->RenderOverlay(texid, overlay, frameID, eventID, events); } else { diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index 884a43140..c4ae87dd3 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -224,7 +224,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver } } - void RenderMesh(int frameID, vector eventID, MeshDisplay cfg) + void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) { if(m_Proxy) m_Proxy->RenderCheckerboard(Vec3f(0.7f, 0.3f, 0.3f), Vec3f(0.3f, 0.3f, 0.7f)); @@ -298,7 +298,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver void InitPostVSBuffers(uint32_t frameID, uint32_t eventID); PostVSMeshData GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage); - ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID); + ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents); ShaderReflection *GetShader(ResourceId id); diff --git a/renderdoc/data/hlsl/debugdisplay.hlsl b/renderdoc/data/hlsl/debugdisplay.hlsl index 0aa8eb2bb..fd3646207 100644 --- a/renderdoc/data/hlsl/debugdisplay.hlsl +++ b/renderdoc/data/hlsl/debugdisplay.hlsl @@ -332,3 +332,59 @@ float4 RENDERDOC_CheckerboardPS(float4 IN : SV_Position) : SV_Target0 return float4(sqrt(Channels.rgb), 1); } + +//////////////////////////////////////////////////////////////////////////////////////////// +// Below shaders courtesy of Stephen Hill (@self_shadow) +// +// http://blog.selfshadow.com/2012/11/12/counting-quads/ +// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx +//////////////////////////////////////////////////////////////////////////////////////////// + +RWTexture2DArray overdrawUAV : register(u0); +Texture2DArray overdrawSRV : register(t0); +cbuffer overdrawRampCBuf : register(b0) +{ + const float4 overdrawRampColours[21]; +}; + +[earlydepthstencil] +void RENDERDOC_QuadOverdrawPS(float4 vpos : SV_Position, uint c0 : SV_Coverage) +{ + // Obtain coverage for all pixels in the quad, via 'message passing'*. + // (* For more details, see: + // "Shader Amortization using Pixel Quad Message Passing", Eric Penner, GPU Pro 2.) + uint2 p = uint2(vpos.xy) & 1; + int2 sign = p ? -1 : 1; + uint c1 = c0 + sign.x*ddx_fine(c0); + uint c2 = c0 + sign.y*ddy_fine(c0); + uint c3 = c2 + sign.x*ddx_fine(c2); + + // Count the live pixels, minus 1 (zero indexing) + uint pixelCount = c0 + c1 + c2 + c3 - 1; + + uint3 quad = uint3(vpos.xy*0.5, pixelCount); + InterlockedAdd(overdrawUAV[quad], 1); +} + +float4 ToColour(uint v) +{ + return overdrawRampColours[min(v, 20)]; +} + +float4 RENDERDOC_QOResolvePS(float4 vpos : SV_POSITION) : SV_Target0 +{ + uint2 quad = vpos.xy*0.5; + + uint overdraw = 0; + for(int i = 0; i < 4; i++) + overdraw += overdrawSRV[uint3(quad, i)]/(i + 1); + + return ToColour(overdraw); +} + +//////////////////////////////////////////////////////////////////////////////////////////// +// Above shaders courtesy of Stephen Hill (@self_shadow) +// +// http://blog.selfshadow.com/2012/11/12/counting-quads/ +// https://github.com/selfshadow/demos/blob/master/QuadShading/QuadShading.fx +//////////////////////////////////////////////////////////////////////////////////////////// diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index 43c44a782..da1e07da6 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -2171,7 +2171,7 @@ void D3D11DebugManager::CreateCustomShaderTex(uint32_t w, uint32_t h) } } -ResourceId D3D11DebugManager::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID) +ResourceId D3D11DebugManager::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents) { TextureShaderDetails details = GetShaderDetails(texid, false); @@ -2533,6 +2533,171 @@ ResourceId D3D11DebugManager::RenderOverlay(ResourceId texid, TextureDisplayOver SAFE_RELEASE(os); SAFE_RELEASE(rs); } + else if(overlay == eTexOverlay_QuadOverdrawPass || overlay == eTexOverlay_QuadOverdrawDraw) + { + SCOPED_TIMER("Quad Overdraw"); + + vector events = passEvents; + + if(overlay == eTexOverlay_QuadOverdrawDraw) + { + events.clear(); + events.push_back(eventID); + } + + if(!events.empty()) + { + if(overlay == eTexOverlay_QuadOverdrawPass) + m_WrappedDevice->ReplayLog(frameID, 0, events[0], eReplay_WithoutDraw); + + D3D11RenderState *state = m_WrappedContext->GetCurrentPipelineState(); + + uint32_t width = 1920>>1; + uint32_t height = 1080>>1; + + { + ID3D11Resource *res = NULL; + if(state->OM.RenderTargets[0]) + { + state->OM.RenderTargets[0]->GetResource(&res); + } + else if(state->OM.DepthView) + { + state->OM.DepthView->GetResource(&res); + } + else + { + RDCERR("Couldn't get size of existing targets"); + return m_OverlayResourceId; + } + + D3D11_RESOURCE_DIMENSION dim; + res->GetType(&dim); + + if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE1D) + { + D3D11_TEXTURE1D_DESC desc; + ((ID3D11Texture1D *)res)->GetDesc(&desc); + + width = desc.Width>>1; + height = 1; + } + else if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) + { + D3D11_TEXTURE2D_DESC desc; + ((ID3D11Texture2D *)res)->GetDesc(&desc); + + width = desc.Width>>1; + height = desc.Height>>1; + } + else + { + RDCERR("Trying to show quad overdraw on invalid view"); + return m_OverlayResourceId; + } + + SAFE_RELEASE(res); + } + + D3D11_TEXTURE2D_DESC uavTexDesc = { + width, height, 1U, 4U, + DXGI_FORMAT_R32_UINT, + { 1, 0 }, + D3D11_USAGE_DEFAULT, + D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE, + 0, + 0, + }; + + ID3D11Texture2D *overdrawTex = NULL; + ID3D11ShaderResourceView *overdrawSRV = NULL; + ID3D11UnorderedAccessView *overdrawUAV = NULL; + + m_WrappedDevice->CreateTexture2D(&uavTexDesc, NULL, &overdrawTex); + m_WrappedDevice->CreateShaderResourceView(overdrawTex, NULL, &overdrawSRV); + m_WrappedDevice->CreateUnorderedAccessView(overdrawTex, NULL, &overdrawUAV); + + UINT val = 0; + m_WrappedContext->ClearUnorderedAccessViewUint(overdrawUAV, &val); + + for(size_t i=0; i < events.size(); i++) + { + D3D11RenderState oldstate = *m_WrappedContext->GetCurrentPipelineState(); + + D3D11_DEPTH_STENCIL_DESC dsdesc = { + /*DepthEnable =*/ TRUE, + /*DepthWriteMask =*/ D3D11_DEPTH_WRITE_MASK_ALL, + /*DepthFunc =*/ D3D11_COMPARISON_LESS, + /*StencilEnable =*/ FALSE, + /*StencilReadMask =*/ D3D11_DEFAULT_STENCIL_READ_MASK, + /*StencilWriteMask =*/ D3D11_DEFAULT_STENCIL_WRITE_MASK, + /*FrontFace =*/ { D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_COMPARISON_ALWAYS }, + /*BackFace =*/ { D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_STENCIL_OP_KEEP, D3D11_COMPARISON_ALWAYS }, + }; + ID3D11DepthStencilState *ds = NULL; + + if(state->OM.DepthStencilState) + state->OM.DepthStencilState->GetDesc(&dsdesc); + + dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + dsdesc.StencilWriteMask = 0; + + m_WrappedDevice->CreateDepthStencilState(&dsdesc, &ds); + + m_WrappedContext->OMSetDepthStencilState(ds, oldstate.OM.StencRef); + + SAFE_RELEASE(ds); + + UINT UAVcount = 0; + m_WrappedContext->OMSetRenderTargetsAndUnorderedAccessViews(0, NULL, oldstate.OM.DepthView, 0, 1, &overdrawUAV, &UAVcount); + + m_pImmediateContext->PSSetShader(m_DebugRender.QuadOverdrawPS, NULL, 0); + + m_WrappedDevice->ReplayLog(frameID, events[i], events[i], eReplay_OnlyDraw); + + oldstate.ApplyState(m_WrappedContext); + + if(overlay == eTexOverlay_QuadOverdrawPass) + { + m_WrappedDevice->ReplayLog(frameID, events[i], events[i], eReplay_OnlyDraw); + + if(i+1 < events.size()) + m_WrappedDevice->ReplayLog(frameID, events[i], events[i+1], eReplay_WithoutDraw); + } + } + + // resolve pass + { + m_pImmediateContext->VSSetShader(m_DebugRender.FullscreenVS, NULL, 0); + m_pImmediateContext->PSSetShader(m_DebugRender.QOResolvePS, NULL, 0); + + ID3D11Buffer *buf = MakeCBuffer((float *)&overdrawRamp[0].x, sizeof(Vec4f)*21); + + m_pImmediateContext->PSSetConstantBuffers(0, 1, &buf); + + m_pImmediateContext->OMSetRenderTargets(1, &rtv, NULL); + + m_pImmediateContext->OMSetDepthStencilState(m_DebugRender.NoDepthState, 0); + m_pImmediateContext->OMSetBlendState(NULL, NULL, 0xffffffff); + m_pImmediateContext->RSSetState(m_DebugRender.RastState); + + float clearColour[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_pImmediateContext->ClearRenderTargetView(rtv, clearColour); + + ID3D11ShaderResourceView *srv = ((WrappedID3D11ShaderResourceView *)overdrawSRV)->GetReal(); + m_pImmediateContext->PSSetShaderResources(0, 1, &srv); + + m_pImmediateContext->Draw(3, 0); + } + + SAFE_RELEASE(overdrawTex); + SAFE_RELEASE(overdrawSRV); + SAFE_RELEASE(overdrawUAV); + + if(overlay == eTexOverlay_QuadOverdrawPass) + m_WrappedDevice->ReplayLog(frameID, 0, eventID, eReplay_WithoutDraw); + } + } else if(preDrawDepth) { D3D11_DEPTH_STENCIL_DESC cur = {0}; diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index 6d1afa9bf..0e3140d5a 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -780,6 +780,9 @@ bool D3D11DebugManager::InitDebugRendering() m_DebugRender.FullscreenVS = MakeVShader(displayhlsl.c_str(), "RENDERDOC_FullscreenVS", "vs_4_0"); m_DebugRender.OverlayPS = MakePShader(displayhlsl.c_str(), "RENDERDOC_OverlayPS", "ps_4_0"); m_DebugRender.CheckerboardPS = MakePShader(displayhlsl.c_str(), "RENDERDOC_CheckerboardPS", "ps_4_0"); + + m_DebugRender.QuadOverdrawPS = MakePShader(displayhlsl.c_str(), "RENDERDOC_QuadOverdrawPS", "ps_5_0"); + m_DebugRender.QOResolvePS = MakePShader(displayhlsl.c_str(), "RENDERDOC_QOResolvePS", "ps_5_0"); string multisamplehlsl = GetEmbeddedResource(multisample_hlsl); @@ -4223,7 +4226,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) } } -void D3D11DebugManager::RenderMesh(int frameID, vector eventID, MeshDisplay cfg) +void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) { DebugVertexCBuffer vertexData; @@ -4299,9 +4302,9 @@ void D3D11DebugManager::RenderMesh(int frameID, vector eventID, MeshDisplay float nearp = 0.1f; float farp = 1000.0f; - for(size_t i=0; i < eventID.size(); i++) + for(size_t i=0; i < events.size(); i++) { - PostVSData data = GetPostVSBuffers(frameID, eventID[i]); + PostVSData data = GetPostVSBuffers(frameID, events[i]); const PostVSData::StageData &stage = data.GetStage(cfg.type); if(stage.buf && stage.nearPlane != stage.farPlane) @@ -4339,15 +4342,15 @@ void D3D11DebugManager::RenderMesh(int frameID, vector eventID, MeshDisplay { m_pImmediateContext->IASetInputLayout(m_DebugRender.GenericHomogLayout); - if(eventID.size() > 1) + if(events.size() > 1) { pixelData.WireframeColour = Vec3f(cfg.prevMeshColour.x, cfg.prevMeshColour.y, cfg.prevMeshColour.z); FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData)); } - for(size_t i=0; i < eventID.size()-1; i++) + for(size_t i=0; i < events.size()-1; i++) { - PostVSData data = GetPostVSBuffers(frameID, eventID[i]); + PostVSData data = GetPostVSBuffers(frameID, events[i]); const PostVSData::StageData &stage = data.GetStage(cfg.type); if(stage.buf) @@ -4366,7 +4369,7 @@ void D3D11DebugManager::RenderMesh(int frameID, vector eventID, MeshDisplay pixelData.WireframeColour = Vec3f(cfg.currentMeshColour.x, cfg.currentMeshColour.y, cfg.currentMeshColour.z); FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData)); - PostVSData data = GetPostVSBuffers(frameID, eventID.back()); + PostVSData data = GetPostVSBuffers(frameID, events.back()); const PostVSData::StageData &stage = data.GetStage(cfg.type); if(stage.buf) { @@ -4544,7 +4547,7 @@ void D3D11DebugManager::RenderMesh(int frameID, vector eventID, MeshDisplay m_pImmediateContext->GSSetShader(m_DebugRender.MeshGS, NULL, 0); } - m_WrappedDevice->ReplayLog(frameID, 0, eventID[0], eReplay_OnlyDraw); + m_WrappedDevice->ReplayLog(frameID, 0, events[0], eReplay_OnlyDraw); if(cfg.solidShadeMode == eShade_Lit) m_pImmediateContext->GSSetShader(NULL, NULL, 0); @@ -4563,7 +4566,7 @@ void D3D11DebugManager::RenderMesh(int frameID, vector eventID, MeshDisplay m_pImmediateContext->PSSetConstantBuffers(0, 1, &m_DebugRender.GenericPSCBuffer); - m_WrappedDevice->ReplayLog(frameID, 0, eventID[0], eReplay_OnlyDraw); + m_WrappedDevice->ReplayLog(frameID, 0, events[0], eReplay_OnlyDraw); } } diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index 9d03e296e..935fe3b47 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -130,7 +130,7 @@ class D3D11DebugManager bool SaveTexture(ResourceId tex, uint32_t saveMip, wstring path); void RenderText(float x, float y, float size, const char *textfmt, ...); - void RenderMesh(int frameID, vector eventID, MeshDisplay cfg); + void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg); ID3D11Buffer *MakeCBuffer(float *data, size_t size); @@ -158,7 +158,7 @@ class D3D11DebugManager ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]); void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, float pixel[4]); - ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID); + ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents); ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip); // don't need to differentiate arrays as we treat everything @@ -438,6 +438,8 @@ class D3D11DebugManager ID3D11PixelShader *CopyMSToArrayPS, *CopyArrayToMSPS; ID3D11PixelShader *FloatCopyMSToArrayPS, *FloatCopyArrayToMSPS; ID3D11PixelShader *DepthCopyMSToArrayPS, *DepthCopyArrayToMSPS; + + ID3D11PixelShader *QuadOverdrawPS, *QOResolvePS; ID3D11Buffer *tileResultBuff, *resultBuff, *resultStageBuff; ID3D11UnorderedAccessView *tileResultUAV[3], *resultUAV[3]; diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index a5fb637b1..a3353463c 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -1245,9 +1245,9 @@ bool D3D11Replay::SaveTexture(ResourceId tex, uint32_t saveMip, wstring path) return m_pDevice->GetDebugManager()->SaveTexture(tex, saveMip, path); } -void D3D11Replay::RenderMesh(int frameID, vector eventID, MeshDisplay cfg) +void D3D11Replay::RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) { - return m_pDevice->GetDebugManager()->RenderMesh(frameID, eventID, cfg); + return m_pDevice->GetDebugManager()->RenderMesh(frameID, events, cfg); } void D3D11Replay::BuildTargetShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors) @@ -1316,9 +1316,9 @@ void D3D11Replay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t m_pDevice->GetDebugManager()->PickPixel(texture, x, y, sliceFace, mip, pixel); } -ResourceId D3D11Replay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID) +ResourceId D3D11Replay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents) { - return m_pDevice->GetDebugManager()->RenderOverlay(texid, overlay, frameID, eventID); + return m_pDevice->GetDebugManager()->RenderOverlay(texid, overlay, frameID, eventID, passEvents); } ResourceId D3D11Replay::ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip) diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index 93904e029..458e6664d 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -101,7 +101,7 @@ class D3D11Replay : public IReplayDriver ResourceId CreateProxyTexture(FetchTexture templateTex); void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize); - void RenderMesh(int frameID, vector eventID, MeshDisplay cfg); + void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg); bool RenderTexture(TextureDisplay cfg); @@ -117,7 +117,7 @@ class D3D11Replay : public IReplayDriver ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]); void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, float pixel[4]); - ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID); + ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents); void BuildCustomShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors); ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip); diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index 96d39cbbc..5c8418b78 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -399,7 +399,7 @@ void GLReplay::RenderHighlightBox(float w, float h, float scale) gl.glDrawArrays(eGL_LINE_LOOP, 0, 4); } -ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID) +ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents) { WrappedOpenGL &gl = *m_pDriver; @@ -635,7 +635,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl return m_pDriver->GetResourceManager()->GetID(TextureRes(ctx, DebugData.overlayTex)); } -void GLReplay::RenderMesh(int frameID, vector eventID, MeshDisplay cfg) +void GLReplay::RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) { WrappedOpenGL &gl = *m_pDriver; @@ -745,7 +745,7 @@ void GLReplay::RenderMesh(int frameID, vector eventID, MeshDisplay cfg) gl.glDisable(eGL_DEPTH_TEST); gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_LINE); - ReplayLog(frameID, 0, eventID[0], eReplay_OnlyDraw); + ReplayLog(frameID, 0, events[0], eReplay_OnlyDraw); if(depthTest) gl.glEnable(eGL_DEPTH_TEST); diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 1eb69eaad..489498981 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -97,7 +97,7 @@ class GLReplay : public IReplayDriver bool SaveTexture(ResourceId tex, uint32_t saveMip, wstring path); - void RenderMesh(int frameID, vector eventID, MeshDisplay cfg); + void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg); void BuildTargetShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors); void BuildCustomShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors); @@ -117,7 +117,7 @@ class GLReplay : public IReplayDriver ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]); void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, float pixel[4]); - ResourceId RenderOverlay(ResourceId cfg, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID); + ResourceId RenderOverlay(ResourceId cfg, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents); ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip); ResourceId CreateProxyTexture(FetchTexture templateTex); diff --git a/renderdoc/maths/matrix.cpp b/renderdoc/maths/matrix.cpp index 52f671917..4c13fbcdb 100644 --- a/renderdoc/maths/matrix.cpp +++ b/renderdoc/maths/matrix.cpp @@ -32,6 +32,32 @@ #include "matrix.h" #include "quat.h" +// colour ramp from http://www.ncl.ucar.edu/Document/Graphics/ColorTables/GMT_wysiwyg.shtml +const Vec4f overdrawRamp[21] = +{ + Vec4f(0.000000f, 0.000000f, 0.000000f, 0.0f), + Vec4f(0.250980f, 0.000000f, 0.250980f, 1.0f), + Vec4f(0.250980f, 0.000000f, 0.752941f, 1.0f), + Vec4f(0.000000f, 0.250980f, 1.000000f, 1.0f), + Vec4f(0.000000f, 0.501961f, 1.000000f, 1.0f), + Vec4f(0.000000f, 0.627451f, 1.000000f, 1.0f), + Vec4f(0.250980f, 0.752941f, 1.000000f, 1.0f), + Vec4f(0.250980f, 0.878431f, 1.000000f, 1.0f), + Vec4f(0.250980f, 1.000000f, 1.000000f, 1.0f), + Vec4f(0.250980f, 1.000000f, 0.752941f, 1.0f), + Vec4f(0.250980f, 1.000000f, 0.250980f, 1.0f), + Vec4f(0.501961f, 1.000000f, 0.250980f, 1.0f), + Vec4f(0.752941f, 1.000000f, 0.250980f, 1.0f), + Vec4f(1.000000f, 1.000000f, 0.250980f, 1.0f), + Vec4f(1.000000f, 0.878431f, 0.250980f, 1.0f), + Vec4f(1.000000f, 0.627451f, 0.250980f, 1.0f), + Vec4f(1.000000f, 0.376471f, 0.250980f, 1.0f), + Vec4f(1.000000f, 0.125490f, 0.250980f, 1.0f), + Vec4f(1.000000f, 0.376471f, 0.752941f, 1.0f), + Vec4f(1.000000f, 0.627451f, 1.000000f, 1.0f), + Vec4f(1.000000f, 0.878431f, 1.000000f, 1.0f), +}; + static inline size_t matIdx(const size_t x, const size_t y) { return x+y*4; } Matrix4f Matrix4f::Mul(const Matrix4f &o) const diff --git a/renderdoc/maths/vec.h b/renderdoc/maths/vec.h index 659e4ab86..41eeb0f4b 100644 --- a/renderdoc/maths/vec.h +++ b/renderdoc/maths/vec.h @@ -75,6 +75,8 @@ struct Vec4f float x, y, z, w; }; +extern const Vec4f overdrawRamp[21]; + inline Vec3f operator *(const Vec3f &a, const float b) { return Vec3f(a.x*b, a.y*b, a.z*b); diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index 7b06de05c..fad54cd6d 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -98,7 +98,7 @@ class IRemoteDriver virtual ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y) = 0; virtual ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]) = 0; - virtual ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID) = 0; + virtual ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents) = 0; virtual bool IsRenderOutput(ResourceId id) = 0; @@ -130,7 +130,7 @@ class IReplayDriver : public IRemoteDriver virtual bool SaveTexture(ResourceId tex, uint32_t saveMip, wstring path) = 0; - virtual void RenderMesh(int frameID, vector eventID, MeshDisplay cfg) = 0; + virtual void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) = 0; virtual bool RenderTexture(TextureDisplay cfg) = 0; virtual void BuildCustomShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors) = 0; diff --git a/renderdoc/replay/replay_enums.h b/renderdoc/replay/replay_enums.h index 0898c6a96..1c6787c1e 100644 --- a/renderdoc/replay/replay_enums.h +++ b/renderdoc/replay/replay_enums.h @@ -123,6 +123,8 @@ enum TextureDisplayOverlay eTexOverlay_ViewportScissor, eTexOverlay_NaN, eTexOverlay_Clipping, + eTexOverlay_QuadOverdrawPass, + eTexOverlay_QuadOverdrawDraw, }; enum SpecialFormat diff --git a/renderdoc/replay/replay_output.cpp b/renderdoc/replay/replay_output.cpp index 91b3d95b9..c49f3f119 100644 --- a/renderdoc/replay/replay_output.cpp +++ b/renderdoc/replay/replay_output.cpp @@ -93,6 +93,8 @@ bool ReplayOutput::SetTextureDisplay(const TextureDisplay &o) bool ReplayOutput::SetMeshDisplay(const MeshDisplay &o) { + if(o.thisDrawOnly!= m_RenderData.meshDisplay.thisDrawOnly) + m_OverlayDirty = true; m_RenderData.meshDisplay = o; m_MainOutput.dirty = true; return true; @@ -122,11 +124,40 @@ void ReplayOutput::RefreshOverlay() { FetchDrawcall *draw = m_pRenderer->GetDrawcallByEID(m_EventID, m_LastDeferredEvent); + { + passEvents.clear(); + + FetchDrawcall *start = draw; + while(start && start->previous != 0 && (m_pRenderer->GetDrawcallByDrawID((uint32_t)start->previous)->flags & eDraw_Clear) == 0) + { + FetchDrawcall *prev = m_pRenderer->GetDrawcallByDrawID((uint32_t)start->previous);; + + if(memcmp(start->outputs, prev->outputs, sizeof(start->outputs)) || start->depthOut != prev->depthOut) + break; + + start = prev; + } + + while(start) + { + if(start->flags & eDraw_Drawcall) + { + passEvents.push_back(start->eventID); + } + + if(start == draw) + break; + + start = m_pRenderer->GetDrawcallByDrawID((uint32_t)start->next); + } + } + if(m_Config.m_Type == eOutputType_TexDisplay && m_RenderData.texDisplay.overlay != eTexOverlay_None) { if(draw && m_pDevice->IsRenderOutput(m_RenderData.texDisplay.texid)) { - m_OverlayResourceId = m_pDevice->RenderOverlay(m_pDevice->GetLiveID(m_RenderData.texDisplay.texid), m_RenderData.texDisplay.overlay, m_FrameID, m_EventID); + m_OverlayResourceId = m_pDevice->RenderOverlay(m_pDevice->GetLiveID(m_RenderData.texDisplay.texid), m_RenderData.texDisplay.overlay, + m_FrameID, m_EventID, passEvents); m_OverlayDirty = false; } } @@ -142,36 +173,22 @@ void ReplayOutput::RefreshOverlay() { m_pDevice->InitPostVSBuffers(m_FrameID, draw->eventID); } - else + else if(!passEvents.empty()) { - FetchDrawcall *start = draw; - while(start->previous != 0 && (m_pRenderer->GetDrawcallByDrawID((uint32_t)start->previous)->flags & eDraw_Clear) == 0) - start = m_pRenderer->GetDrawcallByDrawID((uint32_t)start->previous); - - m_pDevice->ReplayLog(m_FrameID, 0, start->eventID, eReplay_WithoutDraw); + uint32_t prev = passEvents[0]; - uint32_t prev = start->eventID; - - while(start) + for(size_t i=0; i < passEvents.size(); i++) { - if(start->flags & eDraw_Drawcall) + if(prev != passEvents[i]) { - if(prev != start->eventID) - { - m_pDevice->ReplayLog(m_FrameID, prev, start->eventID, eReplay_WithoutDraw); + m_pDevice->ReplayLog(m_FrameID, prev, passEvents[i], eReplay_WithoutDraw); - prev = start->eventID; - } - - m_pDevice->InitPostVSBuffers(m_FrameID, start->eventID); + prev = passEvents[i]; } - if(start == draw) - break; - - start = m_pRenderer->GetDrawcallByDrawID((uint32_t)start->next); + m_pDevice->InitPostVSBuffers(m_FrameID, passEvents[i]); } - + m_pDevice->ReplayLog(m_FrameID, 0, m_EventID, eReplay_WithoutDraw); } } @@ -249,12 +266,38 @@ bool ReplayOutput::PickPixel(ResourceId tex, bool customShader, uint32_t x, uint RDCEraseEl(ret->value_f); + bool decodeRamp = false; + if(customShader && m_RenderData.texDisplay.CustomShader != ResourceId() && m_CustomShaderResourceId != ResourceId()) { tex = m_CustomShaderResourceId; } + if((m_RenderData.texDisplay.overlay == eTexOverlay_QuadOverdrawDraw || + m_RenderData.texDisplay.overlay == eTexOverlay_QuadOverdrawPass) && + m_OverlayResourceId != ResourceId()) + { + decodeRamp = true; + tex = m_OverlayResourceId; + } m_pDevice->PickPixel(m_pDevice->GetLiveID(tex), x, y, sliceFace, mip, ret->value_f); + + if(decodeRamp) + { + for(size_t c=0; c < ARRAY_COUNT(overdrawRamp); c++) + { + if(fabs(ret->value_f[0] - overdrawRamp[c].x) < 0.001f && + fabs(ret->value_f[1] - overdrawRamp[c].y) < 0.001f && + fabs(ret->value_f[2] - overdrawRamp[c].z) < 0.001f) + { + ret->value_i[0] = (int32_t)c; + ret->value_i[1] = 0; + ret->value_i[2] = 0; + ret->value_i[3] = 0; + break; + } + } + } return true; } @@ -294,6 +337,11 @@ void ReplayOutput::DisplayContext() if(m_RenderData.texDisplay.CustomShader != ResourceId()) disp.texid = m_CustomShaderResourceId; + + if((m_RenderData.texDisplay.overlay == eTexOverlay_QuadOverdrawDraw || + m_RenderData.texDisplay.overlay == eTexOverlay_QuadOverdrawPass) && + m_OverlayResourceId != ResourceId()) + disp.texid = m_OverlayResourceId; disp.scale = 8.0f; @@ -490,7 +538,14 @@ void ReplayOutput::DisplayMesh() if(m_RenderData.meshDisplay.type == eMeshDataStage_Unknown) return; if((draw->flags & eDraw_Drawcall) == 0) return; - vector events; + vector events = passEvents; + + if(m_RenderData.meshDisplay.type == eMeshDataStage_VSIn || + m_RenderData.meshDisplay.thisDrawOnly) + { + events.clear(); + events.push_back(draw->eventID); + } if(draw && m_OverlayDirty) { @@ -499,44 +554,11 @@ void ReplayOutput::DisplayMesh() m_pDevice->ReplayLog(m_FrameID, 0, m_EventID, eReplay_OnlyDraw); } - if(m_RenderData.meshDisplay.type != eMeshDataStage_VSIn) - { - if(m_RenderData.meshDisplay.thisDrawOnly) - { - events.push_back(draw->eventID); - } - else - { - FetchDrawcall *start = draw; - while(start->previous != 0 && (m_pRenderer->GetDrawcallByDrawID((uint32_t)start->previous)->flags & eDraw_Clear) == 0) - start = m_pRenderer->GetDrawcallByDrawID((uint32_t)start->previous); - - while(start) - { - if(start->flags & eDraw_Drawcall) - { - events.push_back(start->eventID); - } - - if(start == draw) - break; - - start = m_pRenderer->GetDrawcallByDrawID((uint32_t)start->next); - } - } - } - m_pDevice->BindOutputWindow(m_MainOutput.outputID, true); m_pDevice->ClearOutputWindowDepth(m_MainOutput.outputID, 1.0f, 0); m_pDevice->RenderCheckerboard(Vec3f(0.666f, 0.666f, 0.666f), Vec3f(0.333f, 0.333f, 0.333f)); - if(m_RenderData.meshDisplay.type == eMeshDataStage_VSIn) - { - events.clear(); - events.push_back(draw->eventID); - } - RDCASSERT(!events.empty()); m_pDevice->ClearOutputWindowDepth(m_MainOutput.outputID, 1.0f, 0); diff --git a/renderdoc/replay/replay_renderer.h b/renderdoc/replay/replay_renderer.h index da518e5df..8ea1fccce 100644 --- a/renderdoc/replay/replay_renderer.h +++ b/renderdoc/replay/replay_renderer.h @@ -107,6 +107,8 @@ private: uint32_t m_FirstDeferredEvent; uint32_t m_LastDeferredEvent; OutputConfig m_Config; + + vector passEvents; int32_t m_Width; int32_t m_Height; diff --git a/renderdocui/Interop/Enums.cs b/renderdocui/Interop/Enums.cs index 6a50ced8c..b6948c817 100644 --- a/renderdocui/Interop/Enums.cs +++ b/renderdocui/Interop/Enums.cs @@ -125,6 +125,8 @@ namespace renderdoc ViewportScissor, NaN, Clipping, + QuadOverdrawPass, + QuadOverdrawDraw, }; public enum SpecialFormat diff --git a/renderdocui/Windows/TextureViewer.Designer.cs b/renderdocui/Windows/TextureViewer.Designer.cs index 8f16f6ae0..6509cfeef 100644 --- a/renderdocui/Windows/TextureViewer.Designer.cs +++ b/renderdocui/Windows/TextureViewer.Designer.cs @@ -554,7 +554,9 @@ "Stencil Test", "Viewport/Scissor Region", "NaN/INF/-ve Display", - "Clipping"}); + "Clipping", + "Quad Overdraw (Pass)", + "Quad Overdraw (Draw)"}); this.overlay.Name = "overlay"; this.overlay.Size = new System.Drawing.Size(121, 25); this.overlay.SelectedIndexChanged += new System.EventHandler(this.overlay_SelectedIndexChanged); diff --git a/renderdocui/Windows/TextureViewer.cs b/renderdocui/Windows/TextureViewer.cs index 7e51699b1..bd616d9c4 100644 --- a/renderdocui/Windows/TextureViewer.cs +++ b/renderdocui/Windows/TextureViewer.cs @@ -1331,6 +1331,14 @@ namespace renderdocui.Windows bool uintTex = (tex.format.compType == FormatComponentType.UInt); bool sintTex = (tex.format.compType == FormatComponentType.SInt); + if (m_TexDisplay.overlay == TextureDisplayOverlay.QuadOverdrawPass || + m_TexDisplay.overlay == TextureDisplayOverlay.QuadOverdrawDraw) + { + dsv = false; + uintTex = false; + sintTex = true; + } + if (m_CurHoverValue != null) { if (dsv || uintTex || sintTex)