mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-05 14:21:10 +00:00
Fix instancing support for post-vs mesh views on D3D11 and GL
* We stream-out or transform feedback the whole instanced draw at once, producing a buffer containing all N instances in one. Then when the client requests postvs data, an offset into the buffer is calculated (in 1/N chunks) and carried through everywhere. * Since we were using the offset to indicate where the system position output lay for since-last-clear auto drawing of meshes, we rearrange the output attribute order so system position is always first in the list. * Also since-last-clear now doesn't include the current event, but does include any previous instances before the current instance.
This commit is contained in:
@@ -66,6 +66,7 @@ struct MeshDisplay
|
||||
float fov, aspect;
|
||||
|
||||
bool32 thisDrawOnly;
|
||||
uint32_t curInstance;
|
||||
|
||||
uint32_t highlightVert;
|
||||
MeshFormat position;
|
||||
|
||||
@@ -164,7 +164,7 @@ extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetCBufferVariableCo
|
||||
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_SaveTexture(ReplayRenderer *rend, const TextureSave &saveData, const char *path);
|
||||
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetPostVSData(ReplayRenderer *rend, MeshDataStage stage, MeshFormat *data);
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetPostVSData(ReplayRenderer *rend, uint32_t instID, MeshDataStage stage, MeshFormat *data);
|
||||
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetMinMax(ReplayRenderer *rend, ResourceId tex, uint32_t sliceFace, uint32_t mip, uint32_t sample, PixelValue *minval, PixelValue *maxval);
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetHistogram(ReplayRenderer *rend, ResourceId tex, uint32_t sliceFace, uint32_t mip, uint32_t sample, float minval, float maxval, bool32 channels[4], rdctype::array<uint32_t> *histogram);
|
||||
|
||||
@@ -118,7 +118,7 @@ class ImageViewer : public IReplayDriver
|
||||
void FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector<ShaderVariable> &outvars, const vector<byte> &data) {}
|
||||
vector<byte> GetBufferData(ResourceId buff, uint32_t offset, uint32_t len) { return vector<byte>(); }
|
||||
void InitPostVSBuffers(uint32_t frameID, uint32_t eventID) {}
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage) { MeshFormat ret; RDCEraseEl(ret); return ret; }
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage) { MeshFormat ret; RDCEraseEl(ret); return ret; }
|
||||
ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents) { return ResourceId(); }
|
||||
ShaderReflection *GetShader(ResourceId id) { return NULL; }
|
||||
bool HasCallstacks() { return false; }
|
||||
|
||||
@@ -808,7 +808,7 @@ bool ProxySerialiser::Tick()
|
||||
InitPostVSBuffers(0, 0);
|
||||
break;
|
||||
case eCommand_GetPostVS:
|
||||
GetPostVSBuffers(0, 0, eMeshDataStage_Unknown);
|
||||
GetPostVSBuffers(0, 0, 0, eMeshDataStage_Unknown);
|
||||
break;
|
||||
case eCommand_BuildTargetShader:
|
||||
BuildTargetShader("", "", 0, eShaderStage_Vertex, NULL, NULL);
|
||||
@@ -1307,17 +1307,18 @@ void ProxySerialiser::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
}
|
||||
}
|
||||
|
||||
MeshFormat ProxySerialiser::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage)
|
||||
MeshFormat ProxySerialiser::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage)
|
||||
{
|
||||
MeshFormat ret;
|
||||
|
||||
m_ToReplaySerialiser->Serialise("", frameID);
|
||||
m_ToReplaySerialiser->Serialise("", eventID);
|
||||
m_ToReplaySerialiser->Serialise("", instID);
|
||||
m_ToReplaySerialiser->Serialise("", stage);
|
||||
|
||||
if(m_ReplayHost)
|
||||
{
|
||||
ret = m_Remote->GetPostVSBuffers(frameID, eventID, stage);
|
||||
ret = m_Remote->GetPostVSBuffers(frameID, eventID, instID, stage);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -288,7 +288,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver
|
||||
byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool resolve, bool forceRGBA8unorm, float blackPoint, float whitePoint, size_t &dataSize);
|
||||
|
||||
void InitPostVSBuffers(uint32_t frameID, uint32_t eventID);
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage);
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage);
|
||||
|
||||
ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents);
|
||||
|
||||
|
||||
@@ -3030,10 +3030,9 @@ ResourceId D3D11DebugManager::RenderOverlay(ResourceId texid, TextureDisplayOver
|
||||
vector<uint32_t> events = passEvents;
|
||||
|
||||
if(overlay == eTexOverlay_QuadOverdrawDraw)
|
||||
{
|
||||
events.clear();
|
||||
events.push_back(eventID);
|
||||
}
|
||||
|
||||
events.push_back(eventID);
|
||||
|
||||
if(!events.empty())
|
||||
{
|
||||
|
||||
@@ -359,18 +359,18 @@ static uint32_t strhash(const char *str, uint32_t seed = 5381)
|
||||
{
|
||||
if(str == NULL) return seed;
|
||||
|
||||
uint32_t hash = seed;
|
||||
int c = *str;
|
||||
uint32_t hash = seed;
|
||||
int c = *str;
|
||||
str++;
|
||||
|
||||
while(c)
|
||||
while(c)
|
||||
{
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
c = *str;
|
||||
str++;
|
||||
}
|
||||
|
||||
return hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
string D3D11DebugManager::GetShaderBlob(const char *source, const char *entry, const uint32_t compileFlags, const char *profile, ID3DBlob **srcblob)
|
||||
@@ -3707,7 +3707,7 @@ void D3D11DebugManager::RenderCheckerboard(Vec3f light, Vec3f dark)
|
||||
}
|
||||
}
|
||||
|
||||
MeshFormat D3D11DebugManager::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage)
|
||||
MeshFormat D3D11DebugManager::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage)
|
||||
{
|
||||
PostVSData postvs;
|
||||
RDCEraseEl(postvs);
|
||||
@@ -3732,7 +3732,7 @@ MeshFormat D3D11DebugManager::GetPostVSBuffers(uint32_t frameID, uint32_t eventI
|
||||
else
|
||||
ret.buf = ResourceId();
|
||||
|
||||
ret.offset = s.posOffset;
|
||||
ret.offset = s.instStride*instID;
|
||||
ret.stride = s.vertStride;
|
||||
|
||||
ret.compCount = 4;
|
||||
@@ -3745,7 +3745,7 @@ MeshFormat D3D11DebugManager::GetPostVSBuffers(uint32_t frameID, uint32_t eventI
|
||||
ret.topo = MakePrimitiveTopology(s.topo);
|
||||
ret.numVerts = s.numVerts;
|
||||
|
||||
ret.unproject = true;
|
||||
ret.unproject = s.hasPosOut;
|
||||
ret.nearPlane = s.nearPlane;
|
||||
ret.farPlane = s.farPlane;
|
||||
|
||||
@@ -3837,7 +3837,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
vector<D3D11_SO_DECLARATION_ENTRY> sodecls;
|
||||
|
||||
UINT stride = 0;
|
||||
UINT posoffset = ~0U;
|
||||
int posidx = -1;
|
||||
int numPosComponents = 0;
|
||||
|
||||
ID3D11GeometryShader *streamoutGS = NULL;
|
||||
@@ -3858,24 +3858,24 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
decl.StartComponent = 0;
|
||||
decl.ComponentCount = sign.compCount&0xff;
|
||||
|
||||
string a = strupper(string(decl.SemanticName));
|
||||
|
||||
if(a.find("POSITION") != string::npos)
|
||||
if(sign.systemValue == eAttr_Position)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if(a.find("SV_POSITION") != string::npos || sign.systemValue == eAttr_Position)
|
||||
decl.ComponentCount = 4;
|
||||
|
||||
posoffset = stride;
|
||||
numPosComponents = decl.ComponentCount;
|
||||
}
|
||||
posidx = (int)sodecls.size();
|
||||
numPosComponents = decl.ComponentCount = 4;
|
||||
}
|
||||
|
||||
stride += decl.ComponentCount * sizeof(float);
|
||||
sodecls.push_back(decl);
|
||||
}
|
||||
|
||||
// shift position attribute up to first, keeping order otherwise
|
||||
// the same
|
||||
if(posidx > 0)
|
||||
{
|
||||
D3D11_SO_DECLARATION_ENTRY pos = sodecls[posidx];
|
||||
sodecls.erase(sodecls.begin()+posidx);
|
||||
sodecls.insert(sodecls.begin(), pos);
|
||||
}
|
||||
|
||||
HRESULT hr = m_pDevice->CreateGeometryShaderWithStreamOutput(
|
||||
(void *)&dxbcVS->m_ShaderBlob[0],
|
||||
@@ -3911,7 +3911,10 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
if((drawcall->flags & eDraw_UseIBuffer) == 0)
|
||||
{
|
||||
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
|
||||
m_pImmediateContext->Draw(drawcall->numIndices, drawcall->vertexOffset);
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
m_pImmediateContext->DrawInstanced(drawcall->numIndices, drawcall->numInstances, drawcall->vertexOffset, drawcall->instanceOffset);
|
||||
else
|
||||
m_pImmediateContext->Draw(drawcall->numIndices, drawcall->vertexOffset);
|
||||
m_pImmediateContext->IASetPrimitiveTopology(topo);
|
||||
}
|
||||
else // drawcall is indexed
|
||||
@@ -3983,13 +3986,9 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
SAFE_RELEASE(idxBuf);
|
||||
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
{
|
||||
m_pImmediateContext->DrawIndexedInstanced((UINT)indices.size(), drawcall->numInstances, 0, drawcall->vertexOffset, drawcall->instanceOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pImmediateContext->DrawIndexed((UINT)indices.size(), 0, drawcall->vertexOffset);
|
||||
}
|
||||
|
||||
m_pImmediateContext->IASetPrimitiveTopology(topo);
|
||||
m_pImmediateContext->IASetIndexBuffer(UNWRAP(WrappedID3D11Buffer, origBuf), idxFmt, idxOffs);
|
||||
@@ -4089,7 +4088,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
float nearp = 0.1f;
|
||||
float farp = 100.0f;
|
||||
|
||||
Vec4f *pos0 = (Vec4f *)(byteData + posoffset);
|
||||
Vec4f *pos0 = (Vec4f *)byteData;
|
||||
|
||||
for(UINT64 i=1; numPosComponents == 4 && i < numPrims.NumPrimitivesWritten; i++)
|
||||
{
|
||||
@@ -4111,7 +4110,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// two points, and we pick them reasonably distinct on z to reduce floating-point
|
||||
// error
|
||||
|
||||
Vec4f *pos = (Vec4f *)(byteData + posoffset + i*stride);
|
||||
Vec4f *pos = (Vec4f *)(byteData + i*stride);
|
||||
|
||||
if(fabs(pos->w - pos0->w) > 0.01f)
|
||||
{
|
||||
@@ -4134,13 +4133,16 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
|
||||
m_PostVSData[idx].vsin.topo = topo;
|
||||
m_PostVSData[idx].vsout.buf = vsoutBuffer;
|
||||
m_PostVSData[idx].vsout.posOffset = posoffset;
|
||||
m_PostVSData[idx].vsout.vertStride = stride;
|
||||
m_PostVSData[idx].vsout.nearPlane = nearp;
|
||||
m_PostVSData[idx].vsout.farPlane = farp;
|
||||
|
||||
m_PostVSData[idx].vsout.useIndices = (drawcall->flags & eDraw_UseIBuffer) > 0;
|
||||
m_PostVSData[idx].vsout.numVerts = drawcall->numIndices;
|
||||
|
||||
m_PostVSData[idx].vsout.instStride = 0;
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
m_PostVSData[idx].vsout.instStride = bufferDesc.ByteWidth / RDCMAX(1U, drawcall->numInstances);
|
||||
|
||||
m_PostVSData[idx].vsout.idxBuf = NULL;
|
||||
if(m_PostVSData[idx].vsout.useIndices && idxBuf)
|
||||
@@ -4149,6 +4151,8 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
m_PostVSData[idx].vsout.idxFmt = idxFmt;
|
||||
}
|
||||
|
||||
m_PostVSData[idx].vsout.hasPosOut = posidx >= 0;
|
||||
|
||||
m_PostVSData[idx].vsout.topo = topo;
|
||||
}
|
||||
else
|
||||
@@ -4156,11 +4160,12 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// empty vertex output signature
|
||||
m_PostVSData[idx].vsin.topo = topo;
|
||||
m_PostVSData[idx].vsout.buf = NULL;
|
||||
m_PostVSData[idx].vsout.posOffset = ~0U;
|
||||
m_PostVSData[idx].vsout.instStride = 0;
|
||||
m_PostVSData[idx].vsout.vertStride = 0;
|
||||
m_PostVSData[idx].vsout.nearPlane = 0.0f;
|
||||
m_PostVSData[idx].vsout.farPlane = 0.0f;
|
||||
m_PostVSData[idx].vsout.useIndices = false;
|
||||
m_PostVSData[idx].vsout.hasPosOut = false;
|
||||
m_PostVSData[idx].vsout.idxBuf = NULL;
|
||||
|
||||
m_PostVSData[idx].vsout.topo = topo;
|
||||
@@ -4169,7 +4174,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
if(dxbcGS || dxbcDS)
|
||||
{
|
||||
stride = 0;
|
||||
posoffset = ~0U;
|
||||
posidx = -1;
|
||||
numPosComponents = 0;
|
||||
|
||||
DXBC::DXBCFile *lastShader = dxbcGS;
|
||||
@@ -4193,26 +4198,26 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
decl.SemanticIndex = sign.semanticIndex;
|
||||
decl.StartComponent = 0;
|
||||
decl.ComponentCount = sign.compCount&0xff;
|
||||
|
||||
string a = strupper(string(decl.SemanticName));
|
||||
|
||||
if(a.find("POSITION") != string::npos)
|
||||
if(sign.systemValue == eAttr_Position)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if(a.find("SV_POSITION") != string::npos || sign.systemValue == eAttr_Position)
|
||||
decl.ComponentCount = 4;
|
||||
|
||||
posoffset = stride;
|
||||
numPosComponents = decl.ComponentCount;
|
||||
}
|
||||
posidx = (int)sodecls.size();
|
||||
numPosComponents = decl.ComponentCount = 4;
|
||||
}
|
||||
|
||||
stride += decl.ComponentCount * sizeof(float);
|
||||
sodecls.push_back(decl);
|
||||
}
|
||||
|
||||
// shift position attribute up to first, keeping order otherwise
|
||||
// the same
|
||||
if(posidx > 0)
|
||||
{
|
||||
D3D11_SO_DECLARATION_ENTRY pos = sodecls[posidx];
|
||||
sodecls.erase(sodecls.begin()+posidx);
|
||||
sodecls.insert(sodecls.begin(), pos);
|
||||
}
|
||||
|
||||
streamoutGS = NULL;
|
||||
|
||||
HRESULT hr = m_pDevice->CreateGeometryShaderWithStreamOutput(
|
||||
@@ -4246,9 +4251,36 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// trying to stream out a stream-out-auto based drawcall would be bad!
|
||||
// instead just draw the number of verts we pre-calculated
|
||||
if(drawcall->flags & eDraw_Auto)
|
||||
{
|
||||
m_pImmediateContext->Draw(drawcall->numIndices, 0);
|
||||
}
|
||||
else
|
||||
m_WrappedDevice->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw);
|
||||
{
|
||||
if(drawcall->flags & eDraw_UseIBuffer)
|
||||
{
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
{
|
||||
m_pImmediateContext->DrawIndexedInstanced(drawcall->numIndices, drawcall->numInstances, drawcall->indexOffset,
|
||||
drawcall->vertexOffset, drawcall->instanceOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pImmediateContext->DrawIndexed(drawcall->numIndices, drawcall->indexOffset, drawcall->vertexOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
{
|
||||
m_pImmediateContext->DrawInstanced(drawcall->numIndices, drawcall->numInstances, drawcall->vertexOffset, drawcall->instanceOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pImmediateContext->Draw(drawcall->numIndices, drawcall->vertexOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_pImmediateContext->End(m_SOStatsQuery);
|
||||
|
||||
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
|
||||
@@ -4319,7 +4351,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
float nearp = 0.1f;
|
||||
float farp = 100.0f;
|
||||
|
||||
Vec4f *pos0 = (Vec4f *)(byteData + posoffset);
|
||||
Vec4f *pos0 = (Vec4f *)byteData;
|
||||
|
||||
for(UINT64 i=1; numPosComponents == 4 && i < numPrims.NumPrimitivesWritten; i++)
|
||||
{
|
||||
@@ -4341,7 +4373,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// two points, and we pick them reasonably distinct on z to reduce floating-point
|
||||
// error
|
||||
|
||||
Vec4f *pos = (Vec4f *)(byteData + posoffset + i*stride);
|
||||
Vec4f *pos = (Vec4f *)(byteData + i*stride);
|
||||
|
||||
if(fabs(pos->w - pos0->w) > 0.01f)
|
||||
{
|
||||
@@ -4363,11 +4395,14 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
m_pImmediateContext->Unmap(m_SOStagingBuffer, 0);
|
||||
|
||||
m_PostVSData[idx].gsout.buf = gsoutBuffer;
|
||||
m_PostVSData[idx].gsout.posOffset = posoffset;
|
||||
m_PostVSData[idx].gsout.instStride = 0;
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
m_PostVSData[idx].gsout.instStride = bufferDesc.ByteWidth / RDCMAX(1U, drawcall->numInstances);
|
||||
m_PostVSData[idx].gsout.vertStride = stride;
|
||||
m_PostVSData[idx].gsout.nearPlane = nearp;
|
||||
m_PostVSData[idx].gsout.farPlane = farp;
|
||||
m_PostVSData[idx].gsout.useIndices = false;
|
||||
m_PostVSData[idx].gsout.hasPosOut = posidx >= 0;
|
||||
m_PostVSData[idx].gsout.idxBuf = NULL;
|
||||
|
||||
D3D11_PRIMITIVE_TOPOLOGY topo = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
@@ -4422,6 +4457,9 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ:
|
||||
m_PostVSData[idx].gsout.numVerts = (uint32_t)numPrims.NumPrimitivesWritten*3; break;
|
||||
}
|
||||
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
m_PostVSData[idx].gsout.numVerts /= RDCMAX(1U, drawcall->numInstances);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4856,9 +4894,12 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
|
||||
{
|
||||
MeshDataStage stage = cfg.type;
|
||||
|
||||
if(m_HighlightCache.EID != eventID || stage != m_HighlightCache.stage)
|
||||
if(m_HighlightCache.EID != eventID || stage != m_HighlightCache.stage ||
|
||||
cfg.position.buf != m_HighlightCache.buf || cfg.position.offset != m_HighlightCache.offs)
|
||||
{
|
||||
m_HighlightCache.EID = eventID;
|
||||
m_HighlightCache.buf = cfg.position.buf;
|
||||
m_HighlightCache.offs = cfg.position.offset;
|
||||
m_HighlightCache.stage = stage;
|
||||
|
||||
bool index16 = (ifmt == DXGI_FORMAT_R16_UINT);
|
||||
|
||||
@@ -58,13 +58,15 @@ struct PostVSData
|
||||
D3D11_PRIMITIVE_TOPOLOGY topo;
|
||||
|
||||
uint32_t numVerts;
|
||||
uint32_t posOffset;
|
||||
uint32_t vertStride;
|
||||
uint32_t instStride;
|
||||
|
||||
bool useIndices;
|
||||
ID3D11Buffer *idxBuf;
|
||||
DXGI_FORMAT idxFmt;
|
||||
|
||||
bool hasPosOut;
|
||||
|
||||
float nearPlane;
|
||||
float farPlane;
|
||||
} vsin, vsout, gsout;
|
||||
@@ -113,7 +115,7 @@ class D3D11DebugManager
|
||||
int GetHeight() { return m_height; }
|
||||
|
||||
void InitPostVSBuffers(uint32_t frameID, uint32_t eventID);
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage);
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage);
|
||||
|
||||
uint32_t GetStructCount(ID3D11UnorderedAccessView *uav);
|
||||
vector<byte> GetBufferData(ID3D11Buffer *buff, uint32_t offset, uint32_t len);
|
||||
@@ -298,8 +300,10 @@ class D3D11DebugManager
|
||||
// mesh, not jumping back and forth much between meshes.
|
||||
struct HighlightCache
|
||||
{
|
||||
HighlightCache() : EID(0), stage(eMeshDataStage_Unknown), useidx(false) {}
|
||||
HighlightCache() : EID(0), buf(), offs(0), stage(eMeshDataStage_Unknown), useidx(false) {}
|
||||
uint32_t EID;
|
||||
ResourceId buf;
|
||||
uint32_t offs;
|
||||
MeshDataStage stage;
|
||||
bool useidx;
|
||||
|
||||
|
||||
@@ -1260,9 +1260,9 @@ bool D3D11Replay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mi
|
||||
return m_pDevice->GetDebugManager()->GetHistogram(texid, sliceFace, mip, sample, minval, maxval, channels, histogram);
|
||||
}
|
||||
|
||||
MeshFormat D3D11Replay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage)
|
||||
MeshFormat D3D11Replay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage)
|
||||
{
|
||||
return m_pDevice->GetDebugManager()->GetPostVSBuffers(frameID, eventID, stage);
|
||||
return m_pDevice->GetDebugManager()->GetPostVSBuffers(frameID, eventID, instID, stage);
|
||||
}
|
||||
|
||||
vector<byte> D3D11Replay::GetBufferData(ResourceId buff, uint32_t offset, uint32_t len)
|
||||
|
||||
@@ -87,7 +87,7 @@ class D3D11Replay : public IReplayDriver
|
||||
bool GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float *minval, float *maxval);
|
||||
bool GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float minval, float maxval, bool channels[4], vector<uint32_t> &histogram);
|
||||
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage);
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage);
|
||||
|
||||
vector<byte> GetBufferData(ResourceId buff, uint32_t offset, uint32_t len);
|
||||
byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool resolve, bool forceRGBA8unorm, float blackPoint, float whitePoint, size_t &dataSize);
|
||||
|
||||
@@ -1716,18 +1716,27 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
varyings.clear();
|
||||
|
||||
uint32_t stride = 0;
|
||||
uint32_t posoffset = ~0U;
|
||||
int32_t posidx = -1;
|
||||
|
||||
for(int32_t i=0; i < vsRefl->OutputSig.count; i++)
|
||||
{
|
||||
varyings.push_back(vsRefl->OutputSig[i].varName.elems);
|
||||
|
||||
if(!strcmp(vsRefl->OutputSig[i].varName.elems, "gl_Position"))
|
||||
posoffset = stride;
|
||||
if(vsRefl->OutputSig[i].systemValue == eAttr_Position)
|
||||
posidx = i;
|
||||
|
||||
stride += sizeof(float)*vsRefl->OutputSig[i].compCount;
|
||||
}
|
||||
|
||||
// shift position attribute up to first, keeping order otherwise
|
||||
// the same
|
||||
if(posidx > 0)
|
||||
{
|
||||
const char *pos = varyings[posidx];
|
||||
varyings.erase(varyings.begin()+posidx);
|
||||
varyings.insert(varyings.begin(), pos);
|
||||
}
|
||||
|
||||
// this is REALLY ugly, but I've seen problems with varying specification, so we try and
|
||||
// do some fixup by removing prefixes from the results we got from PROGRAM_OUTPUT.
|
||||
//
|
||||
@@ -1872,7 +1881,11 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
|
||||
if((drawcall->flags & eDraw_UseIBuffer) == 0)
|
||||
{
|
||||
gl.glDrawArrays(eGL_POINTS, drawcall->vertexOffset, drawcall->numIndices);
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
gl.glDrawArraysInstancedBaseInstance(eGL_POINTS, drawcall->vertexOffset, drawcall->numIndices,
|
||||
drawcall->numInstances, drawcall->instanceOffset);
|
||||
else
|
||||
gl.glDrawArrays(eGL_POINTS, drawcall->vertexOffset, drawcall->numIndices);
|
||||
}
|
||||
else // drawcall is indexed
|
||||
{
|
||||
@@ -1936,7 +1949,15 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, indexSetBuffer);
|
||||
gl.glNamedBufferStorageEXT(indexSetBuffer, sizeof(uint32_t)*indices.size(), &indices[0], 0);
|
||||
|
||||
gl.glDrawElementsBaseVertex(eGL_POINTS, (GLsizei)indices.size(), eGL_UNSIGNED_INT, NULL, drawcall->vertexOffset);
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
{
|
||||
gl.glDrawElementsInstancedBaseVertexBaseInstance(eGL_POINTS, (GLsizei)indices.size(), eGL_UNSIGNED_INT, NULL,
|
||||
drawcall->numInstances, drawcall->vertexOffset, drawcall->instanceOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glDrawElementsBaseVertex(eGL_POINTS, (GLsizei)indices.size(), eGL_UNSIGNED_INT, NULL, drawcall->vertexOffset);
|
||||
}
|
||||
|
||||
// delete the buffer, we don't need it anymore
|
||||
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, elArrayBuffer);
|
||||
@@ -1993,9 +2014,9 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
float nearp = 0.1f;
|
||||
float farp = 100.0f;
|
||||
|
||||
Vec4f *pos0 = (Vec4f *)(byteData + posoffset);
|
||||
Vec4f *pos0 = (Vec4f *)byteData;
|
||||
|
||||
for(GLuint i=1; posoffset != ~0U && i < primsWritten; i++)
|
||||
for(GLuint i=1; posidx != -1 && i < primsWritten; i++)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// derive near/far, assuming a standard perspective matrix
|
||||
@@ -2015,7 +2036,7 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// two points, and we pick them reasonably distinct on z to reduce floating-point
|
||||
// error
|
||||
|
||||
Vec4f *pos = (Vec4f *)(byteData + posoffset + i*stride);
|
||||
Vec4f *pos = (Vec4f *)(byteData + i*stride);
|
||||
|
||||
if(fabs(pos->w - pos0->w) > 0.01f)
|
||||
{
|
||||
@@ -2039,13 +2060,16 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// store everything out to the PostVS data cache
|
||||
m_PostVSData[idx].vsin.topo = drawcall->topology;
|
||||
m_PostVSData[idx].vsout.buf = vsoutBuffer;
|
||||
m_PostVSData[idx].vsout.posOffset = posoffset;
|
||||
m_PostVSData[idx].vsout.vertStride = stride;
|
||||
m_PostVSData[idx].vsout.nearPlane = nearp;
|
||||
m_PostVSData[idx].vsout.farPlane = farp;
|
||||
|
||||
m_PostVSData[idx].vsout.useIndices = (drawcall->flags & eDraw_UseIBuffer) > 0;
|
||||
m_PostVSData[idx].vsout.numVerts = drawcall->numIndices;
|
||||
|
||||
m_PostVSData[idx].vsout.instStride = 0;
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
m_PostVSData[idx].vsout.instStride = (stride*primsWritten) / RDCMAX(1U, drawcall->numInstances);
|
||||
|
||||
m_PostVSData[idx].vsout.idxBuf = 0;
|
||||
m_PostVSData[idx].vsout.idxByteWidth = drawcall->indexByteWidth;
|
||||
@@ -2054,6 +2078,8 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
m_PostVSData[idx].vsout.idxBuf = idxBuf;
|
||||
}
|
||||
|
||||
m_PostVSData[idx].vsout.hasPosOut = posidx >= 0;
|
||||
|
||||
m_PostVSData[idx].vsout.topo = drawcall->topology;
|
||||
|
||||
// set vsProg back to no varyings, for future use
|
||||
@@ -2078,17 +2104,26 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
varyings.clear();
|
||||
|
||||
stride = 0;
|
||||
posoffset = ~0U;
|
||||
posidx = -1;
|
||||
|
||||
for(int32_t i=0; i < lastRefl->OutputSig.count; i++)
|
||||
{
|
||||
varyings.push_back(lastRefl->OutputSig[i].varName.elems);
|
||||
|
||||
if(!strcmp(lastRefl->OutputSig[i].varName.elems, "gl_Position"))
|
||||
posoffset = stride;
|
||||
if(lastRefl->OutputSig[i].systemValue == eAttr_Position)
|
||||
posidx = i;
|
||||
|
||||
stride += sizeof(float)*lastRefl->OutputSig[i].compCount;
|
||||
}
|
||||
|
||||
// shift position attribute up to first, keeping order otherwise
|
||||
// the same
|
||||
if(posidx > 0)
|
||||
{
|
||||
const char *pos = varyings[posidx];
|
||||
varyings.erase(varyings.begin()+posidx);
|
||||
varyings.insert(varyings.begin(), pos);
|
||||
}
|
||||
|
||||
// see above for the justification/explanation of this monstrosity.
|
||||
|
||||
@@ -2233,15 +2268,29 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
|
||||
if((drawcall->flags & eDraw_UseIBuffer) == 0)
|
||||
{
|
||||
gl.glDrawArrays(drawtopo, drawcall->vertexOffset, drawcall->numIndices);
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
gl.glDrawArraysInstancedBaseInstance(drawtopo, drawcall->vertexOffset, drawcall->numIndices,
|
||||
drawcall->numInstances, drawcall->instanceOffset);
|
||||
else
|
||||
gl.glDrawArrays(drawtopo, drawcall->vertexOffset, drawcall->numIndices);
|
||||
}
|
||||
else // drawcall is indexed
|
||||
{
|
||||
GLenum idxType = eGL_UNSIGNED_BYTE;
|
||||
if(drawcall->indexByteWidth == 2) idxType = eGL_UNSIGNED_SHORT;
|
||||
else if(drawcall->indexByteWidth == 4) idxType = eGL_UNSIGNED_INT;
|
||||
gl.glDrawElementsBaseVertex(drawtopo, drawcall->numIndices, idxType,
|
||||
(const void *)(drawcall->indexOffset*drawcall->indexByteWidth), drawcall->vertexOffset);
|
||||
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
{
|
||||
gl.glDrawElementsInstancedBaseVertexBaseInstance(drawtopo, drawcall->numIndices, idxType,
|
||||
(const void *)(drawcall->indexOffset*drawcall->indexByteWidth), drawcall->numInstances,
|
||||
drawcall->vertexOffset, drawcall->instanceOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glDrawElementsBaseVertex(drawtopo, drawcall->numIndices, idxType,
|
||||
(const void *)(drawcall->indexOffset*drawcall->indexByteWidth), drawcall->vertexOffset);
|
||||
}
|
||||
}
|
||||
gl.glEndTransformFeedback();
|
||||
gl.glEndQuery(eGL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
|
||||
@@ -2284,9 +2333,9 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
float nearp = 0.1f;
|
||||
float farp = 100.0f;
|
||||
|
||||
Vec4f *pos0 = (Vec4f *)(byteData + posoffset);
|
||||
Vec4f *pos0 = (Vec4f *)byteData;
|
||||
|
||||
for(uint32_t i=1; posoffset != ~0U && i < m_PostVSData[idx].gsout.numVerts; i++)
|
||||
for(uint32_t i=1; posidx != -1 && i < m_PostVSData[idx].gsout.numVerts; i++)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// derive near/far, assuming a standard perspective matrix
|
||||
@@ -2306,7 +2355,7 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
// two points, and we pick them reasonably distinct on z to reduce floating-point
|
||||
// error
|
||||
|
||||
Vec4f *pos = (Vec4f *)(byteData + posoffset + i*stride);
|
||||
Vec4f *pos = (Vec4f *)(byteData + i*stride);
|
||||
|
||||
if(fabs(pos->w - pos0->w) > 0.01f)
|
||||
{
|
||||
@@ -2329,13 +2378,20 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
|
||||
// store everything out to the PostVS data cache
|
||||
m_PostVSData[idx].gsout.buf = lastoutBuffer;
|
||||
m_PostVSData[idx].gsout.posOffset = posoffset;
|
||||
m_PostVSData[idx].gsout.instStride = 0;
|
||||
if(drawcall->flags & eDraw_Instanced)
|
||||
{
|
||||
m_PostVSData[idx].gsout.numVerts /= RDCMAX(1U, drawcall->numInstances);
|
||||
m_PostVSData[idx].gsout.instStride = stride*m_PostVSData[idx].gsout.numVerts;
|
||||
}
|
||||
m_PostVSData[idx].gsout.vertStride = stride;
|
||||
m_PostVSData[idx].gsout.nearPlane = nearp;
|
||||
m_PostVSData[idx].gsout.farPlane = farp;
|
||||
|
||||
m_PostVSData[idx].gsout.useIndices = false;
|
||||
|
||||
m_PostVSData[idx].gsout.hasPosOut = posidx >= 0;
|
||||
|
||||
m_PostVSData[idx].gsout.idxBuf = 0;
|
||||
m_PostVSData[idx].gsout.idxByteWidth = 0;
|
||||
|
||||
@@ -2366,7 +2422,7 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
gl.glEnable(eGL_RASTERIZER_DISCARD);
|
||||
}
|
||||
|
||||
MeshFormat GLReplay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage)
|
||||
MeshFormat GLReplay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage)
|
||||
{
|
||||
GLPostVSData postvs;
|
||||
RDCEraseEl(postvs);
|
||||
@@ -2391,7 +2447,7 @@ MeshFormat GLReplay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDa
|
||||
else
|
||||
ret.buf = ResourceId();
|
||||
|
||||
ret.offset = s.posOffset;
|
||||
ret.offset = s.instStride*instID;
|
||||
ret.stride = s.vertStride;
|
||||
|
||||
ret.compCount = 4;
|
||||
@@ -2404,7 +2460,7 @@ MeshFormat GLReplay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDa
|
||||
ret.topo = s.topo;
|
||||
ret.numVerts = s.numVerts;
|
||||
|
||||
ret.unproject = true;
|
||||
ret.unproject = s.hasPosOut;
|
||||
ret.nearPlane = s.nearPlane;
|
||||
ret.farPlane = s.farPlane;
|
||||
|
||||
@@ -2834,9 +2890,12 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
|
||||
{
|
||||
MeshDataStage stage = cfg.type;
|
||||
|
||||
if(m_HighlightCache.EID != eventID || stage != m_HighlightCache.stage)
|
||||
if(m_HighlightCache.EID != eventID || stage != m_HighlightCache.stage ||
|
||||
cfg.position.buf != m_HighlightCache.buf || cfg.position.offset != m_HighlightCache.offs)
|
||||
{
|
||||
m_HighlightCache.EID = eventID;
|
||||
m_HighlightCache.buf = cfg.position.buf;
|
||||
m_HighlightCache.offs = cfg.position.offset;
|
||||
m_HighlightCache.stage = stage;
|
||||
|
||||
UINT bytesize = cfg.position.idxByteWidth;
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
#include "replay/replay_driver.h"
|
||||
#include "core/core.h"
|
||||
|
||||
using std::pair;
|
||||
using std::map;
|
||||
|
||||
class WrappedOpenGL;
|
||||
|
||||
struct GLPostVSData
|
||||
@@ -40,13 +43,15 @@ struct GLPostVSData
|
||||
PrimitiveTopology topo;
|
||||
|
||||
uint32_t numVerts;
|
||||
uint32_t posOffset;
|
||||
uint32_t vertStride;
|
||||
uint32_t instStride;
|
||||
|
||||
bool useIndices;
|
||||
GLuint idxBuf;
|
||||
uint32_t idxByteWidth;
|
||||
|
||||
bool hasPosOut;
|
||||
|
||||
float nearPlane;
|
||||
float farPlane;
|
||||
} vsin, vsout, gsout;
|
||||
@@ -126,7 +131,7 @@ class GLReplay : public IReplayDriver
|
||||
bool GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float *minval, float *maxval);
|
||||
bool GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float minval, float maxval, bool channels[4], vector<uint32_t> &histogram);
|
||||
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage);
|
||||
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage);
|
||||
|
||||
vector<byte> GetBufferData(ResourceId buff, uint32_t offset, uint32_t len);
|
||||
byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool resolve, bool forceRGBA8unorm, float blackPoint, float whitePoint, size_t &dataSize);
|
||||
@@ -278,8 +283,10 @@ class GLReplay : public IReplayDriver
|
||||
// mesh, not jumping back and forth much between meshes.
|
||||
struct HighlightCache
|
||||
{
|
||||
HighlightCache() : EID(0), stage(eMeshDataStage_Unknown), useidx(false) {}
|
||||
HighlightCache() : EID(0), buf(), offs(0), stage(eMeshDataStage_Unknown), useidx(false) {}
|
||||
uint32_t EID;
|
||||
ResourceId buf;
|
||||
uint32_t offs;
|
||||
MeshDataStage stage;
|
||||
bool useidx;
|
||||
|
||||
@@ -287,8 +294,8 @@ class GLReplay : public IReplayDriver
|
||||
vector<uint32_t> indices;
|
||||
} m_HighlightCache;
|
||||
|
||||
// <frame,event> -> data
|
||||
std::map<std::pair<uint32_t,uint32_t>, GLPostVSData> m_PostVSData;
|
||||
// <frame,instance> -> data
|
||||
map< pair<uint32_t,uint32_t>, GLPostVSData > m_PostVSData;
|
||||
|
||||
void InitDebugData();
|
||||
void DeleteDebugData();
|
||||
|
||||
@@ -81,7 +81,7 @@ class IRemoteDriver
|
||||
|
||||
virtual ResourceId GetLiveID(ResourceId id) = 0;
|
||||
|
||||
virtual MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, MeshDataStage stage) = 0;
|
||||
virtual MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage) = 0;
|
||||
|
||||
virtual vector<byte> GetBufferData(ResourceId buff, uint32_t offset, uint32_t len) = 0;
|
||||
virtual byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool resolve, bool forceRGBA8unorm, float blackPoint, float whitePoint, size_t &dataSize) = 0;
|
||||
|
||||
@@ -142,14 +142,14 @@ void ReplayOutput::RefreshOverlay()
|
||||
|
||||
while(start)
|
||||
{
|
||||
if(start == draw)
|
||||
break;
|
||||
|
||||
if(start->flags & eDraw_Drawcall)
|
||||
{
|
||||
passEvents.push_back(start->eventID);
|
||||
}
|
||||
|
||||
if(start == draw)
|
||||
break;
|
||||
|
||||
start = m_pRenderer->GetDrawcallByEID((uint32_t)start->next, 0);
|
||||
}
|
||||
}
|
||||
@@ -170,12 +170,10 @@ void ReplayOutput::RefreshOverlay()
|
||||
|
||||
if(draw == NULL || (draw->flags & eDraw_Drawcall) == 0)
|
||||
return;
|
||||
|
||||
m_pDevice->InitPostVSBuffers(m_FrameID, draw->eventID);
|
||||
|
||||
if(m_RenderData.meshDisplay.thisDrawOnly)
|
||||
{
|
||||
m_pDevice->InitPostVSBuffers(m_FrameID, draw->eventID);
|
||||
}
|
||||
else if(!passEvents.empty())
|
||||
if(!m_RenderData.meshDisplay.thisDrawOnly && !passEvents.empty())
|
||||
{
|
||||
uint32_t prev = 0;
|
||||
|
||||
@@ -188,7 +186,12 @@ void ReplayOutput::RefreshOverlay()
|
||||
prev = passEvents[i];
|
||||
}
|
||||
|
||||
m_pDevice->InitPostVSBuffers(m_FrameID, passEvents[i]);
|
||||
FetchDrawcall *d = m_pRenderer->GetDrawcallByEID(m_EventID, m_LastDeferredEvent);
|
||||
|
||||
if(d)
|
||||
{
|
||||
m_pDevice->InitPostVSBuffers(m_FrameID, passEvents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
m_pDevice->ReplayLog(m_FrameID, 0, m_EventID, eReplay_WithoutDraw);
|
||||
@@ -571,10 +574,36 @@ void ReplayOutput::DisplayMesh()
|
||||
|
||||
for(size_t i=0; i < passEvents.size(); i++)
|
||||
{
|
||||
// get the 'most final' stage
|
||||
MeshFormat fmt = m_pDevice->GetPostVSBuffers(m_FrameID, passEvents[i], eMeshDataStage_GSOut);
|
||||
if(fmt.buf == ResourceId()) fmt = m_pDevice->GetPostVSBuffers(m_FrameID, passEvents[i], eMeshDataStage_VSOut);
|
||||
secondaryDraws.push_back(fmt);
|
||||
FetchDrawcall *d = m_pRenderer->GetDrawcallByEID(passEvents[i], m_LastDeferredEvent);
|
||||
|
||||
if(d)
|
||||
{
|
||||
for(uint32_t inst=0; inst < RDCMAX(1U, draw->numInstances); inst++)
|
||||
{
|
||||
// get the 'most final' stage
|
||||
MeshFormat fmt = m_pDevice->GetPostVSBuffers(m_FrameID, passEvents[i], inst, eMeshDataStage_GSOut);
|
||||
if(fmt.buf == ResourceId()) fmt = m_pDevice->GetPostVSBuffers(m_FrameID, passEvents[i], inst, eMeshDataStage_VSOut);
|
||||
|
||||
// if unproject is marked, this output had a 'real' system position output
|
||||
if(fmt.unproject)
|
||||
secondaryDraws.push_back(fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
// get the 'most final' stage
|
||||
MeshFormat fmt = m_pDevice->GetPostVSBuffers(m_FrameID, draw->eventID, inst, eMeshDataStage_GSOut);
|
||||
if(fmt.buf == ResourceId()) fmt = m_pDevice->GetPostVSBuffers(m_FrameID, draw->eventID, inst, eMeshDataStage_VSOut);
|
||||
|
||||
// if unproject is marked, this output had a 'real' system position output
|
||||
if(fmt.unproject)
|
||||
secondaryDraws.push_back(fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ bool ReplayRenderer::GetUsage(ResourceId id, rdctype::array<EventUsage> *usage)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReplayRenderer::GetPostVSData(MeshDataStage stage, MeshFormat *data)
|
||||
bool ReplayRenderer::GetPostVSData(uint32_t instID, MeshDataStage stage, MeshFormat *data)
|
||||
{
|
||||
if(data == NULL) return false;
|
||||
|
||||
@@ -367,7 +367,9 @@ bool ReplayRenderer::GetPostVSData(MeshDataStage stage, MeshFormat *data)
|
||||
|
||||
if(draw == NULL || (draw->flags & eDraw_Drawcall) == 0) return false;
|
||||
|
||||
*data = m_pDevice->GetPostVSBuffers(m_FrameID, draw->eventID, stage);
|
||||
if(instID >= RDCMAX(1U, draw->numInstances)) return false;
|
||||
|
||||
*data = m_pDevice->GetPostVSBuffers(m_FrameID, draw->eventID, instID, stage);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1521,8 +1523,8 @@ extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetCBufferVariableCo
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_SaveTexture(ReplayRenderer *rend, const TextureSave &saveData, const char *path)
|
||||
{ return rend->SaveTexture(saveData, path); }
|
||||
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetPostVSData(ReplayRenderer *rend, MeshDataStage stage, MeshFormat *data)
|
||||
{ return rend->GetPostVSData(stage, data); }
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetPostVSData(ReplayRenderer *rend, uint32_t instID, MeshDataStage stage, MeshFormat *data)
|
||||
{ return rend->GetPostVSData(instID, stage, data); }
|
||||
|
||||
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetMinMax(ReplayRenderer *rend, ResourceId tex, uint32_t sliceFace, uint32_t mip, uint32_t sample, PixelValue *minval, PixelValue *maxval)
|
||||
{ return rend->GetMinMax(tex, sliceFace, mip, sample, minval, maxval); }
|
||||
|
||||
@@ -166,7 +166,7 @@ struct ReplayRenderer
|
||||
bool DebugPixel(uint32_t x, uint32_t y, uint32_t sample, uint32_t primitive, ShaderDebugTrace *trace);
|
||||
bool DebugThread(uint32_t groupid[3], uint32_t threadid[3], ShaderDebugTrace *trace);
|
||||
|
||||
bool GetPostVSData(MeshDataStage stage, MeshFormat *data);
|
||||
bool GetPostVSData(uint32_t instID, MeshDataStage stage, MeshFormat *data);
|
||||
|
||||
bool GetMinMax(ResourceId tex, uint32_t sliceFace, uint32_t mip, uint32_t sample, PixelValue *minval, PixelValue *maxval);
|
||||
bool GetHistogram(ResourceId tex, uint32_t sliceFace, uint32_t mip, uint32_t sample, float minval, float maxval, bool channels[4], rdctype::array<uint32_t> *histogram);
|
||||
|
||||
@@ -398,6 +398,7 @@ namespace renderdoc
|
||||
public float aspect = 0.0f;
|
||||
|
||||
public bool thisDrawOnly = true;
|
||||
public UInt32 curInstance = 0;
|
||||
|
||||
public UInt32 highlightVert;
|
||||
public MeshFormat position;
|
||||
|
||||
@@ -240,7 +240,7 @@ namespace renderdoc
|
||||
private static extern bool ReplayRenderer_SaveTexture(IntPtr real, TextureSave saveData, IntPtr path);
|
||||
|
||||
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool ReplayRenderer_GetPostVSData(IntPtr real, MeshDataStage stage, IntPtr outdata);
|
||||
private static extern bool ReplayRenderer_GetPostVSData(IntPtr real, UInt32 instID, MeshDataStage stage, IntPtr outdata);
|
||||
|
||||
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool ReplayRenderer_GetMinMax(IntPtr real, ResourceId tex, UInt32 sliceFace, UInt32 mip, UInt32 sample, IntPtr outminval, IntPtr outmaxval);
|
||||
@@ -636,14 +636,14 @@ namespace renderdoc
|
||||
return ret;
|
||||
}
|
||||
|
||||
public MeshFormat GetPostVSData(MeshDataStage stage)
|
||||
public MeshFormat GetPostVSData(UInt32 instID, MeshDataStage stage)
|
||||
{
|
||||
IntPtr mem = CustomMarshal.Alloc(typeof(MeshFormat));
|
||||
|
||||
MeshFormat ret = new MeshFormat();
|
||||
ret.buf = ResourceId.Null;
|
||||
|
||||
bool success = ReplayRenderer_GetPostVSData(m_Real, stage, mem);
|
||||
bool success = ReplayRenderer_GetPostVSData(m_Real, instID, stage, mem);
|
||||
|
||||
if (success)
|
||||
ret = (MeshFormat)CustomMarshal.PtrToStructure(mem, typeof(MeshFormat), true);
|
||||
|
||||
@@ -194,8 +194,6 @@ namespace renderdocui.Windows
|
||||
private Core m_Core;
|
||||
private ReplayOutput m_Output = null;
|
||||
|
||||
private uint m_CurInst = 0;
|
||||
|
||||
private byte[] m_Zeroes = null;
|
||||
|
||||
private OutputConfig m_OutConfig = new OutputConfig();
|
||||
@@ -249,30 +247,7 @@ namespace renderdocui.Windows
|
||||
render.MouseWheelHandler = render_MouseWheel;
|
||||
(render as Control).KeyDown += new KeyEventHandler(BufferViewer_KeyDown);
|
||||
(render as Control).KeyUp += new KeyEventHandler(BufferViewer_KeyUp);
|
||||
|
||||
m_OutConfig.m_Type = OutputType.MeshDisplay;
|
||||
|
||||
m_MeshDisplay.type = MeshDataStage.VSIn;
|
||||
m_MeshDisplay.fov = 90.0f;
|
||||
|
||||
m_MeshDisplay.solidShadeMode = SolidShadeMode.None;
|
||||
solidShading.SelectedIndex = 0;
|
||||
|
||||
m_MeshDisplay.thisDrawOnly = true;
|
||||
drawRange.SelectedIndex = 0;
|
||||
|
||||
m_MeshDisplay.currentMeshColour = new FloatVector(1, 0, 0, 1);
|
||||
m_MeshDisplay.prevMeshColour = new FloatVector(0, 0, 0, 1);
|
||||
|
||||
m_Arcball = new ArcballCamera(m_Camera);
|
||||
m_Flycam = new FlyCamera(m_Camera);
|
||||
m_CurrentCamera = m_Arcball;
|
||||
m_Updater = new TimedUpdate(10, TimerUpdate);
|
||||
|
||||
m_Arcball.SpeedMultiplier = m_Flycam.SpeedMultiplier = (float)camSpeed.Value;
|
||||
|
||||
fovGuess.Text = m_MeshDisplay.fov.ToString("G");
|
||||
controlType.SelectedIndex = 0;
|
||||
ResetConfig();
|
||||
|
||||
MeshView = meshview;
|
||||
|
||||
@@ -297,6 +272,33 @@ namespace renderdocui.Windows
|
||||
m_Core.AddLogViewer(this);
|
||||
}
|
||||
|
||||
private void ResetConfig()
|
||||
{
|
||||
m_OutConfig.m_Type = OutputType.MeshDisplay;
|
||||
|
||||
m_MeshDisplay = new MeshDisplay();
|
||||
m_MeshDisplay.type = MeshDataStage.VSIn;
|
||||
m_MeshDisplay.fov = 90.0f;
|
||||
|
||||
m_MeshDisplay.solidShadeMode = SolidShadeMode.None;
|
||||
solidShading.SelectedIndex = 0;
|
||||
|
||||
m_MeshDisplay.thisDrawOnly = true;
|
||||
drawRange.SelectedIndex = 0;
|
||||
|
||||
m_MeshDisplay.currentMeshColour = new FloatVector(1, 0, 0, 1);
|
||||
m_MeshDisplay.prevMeshColour = new FloatVector(0, 0, 0, 1);
|
||||
|
||||
m_Arcball = new ArcballCamera(m_Camera);
|
||||
m_Flycam = new FlyCamera(m_Camera);
|
||||
m_CurrentCamera = m_Arcball;
|
||||
m_Updater = new TimedUpdate(10, TimerUpdate);
|
||||
|
||||
m_Arcball.SpeedMultiplier = m_Flycam.SpeedMultiplier = (float)camSpeed.Value;
|
||||
|
||||
fovGuess.Text = m_MeshDisplay.fov.ToString("G");
|
||||
controlType.SelectedIndex = 0;
|
||||
}
|
||||
private void UI_SetupDocks(bool meshview)
|
||||
{
|
||||
if (meshview)
|
||||
@@ -412,6 +414,8 @@ namespace renderdocui.Windows
|
||||
{
|
||||
m_Output = null;
|
||||
|
||||
ResetConfig();
|
||||
|
||||
ClearStoredData();
|
||||
|
||||
exportToToolStripMenuItem.Enabled = exportToolItem.Enabled = false;
|
||||
@@ -702,7 +706,6 @@ namespace renderdocui.Windows
|
||||
if (!MeshView)
|
||||
return null;
|
||||
|
||||
FormatElement[] f = null;
|
||||
Input ret = new Input();
|
||||
ret.Drawcall = draw;
|
||||
ret.Topology = draw.topology;
|
||||
@@ -739,14 +742,14 @@ namespace renderdocui.Windows
|
||||
if (details == null)
|
||||
return null;
|
||||
|
||||
f = new FormatElement[details.OutputSig.Length];
|
||||
List<FormatElement> f = new List<FormatElement>();
|
||||
|
||||
uint offset = 0;
|
||||
int posidx = -1;
|
||||
for (int i = 0; i < details.OutputSig.Length; i++)
|
||||
{
|
||||
var sig = details.OutputSig[i];
|
||||
|
||||
f[i] = new FormatElement();
|
||||
f.Add(new FormatElement());
|
||||
|
||||
f[i].buffer = 0;
|
||||
f[i].name = details.OutputSig[i].varName.Length > 0 ? details.OutputSig[i].varName : details.OutputSig[i].semanticIdxName;
|
||||
@@ -755,16 +758,33 @@ namespace renderdocui.Windows
|
||||
f[i].format.compType = sig.compType;
|
||||
f[i].format.special = false;
|
||||
f[i].format.rawType = 0;
|
||||
f[i].offset = offset;
|
||||
f[i].perinstance = false;
|
||||
f[i].instancerate = 1;
|
||||
f[i].rowmajor = false;
|
||||
f[i].matrixdim = 1;
|
||||
f[i].systemValue = sig.systemValue;
|
||||
|
||||
offset += details.OutputSig[i].compCount * sizeof(float);
|
||||
if(f[i].systemValue == SystemAttribute.Position)
|
||||
posidx = i;
|
||||
}
|
||||
|
||||
ret.BufferFormats = f;
|
||||
// shift position attribute up to first, keeping order otherwise
|
||||
// the same
|
||||
if (posidx > 0)
|
||||
{
|
||||
FormatElement pos = f[posidx];
|
||||
f.RemoveAt(posidx);
|
||||
f.Insert(0, pos);
|
||||
}
|
||||
|
||||
uint offset = 0;
|
||||
for (int i = 0; i < details.OutputSig.Length; i++)
|
||||
{
|
||||
f[i].offset = offset;
|
||||
offset += f[i].format.compCount * sizeof(float);
|
||||
}
|
||||
|
||||
ret.BufferFormats = f.ToArray();
|
||||
ret.Strides = new uint[] { offset };
|
||||
ret.Offsets = new uint[] { 0 };
|
||||
ret.Buffers = null;
|
||||
@@ -786,6 +806,8 @@ namespace renderdocui.Windows
|
||||
}
|
||||
|
||||
{
|
||||
FormatElement[] f = null;
|
||||
|
||||
var vinputs = m_Core.CurPipelineState.GetVertexInputs();
|
||||
f = new FormatElement[vinputs.Length];
|
||||
|
||||
@@ -802,12 +824,12 @@ namespace renderdocui.Windows
|
||||
false);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
ret.BufferFormats = f;
|
||||
ret.Strides = s;
|
||||
ret.Offsets = o;
|
||||
ret.Buffers = bs;
|
||||
ret.BufferFormats = f;
|
||||
ret.Strides = s;
|
||||
ret.Offsets = o;
|
||||
ret.Buffers = bs;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -848,7 +870,7 @@ namespace renderdocui.Windows
|
||||
|
||||
if (type != MeshDataStage.VSIn)
|
||||
{
|
||||
ret.PostVS = r.GetPostVSData(type);
|
||||
ret.PostVS = r.GetPostVSData(Math.Min(m_MeshDisplay.curInstance, Math.Max(1U, input.Drawcall.numInstances)), type);
|
||||
|
||||
ret.Buffers = new byte[1][];
|
||||
|
||||
@@ -859,11 +881,11 @@ namespace renderdocui.Windows
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.Buffers[0] = r.GetBufferData(ret.PostVS.buf, 0, 0);
|
||||
ret.Buffers[0] = r.GetBufferData(ret.PostVS.buf, ret.PostVS.offset, 0);
|
||||
|
||||
ret.Topology = ret.PostVS.topo;
|
||||
|
||||
ret.IndexCount = (uint)ret.Buffers[0].Length / ret.PostVS.stride;
|
||||
ret.IndexCount = ret.PostVS.numVerts;
|
||||
|
||||
uint stride = 0;
|
||||
foreach (var f in input.BufferFormats)
|
||||
@@ -1298,7 +1320,7 @@ namespace renderdocui.Windows
|
||||
var data = state.m_Data;
|
||||
|
||||
Input input = state.m_Input;
|
||||
uint instance = m_CurInst;
|
||||
uint instance = m_MeshDisplay.curInstance;
|
||||
|
||||
Thread th = Helpers.NewThread(new ThreadStart(() =>
|
||||
{
|
||||
@@ -1527,7 +1549,7 @@ namespace renderdocui.Windows
|
||||
|
||||
var data = state.m_Data;
|
||||
Input input = state.m_Input;
|
||||
uint instance = m_CurInst;
|
||||
uint instance = m_MeshDisplay.curInstance;
|
||||
|
||||
if (data.Buffers == null)
|
||||
return;
|
||||
@@ -2277,7 +2299,7 @@ namespace renderdocui.Windows
|
||||
m_MeshDisplay.position.idxByteWidth = ui.m_Data.PostVS.idxByteWidth;
|
||||
|
||||
m_MeshDisplay.position.buf = ui.m_Data.PostVS.buf;
|
||||
m_MeshDisplay.position.offset = pos.offset;
|
||||
m_MeshDisplay.position.offset = ui.m_Data.PostVS.offset + pos.offset;
|
||||
m_MeshDisplay.position.stride = ui.m_Data.PostVS.stride;
|
||||
|
||||
m_MeshDisplay.position.topo = ui.m_Data.PostVS.topo;
|
||||
@@ -2337,7 +2359,7 @@ namespace renderdocui.Windows
|
||||
else if (ui.m_Stage != MeshDataStage.VSIn && ui.m_Data != null && ui.m_Data.PostVS.buf != ResourceId.Null)
|
||||
{
|
||||
m_MeshDisplay.secondary.buf = ui.m_Data.PostVS.buf;
|
||||
m_MeshDisplay.secondary.offset = tex.offset;
|
||||
m_MeshDisplay.secondary.offset = ui.m_Data.PostVS.offset + tex.offset;
|
||||
m_MeshDisplay.secondary.stride = ui.m_Data.PostVS.stride;
|
||||
}
|
||||
}
|
||||
@@ -2473,9 +2495,10 @@ namespace renderdocui.Windows
|
||||
uint inst = 0;
|
||||
if (uint.TryParse(instanceIdxToolitem.Text, out inst))
|
||||
{
|
||||
if (inst != m_CurInst && inst >= 0 && m_Core.CurDrawcall != null && inst < m_Core.CurDrawcall.numInstances)
|
||||
if (inst != m_MeshDisplay.curInstance && inst >= 0 && m_Core.CurDrawcall != null && inst < m_Core.CurDrawcall.numInstances)
|
||||
{
|
||||
m_CurInst = inst;
|
||||
m_MeshDisplay.curInstance = inst;
|
||||
|
||||
|
||||
OnEventSelected(m_Core.CurFrame, m_Core.CurEvent);
|
||||
}
|
||||
@@ -2581,9 +2604,9 @@ namespace renderdocui.Windows
|
||||
uint inst = 0;
|
||||
if (uint.TryParse(instanceIdx.Text, out inst))
|
||||
{
|
||||
if (inst != m_CurInst && inst >= 0 && m_Core.CurDrawcall != null && inst < m_Core.CurDrawcall.numInstances)
|
||||
if (inst != m_MeshDisplay.curInstance && inst >= 0 && m_Core.CurDrawcall != null && inst < m_Core.CurDrawcall.numInstances)
|
||||
{
|
||||
m_CurInst = inst;
|
||||
m_MeshDisplay.curInstance = inst;
|
||||
|
||||
OnEventSelected(m_Core.CurFrame, m_Core.CurEvent);
|
||||
}
|
||||
@@ -2695,14 +2718,14 @@ namespace renderdocui.Windows
|
||||
|
||||
m_Core.Renderer.Invoke((ReplayRenderer r) =>
|
||||
{
|
||||
trace = r.DebugVertex((UInt32)row, (UInt32)m_CurInst, idx, draw.instanceOffset, draw.vertexOffset);
|
||||
trace = r.DebugVertex((UInt32)row, m_MeshDisplay.curInstance, idx, draw.instanceOffset, draw.vertexOffset);
|
||||
});
|
||||
|
||||
this.BeginInvoke(new Action(() =>
|
||||
{
|
||||
string debugContext = String.Format("Vertex {0}", row);
|
||||
if (draw.numInstances > 1)
|
||||
debugContext += String.Format(", Instance {0}", m_CurInst);
|
||||
debugContext += String.Format(", Instance {0}", m_MeshDisplay.curInstance);
|
||||
|
||||
ShaderViewer s = new ShaderViewer(m_Core, shaderDetails, ShaderStageType.Vertex, trace, debugContext);
|
||||
|
||||
@@ -2816,7 +2839,7 @@ namespace renderdocui.Windows
|
||||
|
||||
private void UpdateHighlightVerts(UIState ui)
|
||||
{
|
||||
if (ui.m_RawData == null) return;
|
||||
if (ui == null || ui.m_RawData == null) return;
|
||||
if (ui.m_GridView.SelectedRows.Count == 0) return;
|
||||
if (!MeshView) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user