Add GLRenderState class to track GL state vector

* Use it to serialise in/out initial state at the start of each captured
  frame.
* Serialise active texture and buffer bindings (indexed and non-indexed).
This commit is contained in:
baldurk
2014-05-25 17:57:31 +01:00
parent ada40e303c
commit 5d7f296deb
10 changed files with 275 additions and 33 deletions
@@ -419,7 +419,6 @@ struct D3D11RenderState
void SetSerialiser(Serialiser *ser) { m_pSerialiser = ser; }
void Serialise(LogState state, WrappedID3D11Device *device);
ID3D11Resource *GetSerialised(ID3D11Resource *res) const;
void SetImmediatePipeline(WrappedID3D11Device *device) { m_ImmediatePipeline = true; m_pDevice = device; }
+24 -4
View File
@@ -984,10 +984,20 @@ size_t WrappedOpenGL::BufferIdx(GLenum buf)
{
switch(buf)
{
case eGL_ARRAY_BUFFER: return 0;
case eGL_ELEMENT_ARRAY_BUFFER: return 1;
case eGL_UNIFORM_BUFFER: return 2;
case eGL_COPY_READ_BUFFER: return 3;
case eGL_ARRAY_BUFFER: return 0;
case eGL_ATOMIC_COUNTER_BUFFER: return 1;
case eGL_COPY_READ_BUFFER: return 2;
case eGL_COPY_WRITE_BUFFER: return 3;
case eGL_DRAW_INDIRECT_BUFFER: return 4;
case eGL_DISPATCH_INDIRECT_BUFFER: return 5;
case eGL_ELEMENT_ARRAY_BUFFER: return 6;
case eGL_PIXEL_PACK_BUFFER: return 7;
case eGL_PIXEL_UNPACK_BUFFER: return 8;
case eGL_QUERY_BUFFER: return 9;
case eGL_SHADER_STORAGE_BUFFER: return 10;
case eGL_TEXTURE_BUFFER: return 11;
case eGL_TRANSFORM_FEEDBACK_BUFFER: return 12;
case eGL_UNIFORM_BUFFER: return 13;
default:
RDCERR("Unexpected enum as buffer target: %hs", ToStr::Get(buf).c_str());
}
@@ -1113,6 +1123,16 @@ void WrappedOpenGL::glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
m_Real.glBindBufferBase(target, index, buffer);
}
void WrappedOpenGL::glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
{
if(m_State >= WRITING)
{
RDCUNIMPLEMENTED();
}
m_Real.glBindBufferRange(target, index, buffer, offset, size);
}
void *WrappedOpenGL::glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
{
if(m_State >= WRITING)
+9 -28
View File
@@ -688,43 +688,19 @@ void WrappedOpenGL::AttemptCapture()
bool WrappedOpenGL::Serialise_BeginCaptureFrame(bool applyInitialState)
{
// TODO check GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS bound
// TODO fetch bindings for other types than 2D
ResourceId textures2D[128];
GLRenderState state(&m_Real, m_pSerialiser);
if(m_State >= WRITING)
{
for(int i=0; i < ARRAY_COUNT(textures2D); i++)
{
GLint binding = 0;
m_Real.glActiveTexture(GLenum(eGL_TEXTURE0 + i));
m_Real.glGetIntegerv(eGL_TEXTURE_BINDING_2D, &binding);
if(binding == 0)
textures2D[i] = ResourceId();
else
textures2D[i] = GetResourceManager()->GetID(TextureRes(binding));
}
state.FetchState();
}
m_pSerialiser->Serialise<128>("textures", textures2D);
state.Serialise(m_State, GetResourceManager());
if(m_State <= EXECUTING && applyInitialState)
{
m_DoStateVerify = false;
{
for(int i=0; i < ARRAY_COUNT(textures2D); i++)
{
m_Real.glActiveTexture(GLenum(eGL_TEXTURE0 + i));
if(textures2D[i] == ResourceId())
m_Real.glBindTexture(eGL_TEXTURE_2D, 0);
else
m_Real.glBindTexture(eGL_TEXTURE_2D, GetResourceManager()->GetLiveResource(textures2D[i]).name);
}
}
state.ApplyState();
m_DoStateVerify = true;
}
@@ -1376,6 +1352,11 @@ void WrappedOpenGL::glGetIntegeri_v(GLenum pname, GLuint index, GLint *data)
m_Real.glGetIntegeri_v(pname, index, data);
}
void WrappedOpenGL::glGetInteger64i_v(GLenum pname, GLuint index, GLint64 *data)
{
m_Real.glGetInteger64i_v(pname, index, data);
}
void WrappedOpenGL::glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
{
m_Real.glGetTexLevelParameteriv(target, level, pname, params);
+3
View File
@@ -36,6 +36,7 @@
#include "gl_hookset.h"
#include "gl_resources.h"
#include "gl_manager.h"
#include "gl_renderstate.h"
#include "gl_replay.h"
#include <list>
@@ -275,6 +276,7 @@ class WrappedOpenGL
IMPLEMENT_FUNCTION_SERIALISED(void, glGetFloatv(GLenum pname, GLfloat *params));
IMPLEMENT_FUNCTION_SERIALISED(void, glGetIntegerv(GLenum pname, GLint *params));
IMPLEMENT_FUNCTION_SERIALISED(void, glGetIntegeri_v(GLenum target, GLuint index, GLint *data));
IMPLEMENT_FUNCTION_SERIALISED(void, glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data));
IMPLEMENT_FUNCTION_SERIALISED(const GLubyte *, glGetStringi(GLenum name, GLuint i));
IMPLEMENT_FUNCTION_SERIALISED(const GLubyte *, glGetString(GLenum name));
IMPLEMENT_FUNCTION_SERIALISED(void, glGenTextures(GLsizei n, GLuint* textures));
@@ -339,6 +341,7 @@ class WrappedOpenGL
IMPLEMENT_FUNCTION_SERIALISED(void, glBindBuffer(GLenum target, GLuint buffer));
IMPLEMENT_FUNCTION_SERIALISED(void, glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage));
IMPLEMENT_FUNCTION_SERIALISED(void, glBindBufferBase(GLenum target, GLuint index, GLuint buffer));
IMPLEMENT_FUNCTION_SERIALISED(void, glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size));
IMPLEMENT_FUNCTION_SERIALISED(void *, glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access));
IMPLEMENT_FUNCTION_SERIALISED(GLboolean, glUnmapBuffer(GLenum target));
+2
View File
@@ -91,6 +91,7 @@ struct GLHookSet
PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv;
PFNGLGETSTRINGIPROC glGetStringi;
PFNGLGETINTEGERI_VPROC glGetIntegeri_v;
PFNGLGETINTEGER64I_VPROC glGetInteger64i_v;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLSHADERSOURCEPROC glShaderSource;
@@ -119,6 +120,7 @@ struct GLHookSet
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
PFNGLBUFFERDATAPROC glBufferData;
PFNGLBINDBUFFERBASEPROC glBindBufferBase;
PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
PFNGLUNMAPBUFFERPROC glUnmapBuffer;
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
+4
View File
@@ -102,6 +102,7 @@
HookExtension(PFNGLGETBUFFERPARAMETERIVPROC, glGetBufferParameteriv); \
HookExtension(PFNGLGETSTRINGIPROC, glGetStringi); \
HookExtension(PFNGLGETINTEGERI_VPROC, glGetIntegeri_v); \
HookExtension(PFNGLGETINTEGER64I_VPROC, glGetInteger64i_v); \
HookExtension(PFNGLCREATESHADERPROC, glCreateShader); \
HookExtension(PFNGLDELETESHADERPROC, glDeleteShader); \
HookExtension(PFNGLSHADERSOURCEPROC, glShaderSource); \
@@ -131,6 +132,7 @@
HookExtension(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC, glGetFramebufferAttachmentParameteriv); \
HookExtension(PFNGLBUFFERDATAPROC, glBufferData); \
HookExtension(PFNGLBINDBUFFERBASEPROC, glBindBufferBase); \
HookExtension(PFNGLBINDBUFFERRANGEPROC, glBindBufferRange); \
HookExtension(PFNGLMAPBUFFERRANGEPROC, glMapBufferRange); \
HookExtension(PFNGLUNMAPBUFFERPROC, glUnmapBuffer); \
HookExtension(PFNGLDELETEBUFFERSPROC, glDeleteBuffers); \
@@ -277,6 +279,7 @@
HookWrapper3(void, glGetBufferParameteriv, GLenum, target, GLenum, pname, GLint *, params); \
HookWrapper2(const GLubyte *, glGetStringi, GLenum, name, GLuint, index); \
HookWrapper3(void, glGetIntegeri_v, GLenum, target, GLuint, index, GLint *, data); \
HookWrapper3(void, glGetInteger64i_v, GLenum, target, GLuint, index, GLint64 *, data); \
HookWrapper1(GLuint, glCreateShader, GLenum, type); \
HookWrapper1(void, glDeleteShader, GLuint, shader); \
HookWrapper4(void, glShaderSource, GLuint, shader, GLsizei, count, const GLchar *const*, string, const GLint *, length); \
@@ -305,6 +308,7 @@
HookWrapper4(void, glGetFramebufferAttachmentParameteriv, GLenum, target, GLenum, attachment, GLenum, pname, GLint *, params); \
HookWrapper4(void, glBufferData, GLenum, target, GLsizeiptr, size, const void *, data, GLenum, usage); \
HookWrapper3(void, glBindBufferBase, GLenum, target, GLuint, index, GLuint, buffer); \
HookWrapper5(void, glBindBufferRange, GLenum, target, GLuint, index, GLuint, buffer, GLintptr, offset, GLsizeiptr, size); \
HookWrapper4(void *, glMapBufferRange, GLenum, target, GLintptr, offset, GLsizeiptr, length, GLbitfield, access); \
HookWrapper1(GLboolean, glUnmapBuffer, GLenum, target); \
HookWrapper2(void, glDeleteBuffers, GLsizei, n, const GLuint *, buffers); \
+168
View File
@@ -0,0 +1,168 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "gl_renderstate.h"
GLRenderState::GLRenderState(const GLHookSet *funcs, Serialiser *ser)
: m_Real(funcs)
, m_pSerialiser(ser)
{
Clear();
}
GLRenderState::~GLRenderState()
{
}
void GLRenderState::FetchState()
{
// TODO check GL_MAX_*
m_Real->glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint *)&ActiveTexture);
// TODO fetch bindings for other types than 2D
for(int i=0; i < ARRAY_COUNT(Tex2D); i++)
{
m_Real->glActiveTexture(GLenum(eGL_TEXTURE0 + i));
m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_2D, (GLint*)&Tex2D[i]);
}
m_Real->glActiveTexture(ActiveTexture);
m_Real->glGetIntegerv(eGL_ARRAY_BUFFER_BINDING, (GLint*)&BufferBindings[0]);
m_Real->glGetIntegerv(eGL_COPY_READ_BUFFER_BINDING, (GLint*)&BufferBindings[1]);
m_Real->glGetIntegerv(eGL_COPY_WRITE_BUFFER_BINDING, (GLint*)&BufferBindings[2]);
m_Real->glGetIntegerv(eGL_DRAW_INDIRECT_BUFFER_BINDING, (GLint*)&BufferBindings[3]);
m_Real->glGetIntegerv(eGL_DISPATCH_INDIRECT_BUFFER_BINDING, (GLint*)&BufferBindings[4]);
m_Real->glGetIntegerv(eGL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint*)&BufferBindings[5]);
m_Real->glGetIntegerv(eGL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&BufferBindings[6]);
m_Real->glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, (GLint*)&BufferBindings[7]);
m_Real->glGetIntegerv(eGL_QUERY_BUFFER_BINDING, (GLint*)&BufferBindings[8]);
m_Real->glGetIntegerv(eGL_TEXTURE_BUFFER_BINDING, (GLint*)&BufferBindings[9]);
struct { IdxRangeBuffer *bufs; int count; GLenum binding; GLenum start; GLenum size; } idxBufs[] =
{
{ AtomicCounter, ARRAY_COUNT(AtomicCounter), eGL_ATOMIC_COUNTER_BUFFER_BINDING, },
{ ShaderStorage, ARRAY_COUNT(ShaderStorage), eGL_SHADER_STORAGE_BUFFER_BINDING, },
{ TransformFeedback, ARRAY_COUNT(TransformFeedback), eGL_TRANSFORM_FEEDBACK_BUFFER_BINDING, },
{ UniformBinding, ARRAY_COUNT(UniformBinding), eGL_UNIFORM_BUFFER_BINDING, },
};
for(int b=0; b < ARRAY_COUNT(idxBufs); b++)
{
for(int i=0; i < idxBufs[b].count; i++)
{
m_Real->glGetIntegeri_v(idxBufs[b].binding, i, (GLint*)&idxBufs[b].bufs[i].name);
m_Real->glGetInteger64i_v(idxBufs[b].start, i, (GLint64*)&idxBufs[b].bufs[i].start);
m_Real->glGetInteger64i_v(idxBufs[b].size, i, (GLint64*)&idxBufs[b].bufs[i].size);
}
}
}
void GLRenderState::ApplyState()
{
for(int i=0; i < ARRAY_COUNT(Tex2D); i++)
{
m_Real->glActiveTexture(GLenum(eGL_TEXTURE0 + i));
m_Real->glBindTexture(eGL_TEXTURE_2D, Tex2D[i]);
}
m_Real->glActiveTexture(ActiveTexture);
m_Real->glBindBuffer(eGL_ARRAY_BUFFER, BufferBindings[0]);
m_Real->glBindBuffer(eGL_COPY_READ_BUFFER, BufferBindings[1]);
m_Real->glBindBuffer(eGL_COPY_WRITE_BUFFER, BufferBindings[2]);
m_Real->glBindBuffer(eGL_DRAW_INDIRECT_BUFFER, BufferBindings[3]);
m_Real->glBindBuffer(eGL_DISPATCH_INDIRECT_BUFFER, BufferBindings[4]);
m_Real->glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, BufferBindings[5]);
m_Real->glBindBuffer(eGL_PIXEL_PACK_BUFFER, BufferBindings[6]);
m_Real->glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, BufferBindings[7]);
m_Real->glBindBuffer(eGL_QUERY_BUFFER, BufferBindings[8]);
m_Real->glBindBuffer(eGL_TEXTURE_BUFFER, BufferBindings[9]);
struct { IdxRangeBuffer *bufs; int count; GLenum binding; } idxBufs[] =
{
{ AtomicCounter, ARRAY_COUNT(AtomicCounter), eGL_ATOMIC_COUNTER_BUFFER, },
{ ShaderStorage, ARRAY_COUNT(ShaderStorage), eGL_SHADER_STORAGE_BUFFER, },
{ TransformFeedback, ARRAY_COUNT(TransformFeedback), eGL_TRANSFORM_FEEDBACK_BUFFER, },
{ UniformBinding, ARRAY_COUNT(UniformBinding), eGL_UNIFORM_BUFFER, },
};
for(int b=0; b < ARRAY_COUNT(idxBufs); b++)
for(int i=0; i < idxBufs[b].count; i++)
m_Real->glBindBufferRange(idxBufs[b].binding, i, idxBufs[b].bufs[i].name, (GLintptr)idxBufs[b].bufs[i].start, (GLsizeiptr)idxBufs[b].bufs[i].size);
}
void GLRenderState::Clear()
{
RDCEraseEl(Tex2D);
RDCEraseEl(ActiveTexture);
RDCEraseEl(BufferBindings);
RDCEraseEl(AtomicCounter);
RDCEraseEl(ShaderStorage);
RDCEraseEl(TransformFeedback);
RDCEraseEl(UniformBinding);
}
void GLRenderState::Serialise(LogState state, GLResourceManager *rm)
{
// TODO check GL_MAX_*
{
ResourceId IDs[128];
m_pSerialiser->Serialise<128>("GL_TEXTURE_BINDING_2D", IDs);
}
m_pSerialiser->Serialise("GL_ACTIVE_TEXTURE", ActiveTexture);
for(int i=0; i < ARRAY_COUNT(BufferBindings); i++)
{
ResourceId ID = ResourceId();
if(state >= WRITING) ID = rm->GetID(BufferRes(BufferBindings[i]));
m_pSerialiser->Serialise("GL_BUFFER_BINDING", ID);
if(state < WRITING) BufferBindings[i] = rm->GetLiveResource(ID).name;
}
struct { IdxRangeBuffer *bufs; int count; } idxBufs[] =
{
{ AtomicCounter, ARRAY_COUNT(AtomicCounter), },
{ ShaderStorage, ARRAY_COUNT(ShaderStorage), },
{ TransformFeedback, ARRAY_COUNT(TransformFeedback), },
{ UniformBinding, ARRAY_COUNT(UniformBinding), },
};
for(int b=0; b < ARRAY_COUNT(idxBufs); b++)
{
for(int i=0; i < idxBufs[b].count; i++)
{
ResourceId ID = ResourceId();
if(state >= WRITING) ID = rm->GetID(BufferRes(idxBufs[b].bufs[i].name));
m_pSerialiser->Serialise("BUFFER_BINDING", ID);
if(state < WRITING) idxBufs[b].bufs[i].name = rm->GetLiveResource(ID).name;
m_pSerialiser->Serialise("BUFFER_START", idxBufs[b].bufs[i].start);
m_pSerialiser->Serialise("BUFFER_SIZE", idxBufs[b].bufs[i].size);
}
}
}
+57
View File
@@ -0,0 +1,57 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#pragma once
#include "gl_common.h"
#include "gl_hookset.h"
#include "gl_manager.h"
struct GLRenderState
{
GLRenderState(const GLHookSet *funcs, Serialiser *ser);
~GLRenderState();
void FetchState();
void ApplyState();
void Clear();
//
uint32_t Tex2D[128];
GLenum ActiveTexture;
uint32_t BufferBindings[10];
struct IdxRangeBuffer
{
uint32_t name;
uint64_t start;
uint64_t size;
} AtomicCounter[8], ShaderStorage[8], TransformFeedback[8], UniformBinding[128];
//
void Serialise(LogState state, GLResourceManager *rm);
private:
Serialiser *m_pSerialiser;
const GLHookSet *m_Real;
};
+2
View File
@@ -262,6 +262,7 @@
<ClInclude Include="driver\gl\gl_hookset_defs.h" />
<ClInclude Include="driver\gl\gl_legacy_procs.h" />
<ClInclude Include="driver\gl\gl_manager.h" />
<ClInclude Include="driver\gl\gl_renderstate.h" />
<ClInclude Include="driver\gl\gl_replay.h" />
<ClInclude Include="driver\gl\gl_resources.h" />
<ClInclude Include="driver\gl\official\glcorearb.h" />
@@ -332,6 +333,7 @@
<ClCompile Include="driver\gl\gl_device_driver.cpp" />
<ClCompile Include="driver\gl\gl_driver.cpp" />
<ClCompile Include="driver\gl\gl_manager.cpp" />
<ClCompile Include="driver\gl\gl_renderstate.cpp" />
<ClCompile Include="driver\gl\gl_replay.cpp" />
<ClCompile Include="driver\gl\gl_replay_win32.cpp" />
<ClCompile Include="driver\gl\gl_resources.cpp" />
+6
View File
@@ -285,6 +285,9 @@
<ClInclude Include="replay\gl_pipestate.h">
<Filter>Replay\external interface</Filter>
</ClInclude>
<ClInclude Include="driver\gl\gl_renderstate.h">
<Filter>Drivers\OpenGL</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="maths\camera.cpp">
@@ -473,6 +476,9 @@
<ClCompile Include="driver\gl\gl_debug.cpp">
<Filter>Drivers\OpenGL</Filter>
</ClCompile>
<ClCompile Include="driver\gl\gl_renderstate.cpp">
<Filter>Drivers\OpenGL</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="os\win32\comexport.def">