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:
baldurk
2015-01-28 02:21:14 +00:00
parent 7bf45d043b
commit a703dc54d0
19 changed files with 332 additions and 165 deletions
+1
View File
@@ -66,6 +66,7 @@ struct MeshDisplay
float fov, aspect;
bool32 thisDrawOnly;
uint32_t curInstance;
uint32_t highlightVert;
MeshFormat position;
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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; }
+4 -3
View File
@@ -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
{
+1 -1
View File
@@ -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);
+2 -3
View File
@@ -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())
{
+89 -48
View File
@@ -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);
+7 -3
View File
@@ -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;
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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);
+82 -23
View File
@@ -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;
+12 -5
View File
@@ -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();
+1 -1
View File
@@ -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;
+42 -13
View File
@@ -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);
}
}
}
+6 -4
View File
@@ -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); }
+1 -1
View File
@@ -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);
+1
View File
@@ -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;
+3 -3
View File
@@ -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);
+75 -52
View File
@@ -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;