From 9cdca19aa017ea1711436977855e885d91e78ab0 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 26 Mar 2010 14:46:41 +0000 Subject: [PATCH] Track vertex array state Deduce and show buffer contents --- Makefile | 4 +- source/arraystate.cpp | 34 +++++++++ source/arraystate.h | 31 ++++++++ source/bufferstate.cpp | 104 +++++++++++++++++++++++++- source/bufferstate.h | 29 +++++++- source/commandinterpreter.cpp | 84 ++++++++++++++++++++- source/glstate.cpp | 136 +++++++++++++++++++++++++++++++++- source/glstate.h | 26 ++++++- 8 files changed, 439 insertions(+), 9 deletions(-) create mode 100644 source/arraystate.cpp create mode 100644 source/arraystate.h diff --git a/Makefile b/Makefile index d06ea67..c4dedb2 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ glwrap.so: source/glwrap.o source/arraysize.o gldump: source/gldecoder.o source/gldump.o source/glprint.o source/enums.o source/arraysize.o source/tmpalloc.o $(CC) -o $@ $^ $(LIBS) $(LDFLAGS) -gldbg: source/gldbg.o source/gldecoder.o source/glprint.o source/commandinterpreter.o source/tracer.o source/process.o source/enums.o source/arraysize.o source/tmpalloc.o source/glstate.o source/texturestate.o source/bufferstate.o source/profiler.o +gldbg: source/gldbg.o source/gldecoder.o source/glprint.o source/commandinterpreter.o source/tracer.o source/process.o source/enums.o source/arraysize.o source/tmpalloc.o source/glstate.o source/texturestate.o source/bufferstate.o source/profiler.o source/arraystate.o $(CXX) -o $@ $^ $(LIBS_gldbg) $(LIBS) $(LDFLAGS) source/glwrap.o: source/functions.h gensrc/functions.enum gensrc/glwrap.funcs @@ -29,6 +29,8 @@ source/commandinterpreter.o: source/gldbg.h source/glstate.h source/process.o: source/process.h source/glstate.o: source/glstate.h source/gldecoder.h source/texturestate.h source/bufferstate.h source/texturestate.o: source/texturestate.h +source/bufferstate.o: source/arraystate.h source/bufferstate.h source/enums.h +source/arraystate.o: source/arraystate.h source/bufferstate.h %.o: %.cpp $(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $< diff --git a/source/arraystate.cpp b/source/arraystate.cpp new file mode 100644 index 0000000..37db75a --- /dev/null +++ b/source/arraystate.cpp @@ -0,0 +1,34 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#include "arraystate.h" +#include "bufferstate.h" + +ArrayState::ArrayState(): + kind(0), + index(0), + enabled(false), + size(4), + type(GL_FLOAT), + normalized(false), + stride(0), + buffer(0), + pointer(0) +{ } + +void ArrayState::set(unsigned s, GLenum t, bool n, unsigned r, BufferState *b, long p) +{ + size = s; + type = t; + stride = r; + normalized = n; + buffer = b; + pointer = p; + + if(buffer) + buffer->content.update(*this); +} diff --git a/source/arraystate.h b/source/arraystate.h new file mode 100644 index 0000000..2a0f6d5 --- /dev/null +++ b/source/arraystate.h @@ -0,0 +1,31 @@ +/* $Id$ + +This file is part of gldbg +Copyright © 2010 Mikko Rasa, Mikkosoft Productions +Distributed under the GPL +*/ + +#ifndef ARRAYSTATE_H_ +#define ARRAYSTATE_H_ + +#include + +struct BufferState; + +struct ArrayState +{ + GLenum kind; + unsigned index; + bool enabled; + unsigned size; + GLenum type; + bool normalized; + unsigned stride; + BufferState *buffer; + long pointer; + + ArrayState(); + void set(unsigned, GLenum, bool, unsigned, BufferState *, long); +}; + +#endif diff --git a/source/bufferstate.cpp b/source/bufferstate.cpp index 9b1c38f..356e82b 100644 --- a/source/bufferstate.cpp +++ b/source/bufferstate.cpp @@ -1,17 +1,110 @@ /* $Id$ This file is part of gldbg -Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions Distributed under the GPL */ #include +#include "arraystate.h" #include "bufferstate.h" #include "enums.h" using namespace std; using namespace Msp; +BufferContent::BufferContent(): + consistent(true), + stride(0) +{ } + +void BufferContent::update(const ArrayState &array) +{ + if(array.stride!=stride) + consistent = false; + + stride = array.stride; + + for(vector::iterator i=arrays.begin(); i!=arrays.end(); ++i) + if(i->kind==array.kind && i->index==array.index) + { + if(array.size!=i->size || array.type!=i->type || array.pointer!=i->offset) + { + consistent = false; + arrays.erase(i); + } + else + return; + + + break; + } + + vector::iterator place = arrays.end(); + for(vector::iterator i=arrays.begin(); i!=arrays.end(); ++i) + if(i->offset>array.pointer) + { + place = i; + break; + } + + arrays.insert(place, array); +} + +string BufferContent::describe() const +{ + if(arrays.empty()) + return "(unknown)"; + + string result; + for(vector::const_iterator i=arrays.begin(); i!=arrays.end(); ++i) + { + char kind = '?'; + if(i->kind==GL_VERTEX_ARRAY) + kind = 'V'; + else if(i->kind==GL_NORMAL_ARRAY) + kind = 'N'; + else if(i->kind==GL_COLOR_ARRAY) + kind = 'C'; + else if(i->kind==GL_TEXTURE_COORD_ARRAY && i->index==0) + kind = 'T'; + + char type[3] = { '?', 0, 0 }; + if(i->type==GL_FLOAT) + type[0] = 'F'; + else if(i->type==GL_DOUBLE) + type[0] = 'D'; + else if(i->type==GL_INT || i->type==GL_UNSIGNED_INT) + type[0] = 'I'; + else if(i->type==GL_SHORT || i->type==GL_UNSIGNED_SHORT) + type[0] = 'S'; + else if(i->type==GL_BYTE || i->type==GL_UNSIGNED_BYTE) + type[0] = 'B'; + + if(i->type==GL_UNSIGNED_INT || i->type==GL_UNSIGNED_SHORT || i->type==GL_UNSIGNED_BYTE) + { + type[1] = type[0]; + type[0] = 'U'; + } + + if(!result.empty()) + result += '_'; + result += format("%c%d%s", kind, i->size, type); + } + + return result; +} + + +BufferContent::Array::Array(const ArrayState &a): + kind(a.kind), + index(a.index), + size(a.size), + type(a.type), + offset(a.pointer) +{ } + + BufferState::BufferState(): usage(GL_STATIC_DRAW), size(0), @@ -26,11 +119,12 @@ void BufferState::set_data(unsigned sz, const void *ptr, GLenum use) data = new char[size]; if(ptr) set_sub_data(0, size, ptr); + content = BufferContent(); } void BufferState::set_sub_data(unsigned off, unsigned sz, const void *ptr) { - if(data && off+sz(ptr); copy(cptr, cptr+sz, data+off); @@ -39,5 +133,9 @@ void BufferState::set_sub_data(unsigned off, unsigned sz, const void *ptr) string BufferState::describe() const { - return format("%d bytes, %s", size, describe_enum(usage, "")); + if(content.stride) + return format("%s, %d vertices (%d bytes), %s", + content.describe(), size/content.stride, size, describe_enum(usage, "")); + else + return format("%d bytes, %s", size, describe_enum(usage, "")); } diff --git a/source/bufferstate.h b/source/bufferstate.h index 17462c6..393168d 100644 --- a/source/bufferstate.h +++ b/source/bufferstate.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of gldbg -Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions Distributed under the GPL */ @@ -9,14 +9,41 @@ Distributed under the GPL #define BUFFERSTATE_H_ #include +#include #include +struct ArrayState; + +struct BufferContent +{ + struct Array + { + GLenum kind; + unsigned index; + unsigned size; + GLenum type; + int offset; + + Array(const ArrayState &); + }; + + bool consistent; + unsigned stride; + std::vector arrays; + + BufferContent(); + void update(const ArrayState &); + std::string describe() const; +}; + struct BufferState { unsigned id; + GLenum target; GLenum usage; unsigned size; char *data; + BufferContent content; BufferState(); void set_data(unsigned, const void *, GLenum); diff --git a/source/commandinterpreter.cpp b/source/commandinterpreter.cpp index d02a0b4..e73494c 100644 --- a/source/commandinterpreter.cpp +++ b/source/commandinterpreter.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of gldbg -Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions Distributed under the GPL */ @@ -311,6 +311,88 @@ void CommandInterpreter::cmd_buffer(const string &args) IO::print("Buffer %d:\n", id); IO::print(" Size: %d bytes\n", buf.size); IO::print(" Usage: %s\n", describe_enum(buf.usage, "")); + if(buf.content.stride) + { + IO::print(" Stride: %d bytes\n", buf.content.stride); + + IO::print(" Arrays:\n"); + const vector &arrays = buf.content.arrays; + for(vector::const_iterator i=arrays.begin(); i!=arrays.end(); ++i) + { + if(i->kind) + IO::print(" %2d: %s, %d %s\n", i->offset, + describe_enum(i->kind, ""), i->size, describe_enum(i->type, "DataType")); + else + IO::print(" %2d: Attrib %d, %d %s\n", i->offset, + i->index, i->size, describe_enum(i->type, "DataType")); + } + + IO::print(" Data:\n"); + string header; + for(vector::const_iterator i=arrays.begin(); i!=arrays.end(); ++i) + { + if(!header.empty()) + header += " | "; + + string label; + if(i->kind==GL_VERTEX_ARRAY) + label = "Vertex"; + else if(i->kind==GL_NORMAL_ARRAY) + label = "Normal"; + else if(i->kind==GL_COLOR_ARRAY) + label = "Color"; + else if(i->kind==GL_TEXTURE_COORD_ARRAY) + { + if(i->size==1) + label = "TexC"; + else + label = "TexCoord"; + } + else if(!i->kind) + { + if(i->size==1) + label = format("A %d", i->index); + else + label = format("Attrib %d", i->index); + } + + unsigned width = i->size; + if(i->type==GL_FLOAT) + width *= 5; + else if(i->type==GL_UNSIGNED_BYTE) + width *= 3; + width += i->size-1; + + header.append((width-label.size())/2, ' '); + header += label; + header.append((width-label.size()+1)/2, ' '); + } + IO::print(" %s\n", header); + + unsigned n_verts = buf.size/buf.content.stride; + for(unsigned i=0; i::const_iterator j=arrays.begin(); j!=arrays.end(); ++j) + { + if(!line.empty()) + line += " |"; + + const char *base = vertex+j->offset; + for(unsigned k=0; ksize; ++k) + { + if(j->type==GL_FLOAT) + line += format(" %5.2f", *(reinterpret_cast(base)+k)); + else if(j->type==GL_UNSIGNED_BYTE) + line += format(" %3u", *(reinterpret_cast(base)+k)); + } + } + + IO::print("%3d:%s\n", i, line); + } + } } } diff --git a/source/glstate.cpp b/source/glstate.cpp index 90b0ac0..1459324 100644 --- a/source/glstate.cpp +++ b/source/glstate.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of gldbg -Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions Distributed under the GPL */ @@ -72,9 +72,19 @@ Vector4::Vector4(): GlState::GlState(): decoder(gldecoder_new(this, NULL)), active_tex(0), + client_active_tex(0), array_buffer(0), element_buffer(0) { + vertex_array.kind = GL_VERTEX_ARRAY; + normal_array.kind = GL_NORMAL_ARRAY; + color_array.kind = GL_COLOR_ARRAY; + for(unsigned i=0; i<8; ++i) + { + texcoord_arrays[i].kind = GL_TEXTURE_COORD_ARRAY; + texcoord_arrays[i].index = i; + } + decoder->glColor3ub = wrap_normalized; decoder->glColor3ubv = wrap_array >; decoder->glColor4ub = wrap_normalized; @@ -93,6 +103,7 @@ GlState::GlState(): decoder->glTexCoord4fv = wrap_array; decoder->glNormal3f = glNormal3f; decoder->glNormal3fv = wrap_array; + decoder->glActiveTexture = glActiveTexture; decoder->glActiveTextureARB = glActiveTexture; decoder->glBindTexture = glBindTexture; @@ -100,12 +111,22 @@ GlState::GlState(): decoder->glTexParameteri = glTexParameteri; decoder->glTexParameteriv = glTexParameteriv; decoder->glDeleteTextures = glDeleteTextures; + + decoder->glVertexPointer = glVertexPointer; + decoder->glNormalPointer = glNormalPointer; + decoder->glColorPointer = glColorPointer; + decoder->glClientActiveTexture = glClientActiveTexture; + decoder->glClientActiveTextureARB = glClientActiveTexture; + decoder->glTexCoordPointer = glTexCoordPointer; + decoder->glBindBuffer = glBindBuffer; decoder->glBindBufferARB = glBindBuffer; decoder->glBufferData = glBufferData; decoder->glBufferDataARB = glBufferData; decoder->glBufferSubData = glBufferSubData; decoder->glBufferSubDataARB = glBufferSubData; + decoder->glDeleteBuffers = glDeleteBuffers; + decoder->glDeleteBuffersARB = glDeleteBuffers; } GlState::~GlState() @@ -139,6 +160,21 @@ const BufferState *GlState::get_current_buffer(GLenum target) const return const_cast(this)->get_current_buffer(target); } +bool &GlState::get_boolean_state(GLenum state) +{ + if(state==GL_VERTEX_ARRAY) + return vertex_array.enabled; + else if(state==GL_NORMAL_ARRAY) + return normal_array.enabled; + else if(state==GL_COLOR_ARRAY) + return color_array.enabled; + else if(state==GL_TEXTURE_COORD_ARRAY) + return texcoord_arrays[client_active_tex].enabled; + + static bool dummy; + return dummy; +} + TextureState *GlState::get_current_texture(GLenum target) { return texunits[active_tex].get_current_texture(target); @@ -153,6 +189,35 @@ BufferState *GlState::get_current_buffer(GLenum target) return 0; } +const ArrayState &GlState::get_array(GLenum array) const +{ + if(array==GL_VERTEX_ARRAY) + return vertex_array; + else if(array==GL_NORMAL_ARRAY) + return normal_array; + else if(array==GL_COLOR_ARRAY) + return color_array; + else if(array==GL_TEXTURE_COORD_ARRAY) + return texcoord_arrays[client_active_tex]; + else + throw InvalidParameterValue("Invalid array"); +} + +const ArrayState &GlState::get_texture_coord_array(unsigned index) const +{ + return texcoord_arrays[index]; +} + +const ArrayState &GlState::get_attrib_array(unsigned index) const +{ + map::const_iterator i = attrib_arrays.find(index); + if(i!=attrib_arrays.end()) + return i->second; + + // XXX Return a dummy? + throw KeyError("Unknown attribute array"); +} + void GlState::set_current_texture(GLenum target, unsigned id) { TexUnitState &unit = texunits[active_tex]; @@ -187,6 +252,28 @@ void GlState::set_current_buffer(GLenum target, unsigned id) element_buffer = buf; } +// Boolean state + +void GlState::glEnableClientState(void *user_data, GLenum state) +{ + reinterpret_cast(user_data)->get_boolean_state(state) = true; +} + +void GlState::glDisableClientState(void *user_data, GLenum state) +{ + reinterpret_cast(user_data)->get_boolean_state(state) = false; +} + +void GlState::glEnableVertexAttribArray(void *user_data, unsigned index) +{ + reinterpret_cast(user_data)->attrib_arrays[index].enabled = true; +} + +void GlState::glDisableVertexAttribArray(void *user_data, unsigned index) +{ + reinterpret_cast(user_data)->attrib_arrays[index].enabled = false; +} + // Vertex attributes void GlState::glColor3f(void *user_data, float r, float g, float b) @@ -241,7 +328,9 @@ void GlState::glActiveTexture(void *user_data, unsigned index) } void GlState::glBindTexture(void *user_data, GLenum target, unsigned id) -{ reinterpret_cast(user_data)->set_current_texture(target, id); } +{ + reinterpret_cast(user_data)->set_current_texture(target, id); +} void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int, GLenum, GLenum, const void *) { @@ -264,6 +353,43 @@ void GlState::glDeleteTextures(void *user_data, int count, const unsigned *ids) reinterpret_cast(user_data)->textures.erase(ids[i]); } +// Vertex arrays + +void GlState::glVertexPointer(void *user_data, int size, GLenum type, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->vertex_array.set(size, type, false, stride, self->array_buffer, reinterpret_cast(data)); +} + +void GlState::glNormalPointer(void *user_data, GLenum type, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->normal_array.set(3, type, true, stride, self->array_buffer, reinterpret_cast(data)); +} + +void GlState::glColorPointer(void *user_data, int size, GLenum type, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->color_array.set(size, type, true, stride, self->array_buffer, reinterpret_cast(data)); +} + +void GlState::glClientActiveTexture(void *user_data, unsigned index) +{ + reinterpret_cast(user_data)->client_active_tex = index-GL_TEXTURE0; +} + +void GlState::glTexCoordPointer(void *user_data, int size, GLenum type, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->texcoord_arrays[self->client_active_tex].set(size, type, false, stride, self->array_buffer, reinterpret_cast(data)); +} + +void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, int norm, int stride, const void *data) +{ + GlState *self = reinterpret_cast(user_data); + self->attrib_arrays[index].set(size, type, norm, stride, self->array_buffer, reinterpret_cast(data)); +} + // Buffer objects void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id) @@ -280,3 +406,9 @@ void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int si if(BufferState *buf = reinterpret_cast(user_data)->get_current_buffer(target)) buf->set_sub_data(offset, size, data); } + +void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids) +{ + for(int i=0; i(user_data)->buffers.erase(ids[i]); +} diff --git a/source/glstate.h b/source/glstate.h index b21034d..86cc538 100644 --- a/source/glstate.h +++ b/source/glstate.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of gldbg -Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions Distributed under the GPL */ @@ -10,6 +10,7 @@ Distributed under the GPL #include #include +#include "arraystate.h" #include "bufferstate.h" #include "gldecoder.h" #include "texturestate.h" @@ -50,11 +51,17 @@ private: Vector4 texcoord[8]; Vector3 normal; unsigned active_tex; + unsigned client_active_tex; TextureMap textures; TexUnitState texunits[8]; BufferMap buffers; BufferState *array_buffer; BufferState *element_buffer; + ArrayState vertex_array; + ArrayState normal_array; + ArrayState color_array; + ArrayState texcoord_arrays[8]; + std::map attrib_arrays; public: GlState(); @@ -70,12 +77,21 @@ public: const BufferMap &get_buffers() const { return buffers; } const BufferState &get_buffer(unsigned) const; const BufferState *get_current_buffer(GLenum) const; + const ArrayState &get_array(GLenum) const; + const ArrayState &get_texture_coord_array(unsigned) const; + const ArrayState &get_attrib_array(unsigned) const; private: + bool &get_boolean_state(GLenum); TextureState *get_current_texture(GLenum); BufferState *get_current_buffer(GLenum); void set_current_texture(GLenum, unsigned); void set_current_buffer(GLenum, unsigned); + static void glEnableClientState(void *, GLenum); + static void glDisableClientState(void *, GLenum); + static void glEnableVertexAttribArray(void *, unsigned); + static void glDisableVertexAttribArray(void *, unsigned); + static void glColor3f(void *, float, float, float); static void glColor4f(void *, float, float, float, float); static void glNormal3f(void *, float, float, float); @@ -92,9 +108,17 @@ private: static void glTexParameteriv(void *, GLenum, GLenum, const int *); static void glDeleteTextures(void *, int, const unsigned *); + static void glVertexPointer(void *, int, GLenum, int, const void *); + static void glNormalPointer(void *, GLenum, int, const void *); + static void glColorPointer(void *, int, GLenum, int, const void *); + static void glClientActiveTexture(void *, unsigned); + static void glTexCoordPointer(void *, int, GLenum, int, const void *); + static void glVertexAttribPointer(void *, unsigned, int, GLenum, int, int, const void *); + static void glBindBuffer(void *, GLenum, unsigned); static void glBufferData(void *, GLenum, int, const void *, GLenum); static void glBufferSubData(void *, GLenum, int, int, const void *); + static void glDeleteBuffers(void *, int, const unsigned *); }; #endif -- 2.43.0