diff --git a/renderdoc/api/replay/control_types.h b/renderdoc/api/replay/control_types.h index 8c1f70b1e..1a715e0e5 100644 --- a/renderdoc/api/replay/control_types.h +++ b/renderdoc/api/replay/control_types.h @@ -32,9 +32,10 @@ struct OutputConfig struct MeshFormat { ResourceId idxbuf; + uint32_t idxoffs; uint32_t idxByteWidth; - ResourceId buf; + ResourceId buf; uint32_t offset; uint32_t stride; @@ -46,6 +47,7 @@ struct MeshFormat bool showAlpha; PrimitiveTopology topo; + uint32_t numVerts; bool32 unproject; float nearPlane; diff --git a/renderdoc/core/image_viewer.cpp b/renderdoc/core/image_viewer.cpp index 11c6cad52..7938b6a9b 100644 --- a/renderdoc/core/image_viewer.cpp +++ b/renderdoc/core/image_viewer.cpp @@ -103,7 +103,7 @@ class ImageViewer : public IReplayDriver // other operations are dropped/ignored, to avoid confusion void ReadLogInitialisation() {} - void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) {} + void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg) {} vector GetBuffers() { return vector(); } vector GetDebugMessages() { return vector(); } FetchBuffer GetBuffer(ResourceId id) { FetchBuffer ret; RDCEraseEl(ret); return ret; } diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index 3fb738cc6..bd671e330 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -214,7 +214,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver } } - void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) + void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg) { if(m_Proxy) m_Proxy->RenderCheckerboard(Vec3f(0.7f, 0.3f, 0.3f), Vec3f(0.3f, 0.3f, 0.7f)); diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index b52540f05..2b5b53d28 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -63,6 +63,73 @@ HMODULE GetD3DCompiler() return ret; } +D3D11_PRIMITIVE_TOPOLOGY MakeD3D11PrimitiveTopology(PrimitiveTopology Topo) +{ + switch(Topo) + { + case eTopology_LineLoop: + case eTopology_TriangleFan: + RDCWARN("Unsupported primitive topology on D3D11: %x", Topo); + break; + default: + case eTopology_Unknown: + return D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + case eTopology_PointList: + return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; + case eTopology_LineList: + return D3D11_PRIMITIVE_TOPOLOGY_LINELIST; + case eTopology_LineStrip: + return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP; + case eTopology_TriangleList: + return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + case eTopology_TriangleStrip: + return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + case eTopology_LineList_Adj: + return D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; + case eTopology_LineStrip_Adj: + return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ; + case eTopology_TriangleList_Adj: + return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; + case eTopology_TriangleStrip_Adj: + return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ; + case eTopology_PatchList_1CPs: + case eTopology_PatchList_2CPs: + case eTopology_PatchList_3CPs: + case eTopology_PatchList_4CPs: + case eTopology_PatchList_5CPs: + case eTopology_PatchList_6CPs: + case eTopology_PatchList_7CPs: + case eTopology_PatchList_8CPs: + case eTopology_PatchList_9CPs: + case eTopology_PatchList_10CPs: + case eTopology_PatchList_11CPs: + case eTopology_PatchList_12CPs: + case eTopology_PatchList_13CPs: + case eTopology_PatchList_14CPs: + case eTopology_PatchList_15CPs: + case eTopology_PatchList_16CPs: + case eTopology_PatchList_17CPs: + case eTopology_PatchList_18CPs: + case eTopology_PatchList_19CPs: + case eTopology_PatchList_20CPs: + case eTopology_PatchList_21CPs: + case eTopology_PatchList_22CPs: + case eTopology_PatchList_23CPs: + case eTopology_PatchList_24CPs: + case eTopology_PatchList_25CPs: + case eTopology_PatchList_26CPs: + case eTopology_PatchList_27CPs: + case eTopology_PatchList_28CPs: + case eTopology_PatchList_29CPs: + case eTopology_PatchList_30CPs: + case eTopology_PatchList_31CPs: + case eTopology_PatchList_32CPs: + return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (Topo - eTopology_PatchList_1CPs)); + } + + return D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; +} + PrimitiveTopology MakePrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topo) { switch(Topo) diff --git a/renderdoc/driver/d3d11/d3d11_common.h b/renderdoc/driver/d3d11/d3d11_common.h index ab2c81748..2ae47e694 100644 --- a/renderdoc/driver/d3d11/d3d11_common.h +++ b/renderdoc/driver/d3d11/d3d11_common.h @@ -44,6 +44,7 @@ HMODULE GetD3DCompiler(); ResourceFormat MakeResourceFormat(DXGI_FORMAT fmt); DXGI_FORMAT MakeDXGIFormat(ResourceFormat fmt); PrimitiveTopology MakePrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topo); +D3D11_PRIMITIVE_TOPOLOGY MakeD3D11PrimitiveTopology(PrimitiveTopology Topo); ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc); diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index c2694fc9d..2c3ba3713 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -3729,6 +3729,7 @@ MeshFormat D3D11DebugManager::GetPostVSBuffers(uint32_t frameID, uint32_t eventI ret.idxbuf = ((WrappedID3D11Buffer *)s.idxBuf)->GetResourceID(); else ret.idxbuf = ResourceId(); + ret.idxoffs = 0; ret.idxByteWidth = s.idxFmt == DXGI_FORMAT_R16_UINT ? 2 : 4; if(s.buf) @@ -3747,6 +3748,7 @@ MeshFormat D3D11DebugManager::GetPostVSBuffers(uint32_t frameID, uint32_t eventI ret.showAlpha = false; ret.topo = MakePrimitiveTopology(s.topo); + ret.numVerts = s.numVerts; ret.unproject = true; ret.nearPlane = s.nearPlane; @@ -4521,38 +4523,14 @@ FloatVector D3D11DebugManager::InterpretVertex(byte *data, uint32_t vert, MeshDi return ret; } -void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) +void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg) { DebugVertexCBuffer vertexData; + + D3D11RenderStateTracker tracker(m_WrappedContext); vertexData.LineStrip = 0; - D3D11PipelineState pipeState = m_WrappedDevice->GetReplay()->GetD3D11PipelineState(); - D3D11RenderState *curRS = m_WrappedDevice->GetImmediateContext()->GetCurrentPipelineState(); - - float aspect = 1.0f; - - // guess the output aspect ratio, for mesh calculation - if(pipeState.m_OM.DepthTarget.Resource != ResourceId()) - { - FetchTexture desc = m_WrappedDevice->GetReplay()->GetTexture(m_ResourceManager->GetLiveID(pipeState.m_OM.DepthTarget.Resource)); - - aspect = float(desc.width)/float(desc.height); - } - else - { - for(int32_t i=0; i < pipeState.m_OM.RenderTargets.count; i++) - { - if(pipeState.m_OM.RenderTargets[i].Resource != ResourceId()) - { - FetchTexture desc = m_WrappedDevice->GetReplay()->GetTexture(m_ResourceManager->GetLiveID(pipeState.m_OM.RenderTargets[i].Resource)); - - aspect = float(desc.width)/float(desc.height); - break; - } - } - } - Matrix4f projMat = Matrix4f::Perspective(90.0f, 0.1f, 100000.0f, float(GetWidth())/float(GetHeight())); Camera cam; @@ -4584,14 +4562,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve m_pImmediateContext->OMSetBlendState(m_WireframeHelpersBS, NULL, 0xffffffff); // don't cull in wireframe mesh display - /* - if(pipeState.m_RS.m_State.CullMode != eCull_None && pipeState.m_RS.m_State.FrontCCW) - m_pImmediateContext->RSSetState(m_WireframeHelpersCullCWRS); - else if(pipeState.m_RS.m_State.CullMode != eCull_None && !pipeState.m_RS.m_State.FrontCCW) - m_pImmediateContext->RSSetState(m_WireframeHelpersCullCCWRS); - else - */ - m_pImmediateContext->RSSetState(m_WireframeHelpersRS); + m_pImmediateContext->RSSetState(m_WireframeHelpersRS); ResourceFormat resFmt; resFmt.compByteWidth = cfg.position.compByteWidth; @@ -4665,194 +4636,97 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve m_PrevMeshFmt = resFmt; m_PrevMeshFmt2 = resFmt2; + + ID3D11Buffer *ibuf = NULL; + DXGI_FORMAT ifmt = DXGI_FORMAT_R16_UINT; + UINT ioffs = cfg.position.idxoffs; + + D3D11_PRIMITIVE_TOPOLOGY topo = MakeD3D11PrimitiveTopology(cfg.position.topo); - if(cfg.position.unproject || events.size() > 1) + // render the mesh itself (solid, then wireframe) { - float nearp = 0.1f; - float farp = 1000.0f; - - for(size_t i=0; i < events.size(); i++) + if(cfg.position.unproject) { - PostVSData data = GetPostVSBuffers(frameID, events[i]); - const PostVSData::StageData &stage = data.GetStage(cfg.type); + // the derivation of the projection matrix might not be right (hell, it could be an + // orthographic projection). But it'll be close enough likely. + Matrix4f guessProj = Matrix4f::Perspective(cfg.fov, cfg.position.nearPlane, cfg.position.farPlane, cfg.aspect); - if(stage.buf && stage.nearPlane != stage.farPlane) + if(cfg.ortho) { - nearp = stage.nearPlane; - farp = stage.farPlane; - break; - } - } - - if(cfg.position.nearPlane > -FLT_MAX) nearp = cfg.position.nearPlane; - if(cfg.position.farPlane > -FLT_MAX) farp = cfg.position.farPlane; - if(cfg.aspect > 0.0f) aspect = cfg.aspect; - - // the derivation of the projection matrix might not be right (hell, it could be an - // orthographic projection). But it'll be close enough likely. - Matrix4f guessProj = Matrix4f::Perspective(cfg.fov, nearp, farp, aspect); - - if(cfg.ortho) - { - guessProj = Matrix4f::Orthographic(nearp, farp); - } - - guessProjInv = guessProj.Inverse(); - - vertexData.ModelViewProj = projMat.Mul(camMat.Mul(guessProjInv)); - - FillCBuffer(m_DebugRender.GenericVSCBuffer, (float *)&vertexData, sizeof(DebugVertexCBuffer)); - m_pImmediateContext->VSSetConstantBuffers(0, 1, &m_DebugRender.GenericVSCBuffer); - m_pImmediateContext->VSSetShader(m_DebugRender.WireframeHomogVS, NULL, 0); - - m_pImmediateContext->PSSetConstantBuffers(0, 1, &m_DebugRender.GenericPSCBuffer); - m_pImmediateContext->PSSetShader(m_DebugRender.MeshPS, NULL, 0); - - { - if(events.size() > 1) - { - pixelData.OutputDisplayFormat = MESHDISPLAY_SOLID; - pixelData.WireframeColour = Vec3f(cfg.prevMeshColour.x, cfg.prevMeshColour.y, cfg.prevMeshColour.z); - FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData)); - } - - m_pImmediateContext->IASetInputLayout(m_DebugRender.GenericHomogLayout); - - for(size_t i=0; i < events.size()-1; i++) - { - PostVSData data = GetPostVSBuffers(frameID, events[i]); - PostVSData::StageData stage = data.GetStage(cfg.type); - - if(stage.buf == NULL && cfg.type == eMeshDataStage_GSOut) - stage = data.GetStage(eMeshDataStage_VSOut); - - if(stage.buf) - { - if(stage.topo > D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST) - m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - else - m_pImmediateContext->IASetPrimitiveTopology(stage.topo); - - ID3D11Buffer *buf = UNWRAP(WrappedID3D11Buffer, stage.buf); - m_pImmediateContext->IASetVertexBuffers(0, 1, &buf, (UINT *)&stage.vertStride, (UINT *)&stage.posOffset); - if(stage.useIndices) - { - buf = UNWRAP(WrappedID3D11Buffer, stage.idxBuf); - m_pImmediateContext->IASetIndexBuffer(buf, stage.idxFmt, 0); - - m_pImmediateContext->DrawIndexed(stage.numVerts, 0, 0); - } - else - { - m_pImmediateContext->Draw(stage.numVerts, 0); - } - } - } - - m_pImmediateContext->IASetInputLayout(m_PostMeshDisplayLayout); - - if(m_PostMeshDisplayLayout == NULL) - { - RDCWARN("Couldn't get a mesh display layout"); - return; - } - - PostVSData data = GetPostVSBuffers(frameID, events.back()); - const PostVSData::StageData &stage = data.GetStage(cfg.type); - if(stage.buf) - { - if(stage.topo > D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST) - m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - else - m_pImmediateContext->IASetPrimitiveTopology(stage.topo); - - ID3D11Buffer *buf = UNWRAP(WrappedID3D11Buffer, stage.buf); - m_pImmediateContext->IASetVertexBuffers(0, 1, &buf, (UINT *)&stage.vertStride, (UINT *)&stage.posOffset); - - UINT offset = cfg.second.offset; - m_pImmediateContext->IASetVertexBuffers(1, 1, &buf, (UINT *)&stage.vertStride, &offset); - - if(stage.useIndices) - { - buf = UNWRAP(WrappedID3D11Buffer, stage.idxBuf); - m_pImmediateContext->IASetIndexBuffer(buf, stage.idxFmt, 0); - } - - // draw solid shaded mode - if(cfg.solidShadeMode != eShade_None) - { - m_pImmediateContext->RSSetState(m_DebugRender.RastState); - - pixelData.OutputDisplayFormat = (int)cfg.solidShadeMode; - if(cfg.solidShadeMode == eShade_Secondary && cfg.second.showAlpha) - pixelData.OutputDisplayFormat = MESHDISPLAY_SECONDARY_ALPHA; - pixelData.WireframeColour = Vec3f(0.8f, 0.8f, 0.0f); - FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData)); - - if(cfg.solidShadeMode == eShade_Lit) - { - DebugGeometryCBuffer geomData; - - geomData.InvProj = projMat.Inverse(); - - FillCBuffer(m_DebugRender.GenericGSCBuffer, (float *)&geomData, sizeof(DebugGeometryCBuffer)); - m_pImmediateContext->GSSetConstantBuffers(0, 1, &m_DebugRender.GenericGSCBuffer); - - m_pImmediateContext->GSSetShader(m_DebugRender.MeshGS, NULL, 0); - } - - if(stage.useIndices) - m_pImmediateContext->DrawIndexed(stage.numVerts, 0, 0); - else - m_pImmediateContext->Draw(stage.numVerts, 0); - - if(cfg.solidShadeMode == eShade_Lit) - m_pImmediateContext->GSSetShader(NULL, NULL, 0); - } - - // draw wireframe mode - if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw) - { - m_pImmediateContext->RSSetState(m_WireframeHelpersRS); - - m_pImmediateContext->OMSetDepthStencilState(m_DebugRender.LEqualDepthState, 0); - - pixelData.OutputDisplayFormat = MESHDISPLAY_SOLID; - if(cfg.solidShadeMode == eShade_None) - pixelData.WireframeColour = Vec3f(cfg.currentMeshColour.x, cfg.currentMeshColour.y, cfg.currentMeshColour.z); - else - pixelData.WireframeColour = Vec3f(0.0f, 0.0f, 0.0f); - FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData)); - - if(stage.useIndices) - m_pImmediateContext->DrawIndexed(stage.numVerts, 0, 0); - else - m_pImmediateContext->Draw(stage.numVerts, 0); - } + guessProj = Matrix4f::Orthographic(cfg.position.nearPlane, cfg.position.farPlane); } - if(cfg.solidShadeMode == eShade_Lit) - m_pImmediateContext->GSSetShader(NULL, NULL, 0); + guessProjInv = guessProj.Inverse(); + + vertexData.ModelViewProj = projMat.Mul(camMat.Mul(guessProjInv)); } - } - else - { + FillCBuffer(m_DebugRender.GenericVSCBuffer, (float *)&vertexData, sizeof(DebugVertexCBuffer)); + m_pImmediateContext->VSSetConstantBuffers(0, 1, &m_DebugRender.GenericVSCBuffer); - m_pImmediateContext->VSSetShader(m_DebugRender.MeshVS, NULL, 0); + m_pImmediateContext->PSSetConstantBuffers(0, 1, &m_DebugRender.GenericPSCBuffer); + + if(cfg.position.unproject) + m_pImmediateContext->VSSetShader(m_DebugRender.WireframeHomogVS, NULL, 0); + else + m_pImmediateContext->VSSetShader(m_DebugRender.MeshVS, NULL, 0); + m_pImmediateContext->PSSetShader(m_DebugRender.MeshPS, NULL, 0); + + // secondary draws - this is the "draw since last clear" feature. We don't have + // full flexibility, it only draws wireframe, and only the final rasterized position. + if(secondaryDraws.size() > 0) + { + m_pImmediateContext->IASetInputLayout(m_DebugRender.GenericHomogLayout); + + pixelData.OutputDisplayFormat = MESHDISPLAY_SOLID; + 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 < secondaryDraws.size(); i++) + { + const MeshFormat &fmt = secondaryDraws[i]; + + if(fmt.buf != ResourceId()) + { + D3D11_PRIMITIVE_TOPOLOGY d3d11topo = MakeD3D11PrimitiveTopology(fmt.topo); + + m_pImmediateContext->IASetPrimitiveTopology(MakeD3D11PrimitiveTopology(fmt.topo)); + + auto it = WrappedID3D11Buffer::m_BufferList.find(fmt.buf); + + ID3D11Buffer *buf = UNWRAP(WrappedID3D11Buffer, it->second.m_Buffer); + m_pImmediateContext->IASetVertexBuffers(0, 1, &buf, (UINT *)&fmt.stride, (UINT *)&fmt.offset); + if(fmt.idxbuf != ResourceId()) + { + it = WrappedID3D11Buffer::m_BufferList.find(fmt.idxbuf); + buf = UNWRAP(WrappedID3D11Buffer, it->second.m_Buffer); + m_pImmediateContext->IASetIndexBuffer(buf, fmt.idxByteWidth == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, fmt.idxoffs); + + m_pImmediateContext->DrawIndexed(fmt.numVerts, 0, 0); + } + else + { + m_pImmediateContext->Draw(fmt.numVerts, 0); + } + } + } + } + + ID3D11InputLayout *layout = cfg.position.unproject ? m_PostMeshDisplayLayout : m_MeshDisplayLayout; - if(m_MeshDisplayLayout == NULL) + if(layout == NULL) { RDCWARN("Couldn't get a mesh display layout"); return; } + + m_pImmediateContext->IASetInputLayout(layout); ID3D11Buffer *vbs[2] = { NULL, NULL }; UINT str[] = { cfg.position.stride, cfg.second.stride }; UINT offs[] = { cfg.position.offset, cfg.second.offset }; - if(cfg.type == eMeshDataStage_VSIn) { auto it = WrappedID3D11Buffer::m_BufferList.find(cfg.position.buf); @@ -4863,27 +4737,27 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve if(it != WrappedID3D11Buffer::m_BufferList.end()) vbs[1] = UNWRAP(WrappedID3D11Buffer, it->second.m_Buffer); - } - else - { - PostVSData data = GetPostVSBuffers(frameID, events[0]); - if(cfg.type == eMeshDataStage_VSOut) - vbs[0] = vbs[1] = UNWRAP(WrappedID3D11Buffer, data.vsout.buf); - if(cfg.type == eMeshDataStage_GSOut) - vbs[0] = vbs[1] = UNWRAP(WrappedID3D11Buffer, data.gsout.buf); + it = WrappedID3D11Buffer::m_BufferList.find(cfg.position.idxbuf); + + if(it != WrappedID3D11Buffer::m_BufferList.end()) + ibuf = UNWRAP(WrappedID3D11Buffer, it->second.m_Buffer); + + if(cfg.position.idxByteWidth == 4) + ifmt = DXGI_FORMAT_R32_UINT; } m_pImmediateContext->IASetVertexBuffers(0, 2, vbs, str, offs); - m_pImmediateContext->IASetInputLayout(m_MeshDisplayLayout); - - const FetchDrawcall *drawcall = m_WrappedDevice->GetDrawcall(frameID, events.back()); + if(ibuf) + m_pImmediateContext->IASetIndexBuffer(ibuf, ifmt, ioffs); // draw solid shaded mode - if(cfg.solidShadeMode != eShade_None && drawcall->topology < eTopology_PatchList_1CPs) + if(cfg.solidShadeMode != eShade_None && cfg.position.topo < eTopology_PatchList_1CPs) { m_pImmediateContext->RSSetState(m_DebugRender.RastState); + m_pImmediateContext->IASetPrimitiveTopology(topo); + pixelData.OutputDisplayFormat = (int)cfg.solidShadeMode; if(cfg.solidShadeMode == eShade_Secondary && cfg.second.showAlpha) pixelData.OutputDisplayFormat = MESHDISPLAY_SECONDARY_ALPHA; @@ -4904,29 +4778,40 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve m_pImmediateContext->GSSetShader(m_DebugRender.MeshGS, NULL, 0); } - m_WrappedDevice->ReplayLog(frameID, 0, events[0], eReplay_OnlyDraw); + if(ibuf) + m_pImmediateContext->DrawIndexed(cfg.position.numVerts, 0, 0); + else + m_pImmediateContext->Draw(cfg.position.numVerts, 0); if(cfg.solidShadeMode == eShade_Lit) m_pImmediateContext->GSSetShader(NULL, NULL, 0); } // draw wireframe mode - if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw || drawcall->topology >= eTopology_PatchList_1CPs) + if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw || cfg.position.topo >= eTopology_PatchList_1CPs) { m_pImmediateContext->RSSetState(m_WireframeHelpersRS); m_pImmediateContext->OMSetDepthStencilState(m_DebugRender.LEqualDepthState, 0); pixelData.OutputDisplayFormat = MESHDISPLAY_SOLID; - pixelData.WireframeColour = Vec3f(0.0f, 0.0f, 0.0f); + if(secondaryDraws.size() > 0 && cfg.solidShadeMode == eShade_None) + pixelData.WireframeColour = Vec3f(cfg.currentMeshColour.x, cfg.currentMeshColour.y, cfg.currentMeshColour.z); + else + pixelData.WireframeColour = Vec3f(0.0f, 0.0f, 0.0f); FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData)); m_pImmediateContext->PSSetConstantBuffers(0, 1, &m_DebugRender.GenericPSCBuffer); - if(drawcall->topology >= eTopology_PatchList_1CPs) + if(cfg.position.topo >= eTopology_PatchList_1CPs) m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - - m_WrappedDevice->ReplayLog(frameID, 0, events[0], eReplay_OnlyDraw); + else + m_pImmediateContext->IASetPrimitiveTopology(topo); + + if(ibuf) + m_pImmediateContext->DrawIndexed(cfg.position.numVerts, 0, 0); + else + m_pImmediateContext->Draw(cfg.position.numVerts, 0); } } @@ -4974,44 +4859,20 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve if(cfg.highlightVert != ~0U) { - const FetchDrawcall *drawcall = m_WrappedDevice->GetDrawcall(frameID, events.back()); - MeshDataStage stage = cfg.type; - if(m_HighlightCache.EID != events.back() || m_HighlightCache.buf != cfg.position.buf || stage != m_HighlightCache.stage) + if(m_HighlightCache.EID != eventID || stage != m_HighlightCache.stage) { - m_HighlightCache.EID = events.back(); - m_HighlightCache.buf = cfg.position.buf; + m_HighlightCache.EID = eventID; m_HighlightCache.stage = stage; - ID3D11Buffer *idxBuf = curRS->IA.IndexBuffer; - DXGI_FORMAT idxFmt = curRS->IA.IndexFormat; - UINT idxOffs = curRS->IA.IndexOffset; - bool index16 = (idxFmt == DXGI_FORMAT_R16_UINT); + bool index16 = (ifmt == DXGI_FORMAT_R16_UINT); UINT bytesize = index16 ? 2 : 4; - if(stage == eMeshDataStage_VSIn) - { - m_HighlightCache.data = GetBufferData(cfg.position.buf, 0, 0); - m_HighlightCache.topo = curRS->IA.Topo; - idxOffs += drawcall->indexOffset*bytesize; - } - else - { - MeshFormat postvs = GetPostVSBuffers(frameID, events.back(), stage); - m_HighlightCache.data = GetBufferData(postvs.buf, 0, 0); + m_HighlightCache.data = GetBufferData(cfg.position.buf, 0, 0); + m_HighlightCache.topo = topo; - const PostVSData::StageData &stagedata = GetPostVSBuffers(frameID, events.back()).GetStage(stage); - - m_HighlightCache.topo = stagedata.topo; - idxBuf = stagedata.idxBuf; - idxFmt = stagedata.idxFmt; - idxOffs = 0; - index16 = (idxFmt == DXGI_FORMAT_R16_UINT); - bytesize = index16 ? 2 : 4; - } - - if((drawcall->flags & eDraw_UseIBuffer) == 0 || stage == eMeshDataStage_GSOut) + if(ibuf == NULL || stage == eMeshDataStage_GSOut) { m_HighlightCache.indices.clear(); m_HighlightCache.useidx = false; @@ -5020,12 +4881,12 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve { m_HighlightCache.useidx = true; - vector idxdata = GetBufferData(idxBuf, idxOffs, drawcall->numIndices*bytesize); + vector idxdata = GetBufferData(cfg.position.idxbuf, ioffs, cfg.position.numVerts*bytesize); uint16_t *idx16 = (uint16_t *)&idxdata[0]; uint32_t *idx32 = (uint32_t *)&idxdata[0]; - uint32_t numIndices = RDCMIN(drawcall->numIndices, uint32_t(idxdata.size()/bytesize)); + uint32_t numIndices = RDCMIN(cfg.position.numVerts, uint32_t(idxdata.size()/bytesize)); m_HighlightCache.indices.resize(numIndices); @@ -5042,8 +4903,6 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve byte *dataEnd = data + m_HighlightCache.data.size(); data += cfg.position.offset; // to start of position data - if(stage == eMeshDataStage_VSIn) - data += drawcall->vertexOffset*cfg.position.stride; // to first vertex /////////////////////////////////////////////////////////////// // vectors to be set from buffers, depending on topology @@ -5197,7 +5056,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve // Triangle strip with adjacency is the most complex topology, as // we need to handle the ends separately where the pattern breaks. - uint32_t numidx = drawcall->numIndices; + uint32_t numidx = cfg.position.numVerts; if(numidx < 6) { diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index 36c28a87c..de3bd2527 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -134,7 +134,7 @@ class D3D11DebugManager void TimeDrawcalls(rdctype::array &arr); void RenderText(float x, float y, const char *textfmt, ...); - void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg); + void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg); ID3D11Buffer *MakeCBuffer(float *data, size_t size); @@ -299,9 +299,8 @@ class D3D11DebugManager // mesh, not jumping back and forth much between meshes. struct HighlightCache { - HighlightCache() : EID(0), buf(), stage(eMeshDataStage_Unknown), useidx(false) {} + HighlightCache() : EID(0), stage(eMeshDataStage_Unknown), useidx(false) {} uint32_t EID; - ResourceId buf; MeshDataStage stage; bool useidx; D3D11_PRIMITIVE_TOPOLOGY topo; diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index abca9ac34..7997322a4 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -1290,9 +1290,9 @@ void D3D11Replay::TimeDrawcalls(rdctype::array &arr) return m_pDevice->GetDebugManager()->TimeDrawcalls(arr); } -void D3D11Replay::RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) +void D3D11Replay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg) { - return m_pDevice->GetDebugManager()->RenderMesh(frameID, events, cfg); + return m_pDevice->GetDebugManager()->RenderMesh(frameID, eventID, secondaryDraws, cfg); } void D3D11Replay::BuildTargetShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors) diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index 20c2ccc54..625f03f4a 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(uint32_t frameID, const vector &events, MeshDisplay cfg); + void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg); bool RenderTexture(TextureDisplay cfg); diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index 55eb9d1f4..487ae179d 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -1450,7 +1450,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl return m_pDriver->GetResourceManager()->GetID(TextureRes(ctx, DebugData.overlayTex)); } -void GLReplay::RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) +void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg) { #if 0 WrappedOpenGL &gl = *m_pDriver; diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 7ac3b010f..dfa70964d 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -97,7 +97,7 @@ class GLReplay : public IReplayDriver void TimeDrawcalls(rdctype::array &arr); - void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg); + void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, 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); diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index 93c30cc99..d2d74d913 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -130,7 +130,7 @@ class IReplayDriver : public IRemoteDriver virtual ResourceId CreateProxyTexture(FetchTexture templateTex) = 0; virtual void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize) = 0; - virtual void RenderMesh(uint32_t frameID, const vector &events, MeshDisplay cfg) = 0; + virtual void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, 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_output.cpp b/renderdoc/replay/replay_output.cpp index 6a9c4146e..45497a900 100644 --- a/renderdoc/replay/replay_output.cpp +++ b/renderdoc/replay/replay_output.cpp @@ -541,15 +541,6 @@ void ReplayOutput::DisplayMesh() if(m_RenderData.meshDisplay.type == eMeshDataStage_Unknown) return; if((draw->flags & eDraw_Drawcall) == 0) return; - 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) { m_pDevice->ReplayLog(m_FrameID, 0, m_EventID, eReplay_WithoutDraw); @@ -561,16 +552,33 @@ void ReplayOutput::DisplayMesh() 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)); - - RDCASSERT(!events.empty()); m_pDevice->ClearOutputWindowDepth(m_MainOutput.outputID, 1.0f, 0); MeshDisplay mesh = m_RenderData.meshDisplay; mesh.position.buf = m_pDevice->GetLiveID(mesh.position.buf); + mesh.position.idxbuf = m_pDevice->GetLiveID(mesh.position.idxbuf); mesh.second.buf = m_pDevice->GetLiveID(mesh.second.buf); + mesh.second.idxbuf = m_pDevice->GetLiveID(mesh.second.idxbuf); + + vector secondaryDraws; + + if(m_RenderData.meshDisplay.type != eMeshDataStage_VSIn && + !m_RenderData.meshDisplay.thisDrawOnly) + { + mesh.position.unproject = true; + mesh.second.unproject = true; - m_pDevice->RenderMesh(m_FrameID, events, mesh); + for(size_t i=0; i < passEvents.size(); i++) + { + // get the 'most final' stage + MeshFormat fmt = m_pDevice->GetPostVSBuffers(m_FrameID, passEvents[i], eMeshDataStage_GSOut); + if(fmt.buf == ResourceId()) fmt = m_pDevice->GetPostVSBuffers(m_FrameID, passEvents[i], eMeshDataStage_VSOut); + secondaryDraws.push_back(fmt); + } + } + + m_pDevice->RenderMesh(m_FrameID, m_EventID, secondaryDraws, mesh); } diff --git a/renderdocui/Code/CommonPipelineState.cs b/renderdocui/Code/CommonPipelineState.cs index cab4da32f..2b3bada3c 100644 --- a/renderdocui/Code/CommonPipelineState.cs +++ b/renderdocui/Code/CommonPipelineState.cs @@ -519,6 +519,32 @@ namespace renderdocui.Code return null; } + public ResourceId GetDepthTarget() + { + if (LogLoaded) + { + if (IsLogD3D11) + return m_D3D11.m_OM.DepthTarget.Resource; + else if (IsLogGL) + return m_GL.m_FB.m_DrawFBO.Depth; + } + + return ResourceId.Null; + } + + public ResourceId GetStencilTarget() + { + if (LogLoaded) + { + if (IsLogD3D11) + return m_D3D11.m_OM.DepthTarget.Resource; + else if (IsLogGL) + return m_GL.m_FB.m_DrawFBO.Stencil; + } + + return ResourceId.Null; + } + public ResourceId[] GetOutputTargets() { if (LogLoaded) diff --git a/renderdocui/Interop/FetchInfo.cs b/renderdocui/Interop/FetchInfo.cs index 6f9a510e3..519e1599a 100644 --- a/renderdocui/Interop/FetchInfo.cs +++ b/renderdocui/Interop/FetchInfo.cs @@ -362,9 +362,10 @@ namespace renderdoc public struct MeshFormat { public ResourceId idxbuf; + public UInt32 idxoffs; public UInt32 idxByteWidth; - public ResourceId buf; + public ResourceId buf; public UInt32 offset; public UInt32 stride; @@ -376,6 +377,7 @@ namespace renderdoc public bool showAlpha; public PrimitiveTopology topo; + public UInt32 numVerts; public bool unproject; public float nearPlane; diff --git a/renderdocui/Windows/BufferViewer.cs b/renderdocui/Windows/BufferViewer.cs index 09f3f07d9..40522f8fb 100644 --- a/renderdocui/Windows/BufferViewer.cs +++ b/renderdocui/Windows/BufferViewer.cs @@ -86,6 +86,8 @@ namespace renderdocui.Windows public uint IndexCount = 0; public uint IndexAdd = 0; + public MeshFormat PostVS; + public PrimitiveTopology Topology = PrimitiveTopology.Unknown; public byte[][] Buffers = null; @@ -475,6 +477,8 @@ namespace renderdocui.Windows UI_SetRowsData(MeshDataStage.VSOut, contentsVSOut, 0); if (m_GSOut.m_Input != null) UI_SetRowsData(MeshDataStage.GSOut, contentsGSOut, 0); + + camGuess_PropChanged(); })); }); } @@ -579,6 +583,8 @@ namespace renderdocui.Windows if (m_GSOut.m_Input != null) UI_SetRowsData(MeshDataStage.GSOut, contentsGSOut, horizscroll[2]); + camGuess_PropChanged(); + render.Invalidate(); })); }); @@ -840,22 +846,22 @@ namespace renderdocui.Windows if (type != MeshDataStage.VSIn) { - var postvs = r.GetPostVSData(type); + ret.PostVS = r.GetPostVSData(type); ret.Buffers = new byte[1][]; - if (postvs.buf == ResourceId.Null) + if (ret.PostVS.buf == ResourceId.Null) { ret.IndexCount = 0; ret.Topology = PrimitiveTopology.Unknown; } else { - ret.Buffers[0] = r.GetBufferData(postvs.buf, 0, 0); + ret.Buffers[0] = r.GetBufferData(ret.PostVS.buf, 0, 0); - ret.Topology = postvs.topo; + ret.Topology = ret.PostVS.topo; - ret.IndexCount = (uint)ret.Buffers[0].Length / postvs.stride; + ret.IndexCount = (uint)ret.Buffers[0].Length / ret.PostVS.stride; uint stride = 0; foreach (var f in input.BufferFormats) @@ -867,7 +873,7 @@ namespace renderdocui.Windows ret.Indices = null; - if (postvs.buf != ResourceId.Null && type == MeshDataStage.VSOut && + if (ret.PostVS.buf != ResourceId.Null && type == MeshDataStage.VSOut && (input.Drawcall.flags & DrawcallFlags.UseIBuffer) > 0 && input.IndexBuffer != ResourceId.Null) { ret.IndexCount = input.Drawcall.numIndices; @@ -2197,32 +2203,87 @@ namespace renderdocui.Windows { var ui = GetUIState(m_MeshDisplay.type); + // set position data etc from postvs if relevant + // also need to bake in drawcall offsets etc + // set numVerts from drawcall or postvs data + if (ui.m_Input == null || ui.m_Input.BufferFormats == null || CurPosElement == -1 || CurPosElement >= ui.m_Input.BufferFormats.Length) { + m_MeshDisplay.position.idxbuf = ResourceId.Null; + m_MeshDisplay.position.idxoffs = 0; + m_MeshDisplay.position.idxByteWidth = 0; + m_MeshDisplay.position.buf = ResourceId.Null; m_MeshDisplay.position.offset = 0; m_MeshDisplay.position.stride = 0; - m_MeshDisplay.position.compByteWidth = 0; + m_MeshDisplay.position.compCount = 0; + m_MeshDisplay.position.compByteWidth = 0; m_MeshDisplay.position.compType = FormatComponentType.None; m_MeshDisplay.position.specialFormat = SpecialFormat.Unknown; + m_MeshDisplay.position.showAlpha = false; + + m_MeshDisplay.position.topo = PrimitiveTopology.Unknown; + m_MeshDisplay.position.numVerts = 0; + + m_MeshDisplay.position.unproject = false; + // near and far plane handled elsewhere } else { FormatElement pos = ui.m_Input.BufferFormats[CurPosElement]; - m_MeshDisplay.position.buf = m_VSIn.m_Input.Buffers[pos.buffer]; - m_MeshDisplay.position.offset = pos.offset + ui.m_Input.Offsets[pos.buffer]; - m_MeshDisplay.position.stride = ui.m_Input.Strides[pos.buffer]; - m_MeshDisplay.position.compByteWidth = pos.format.compByteWidth; + m_MeshDisplay.position.idxbuf = ResourceId.Null; + m_MeshDisplay.position.idxoffs = 0; + m_MeshDisplay.position.idxByteWidth = 0; + + m_MeshDisplay.position.buf = ResourceId.Null; + m_MeshDisplay.position.offset = 0; + m_MeshDisplay.position.stride = 0; + m_MeshDisplay.position.compCount = pos.format.compCount; + m_MeshDisplay.position.compByteWidth = pos.format.compByteWidth; m_MeshDisplay.position.compType = pos.format.compType; m_MeshDisplay.position.specialFormat = pos.format.special ? pos.format.specialFormat : SpecialFormat.Unknown; + m_MeshDisplay.position.showAlpha = false; + m_MeshDisplay.position.topo = PrimitiveTopology.Unknown; + m_MeshDisplay.position.numVerts = 0; + + if (ui.m_Stage == MeshDataStage.VSIn && ui.m_Input.Drawcall != null) + { + m_MeshDisplay.position.idxbuf = m_VSIn.m_Input.IndexBuffer; + m_MeshDisplay.position.idxoffs = m_VSIn.m_Input.IndexOffset + + ui.m_Input.Drawcall.indexOffset * ui.m_Input.Drawcall.indexByteWidth; + m_MeshDisplay.position.idxByteWidth = ui.m_Input.Drawcall.indexByteWidth; + + m_MeshDisplay.position.buf = m_VSIn.m_Input.Buffers[pos.buffer]; + m_MeshDisplay.position.offset = pos.offset + ui.m_Input.Offsets[pos.buffer] + + ui.m_Input.Drawcall.vertexOffset * m_MeshDisplay.position.stride; + m_MeshDisplay.position.stride = ui.m_Input.Strides[pos.buffer]; + + m_MeshDisplay.position.topo = ui.m_Input.Drawcall.topology; + m_MeshDisplay.position.numVerts = ui.m_Input.Drawcall.numIndices; + } + else if (ui.m_Stage != MeshDataStage.VSIn && ui.m_Data != null && ui.m_Data.PostVS.buf != ResourceId.Null) + { + m_MeshDisplay.position.idxbuf = ui.m_Data.PostVS.idxbuf; + m_MeshDisplay.position.idxoffs = ui.m_Input.Drawcall.indexOffset * ui.m_Data.PostVS.idxByteWidth; + m_MeshDisplay.position.idxByteWidth = ui.m_Data.PostVS.idxByteWidth; + + m_MeshDisplay.position.buf = ui.m_Data.PostVS.buf; + m_MeshDisplay.position.offset = pos.offset; + m_MeshDisplay.position.stride = ui.m_Data.PostVS.stride; + + m_MeshDisplay.position.topo = ui.m_Data.PostVS.topo; + m_MeshDisplay.position.numVerts = ui.m_Data.PostVS.numVerts; + } + m_MeshDisplay.position.unproject = false; + // near and far plane handled elsewhere if ((ui.m_Stage == MeshDataStage.VSOut && !m_Core.CurPipelineState.IsTessellationEnabled) || ui.m_Stage == MeshDataStage.GSOut) { @@ -2233,27 +2294,50 @@ namespace renderdocui.Windows if (ui.m_Input == null || ui.m_Input.BufferFormats == null || CurSecondElement == -1 || CurSecondElement >= ui.m_Input.BufferFormats.Length) { + m_MeshDisplay.secondary.idxbuf = ResourceId.Null; + m_MeshDisplay.secondary.idxoffs = 0; + m_MeshDisplay.secondary.idxByteWidth = 0; + m_MeshDisplay.secondary.buf = ResourceId.Null; m_MeshDisplay.secondary.offset = 0; m_MeshDisplay.secondary.stride = 0; - m_MeshDisplay.secondary.compByteWidth = 0; + m_MeshDisplay.secondary.compCount = 0; + m_MeshDisplay.secondary.compByteWidth = 0; m_MeshDisplay.secondary.compType = FormatComponentType.None; m_MeshDisplay.secondary.specialFormat = SpecialFormat.Unknown; + m_MeshDisplay.secondary.showAlpha = false; + + m_MeshDisplay.secondary.topo = PrimitiveTopology.Unknown; + m_MeshDisplay.secondary.numVerts = 0; + + m_MeshDisplay.secondary.unproject = false; } else { FormatElement tex = ui.m_Input.BufferFormats[CurSecondElement]; - m_MeshDisplay.secondary.buf = m_VSIn.m_Input.Buffers[tex.buffer]; - m_MeshDisplay.secondary.offset = tex.offset + ui.m_Input.Offsets[tex.buffer]; - m_MeshDisplay.secondary.stride = ui.m_Input.Strides[tex.buffer]; - m_MeshDisplay.secondary.compByteWidth = tex.format.compByteWidth; m_MeshDisplay.secondary.compCount = tex.format.compCount; + m_MeshDisplay.secondary.compByteWidth = tex.format.compByteWidth; m_MeshDisplay.secondary.compType = tex.format.compType; m_MeshDisplay.secondary.specialFormat = tex.format.special ? tex.format.specialFormat : SpecialFormat.Unknown; + m_MeshDisplay.secondary.showAlpha = CurSecondShowAlpha; + + if (ui.m_Stage == MeshDataStage.VSIn && ui.m_Input.Drawcall != null) + { + m_MeshDisplay.secondary.buf = m_VSIn.m_Input.Buffers[tex.buffer]; + m_MeshDisplay.secondary.offset = tex.offset + ui.m_Input.Offsets[tex.buffer] + + ui.m_Input.Drawcall.vertexOffset * m_MeshDisplay.position.stride; + m_MeshDisplay.secondary.stride = ui.m_Input.Strides[tex.buffer]; + } + else if (ui.m_Stage != MeshDataStage.VSIn && ui.m_Data != null && ui.m_Data.PostVS.buf != ResourceId.Null) + { + m_MeshDisplay.secondary.buf = ui.m_Data.PostVS.buf; + m_MeshDisplay.secondary.offset = tex.offset; + m_MeshDisplay.secondary.stride = ui.m_Data.PostVS.stride; + } } UI_UpdateAllColumns(); @@ -2263,50 +2347,61 @@ namespace renderdocui.Windows { m_MeshDisplay.ortho = matrixType.SelectedIndex == 1; - float fov; - if (float.TryParse(fovGuess.Text, out fov)) - { - m_MeshDisplay.fov = fov; - } + float fov = 90.0f; + float.TryParse(fovGuess.Text, out fov); + m_MeshDisplay.fov = fov; fovGuess.Text = m_MeshDisplay.fov.ToString("G"); + m_MeshDisplay.aspect = 1.0f; + // take a guess for the aspect ratio, for if the user hasn't overridden it + ResourceId depth = m_Core.CurPipelineState.GetDepthTarget(); + ResourceId[] targets = m_Core.CurPipelineState.GetOutputTargets(); - - float aspect = 0.0f; - if (aspectGuess.Text.Length > 0) + if (depth != ResourceId.Null || (targets != null && targets.Length > 0)) { - float.TryParse(aspectGuess.Text, out aspect); + foreach (var t in m_Core.CurTextures) + { + if (depth != ResourceId.Null && t.ID == depth) + { + m_MeshDisplay.aspect = (float)t.width / (float)t.height; + break; + } + if (depth == ResourceId.Null && targets != null && targets.Length > 0 && t.ID == targets[0]) + { + m_MeshDisplay.aspect = (float)t.width / (float)t.height; + break; + } + } } - m_MeshDisplay.aspect = aspect; + if (aspectGuess.Text.Length > 0 && float.TryParse(aspectGuess.Text, out m_MeshDisplay.aspect)) + aspectGuess.Text = m_MeshDisplay.aspect.ToString("G"); + else + aspectGuess.Text = ""; - aspectGuess.Text = aspect > 0.0f ? aspect.ToString("G") : ""; + // use estimates from post vs data (calculated from vertex position data) if the user + // hasn't overridden the values + m_MeshDisplay.position.nearPlane = 1.0f; + if (m_VSOut.m_Data != null && m_VSOut.m_Data.PostVS.buf != ResourceId.Null) + m_MeshDisplay.position.nearPlane = m_VSOut.m_Data.PostVS.nearPlane; + if (nearGuess.Text.Length > 0 && float.TryParse(nearGuess.Text, out m_MeshDisplay.position.nearPlane)) + nearGuess.Text = m_MeshDisplay.position.nearPlane.ToString("G"); + else + nearGuess.Text = ""; - float near = -float.MaxValue; - if (nearGuess.Text.Length > 0) - { - float.TryParse(nearGuess.Text, out near); - } + m_MeshDisplay.position.farPlane = 10.0f; - m_MeshDisplay.position.nearPlane = near; + if (m_VSOut.m_Data != null && m_VSOut.m_Data.PostVS.buf != ResourceId.Null) + m_MeshDisplay.position.farPlane = m_VSOut.m_Data.PostVS.farPlane; - nearGuess.Text = near > -float.MaxValue ? near.ToString("G") : ""; - - - - float far = -float.MaxValue; - if (farGuess.Text.Length > 0) - { - float.TryParse(farGuess.Text, out far); - } - - m_MeshDisplay.position.farPlane = far; - - farGuess.Text = far > -float.MaxValue ? far.ToString("G") : ""; + if (farGuess.Text.Length > 0 && float.TryParse(farGuess.Text, out m_MeshDisplay.position.farPlane)) + farGuess.Text = m_MeshDisplay.position.farPlane.ToString("G"); + else + farGuess.Text = ""; render.Invalidate(); }