Add 'show all instances' mode, and make colours consistent. Closes #248

This commit is contained in:
baldurk
2016-06-03 17:34:26 +02:00
parent e0d664f1b3
commit 947f7decb2
12 changed files with 144 additions and 61 deletions
+8
View File
@@ -59,6 +59,14 @@ You can also use this if the position data isn't detected in your inputs and you
Preview: Previewing the uv co-ordinates as colour on the mesh.
When displaying the post-projection output - typically the VS output, but possibly tessellation/geometry output - you can select how much data to display.
The dropdown above the mesh view will let you choose ``Only this draw``, ``Show previous instances``, ``Show all instances``, or ``Show whole pass``.
These let you narrow or expand the mesh outputs displayed. At minimum you will see the current draw - a specific instance, if the drawcall is an instanced draw. You can also display other instances in the same drawcall (either up to the selected instance, or all instances before or after the selected instance). Finally you can opt to display all other meshes up to the current draw in the same notional render pass.
The current draw is always dark tinted, instances within the same draw have a lighter red colour, and other drawcalls in the pass will be light grey.
Raw Buffer Viewer
-----------------
+5 -4
View File
@@ -50,6 +50,8 @@ struct MeshFormat
bool32 bgraOrder;
SpecialFormat specialFormat;
FloatVector meshColour;
bool showAlpha;
PrimitiveTopology topo;
@@ -71,16 +73,15 @@ struct MeshDisplay
bool32 ortho;
float fov, aspect;
bool32 thisDrawOnly;
bool32 showPrevInstances;
bool32 showAllInstances;
bool32 showWholePass;
uint32_t curInstance;
uint32_t highlightVert;
MeshFormat position;
MeshFormat second;
FloatVector prevMeshColour;
FloatVector currentMeshColour;
FloatVector minBounds;
FloatVector maxBounds;
bool32 showBBox;
+7 -1
View File
@@ -1310,6 +1310,7 @@ void Serialiser::Serialise(const char *name, MeshFormat &el)
Serialise("", el.compType);
Serialise("", el.bgraOrder);
Serialise("", el.specialFormat);
Serialise("", el.meshColour);
Serialise("", el.showAlpha);
Serialise("", el.topo);
Serialise("", el.numVerts);
@@ -1317,7 +1318,7 @@ void Serialiser::Serialise(const char *name, MeshFormat &el)
Serialise("", el.nearPlane);
Serialise("", el.farPlane);
SIZE_CHECK(MeshFormat, 88);
SIZE_CHECK(MeshFormat, 104);
}
template <>
@@ -1609,6 +1610,11 @@ string ToStrHelper<false, ReplayLogType>::Get(const ReplayLogType &el)
{
return "<...>";
}
template <>
string ToStrHelper<false, FloatVector>::Get(const FloatVector &el)
{
return "<...>";
}
#pragma endregion Plain - old data structures
+6 -8
View File
@@ -4773,9 +4773,6 @@ void D3D11DebugManager::RenderMesh(uint32_t eventID, const vector<MeshFormat> &s
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++)
{
@@ -4783,6 +4780,10 @@ void D3D11DebugManager::RenderMesh(uint32_t eventID, const vector<MeshFormat> &s
if(fmt.buf != ResourceId())
{
pixelData.WireframeColour = Vec3f(fmt.meshColour.x, fmt.meshColour.y, fmt.meshColour.z);
FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData,
sizeof(DebugPixelCBufferData));
m_pImmediateContext->IASetPrimitiveTopology(MakeD3D11PrimitiveTopology(fmt.topo));
auto it = WrappedID3D11Buffer::m_BufferList.find(fmt.buf);
@@ -4898,11 +4899,8 @@ void D3D11DebugManager::RenderMesh(uint32_t eventID, const vector<MeshFormat> &s
m_pImmediateContext->OMSetDepthStencilState(m_DebugRender.LEqualDepthState, 0);
pixelData.OutputDisplayFormat = MESHDISPLAY_SOLID;
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);
pixelData.WireframeColour =
Vec3f(cfg.position.meshColour.x, cfg.position.meshColour.y, cfg.position.meshColour.z);
FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData));
m_pImmediateContext->PSSetConstantBuffers(0, 1, &m_DebugRender.GenericPSCBuffer);
+3 -10
View File
@@ -3541,8 +3541,6 @@ void GLReplay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &secondaryD
if(!secondaryDraws.empty())
{
gl.glUniform4fv(colLoc, 1, &cfg.prevMeshColour.x);
gl.glUniform1ui(fmtLoc, MESHDISPLAY_SOLID);
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_LINE);
@@ -3558,6 +3556,8 @@ void GLReplay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &secondaryD
if(fmt.buf != ResourceId())
{
gl.glUniform4fv(colLoc, 1, &fmt.meshColour.x);
GLuint vb = m_pDriver->GetResourceManager()->GetCurrentResource(fmt.buf).name;
gl.glBindVertexBuffer(0, vb, (GLintptr)fmt.offset, fmt.stride);
@@ -3761,14 +3761,7 @@ void GLReplay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &secondaryD
// wireframe render
if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw || topo == eGL_PATCHES)
{
float wireCol[] = {0.0f, 0.0f, 0.0f, 1.0f};
if(!secondaryDraws.empty())
{
wireCol[0] = cfg.currentMeshColour.x;
wireCol[1] = cfg.currentMeshColour.y;
wireCol[2] = cfg.currentMeshColour.z;
}
gl.glUniform4fv(colLoc, 1, wireCol);
gl.glUniform4fv(colLoc, 1, &cfg.position.meshColour.x);
gl.glUniform1ui(fmtLoc, MESHDISPLAY_SOLID);
+2
View File
@@ -49,6 +49,8 @@ void VulkanDebugManager::GPUBuffer::Create(WrappedVulkan *driver, VkDevice dev,
totalsize = ringSize == 1 ? size : AlignUp(size, align) * ringSize;
curoffset = 0;
ringCount = ringSize;
VkBufferCreateInfo bufInfo = {
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, 0, totalsize, 0,
};
+3
View File
@@ -144,6 +144,7 @@ public:
void FillDescriptor(VkDescriptorBufferInfo &desc);
size_t GetRingCount() { return size_t(ringCount); }
void *Map(VkDeviceSize &bindoffset, VkDeviceSize usedsize = 0);
void *Map(uint32_t *bindoffset = NULL, VkDeviceSize usedsize = 0);
void Unmap();
@@ -159,6 +160,8 @@ public:
VkDeviceSize totalsize;
VkDeviceSize curoffset;
uint32_t ringCount;
WrappedVulkan *m_pDriver;
VkDevice device;
};
+58 -18
View File
@@ -1719,17 +1719,7 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &second
if(!secondaryDraws.empty())
{
uint32_t uboOffs = 0;
MeshUBOData *data = (MeshUBOData *)GetDebugManager()->m_MeshUBO.Map(&uboOffs);
data->mvp = ModelViewProj;
data->color = Vec4f(cfg.prevMeshColour.x, cfg.prevMeshColour.y, cfg.prevMeshColour.z,
cfg.prevMeshColour.w);
data->homogenousInput = cfg.position.unproject;
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
data->displayFormat = MESHDISPLAY_SOLID;
GetDebugManager()->m_MeshUBO.Unmap();
size_t mapsUsed = 0;
for(size_t i = 0; i < secondaryDraws.size(); i++)
{
@@ -1737,6 +1727,42 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &second
if(fmt.buf != ResourceId())
{
// TODO should move the color to a push constant so we don't have to map all the time
uint32_t uboOffs = 0;
MeshUBOData *data = (MeshUBOData *)GetDebugManager()->m_MeshUBO.Map(&uboOffs);
data->mvp = ModelViewProj;
data->color = Vec4f(fmt.meshColour.x, fmt.meshColour.y, fmt.meshColour.z, fmt.meshColour.w);
data->homogenousInput = cfg.position.unproject;
data->pointSpriteSize = Vec2f(0.0f, 0.0f);
data->displayFormat = MESHDISPLAY_SOLID;
GetDebugManager()->m_MeshUBO.Unmap();
mapsUsed++;
if(mapsUsed + 1 >= GetDebugManager()->m_MeshUBO.GetRingCount())
{
// flush and sync so we can use more maps
vt->CmdEndRenderPass(Unwrap(cmd));
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
mapsUsed = 0;
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport);
}
MeshDisplayPipelines secondaryCache =
GetDebugManager()->CacheMeshDisplayPipelines(secondaryDraws[i], secondaryDraws[i]);
@@ -1772,6 +1798,25 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &second
}
}
}
{
// flush and sync so we can use more maps
vt->CmdEndRenderPass(Unwrap(cmd));
vkr = vt->EndCommandBuffer(Unwrap(cmd));
RDCASSERTEQUAL(vkr, VK_SUCCESS);
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
cmd = m_pDriver->GetNextCmd();
vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
RDCASSERTEQUAL(vkr, VK_SUCCESS);
vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);
vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport);
}
}
MeshDisplayPipelines cache = GetDebugManager()->CacheMeshDisplayPipelines(cfg.position, cfg.second);
@@ -1857,13 +1902,8 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &second
if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw ||
cfg.position.topo >= eTopology_PatchList)
{
Vec4f wireCol = Vec4f(0.0f, 0.0f, 0.0f, 1.0f);
if(!secondaryDraws.empty())
{
wireCol.x = cfg.currentMeshColour.x;
wireCol.y = cfg.currentMeshColour.y;
wireCol.z = cfg.currentMeshColour.z;
}
Vec4f wireCol =
Vec4f(cfg.position.meshColour.x, cfg.position.meshColour.y, cfg.position.meshColour.z, 1.0f);
uint32_t uboOffs = 0;
MeshUBOData *data = (MeshUBOData *)GetDebugManager()->m_MeshUBO.Map(&uboOffs);
+31 -10
View File
@@ -106,7 +106,7 @@ bool ReplayOutput::SetTextureDisplay(const TextureDisplay &o)
bool ReplayOutput::SetMeshDisplay(const MeshDisplay &o)
{
if(o.thisDrawOnly != m_RenderData.meshDisplay.thisDrawOnly)
if(o.showWholePass != m_RenderData.meshDisplay.showWholePass)
m_OverlayDirty = true;
m_RenderData.meshDisplay = o;
m_MainOutput.dirty = true;
@@ -158,7 +158,7 @@ void ReplayOutput::RefreshOverlay()
m_pDevice->InitPostVSBuffers(draw->eventID);
if(!m_RenderData.meshDisplay.thisDrawOnly && !passEvents.empty())
if(!m_RenderData.meshDisplay.showWholePass && !passEvents.empty())
{
m_pDevice->InitPostVSBuffers(passEvents);
@@ -583,12 +583,23 @@ void ReplayOutput::DisplayMesh()
vector<MeshFormat> secondaryDraws;
if(m_RenderData.meshDisplay.type != eMeshDataStage_VSIn && !m_RenderData.meshDisplay.thisDrawOnly)
{
mesh.position.unproject = true;
mesh.second.unproject = true;
// we choose a pallette here so that the colours stay consistent (i.e the
// current draw is always the same colour), but also to indicate somewhat
// the relationship - ie. instances are closer in colour than other draws
// in the pass
for(size_t i = 0; i < passEvents.size(); i++)
// very slightly dark red
const FloatVector drawItself(0.06f, 0.0f, 0.0f, 1.0f);
// more desaturated/lighter, but still reddish
const FloatVector otherInstances(0.18f, 0.1f, 0.1f, 1.0f);
// lighter grey with blue tinge to contrast from main/instance draws
const FloatVector passDraws(0.2f, 0.2f, 0.25f, 1.0f);
if(m_RenderData.meshDisplay.type != eMeshDataStage_VSIn)
{
for(size_t i = 0; m_RenderData.meshDisplay.showWholePass && i < passEvents.size(); i++)
{
FetchDrawcall *d = m_pRenderer->GetDrawcallByEID(passEvents[i], m_LastDeferredEvent);
@@ -601,6 +612,8 @@ void ReplayOutput::DisplayMesh()
if(fmt.buf == ResourceId())
fmt = m_pDevice->GetPostVSBuffers(passEvents[i], inst, eMeshDataStage_VSOut);
fmt.meshColour = passDraws;
// if unproject is marked, this output had a 'real' system position output
if(fmt.unproject)
secondaryDraws.push_back(fmt);
@@ -611,15 +624,21 @@ void ReplayOutput::DisplayMesh()
// draw previous instances in the current drawcall
if(draw->flags & eDraw_Instanced)
{
for(uint32_t inst = 0;
inst < RDCMAX(1U, draw->numInstances) && inst < m_RenderData.meshDisplay.curInstance;
inst++)
uint32_t maxInst = 0;
if(m_RenderData.meshDisplay.showPrevInstances)
maxInst = RDCMAX(1U, m_RenderData.meshDisplay.curInstance);
if(m_RenderData.meshDisplay.showAllInstances)
maxInst = RDCMAX(1U, draw->numInstances);
for(uint32_t inst = 0; inst < maxInst; inst++)
{
// get the 'most final' stage
MeshFormat fmt = m_pDevice->GetPostVSBuffers(draw->eventID, inst, eMeshDataStage_GSOut);
if(fmt.buf == ResourceId())
fmt = m_pDevice->GetPostVSBuffers(draw->eventID, inst, eMeshDataStage_VSOut);
fmt.meshColour = otherInstances;
// if unproject is marked, this output had a 'real' system position output
if(fmt.unproject)
secondaryDraws.push_back(fmt);
@@ -627,6 +646,8 @@ void ReplayOutput::DisplayMesh()
}
}
mesh.position.meshColour = drawItself;
m_pDevice->RenderMesh(m_EventID, secondaryDraws, mesh);
}
+5 -4
View File
@@ -601,6 +601,8 @@ namespace renderdoc
public bool bgraOrder;
public SpecialFormat specialFormat;
public FloatVector meshColour;
public bool showAlpha;
public PrimitiveTopology topo;
@@ -622,16 +624,15 @@ namespace renderdoc
public float fov = 90.0f;
public float aspect = 0.0f;
public bool thisDrawOnly = true;
public bool showPrevInstances = false;
public bool showAllInstances = false;
public bool showWholePass = false;
public UInt32 curInstance = 0;
public UInt32 highlightVert;
public MeshFormat position;
public MeshFormat secondary;
public FloatVector prevMeshColour = new FloatVector();
public FloatVector currentMeshColour = new FloatVector();
public FloatVector minBounds = new FloatVector();
public FloatVector maxBounds = new FloatVector();
public bool showBBox = false;
+3 -1
View File
@@ -463,9 +463,11 @@
this.drawRange.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.drawRange.Items.AddRange(new object[] {
"Only this draw",
"Show previous instances",
"Show all instances",
"Show whole pass"});
this.drawRange.Name = "drawRange";
this.drawRange.Size = new System.Drawing.Size(121, 25);
this.drawRange.Size = new System.Drawing.Size(140, 25);
this.drawRange.SelectedIndexChanged += new System.EventHandler(this.drawRange_SelectedIndexChanged);
//
// toolStripSeparator4
+13 -5
View File
@@ -303,12 +303,11 @@ namespace renderdocui.Windows
m_MeshDisplay.solidShadeMode = SolidShadeMode.None;
solidShading.SelectedIndex = 0;
m_MeshDisplay.thisDrawOnly = true;
m_MeshDisplay.showPrevInstances = false;
m_MeshDisplay.showAllInstances = false;
m_MeshDisplay.showWholePass = false;
drawRange.SelectedIndex = 0;
m_MeshDisplay.currentMeshColour = new FloatVector(1, 0, 0, 1);
m_MeshDisplay.prevMeshColour = new FloatVector(0, 0, 0, 1);
if (m_Arcball != null)
m_Arcball.Camera.Shutdown();
if (m_Flycam != null)
@@ -2990,7 +2989,16 @@ namespace renderdocui.Windows
private void drawRange_SelectedIndexChanged(object sender, EventArgs e)
{
m_MeshDisplay.thisDrawOnly = (drawRange.SelectedIndex == 0);
/*
"Only this draw",
"Show previous instances",
"Show all instances",
"Show whole pass"
*/
m_MeshDisplay.showPrevInstances = (drawRange.SelectedIndex >= 1);
m_MeshDisplay.showAllInstances = (drawRange.SelectedIndex >= 2);
m_MeshDisplay.showWholePass = (drawRange.SelectedIndex >= 3);
render.Invalidate();
}