[PATCH 5/5] d3d10core: Implement d3d10_device_DrawIndexedInstanced().

Henri Verbeet hverbeet at codeweavers.com
Mon Nov 26 15:52:41 CST 2012


---
 dlls/d3d10core/device.c        |   10 ++++++++--
 dlls/wined3d/device.c          |   22 +++++++++++++++-------
 dlls/wined3d/directx.c         |    1 +
 dlls/wined3d/drawprim.c        |   39 ++++++++++++++++++++++++++++-----------
 dlls/wined3d/glsl_shader.c     |    3 ++-
 dlls/wined3d/wined3d.spec      |    1 +
 dlls/wined3d/wined3d_gl.h      |    4 ++++
 dlls/wined3d/wined3d_private.h |    9 ++-------
 include/wine/wined3d.h         |    2 ++
 9 files changed, 63 insertions(+), 28 deletions(-)

diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c
index 3ac02a0..dff8fd3 100644
--- a/dlls/d3d10core/device.c
+++ b/dlls/d3d10core/device.c
@@ -236,10 +236,16 @@ static void STDMETHODCALLTYPE d3d10_device_DrawIndexedInstanced(ID3D10Device *if
         UINT instance_index_count, UINT instance_count, UINT start_index_location,
         INT base_vertex_location, UINT start_instance_location)
 {
-    FIXME("iface %p, instance_index_count %u, instance_count %u, start_index_location %u,\n"
-            "\tbase_vertex_location %d, start_instance_location %u stub!\n",
+    struct d3d10_device *device = impl_from_ID3D10Device(iface);
+
+    TRACE("iface %p, instance_index_count %u, instance_count %u, start_index_location %u,\n"
+            "\tbase_vertex_location %d, start_instance_location %u.\n",
             iface, instance_index_count, instance_count, start_index_location,
             base_vertex_location, start_instance_location);
+
+    wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_location);
+    wined3d_device_draw_indexed_primitive_instanced(device->wined3d_device, start_index_location,
+            instance_index_count, start_instance_location, instance_count);
 }
 
 static void STDMETHODCALLTYPE d3d10_device_DrawInstanced(ID3D10Device *iface,
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 20c535c..713e959 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3868,7 +3868,7 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT
 
     /* Account for the loading offset due to index buffers. Instead of
      * reloading all sources correct it with the startvertex parameter. */
-    drawPrimitive(device, vertex_count, start_vertex, FALSE, NULL);
+    draw_primitive(device, start_vertex, vertex_count, 0, 0, FALSE, NULL);
     return WINED3D_OK;
 }
 
@@ -3907,11 +3907,19 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic
         device_invalidate_state(device, STATE_BASEVERTEXINDEX);
     }
 
-    drawPrimitive(device, index_count, start_idx, TRUE, NULL);
+    draw_primitive(device, start_idx, index_count, 0, 0, TRUE, NULL);
 
     return WINED3D_OK;
 }
 
