static inline void dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix) { if (!glIsEnabled(target)) { return; } GLint program_parameters = 0; glGetProgramivARB(target, GL_PROGRAM_PARAMETERS_ARB, &program_parameters); if (!program_parameters) { return; } GLint max_program_local_parameters = 0; glGetProgramivARB(target, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_program_local_parameters); for (GLint index = 0; index < max_program_local_parameters; ++index) { GLdouble params[4] = {0, 0, 0, 0}; glGetProgramLocalParameterdvARB(target, index, params); if (!params[0] && !params[1] && !params[2] && !params[3]) { continue; } char name[256]; snprintf(name, sizeof name, "%sprogram.local[%i]", prefix, index); json.beginMember(name); json.beginArray(); json.writeFloat(params[0]); json.writeFloat(params[1]); json.writeFloat(params[2]); json.writeFloat(params[3]); json.endArray(); json.endMember(); } GLint max_program_env_parameters = 0; glGetProgramivARB(target, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &max_program_env_parameters); for (GLint index = 0; index < max_program_env_parameters; ++index) { GLdouble params[4] = {0, 0, 0, 0}; glGetProgramEnvParameterdvARB(target, index, params); if (!params[0] && !params[1] && !params[2] && !params[3]) { continue; } char name[256]; snprintf(name, sizeof name, "%sprogram.env[%i]", prefix, index); json.beginMember(name); json.beginArray(); json.writeFloat(params[0]); json.writeFloat(params[1]); json.writeFloat(params[2]); json.writeFloat(params[3]); json.endArray(); json.endMember(); } }
static void dumpAttrib(JSONWriter &json, const AttribDesc &desc, const GLbyte *data) { assert(desc); if (desc.numRows > 1) { json.beginArray(); } for (GLint row = 0; row < desc.numRows; ++row) { if (desc.numCols > 1) { json.beginArray(); } for (GLint col = 0; col < desc.numCols; ++col) { union { const GLbyte *rawvalue; const GLfloat *fvalue; const GLdouble *dvalue; const GLint *ivalue; const GLuint *uivalue; } u; u.rawvalue = data + row*desc.rowStride + col*desc.colStride; switch (desc.elemType) { case GL_FLOAT: json.writeFloat(*u.fvalue); break; case GL_DOUBLE: json.writeFloat(*u.dvalue); break; case GL_INT: json.writeInt(*u.ivalue); break; case GL_UNSIGNED_INT: json.writeInt(*u.uivalue); break; case GL_BOOL: json.writeBool(*u.uivalue); break; default: assert(0); json.writeNull(); break; } } if (desc.numCols > 1) { json.endArray(); } } if (desc.numRows > 1) { json.endArray(); } }
static void dumpAttribArray(JSONWriter &json, const std::string & name, const AttribDesc &desc, const GLbyte *data) { json.beginMember(name); if (desc.size > 1) { json.beginArray(); } for (GLint i = 0; i < desc.size; ++i) { const GLbyte *row = data + desc.arrayStride*i; dumpAttrib(json, desc, row); } if (desc.size > 1) { json.endArray(); } json.endMember(); }
static void dumpBlendState(JSONWriter &json, ID3D11DeviceContext *pDeviceContext) { com_ptr<ID3D11BlendState> pBlendState; FLOAT BlendFactor[4]; UINT SampleMask; pDeviceContext->OMGetBlendState(&pBlendState, BlendFactor, &SampleMask); json.beginMember("BlendState"); dumpStateObjectDesc(json, pBlendState); json.endMember(); // BlendState json.beginMember("BlendFactor"); json.beginArray(); json.writeFloat(BlendFactor[0]); json.writeFloat(BlendFactor[1]); json.writeFloat(BlendFactor[2]); json.writeFloat(BlendFactor[3]); json.endArray(); json.endMember(); // BlendFactor json.writeIntMember("SampleMask", SampleMask); }
static inline void dumpTransformFeedback(JSONWriter &json, GLint program) { GLint transform_feedback_varyings = 0; glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &transform_feedback_varyings); if (!transform_feedback_varyings) { return; } GLint max_name_length = 0; glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_name_length); std::vector<GLchar> name(max_name_length); GLint buffer_mode = GL_INTERLEAVED_ATTRIBS; glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &buffer_mode); std::vector<TransformFeedbackAttrib> attribs(transform_feedback_varyings); // Calculate the offsets and strides of each attribute according to // the value of GL_TRANSFORM_FEEDBACK_BUFFER_MODE GLsizei cum_attrib_offset = 0; for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; GLsizei length = 0; GLsizei size = 0; GLenum type = GL_NONE; glGetTransformFeedbackVarying(program, slot, max_name_length, &length, &size, &type, &name[0]); attrib.name = &name[0]; const AttribDesc & desc = attrib.desc = AttribDesc(type, size); if (!desc) { return; } attrib.size = desc.arrayStride; switch (buffer_mode) { case GL_INTERLEAVED_ATTRIBS: attrib.offset = cum_attrib_offset; break; case GL_SEPARATE_ATTRIBS: attrib.offset = 0; attrib.stride = desc.arrayStride; break; default: assert(0); attrib.offset = 0; attrib.stride = 0; } cum_attrib_offset += desc.arrayStride; } if (buffer_mode == GL_INTERLEAVED_ATTRIBS) { for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; attrib.stride = cum_attrib_offset; } } GLint previous_tbo = 0; glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &previous_tbo); // Map the buffers and calculate how many vertices can they hold // XXX: We currently limit to 1024, or things can get significantly slow. unsigned numVertices = 16*1024; for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; attrib.map = NULL; if (slot == 0 || buffer_mode != GL_INTERLEAVED_ATTRIBS) { GLint tbo = 0; glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, slot, &tbo); if (!tbo) { numVertices = 0; continue; } GLint start = 0; glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_START, slot, &start); GLint size = 0; glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, slot, &size); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo); if (size == 0) { glGetBufferParameteriv(GL_TRANSFORM_FEEDBACK_BUFFER, GL_BUFFER_SIZE, &size); assert(size >= start); size -= start; } unsigned numAttribVertices = calcNumElements(size, attrib.offset, attrib.size, attrib.stride); numVertices = std::min(numVertices, numAttribVertices); attrib.map = (const GLbyte *)glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY) + start; } else { attrib.map = attribs[0].map; } } // Actually dump the vertices json.beginMember("GL_TRANSFORM_FEEDBACK"); json.beginArray(); for (unsigned vertex = 0; vertex < numVertices; ++vertex) { json.beginObject(); for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; if (!attrib.map) { continue; } const AttribDesc & desc = attrib.desc; assert(desc); const GLbyte *vertex_data = attrib.map + attrib.stride*vertex + attrib.offset; dumpAttribArray(json, attrib.name, desc, vertex_data); } json.endObject(); } json.endArray(); json.endMember(); // Unmap the buffers for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; if (slot == 0 || buffer_mode != GL_INTERLEAVED_ATTRIBS) { if (!attrib.map) { continue; } GLint tbo = 0; glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, slot, &tbo); assert(tbo); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo); glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); } } glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, previous_tbo); }
static void dumpUniform(JSONWriter &json, GLint program, const AttribDesc & desc, const GLchar *name) { if (desc.elemType == GL_NONE) { return; } union { GLfloat fvalues[4*4]; GLdouble dvalues[4*4]; GLint ivalues[4*4]; GLuint uivalues[4*4]; GLbyte data[4*4*4]; } u; GLint i; std::string qualifiedName = resolveUniformName(name, desc.size); json.beginMember(qualifiedName); if (desc.size > 1) { json.beginArray(); } for (i = 0; i < desc.size; ++i) { std::stringstream ss; ss << qualifiedName; if (desc.size > 1) { ss << '[' << i << ']'; } std::string elemName = ss.str(); GLint location = glGetUniformLocation(program, elemName.c_str()); assert(location != -1); if (location == -1) { continue; } switch (desc.elemType) { case GL_FLOAT: glGetUniformfv(program, location, u.fvalues); break; case GL_DOUBLE: glGetUniformdv(program, location, u.dvalues); break; case GL_INT: glGetUniformiv(program, location, u.ivalues); break; case GL_UNSIGNED_INT: glGetUniformuiv(program, location, u.uivalues); break; case GL_BOOL: glGetUniformiv(program, location, u.ivalues); break; default: assert(0); break; } dumpAttrib(json, desc, u.data); } if (desc.size > 1) { json.endArray(); } json.endMember(); }