void WrappedOpenGL::glCompileShaderIncludeARB(GLuint shader, GLsizei count, const GLchar *const *path, const GLint *length) { m_Real.glCompileShaderIncludeARB(shader, count, path, length); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ShaderRes(GetCtx(), shader)); RDCASSERT(record); { SCOPED_SERIALISE_CONTEXT(COMPILESHADERINCLUDE); Serialise_glCompileShaderIncludeARB(shader, count, path, length); record->AddChunk(scope.Get()); } } else { ResourceId id = GetResourceManager()->GetID(ShaderRes(GetCtx(), shader)); auto &shadDetails = m_Shaders[id]; shadDetails.includepaths.clear(); shadDetails.includepaths.reserve(count); for(int32_t i = 0; i < count; i++) shadDetails.includepaths.push_back(path[i]); shadDetails.Compile(*this); } }
void WrappedOpenGL::glAttachShader(GLuint program, GLuint shader) { m_Real.glAttachShader(program, shader); if(m_State >= WRITING && program != 0 && shader != 0) { GLResourceRecord *progRecord = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), program)); GLResourceRecord *shadRecord = GetResourceManager()->GetResourceRecord(ShaderRes(GetCtx(), shader)); RDCASSERT(progRecord && shadRecord); if(progRecord && shadRecord) { SCOPED_SERIALISE_CONTEXT(ATTACHSHADER); Serialise_glAttachShader(program, shader); progRecord->AddParent(shadRecord); progRecord->AddChunk(scope.Get()); } } else { ResourceId progid = GetResourceManager()->GetID(ProgramRes(GetCtx(), program)); ResourceId shadid = GetResourceManager()->GetID(ShaderRes(GetCtx(), shader)); m_Programs[progid].shaders.push_back(shadid); } }
void WrappedOpenGL::glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length) { m_Real.glShaderSource(shader, count, string, length); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ShaderRes(GetCtx(), shader)); RDCASSERT(record); { SCOPED_SERIALISE_CONTEXT(SHADERSOURCE); Serialise_glShaderSource(shader, count, string, length); record->AddChunk(scope.Get()); } } else { ResourceId id = GetResourceManager()->GetID(ShaderRes(GetCtx(), shader)); m_Shaders[id].sources.clear(); m_Shaders[id].sources.reserve(count); for(GLsizei i = 0; i < count; i++) m_Shaders[id].sources.push_back(string[i]); } }
GLuint WrappedOpenGL::glCreateShader(GLenum type) { GLuint real = m_Real.glCreateShader(type); GLResource res = ShaderRes(GetCtx(), real); ResourceId id = GetResourceManager()->RegisterResource(res); if(m_State >= WRITING) { Chunk *chunk = NULL; { SCOPED_SERIALISE_CONTEXT(CREATE_SHADER); Serialise_glCreateShader(real, type); chunk = scope.Get(); } GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id); RDCASSERT(record); record->AddChunk(chunk); } else { GetResourceManager()->AddLiveResource(id, res); m_Shaders[id].type = type; } return real; }
bool WrappedOpenGL::Serialise_glDetachShader(GLuint program, GLuint shader) { SERIALISE_ELEMENT(ResourceId, progid, GetResourceManager()->GetID(ProgramRes(GetCtx(), program))); SERIALISE_ELEMENT(ResourceId, shadid, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); if(m_State == READING) { ResourceId liveProgId = GetResourceManager()->GetLiveID(progid); ResourceId liveShadId = GetResourceManager()->GetLiveID(shadid); if(!m_Programs[liveProgId].linked) { for(auto it = m_Programs[liveProgId].shaders.begin(); it != m_Programs[liveProgId].shaders.end(); ++it) { if(*it == liveShadId) { m_Programs[liveProgId].shaders.erase(it); break; } } } m_Real.glDetachShader(GetResourceManager()->GetLiveResource(progid).name, GetResourceManager()->GetLiveResource(shadid).name); } return true; }
bool WrappedOpenGL::Serialise_glCreateShader(GLuint shader, GLenum type) { SERIALISE_ELEMENT(GLenum, Type, type); SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); if(m_State == READING) { GLuint real = m_Real.glCreateShader(Type); GLResource res = ShaderRes(GetCtx(), real); ResourceId liveId = GetResourceManager()->RegisterResource(res); m_Shaders[liveId].type = Type; GetResourceManager()->AddLiveResource(id, res); } return true; }
void WrappedOpenGL::glCompileShader(GLuint shader) { m_Real.glCompileShader(shader); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ShaderRes(GetCtx(), shader)); RDCASSERT(record); { SCOPED_SERIALISE_CONTEXT(COMPILESHADER); Serialise_glCompileShader(shader); record->AddChunk(scope.Get()); } } else { m_Shaders[GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))].Compile(*this); } }
void WrappedOpenGL::glDeleteShader(GLuint shader) { m_Real.glDeleteShader(shader); GLResource res = ShaderRes(GetCtx(), shader); if(GetResourceManager()->HasCurrentResource(res)) { if(GetResourceManager()->HasResourceRecord(res)) GetResourceManager()->GetResourceRecord(res)->Delete(GetResourceManager()); GetResourceManager()->UnregisterResource(res); } }
void WrappedOpenGL::glDetachShader(GLuint program, GLuint shader) { m_Real.glDetachShader(program, shader); // check that shader still exists, it might have been deleted. If it has, it's not too important // that we detach the shader (only important if the program will attach it elsewhere). if(m_State >= WRITING && program != 0 && shader != 0 && GetResourceManager()->HasCurrentResource(ShaderRes(GetCtx(), shader))) { GLResourceRecord *progRecord = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), program)); RDCASSERT(progRecord); { SCOPED_SERIALISE_CONTEXT(DETACHSHADER); Serialise_glDetachShader(program, shader); progRecord->AddChunk(scope.Get()); } } else { ResourceId progid = GetResourceManager()->GetID(ProgramRes(GetCtx(), program)); ResourceId shadid = GetResourceManager()->GetID(ShaderRes(GetCtx(), shader)); if(!m_Programs[progid].linked) { for(auto it = m_Programs[progid].shaders.begin(); it != m_Programs[progid].shaders.end(); ++it) { if(*it == shadid) { m_Programs[progid].shaders.erase(it); break; } } } } }
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 && length[i] > 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]); shadDetails.Compile(*this); m_Real.glCompileShaderIncludeARB(GetResourceManager()->GetLiveResource(id).name, Count, pathstrings, NULL); delete[] pathstrings; } return true; }
bool WrappedOpenGL::Serialise_glCompileShader(GLuint shader) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); if(m_State == READING) { ResourceId liveId = GetResourceManager()->GetLiveID(id); m_Shaders[liveId].Compile(*this); m_Real.glCompileShader(GetResourceManager()->GetLiveResource(id).name); } return true; }
void WrappedOpenGL::glCompileShaderIncludeARB(GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length) { m_Real.glCompileShaderIncludeARB(shader, count, path, length); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ShaderRes(GetCtx(), shader)); RDCASSERT(record); { SCOPED_SERIALISE_CONTEXT(COMPILESHADERINCLUDE); Serialise_glCompileShaderIncludeARB(shader, count, path, length); record->AddChunk(scope.Get()); } } }
void WrappedOpenGL::glShaderSource(GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length) { m_Real.glShaderSource(shader, count, string, length); if(m_State >= WRITING) { GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ShaderRes(GetCtx(), shader)); RDCASSERT(record); { SCOPED_SERIALISE_CONTEXT(SHADERSOURCE); Serialise_glShaderSource(shader, count, string, length); record->AddChunk(scope.Get()); } } }
bool WrappedOpenGL::Serialise_glAttachShader(GLuint program, GLuint shader) { SERIALISE_ELEMENT(ResourceId, progid, GetResourceManager()->GetID(ProgramRes(GetCtx(), program))); SERIALISE_ELEMENT(ResourceId, shadid, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); if(m_State == READING) { ResourceId liveProgId = GetResourceManager()->GetLiveID(progid); ResourceId liveShadId = GetResourceManager()->GetLiveID(shadid); m_Programs[liveProgId].shaders.push_back(liveShadId); m_Real.glAttachShader(GetResourceManager()->GetLiveResource(progid).name, GetResourceManager()->GetLiveResource(shadid).name); } return true; }
bool WrappedOpenGL::Serialise_glShaderSource(GLuint shader, GLsizei count, const GLchar *const *source, const GLint *length) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ShaderRes(GetCtx(), shader))); SERIALISE_ELEMENT(uint32_t, Count, count); vector<string> srcs; for(uint32_t i = 0; i < Count; i++) { string s; if(source && source[i]) s = (length && length[i] > 0) ? string(source[i], source[i] + length[i]) : string(source[i]); m_pSerialiser->SerialiseString("source", s); if(m_State == READING) srcs.push_back(s); } if(m_State == READING) { size_t numStrings = srcs.size(); const char **strings = new const char *[numStrings]; for(size_t i = 0; i < numStrings; i++) strings[i] = srcs[i].c_str(); ResourceId liveId = GetResourceManager()->GetLiveID(id); m_Shaders[liveId].sources.clear(); m_Shaders[liveId].sources.reserve(Count); for(uint32_t i = 0; i < Count; i++) m_Shaders[liveId].sources.push_back(strings[i]); m_Real.glShaderSource(GetResourceManager()->GetLiveResource(id).name, Count, strings, NULL); delete[] strings; } return true; }
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; }
bool WrappedOpenGL::Serialise_glObjectLabel(SerialiserType &ser, GLenum identifier, GLuint name, GLsizei length, const GLchar *label) { GLResource Resource; std::string Label; if(ser.IsWriting()) { // we share implementations between KHR_debug and EXT_debug_label, however KHR_debug follows the // pattern elsewhere (e.g. in glShaderSource) of a length of -1 meaning indeterminate // NULL-terminated length, but EXT_debug_label takes length of 0 to mean that. GLsizei realLength = length; if(gl_CurChunk == GLChunk::glLabelObjectEXT && length == 0) realLength = -1; // if length is negative (after above twiddling), it's taken from strlen and the label must be // NULL-terminated if(realLength < 0) realLength = label ? (GLsizei)strlen(label) : 0; if(realLength == 0 || label == NULL) Label = ""; else Label = std::string(label, label + realLength); switch(identifier) { case eGL_TEXTURE: Resource = TextureRes(GetCtx(), name); break; case eGL_BUFFER_OBJECT_EXT: case eGL_BUFFER: Resource = BufferRes(GetCtx(), name); break; case eGL_PROGRAM_OBJECT_EXT: case eGL_PROGRAM: Resource = ProgramRes(GetCtx(), name); break; case eGL_PROGRAM_PIPELINE_OBJECT_EXT: case eGL_PROGRAM_PIPELINE: Resource = ProgramPipeRes(GetCtx(), name); break; case eGL_VERTEX_ARRAY_OBJECT_EXT: case eGL_VERTEX_ARRAY: Resource = VertexArrayRes(GetCtx(), name); break; case eGL_SHADER_OBJECT_EXT: case eGL_SHADER: Resource = ShaderRes(GetCtx(), name); break; case eGL_QUERY_OBJECT_EXT: case eGL_QUERY: Resource = QueryRes(GetCtx(), name); break; case eGL_TRANSFORM_FEEDBACK: Resource = FeedbackRes(GetCtx(), name); break; case eGL_SAMPLER: Resource = SamplerRes(GetCtx(), name); break; case eGL_RENDERBUFFER: Resource = RenderbufferRes(GetCtx(), name); break; case eGL_FRAMEBUFFER: Resource = FramebufferRes(GetCtx(), name); break; default: RDCERR("Unhandled namespace in glObjectLabel"); } } SERIALISE_ELEMENT(Resource); SERIALISE_ELEMENT(length); SERIALISE_ELEMENT(Label); SERIALISE_CHECK_READ_ERRORS(); if(IsReplayingAndReading() && Resource.name) { ResourceId origId = GetResourceManager()->GetOriginalID(GetResourceManager()->GetID(Resource)); GetResourceManager()->SetName(origId, Label); ResourceDescription &descr = GetReplay()->GetResourceDesc(origId); descr.SetCustomName(Label); AddResourceCurChunk(descr); } 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; }
bool WrappedOpenGL::Serialise_glObjectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label) { ResourceId liveid; bool extvariant = false; string Label; if(m_State >= WRITING) { if(length == 0) Label = ""; else Label = string(label, label + (length > 0 ? length : strlen(label))); switch(identifier) { case eGL_TEXTURE: liveid = GetResourceManager()->GetID(TextureRes(GetCtx(), name)); break; case eGL_BUFFER_OBJECT_EXT: extvariant = true; case eGL_BUFFER: liveid = GetResourceManager()->GetID(BufferRes(GetCtx(), name)); break; case eGL_PROGRAM_OBJECT_EXT: extvariant = true; case eGL_PROGRAM: liveid = GetResourceManager()->GetID(ProgramRes(GetCtx(), name)); break; case eGL_PROGRAM_PIPELINE_OBJECT_EXT: extvariant = true; case eGL_PROGRAM_PIPELINE: liveid = GetResourceManager()->GetID(ProgramPipeRes(GetCtx(), name)); break; case eGL_VERTEX_ARRAY_OBJECT_EXT: extvariant = true; case eGL_VERTEX_ARRAY: liveid = GetResourceManager()->GetID(VertexArrayRes(GetCtx(), name)); break; case eGL_SHADER_OBJECT_EXT: extvariant = true; case eGL_SHADER: liveid = GetResourceManager()->GetID(ShaderRes(GetCtx(), name)); break; case eGL_QUERY_OBJECT_EXT: extvariant = true; case eGL_QUERY: liveid = GetResourceManager()->GetID(QueryRes(GetCtx(), name)); break; case eGL_TRANSFORM_FEEDBACK: liveid = GetResourceManager()->GetID(FeedbackRes(GetCtx(), name)); break; case eGL_SAMPLER: liveid = GetResourceManager()->GetID(SamplerRes(GetCtx(), name)); break; case eGL_RENDERBUFFER: liveid = GetResourceManager()->GetID(RenderbufferRes(GetCtx(), name)); break; case eGL_FRAMEBUFFER: liveid = GetResourceManager()->GetID(FramebufferRes(GetCtx(), name)); break; default: RDCERR("Unhandled namespace in glObjectLabel"); } } SERIALISE_ELEMENT(GLenum, Identifier, identifier); SERIALISE_ELEMENT(ResourceId, id, liveid); SERIALISE_ELEMENT(uint32_t, Length, length); SERIALISE_ELEMENT(bool, HasLabel, label != NULL); m_pSerialiser->SerialiseString("label", Label); if(m_State == READING && GetResourceManager()->HasLiveResource(id)) { GLResource res = GetResourceManager()->GetLiveResource(id); if(extvariant && m_Real.glLabelObjectEXT) m_Real.glLabelObjectEXT(Identifier, res.name, Length, HasLabel ? Label.c_str() : NULL); else m_Real.glObjectLabel(Identifier, res.name, Length, HasLabel ? Label.c_str() : NULL); } return true; }
void WrappedOpenGL::glDetachShader(GLuint program, GLuint shader) { m_Real.glDetachShader(program, shader); // check that shader still exists, it might have been deleted. If it has, it's not too important // that we detach the shader (only important if the program will attach it elsewhere). if(m_State >= WRITING && program != 0 && shader != 0 && GetResourceManager()->HasCurrentResource(ShaderRes(GetCtx(), shader))) { GLResourceRecord *progRecord = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), program)); RDCASSERT(progRecord); { SCOPED_SERIALISE_CONTEXT(DETACHSHADER); Serialise_glDetachShader(program, shader); progRecord->AddChunk(scope.Get()); } } }