mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-29 17:15:56 +00:00
When replaying specific GL extension functions, check availability
* In theory we should check everywhere on every function otherwise we crash with a NULL pointer, but figuring out which functions to check is non-trivial in some cases and there's the risk of false positives with fallbacks available etc in cases where there are several possible alternatives for a given function. * These checks have been sprinkled around in places where it's safe because there's only one implementation of a function that never made it to core, as well as the most common problems - glFramebufferTexture2DMultisampleEXT and glFramebufferTextureMultiviewOVR/glFramebufferTextureMultisampleMultiviewOVR which comes from users mistakenly replaying a mobile capture on desktop. This is not expected to work but it shouldn't crash.
This commit is contained in:
@@ -428,6 +428,16 @@ T CheckConstParam(T t);
|
||||
// Writing is unambiguously during capture mode, so we don't have to check both in that case.
|
||||
#define IsReplayingAndReading() (ser.IsReading() && IsReplayMode(m_State))
|
||||
|
||||
// on GL we don't have an easy way of checking which functions/extensions were used or which
|
||||
// functions/extensions on replay could suffice. So we check at the last minute on replay and bail
|
||||
// out if it's not present
|
||||
#define CheckReplayFunctionPresent(func) \
|
||||
if(func == NULL) \
|
||||
{ \
|
||||
m_FailedReplayStatus = ReplayStatus::APIHardwareUnsupported; \
|
||||
return false; \
|
||||
}
|
||||
|
||||
// no longer in glcorearb.h or glext.h
|
||||
const GLenum eGL_LIGHTING = (GLenum)0x0B50;
|
||||
const GLenum eGL_ALPHA_TEST = (GLenum)0x0BC0;
|
||||
|
||||
@@ -308,6 +308,8 @@ bool WrappedOpenGL::Serialise_glDispatchComputeGroupSizeARB(SerialiserType &ser,
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glDispatchComputeGroupSizeARB);
|
||||
|
||||
GL.glDispatchComputeGroupSizeARB(num_groups_x, num_groups_y, num_groups_z, group_size_x,
|
||||
group_size_y, group_size_z);
|
||||
|
||||
@@ -408,6 +410,8 @@ bool WrappedOpenGL::Serialise_glDispatchComputeIndirect(SerialiserType &ser, GLi
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glDispatchComputeIndirect);
|
||||
|
||||
GL.glDispatchComputeIndirect((GLintptr)offset);
|
||||
|
||||
if(IsLoading(m_State))
|
||||
@@ -1094,6 +1098,8 @@ bool WrappedOpenGL::Serialise_glDrawArraysIndirect(SerialiserType &ser, GLenum m
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glDrawArraysIndirect);
|
||||
|
||||
if(Check_SafeDraw(false))
|
||||
GL.glDrawArraysIndirect(mode, (const void *)offset);
|
||||
|
||||
@@ -1397,6 +1403,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsIndirect(SerialiserType &ser, GLenum
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glDrawElementsIndirect);
|
||||
|
||||
if(Check_SafeDraw(true))
|
||||
GL.glDrawElementsIndirect(mode, type, (const void *)offset);
|
||||
|
||||
@@ -2529,6 +2537,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirect(SerialiserType &ser, GLe
|
||||
{
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glMultiDrawArraysIndirect);
|
||||
|
||||
if(Check_SafeDraw(false))
|
||||
GL.glMultiDrawArraysIndirect(mode, (const void *)offset, drawcount, stride);
|
||||
|
||||
@@ -2743,6 +2753,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirect(SerialiserType &ser, G
|
||||
{
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glMultiDrawElementsIndirect);
|
||||
|
||||
GLRenderState state;
|
||||
state.FetchState(this);
|
||||
|
||||
@@ -2970,6 +2982,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirectCount(SerialiserType &ser
|
||||
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glMultiDrawArraysIndirectCount);
|
||||
|
||||
if(Check_SafeDraw(false))
|
||||
GL.glMultiDrawArraysIndirectCount(mode, (const void *)offset, (GLintptr)drawcount,
|
||||
maxdrawcount, stride);
|
||||
@@ -3196,6 +3210,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirectCount(SerialiserType &s
|
||||
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glMultiDrawElementsIndirectCount);
|
||||
|
||||
if(Check_SafeDraw(true))
|
||||
GL.glMultiDrawElementsIndirectCount(mode, type, (const void *)offset, (GLintptr)drawcount,
|
||||
maxdrawcount, stride);
|
||||
|
||||
@@ -599,6 +599,8 @@ bool WrappedOpenGL::Serialise_glFramebufferTexture2DMultisampleEXT(
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glFramebufferTexture2DMultisampleEXT);
|
||||
|
||||
if(framebuffer.name == 0)
|
||||
framebuffer.name = m_CurrentDefaultFBO;
|
||||
|
||||
@@ -1137,6 +1139,8 @@ bool WrappedOpenGL::Serialise_glFramebufferTextureMultiviewOVR(SerialiserType &s
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glFramebufferTextureMultiviewOVR);
|
||||
|
||||
GL.glFramebufferTextureMultiviewOVR(target, attachment, texture.name, level, baseViewIndex,
|
||||
numViews);
|
||||
|
||||
@@ -1253,6 +1257,8 @@ bool WrappedOpenGL::Serialise_glFramebufferTextureMultisampleMultiviewOVR(
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glFramebufferTextureMultisampleMultiviewOVR);
|
||||
|
||||
GL.glFramebufferTextureMultisampleMultiviewOVR(target, attachment, texture.name, level, samples,
|
||||
baseViewIndex, numViews);
|
||||
|
||||
@@ -2403,6 +2409,10 @@ bool WrappedOpenGL::Serialise_glNamedRenderbufferStorageMultisampleEXT(Serialise
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
// the DSA function is emulated if not present, but we need to check the underlying function is
|
||||
// present
|
||||
CheckReplayFunctionPresent(GL.glRenderbufferStorageMultisample);
|
||||
|
||||
ResourceId liveId = GetResourceManager()->GetID(renderbuffer);
|
||||
TextureData &texDetails = m_Textures[liveId];
|
||||
|
||||
@@ -2596,6 +2606,8 @@ bool WrappedOpenGL::Serialise_glRenderbufferStorageMultisampleEXT(SerialiserType
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glRenderbufferStorageMultisampleEXT);
|
||||
|
||||
ResourceId liveId = GetResourceManager()->GetID(renderbuffer);
|
||||
TextureData &texDetails = m_Textures[liveId];
|
||||
|
||||
|
||||
@@ -541,6 +541,8 @@ bool WrappedOpenGL::Serialise_glCreateMemoryObjectsEXT(SerialiserType &ser, GLsi
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glCreateMemoryObjectsEXT);
|
||||
|
||||
GLuint real = 0;
|
||||
GL.glCreateMemoryObjectsEXT(1, &real);
|
||||
|
||||
@@ -621,6 +623,8 @@ bool WrappedOpenGL::Serialise_glMemoryObjectParameterivEXT(SerialiserType &ser,
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glMemoryObjectParameterivEXT);
|
||||
|
||||
GL.glMemoryObjectParameterivEXT(memoryObject.name, pname, params);
|
||||
|
||||
AddResourceInitChunk(memoryObject);
|
||||
@@ -812,6 +816,8 @@ bool WrappedOpenGL::Serialise_glGenSemaphoresEXT(SerialiserType &ser, GLsizei n,
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glGenSemaphoresEXT);
|
||||
|
||||
GLuint real = 0;
|
||||
GL.glGenSemaphoresEXT(1, &real);
|
||||
|
||||
@@ -892,6 +898,8 @@ bool WrappedOpenGL::Serialise_glSemaphoreParameterui64vEXT(SerialiserType &ser,
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glSemaphoreParameterui64vEXT);
|
||||
|
||||
GL.glSemaphoreParameterui64vEXT(semaphore.name, pname, params);
|
||||
|
||||
AddResourceInitChunk(semaphore);
|
||||
@@ -1633,6 +1641,10 @@ bool WrappedOpenGL::Serialise_glTextureStorageMem2DMultisampleEXT(
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
// the DSA function is emulated if not present, but we need to check the underlying function is
|
||||
// present
|
||||
CheckReplayFunctionPresent(GL.glTexStorage2DMultisample);
|
||||
|
||||
// Replay external texture storage backed by external memory as just a plain texture.
|
||||
ResourceId liveId = GetResourceManager()->GetID(texture);
|
||||
m_Textures[liveId].width = width;
|
||||
|
||||
@@ -1755,6 +1755,8 @@ bool WrappedOpenGL::Serialise_glCompileShaderIncludeARB(SerialiserType &ser, GLu
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glCompileShaderIncludeARB);
|
||||
|
||||
ResourceId liveId = GetResourceManager()->GetID(shader);
|
||||
|
||||
auto &shadDetails = m_Shaders[liveId];
|
||||
@@ -1828,6 +1830,8 @@ bool WrappedOpenGL::Serialise_glNamedStringARB(SerialiserType &ser, GLenum type,
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glNamedStringARB);
|
||||
|
||||
GL.glNamedStringARB(type, (GLint)name.length(), name.c_str(), (GLint)value.length(),
|
||||
value.c_str());
|
||||
}
|
||||
@@ -1865,6 +1869,8 @@ bool WrappedOpenGL::Serialise_glDeleteNamedStringARB(SerialiserType &ser, GLint
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glDeleteNamedStringARB);
|
||||
|
||||
GL.glDeleteNamedStringARB((GLint)name.length(), name.c_str());
|
||||
}
|
||||
|
||||
@@ -1913,6 +1919,8 @@ bool WrappedOpenGL::Serialise_glSpecializeShader(SerialiserType &ser, GLuint sha
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glSpecializeShader);
|
||||
|
||||
ResourceId liveId = GetResourceManager()->GetID(shader);
|
||||
|
||||
GL.glSpecializeShader(shader.name, pEntryPoint, numSpecializationConstants, pConstantIndex,
|
||||
|
||||
@@ -923,6 +923,8 @@ bool WrappedOpenGL::Serialise_glDepthBoundsEXT(SerialiserType &ser, GLclampd nea
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glDepthBoundsEXT);
|
||||
|
||||
GL.glDepthBoundsEXT(nearVal, farVal);
|
||||
}
|
||||
|
||||
@@ -1418,6 +1420,8 @@ bool WrappedOpenGL::Serialise_glRasterSamplesEXT(SerialiserType &ser, GLuint sam
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glRasterSamplesEXT);
|
||||
|
||||
GL.glRasterSamplesEXT(samples, fixedsamplelocations ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
||||
@@ -1915,6 +1919,8 @@ bool WrappedOpenGL::Serialise_glPolygonOffsetClamp(SerialiserType &ser, GLfloat
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glPolygonOffsetClamp);
|
||||
|
||||
GL.glPolygonOffsetClamp(factor, units, clamp);
|
||||
}
|
||||
|
||||
@@ -1953,6 +1959,8 @@ bool WrappedOpenGL::Serialise_glPrimitiveBoundingBox(SerialiserType &ser, GLfloa
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glPrimitiveBoundingBox);
|
||||
|
||||
GL.glPrimitiveBoundingBox(minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
|
||||
}
|
||||
|
||||
|
||||
@@ -6352,6 +6352,8 @@ bool WrappedOpenGL::Serialise_glTextureFoveationParametersQCOM(SerialiserType &s
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
CheckReplayFunctionPresent(GL.glTextureFoveationParametersQCOM);
|
||||
|
||||
GL.glTextureFoveationParametersQCOM(texture.name, layer, focalPoint, focalX, focalY, gainX,
|
||||
gainY, foveaArea);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user