+void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device *device,
+        UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count)
+{
+    TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count);
+
+    draw_primitive(device, start_idx, index_count, start_instance, instance_count, TRUE, NULL);
+}
+
 HRESULT CDECL wined3d_device_draw_primitive_up(struct wined3d_device *device, UINT vertex_count,
         const void *stream_data, UINT stream_stride)
 {
@@ -3945,7 +3953,7 @@ HRESULT CDECL wined3d_device_draw_primitive_up(struct wined3d_device *device, UI
     /* TODO: Only mark dirty if drawing from a different UP address */
     device_invalidate_state(device, STATE_STREAMSRC);
 
-    drawPrimitive(device, vertex_count, 0, FALSE, NULL);
+    draw_primitive(device, 0, vertex_count, 0, 0, FALSE, NULL);
 
     /* MSDN specifies stream zero settings must be set to NULL */
     stream->buffer = NULL;
@@ -3983,7 +3991,7 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive_up(struct wined3d_device *de
     device->stateBlock->state.user_stream = TRUE;
     device->stateBlock->state.index_format = index_data_format_id;
 
-    /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
+    /* Set to 0 as per MSDN. Do it now due to the stream source loading during draw_primitive(). */
     device->stateBlock->state.base_vertex_index = 0;
     if (device->stateBlock->state.load_base_vertex_index)
     {
@@ -3994,7 +4002,7 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive_up(struct wined3d_device *de
     device_invalidate_state(device, STATE_STREAMSRC);
     device_invalidate_state(device, STATE_INDEXBUFFER);
 
-    drawPrimitive(device, index_count, 0, TRUE, index_data);
+    draw_primitive(device, 0, index_count, 0, 0, TRUE, index_data);
 
     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
     stream->buffer = NULL;
@@ -4024,7 +4032,7 @@ HRESULT CDECL wined3d_device_draw_primitive_strided(struct wined3d_device *devic
 
     device->stateBlock->state.base_vertex_index = 0;
     device->up_strided = strided_data;
-    drawPrimitive(device, vertex_count, 0, FALSE, NULL);
+    draw_primitive(device, 0, vertex_count, 0, 0, FALSE, NULL);
     device->up_strided = NULL;
 
     /* Invalidate the states again to make sure the values from the stateblock
@@ -4056,7 +4064,7 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive_strided(struct wined3d_devic
     device->stateBlock->state.user_stream = TRUE;
     device->stateBlock->state.base_vertex_index = 0;
     device->up_strided = strided_data;
-    drawPrimitive(device, index_count, 0, TRUE, index_data);
+    draw_primitive(device, 0, index_count, 0, 0, TRUE, index_data);
     device->up_strided = NULL;
     device->stateBlock->state.index_format = prev_idx_format;
 
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 58dc0da..ccfcf4b 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -97,6 +97,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_depth_texture",                ARB_DEPTH_TEXTURE             },
     {"GL_ARB_draw_buffers",                 ARB_DRAW_BUFFERS              },
     {"GL_ARB_draw_elements_base_vertex",    ARB_DRAW_ELEMENTS_BASE_VERTEX },
+    {"GL_ARB_draw_instanced",               ARB_DRAW_INSTANCED            },
     {"GL_ARB_fragment_program",             ARB_FRAGMENT_PROGRAM          },
     {"GL_ARB_fragment_shader",              ARB_FRAGMENT_SHADER           },
     {"GL_ARB_framebuffer_object",           ARB_FRAMEBUFFER_OBJECT        },
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 2aea660..02d0144 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -36,12 +36,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw);
 
 /* GL locking is done by the caller */
 static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size,
-        const void *idx_data, UINT start_idx, INT base_vertex_index)
+        const void *idx_data, UINT start_idx, INT base_vertex_index, UINT start_instance, UINT instance_count)
 {
     if (idx_size)
     {
         GLenum idxtype = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
-        if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+        if (instance_count)
+        {
+            if (!gl_info->supported[ARB_DRAW_INSTANCED])
+            {
+                FIXME("Instanced drawing not supported.\n");
+            }
+            else
+            {
+                if (start_instance)
+                    FIXME("Start instance (%u) not supported.\n", start_instance);
+                GL_EXTCALL(glDrawElementsInstancedBaseVertex(primitive_type, count, idxtype,
+                        (const char *)idx_data + (idx_size * start_idx), instance_count, base_vertex_index));
+                checkGLcall("glDrawElementsInstancedBaseVertex");
+            }
+        }
+        else if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
         {
             GL_EXTCALL(glDrawElementsBaseVertex(primitive_type, count, idxtype,
                     (const char *)idx_data + (idx_size * start_idx), base_vertex_index));
@@ -577,7 +592,8 @@ static void remove_vbos(const struct wined3d_gl_info *gl_info,
 }
 
 /* Routine common to the draw primitive and draw indexed primitive routines */
-void drawPrimitive(struct wined3d_device *device, UINT index_count, UINT StartIdx, BOOL indexed, const void *idxData)
+void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count,
+        UINT start_instance, UINT instance_count, BOOL indexed, const void *idx_data)
 {
     const struct wined3d_state *state = &device->stateBlock->state;
     struct wined3d_event_query *ib_query = NULL;
@@ -682,11 +698,11 @@ void drawPrimitive(struct wined3d_device *device, UINT index_count, UINT StartId
             {
                 struct wined3d_buffer *index_buffer = state->index_buffer;
                 if (!index_buffer->buffer_object || !stream_info->all_vbo)
-                    idxData = index_buffer->resource.allocatedMemory;
+                    idx_data = index_buffer->resource.allocatedMemory;
                 else
                 {
                     ib_query = index_buffer->query;
-                    idxData = NULL;
+                    idx_data = NULL;
                 }
             }
 
@@ -744,24 +760,25 @@ void drawPrimitive(struct wined3d_device *device, UINT index_count, UINT StartId
                 } else {
                     TRACE("Using immediate mode with vertex shaders for half float emulation\n");
                 }
-                drawStridedSlowVs(gl_info, state, stream_info,
-                        index_count, glPrimType, idxData, idx_size, StartIdx);
+                drawStridedSlowVs(gl_info, state, stream_info, index_count,
+                        glPrimType, idx_data, idx_size, start_idx);
             }
             else
             {
                 drawStridedSlow(device, context, stream_info, index_count,
-                        glPrimType, idxData, idx_size, StartIdx);
+                        glPrimType, idx_data, idx_size, start_idx);
             }
         }
         else if (device->instancedDraw)
         {
             /* Instancing emulation with mixing immediate mode and arrays */
-            drawStridedInstanced(gl_info, state, stream_info,
-                    index_count, glPrimType, idxData, idx_size, StartIdx, base_vertex_index);
+            drawStridedInstanced(gl_info, state, stream_info, index_count,
+                    glPrimType, idx_data, idx_size, start_idx, base_vertex_index);
         }
         else
         {
-            drawStridedFast(gl_info, glPrimType, index_count, idx_size, idxData, StartIdx, base_vertex_index);
+            drawStridedFast(gl_info, glPrimType, index_count, idx_size, idx_data,
+                    start_idx, base_vertex_index, start_instance, instance_count);
         }
     }
 
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 85c8437..9490552 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -6195,7 +6195,8 @@ static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct s
     UINT shader_model;
 
     if (gl_info->supported[EXT_GPU_SHADER4] && gl_info->supported[ARB_SHADER_BIT_ENCODING]
-            && gl_info->supported[ARB_GEOMETRY_SHADER4] && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50))
+            && gl_info->supported[ARB_GEOMETRY_SHADER4] && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50)
+            && gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] && gl_info->supported[ARB_DRAW_INSTANCED])
         shader_model = 4;
     /* ARB_shader_texture_lod or EXT_gpu_shader4 is required for the SM3
      * texldd and texldl instructions. */
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 549a444..d664c76 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -43,6 +43,7 @@
 @ cdecl wined3d_device_decref(ptr)
 @ cdecl wined3d_device_delete_patch(ptr long)
 @ cdecl wined3d_device_draw_indexed_primitive(ptr long long)
