Handle vtx highlights outside UI, for complex topologies. Refs #85

This commit is contained in:
baldurk
2014-09-28 02:24:57 +01:00
parent 7da04de998
commit faeb047211
8 changed files with 663 additions and 160 deletions
+8 -2
View File
@@ -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;
+577 -66
View File
@@ -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);
}
+17
View File
@@ -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();
+3
View File
@@ -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"
+4 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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)
{
+8 -11
View File
@@ -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();
+45 -79
View File
@@ -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(); });
}