Add initial contents and dirtying for high-frequency samplers

* For samplers that are updated a lot we fall back to fetching & applying their
  state as initial contents.
This commit is contained in:
baldurk
2019-01-16 13:47:56 +00:00
parent adbf24da77
commit f395f244eb
5 changed files with 233 additions and 7 deletions
+4
View File
@@ -1141,6 +1141,10 @@ bool GLInitParams::IsSupportedVersion(uint64_t ver)
if(ver == 0x1D)
return true;
// 0x1E -> 0x1F - added initial states for samplers that are modified a lot
if(ver == 0x1E)
return true;
return false;
}
+1 -1
View File
@@ -54,7 +54,7 @@ struct GLInitParams
bool isYFlipped;
// check if a frame capture section version is supported
static const uint64_t CurrentVersion = 0x1E;
static const uint64_t CurrentVersion = 0x1F;
static bool IsSupportedVersion(uint64_t ver);
};
+129
View File
@@ -108,6 +108,22 @@ void DoSerialise(SerialiserType &ser, PipelineInitialData &el)
SERIALISE_MEMBER(programs);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, SamplerInitialData &el)
{
SERIALISE_MEMBER(valid);
SERIALISE_MEMBER(border);
SERIALISE_MEMBER(compareFunc);
SERIALISE_MEMBER(compareMode);
SERIALISE_MEMBER(lodBias);
SERIALISE_MEMBER(minLod);
SERIALISE_MEMBER(maxLod);
SERIALISE_MEMBER(minFilter);
SERIALISE_MEMBER(magFilter);
SERIALISE_MEMBER(maxAniso);
SERIALISE_MEMBER(wrap);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, TextureStateInitialData &el)
{
@@ -287,6 +303,47 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
GL.glGetProgramPipelineiv(res.name, eGL_TESS_EVALUATION_SHADER, (GLint *)&data.programs[2].name);
GL.glGetProgramPipelineiv(res.name, eGL_COMPUTE_SHADER, (GLint *)&data.programs[5].name);
}
else if(res.Namespace == eResSampler)
{
SamplerInitialData &data = initContents.samp;
RDCASSERT(!data.valid);
data.valid = true;
GLenum activeTexture = eGL_TEXTURE0;
GL.glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint *)&activeTexture);
GL.glActiveTexture(eGL_TEXTURE0);
GLuint prevsampler = 0;
GL.glGetIntegerv(eGL_SAMPLER_BINDING, (GLint *)&prevsampler);
{
GL.glGetSamplerParameteriv(res.name, eGL_TEXTURE_COMPARE_FUNC, (GLint *)&data.compareFunc);
GL.glGetSamplerParameteriv(res.name, eGL_TEXTURE_COMPARE_MODE, (GLint *)&data.compareMode);
GL.glGetSamplerParameteriv(res.name, eGL_TEXTURE_MIN_FILTER, (GLint *)&data.minFilter);
GL.glGetSamplerParameteriv(res.name, eGL_TEXTURE_MAG_FILTER, (GLint *)&data.magFilter);
GL.glGetSamplerParameteriv(res.name, eGL_TEXTURE_WRAP_R, (GLint *)&data.wrap[0]);
GL.glGetSamplerParameteriv(res.name, eGL_TEXTURE_WRAP_S, (GLint *)&data.wrap[1]);
GL.glGetSamplerParameteriv(res.name, eGL_TEXTURE_WRAP_T, (GLint *)&data.wrap[2]);
GL.glGetSamplerParameterfv(res.name, eGL_TEXTURE_MIN_LOD, &data.minLod);
GL.glGetSamplerParameterfv(res.name, eGL_TEXTURE_MAX_LOD, &data.maxLod);
if(!IsGLES)
GL.glGetSamplerParameterfv(res.name, eGL_TEXTURE_LOD_BIAS, &data.lodBias);
// technically border color has been in since GL 1.0, but since this extension was really
// early and dovetails nicely with OES_texture_border_color which added both border colors and
// clamping, we check it.
if(HasExt[ARB_texture_border_clamp])
GL.glGetSamplerParameterfv(res.name, eGL_TEXTURE_BORDER_COLOR, &data.border[0]);
else
data.border[0] = data.border[1] = data.border[2] = data.border[3] = 1.0f;
}
GL.glBindSampler(0, prevsampler);
GL.glActiveTexture(activeTexture);
}
else if(res.Namespace == eResFeedback)
{
FeedbackInitialData &data = initContents.xfb;
@@ -500,6 +557,20 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
ContextPrepare_InitialState(res);
}
}
else if(res.Namespace == eResSampler)
{
// queue initial state fetching if we're not on the right context, see above in FBOs for more
// explanation of this.
ContextPair &ctx = m_Driver->GetCtx();
if(res.ContextShareGroup != ctx.ctx && res.ContextShareGroup != ctx.shareGroup)
{
m_Driver->QueuePrepareInitialState(res);
}
else
{
ContextPrepare_InitialState(res);
}
}
else if(res.Namespace == eResFeedback)
{
// queue initial state fetching if we're not on the right context, see above in FBOs for more
@@ -1088,6 +1159,11 @@ uint32_t GLResourceManager::GetSize_InitialState(ResourceId resid, GLResource re
{
return sizeof(FramebufferInitialData);
}
else if(res.Namespace == eResSampler)
{
// reserve some extra size to account for array count
return sizeof(SamplerInitialData) + 32;
}
else if(res.Namespace == eResFeedback)
{
return sizeof(FeedbackInitialData);
@@ -1671,6 +1747,22 @@ bool GLResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceId r
SetInitialContents(Id, initContents);
}
}
else if(Type == eResSampler)
{
SamplerInitialData &SamplerState = initContents.samp;
SERIALISE_ELEMENT(SamplerState);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
byte *blob = AllocAlignedBuffer(sizeof(SamplerState));
memcpy(blob, &SamplerState, sizeof(SamplerState));
SetInitialContents(Id, initContents);
}
}
else if(Type == eResFeedback)
{
FeedbackInitialData &TransformFeedbackState = initContents.xfb;
@@ -2180,6 +2272,43 @@ void GLResourceManager::Apply_InitialState(GLResource live, GLInitialContents in
GL.glBindFramebuffer(eGL_READ_FRAMEBUFFER, prevread);
}
}
else if(live.Namespace == eResSampler)
{
const SamplerInitialData &data = initial.samp;
if(data.valid)
{
GLenum activeTexture = eGL_TEXTURE0;
GL.glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint *)&activeTexture);
GL.glActiveTexture(eGL_TEXTURE0);
GLuint prevsampler = 0;
GL.glGetIntegerv(eGL_SAMPLER_BINDING, (GLint *)&prevsampler);
{
GL.glSamplerParameteri(live.name, eGL_TEXTURE_COMPARE_FUNC, (GLint)data.compareFunc);
GL.glSamplerParameteri(live.name, eGL_TEXTURE_COMPARE_MODE, (GLint)data.compareMode);
GL.glSamplerParameteri(live.name, eGL_TEXTURE_MIN_FILTER, (GLint)data.minFilter);
GL.glSamplerParameteri(live.name, eGL_TEXTURE_MAG_FILTER, (GLint)data.magFilter);
GL.glSamplerParameteri(live.name, eGL_TEXTURE_WRAP_R, (GLint)data.wrap[0]);
GL.glSamplerParameteri(live.name, eGL_TEXTURE_WRAP_S, (GLint)data.wrap[1]);
GL.glSamplerParameteri(live.name, eGL_TEXTURE_WRAP_T, (GLint)data.wrap[2]);
GL.glSamplerParameterf(live.name, eGL_TEXTURE_MIN_LOD, data.minLod);
GL.glSamplerParameterf(live.name, eGL_TEXTURE_MAX_LOD, data.maxLod);
if(!IsGLES)
GL.glSamplerParameterf(live.name, eGL_TEXTURE_LOD_BIAS, data.lodBias);
// see fetch in PrepareTextureInitialContents
if(HasExt[ARB_texture_border_clamp])
GL.glSamplerParameterfv(live.name, eGL_TEXTURE_BORDER_COLOR, &data.border[0]);
}
GL.glBindSampler(0, prevsampler);
GL.glActiveTexture(activeTexture);
}
}
else if(live.Namespace == eResFeedback)
{
const FeedbackInitialData &data = initial.xfb;
+15
View File
@@ -99,6 +99,20 @@ struct FramebufferInitialData
DECLARE_REFLECTION_STRUCT(FramebufferInitialData);
struct SamplerInitialData
{
bool valid;
float border[4];
GLenum compareFunc, compareMode;
float lodBias;
float minLod, maxLod;
GLenum minFilter, magFilter;
float maxAniso;
GLenum wrap[3];
};
DECLARE_REFLECTION_STRUCT(SamplerInitialData);
struct PipelineInitialData
{
bool valid;
@@ -164,6 +178,7 @@ struct GLInitialContents
VAOInitialData vao;
FeedbackInitialData xfb;
FramebufferInitialData fbo;
SamplerInitialData samp;
PipelineInitialData pipe;
TextureStateInitialData tex;
};
@@ -273,13 +273,26 @@ void WrappedOpenGL::glSamplerParameteri(GLuint sampler, GLenum pname, GLint para
if(IsCaptureMode(m_State))
{
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler));
if(m_HighTrafficResources.find(record->GetResourceID()) != m_HighTrafficResources.end() &&
IsBackgroundCapturing(m_State))
return;
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(gl_CurChunk);
Serialise_glSamplerParameteri(ser, sampler, pname, param);
if(IsBackgroundCapturing(m_State))
{
GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler))->AddChunk(scope.Get());
record->AddChunk(scope.Get());
record->UpdateCount++;
if(record->UpdateCount > 20)
{
m_HighTrafficResources.insert(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
}
}
else
{
@@ -320,13 +333,26 @@ void WrappedOpenGL::glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat pa
if(IsCaptureMode(m_State))
{
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler));
if(m_HighTrafficResources.find(record->GetResourceID()) != m_HighTrafficResources.end() &&
IsBackgroundCapturing(m_State))
return;
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(gl_CurChunk);
Serialise_glSamplerParameterf(ser, sampler, pname, param);
if(IsBackgroundCapturing(m_State))
{
GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler))->AddChunk(scope.Get());
record->AddChunk(scope.Get());
record->UpdateCount++;
if(record->UpdateCount > 20)
{
m_HighTrafficResources.insert(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
}
}
else
{
@@ -368,13 +394,26 @@ void WrappedOpenGL::glSamplerParameteriv(GLuint sampler, GLenum pname, const GLi
if(IsCaptureMode(m_State))
{
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler));
if(m_HighTrafficResources.find(record->GetResourceID()) != m_HighTrafficResources.end() &&
IsBackgroundCapturing(m_State))
return;
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(gl_CurChunk);
Serialise_glSamplerParameteriv(ser, sampler, pname, params);
if(IsBackgroundCapturing(m_State))
{
GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler))->AddChunk(scope.Get());
record->AddChunk(scope.Get());
record->UpdateCount++;
if(record->UpdateCount > 20)
{
m_HighTrafficResources.insert(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
}
}
else
{
@@ -416,13 +455,26 @@ void WrappedOpenGL::glSamplerParameterfv(GLuint sampler, GLenum pname, const GLf
if(IsCaptureMode(m_State))
{
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler));
if(m_HighTrafficResources.find(record->GetResourceID()) != m_HighTrafficResources.end() &&
IsBackgroundCapturing(m_State))
return;
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(gl_CurChunk);
Serialise_glSamplerParameterfv(ser, sampler, pname, params);
if(IsBackgroundCapturing(m_State))
{
GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler))->AddChunk(scope.Get());
record->AddChunk(scope.Get());
record->UpdateCount++;
if(record->UpdateCount > 20)
{
m_HighTrafficResources.insert(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
}
}
else
{
@@ -464,13 +516,26 @@ void WrappedOpenGL::glSamplerParameterIiv(GLuint sampler, GLenum pname, const GL
if(IsCaptureMode(m_State))
{
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler));
if(m_HighTrafficResources.find(record->GetResourceID()) != m_HighTrafficResources.end() &&
IsBackgroundCapturing(m_State))
return;
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(gl_CurChunk);
Serialise_glSamplerParameterIiv(ser, sampler, pname, params);
if(IsBackgroundCapturing(m_State))
{
GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler))->AddChunk(scope.Get());
record->AddChunk(scope.Get());
record->UpdateCount++;
if(record->UpdateCount > 20)
{
m_HighTrafficResources.insert(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
}
}
else
{
@@ -512,13 +577,26 @@ void WrappedOpenGL::glSamplerParameterIuiv(GLuint sampler, GLenum pname, const G
if(IsCaptureMode(m_State))
{
GLResourceRecord *record = GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler));
if(m_HighTrafficResources.find(record->GetResourceID()) != m_HighTrafficResources.end() &&
IsBackgroundCapturing(m_State))
return;
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(gl_CurChunk);
Serialise_glSamplerParameterIuiv(ser, sampler, pname, params);
if(IsBackgroundCapturing(m_State))
{
GetResourceManager()->GetResourceRecord(SamplerRes(GetCtx(), sampler))->AddChunk(scope.Get());
record->AddChunk(scope.Get());
record->UpdateCount++;
if(record->UpdateCount > 20)
{
m_HighTrafficResources.insert(record->GetResourceID());
GetResourceManager()->MarkDirtyResource(record->GetResourceID());
}
}
else
{