diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index eff962695..2f6db95ea 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -773,6 +773,41 @@ void GLMarkerRegion::End() gl->glPopDebugGroup(); } +GLInitParams::GLInitParams() +{ + colorBits = 32; + depthBits = 32; + stencilBits = 8; + isSRGB = 1; + multiSamples = 1; + width = 32; + height = 32; +} + +bool GLInitParams::IsSupportedVersion(uint64_t ver) +{ + if(ver == CurrentVersion) + return true; + + // we can check other older versions we support here. + + return false; +} + +template +void DoSerialise(SerialiserType &ser, GLInitParams &el) +{ + SERIALISE_MEMBER(colorBits); + SERIALISE_MEMBER(depthBits); + SERIALISE_MEMBER(stencilBits); + SERIALISE_MEMBER(isSRGB); + SERIALISE_MEMBER(multiSamples); + SERIALISE_MEMBER(width); + SERIALISE_MEMBER(height); +} + +INSTANTIATE_SERIALISE_TYPE(GLInitParams); + size_t BufferIdx(GLenum buf) { switch(buf) diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 2f74a8d8f..e88911e4d 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -44,74 +44,6 @@ const float charPixelHeight = 20.0f; stbtt_bakedchar chardata[numChars]; - -GLInitParams::GLInitParams() -{ - SerialiseVersion = GL_SERIALISE_VERSION; - colorBits = 32; - depthBits = 32; - stencilBits = 8; - isSRGB = 1; - multiSamples = 1; - width = 32; - height = 32; -} - -// handling for these versions is scattered throughout the code (as relevant to enable/disable bits -// of serialisation and set some defaults if necessary). -// Here we list which non-current versions we support, and what changed -const uint32_t GLInitParams::GL_OLD_VERSIONS[GLInitParams::GL_NUM_SUPPORTED_OLD_VERSIONS] = { - 0x000010, // from 0x10 to 0x11, we added a dummy marker value used to identify serialised - // data in glUseProgramStages (hack :( ) - 0x000011, // We added initial contents for buffers in this version, we don't have to do - // anything special to support older logs, just make sure we don't open new logs - // in an older version. - 0x000012, // Added support for GL-DX interop - 0x000013, // Serialised vertex attribute and fragdata bindings for programs as initial - // contents data - 0x000014, // Added support for primitive bounding boxes on GLES - 0x000015, // Changed serialisation of client-side index buffers which removed a bool even - // when they aren't used. -}; - -ReplayStatus GLInitParams::Serialise() -{ - SERIALISE_ELEMENT(uint32_t, ver, GL_SERIALISE_VERSION); - SerialiseVersion = ver; - - if(ver != GL_SERIALISE_VERSION) - { - bool oldsupported = false; - for(uint32_t i = 0; i < GL_NUM_SUPPORTED_OLD_VERSIONS; i++) - { - if(ver == GL_OLD_VERSIONS[i]) - { - oldsupported = true; - RDCWARN( - "Old OpenGL serialise version %d, latest is %d. Loading with possibly degraded " - "features/support.", - ver, GL_SERIALISE_VERSION); - } - } - - if(!oldsupported) - { - RDCERR("Incompatible OpenGL serialise version, expected %d got %d", GL_SERIALISE_VERSION, ver); - return ReplayStatus::APIIncompatibleVersion; - } - } - - m_pSerialiser->Serialise("Color bits", colorBits); - m_pSerialiser->Serialise("Depth bits", depthBits); - m_pSerialiser->Serialise("Stencil bits", stencilBits); - m_pSerialiser->Serialise("Is SRGB", isSRGB); - m_pSerialiser->Serialise("MSAA samples", multiSamples); - m_pSerialiser->Serialise("Width", width); - m_pSerialiser->Serialise("Height", height); - - return ReplayStatus::Succeeded; -} - void WrappedOpenGL::BuildGLExtensions() { m_GLExtensions.push_back("GL_ARB_arrays_of_arrays"); @@ -554,7 +486,7 @@ void WrappedOpenGL::BuildGLESExtensions() std::sort(m_GLESExtensions.begin(), m_GLESExtensions.end()); } -WrappedOpenGL::WrappedOpenGL(const char *logfile, const GLHookSet &funcs, GLPlatform &platform) +WrappedOpenGL::WrappedOpenGL(const GLHookSet &funcs, GLPlatform &platform) : m_Real(funcs), m_Platform(platform) { if(RenderDoc::Inst().GetCrashHandler()) diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index f5ec4c0f1..fb23febf0 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -40,10 +40,9 @@ using std::list; -struct GLInitParams : public RDCInitParams +struct GLInitParams { GLInitParams(); - ReplayStatus Serialise(); uint32_t colorBits; uint32_t depthBits; @@ -53,16 +52,13 @@ struct GLInitParams : public RDCInitParams uint32_t width; uint32_t height; - static const uint32_t GL_SERIALISE_VERSION = 0x0000016; - - // backwards compatibility for old logs described at the declaration of this array - static const uint32_t GL_NUM_SUPPORTED_OLD_VERSIONS = 6; - static const uint32_t GL_OLD_VERSIONS[GL_NUM_SUPPORTED_OLD_VERSIONS]; - - // version number internal to opengl stream - uint32_t SerialiseVersion; + // check if a frame capture section version is supported + static const uint64_t CurrentVersion = 0x17; + static bool IsSupportedVersion(uint64_t ver); }; +DECLARE_REFLECTION_STRUCT(GLInitParams); + enum CaptureFailReason { CaptureSucceeded = 0, @@ -123,6 +119,7 @@ private: RDCDriver m_DriverType; GLInitParams m_InitParams; + uint64_t m_SectionVersion; map m_ActiveContexts; @@ -511,10 +508,10 @@ private: WrappedOpenGL &operator=(const WrappedOpenGL &); public: - WrappedOpenGL(const char *logfile, const GLHookSet &funcs, GLPlatform &platform); + WrappedOpenGL(const GLHookSet &funcs, GLPlatform &platform); virtual ~WrappedOpenGL(); - uint32_t GetLogVersion() { return m_InitParams.SerialiseVersion; } + uint64_t GetLogVersion() { return m_SectionVersion; } static const char *GetChunkName(uint32_t idx); GLResourceManager *GetResourceManager() { return m_ResourceManager; } ResourceId GetDeviceResourceID() { return m_DeviceResourceID; } @@ -538,7 +535,7 @@ public: void AddMissingTrack(ResourceId id) { m_MissingTracks.insert(id); } // replay interface - void Initialise(GLInitParams ¶ms); + void Initialise(GLInitParams ¶ms, uint64_t sectionVersion); void ReplayLog(uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType); void ReadLogInitialisation(); diff --git a/renderdoc/driver/gl/gl_hooks_egl.cpp b/renderdoc/driver/gl/gl_hooks_egl.cpp index b9254c081..5bcaead68 100644 --- a/renderdoc/driver/gl/gl_hooks_egl.cpp +++ b/renderdoc/driver/gl/gl_hooks_egl.cpp @@ -309,7 +309,7 @@ public: { if(m_GLDriver == NULL) { - m_GLDriver = new WrappedOpenGL("", GL, *this); + m_GLDriver = new WrappedOpenGL(GL, *this); m_GLDriver->SetDriverType(RDC_OpenGLES); } diff --git a/renderdoc/driver/gl/gl_hooks_linux.cpp b/renderdoc/driver/gl/gl_hooks_linux.cpp index 58d220048..648213faa 100644 --- a/renderdoc/driver/gl/gl_hooks_linux.cpp +++ b/renderdoc/driver/gl/gl_hooks_linux.cpp @@ -375,7 +375,7 @@ public: WrappedOpenGL *GetDriver() { if(m_GLDriver == NULL) - m_GLDriver = new WrappedOpenGL("", GL, *this); + m_GLDriver = new WrappedOpenGL(GL, *this); return m_GLDriver; } diff --git a/renderdoc/driver/gl/gl_hooks_win32.cpp b/renderdoc/driver/gl/gl_hooks_win32.cpp index 663d3e5bc..f68edbdcc 100644 --- a/renderdoc/driver/gl/gl_hooks_win32.cpp +++ b/renderdoc/driver/gl/gl_hooks_win32.cpp @@ -832,7 +832,7 @@ private: WrappedOpenGL *GetDriver() { if(m_GLDriver == NULL) - m_GLDriver = new WrappedOpenGL("", GL, *this); + m_GLDriver = new WrappedOpenGL(GL, *this); return m_GLDriver; } diff --git a/renderdoc/driver/gl/gl_replay_apple.cpp b/renderdoc/driver/gl/gl_replay_apple.cpp index a7ab6f86c..c474095c8 100644 --- a/renderdoc/driver/gl/gl_replay_apple.cpp +++ b/renderdoc/driver/gl/gl_replay_apple.cpp @@ -23,10 +23,11 @@ ******************************************************************************/ #include "gl_replay.h" +#include "serialise/rdcfile.h" #include "gl_driver.h" #include "gl_resources.h" -ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) +ReplayStatus GL_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) { RDCUNIMPLEMENTED("GL_CreateReplayDevice"); return ReplayStatus::APIHardwareUnsupported; diff --git a/renderdoc/driver/gl/gl_replay_egl.cpp b/renderdoc/driver/gl/gl_replay_egl.cpp index beabeef90..20128faba 100644 --- a/renderdoc/driver/gl/gl_replay_egl.cpp +++ b/renderdoc/driver/gl/gl_replay_egl.cpp @@ -24,6 +24,7 @@ #include "gl_replay.h" #include +#include "serialise/rdcfile.h" #include "gl_driver.h" #include "gl_resources.h" @@ -64,7 +65,7 @@ PFN_eglGetProcAddress eglGetProcAddressProc = NULL; const GLHookSet &GetRealGLFunctionsEGL(); GLPlatform &GetGLPlatformEGL(); -ReplayStatus GLES_CreateReplayDevice(const char *logfile, IReplayDriver **driver) +ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) { RDCDEBUG("Creating an OpenGL ES replay device"); @@ -101,16 +102,44 @@ ReplayStatus GLES_CreateReplayDevice(const char *logfile, IReplayDriver **driver } GLInitParams initParams; - RDCDriver driverType = RDC_OpenGLES; - string driverName = "OpenGLES"; - uint64_t machineIdent = 0; + uint64_t ver = GLInitParams::CurrentVersion; - if(logfile) + // if we have an RDCFile, open the frame capture section and serialise the init params. + // if not, we're creating a proxy-capable device so use default-initialised init params. + if(rdc) { - auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, machineIdent, - (RDCInitParams *)&initParams); - if(status != ReplayStatus::Succeeded) - return status; + int sectionIdx = rdc->SectionIndex(SectionType::FrameCapture); + + if(sectionIdx < 0) + return ReplayStatus::InternalError; + + ver = rdc->GetSectionProperties(sectionIdx).version; + + if(!GLInitParams::IsSupportedVersion(ver)) + { + RDCERR("Incompatible D3D11 serialise version %llu", ver); + return ReplayStatus::APIUnsupported; + } + + StreamReader *reader = rdc->ReadSection(sectionIdx); + + ReadSerialiser ser(reader, Ownership::Stream); + + SystemChunk chunk = ser.ReadChunk(); + + if(chunk != SystemChunk::DriverInit) + { + RDCERR("Expected to get a DriverInit chunk, instead got %u", chunk); + return ReplayStatus::FileCorrupted; + } + + SERIALISE_ELEMENT(initParams); + + if(ser.IsErrored()) + { + RDCERR("Failed reading driver init params."); + return ReplayStatus::FileIOFailed; + } } #if ENABLED(RDOC_ANDROID) @@ -195,19 +224,13 @@ ReplayStatus GLES_CreateReplayDevice(const char *logfile, IReplayDriver **driver return ReplayStatus::APIHardwareUnsupported; } - WrappedOpenGL *gl = new WrappedOpenGL(logfile, real, GetGLPlatformEGL()); + WrappedOpenGL *gl = new WrappedOpenGL(real, GetGLPlatformEGL()); gl->SetDriverType(RDC_OpenGLES); - gl->Initialise(initParams); - - if(gl->GetSerialiser()->HasError()) - { - delete gl; - return ReplayStatus::FileIOFailed; - } + gl->Initialise(initParams, ver); RDCLOG("Created OPEN GL ES replay device."); GLReplay *replay = gl->GetReplay(); - replay->SetProxy(logfile == NULL); + replay->SetProxy(rdc == NULL); GLWindowingData data; data.egl_dpy = eglDisplay; data.egl_ctx = ctx; diff --git a/renderdoc/driver/gl/gl_replay_linux.cpp b/renderdoc/driver/gl/gl_replay_linux.cpp index fef9a3b8a..f534bc07a 100644 --- a/renderdoc/driver/gl/gl_replay_linux.cpp +++ b/renderdoc/driver/gl/gl_replay_linux.cpp @@ -25,6 +25,7 @@ #include "gl_replay.h" #include +#include "serialise/rdcfile.h" #include "gl_driver.h" #include "gl_resources.h" @@ -53,7 +54,7 @@ int NonFatalX11ErrorHandler(Display *display, XErrorEvent *error) typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *error); -ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) +ReplayStatus GL_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) { RDCDEBUG("Creating an OpenGL replay device"); @@ -91,15 +92,44 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) } GLInitParams initParams; - RDCDriver driverType = RDC_OpenGL; - string driverName = "OpenGL"; - uint64_t machineIdent = 0; - if(logfile) + uint64_t ver = GLInitParams::CurrentVersion; + + // if we have an RDCFile, open the frame capture section and serialise the init params. + // if not, we're creating a proxy-capable device so use default-initialised init params. + if(rdc) { - auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, machineIdent, - (RDCInitParams *)&initParams); - if(status != ReplayStatus::Succeeded) - return status; + int sectionIdx = rdc->SectionIndex(SectionType::FrameCapture); + + if(sectionIdx < 0) + return ReplayStatus::InternalError; + + ver = rdc->GetSectionProperties(sectionIdx).version; + + if(!GLInitParams::IsSupportedVersion(ver)) + { + RDCERR("Incompatible D3D11 serialise version %llu", ver); + return ReplayStatus::APIUnsupported; + } + + StreamReader *reader = rdc->ReadSection(sectionIdx); + + ReadSerialiser ser(reader, Ownership::Stream); + + SystemChunk chunk = ser.ReadChunk(); + + if(chunk != SystemChunk::DriverInit) + { + RDCERR("Expected to get a DriverInit chunk, instead got %u", chunk); + return ReplayStatus::FileCorrupted; + } + + SERIALISE_ELEMENT(initParams); + + if(ser.IsErrored()) + { + RDCERR("Failed reading driver init params."); + return ReplayStatus::FileIOFailed; + } } int attribs[64] = {0}; @@ -259,18 +289,12 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) } } - WrappedOpenGL *gl = new WrappedOpenGL(logfile, real, GetGLPlatform()); - gl->Initialise(initParams); - - if(gl->GetSerialiser()->HasError()) - { - delete gl; - return ReplayStatus::FileIOFailed; - } + WrappedOpenGL *gl = new WrappedOpenGL(real, GetGLPlatform()); + gl->Initialise(initParams, ver); RDCLOG("Created device."); GLReplay *replay = gl->GetReplay(); - replay->SetProxy(logfile == NULL); + replay->SetProxy(rdc == NULL); GLWindowingData data; data.dpy = dpy; data.ctx = ctx; diff --git a/renderdoc/driver/gl/gl_replay_win32.cpp b/renderdoc/driver/gl/gl_replay_win32.cpp index 1fad0d5bd..fab7ca6bd 100644 --- a/renderdoc/driver/gl/gl_replay_win32.cpp +++ b/renderdoc/driver/gl/gl_replay_win32.cpp @@ -24,6 +24,7 @@ ******************************************************************************/ #include "gl_replay.h" +#include "serialise/rdcfile.h" #include "gl_driver.h" #include "gl_resources.h" @@ -40,7 +41,7 @@ WGLCREATECONTEXTPROC wglCreateRC = NULL; WGLMAKECURRENTPROC wglMakeCurrentProc = NULL; WGLDELETECONTEXTPROC wglDeleteRC = NULL; -ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) +ReplayStatus GL_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) { RDCDEBUG("Creating an OpenGL replay device"); @@ -53,15 +54,44 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) } GLInitParams initParams; - RDCDriver driverType = RDC_OpenGL; - string driverName = "OpenGL"; - uint64_t machineIdent = 0; - if(logfile) + uint64_t ver = GLInitParams::CurrentVersion; + + // if we have an RDCFile, open the frame capture section and serialise the init params. + // if not, we're creating a proxy-capable device so use default-initialised init params. + if(rdc) { - auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, machineIdent, - (RDCInitParams *)&initParams); - if(status != ReplayStatus::Succeeded) - return status; + int sectionIdx = rdc->SectionIndex(SectionType::FrameCapture); + + if(sectionIdx < 0) + return ReplayStatus::InternalError; + + ver = rdc->GetSectionProperties(sectionIdx).version; + + if(!GLInitParams::IsSupportedVersion(ver)) + { + RDCERR("Incompatible D3D11 serialise version %llu", ver); + return ReplayStatus::APIUnsupported; + } + + StreamReader *reader = rdc->ReadSection(sectionIdx); + + ReadSerialiser ser(reader, Ownership::Stream); + + SystemChunk chunk = ser.ReadChunk(); + + if(chunk != SystemChunk::DriverInit) + { + RDCERR("Expected to get a DriverInit chunk, instead got %u", chunk); + return ReplayStatus::FileCorrupted; + } + + SERIALISE_ELEMENT(initParams); + + if(ser.IsErrored()) + { + RDCERR("Failed reading driver init params."); + return ReplayStatus::FileIOFailed; + } } PIXELFORMATDESCRIPTOR pfd = {0}; @@ -287,18 +317,12 @@ ReplayStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver) return ReplayStatus::APIInitFailed; } - WrappedOpenGL *gl = new WrappedOpenGL(logfile, real, GetGLPlatform()); - gl->Initialise(initParams); - - if(gl->GetSerialiser()->HasError()) - { - delete gl; - return ReplayStatus::FileIOFailed; - } + WrappedOpenGL *gl = new WrappedOpenGL(real, GetGLPlatform()); + gl->Initialise(initParams, ver); RDCLOG("Created device."); GLReplay *replay = gl->GetReplay(); - replay->SetProxy(logfile == NULL); + replay->SetProxy(rdc == NULL); GLWindowingData data; data.DC = dc; data.ctx = rc;