mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-18 21:47:13 +00:00
Add 'show all instances' mode, and make colours consistent. Closes #248
This commit is contained in:
@@ -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
|
||||
-----------------
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user