[PATCH 5/6] wined3d: Merge drawStridedFast() and drawStridedInstanced().
Henri Verbeet
hverbeet at codeweavers.com
Wed Apr 6 12:12:06 CDT 2016
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/wined3d/buffer.c | 2 +-
dlls/wined3d/drawprim.c | 211 +++++++++++++++++++++++-------------------------
2 files changed, 101 insertions(+), 112 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 3dd2aae..bf2e58d 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1320,7 +1320,7 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device
}
/* Observations show that draw_primitive_immediate_mode() is faster on
- * dynamic vertex buffers than converting + drawStridedFast().
+ * dynamic vertex buffers than converting + draw_primitive_arrays().
* (Half-Life 2 and others.) */
dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE];
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index b4eee2b..d83b494 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -36,55 +36,119 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
#include <math.h>
/* Context activation 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, UINT start_instance, UINT instance_count)
+static void draw_primitive_arrays(struct wined3d_context *context, const struct wined3d_state *state,
+ unsigned int count, const void *idx_data, unsigned int idx_size, unsigned int start_idx,
+ unsigned int start_instance, unsigned int instance_count)
{
- if (idx_size)
+ const struct wined3d_ffp_attrib_ops *ops = &context->d3d_info->ffp_attrib_ops;
+ GLenum idx_type = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+ const struct wined3d_stream_info *si = &context->stream_info;
+ unsigned int instanced_elements[ARRAY_SIZE(si->elements)];
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+ unsigned int instanced_element_count = 0;
+ unsigned int i, j;
+
+ if (!instance_count)
{
- GLenum idxtype = idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
- if (instance_count)
+ if (!idx_size)
{
- if (start_instance)
- FIXME("Start instance (%u) not supported.\n", start_instance);
- if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
- {
- GL_EXTCALL(glDrawElementsInstancedBaseVertex(primitive_type, count, idxtype,
- (const char *)idx_data + (idx_size * start_idx), instance_count, base_vertex_index));
- checkGLcall("glDrawElementsInstancedBaseVertex");
- }
- else
- {
- GL_EXTCALL(glDrawElementsInstanced(primitive_type, count, idxtype,
- (const char *)idx_data + (idx_size * start_idx), instance_count));
- checkGLcall("glDrawElementsInstanced");
- }
+ gl_info->gl_ops.gl.p_glDrawArrays(state->gl_primitive_type, start_idx, count);
+ checkGLcall("glDrawArrays");
+ return;
}
- else if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+
+ 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));
+ GL_EXTCALL(glDrawElementsBaseVertex(state->gl_primitive_type, count, idx_type,
+ (const char *)idx_data + (idx_size * start_idx), state->base_vertex_index));
checkGLcall("glDrawElementsBaseVertex");
+ return;
}
- else
+
+ gl_info->gl_ops.gl.p_glDrawElements(state->gl_primitive_type, count,
+ idx_type, (const char *)idx_data + (idx_size * start_idx));
+ checkGLcall("glDrawElements");
+ return;
+ }
+
+ if (start_instance)
+ FIXME("Start instance (%u) not supported.\n", start_instance);
+
+ if (gl_info->supported[ARB_INSTANCED_ARRAYS])
+ {
+ if (!idx_size)
{
- gl_info->gl_ops.gl.p_glDrawElements(primitive_type, count,
- idxtype, (const char *)idx_data + (idx_size * start_idx));
- checkGLcall("glDrawElements");
+ GL_EXTCALL(glDrawArraysInstanced(state->gl_primitive_type, start_idx, count, instance_count));
+ checkGLcall("glDrawArraysInstanced");
+ return;
+ }
+
+ if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+ {
+ GL_EXTCALL(glDrawElementsInstancedBaseVertex(state->gl_primitive_type, count, idx_type,
+ (const char *)idx_data + (idx_size * start_idx), instance_count, state->base_vertex_index));
+ checkGLcall("glDrawElementsInstancedBaseVertex");
+ return;
}
+
+ GL_EXTCALL(glDrawElementsInstanced(state->gl_primitive_type, count, idx_type,
+ (const char *)idx_data + (idx_size * start_idx), instance_count));
+ checkGLcall("glDrawElementsInstanced");
+ return;
}
- else
+
+ /* Instancing emulation by mixing immediate mode and arrays. */
+
+ /* This is a nasty thing. MSDN says no hardware supports this and
+ * applications have to use software vertex processing. We don't support
+ * this for now.
+ *
+ * Shouldn't be too hard to support with OpenGL, in theory just call
+ * glDrawArrays() instead of drawElements(). But the stream fequency value
+ * has a different meaning in that situation. */
+ if (!idx_size)
{
- if (instance_count)
+ FIXME("Non-indexed instanced drawing is not supported\n");
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(si->elements); ++i)
+ {
+ if (!(si->use_map & (1u << i)))
+ continue;
+
+ if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
+ instanced_elements[instanced_element_count++] = i;
+ }
+
+ for (i = 0; i < instance_count; ++i)
+ {
+ /* Specify the instanced attributes using immediate mode calls. */
+ for (j = 0; j < instanced_element_count; ++j)
{
- if (start_instance)
- FIXME("Start instance (%u) not supported.\n", start_instance);
- GL_EXTCALL(glDrawArraysInstanced(primitive_type, start_idx, count, instance_count));
- checkGLcall("glDrawArraysInstanced");
+ const struct wined3d_stream_info_element *element;
+ unsigned int element_idx;
+ const BYTE *ptr;
+
+ element_idx = instanced_elements[j];
+ element = &si->elements[element_idx];
+ ptr = element->data.addr + element->stride * i;
+ if (element->data.buffer_object)
+ ptr += (ULONG_PTR)buffer_get_sysmem(state->streams[element->stream_idx].buffer, context);
+ ops->generic[element->format->emit_idx](element_idx, ptr);
+ }
+
+ if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
+ {
+ GL_EXTCALL(glDrawElementsBaseVertex(state->gl_primitive_type, count, idx_type,
+ (const char *)idx_data + (idx_size * start_idx), state->base_vertex_index));
+ checkGLcall("glDrawElementsBaseVertex");
}
else
{
- gl_info->gl_ops.gl.p_glDrawArrays(primitive_type, start_idx, count);
- checkGLcall("glDrawArrays");
+ gl_info->gl_ops.gl.p_glDrawElements(state->gl_primitive_type, count, idx_type,
+ (const char *)idx_data + (idx_size * start_idx));
+ checkGLcall("glDrawElements");
}
}
}
@@ -321,71 +385,6 @@ static void draw_primitive_immediate_mode(struct wined3d_context *context, const
checkGLcall("glEnd and previous calls");
}
-/* Context activation is done by the caller. */
-static void drawStridedInstanced(struct wined3d_context *context, const struct wined3d_state *state,
- const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType,
- const void *idxData, UINT idxSize, UINT startIdx, UINT base_vertex_index, UINT instance_count)
-{
- const struct wined3d_ffp_attrib_ops *ops = &context->d3d_info->ffp_attrib_ops;
- const struct wined3d_gl_info *gl_info = context->gl_info;
- int numInstancedAttribs = 0, j;
- UINT instancedData[sizeof(si->elements) / sizeof(*si->elements) /* 16 */];
- GLenum idxtype = idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
- UINT i;
-
- if (!idxSize)
- {
- /* This is a nasty thing. MSDN says no hardware supports that and apps have to use software vertex processing.
- * We don't support this for now
- *
- * Shouldn't be too hard to support with opengl, in theory just call glDrawArrays instead of drawElements.
- * But the StreamSourceFreq value has a different meaning in that situation.
- */
- FIXME("Non-indexed instanced drawing is not supported\n");
- return;
- }
-
- for (i = 0; i < sizeof(si->elements) / sizeof(*si->elements); ++i)
- {
- if (!(si->use_map & (1u << i))) continue;
-
- if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA)
- {
- instancedData[numInstancedAttribs] = i;
- numInstancedAttribs++;
- }
- }
-
- for (i = 0; i < instance_count; ++i)
- {
- /* Specify the instanced attributes using immediate mode calls */
- for(j = 0; j < numInstancedAttribs; j++) {
- const BYTE *ptr = si->elements[instancedData[j]].data.addr
- + si->elements[instancedData[j]].stride * i;
- if (si->elements[instancedData[j]].data.buffer_object)
- {
- struct wined3d_buffer *vb = state->streams[si->elements[instancedData[j]].stream_idx].buffer;
- ptr += (ULONG_PTR)buffer_get_sysmem(vb, context);
- }
-
- ops->generic[si->elements[instancedData[j]].format->emit_idx](instancedData[j], ptr);
- }
-
- if (gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
- {
- GL_EXTCALL(glDrawElementsBaseVertex(glPrimitiveType, numberOfVertices, idxtype,
- (const char *)idxData+(idxSize * startIdx), base_vertex_index));
- checkGLcall("glDrawElementsBaseVertex");
- }
- else
- {
- gl_info->gl_ops.gl.p_glDrawElements(glPrimitiveType, numberOfVertices, idxtype,
- (const char *)idxData + (idxSize * startIdx));
- checkGLcall("glDrawElements");
- }
- }
-}
-
static void remove_vbos(struct wined3d_context *context,
const struct wined3d_state *state, struct wined3d_stream_info *s)
{
@@ -569,21 +568,11 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co
}
if (context->use_immediate_mode_draw || emulation)
- {
draw_primitive_immediate_mode(context, state, stream_info, index_count,
idx_data, idx_size, start_idx, instance_count);
- }
- else if (!gl_info->supported[ARB_INSTANCED_ARRAYS] && instance_count)
- {
- /* Instancing emulation by mixing immediate mode and arrays. */
- drawStridedInstanced(context, state, stream_info, index_count, state->gl_primitive_type,
- idx_data, idx_size, start_idx, state->base_vertex_index, instance_count);
- }
else
- {
- drawStridedFast(gl_info, state->gl_primitive_type, index_count, idx_size, idx_data,
- start_idx, state->base_vertex_index, start_instance, instance_count);
- }
+ draw_primitive_arrays(context, state, index_count, idx_data,
+ idx_size, start_idx, start_instance, instance_count);
if (ib_query)
wined3d_event_query_issue(ib_query, device);
--
2.1.4
More information about the wine-patches
mailing list