mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
Handle vtx highlights outside UI, for complex topologies. Refs #85
This commit is contained in:
@@ -42,8 +42,14 @@ struct MeshDisplay
|
||||
|
||||
bool32 thisDrawOnly;
|
||||
|
||||
bool32 showVerts;
|
||||
FloatVector hilightVerts[3];
|
||||
uint32_t highlightVert;
|
||||
ResourceId positionBuf;
|
||||
uint32_t positionOffset;
|
||||
uint32_t positionStride;
|
||||
uint32_t positionCompCount;
|
||||
uint32_t positionCompByteWidth;
|
||||
FormatComponentType positionCompType;
|
||||
SpecialFormat positionFormat;
|
||||
|
||||
FloatVector prevMeshColour;
|
||||
FloatVector currentMeshColour;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "maths/camera.h"
|
||||
#include "data/resource.h"
|
||||
#include "common/string_utils.h"
|
||||
#include "maths/formatpacking.h"
|
||||
|
||||
#include "driver/d3d11/d3d11_resources.h"
|
||||
|
||||
@@ -1480,7 +1481,7 @@ bool D3D11DebugManager::InitStreamOut()
|
||||
D3D11_BUFFER_DESC bdesc;
|
||||
bdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bdesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
bdesc.ByteWidth = sizeof(Vec4f)*4;
|
||||
bdesc.ByteWidth = sizeof(Vec4f)*16;
|
||||
bdesc.MiscFlags = 0;
|
||||
bdesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
|
||||
@@ -2172,15 +2173,16 @@ vector<byte> D3D11DebugManager::GetBufferData(ID3D11Buffer *buffer, uint32_t off
|
||||
D3D11_BUFFER_DESC desc;
|
||||
buffer->GetDesc(&desc);
|
||||
|
||||
if(len == 0)
|
||||
{
|
||||
len = desc.ByteWidth-offset;
|
||||
}
|
||||
|
||||
if(len > 0 && offset+len > desc.ByteWidth)
|
||||
{
|
||||
RDCWARN("Attempting to read off the end of the array. Will be clamped");
|
||||
len = RDCMIN(len, desc.ByteWidth-offset);
|
||||
}
|
||||
else if(len == 0)
|
||||
{
|
||||
len = desc.ByteWidth;
|
||||
}
|
||||
|
||||
uint32_t outOffs = 0;
|
||||
|
||||
@@ -3870,7 +3872,8 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// force to 4 components, as we need it, and store its offset
|
||||
if(a.find("SV_POSITION") != string::npos || sign.systemValue == eAttr_Position || posoffset == ~0U)
|
||||
{
|
||||
decl.ComponentCount = 4;
|
||||
if(a.find("SV_POSITION") != string::npos || sign.systemValue == eAttr_Position)
|
||||
decl.ComponentCount = 4;
|
||||
|
||||
posoffset = stride;
|
||||
numPosComponents = decl.ComponentCount;
|
||||
@@ -4027,6 +4030,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
if(numPrims.NumPrimitivesWritten == 0)
|
||||
{
|
||||
m_PostVSData[idx] = PostVSData();
|
||||
SAFE_RELEASE(idxBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4036,6 +4040,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Failed to map sobuffer %08x", hr);
|
||||
SAFE_RELEASE(idxBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4054,6 +4059,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
RDCERR("Generated output data too large: %08x", bufferDesc.ByteWidth);
|
||||
|
||||
m_pImmediateContext->Unmap(m_SOStagingBuffer, 0);
|
||||
SAFE_RELEASE(idxBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4073,6 +4079,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
RDCERR("Failed to create postvs pos buffer %08x", hr);
|
||||
|
||||
m_pImmediateContext->Unmap(m_SOStagingBuffer, 0);
|
||||
SAFE_RELEASE(idxBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4193,7 +4200,8 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// force to 4 components, as we need it, and store its offset
|
||||
if(a.find("SV_POSITION") != string::npos || sign.systemValue == eAttr_Position || posoffset == ~0U)
|
||||
{
|
||||
decl.ComponentCount = 4;
|
||||
if(a.find("SV_POSITION") != string::npos || sign.systemValue == eAttr_Position)
|
||||
decl.ComponentCount = 4;
|
||||
|
||||
posoffset = stride;
|
||||
numPosComponents = decl.ComponentCount;
|
||||
@@ -4410,6 +4418,99 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
}
|
||||
}
|
||||
|
||||
FloatVector D3D11DebugManager::InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool &valid)
|
||||
{
|
||||
FloatVector ret(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
if(m_HighlightCache.useidx)
|
||||
{
|
||||
if(vert >= (uint32_t)m_HighlightCache.indices.size())
|
||||
{
|
||||
valid = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
vert = m_HighlightCache.indices[vert];
|
||||
}
|
||||
|
||||
data += vert*cfg.positionStride;
|
||||
|
||||
float *out = &ret.x;
|
||||
|
||||
ResourceFormat fmt;
|
||||
fmt.compByteWidth = cfg.positionCompByteWidth;
|
||||
fmt.compCount = cfg.positionCompCount;
|
||||
fmt.compType = cfg.positionCompType;
|
||||
|
||||
if(cfg.positionFormat == eSpecial_R10G10B10A2)
|
||||
{
|
||||
if(data+4 >= end)
|
||||
{
|
||||
valid = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Vec4f v = ConvertFromR10G10B10A2(*(uint32_t *)data);
|
||||
ret.x = v.x;
|
||||
ret.y = v.y;
|
||||
ret.z = v.z;
|
||||
ret.w = v.w;
|
||||
return ret;
|
||||
}
|
||||
else if(cfg.positionFormat == eSpecial_R11G11B10)
|
||||
{
|
||||
if(data+4 >= end)
|
||||
{
|
||||
valid = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Vec3f v = ConvertFromR11G11B10(*(uint32_t *)data);
|
||||
ret.x = v.x;
|
||||
ret.y = v.y;
|
||||
ret.z = v.z;
|
||||
return ret;
|
||||
}
|
||||
else if(cfg.positionFormat == eSpecial_B8G8R8A8)
|
||||
{
|
||||
if(data+4 >= end)
|
||||
{
|
||||
valid = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
fmt.compByteWidth = 1;
|
||||
fmt.compCount = 4;
|
||||
fmt.compType = eCompType_UNorm;
|
||||
}
|
||||
|
||||
if(data + cfg.positionCompCount*cfg.positionCompByteWidth >= end)
|
||||
{
|
||||
valid = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(uint32_t i=0; i < cfg.positionCompCount; i++)
|
||||
{
|
||||
*out = ConvertComponent(fmt, data);
|
||||
|
||||
data += cfg.positionCompByteWidth;
|
||||
out++;
|
||||
}
|
||||
|
||||
if(cfg.positionFormat == eSpecial_B8G8R8A8)
|
||||
{
|
||||
FloatVector reversed;
|
||||
reversed.x = ret.x;
|
||||
reversed.y = ret.y;
|
||||
reversed.z = ret.z;
|
||||
reversed.w = ret.w;
|
||||
return reversed;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector<uint32_t> &events, MeshDisplay cfg)
|
||||
{
|
||||
DebugVertexCBuffer vertexData;
|
||||
@@ -4823,79 +4924,489 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector<uint32_t> &eve
|
||||
m_pImmediateContext->Draw(2, 4);
|
||||
}
|
||||
|
||||
if(cfg.showVerts)
|
||||
{
|
||||
// if data is from post transform, it will be in clipspace
|
||||
if((cfg.type != eMeshDataStage_VSIn && pipeState.m_HS.Shader == ResourceId()) ||
|
||||
(cfg.type == eMeshDataStage_GSOut && pipeState.m_HS.Shader != ResourceId()))
|
||||
if(cfg.highlightVert != ~0U)
|
||||
{
|
||||
const FetchDrawcall *drawcall = m_WrappedDevice->GetDrawcall(frameID, events.back());
|
||||
|
||||
MeshDataStage stage = cfg.type;
|
||||
|
||||
if(cfg.type == eMeshDataStage_VSOut && pipeState.m_HS.Shader != ResourceId())
|
||||
stage = eMeshDataStage_VSIn;
|
||||
|
||||
if(m_HighlightCache.EID != events.back() || m_HighlightCache.buf != cfg.positionBuf || stage != m_HighlightCache.stage)
|
||||
{
|
||||
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(guessProjInv));
|
||||
m_pImmediateContext->VSSetShader(m_DebugRender.WireframeHomogVS, NULL, 0);
|
||||
m_pImmediateContext->IASetInputLayout(m_DebugRender.GenericHomogLayout);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexData.ModelViewProj = projMat.Mul(camMat);
|
||||
m_pImmediateContext->IASetInputLayout(m_DebugRender.GenericLayout);
|
||||
m_HighlightCache.EID = events.back();
|
||||
m_HighlightCache.buf = cfg.positionBuf;
|
||||
m_HighlightCache.stage = stage;
|
||||
|
||||
if(cfg.type == eMeshDataStage_VSIn)
|
||||
{
|
||||
m_HighlightCache.data = GetBufferData(cfg.positionBuf, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
PostVSMeshData postvs = GetPostVSBuffers(frameID, events.back(), stage);
|
||||
m_HighlightCache.data.resize(postvs.buf.count);
|
||||
memcpy(&m_HighlightCache.data[0], postvs.buf.elems, postvs.buf.count);
|
||||
}
|
||||
|
||||
if((drawcall->flags & eDraw_UseIBuffer) == 0)
|
||||
{
|
||||
m_HighlightCache.indices.clear();
|
||||
m_HighlightCache.useidx = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HighlightCache.useidx = true;
|
||||
|
||||
ID3D11Buffer *idxBuf = curRS->IA.IndexBuffer;
|
||||
DXGI_FORMAT idxFmt = curRS->IA.IndexFormat;
|
||||
UINT idxOffs = curRS->IA.IndexOffset;
|
||||
|
||||
bool index16 = (idxFmt == DXGI_FORMAT_R16_UINT);
|
||||
UINT bytesize = index16 ? 2 : 4;
|
||||
|
||||
vector<byte> idxdata = GetBufferData(idxBuf, idxOffs + drawcall->indexOffset*bytesize, drawcall->numIndices*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));
|
||||
|
||||
m_HighlightCache.indices.resize(numIndices);
|
||||
|
||||
for(uint32_t i=0; i < numIndices; i++)
|
||||
m_HighlightCache.indices[i] = index16 ? uint32_t(idx16[i]) : idx32[i];
|
||||
}
|
||||
}
|
||||
|
||||
FillCBuffer(m_DebugRender.GenericVSCBuffer, (float *)&vertexData, sizeof(DebugVertexCBuffer));
|
||||
uint32_t idx = cfg.highlightVert;
|
||||
|
||||
pixelData.WireframeColour = Vec3f(1.0f, 0.0f, 0.0f);
|
||||
FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData));
|
||||
byte *data = &m_HighlightCache.data[0]; // buffer start
|
||||
byte *dataEnd = data + m_HighlightCache.data.size();
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
data += cfg.positionOffset; // to start of position data
|
||||
data += drawcall->vertexOffset*cfg.positionStride; // to first vertex
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// vectors to be set from buffers, depending on topology
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
bool valid = true;
|
||||
|
||||
hr = m_pImmediateContext->Map(m_TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
// this vert (blue dot, required)
|
||||
FloatVector activeVertex;
|
||||
|
||||
// primitive this vert is a part of (red prim, optional)
|
||||
vector<FloatVector> activePrim;
|
||||
|
||||
if(FAILED(hr))
|
||||
// for patch lists, to show other verts in patch (green dots, optional)
|
||||
// for non-patch lists, we use the activePrim and adjacentPrimVertices
|
||||
// to show what other verts are related
|
||||
vector<FloatVector> inactiveVertices;
|
||||
|
||||
// adjacency (line or tri, strips or lists) (green prims, optional)
|
||||
// will be N*M long, N adjacent prims of M verts each. M = primSize below
|
||||
vector<FloatVector> adjacentPrimVertices;
|
||||
|
||||
D3D11_PRIMITIVE_TOPOLOGY primTopo = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; // tri or line list
|
||||
uint32_t primSize = 3; // number of verts per primitive
|
||||
|
||||
if(pipeState.m_IA.Topology == eTopology_LineList ||
|
||||
pipeState.m_IA.Topology == eTopology_LineList_Adj ||
|
||||
pipeState.m_IA.Topology == eTopology_LineStrip ||
|
||||
pipeState.m_IA.Topology == eTopology_LineStrip_Adj)
|
||||
{
|
||||
RDCERR("Failde to map m_TriHighlightHelper %08x", hr);
|
||||
return;
|
||||
primSize = 2;
|
||||
primTopo = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
|
||||
}
|
||||
|
||||
activeVertex = InterpretVertex(data, idx, cfg, dataEnd, valid);
|
||||
|
||||
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx for
|
||||
// how primitive topologies are laid out
|
||||
if(pipeState.m_IA.Topology == eTopology_LineList)
|
||||
{
|
||||
uint32_t v = uint32_t(idx/2) * 2; // find first vert in primitive
|
||||
|
||||
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
|
||||
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
|
||||
}
|
||||
else if(pipeState.m_IA.Topology == eTopology_TriangleList)
|
||||
{
|
||||
uint32_t v = uint32_t(idx/3) * 3; // find first vert in primitive
|
||||
|
||||
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
|
||||
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
|
||||
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, valid));
|
||||
}
|
||||
else if(pipeState.m_IA.Topology == eTopology_LineList_Adj)
|
||||
{
|
||||
uint32_t v = uint32_t(idx/4) * 4; // find first vert in primitive
|
||||
|
||||
FloatVector vs[] = {
|
||||
InterpretVertex(data, v+0, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+1, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+2, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+3, cfg, dataEnd, valid),
|
||||
};
|
||||
|
||||
adjacentPrimVertices.push_back(vs[0]);
|
||||
adjacentPrimVertices.push_back(vs[1]);
|
||||
|
||||
adjacentPrimVertices.push_back(vs[2]);
|
||||
adjacentPrimVertices.push_back(vs[3]);
|
||||
|
||||
activePrim.push_back(vs[1]);
|
||||
activePrim.push_back(vs[2]);
|
||||
}
|
||||
else if(pipeState.m_IA.Topology == eTopology_TriangleList_Adj)
|
||||
{
|
||||
uint32_t v = uint32_t(idx/6) * 6; // find first vert in primitive
|
||||
|
||||
FloatVector vs[] = {
|
||||
InterpretVertex(data, v+0, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+1, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+2, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+3, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+4, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+5, cfg, dataEnd, valid),
|
||||
};
|
||||
|
||||
adjacentPrimVertices.push_back(vs[0]);
|
||||
adjacentPrimVertices.push_back(vs[1]);
|
||||
adjacentPrimVertices.push_back(vs[2]);
|
||||
|
||||
adjacentPrimVertices.push_back(vs[2]);
|
||||
adjacentPrimVertices.push_back(vs[3]);
|
||||
adjacentPrimVertices.push_back(vs[4]);
|
||||
|
||||
adjacentPrimVertices.push_back(vs[4]);
|
||||
adjacentPrimVertices.push_back(vs[5]);
|
||||
adjacentPrimVertices.push_back(vs[0]);
|
||||
|
||||
activePrim.push_back(vs[0]);
|
||||
activePrim.push_back(vs[2]);
|
||||
activePrim.push_back(vs[4]);
|
||||
}
|
||||
else if(pipeState.m_IA.Topology == eTopology_LineStrip)
|
||||
{
|
||||
// find first vert in primitive. In strips a vert isn't
|
||||
// in only one primitive, so we pick the first primitive
|
||||
// it's in. This means the first N points are in the first
|
||||
// primitive, and thereafter each point is in the next primitive
|
||||
uint32_t v = RDCMAX(idx, 1U) - 1;
|
||||
|
||||
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
|
||||
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
|
||||
}
|
||||
else if(pipeState.m_IA.Topology == eTopology_TriangleStrip)
|
||||
{
|
||||
// find first vert in primitive. In strips a vert isn't
|
||||
// in only one primitive, so we pick the first primitive
|
||||
// it's in. This means the first N points are in the first
|
||||
// primitive, and thereafter each point is in the next primitive
|
||||
uint32_t v = RDCMAX(idx, 2U) - 2;
|
||||
|
||||
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
|
||||
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
|
||||
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, valid));
|
||||
}
|
||||
else if(pipeState.m_IA.Topology == eTopology_LineStrip_Adj)
|
||||
{
|
||||
// find first vert in primitive. In strips a vert isn't
|
||||
// in only one primitive, so we pick the first primitive
|
||||
// it's in. This means the first N points are in the first
|
||||
// primitive, and thereafter each point is in the next primitive
|
||||
uint32_t v = RDCMAX(idx, 3U) - 3;
|
||||
|
||||
FloatVector vs[] = {
|
||||
InterpretVertex(data, v+0, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+1, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+2, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+3, cfg, dataEnd, valid),
|
||||
};
|
||||
|
||||
adjacentPrimVertices.push_back(vs[0]);
|
||||
adjacentPrimVertices.push_back(vs[1]);
|
||||
|
||||
adjacentPrimVertices.push_back(vs[2]);
|
||||
adjacentPrimVertices.push_back(vs[3]);
|
||||
|
||||
activePrim.push_back(vs[1]);
|
||||
activePrim.push_back(vs[2]);
|
||||
}
|
||||
else if(pipeState.m_IA.Topology == eTopology_TriangleStrip_Adj)
|
||||
{
|
||||
// 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;
|
||||
|
||||
if(numidx < 6)
|
||||
{
|
||||
// not enough indices provided, bail to make sure logic below doesn't
|
||||
// need to have tons of edge case detection
|
||||
valid = false;
|
||||
}
|
||||
else if(idx <= 4 || numidx <= 7)
|
||||
{
|
||||
FloatVector vs[] = {
|
||||
InterpretVertex(data, 0, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, 1, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, 2, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, 3, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, 4, cfg, dataEnd, valid),
|
||||
|
||||
// note this one isn't used as it's adjacency for the next triangle
|
||||
InterpretVertex(data, 5, cfg, dataEnd, valid),
|
||||
|
||||
// min() with number of indices in case this is a tiny strip
|
||||
// that is basically just a list
|
||||
InterpretVertex(data, RDCMIN(6U, numidx-1), cfg, dataEnd, valid),
|
||||
};
|
||||
|
||||
// these are the triangles on the far left of the MSDN diagram above
|
||||
adjacentPrimVertices.push_back(vs[0]);
|
||||
adjacentPrimVertices.push_back(vs[1]);
|
||||
adjacentPrimVertices.push_back(vs[2]);
|
||||
|
||||
adjacentPrimVertices.push_back(vs[4]);
|
||||
adjacentPrimVertices.push_back(vs[3]);
|
||||
adjacentPrimVertices.push_back(vs[0]);
|
||||
|
||||
adjacentPrimVertices.push_back(vs[4]);
|
||||
adjacentPrimVertices.push_back(vs[2]);
|
||||
adjacentPrimVertices.push_back(vs[6]);
|
||||
|
||||
activePrim.push_back(vs[0]);
|
||||
activePrim.push_back(vs[2]);
|
||||
activePrim.push_back(vs[4]);
|
||||
}
|
||||
else if(idx > numidx-4)
|
||||
{
|
||||
// in diagram, numidx == 14
|
||||
|
||||
FloatVector vs[] = {
|
||||
/*[0]=*/ InterpretVertex(data, numidx-8, cfg, dataEnd, valid), // 6 in diagram
|
||||
|
||||
// as above, unused since this is adjacency for 2-previous triangle
|
||||
/*[1]=*/ InterpretVertex(data, numidx-7, cfg, dataEnd, valid), // 7 in diagram
|
||||
/*[2]=*/ InterpretVertex(data, numidx-6, cfg, dataEnd, valid), // 8 in diagram
|
||||
|
||||
// as above, unused since this is adjacency for previous triangle
|
||||
/*[3]=*/ InterpretVertex(data, numidx-5, cfg, dataEnd, valid), // 9 in diagram
|
||||
/*[4]=*/ InterpretVertex(data, numidx-4, cfg, dataEnd, valid), // 10 in diagram
|
||||
/*[5]=*/ InterpretVertex(data, numidx-3, cfg, dataEnd, valid), // 11 in diagram
|
||||
/*[6]=*/ InterpretVertex(data, numidx-2, cfg, dataEnd, valid), // 12 in diagram
|
||||
/*[7]=*/ InterpretVertex(data, numidx-1, cfg, dataEnd, valid), // 13 in diagram
|
||||
};
|
||||
|
||||
// these are the triangles on the far right of the MSDN diagram above
|
||||
adjacentPrimVertices.push_back(vs[2]); // 8 in diagram
|
||||
adjacentPrimVertices.push_back(vs[0]); // 6 in diagram
|
||||
adjacentPrimVertices.push_back(vs[4]); // 10 in diagram
|
||||
|
||||
adjacentPrimVertices.push_back(vs[4]); // 10 in diagram
|
||||
adjacentPrimVertices.push_back(vs[7]); // 13 in diagram
|
||||
adjacentPrimVertices.push_back(vs[6]); // 12 in diagram
|
||||
|
||||
adjacentPrimVertices.push_back(vs[6]); // 12 in diagram
|
||||
adjacentPrimVertices.push_back(vs[5]); // 11 in diagram
|
||||
adjacentPrimVertices.push_back(vs[2]); // 8 in diagram
|
||||
|
||||
activePrim.push_back(vs[2]); // 8 in diagram
|
||||
activePrim.push_back(vs[4]); // 10 in diagram
|
||||
activePrim.push_back(vs[6]); // 12 in diagram
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're in the middle somewhere. Each primitive has two vertices for it
|
||||
// so our step rate is 2. The first 'middle' primitive starts at indices 5&6
|
||||
// and uses indices all the way back to 0
|
||||
uint32_t v = RDCMAX( ( (idx+1) / 2) * 2, 6U) - 6;
|
||||
|
||||
// these correspond to the indices in the MSDN diagram, with {2,4,6} as the
|
||||
// main triangle
|
||||
FloatVector vs[] = {
|
||||
InterpretVertex(data, v+0, cfg, dataEnd, valid),
|
||||
|
||||
// this one is adjacency for 2-previous triangle
|
||||
InterpretVertex(data, v+1, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+2, cfg, dataEnd, valid),
|
||||
|
||||
// this one is adjacency for previous triangle
|
||||
InterpretVertex(data, v+3, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+4, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+5, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+6, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+7, cfg, dataEnd, valid),
|
||||
InterpretVertex(data, v+8, cfg, dataEnd, valid),
|
||||
};
|
||||
|
||||
// these are the triangles around {2,4,6} in the MSDN diagram above
|
||||
adjacentPrimVertices.push_back(vs[0]);
|
||||
adjacentPrimVertices.push_back(vs[2]);
|
||||
adjacentPrimVertices.push_back(vs[4]);
|
||||
|
||||
adjacentPrimVertices.push_back(vs[2]);
|
||||
adjacentPrimVertices.push_back(vs[5]);
|
||||
adjacentPrimVertices.push_back(vs[6]);
|
||||
|
||||
adjacentPrimVertices.push_back(vs[6]);
|
||||
adjacentPrimVertices.push_back(vs[8]);
|
||||
adjacentPrimVertices.push_back(vs[4]);
|
||||
|
||||
activePrim.push_back(vs[2]);
|
||||
activePrim.push_back(vs[4]);
|
||||
activePrim.push_back(vs[6]);
|
||||
}
|
||||
}
|
||||
else if(pipeState.m_IA.Topology >= eTopology_PatchList_1CPs)
|
||||
{
|
||||
uint32_t dim = (pipeState.m_IA.Topology-eTopology_PatchList_1CPs) + 1;
|
||||
|
||||
uint32_t v0 = uint32_t(idx/dim) * dim;
|
||||
|
||||
for(uint32_t v = v0; v < v0+dim; v++)
|
||||
{
|
||||
if(v != idx && valid)
|
||||
inactiveVertices.push_back(InterpretVertex(data, v, cfg, dataEnd, valid));
|
||||
}
|
||||
}
|
||||
else // if(pipeState.m_IA.Topology == eTopology_PointList) point list, or unknown/unhandled type
|
||||
{
|
||||
// no adjacency, inactive verts or active primitive
|
||||
}
|
||||
|
||||
memcpy(mapped.pData, cfg.hilightVerts, sizeof(Vec4f)*3);
|
||||
m_pImmediateContext->Unmap(m_TriHighlightHelper, 0);
|
||||
|
||||
UINT strides[] = { sizeof(Vec4f) };
|
||||
UINT offsets[] = { 0 };
|
||||
|
||||
m_pImmediateContext->IASetVertexBuffers(0, 1, &m_TriHighlightHelper, (UINT *)&strides, (UINT *)&offsets);
|
||||
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
m_pImmediateContext->Draw(3, 0);
|
||||
|
||||
FloatVector vertSprite[4] = {
|
||||
cfg.hilightVerts[0],
|
||||
cfg.hilightVerts[0],
|
||||
cfg.hilightVerts[0],
|
||||
cfg.hilightVerts[0]
|
||||
};
|
||||
|
||||
hr = m_pImmediateContext->Map(m_TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
|
||||
if(FAILED(hr))
|
||||
if(valid)
|
||||
{
|
||||
RDCERR("Failde to map m_TriHighlightHelper %08x", hr);
|
||||
return;
|
||||
////////////////////////////////////////////////////////////////
|
||||
// prepare rendering (for both vertices & primitives)
|
||||
|
||||
// if data is from post transform, it will be in clipspace
|
||||
if((cfg.type != eMeshDataStage_VSIn && pipeState.m_HS.Shader == ResourceId()) ||
|
||||
(cfg.type == eMeshDataStage_GSOut && pipeState.m_HS.Shader != ResourceId()))
|
||||
{
|
||||
vertexData.ModelViewProj = projMat.Mul(camMat.Mul(guessProjInv));
|
||||
m_pImmediateContext->VSSetShader(m_DebugRender.WireframeHomogVS, NULL, 0);
|
||||
m_pImmediateContext->IASetInputLayout(m_DebugRender.GenericHomogLayout);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexData.ModelViewProj = projMat.Mul(camMat);
|
||||
m_pImmediateContext->IASetInputLayout(m_DebugRender.GenericLayout);
|
||||
}
|
||||
|
||||
FillCBuffer(m_DebugRender.GenericVSCBuffer, (float *)&vertexData, sizeof(DebugVertexCBuffer));
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
HRESULT hr = S_OK;
|
||||
UINT strides[] = { sizeof(Vec4f) };
|
||||
UINT offsets[] = { 0 };
|
||||
m_pImmediateContext->IASetVertexBuffers(0, 1, &m_TriHighlightHelper, (UINT *)&strides, (UINT *)&offsets);
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// render primitives
|
||||
|
||||
m_pImmediateContext->IASetPrimitiveTopology(primTopo);
|
||||
|
||||
// Draw active primitive (red)
|
||||
pixelData.WireframeColour = Vec3f(1.0f, 0.0f, 0.0f);
|
||||
FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData));
|
||||
|
||||
if(activePrim.size() >= primSize)
|
||||
{
|
||||
hr = m_pImmediateContext->Map(m_TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Failde to map m_TriHighlightHelper %08x", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(mapped.pData, &activePrim[0], sizeof(Vec4f)*primSize);
|
||||
m_pImmediateContext->Unmap(m_TriHighlightHelper, 0);
|
||||
|
||||
m_pImmediateContext->Draw(primSize, 0);
|
||||
}
|
||||
|
||||
// Draw adjacent primitives (green)
|
||||
pixelData.WireframeColour = Vec3f(0.0f, 1.0f, 0.0f);
|
||||
FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData));
|
||||
|
||||
if(adjacentPrimVertices.size() >= primSize && (adjacentPrimVertices.size() % primSize) == 0)
|
||||
{
|
||||
hr = m_pImmediateContext->Map(m_TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Failde to map m_TriHighlightHelper %08x", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(mapped.pData, &adjacentPrimVertices[0], sizeof(Vec4f)*adjacentPrimVertices.size());
|
||||
m_pImmediateContext->Unmap(m_TriHighlightHelper, 0);
|
||||
|
||||
m_pImmediateContext->Draw((UINT)adjacentPrimVertices.size(), 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// prepare to render dots (set new VS params and topology)
|
||||
float scale = 800.0f/float(GetHeight());
|
||||
float asp = float(GetWidth())/float(GetHeight());
|
||||
|
||||
vertexData.SpriteSize = Vec2f(scale/asp, scale);
|
||||
FillCBuffer(m_DebugRender.GenericVSCBuffer, (float *)&vertexData, sizeof(DebugVertexCBuffer));
|
||||
|
||||
// Draw active vertex (blue)
|
||||
pixelData.WireframeColour = Vec3f(0.0f, 0.0f, 1.0f);
|
||||
FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData));
|
||||
|
||||
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
FloatVector vertSprite[4] = {
|
||||
activeVertex,
|
||||
activeVertex,
|
||||
activeVertex,
|
||||
activeVertex,
|
||||
};
|
||||
|
||||
hr = m_pImmediateContext->Map(m_TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Failde to map m_TriHighlightHelper %08x", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(mapped.pData, vertSprite, sizeof(vertSprite));
|
||||
m_pImmediateContext->Unmap(m_TriHighlightHelper, 0);
|
||||
|
||||
m_pImmediateContext->Draw(4, 0);
|
||||
|
||||
// Draw inactive vertices (green)
|
||||
pixelData.WireframeColour = Vec3f(0.0f, 1.0f, 0.0f);
|
||||
FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData));
|
||||
|
||||
for(size_t i=0; i < inactiveVertices.size(); i++)
|
||||
{
|
||||
vertSprite[0] = vertSprite[1] = vertSprite[2] = vertSprite[3] = inactiveVertices[i];
|
||||
|
||||
hr = m_pImmediateContext->Map(m_TriHighlightHelper, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
RDCERR("Failde to map m_TriHighlightHelper %08x", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(mapped.pData, vertSprite, sizeof(vertSprite));
|
||||
m_pImmediateContext->Unmap(m_TriHighlightHelper, 0);
|
||||
|
||||
m_pImmediateContext->Draw(4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(mapped.pData, vertSprite, sizeof(vertSprite));
|
||||
m_pImmediateContext->Unmap(m_TriHighlightHelper, 0);
|
||||
|
||||
float scale = 800.0f/float(GetHeight());
|
||||
float asp = float(GetWidth())/float(GetHeight());
|
||||
|
||||
pixelData.WireframeColour = Vec3f(0.0f, 0.0f, 1.0f);
|
||||
vertexData.SpriteSize = Vec2f(scale/asp, scale);
|
||||
FillCBuffer(m_DebugRender.GenericVSCBuffer, (float *)&vertexData, sizeof(DebugVertexCBuffer));
|
||||
FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData));
|
||||
|
||||
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
m_pImmediateContext->Draw(4, 0);
|
||||
|
||||
if(cfg.type != eMeshDataStage_VSIn)
|
||||
m_pImmediateContext->VSSetShader(m_DebugRender.WireframeVS, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -292,6 +292,21 @@ class D3D11DebugManager
|
||||
// <frame,event> -> data
|
||||
map<pair<uint32_t,uint32_t>, PostVSData> m_PostVSData;
|
||||
|
||||
// simple cache for when we need buffer data for highlighting
|
||||
// vertices, typical use will be lots of vertices in the same
|
||||
// mesh, not jumping back and forth much between meshes.
|
||||
struct HighlightCache
|
||||
{
|
||||
HighlightCache() : EID(0), buf(), stage(eMeshDataStage_Unknown), useidx(false) {}
|
||||
uint32_t EID;
|
||||
ResourceId buf;
|
||||
MeshDataStage stage;
|
||||
bool useidx;
|
||||
|
||||
vector<byte> data;
|
||||
vector<uint32_t> indices;
|
||||
} m_HighlightCache;
|
||||
|
||||
ID3D11Texture2D *m_OverlayRenderTex;
|
||||
ResourceId m_OverlayResourceId;
|
||||
|
||||
@@ -314,6 +329,8 @@ class D3D11DebugManager
|
||||
ID3D11Buffer *m_FrustumHelper;
|
||||
ID3D11Buffer *m_TriHighlightHelper;
|
||||
|
||||
FloatVector InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool &valid);
|
||||
|
||||
bool InitStreamOut();
|
||||
void ShutdownStreamOut();
|
||||
|
||||
|
||||
@@ -102,4 +102,7 @@ inline float ConvertFromSRGB8(uint8_t comp)
|
||||
return SRGB8_lookuptable[comp];
|
||||
}
|
||||
|
||||
struct ResourceFormat;
|
||||
float ConvertComponent(ResourceFormat fmt, byte *data);
|
||||
|
||||
#include "half_convert.h"
|
||||
|
||||
@@ -564,7 +564,10 @@ void ReplayOutput::DisplayMesh()
|
||||
|
||||
m_pDevice->ClearOutputWindowDepth(m_MainOutput.outputID, 1.0f, 0);
|
||||
|
||||
m_pDevice->RenderMesh(m_FrameID, events, m_RenderData.meshDisplay);
|
||||
MeshDisplay mesh = m_RenderData.meshDisplay;
|
||||
mesh.positionBuf = m_pDevice->GetLiveID(mesh.positionBuf);
|
||||
|
||||
m_pDevice->RenderMesh(m_FrameID, events, mesh);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "stb/stb_image_write.h"
|
||||
#include "common/dds_readwrite.h"
|
||||
|
||||
static inline float ConvertComponent(ResourceFormat fmt, byte *data)
|
||||
float ConvertComponent(ResourceFormat fmt, byte *data)
|
||||
{
|
||||
if(fmt.compByteWidth == 4)
|
||||
{
|
||||
|
||||
@@ -355,17 +355,14 @@ namespace renderdoc
|
||||
|
||||
public bool thisDrawOnly = true;
|
||||
|
||||
public bool showVerts;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct HighlightVerts
|
||||
{
|
||||
public FloatVector v0;
|
||||
public FloatVector v1;
|
||||
public FloatVector v2;
|
||||
};
|
||||
[CustomMarshalAs(CustomUnmanagedType.CustomClass)]
|
||||
public HighlightVerts highlight = new HighlightVerts();
|
||||
public UInt32 highlightVert;
|
||||
public ResourceId positionBuf;
|
||||
public UInt32 positionOffset;
|
||||
public UInt32 positionStride;
|
||||
public UInt32 positionCompCount;
|
||||
public UInt32 positionCompByteWidth;
|
||||
public FormatComponentType positionCompType;
|
||||
public SpecialFormat positionFormat;
|
||||
|
||||
public FloatVector prevMeshColour = new FloatVector();
|
||||
public FloatVector currentMeshColour = new FloatVector();
|
||||
|
||||
@@ -443,6 +443,8 @@ namespace renderdocui.Windows
|
||||
var contentsVSOut = RT_FetchBufferContents(MeshDataStage.VSOut, r, m_VSOut.m_Input);
|
||||
var contentsGSOut = RT_FetchBufferContents(MeshDataStage.GSOut, r, m_GSOut.m_Input);
|
||||
|
||||
UpdateMeshPositionBuffer();
|
||||
|
||||
if (curReq != m_ReqID)
|
||||
return;
|
||||
|
||||
@@ -520,6 +522,9 @@ namespace renderdocui.Windows
|
||||
var contentsVSOut = RT_FetchBufferContents(MeshDataStage.VSOut, r, m_VSOut.m_Input);
|
||||
var contentsGSOut = RT_FetchBufferContents(MeshDataStage.GSOut, r, m_GSOut.m_Input);
|
||||
|
||||
if (MeshView)
|
||||
UpdateMeshPositionBuffer();
|
||||
|
||||
if (curReq != m_ReqID)
|
||||
return;
|
||||
|
||||
@@ -1792,7 +1797,7 @@ namespace renderdocui.Windows
|
||||
}
|
||||
}
|
||||
|
||||
ClearHighlightVerts();
|
||||
UpdateHighlightVerts(GetUIState(m_MeshDisplay.type));
|
||||
|
||||
m_CurrentCamera.Apply();
|
||||
m_Core.Renderer.BeginInvoke(RT_UpdateRenderOutput);
|
||||
@@ -1950,11 +1955,48 @@ namespace renderdocui.Windows
|
||||
controlType.SelectedIndex = 1;
|
||||
}
|
||||
|
||||
UpdateMeshPositionBuffer();
|
||||
|
||||
enableCameraControls();
|
||||
|
||||
controlType_SelectedIndexChanged(sender, e);
|
||||
}
|
||||
|
||||
private void UpdateMeshPositionBuffer()
|
||||
{
|
||||
var ui = GetUIState(m_MeshDisplay.type);
|
||||
|
||||
FormatElement pos = null;
|
||||
|
||||
if (ui.m_Input.BufferFormats != null)
|
||||
{
|
||||
foreach (var el in ui.m_Input.BufferFormats)
|
||||
{
|
||||
// prioritise SV_Position over general POSITION
|
||||
if (el.name.ToUpper() == "SV_POSITION")
|
||||
pos = el;
|
||||
if (el.name.ToUpper() == "POSITION" && pos == null)
|
||||
pos = el;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == null)
|
||||
{
|
||||
m_MeshDisplay.positionBuf = ResourceId.Null;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_MeshDisplay.positionBuf = m_VSIn.m_Input.Buffers[pos.buffer];
|
||||
m_MeshDisplay.positionOffset = pos.offset + ui.m_Input.Offsets[pos.buffer];
|
||||
m_MeshDisplay.positionStride = ui.m_Input.Strides[pos.buffer];
|
||||
|
||||
m_MeshDisplay.positionCompByteWidth = pos.format.compByteWidth;
|
||||
m_MeshDisplay.positionCompCount = pos.format.compCount;
|
||||
m_MeshDisplay.positionCompType = pos.format.compType;
|
||||
m_MeshDisplay.positionFormat = pos.format.special ? pos.format.specialFormat : SpecialFormat.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
private void camGuess_PropChanged()
|
||||
{
|
||||
m_MeshDisplay.ortho = matrixType.SelectedIndex == 1;
|
||||
@@ -2397,7 +2439,7 @@ namespace renderdocui.Windows
|
||||
|
||||
private void ClearHighlightVerts()
|
||||
{
|
||||
m_MeshDisplay.showVerts = false;
|
||||
m_MeshDisplay.highlightVert = ~0U;
|
||||
m_Core.Renderer.BeginInvoke((ReplayRenderer r) => { RT_UpdateRenderOutput(r); if (m_Output != null) m_Output.Display(); });
|
||||
}
|
||||
|
||||
@@ -2407,83 +2449,7 @@ namespace renderdocui.Windows
|
||||
if (ui.m_GridView.SelectedRows.Count == 0) return;
|
||||
if (!MeshView) return;
|
||||
|
||||
int v0 = (ui.m_GridView.SelectedRows[0].Index / 3) * 3;
|
||||
|
||||
if (ui == m_VSIn && ui.m_Data.Topology == PrimitiveTopology.TriangleStrip)
|
||||
{
|
||||
int idx = ui.m_GridView.SelectedRows[0].Index;
|
||||
v0 = Math.Min(ui.m_GridView.RowCount - 3, idx);
|
||||
|
||||
if ((ui.m_Input.Drawcall.flags & DrawcallFlags.UseIBuffer) != 0)
|
||||
{
|
||||
// handle tristrip reset values by clamping where possible.
|
||||
if (GetIndex(ui, v0 + 2) == uint.MaxValue && v0 > 0)
|
||||
{
|
||||
if (v0 > 0)
|
||||
{
|
||||
v0 -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset value before we've done a full tri. Don't show highlight
|
||||
ClearHighlightVerts();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (GetIndex(ui, v0 + 1) == uint.MaxValue && v0 > 1)
|
||||
{
|
||||
if (v0 > 1)
|
||||
{
|
||||
v0 -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset value before we've done a full tri. Don't show highlight
|
||||
ClearHighlightVerts();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetIndex(ui, v0 + 0) == uint.MaxValue ||
|
||||
GetIndex(ui, v0 + 1) == uint.MaxValue ||
|
||||
GetIndex(ui, v0 + 2) == uint.MaxValue)
|
||||
{
|
||||
// selected a reset value, or shifted back into a reset value thus degenerate triangle,
|
||||
// don't show anything
|
||||
ClearHighlightVerts();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ui.m_GridView.SelectedRows[0].Index == v0 + 0)
|
||||
{
|
||||
m_MeshDisplay.highlight.v0 = GetPosition(ui, v0 + 0);
|
||||
m_MeshDisplay.highlight.v1 = GetPosition(ui, v0 + 1);
|
||||
m_MeshDisplay.highlight.v2 = GetPosition(ui, v0 + 2);
|
||||
m_MeshDisplay.showVerts = true;
|
||||
}
|
||||
if (ui.m_GridView.SelectedRows[0].Index == v0 + 1)
|
||||
{
|
||||
m_MeshDisplay.highlight.v0 = GetPosition(ui, v0 + 1);
|
||||
m_MeshDisplay.highlight.v1 = GetPosition(ui, v0 + 0);
|
||||
m_MeshDisplay.highlight.v2 = GetPosition(ui, v0 + 2);
|
||||
m_MeshDisplay.showVerts = true;
|
||||
}
|
||||
if (ui.m_GridView.SelectedRows[0].Index == v0 + 2)
|
||||
{
|
||||
m_MeshDisplay.highlight.v0 = GetPosition(ui, v0 + 2);
|
||||
m_MeshDisplay.highlight.v1 = GetPosition(ui, v0 + 1);
|
||||
m_MeshDisplay.highlight.v2 = GetPosition(ui, v0 + 0);
|
||||
m_MeshDisplay.showVerts = true;
|
||||
}
|
||||
|
||||
if (ui.m_Data.Topology == PrimitiveTopology.PointList)
|
||||
m_MeshDisplay.highlight.v2 = m_MeshDisplay.highlight.v1 = m_MeshDisplay.highlight.v0;
|
||||
|
||||
if (ui.m_Data.Topology == PrimitiveTopology.LineList ||
|
||||
ui.m_Data.Topology == PrimitiveTopology.LineStrip)
|
||||
m_MeshDisplay.highlight.v2 = m_MeshDisplay.highlight.v1;
|
||||
m_MeshDisplay.highlightVert = (uint)ui.m_GridView.SelectedRows[0].Index;
|
||||
|
||||
m_Core.Renderer.BeginInvoke((ReplayRenderer r) => { RT_UpdateRenderOutput(r); if (m_Output != null) m_Output.Display(); });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user