From 12019c38444f9262e918326c559ce0d3c8d875ee Mon Sep 17 00:00:00 2001 From: Baldur Karlsson Date: Tue, 24 Jun 2014 15:52:33 +0100 Subject: [PATCH] For now handle no program being bound, e.g. if pipeline is bound --- renderdoc/driver/gl/gl_replay.cpp | 268 ++++++++++++++++-------------- 1 file changed, 140 insertions(+), 128 deletions(-) diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 17a7f0a9a..262fe2a4f 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -939,32 +939,8 @@ void GLReplay::SavePipelineState() break; } } - - // Shader stages - GLuint curProg = 0; - gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg); - - auto &progDetails = m_pDriver->m_Programs[rm->GetID(ProgramRes(curProg))]; - - RDCASSERT(progDetails.shaders.size()); - - for(size_t i=0; i < progDetails.shaders.size(); i++) - { - if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_VERTEX_SHADER) - pipe.m_VS.Shader = rm->GetOriginalID(progDetails.shaders[i]); - else if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_FRAGMENT_SHADER) - pipe.m_FS.Shader = rm->GetOriginalID(progDetails.shaders[i]); - } - - pipe.m_VS.stage = eShaderStage_Vertex; - pipe.m_TCS.stage = eShaderStage_Tess_Control; - pipe.m_TES.stage = eShaderStage_Tess_Eval; - pipe.m_GS.stage = eShaderStage_Geometry; - pipe.m_FS.stage = eShaderStage_Fragment; - pipe.m_CS.stage = eShaderStage_Compute; - - // Textures + // Shader stages & Textures GLint numTexUnits = 8; gl.glGetIntegerv(eGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numTexUnits); @@ -973,124 +949,160 @@ void GLReplay::SavePipelineState() GLenum activeTexture = eGL_TEXTURE0; gl.glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint*)&activeTexture); - // GL is ass-backwards in its handling of texture units. When a shader is active - // the types in the glsl samplers inform which targets are used from which texture units - // - // So texture unit 5 can have a 2D bound (texture 52) and a Cube bound (texture 77). - // * if a uniform sampler2D has value 5 then the 2D texture is used, and we sample from 52 - // * if a uniform samplerCube has value 5 then the Cube texture is used, and we sample from 77 - // It's illegal for both a sampler2D and samplerCube to both have the same value (or any two - // different types). It makes it all rather pointless and needlessly complex. - // - // What we have to do then, is consider the program, look at the values of the uniforms, and - // then get the appropriate current binding based on the uniform type. We can warn/alert the - // user if we hit the illegal case of two uniforms with different types but the same value - // - // Handling is different if no shaders are active, but we don't consider that case. - - - // prefetch uniform values in GetShader() - ShaderReflection *refls[6]; - for(size_t s=0; s < progDetails.shaders.size(); s++) - refls[s] = GetShader(progDetails.shaders[s]); - - for(GLint unit=0; unit < numTexUnits; unit++) + pipe.m_VS.stage = eShaderStage_Vertex; + pipe.m_TCS.stage = eShaderStage_Tess_Control; + pipe.m_TES.stage = eShaderStage_Tess_Eval; + pipe.m_GS.stage = eShaderStage_Geometry; + pipe.m_FS.stage = eShaderStage_Fragment; + pipe.m_CS.stage = eShaderStage_Compute; + + GLuint curProg = 0; + gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg); + + if(curProg == 0) { - GLenum binding = eGL_UNKNOWN_ENUM; - GLenum target = eGL_UNKNOWN_ENUM; + pipe.m_VS.Shader = ResourceId(); + pipe.m_FS.Shader = ResourceId(); - for(size_t s=0; s < progDetails.shaders.size(); s++) + for(GLint unit=0; unit < numTexUnits; unit++) { - if(refls[s] == NULL) continue; + pipe.Textures[unit].FirstSlice = 0; + pipe.Textures[unit].Resource = ResourceId(); + } + } + else + { + auto &progDetails = m_pDriver->m_Programs[rm->GetID(ProgramRes(curProg))]; - for(int32_t r=0; r < refls[s]->Resources.count; r++) + RDCASSERT(progDetails.shaders.size()); + + for(size_t i=0; i < progDetails.shaders.size(); i++) + { + if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_VERTEX_SHADER) + pipe.m_VS.Shader = rm->GetOriginalID(progDetails.shaders[i]); + else if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_FRAGMENT_SHADER) + pipe.m_FS.Shader = rm->GetOriginalID(progDetails.shaders[i]); + } + + // GL is ass-backwards in its handling of texture units. When a shader is active + // the types in the glsl samplers inform which targets are used from which texture units + // + // So texture unit 5 can have a 2D bound (texture 52) and a Cube bound (texture 77). + // * if a uniform sampler2D has value 5 then the 2D texture is used, and we sample from 52 + // * if a uniform samplerCube has value 5 then the Cube texture is used, and we sample from 77 + // It's illegal for both a sampler2D and samplerCube to both have the same value (or any two + // different types). It makes it all rather pointless and needlessly complex. + // + // What we have to do then, is consider the program, look at the values of the uniforms, and + // then get the appropriate current binding based on the uniform type. We can warn/alert the + // user if we hit the illegal case of two uniforms with different types but the same value + // + // Handling is different if no shaders are active, but we don't consider that case. + + + // prefetch uniform values in GetShader() + ShaderReflection *refls[6]; + for(size_t s=0; s < progDetails.shaders.size(); s++) + refls[s] = GetShader(progDetails.shaders[s]); + + for(GLint unit=0; unit < numTexUnits; unit++) + { + GLenum binding = eGL_UNKNOWN_ENUM; + GLenum target = eGL_UNKNOWN_ENUM; + + for(size_t s=0; s < progDetails.shaders.size(); s++) { - // bindPoint is the uniform value for this sampler - if(refls[s]->Resources[r].bindPoint == (uint32_t)unit) + if(refls[s] == NULL) continue; + + for(int32_t r=0; r < refls[s]->Resources.count; r++) { - GLenum t = eGL_UNKNOWN_ENUM; + // bindPoint is the uniform value for this sampler + if(refls[s]->Resources[r].bindPoint == (uint32_t)unit) + { + GLenum t = eGL_UNKNOWN_ENUM; - switch(refls[s]->Resources[r].resType) - { - case eResType_None: - t = eGL_UNKNOWN_ENUM; - break; - case eResType_Buffer: - t = eGL_TEXTURE_BINDING_BUFFER; - break; - case eResType_Texture1D: - t = eGL_TEXTURE_BINDING_1D; - target = eGL_TEXTURE_1D; - break; - case eResType_Texture1DArray: - t = eGL_TEXTURE_BINDING_1D_ARRAY; - target = eGL_TEXTURE_1D_ARRAY; - break; - case eResType_Texture2D: - t = eGL_TEXTURE_BINDING_2D; - target = eGL_TEXTURE_2D; - break; - case eResType_Texture2DArray: - t = eGL_TEXTURE_BINDING_2D_ARRAY; - target = eGL_TEXTURE_2D_ARRAY; - break; - case eResType_Texture2DMS: - t = eGL_TEXTURE_BINDING_2D_MULTISAMPLE; - target = eGL_TEXTURE_2D_MULTISAMPLE; - break; - case eResType_Texture2DMSArray: - t = eGL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY; - target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY; - break; - case eResType_Texture3D: - t = eGL_TEXTURE_BINDING_3D; - target = eGL_TEXTURE_3D; - break; - case eResType_TextureCube: - t = eGL_TEXTURE_BINDING_CUBE_MAP; - target = eGL_TEXTURE_CUBE_MAP; - break; - case eResType_TextureCubeArray: - t = eGL_TEXTURE_BINDING_CUBE_MAP_ARRAY; - target = eGL_TEXTURE_CUBE_MAP_ARRAY; - break; - } + switch(refls[s]->Resources[r].resType) + { + case eResType_None: + t = eGL_UNKNOWN_ENUM; + break; + case eResType_Buffer: + t = eGL_TEXTURE_BINDING_BUFFER; + break; + case eResType_Texture1D: + t = eGL_TEXTURE_BINDING_1D; + target = eGL_TEXTURE_1D; + break; + case eResType_Texture1DArray: + t = eGL_TEXTURE_BINDING_1D_ARRAY; + target = eGL_TEXTURE_1D_ARRAY; + break; + case eResType_Texture2D: + t = eGL_TEXTURE_BINDING_2D; + target = eGL_TEXTURE_2D; + break; + case eResType_Texture2DArray: + t = eGL_TEXTURE_BINDING_2D_ARRAY; + target = eGL_TEXTURE_2D_ARRAY; + break; + case eResType_Texture2DMS: + t = eGL_TEXTURE_BINDING_2D_MULTISAMPLE; + target = eGL_TEXTURE_2D_MULTISAMPLE; + break; + case eResType_Texture2DMSArray: + t = eGL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY; + target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY; + break; + case eResType_Texture3D: + t = eGL_TEXTURE_BINDING_3D; + target = eGL_TEXTURE_3D; + break; + case eResType_TextureCube: + t = eGL_TEXTURE_BINDING_CUBE_MAP; + target = eGL_TEXTURE_CUBE_MAP; + break; + case eResType_TextureCubeArray: + t = eGL_TEXTURE_BINDING_CUBE_MAP_ARRAY; + target = eGL_TEXTURE_CUBE_MAP_ARRAY; + break; + } - if(binding == eGL_UNKNOWN_ENUM) - { - binding = t; - } - else if(binding == t) - { - // two uniforms with the same type pointing to the same slot is fine - binding = t; - } - else if(binding != t) - { - RDCWARN("Two uniforms pointing to texture unit %d with types %s and %s", unit, ToStr::Get(binding).c_str(), ToStr::Get(t).c_str()); + if(binding == eGL_UNKNOWN_ENUM) + { + binding = t; + } + else if(binding == t) + { + // two uniforms with the same type pointing to the same slot is fine + binding = t; + } + else if(binding != t) + { + RDCWARN("Two uniforms pointing to texture unit %d with types %s and %s", unit, ToStr::Get(binding).c_str(), ToStr::Get(t).c_str()); + } } } } - } - if(binding != eGL_UNKNOWN_ENUM) - { - gl.glActiveTexture(GLenum(eGL_TEXTURE0+unit)); + if(binding != eGL_UNKNOWN_ENUM) + { + gl.glActiveTexture(GLenum(eGL_TEXTURE0+unit)); - GLuint tex; - gl.glGetIntegerv(binding, (GLint *)&tex); + GLuint tex; + gl.glGetIntegerv(binding, (GLint *)&tex); - // very bespoke/specific - GLint firstSlice = 0; - gl.glGetTexParameteriv(target, eGL_TEXTURE_VIEW_MIN_LEVEL, &firstSlice); + // very bespoke/specific + GLint firstSlice = 0; + gl.glGetTexParameteriv(target, eGL_TEXTURE_VIEW_MIN_LEVEL, &firstSlice); - pipe.Textures[unit].Resource = rm->GetOriginalID(rm->GetID(TextureRes(tex))); - pipe.Textures[unit].FirstSlice = (uint32_t)firstSlice; - } - else - { - // what should we do in this case? there could be something bound just not used, - // it'd be nice to return that + pipe.Textures[unit].Resource = rm->GetOriginalID(rm->GetID(TextureRes(tex))); + pipe.Textures[unit].FirstSlice = (uint32_t)firstSlice; + } + else + { + // what should we do in this case? there could be something bound just not used, + // it'd be nice to return that + } } }