Verify thread access to ReplayController to ReplayOutput

This commit is contained in:
baldurk
2018-12-20 10:49:13 +00:00
parent 1617b4618d
commit 7498c53a37
3 changed files with 168 additions and 0 deletions
+114
View File
@@ -170,6 +170,8 @@ static void fileWriteFunc(void *context, void *data, int size)
ReplayController::ReplayController()
{
m_ThreadID = Threading::GetCurrentID();
m_pDevice = NULL;
m_EventID = 100000;
@@ -185,6 +187,8 @@ ReplayController::ReplayController()
ReplayController::~ReplayController()
{
CHECK_REPLAY_THREAD();
RDCLOG("Shutting down replay renderer");
for(size_t i = 0; i < m_Outputs.size(); i++)
@@ -209,6 +213,8 @@ ReplayController::~ReplayController()
void ReplayController::SetFrameEvent(uint32_t eventId, bool force)
{
CHECK_REPLAY_THREAD();
if(eventId != m_EventID || force)
{
m_EventID = eventId;
@@ -226,31 +232,43 @@ void ReplayController::SetFrameEvent(uint32_t eventId, bool force)
const D3D11Pipe::State *ReplayController::GetD3D11PipelineState()
{
CHECK_REPLAY_THREAD();
return m_D3D11PipelineState;
}
const D3D12Pipe::State *ReplayController::GetD3D12PipelineState()
{
CHECK_REPLAY_THREAD();
return m_D3D12PipelineState;
}
const GLPipe::State *ReplayController::GetGLPipelineState()
{
CHECK_REPLAY_THREAD();
return m_GLPipelineState;
}
const VKPipe::State *ReplayController::GetVulkanPipelineState()
{
CHECK_REPLAY_THREAD();
return m_VulkanPipelineState;
}
const PipeState &ReplayController::GetPipelineState()
{
CHECK_REPLAY_THREAD();
return m_PipeState;
}
rdcarray<rdcstr> ReplayController::GetDisassemblyTargets()
{
CHECK_REPLAY_THREAD();
rdcarray<rdcstr> ret;
vector<string> targets = m_pDevice->GetDisassemblyTargets();
@@ -268,6 +286,8 @@ rdcarray<rdcstr> ReplayController::GetDisassemblyTargets()
rdcstr ReplayController::DisassembleShader(ResourceId pipeline, const ShaderReflection *refl,
const char *target)
{
CHECK_REPLAY_THREAD();
for(const std::string &t : m_GCNTargets)
if(t == target)
return GCNISA::Disassemble(refl->encoding, refl->stage, refl->rawBytes, target);
@@ -277,16 +297,22 @@ rdcstr ReplayController::DisassembleShader(ResourceId pipeline, const ShaderRefl
FrameDescription ReplayController::GetFrameInfo()
{
CHECK_REPLAY_THREAD();
return m_FrameRecord.frameInfo;
}
const SDFile &ReplayController::GetStructuredFile()
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetStructuredFile();
}
DrawcallDescription *ReplayController::GetDrawcallByEID(uint32_t eventId)
{
CHECK_REPLAY_THREAD();
if(eventId >= m_Drawcalls.size())
return NULL;
@@ -295,11 +321,15 @@ DrawcallDescription *ReplayController::GetDrawcallByEID(uint32_t eventId)
const rdcarray<DrawcallDescription> &ReplayController::GetDrawcalls()
{
CHECK_REPLAY_THREAD();
return m_FrameRecord.drawcallList;
}
bool ReplayController::ContainsMarker(const rdcarray<DrawcallDescription> &draws)
{
CHECK_REPLAY_THREAD();
bool ret = false;
for(const DrawcallDescription &d : draws)
@@ -317,6 +347,8 @@ bool ReplayController::ContainsMarker(const rdcarray<DrawcallDescription> &draws
bool ReplayController::PassEquivalent(const DrawcallDescription &a, const DrawcallDescription &b)
{
CHECK_REPLAY_THREAD();
// don't group draws and compute executes
if((a.flags & DrawFlags::Dispatch) != (b.flags & DrawFlags::Dispatch))
return false;
@@ -387,6 +419,8 @@ bool ReplayController::PassEquivalent(const DrawcallDescription &a, const Drawca
void ReplayController::AddFakeMarkers()
{
CHECK_REPLAY_THREAD();
rdcarray<DrawcallDescription> &draws = m_FrameRecord.drawcallList;
if(ContainsMarker(draws))
@@ -502,6 +536,8 @@ void ReplayController::AddFakeMarkers()
rdcarray<CounterResult> ReplayController::FetchCounters(const rdcarray<GPUCounter> &counters)
{
CHECK_REPLAY_THREAD();
std::vector<GPUCounter> counterArray(counters.begin(), counters.end());
return m_pDevice->FetchCounters(counterArray);
@@ -509,46 +545,64 @@ rdcarray<CounterResult> ReplayController::FetchCounters(const rdcarray<GPUCounte
rdcarray<GPUCounter> ReplayController::EnumerateCounters()
{
CHECK_REPLAY_THREAD();
return m_pDevice->EnumerateCounters();
}
CounterDescription ReplayController::DescribeCounter(GPUCounter counterID)
{
CHECK_REPLAY_THREAD();
return m_pDevice->DescribeCounter(counterID);
}
const rdcarray<ResourceDescription> &ReplayController::GetResources()
{
CHECK_REPLAY_THREAD();
return m_Resources;
}
const rdcarray<BufferDescription> &ReplayController::GetBuffers()
{
CHECK_REPLAY_THREAD();
return m_Buffers;
}
const rdcarray<TextureDescription> &ReplayController::GetTextures()
{
CHECK_REPLAY_THREAD();
return m_Textures;
}
rdcarray<DebugMessage> ReplayController::GetDebugMessages()
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetDebugMessages();
}
rdcarray<ShaderEntryPoint> ReplayController::GetShaderEntryPoints(ResourceId shader)
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetShaderEntryPoints(m_pDevice->GetLiveID(shader));
}
ShaderReflection *ReplayController::GetShader(ResourceId shader, ShaderEntryPoint entry)
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetShader(m_pDevice->GetLiveID(shader), entry);
}
rdcarray<EventUsage> ReplayController::GetUsage(ResourceId id)
{
CHECK_REPLAY_THREAD();
id = m_pDevice->GetLiveID(id);
if(id == ResourceId())
return rdcarray<EventUsage>();
@@ -557,6 +611,8 @@ rdcarray<EventUsage> ReplayController::GetUsage(ResourceId id)
MeshFormat ReplayController::GetPostVSData(uint32_t instID, uint32_t viewID, MeshDataStage stage)
{
CHECK_REPLAY_THREAD();
DrawcallDescription *draw = GetDrawcallByEID(m_EventID);
MeshFormat ret;
@@ -574,6 +630,8 @@ MeshFormat ReplayController::GetPostVSData(uint32_t instID, uint32_t viewID, Mes
bytebuf ReplayController::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len)
{
CHECK_REPLAY_THREAD();
bytebuf retData;
if(buff == ResourceId())
@@ -594,6 +652,8 @@ bytebuf ReplayController::GetBufferData(ResourceId buff, uint64_t offset, uint64
bytebuf ReplayController::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip)
{
CHECK_REPLAY_THREAD();
bytebuf ret;
ResourceId liveId = m_pDevice->GetLiveID(tex);
@@ -611,6 +671,8 @@ bytebuf ReplayController::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint
bool ReplayController::SaveTexture(const TextureSave &saveData, const char *path)
{
CHECK_REPLAY_THREAD();
TextureSave sd = saveData; // mutable copy
ResourceId liveid = m_pDevice->GetLiveID(sd.resourceId);
@@ -1492,6 +1554,8 @@ rdcarray<PixelModification> ReplayController::PixelHistory(ResourceId target, ui
uint32_t y, uint32_t slice, uint32_t mip,
uint32_t sampleIdx, CompType typeHint)
{
CHECK_REPLAY_THREAD();
rdcarray<PixelModification> ret;
for(size_t t = 0; t < m_Textures.size(); t++)
@@ -1600,6 +1664,8 @@ rdcarray<PixelModification> ReplayController::PixelHistory(ResourceId target, ui
ShaderDebugTrace *ReplayController::DebugVertex(uint32_t vertid, uint32_t instid, uint32_t idx,
uint32_t instOffset, uint32_t vertOffset)
{
CHECK_REPLAY_THREAD();
ShaderDebugTrace *ret = new ShaderDebugTrace;
*ret = m_pDevice->DebugVertex(m_EventID, vertid, instid, idx, instOffset, vertOffset);
@@ -1612,6 +1678,8 @@ ShaderDebugTrace *ReplayController::DebugVertex(uint32_t vertid, uint32_t instid
ShaderDebugTrace *ReplayController::DebugPixel(uint32_t x, uint32_t y, uint32_t sample,
uint32_t primitive)
{
CHECK_REPLAY_THREAD();
ShaderDebugTrace *ret = new ShaderDebugTrace;
*ret = m_pDevice->DebugPixel(m_EventID, x, y, sample, primitive);
@@ -1623,6 +1691,8 @@ ShaderDebugTrace *ReplayController::DebugPixel(uint32_t x, uint32_t y, uint32_t
ShaderDebugTrace *ReplayController::DebugThread(const uint32_t groupid[3], const uint32_t threadid[3])
{
CHECK_REPLAY_THREAD();
ShaderDebugTrace *ret = new ShaderDebugTrace;
*ret = m_pDevice->DebugThread(m_EventID, groupid, threadid);
@@ -1634,12 +1704,16 @@ ShaderDebugTrace *ReplayController::DebugThread(const uint32_t groupid[3], const
void ReplayController::FreeTrace(ShaderDebugTrace *trace)
{
CHECK_REPLAY_THREAD();
delete trace;
}
rdcarray<ShaderVariable> ReplayController::GetCBufferVariableContents(
ResourceId shader, const char *entryPoint, uint32_t cbufslot, ResourceId buffer, uint64_t offs)
{
CHECK_REPLAY_THREAD();
bytebuf data;
if(buffer != ResourceId())
{
@@ -1660,11 +1734,15 @@ rdcarray<ShaderVariable> ReplayController::GetCBufferVariableContents(
rdcarray<WindowingSystem> ReplayController::GetSupportedWindowSystems()
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetSupportedWindowSystems();
}
rdcstr ReplayController::CreateRGPProfile(WindowingData window)
{
CHECK_REPLAY_THREAD();
AMDRGPControl *rgp = m_pDevice->GetRGPControl();
if(!rgp)
@@ -1734,6 +1812,8 @@ rdcstr ReplayController::CreateRGPProfile(WindowingData window)
void ReplayController::ReplayLoop(WindowingData window, ResourceId texid)
{
CHECK_REPLAY_THREAD();
ReplayOutput *output = CreateOutput(window, ReplayOutputType::Texture);
TextureDisplay d;
@@ -1777,6 +1857,8 @@ void ReplayController::ReplayLoop(WindowingData window, ResourceId texid)
void ReplayController::CancelReplayLoop()
{
CHECK_REPLAY_THREAD();
Atomic::Inc32(&m_ReplayLoopCancel);
// wait for it to actually finish before returning
@@ -1786,6 +1868,8 @@ void ReplayController::CancelReplayLoop()
ReplayOutput *ReplayController::CreateOutput(WindowingData window, ReplayOutputType type)
{
CHECK_REPLAY_THREAD();
ReplayOutput *out = new ReplayOutput(this, window, type);
m_Outputs.push_back(out);
@@ -1801,6 +1885,8 @@ ReplayOutput *ReplayController::CreateOutput(WindowingData window, ReplayOutputT
void ReplayController::ShutdownOutput(IReplayOutput *output)
{
CHECK_REPLAY_THREAD();
for(auto it = m_Outputs.begin(); it != m_Outputs.end(); ++it)
{
if((IReplayOutput *)*it == output)
@@ -1816,11 +1902,15 @@ void ReplayController::ShutdownOutput(IReplayOutput *output)
void ReplayController::Shutdown()
{
CHECK_REPLAY_THREAD();
delete this;
}
rdcarray<ShaderEncoding> ReplayController::GetTargetShaderEncodings()
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetTargetShaderEncodings();
}
@@ -1828,6 +1918,8 @@ rdcpair<ResourceId, rdcstr> ReplayController::BuildTargetShader(
const char *entry, ShaderEncoding sourceEncoding, bytebuf source,
const ShaderCompileFlags &compileFlags, ShaderStage type)
{
CHECK_REPLAY_THREAD();
rdcarray<ShaderEncoding> encodings = m_pDevice->GetTargetShaderEncodings();
if(encodings.indexOf(sourceEncoding) == -1)
@@ -1860,6 +1952,8 @@ rdcpair<ResourceId, rdcstr> ReplayController::BuildTargetShader(
rdcpair<ResourceId, rdcstr> ReplayController::BuildCustomShader(
const char *entry, const char *source, const ShaderCompileFlags &compileFlags, ShaderStage type)
{
CHECK_REPLAY_THREAD();
ResourceId id;
string errs;
@@ -1884,18 +1978,24 @@ rdcpair<ResourceId, rdcstr> ReplayController::BuildCustomShader(
void ReplayController::FreeTargetResource(ResourceId id)
{
CHECK_REPLAY_THREAD();
m_TargetResources.erase(id);
m_pDevice->FreeTargetResource(id);
}
void ReplayController::FreeCustomShader(ResourceId id)
{
CHECK_REPLAY_THREAD();
m_CustomShaders.erase(id);
m_pDevice->FreeCustomShader(id);
}
void ReplayController::ReplaceResource(ResourceId from, ResourceId to)
{
CHECK_REPLAY_THREAD();
m_pDevice->ReplaceResource(from, to);
SetFrameEvent(m_EventID, true);
@@ -1907,6 +2007,8 @@ void ReplayController::ReplaceResource(ResourceId from, ResourceId to)
void ReplayController::RemoveReplacement(ResourceId id)
{
CHECK_REPLAY_THREAD();
m_pDevice->RemoveReplacement(id);
SetFrameEvent(m_EventID, true);
@@ -1918,6 +2020,8 @@ void ReplayController::RemoveReplacement(ResourceId id)
ReplayStatus ReplayController::CreateDevice(RDCFile *rdc)
{
CHECK_REPLAY_THREAD();
IReplayDriver *driver = NULL;
ReplayStatus status = RenderDoc::Inst().CreateReplayDriver(rdc, &driver);
@@ -1933,6 +2037,8 @@ ReplayStatus ReplayController::CreateDevice(RDCFile *rdc)
ReplayStatus ReplayController::SetDevice(IReplayDriver *device)
{
CHECK_REPLAY_THREAD();
if(device)
{
RDCLOG("Got replay driver.");
@@ -1945,6 +2051,8 @@ ReplayStatus ReplayController::SetDevice(IReplayDriver *device)
ReplayStatus ReplayController::PostCreateInit(IReplayDriver *device, RDCFile *rdc)
{
CHECK_REPLAY_THREAD();
m_pDevice = device;
ReplayStatus status = m_pDevice->ReadLogInitialisation(rdc, false);
@@ -1992,16 +2100,22 @@ ReplayStatus ReplayController::PostCreateInit(IReplayDriver *device, RDCFile *rd
void ReplayController::FileChanged()
{
CHECK_REPLAY_THREAD();
m_pDevice->FileChanged();
}
APIProperties ReplayController::GetAPIProperties()
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetAPIProperties();
}
void ReplayController::FetchPipelineState()
{
CHECK_REPLAY_THREAD();
m_pDevice->SavePipelineState();
m_D3D11PipelineState = m_pDevice->GetD3D11PipelineState();
+6
View File
@@ -32,6 +32,8 @@
#include "core/core.h"
#include "replay/replay_driver.h"
#define CHECK_REPLAY_THREAD() RDCASSERT(Threading::GetCurrentID() == m_ThreadID);
struct ReplayController;
struct ReplayOutput : public IReplayOutput
@@ -76,6 +78,8 @@ private:
void DisplayMesh();
uint64_t m_ThreadID;
ReplayController *m_pRenderer;
bool m_OverlayDirty;
@@ -219,6 +223,8 @@ private:
FrameRecord m_FrameRecord;
vector<DrawcallDescription *> m_Drawcalls;
uint64_t m_ThreadID;
APIProperties m_APIProps;
std::vector<std::string> m_GCNTargets;
+48
View File
@@ -76,6 +76,8 @@ static uint64_t GetHandle(WindowingData window)
ReplayOutput::ReplayOutput(ReplayController *parent, WindowingData window, ReplayOutputType type)
{
m_ThreadID = Threading::GetCurrentID();
m_pRenderer = parent;
m_MainOutput.dirty = true;
@@ -116,6 +118,8 @@ ReplayOutput::ReplayOutput(ReplayController *parent, WindowingData window, Repla
void ReplayOutput::SetDimensions(int32_t width, int32_t height)
{
CHECK_REPLAY_THREAD();
if(m_MainOutput.outputID == 0)
{
m_Width = width;
@@ -125,6 +129,8 @@ void ReplayOutput::SetDimensions(int32_t width, int32_t height)
ReplayOutput::~ReplayOutput()
{
CHECK_REPLAY_THREAD();
m_pDevice->DestroyOutputWindow(m_MainOutput.outputID);
m_pDevice->DestroyOutputWindow(m_PixelContext.outputID);
@@ -135,11 +141,15 @@ ReplayOutput::~ReplayOutput()
void ReplayOutput::Shutdown()
{
CHECK_REPLAY_THREAD();
m_pRenderer->ShutdownOutput(this);
}
void ReplayOutput::SetTextureDisplay(const TextureDisplay &o)
{
CHECK_REPLAY_THREAD();
if(o.overlay != m_RenderData.texDisplay.overlay || o.typeHint != m_RenderData.texDisplay.typeHint ||
o.resourceId != m_RenderData.texDisplay.resourceId)
{
@@ -159,6 +169,8 @@ void ReplayOutput::SetTextureDisplay(const TextureDisplay &o)
void ReplayOutput::SetMeshDisplay(const MeshDisplay &o)
{
CHECK_REPLAY_THREAD();
if(o.showWholePass != m_RenderData.meshDisplay.showWholePass)
m_OverlayDirty = true;
m_RenderData.meshDisplay = o;
@@ -167,6 +179,8 @@ void ReplayOutput::SetMeshDisplay(const MeshDisplay &o)
void ReplayOutput::SetFrameEvent(int eventId)
{
CHECK_REPLAY_THREAD();
m_EventID = eventId;
m_OverlayDirty = true;
@@ -180,6 +194,8 @@ void ReplayOutput::SetFrameEvent(int eventId)
void ReplayOutput::RefreshOverlay()
{
CHECK_REPLAY_THREAD();
DrawcallDescription *draw = m_pRenderer->GetDrawcallByEID(m_EventID);
passEvents = m_pDevice->GetPassEvents(m_EventID);
@@ -236,11 +252,15 @@ void ReplayOutput::RefreshOverlay()
ResourceId ReplayOutput::GetCustomShaderTexID()
{
CHECK_REPLAY_THREAD();
return m_CustomShaderResourceId;
}
ResourceId ReplayOutput::GetDebugOverlayTexID()
{
CHECK_REPLAY_THREAD();
if(m_OverlayDirty)
{
m_pDevice->ReplayLog(m_EventID, eReplay_WithoutDraw);
@@ -253,6 +273,8 @@ ResourceId ReplayOutput::GetDebugOverlayTexID()
void ReplayOutput::ClearThumbnails()
{
CHECK_REPLAY_THREAD();
for(size_t i = 0; i < m_Thumbnails.size(); i++)
m_pDevice->DestroyOutputWindow(m_Thumbnails[i].outputID);
@@ -261,6 +283,8 @@ void ReplayOutput::ClearThumbnails()
bool ReplayOutput::SetPixelContext(WindowingData window)
{
CHECK_REPLAY_THREAD();
m_PixelContext.outputID = m_pDevice->MakeOutputWindow(window, false);
m_PixelContext.texture = ResourceId();
m_PixelContext.depthMode = false;
@@ -272,6 +296,8 @@ bool ReplayOutput::SetPixelContext(WindowingData window)
bool ReplayOutput::AddThumbnail(WindowingData window, ResourceId texID, CompType typeHint)
{
CHECK_REPLAY_THREAD();
OutputPair p;
RDCASSERT(window.system != WindowingSystem::Unknown);
@@ -320,6 +346,8 @@ bool ReplayOutput::AddThumbnail(WindowingData window, ResourceId texID, CompType
rdcpair<PixelValue, PixelValue> ReplayOutput::GetMinMax()
{
CHECK_REPLAY_THREAD();
PixelValue minval = {{0.0f, 0.0f, 0.0f, 0.0f}};
PixelValue maxval = {{1.0f, 1.0f, 1.0f, 1.0f}};
@@ -347,6 +375,8 @@ rdcpair<PixelValue, PixelValue> ReplayOutput::GetMinMax()
rdcarray<uint32_t> ReplayOutput::GetHistogram(float minval, float maxval, bool channels[4])
{
CHECK_REPLAY_THREAD();
vector<uint32_t> hist;
ResourceId tex = m_pDevice->GetLiveID(m_RenderData.texDisplay.resourceId);
@@ -373,6 +403,8 @@ rdcarray<uint32_t> ReplayOutput::GetHistogram(float minval, float maxval, bool c
PixelValue ReplayOutput::PickPixel(ResourceId tex, bool customShader, uint32_t x, uint32_t y,
uint32_t sliceFace, uint32_t mip, uint32_t sample)
{
CHECK_REPLAY_THREAD();
PixelValue ret;
RDCEraseEl(ret.floatValue);
@@ -408,6 +440,8 @@ PixelValue ReplayOutput::PickPixel(ResourceId tex, bool customShader, uint32_t x
rdcpair<uint32_t, uint32_t> ReplayOutput::PickVertex(uint32_t eventId, uint32_t x, uint32_t y)
{
CHECK_REPLAY_THREAD();
DrawcallDescription *draw = m_pRenderer->GetDrawcallByEID(eventId);
const rdcpair<uint32_t, uint32_t> errorReturn = make_rdcpair(~0U, ~0U);
@@ -481,6 +515,8 @@ rdcpair<uint32_t, uint32_t> ReplayOutput::PickVertex(uint32_t eventId, uint32_t
void ReplayOutput::SetPixelContextLocation(uint32_t x, uint32_t y)
{
CHECK_REPLAY_THREAD();
m_ContextX = RDCMAX((float)x, 0.0f);
m_ContextY = RDCMAX((float)y, 0.0f);
@@ -489,6 +525,8 @@ void ReplayOutput::SetPixelContextLocation(uint32_t x, uint32_t y)
void ReplayOutput::DisablePixelContext()
{
CHECK_REPLAY_THREAD();
m_ContextX = -1.0f;
m_ContextY = -1.0f;
@@ -497,6 +535,8 @@ void ReplayOutput::DisablePixelContext()
void ReplayOutput::ClearBackground(uint64_t outputID, const FloatVector &backgroundColor)
{
CHECK_REPLAY_THREAD();
if(m_RenderData.texDisplay.backgroundColor.x == 0.0f &&
m_RenderData.texDisplay.backgroundColor.y == 0.0f &&
m_RenderData.texDisplay.backgroundColor.z == 0.0f &&
@@ -508,6 +548,8 @@ void ReplayOutput::ClearBackground(uint64_t outputID, const FloatVector &backgro
void ReplayOutput::DisplayContext()
{
CHECK_REPLAY_THREAD();
if(m_PixelContext.outputID == 0)
return;
m_pDevice->BindOutputWindow(m_PixelContext.outputID, false);
@@ -570,6 +612,8 @@ void ReplayOutput::DisplayContext()
void ReplayOutput::Display()
{
CHECK_REPLAY_THREAD();
if(m_pDevice->CheckResizeOutputWindow(m_MainOutput.outputID))
{
m_pDevice->GetOutputWindowDimensions(m_MainOutput.outputID, m_Width, m_Height);
@@ -677,6 +721,8 @@ void ReplayOutput::Display()
void ReplayOutput::DisplayTex()
{
CHECK_REPLAY_THREAD();
DrawcallDescription *draw = m_pRenderer->GetDrawcallByEID(m_EventID);
if(m_MainOutput.outputID == 0)
@@ -760,6 +806,8 @@ void ReplayOutput::DisplayTex()
void ReplayOutput::DisplayMesh()
{
CHECK_REPLAY_THREAD();
DrawcallDescription *draw = m_pRenderer->GetDrawcallByEID(m_EventID);
if(draw == NULL || m_MainOutput.outputID == 0 || m_Width <= 0 || m_Height <= 0 ||