bool WrappedOpenGL::Serialise_glCompileShader(GLuint shader) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); if(m_State == READING) { ResourceId liveId = GetResourceManager()->GetLiveID(id); auto &shadDetails = m_Shaders[liveId]; bool pointSizeUsed = false, clipDistanceUsed = false; if(shadDetails.type == eGL_VERTEX_SHADER) CheckVertexOutputUses(shadDetails.sources, pointSizeUsed, clipDistanceUsed); GLuint sepProg = MakeSeparableShaderProgram(m_Real, shadDetails.type, shadDetails.sources, NULL); if(sepProg == 0) { RDCERR("Couldn't make separable program for shader via patching - functionality will be broken."); } else { shadDetails.prog = sepProg; MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection, pointSizeUsed, clipDistanceUsed); string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.sources, shadDetails.spirv); if(!shadDetails.spirv.empty()) DisassembleSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.spirv, s); shadDetails.reflection.Disassembly = s; create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size()); for(size_t i=0; i < shadDetails.sources.size(); i++) { shadDetails.reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i); shadDetails.reflection.DebugInfo.files[i].second = shadDetails.sources[i]; } } m_Real.glCompileShader(GetResourceManager()->GetLiveResource(id).name); } return true; }
void WrappedOpenGL::ShaderData::Compile(WrappedOpenGL &gl) { bool pointSizeUsed = false, clipDistanceUsed = false; if(type == eGL_VERTEX_SHADER) CheckVertexOutputUses(sources, pointSizeUsed, clipDistanceUsed); GLuint sepProg = prog; if(sepProg == 0) sepProg = MakeSeparableShaderProgram(gl, type, sources, NULL); if(sepProg == 0) { RDCERR( "Couldn't make separable program for shader via patching - functionality will be broken."); } else { prog = sepProg; MakeShaderReflection(gl.GetHookset(), type, sepProg, reflection, pointSizeUsed, clipDistanceUsed); vector<uint32_t> spirvwords; string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(type)), sources, spirvwords); if(!spirvwords.empty()) ParseSPIRV(&spirvwords.front(), spirvwords.size(), spirv); // for classic GL, entry point is always main reflection.Disassembly = spirv.Disassemble("main"); create_array_uninit(reflection.DebugInfo.files, sources.size()); for(size_t i = 0; i < sources.size(); i++) { reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i); reflection.DebugInfo.files[i].second = sources[i]; } } }
bool WrappedOpenGL::Serialise_glCreateShaderProgramv(GLuint program, GLenum type, GLsizei count, const GLchar *const*strings) { SERIALISE_ELEMENT(GLenum, Type, type); SERIALISE_ELEMENT(int32_t, Count, count); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ProgramRes(GetCtx(), program))); vector<string> src; for(int32_t i=0; i < Count; i++) { string s; if(m_State >= WRITING) s = strings[i]; m_pSerialiser->SerialiseString("Source", s); if(m_State < WRITING) src.push_back(s); } if(m_State == READING) { char **sources = new char*[Count]; for(int32_t i=0; i < Count; i++) sources[i] = &src[i][0]; GLuint real = m_Real.glCreateShaderProgramv(Type, Count, sources); // we want a separate program that we can mess about with for making overlays // and relink without having to worry about restoring the 'real' program state. GLuint sepprog = MakeSeparableShaderProgram(m_Real, Type, src, NULL); delete[] sources; GLResource res = ProgramRes(GetCtx(), real); ResourceId liveId = m_ResourceManager->RegisterResource(res); auto &progDetails = m_Programs[liveId]; progDetails.linked = true; progDetails.shaders.push_back(liveId); progDetails.stageShaders[ShaderIdx(Type)] = liveId; auto &shadDetails = m_Shaders[liveId]; bool pointSizeUsed = false, clipDistanceUsed = false; if(Type == eGL_VERTEX_SHADER) CheckVertexOutputUses(src, pointSizeUsed, clipDistanceUsed); shadDetails.type = Type; shadDetails.sources.swap(src); shadDetails.prog = sepprog; MakeShaderReflection(m_Real, Type, real, shadDetails.reflection, pointSizeUsed, clipDistanceUsed); string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.sources, shadDetails.spirv); if(!shadDetails.spirv.empty()) DisassembleSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.spirv, s); shadDetails.reflection.Disassembly = s; create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size()); for(size_t i=0; i < shadDetails.sources.size(); i++) { shadDetails.reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i); shadDetails.reflection.DebugInfo.files[i].second = shadDetails.sources[i]; } GetResourceManager()->AddLiveResource(id, res); } return true; }
bool WrappedOpenGL::Serialise_glCompileShaderIncludeARB(GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); SERIALISE_ELEMENT(int32_t, Count, count); vector<string> paths; for(int32_t i=0; i < Count; i++) { string s; if(path && path[i]) s = length > 0 ? string(path[i], path[i] + length[i]) : string(path[i]); m_pSerialiser->SerialiseString("path", s); if(m_State == READING) paths.push_back(s); } if(m_State == READING) { size_t numStrings = paths.size(); const char **pathstrings = new const char*[numStrings]; for(size_t i=0; i < numStrings; i++) pathstrings[i] = paths[i].c_str(); ResourceId liveId = GetResourceManager()->GetLiveID(id); auto &shadDetails = m_Shaders[liveId]; shadDetails.includepaths.clear(); shadDetails.includepaths.reserve(Count); for(int32_t i=0; i < Count; i++) shadDetails.includepaths.push_back(pathstrings[i]); bool pointSizeUsed = false, clipDistanceUsed = false; if(shadDetails.type == eGL_VERTEX_SHADER) CheckVertexOutputUses(shadDetails.sources, pointSizeUsed, clipDistanceUsed); GLuint sepProg = MakeSeparableShaderProgram(m_Real, shadDetails.type, shadDetails.sources, &paths); if(sepProg == 0) { RDCERR("Couldn't make separable program for shader via patching - functionality will be broken."); } else { shadDetails.prog = sepProg; MakeShaderReflection(m_Real, shadDetails.type, sepProg, shadDetails.reflection, pointSizeUsed, clipDistanceUsed); string s = CompileSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.sources, shadDetails.spirv); if(!shadDetails.spirv.empty()) DisassembleSPIRV(SPIRVShaderStage(ShaderIdx(shadDetails.type)), shadDetails.spirv, s); shadDetails.reflection.Disassembly = s; create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size()); for(size_t i=0; i < shadDetails.sources.size(); i++) { shadDetails.reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i); shadDetails.reflection.DebugInfo.files[i].second = shadDetails.sources[i]; } } m_Real.glCompileShaderIncludeARB(GetResourceManager()->GetLiveResource(id).name, Count, pathstrings, NULL); delete[] pathstrings; } return true; }