Store read/draw buffers for FBOs in initial data

* This avoids spamming of glReadBuffer/glDrawBuffer calls pointlessly into
  the pre-frame chunk stream.
* The default FBO stores its ReadBuffer and DrawBuffers in the initial
  frame state vector.
This commit is contained in:
baldurk
2014-12-07 15:24:46 +00:00
parent acb66bf626
commit 1cff12ee87
6 changed files with 153 additions and 41 deletions
+2 -2
View File
@@ -1422,7 +1422,7 @@ bool WrappedOpenGL::Serialise_BeginCaptureFrame(bool applyInitialState)
if(m_State >= WRITING)
{
state.FetchState();
state.FetchState(GetCtx(), this);
}
state.Serialise(m_State, GetCtx(), this);
@@ -1430,7 +1430,7 @@ bool WrappedOpenGL::Serialise_BeginCaptureFrame(bool applyInitialState)
if(m_State <= EXECUTING && applyInitialState)
{
m_DoStateVerify = false;
state.ApplyState();
state.ApplyState(GetCtx(), this);
m_DoStateVerify = true;
}
+81
View File
@@ -59,6 +59,12 @@ struct FeedbackInitialData
uint64_t Size[4];
};
struct FramebufferInitialData
{
GLenum DrawBuffers[8];
GLenum ReadBuffer;
};
template<>
void Serialiser::Serialise(const char *name, VertexAttribInitialData &el)
{
@@ -91,6 +97,14 @@ void Serialiser::Serialise(const char *name, FeedbackInitialData &el)
Serialise<4>("Size", el.Size);
}
template<>
void Serialiser::Serialise(const char *name, FramebufferInitialData &el)
{
ScopedContext scope(this, this, name, "FramebufferInitialData", 0, true);
Serialise<8>("DrawBuffers", el.DrawBuffers);
Serialise("ReadBuffer", el.ReadBuffer);
}
struct TextureStateInitialData
{
int32_t baseLevel, maxLevel;
@@ -280,6 +294,34 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
SetInitialContents(Id, InitialContentData(TextureRes(res.Context, tex), 0, (byte *)state));
}
else if(res.Namespace == eResFramebuffer)
{
// need to be on the right context, as feedback objects are never shared
void *oldctx = m_GL->SwitchToContext(res.Context);
GLuint prevread = 0, prevdraw = 0;
gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint *)&prevdraw);
gl.glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, (GLint *)&prevread);
gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, res.name);
gl.glBindFramebuffer(eGL_READ_FRAMEBUFFER, res.name);
FramebufferInitialData *data = (FramebufferInitialData *)Serialiser::AllocAlignedBuffer(sizeof(FramebufferInitialData));
RDCEraseMem(data, sizeof(FramebufferInitialData));
for(int i=0; i < (int)ARRAY_COUNT(data->DrawBuffers); i++)
gl.glGetIntegerv(GLenum(eGL_DRAW_BUFFER0 + i), (GLint *)&data->DrawBuffers[i]);
gl.glGetIntegerv(eGL_READ_BUFFER, (GLint *)&data->ReadBuffer);
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, (byte *)data));
gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, prevdraw);
gl.glBindFramebuffer(eGL_READ_FRAMEBUFFER, prevread);
// restore the previous context
m_GL->SwitchToContext(oldctx);
}
else if(res.Namespace == eResFeedback)
{
// need to be on the right context, as feedback objects are never shared
@@ -795,6 +837,26 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
gl.glPixelStorei(eGL_UNPACK_ALIGNMENT, unpackParams[7]);
}
}
else if(res.Namespace == eResFramebuffer)
{
FramebufferInitialData data;
if(m_State >= WRITING)
{
FramebufferInitialData *initialdata = (FramebufferInitialData *)GetInitialContents(Id).blob;
memcpy(&data, initialdata, sizeof(data));
}
m_pSerialiser->Serialise("Framebuffer object Buffers", data);
if(m_State < WRITING)
{
byte *blob = Serialiser::AllocAlignedBuffer(sizeof(data));
memcpy(blob, &data, sizeof(data));
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, blob));
}
}
else if(res.Namespace == eResFeedback)
{
FeedbackInitialData data;
@@ -936,6 +998,25 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i
{
CopyProgramUniforms(gl, initial.resource.name, live.name);
}
else if(live.Namespace == eResFramebuffer)
{
GLuint prevread = 0, prevdraw = 0;
gl.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint *)&prevdraw);
gl.glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, (GLint *)&prevread);
gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, live.name);
gl.glBindFramebuffer(eGL_READ_FRAMEBUFFER, live.name);
FramebufferInitialData *data = (FramebufferInitialData *)initial.blob;
for(int i=0; i < (int)ARRAY_COUNT(data->DrawBuffers); i++)
gl.glDrawBuffers(ARRAY_COUNT(data->DrawBuffers), data->DrawBuffers);
gl.glReadBuffer(data->ReadBuffer);
gl.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, prevdraw);
gl.glBindFramebuffer(eGL_READ_FRAMEBUFFER, prevread);
}
else if(live.Namespace == eResFeedback)
{
GLuint prevfeedback = 0;
+23 -6
View File
@@ -37,7 +37,7 @@ GLRenderState::~GLRenderState()
{
}
void GLRenderState::FetchState()
void GLRenderState::FetchState(void *ctx, WrappedOpenGL *gl)
{
GLint boolread = 0;
// TODO check GL_MAX_*
@@ -211,9 +211,17 @@ void GLRenderState::FetchState()
m_Real->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint *)&DrawFBO);
m_Real->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, (GLint *)&ReadFBO);
m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, 0);
m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, 0);
for(size_t i=0; i < ARRAY_COUNT(DrawBuffers); i++)
m_Real->glGetIntegerv(GLenum(eGL_DRAW_BUFFER0 + i), (GLint *)&DrawBuffers[i]);
m_Real->glGetIntegerv(eGL_READ_BUFFER, (GLint *)&ReadBuffer);
m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, DrawFBO);
m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, ReadFBO);
m_Real->glGetIntegerv(eGL_FRAGMENT_SHADER_DERIVATIVE_HINT, (GLint *)&Hints.Derivatives);
m_Real->glGetIntegerv(eGL_LINE_SMOOTH_HINT, (GLint *)&Hints.LineSmooth);
m_Real->glGetIntegerv(eGL_POLYGON_SMOOTH_HINT, (GLint *)&Hints.PolySmooth);
@@ -287,7 +295,7 @@ void GLRenderState::FetchState()
m_Real->glGetIntegerv(eGL_CULL_FACE_MODE, (GLint *)&CullFace);
}
void GLRenderState::ApplyState()
void GLRenderState::ApplyState(void *ctx, WrappedOpenGL *gl)
{
{
GLenum pnames[] =
@@ -437,9 +445,6 @@ void GLRenderState::ApplyState()
m_Real->glDisablei(eGL_SCISSOR_TEST, s);
}
m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, ReadFBO);
m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, DrawFBO);
GLenum DBs[8] = { eGL_NONE };
uint32_t numDBs = 0;
for(GLuint i=0; i < (GLuint)ARRAY_COUNT(DrawBuffers); i++)
@@ -469,7 +474,17 @@ void GLRenderState::ApplyState()
break;
}
}
// apply drawbuffers/readbuffer to default framebuffer
m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, gl->GetFakeBBFBO());
m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, gl->GetFakeBBFBO());
m_Real->glDrawBuffers(numDBs, DBs);
// see above for reasoning for this
m_Real->glReadBuffer(eGL_COLOR_ATTACHMENT0);
m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, ReadFBO);
m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, DrawFBO);
m_Real->glHint(eGL_FRAGMENT_SHADER_DERIVATIVE_HINT, Hints.Derivatives);
m_Real->glHint(eGL_LINE_SMOOTH_HINT, Hints.LineSmooth);
@@ -565,6 +580,7 @@ void GLRenderState::Clear()
RDCEraseEl(DrawFBO);
RDCEraseEl(ReadFBO);
RDCEraseEl(DrawBuffers);
RDCEraseEl(ReadBuffer);
RDCEraseEl(PatchParams);
RDCEraseEl(PolygonMode);
@@ -746,7 +762,8 @@ void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl)
m_pSerialiser->Serialise("GL_SCISSOR.enabled", Scissors[i].enabled);
}
m_pSerialiser->Serialise<8>("GL_DRAWBUFFERS", DrawBuffers);
m_pSerialiser->Serialise<8>("GL_DRAW_BUFFERS", DrawBuffers);
m_pSerialiser->Serialise("GL_READ_BUFFER", ReadBuffer);
m_pSerialiser->Serialise("GL_FRAGMENT_SHADER_DERIVATIVE_HINT", Hints.Derivatives);
m_pSerialiser->Serialise("GL_LINE_SMOOTH_HINT", Hints.LineSmooth);
+6 -3
View File
@@ -36,8 +36,8 @@ struct GLRenderState
GLRenderState(const GLHookSet *funcs, Serialiser *ser, LogState state);
~GLRenderState();
void FetchState();
void ApplyState();
void FetchState(void *ctx, WrappedOpenGL *gl);
void ApplyState(void *ctx, WrappedOpenGL *gl);
void Clear();
void Serialise(LogState state, void *ctx, WrappedOpenGL *gl);
@@ -151,12 +151,15 @@ struct GLRenderState
} Scissors[16];
GLuint ReadFBO, DrawFBO;
// these refer to the states on the default framebuffer.
// Other FBOs serialise them in their resource records.
GLenum ReadBuffer;
GLenum DrawBuffers[8];
// TODO:
// Image state (GL_IMAGE_BINDING_NAME)
// multisampling
// provoking vertex
// other misc state :)
struct
+1 -1
View File
@@ -820,7 +820,7 @@ void GLReplay::SavePipelineState()
MakeCurrentReplayContext(&m_ReplayCtx);
GLRenderState rs(&gl.GetHookset(), NULL, READING);
rs.FetchState();
rs.FetchState(m_ReplayCtx.ctx, &gl);
// Index buffer
@@ -728,26 +728,19 @@ void WrappedOpenGL::glReadBuffer(GLenum mode)
if(m_State >= WRITING)
{
SCOPED_SERIALISE_CONTEXT(READ_BUFFER);
Serialise_glReadBuffer(mode);
if(m_State == WRITING_IDLE)
if(m_State == WRITING_CAPFRAME)
{
if(GetCtxData().m_ReadFramebufferRecord)
{
Chunk *last = GetCtxData().m_ReadFramebufferRecord->GetLastChunk();
if(last->GetChunkType() == READ_BUFFER)
{
delete last;
GetCtxData().m_ReadFramebufferRecord->PopChunk();
}
GetCtxData().m_ReadFramebufferRecord->AddChunk(scope.Get());
}
else
m_DeviceRecord->AddChunk(scope.Get());
SCOPED_SERIALISE_CONTEXT(READ_BUFFER);
Serialise_glReadBuffer(mode);
m_ContextRecord->AddChunk(scope.Get());
}
else
m_ContextRecord->AddChunk(scope.Get());
{
GLResourceRecord *readrecord = GetCtxData().m_ReadFramebufferRecord;
if(readrecord)
GetResourceManager()->MarkDirtyResource(readrecord->GetResourceID());
}
}
}
@@ -813,12 +806,21 @@ bool WrappedOpenGL::Serialise_glDrawBuffer(GLenum buf)
void WrappedOpenGL::glDrawBuffer(GLenum buf)
{
if(m_State == WRITING_CAPFRAME)
if(m_State >= WRITING)
{
SCOPED_SERIALISE_CONTEXT(DRAW_BUFFER);
Serialise_glDrawBuffer(buf);
m_ContextRecord->AddChunk(scope.Get());
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAW_BUFFER);
Serialise_glDrawBuffer(buf);
m_ContextRecord->AddChunk(scope.Get());
}
else
{
GLResourceRecord *drawrecord = GetCtxData().m_DrawFramebufferRecord;
if(drawrecord)
GetResourceManager()->MarkDirtyResource(drawrecord->GetResourceID());
}
}
m_Real.glDrawBuffer(buf);
@@ -872,15 +874,24 @@ void WrappedOpenGL::glFramebufferDrawBuffersEXT(GLuint framebuffer, GLsizei n, c
void WrappedOpenGL::glDrawBuffers(GLsizei n, const GLenum *bufs)
{
if(m_State == WRITING_CAPFRAME)
if(m_State >= WRITING)
{
SCOPED_SERIALISE_CONTEXT(DRAW_BUFFERS);
if(GetCtxData().m_DrawFramebufferRecord)
Serialise_glFramebufferDrawBuffersEXT(GetResourceManager()->GetCurrentResource(GetCtxData().m_DrawFramebufferRecord->GetResourceID()).name, n, bufs);
GLResourceRecord *drawrecord = GetCtxData().m_DrawFramebufferRecord;
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(DRAW_BUFFERS);
if(drawrecord)
Serialise_glFramebufferDrawBuffersEXT(GetResourceManager()->GetCurrentResource(drawrecord->GetResourceID()).name, n, bufs);
else
Serialise_glFramebufferDrawBuffersEXT(0, n, bufs);
m_ContextRecord->AddChunk(scope.Get());
}
else
Serialise_glFramebufferDrawBuffersEXT(0, n, bufs);
m_ContextRecord->AddChunk(scope.Get());
{
if(drawrecord)
GetResourceManager()->MarkDirtyResource(drawrecord->GetResourceID());
}
}
m_Real.glDrawBuffers(n, bufs);