]> git.cworth.org Git - apitrace/commitdiff
gltrace,glretrace: Better support for indirect draws from user memory.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Sun, 14 Apr 2013 14:40:01 +0000 (15:40 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Sun, 14 Apr 2013 14:40:01 +0000 (15:40 +0100)
Not really tested, though should be no worse than current situation.

helpers/glsize.hpp
retrace/glretrace.py
wrappers/gltrace.py

index 9821b8fb40cb5166f316d27dca9bfbd6cd7a614a..339db88055e5b0bcdade7073383517f73e977880 100644 (file)
@@ -445,18 +445,142 @@ _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indice
 #define _glDrawArraysInstancedEXT_count _glDrawArraysInstanced_count
 #define _glDrawElementsInstancedEXT_count _glDrawElementsInstanced_count
 
+typedef struct {
+    GLuint count;
+    GLuint primCount;
+    GLuint first;
+    GLuint baseInstance;
+} DrawArraysIndirectCommand;
+
+static inline GLuint
+_glMultiDrawArraysIndirect_count(const GLvoid *indirect, GLsizei drawcount, GLsizei stride) {
+    const DrawArraysIndirectCommand *cmd;
+    GLvoid *temp = 0;
+
+    if (drawcount <= 0) {
+        return 0;
+    }
+
+    if (stride == 0) {
+        stride = sizeof *cmd;
+    }
+
+    GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING);
+    if (draw_indirect_buffer) {
+        // Read commands from indirect buffer object
+        GLintptr offset = (GLintptr)indirect;
+        GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride;
+        GLvoid *temp = malloc(size);
+        if (!temp) {
+            return 0;
+        }
+        memset(temp, 0, size);
+        _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp);
+        indirect = temp;
+    } else {
+        if (!indirect) {
+            return 0;
+        }
+    }
+
+    GLuint count = 0;
+    for (GLsizei i = 0; i < drawcount; ++i) {
+        cmd = (const DrawArraysIndirectCommand *)((const uint8_t *)indirect + i * stride);
+
+        GLuint count_i = _glDrawArraysInstancedBaseInstance_count(
+            cmd->first,
+            cmd->count,
+            cmd->primCount,
+            cmd->baseInstance
+        );
+
+        count = std::max(count, count_i);
+    }
+
+    if (draw_indirect_buffer) {
+        free(temp);
+    }
+
+    return count;
+}
+
 static inline GLuint
 _glDrawArraysIndirect_count(const GLvoid *indirect) {
-    os::log("apitrace: warning: %s: unsupported\n", __FUNCTION__);
-    return 0;
+    return _glMultiDrawArraysIndirect_count(indirect, 1, 0);
+}
+
+typedef struct {
+    GLuint count;
+    GLuint primCount;
+    GLuint firstIndex;
+    GLuint baseVertex;
+    GLuint baseInstance;
+} DrawElementsIndirectCommand;
+
+static inline GLuint
+_glMultiDrawElementsIndirect_count(GLenum type, const GLvoid *indirect, GLsizei drawcount, GLsizei stride) {
+    const DrawElementsIndirectCommand *cmd;
+    GLvoid *temp = 0;
+
+    if (drawcount <= 0) {
+        return 0;
+    }
+
+    if (stride == 0) {
+        stride = sizeof *cmd;
+    }
+
+    GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING);
+    if (draw_indirect_buffer) {
+        // Read commands from indirect buffer object
+        GLintptr offset = (GLintptr)indirect;
+        GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride;
+        GLvoid *temp = malloc(size);
+        if (!temp) {
+            return 0;
+        }
+        memset(temp, 0, size);
+        _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp);
+        indirect = temp;
+    } else {
+        if (!indirect) {
+            return 0;
+        }
+    }
+
+    cmd = (const DrawElementsIndirectCommand *)indirect;
+
+    GLuint count = 0;
+    for (GLsizei i = 0; i < drawcount; ++i) {
+        cmd = (const DrawElementsIndirectCommand *)((const uint8_t *)indirect + i * stride);
+
+        GLuint count_i = _glDrawElementsInstancedBaseVertexBaseInstance_count(
+            cmd->count,
+            type,
+            (GLvoid *)(uintptr_t)(cmd->firstIndex * _gl_type_size(type)),
+            cmd->primCount,
+            cmd->baseVertex,
+            cmd->baseInstance
+        );
+
+        count = std::max(count, count_i);
+    }
+
+    if (draw_indirect_buffer) {
+        free(temp);
+    }
+
+    return count;
 }
 
 static inline GLuint
 _glDrawElementsIndirect_count(GLenum type, const GLvoid *indirect) {
-    os::log("apitrace: warning: %s: unsupported\n", __FUNCTION__);
-    return 0;
+    return _glMultiDrawElementsIndirect_count(type, indirect, 1, 0);
 }
 
+#define _glMultiDrawArraysIndirectAMD_count _glMultiDrawArraysIndirect_count
+#define _glMultiDrawElementsIndirectAMD_count _glMultiDrawElementsIndirect_count
+
 static inline GLuint
 _glMultiDrawArrays_count(const GLint *first, const GLsizei *count, GLsizei drawcount) {
     GLuint _count = 0;
index 8b6c0d5c99292fda5a6a05871cbab25075fae25f..44b2f9d941438e5be45f343ef773348a72e726b9 100644 (file)
@@ -84,6 +84,8 @@ class GlRetracer(Retracer):
         "glMultiDrawArrays",
         "glMultiDrawArraysEXT",
         "glMultiModeDrawArraysIBM",
+        'glMultiDrawArraysIndirect',
+        'glMultiDrawArraysIndirectAMD',
     ])
 
     draw_elements_function_names = set([
@@ -103,11 +105,17 @@ class GlRetracer(Retracer):
         "glMultiDrawElementsBaseVertex",
         "glMultiDrawElementsEXT",
         "glMultiModeDrawElementsIBM",
+        'glMultiDrawElementsIndirect',
+        'glMultiDrawElementsIndirectAMD',
     ])
 
     draw_indirect_function_names = set([
         "glDrawArraysIndirect",
         "glDrawElementsIndirect",
+        'glMultiDrawArraysIndirect',
+        'glMultiDrawArraysIndirectAMD',
+        'glMultiDrawElementsIndirect',
+        'glMultiDrawElementsIndirectAMD',
     ])
 
     misc_draw_function_names = set([
index 5811e7bb5d1889e893f1a119a1e8e367bec23c5a..c40fbb36de62aaac143a13ab1acf9b4e894f659f 100644 (file)
@@ -443,6 +443,10 @@ class GlTracer(Tracer):
         'glMultiDrawElementsBaseVertex',
         'glDrawArraysIndirect',
         'glDrawElementsIndirect',
+        'glMultiDrawArraysIndirect',
+        'glMultiDrawArraysIndirectAMD',
+        'glMultiDrawElementsIndirect',
+        'glMultiDrawElementsIndirectAMD',
         'glDrawArraysEXT',
         'glDrawRangeElementsEXT',
         'glDrawRangeElementsEXT_size',