diff options
-rw-r--r-- | retrace/glstate.cpp | 4 | ||||
-rw-r--r-- | retrace/glstate_shaders.cpp | 157 |
2 files changed, 158 insertions, 3 deletions
diff --git a/retrace/glstate.cpp b/retrace/glstate.cpp index 8e693754..b7e5e0f6 100644 --- a/retrace/glstate.cpp +++ b/retrace/glstate.cpp @@ -190,6 +190,10 @@ BufferMapping::BufferMapping() : GLvoid * BufferMapping::map(GLenum _target, GLuint _buffer) { + if (target == _target && buffer == _buffer) { + return map_pointer; + } + target = _target; buffer = _buffer; map_pointer = NULL; diff --git a/retrace/glstate_shaders.cpp b/retrace/glstate_shaders.cpp index c5faf4a9..2db1bfb9 100644 --- a/retrace/glstate_shaders.cpp +++ b/retrace/glstate_shaders.cpp @@ -166,10 +166,10 @@ dumpProgram(StateWriter &writer, Context &context, GLint program) /** - * Built-in uniforms can't be queried through glGetUniform*. + * Built-in uniforms/attributes need special treatment. */ static inline bool -isBuiltinUniform(const GLchar *name) +isBuiltinName(const GLchar *name) { return name[0] == 'g' && name[1] == 'l' && name[2] == '_'; } @@ -526,7 +526,7 @@ dumpProgramUniforms(StateWriter &writer, GLint program) GLenum type = GL_NONE; glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name); - if (isBuiltinUniform(name)) { + if (isBuiltinName(name)) { continue; } @@ -824,6 +824,152 @@ dumpProgramUniformsStage(StateWriter &writer, GLint program, const char *stage) writer.endMember(); } +struct VertexAttrib { + std::string name; + AttribDesc desc; + GLsizei offset = 0; + GLsizei stride = 0; + GLsizei size = 0; + const GLbyte *map; +}; + +static void +dumpVertexAttributes(StateWriter &writer, Context &context, GLint program) +{ + if (program <= 0) { + return; + } + + GLint activeAttribs = 0; + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribs); + if (!activeAttribs) { + return; + } + + GLint max_name_length = 0; + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); + std::vector<GLchar> name(max_name_length); + + std::map<GLuint, BufferMapping> mappings; + std::vector<VertexAttrib> attribs; + unsigned count = ~0U; + + for (GLint index = 0; index < activeAttribs; ++index) { + GLsizei length = 0; + GLint shaderSize = 0; + GLenum shaderType = GL_NONE; + glGetActiveAttrib(program, index, max_name_length, &length, &shaderSize, &shaderType, &name[0]); + + if (isBuiltinName(&name[0])) { + // TODO: Handle built-ins too + std::cerr << "warning: dumping of built-in vertex attribute (" << &name[0] << ") not yet supported\n"; + continue; + } + + GLint location = glGetAttribLocation(program, &name[0]); + if (location < 0) { + continue; + } + + GLint buffer = 0; + glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer); + if (!buffer) { + continue; + } + + + + GLint size = 0; + glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size); + GLint type = 0; + glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type); + GLint normalized = 0; + glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized); + GLint stride = 0; + glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride); + GLvoid * pointer = 0; + glGetVertexAttribPointerv(location, GL_VERTEX_ATTRIB_ARRAY_POINTER, &pointer); + + GLint offset = reinterpret_cast<intptr_t>(pointer); + assert(offset >= 0); + + GLint divisor = 0; + glGetVertexAttribiv(location, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor); + if (divisor) { + // TODO: not clear the best way of presenting instanced attibutes on the dump + std::cerr << "warning: dumping of instanced attributes (" << &name[0] << ") not yet supported\n"; + return; + } + + if (size == GL_BGRA) { + std::cerr << "warning: dumping of GL_BGRA attributes (" << &name[0] << ") not yet supported\n"; + size = 4; + } + + AttribDesc desc(type, size); + if (!desc) { + std::cerr << "warning: dumping of packed attribute (" << &name[0] << ") not yet supported\n"; + // TODO: handle + continue; + } + + attribs.emplace_back(); + VertexAttrib &attrib = attribs.back(); + attrib.name = &name[0]; + + // TODO handle normalized attributes + if (normalized) { + std::cerr << "warning: dumping of normalized attribute (" << &name[0] << ") not yet supported\n"; + } + + attrib.desc = desc; + GLsizei attribSize = attrib.desc.arrayStride; + + if (stride == 0) { + // tightly packed + stride = attribSize; + } + + attrib.offset = offset; + attrib.stride = stride; + + BufferMapping &mapping = mappings[buffer]; + attrib.map = (const GLbyte *)mapping.map(GL_ARRAY_BUFFER, buffer); + + BufferBinding bb(GL_ARRAY_BUFFER, buffer); + GLint bufferSize = 0; + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufferSize); + + if (bufferSize <= offset || + bufferSize <= offset + attribSize) { + return; + } else { + unsigned attribCount = (bufferSize - offset - attribSize)/stride + 1; + count = std::min(count, attribCount); + } + } + + if (count == 0 || count == ~0U || attribs.empty()) { + return; + } + + writer.beginMember("vertices"); + writer.beginArray(); + for (unsigned vertex = 0; vertex < count; ++vertex) { + writer.beginObject(); + for (auto attrib : attribs) { + const AttribDesc & desc = attrib.desc; + assert(desc); + + const GLbyte *vertex_data = attrib.map + attrib.stride*vertex + attrib.offset; + dumpAttribArray(writer, attrib.name, desc, vertex_data); + } + writer.endObject(); + } + writer.endArray(); + writer.endMember(); +} + void dumpShadersUniforms(StateWriter &writer, Context &context) { @@ -890,6 +1036,11 @@ dumpShadersUniforms(StateWriter &writer, Context &context) writer.beginMember("buffers"); writer.beginObject(); + if (pipeline) { + dumpVertexAttributes(writer, context, vertex_program); + } else { + dumpVertexAttributes(writer, context, program); + } if (program) { dumpTransformFeedback(writer, program); } |