+@ cdecl wined3d_device_draw_indexed_primitive_instanced(ptr long long long long)
 @ cdecl wined3d_device_draw_indexed_primitive_strided(ptr long ptr long ptr long)
 @ cdecl wined3d_device_draw_indexed_primitive_up(ptr long ptr long ptr long)
 @ cdecl wined3d_device_draw_primitive(ptr long long)
diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h
index 4575400..fc0a68c 100644
--- a/dlls/wined3d/wined3d_gl.h
+++ b/dlls/wined3d/wined3d_gl.h
@@ -49,6 +49,7 @@ enum wined3d_gl_extension
     ARB_DEPTH_TEXTURE,
     ARB_DRAW_BUFFERS,
     ARB_DRAW_ELEMENTS_BASE_VERTEX,
+    ARB_DRAW_INSTANCED,
     ARB_FRAGMENT_PROGRAM,
     ARB_FRAGMENT_SHADER,
     ARB_FRAMEBUFFER_OBJECT,
@@ -184,6 +185,9 @@ enum wined3d_gl_extension
     USE_GL_FUNC(glDrawElementsInstancedBaseVertex) \
     USE_GL_FUNC(glDrawRangeElementsBaseVertex) \
     USE_GL_FUNC(glMultiDrawElementsBaseVertex) \
+    /* GL_ARB_draw_instanced */ \
+    USE_GL_FUNC(glDrawArraysInstancedARB) \
+    USE_GL_FUNC(glDrawElementsInstancedARB) \
     /* GL_ARB_framebuffer_object */ \
     USE_GL_FUNC(glBindFramebuffer) \
     USE_GL_FUNC(glBindRenderbuffer) \
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index ea3010f..fb1a6be 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -944,13 +944,8 @@ struct wined3d_stream_info
     WORD use_map; /* MAX_ATTRIBS, 16 */
 };
 
-/*****************************************************************************
- * Prototypes
- */
-
-/* Routine common to the draw primitive and draw indexed primitive routines */
-void drawPrimitive(struct wined3d_device *device, UINT index_count,
-        UINT start_idx, BOOL indexed, const void *idxData) DECLSPEC_HIDDEN;
+void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count,
+        UINT start_instance, UINT instance_count, BOOL indexed, const void *idx_data) DECLSPEC_HIDDEN;
 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN;
 
 typedef void (WINE_GLAPI *glAttribFunc)(const void *data);
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index dd4d29b..b540991 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2088,6 +2088,8 @@ HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx,
 ULONG __cdecl wined3d_device_decref(struct wined3d_device *device);
 HRESULT __cdecl wined3d_device_delete_patch(struct wined3d_device *device, UINT handle);
 HRESULT __cdecl wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count);
+void __cdecl wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device *device,
+        UINT start_idx, UINT index_count, UINT start_instance, UINT instance_count);
 HRESULT __cdecl wined3d_device_draw_indexed_primitive_strided(struct wined3d_device *device, UINT index_count,
         const struct wined3d_strided_data *strided_data, UINT vertex_count, const void *index_data,
         enum wined3d_format_id index_data_format_id);
-- 
1.7.8.6




More information about the wine-patches mailing list