diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index fdf684e3f6e..238ae312832 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -3564,6 +3564,12 @@ BOOL context_apply_draw_state(struct wined3d_context *context, return TRUE; } +void context_apply_compute_state(struct wined3d_context *context, + const struct wined3d_device *device, const struct wined3d_state *state) +{ + FIXME("Implement applying compute state.\n"); +} + static void context_setup_target(struct wined3d_context *context, struct wined3d_texture *texture, unsigned int sub_resource_idx) { diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index d2c334fda09..220ddeebe98 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -28,6 +28,7 @@ enum wined3d_cs_op { WINED3D_CS_OP_PRESENT, WINED3D_CS_OP_CLEAR, + WINED3D_CS_OP_DISPATCH, WINED3D_CS_OP_DRAW, WINED3D_CS_OP_SET_PREDICATION, WINED3D_CS_OP_SET_VIEWPORT, @@ -83,6 +84,14 @@ struct wined3d_cs_clear RECT rects[1]; }; +struct wined3d_cs_dispatch +{ + enum wined3d_cs_op opcode; + unsigned int group_count_x; + unsigned int group_count_y; + unsigned int group_count_z; +}; + struct wined3d_cs_draw { enum wined3d_cs_op opcode; @@ -482,6 +491,32 @@ static void release_shader_resources(const struct wined3d_state *state, unsigned } } +static void wined3d_cs_exec_dispatch(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_dispatch *op = data; + + dispatch_compute(cs->device, &cs->device->state, + op->group_count_x, op->group_count_y, op->group_count_z); + + release_shader_resources(&cs->device->state, 1u << WINED3D_SHADER_TYPE_COMPUTE); +} + +void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, + unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) +{ + struct wined3d_cs_dispatch *op; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_DISPATCH; + op->group_count_x = group_count_x; + op->group_count_y = group_count_y; + op->group_count_z = group_count_z; + + acquire_shader_resources(&cs->device->state, 1u << WINED3D_SHADER_TYPE_COMPUTE); + + cs->ops->submit(cs); +} + static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) { struct wined3d_state *state = &cs->device->state; @@ -1462,6 +1497,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void { /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, /* WINED3D_CS_OP_CLEAR */ wined3d_cs_exec_clear, + /* WINED3D_CS_OP_DISPATCH */ wined3d_cs_exec_dispatch, /* WINED3D_CS_OP_DRAW */ wined3d_cs_exec_draw, /* WINED3D_CS_OP_SET_PREDICATION */ wined3d_cs_exec_set_predication, /* WINED3D_CS_OP_SET_VIEWPORT */ wined3d_cs_exec_set_viewport, diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 1c69cddaba8..0e969be247e 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -3483,6 +3483,15 @@ struct wined3d_query * CDECL wined3d_device_get_predication(struct wined3d_devic return device->state.predicate; } +void CDECL wined3d_device_dispatch_compute(struct wined3d_device *device, + unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) +{ + TRACE("device %p, group_count_x %u, group_count_y %u, group_count_z %u.\n", + device, group_count_x, group_count_y, group_count_z); + + wined3d_cs_emit_dispatch(device->cs, group_count_x, group_count_y, group_count_z); +} + void CDECL wined3d_device_set_primitive_type(struct wined3d_device *device, enum wined3d_primitive_type primitive_type) { diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index a3d88b99988..49804131efb 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -580,3 +580,46 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s TRACE("Done all gl drawing.\n"); } + +void dispatch_compute(struct wined3d_device *device, const struct wined3d_state *state, + unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) +{ + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + + context = context_acquire(device, NULL); + if (!context->valid) + { + context_release(context); + WARN("Invalid context, skipping dispatch.\n"); + return; + } + gl_info = context->gl_info; + + if (!gl_info->supported[ARB_COMPUTE_SHADER]) + { + context_release(context); + FIXME("OpenGL implementation does not support compute shaders.\n"); + return; + } + + context_apply_compute_state(context, device, state); + + if (!state->shader[WINED3D_SHADER_TYPE_COMPUTE]) + { + context_release(context); + WARN("No compute shader bound, skipping dispatch.\n"); + return; + } + + GL_EXTCALL(glDispatchCompute(group_count_x, group_count_y, group_count_z)); + checkGLcall("glDispatchCompute"); + + GL_EXTCALL(glMemoryBarrier(GL_ALL_BARRIER_BITS)); + checkGLcall("glMemoryBarrier"); + + if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); +} diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 3e87ca27764..57e1efbebeb 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -39,6 +39,7 @@ @ cdecl wined3d_device_copy_sub_resource_region(ptr ptr long long long long ptr long ptr) @ cdecl wined3d_device_create(ptr long long ptr long long ptr ptr) @ cdecl wined3d_device_decref(ptr) +@ cdecl wined3d_device_dispatch_compute(ptr long long 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_primitive(ptr long long) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 2ea6763536f..2b70bad3a01 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1343,6 +1343,8 @@ struct wined3d_stream_info void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, int base_vertex_idx, unsigned int start_idx, unsigned int index_count, unsigned int start_instance, unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN; +void dispatch_compute(struct wined3d_device *device, const struct wined3d_state *state, + unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) DECLSPEC_HIDDEN; DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN; #define eps 1e-8f @@ -1783,6 +1785,8 @@ void context_alloc_occlusion_query(struct wined3d_context *context, void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) DECLSPEC_HIDDEN; BOOL context_apply_clear_state(struct wined3d_context *context, const struct wined3d_state *state, UINT rt_count, const struct wined3d_fb_state *fb) DECLSPEC_HIDDEN; +void context_apply_compute_state(struct wined3d_context *context, + const struct wined3d_device *device, const struct wined3d_state *state) DECLSPEC_HIDDEN; BOOL context_apply_draw_state(struct wined3d_context *context, const struct wined3d_device *device, const struct wined3d_state *state) DECLSPEC_HIDDEN; void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, @@ -3134,6 +3138,8 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; void wined3d_cs_emit_destroy_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; +void wined3d_cs_emit_dispatch(struct wined3d_cs *cs, + unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z) DECLSPEC_HIDDEN; void wined3d_cs_emit_draw(struct wined3d_cs *cs, int base_vertex_idx, unsigned int start_idx, unsigned int index_count, unsigned int start_instance, unsigned int instance_count, BOOL indexed) DECLSPEC_HIDDEN; void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 42a125d19fa..8b8305bff3c 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2129,6 +2129,8 @@ HRESULT __cdecl wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx, enum wined3d_device_type device_type, HWND focus_window, DWORD behaviour_flags, BYTE surface_alignment, struct wined3d_device_parent *device_parent, struct wined3d_device **device); ULONG __cdecl wined3d_device_decref(struct wined3d_device *device); +void __cdecl wined3d_device_dispatch_compute(struct wined3d_device *device, + unsigned int group_count_x, unsigned int group_count_y, unsigned int group_count_z); 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);