diff options
author | Jose Fonseca <jfonseca@vmware.com> | 2016-02-09 16:50:30 +0000 |
---|---|---|
committer | Jose Fonseca <jfonseca@vmware.com> | 2016-02-09 16:50:51 +0000 |
commit | f6305d3d105376de5306f6d0e70ff666df38d2e0 (patch) | |
tree | 3db06d71d161dd67038acc036adeaea25b9d0361 | |
parent | c7552652ca01fe76af98315fedb43f9efb978691 (diff) |
glstate: Dump bound vertex attributes.
The current implementation has several limitations and there are several
things we could do to make this more useful.
But where it works, it should be better than forcing users to chase
glMapBuffer() calls up in the trace to see the attributes.
-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); } |