diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c index 3ac02a00e5b..dff8fd36499 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 20c535c364b..713e959a3b0 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 58dc0da66b4..ccfcf4b0dfc 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 2aea6608714..02d0144b916 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 85c8437af5c..9490552172e 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 549a444f0e4..d664c76b93e 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 4575400f3bf..fc0a68c0756 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 ea3010f45e3..fb1a6be4c81 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 dd4d29bdd94..b540991a3ee 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);