From 1b400f74335e8c4b9e919aeeb72de60f16a44b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Mon, 6 Feb 2017 14:12:14 +0100 Subject: [PATCH] wined3d: Implement applying state for compute pipeline. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/context.c | 45 ++++++++++++++++++++++++++++++---- dlls/wined3d/cs.c | 19 +++++++++++--- dlls/wined3d/device.c | 8 ++++++ dlls/wined3d/wined3d_private.h | 5 ++++ 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index c141d705f50..5ae1bdcfb15 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -1405,6 +1405,16 @@ static void context_enter(struct wined3d_context *context) } } +void context_invalidate_compute_state(struct wined3d_context *context, DWORD state_id) +{ + DWORD representative = context->state_table[state_id].representative; + unsigned int index, shift; + + index = representative / (sizeof(*context->dirty_compute_states) * CHAR_BIT); + shift = representative & (sizeof(*context->dirty_compute_states) * CHAR_BIT - 1); + context->dirty_compute_states[index] |= (1u << shift); +} + void context_invalidate_state(struct wined3d_context *context, DWORD state) { DWORD rep = context->state_table[state].representative; @@ -3312,7 +3322,8 @@ static void context_preload_textures(struct wined3d_context *context, const stru } } -static void context_load_shader_resources(struct wined3d_context *context, const struct wined3d_state *state) +static void context_load_shader_resources(struct wined3d_context *context, const struct wined3d_state *state, + unsigned int shader_mask) { struct wined3d_shader_sampler_map_entry *entry; struct wined3d_shader_resource_view *view; @@ -3321,6 +3332,9 @@ static void context_load_shader_resources(struct wined3d_context *context, const for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i) { + if (!(shader_mask & (1u << i))) + continue; + if (!(shader = state->shader[i])) continue; @@ -3489,7 +3503,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, * updating a resource location. */ context_update_tex_unit_map(context, state); context_preload_textures(context, state); - context_load_shader_resources(context, state); + context_load_shader_resources(context, state, ~(1u << WINED3D_SHADER_TYPE_COMPUTE)); /* TODO: Right now the dependency on the vertex shader is necessary * since context_stream_info_from_declaration depends on the reg_maps of * the current VS but maybe it's possible to relax the coupling in some @@ -3528,10 +3542,10 @@ BOOL context_apply_draw_state(struct wined3d_context *context, state_table[rep].apply(context, state, rep); } - if (context->shader_update_mask) + if (context->shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE)) { device->shader_backend->shader_select(device->shader_priv, context, state); - context->shader_update_mask = 0; + context->shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE; } if (context->constant_update_mask) @@ -3566,7 +3580,28 @@ BOOL context_apply_draw_state(struct wined3d_context *context, 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"); + const struct StateEntry *state_table = context->state_table; + unsigned int state_id, i, j; + + context_load_shader_resources(context, state, 1u << WINED3D_SHADER_TYPE_COMPUTE); + + for (i = 0, state_id = 0; i < ARRAY_SIZE(context->dirty_compute_states); ++i) + { + for (j = 0; j < sizeof(*context->dirty_compute_states) * CHAR_BIT; ++j, ++state_id) + { + if (context->dirty_compute_states[i] & (1u << j)) + state_table[state_id].apply(context, state, state_id); + } + } + memset(context->dirty_compute_states, 0, sizeof(*context->dirty_compute_states)); + + if (context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE)) + { + device->shader_backend->shader_select_compute(device->shader_priv, context, state); + context->shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE); + } + + context->last_was_blit = FALSE; } static void context_setup_target(struct wined3d_context *context, diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 220ddeebe98..d57515944e2 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -907,7 +907,10 @@ static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const voi if (prev) InterlockedDecrement(&prev->resource.bind_count); - device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type)); + if (op->type != WINED3D_SHADER_TYPE_COMPUTE) + device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type)); + else + device_invalidate_compute_state(cs->device, STATE_CONSTANT_BUFFER(op->type)); } void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, @@ -1020,7 +1023,8 @@ static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, cons const struct wined3d_cs_set_shader_resource_view *op = data; cs->state.shader_resource_view[op->type][op->view_idx] = op->view; - device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING); + if (op->type != WINED3D_SHADER_TYPE_COMPUTE) + device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING); } void wined3d_cs_emit_set_unordered_access_view(struct wined3d_cs *cs, unsigned int view_idx, @@ -1093,8 +1097,15 @@ static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) const struct wined3d_cs_set_shader *op = data; cs->state.shader[op->type] = op->shader; - device_invalidate_state(cs->device, STATE_SHADER(op->type)); - device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING); + if (op->type != WINED3D_SHADER_TYPE_COMPUTE) + { + device_invalidate_state(cs->device, STATE_SHADER(op->type)); + device_invalidate_state(cs->device, STATE_SHADER_RESOURCE_BINDING); + } + else + { + device_invalidate_compute_state(cs->device, STATE_SHADER(op->type)); + } } void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 0e969be247e..71bb9299b45 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5113,6 +5113,14 @@ void device_invalidate_state(const struct wined3d_device *device, DWORD state) } } +void device_invalidate_compute_state(const struct wined3d_device *device, DWORD state_id) +{ + unsigned int i; + + for (i = 0; i < device->context_count; ++i) + context_invalidate_compute_state(device->contexts[i], state_id); +} + LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode, UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9b16e14aad6..ead88474579 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1427,6 +1427,8 @@ DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN; #define STATE_HIGHEST (STATE_COLOR_KEY) +#define STATE_COMPUTE_HIGHEST (STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE)) + enum fogsource { FOGSOURCE_FFP, FOGSOURCE_VS, @@ -1530,6 +1532,7 @@ struct wined3d_context DWORD dirtyArray[STATE_HIGHEST + 1]; /* Won't get bigger than that, a state is never marked dirty 2 times */ DWORD numDirtyEntries; DWORD isStateDirty[STATE_HIGHEST / (sizeof(DWORD) * CHAR_BIT) + 1]; /* Bitmap to find out quickly if a state is dirty */ + unsigned int dirty_compute_states[STATE_COMPUTE_HIGHEST / (sizeof(unsigned int) * CHAR_BIT) + 1]; struct wined3d_device *device; struct wined3d_swapchain *swapchain; @@ -1811,6 +1814,7 @@ GLenum context_get_offscreen_gl_buffer(const struct wined3d_context *context) DE DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN; void context_gl_resource_released(struct wined3d_device *device, GLuint name, BOOL rb_namespace) DECLSPEC_HIDDEN; +void context_invalidate_compute_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN; void context_invalidate_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN; void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN; void context_resource_released(const struct wined3d_device *device, @@ -2627,6 +2631,7 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN; void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; +void device_invalidate_compute_state(const struct wined3d_device *device, DWORD state_id) DECLSPEC_HIDDEN; void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)