diff --git a/renderdoc/core/image_viewer.cpp b/renderdoc/core/image_viewer.cpp index 9abca1639..daf83b379 100644 --- a/renderdoc/core/image_viewer.cpp +++ b/renderdoc/core/image_viewer.cpp @@ -140,13 +140,24 @@ class ImageViewer : public IReplayDriver // these are proxy functions, and will never be used ResourceId CreateProxyTexture(FetchTexture templateTex) { - RDCERR("Calling proxy-render functions on a proxy serialiser"); + RDCERR("Calling proxy-render functions on an image viewer"); return ResourceId(); } void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize) { - RDCERR("Calling proxy-render functions on a proxy serialiser"); + RDCERR("Calling proxy-render functions on an image viewer"); + } + + ResourceId CreateProxyBuffer(FetchBuffer templateBuf) + { + RDCERR("Calling proxy-render functions on an image viewer"); + return ResourceId(); + } + + void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize) + { + RDCERR("Calling proxy-render functions on an image viewer"); } private: diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 3673ba3d8..be687aa27 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -947,7 +947,7 @@ bool ProxySerialiser::SendReplayCommand(CommandPacketType type) return true; } -void ProxySerialiser::EnsureCached(ResourceId texid, uint32_t arrayIdx, uint32_t mip) +void ProxySerialiser::EnsureTexCached(ResourceId texid, uint32_t arrayIdx, uint32_t mip) { TextureCacheEntry entry = { texid, arrayIdx, mip }; @@ -976,6 +976,27 @@ void ProxySerialiser::EnsureCached(ResourceId texid, uint32_t arrayIdx, uint32_t } } +void ProxySerialiser::EnsureBufCached(ResourceId bufid) +{ + if(m_BufferProxyCache.find(bufid) == m_BufferProxyCache.end()) + { + if(m_ProxyBufferIds.find(bufid) == m_ProxyBufferIds.end()) + { + FetchBuffer buf = GetBuffer(bufid); + m_ProxyBufferIds[bufid] = m_Proxy->CreateProxyBuffer(buf); + } + + ResourceId proxyid = m_ProxyBufferIds[bufid]; + + vector data = GetBufferData(bufid, 0, 0); + + if(!data.empty()) + m_Proxy->SetProxyBufferData(proxyid, &data[0], data.size()); + + m_BufferProxyCache.insert(bufid); + } +} + bool ProxySerialiser::Tick() { if(!m_ReplayHost) return true; @@ -1010,7 +1031,7 @@ bool ProxySerialiser::Tick() GetBuffers(); break; case eCommand_GetBuffer: - GetTexture(ResourceId()); + GetBuffer(ResourceId()); break; case eCommand_GetShader: GetShader(ResourceId()); @@ -1310,6 +1331,7 @@ void ProxySerialiser::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_ return; m_TextureProxyCache.clear(); + m_BufferProxyCache.clear(); } } diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index fc73df1ac..881c2dbf3 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -175,7 +175,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver { if(m_Proxy) { - EnsureCached(texid, sliceFace, mip); + EnsureTexCached(texid, sliceFace, mip); return m_Proxy->GetMinMax(m_ProxyTextureIds[texid], sliceFace, mip, sample, minval, maxval); } @@ -186,7 +186,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver { if(m_Proxy) { - EnsureCached(texid, sliceFace, mip); + EnsureTexCached(texid, sliceFace, mip); return m_Proxy->GetHistogram(m_ProxyTextureIds[texid], sliceFace, mip, sample, minval, maxval, channels, histogram); } @@ -197,7 +197,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver { if(m_Proxy) { - EnsureCached(cfg.texid, cfg.sliceFace, cfg.mip); + EnsureTexCached(cfg.texid, cfg.sliceFace, cfg.mip); cfg.texid = m_ProxyTextureIds[cfg.texid]; return m_Proxy->RenderTexture(cfg); } @@ -209,15 +209,48 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver { if(m_Proxy) { - EnsureCached(texture, sliceFace, mip); + EnsureTexCached(texture, sliceFace, mip); m_Proxy->PickPixel(m_ProxyTextureIds[texture], x, y, sliceFace, mip, sample, pixel); } } void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg) { - if(m_Proxy) - m_Proxy->RenderCheckerboard(Vec3f(0.7f, 0.3f, 0.3f), Vec3f(0.3f, 0.3f, 0.7f)); + if(m_Proxy && cfg.position.buf != ResourceId()) + { + EnsureBufCached(cfg.position.buf); + cfg.position.buf = m_ProxyBufferIds[cfg.position.buf]; + + if(cfg.second.buf != ResourceId()) + { + EnsureBufCached(cfg.second.buf); + cfg.second.buf = m_ProxyBufferIds[cfg.second.buf]; + } + + if(cfg.position.idxbuf != ResourceId()) + { + EnsureBufCached(cfg.position.idxbuf); + cfg.position.idxbuf = m_ProxyBufferIds[cfg.position.idxbuf]; + } + + vector secDraws = secondaryDraws; + + for(size_t i=0; i < secDraws.size(); i++) + { + if(secDraws[i].buf != ResourceId()) + { + EnsureBufCached(secDraws[i].buf); + secDraws[i].buf = m_ProxyBufferIds[secDraws[i].buf]; + } + if(secDraws[i].idxbuf != ResourceId()) + { + EnsureBufCached(secDraws[i].idxbuf); + secDraws[i].idxbuf = m_ProxyBufferIds[secDraws[i].idxbuf]; + } + } + + m_Proxy->RenderMesh(frameID, eventID, secDraws, cfg); + } } void BuildCustomShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors) @@ -243,7 +276,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver { if(m_Proxy) { - EnsureCached(texid, 0, mip); + EnsureTexCached(texid, 0, mip); texid = m_ProxyTextureIds[texid]; ResourceId customResourceId = m_Proxy->ApplyCustomShader(shader, texid, mip); m_LocalTextures.insert(customResourceId); @@ -323,11 +356,23 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver RDCERR("Calling proxy-render functions on a proxy serialiser"); } + ResourceId CreateProxyBuffer(FetchBuffer templateBuf) + { + RDCERR("Calling proxy-render functions on a proxy serialiser"); + return ResourceId(); + } + + void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize) + { + RDCERR("Calling proxy-render functions on a proxy serialiser"); + } + private: bool SendReplayCommand(CommandPacketType type); void CopyDrawcallTimes(rdctype::array &src, rdctype::array &dst); - void EnsureCached(ResourceId texid, uint32_t arrayIdx, uint32_t mip); + void EnsureTexCached(ResourceId texid, uint32_t arrayIdx, uint32_t mip); + void EnsureBufCached(ResourceId bufid); struct TextureCacheEntry { @@ -348,6 +393,9 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver set m_LocalTextures; map m_ProxyTextureIds; + set m_BufferProxyCache; + map m_ProxyBufferIds; + map m_LiveIDs; map m_ShaderReflectionCache; diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 91a02123a..1090d6767 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -381,7 +381,9 @@ FetchBuffer D3D11Replay::GetBuffer(ResourceId id) ret.name = str; ret.length = it->second.length; - ret.structureSize = desc.StructureByteStride; + ret.structureSize = 0; + if(desc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) + ret.structureSize = desc.StructureByteStride; ret.byteSize = desc.ByteWidth; ret.creationFlags = 0; @@ -1618,6 +1620,89 @@ void D3D11Replay::SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint3 } } +ResourceId D3D11Replay::CreateProxyBuffer(FetchBuffer templateBuf) +{ + ResourceId ret; + + ID3D11Resource *resource = NULL; + + { + ID3D11Buffer *throwaway = NULL; + D3D11_BUFFER_DESC desc; + + desc.ByteWidth = (UINT)templateBuf.byteSize; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + + if(templateBuf.structureSize > 0) + { + desc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.StructureByteStride = templateBuf.structureSize; + } + + if(templateBuf.creationFlags & eBufferCreate_Indirect) + { + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; + } + if(templateBuf.creationFlags & eBufferCreate_IB) + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + if(templateBuf.creationFlags & eBufferCreate_CB) + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + if(templateBuf.creationFlags & eBufferCreate_UAV) + desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS|D3D11_BIND_SHADER_RESOURCE; + + HRESULT hr = m_pDevice->CreateBuffer(&desc, NULL, &throwaway); + if(FAILED(hr)) + { + RDCERR("Failed to create proxy buffer"); + return ResourceId(); + } + + resource = throwaway; + + ret = ((WrappedID3D11Buffer *)throwaway)->GetResourceID(); + } + + if(resource != NULL && templateBuf.customName) + { + string name = templateBuf.name.elems; + SetDebugName(resource, templateBuf.name.elems); + } + + return ret; +} + +void D3D11Replay::SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize) +{ + if(bufid == ResourceId()) return; + + ID3D11DeviceContext *ctx = m_pDevice->GetImmediateContext()->GetReal(); + + if(WrappedID3D11Buffer::m_BufferList.find(bufid) != WrappedID3D11Buffer::m_BufferList.end()) + { + WrappedID3D11Buffer *buf = (WrappedID3D11Buffer *)WrappedID3D11Buffer::m_BufferList[bufid].m_Buffer; + + D3D11_BUFFER_DESC desc; + buf->GetDesc(&desc); + + if(dataSize < desc.ByteWidth) + { + RDCERR("Insufficient data provided to SetProxyBufferData"); + return; + } + + ctx->UpdateSubresource(buf->GetReal(), 0, NULL, data, dataSize, dataSize); + } + else + { + RDCERR("Invalid buffer id passed to SetProxyBufferData"); + } +} + ReplayCreateStatus D3D11_CreateReplayDevice(const char *logfile, IReplayDriver **driver) { RDCDEBUG("Creating a D3D11 replay device"); diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index c9e0dc0fb..433d4fafe 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -100,6 +100,9 @@ class D3D11Replay : public IReplayDriver ResourceId CreateProxyTexture(FetchTexture templateTex); void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize); + + ResourceId CreateProxyBuffer(FetchBuffer templateBuf); + void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize); void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg); diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index ccd51b105..70d05a457 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -2255,6 +2255,17 @@ void GLReplay::SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t RDCUNIMPLEMENTED("SetProxyTextureData"); } +ResourceId GLReplay::CreateProxyBuffer(FetchBuffer templateBuf) +{ + RDCUNIMPLEMENTED("CreateProxyBuffer"); + return ResourceId(); +} + +void GLReplay::SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize) +{ + RDCUNIMPLEMENTED("SetProxyBufferData"); +} + const GLHookSet &GetRealFunctions(); // defined in gl_replay_.cpp diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 3a062558b..93e38cdcc 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -166,6 +166,9 @@ class GLReplay : public IReplayDriver ResourceId CreateProxyTexture(FetchTexture templateTex); void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize); + + ResourceId CreateProxyBuffer(FetchBuffer templateBuf); + void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize); bool IsRenderOutput(ResourceId id); diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index b8dab17f4..228115609 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -129,6 +129,9 @@ class IReplayDriver : public IRemoteDriver virtual ResourceId CreateProxyTexture(FetchTexture templateTex) = 0; virtual void SetProxyTextureData(ResourceId texid, uint32_t arrayIdx, uint32_t mip, byte *data, size_t dataSize) = 0; + + virtual ResourceId CreateProxyBuffer(FetchBuffer templateBuf) = 0; + virtual void SetProxyBufferData(ResourceId bufid, byte *data, size_t dataSize) = 0; virtual void RenderMesh(uint32_t frameID, uint32_t eventID, const vector &secondaryDraws, MeshDisplay cfg) = 0; virtual bool RenderTexture(TextureDisplay cfg) = 0;