From 390e3c1bf468f1ca54ce248fac68690ffbfaa414 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 3 May 2017 19:46:36 +0100 Subject: [PATCH] Don't try to relink programs created by glCreateShaderProgramv * When creating a program with glCreateShaderProgramv it implicitly acts as if the shaders are detached and deleted after linking. This means it cannot be relinked again. * However the only time we need to relink a program is when we are copying across fragdata and vertex attrib bindings in case they were changed from creation - but for the same reason that we can't relink a program to apply them, the application can't either - which means the data must be unchanged from creation, and so the copy is not needed. --- renderdoc/driver/gl/gl_driver.h | 7 +++++++ renderdoc/driver/gl/gl_manager.cpp | 6 ++++-- renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index f87311c96..e188f6c9b 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -303,6 +303,13 @@ private: map locationTranslate; + // this flag indicates the program was created with glCreateShaderProgram and cannot be relinked + // again (because that function implicitly detaches and destroys the shader). However we only + // need to relink when restoring things like frag data or attrib bindings which must be relinked + // to apply - and since the application *also* could not have relinked them, they must be + // unchanged since creation. So in this case, we can skip the relink since it was impossible for + // the application to modify anything. + bool shaderProgramUnlinkable = false; bool linked; ResourceId stageShaders[6]; }; diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index f2cbd34da..ba99ac4b1 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -1953,8 +1953,10 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i CopyProgramFragDataBindings(gl, initial.resource.name, live.name, &m_GL->m_Shaders[prog.stageShaders[4]].reflection); - // we need to re-link the program to apply the bindings. - gl.glLinkProgram(live.name); + // we need to re-link the program to apply the bindings, as long as it's linkable. + // See the comment on shaderProgramUnlinkable for more information. + if(!prog.shaderProgramUnlinkable) + gl.glLinkProgram(live.name); } CopyProgramUniforms(gl, initial.resource.name, live.name); diff --git a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp index dc7fc7de1..b95e1c415 100644 --- a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp @@ -456,6 +456,7 @@ bool WrappedOpenGL::Serialise_glCreateShaderProgramv(GLuint program, GLenum type progDetails.linked = true; progDetails.shaders.push_back(liveId); progDetails.stageShaders[ShaderIdx(Type)] = liveId; + progDetails.shaderProgramUnlinkable = true; auto &shadDetails = m_Shaders[liveId];