Module: wine Branch: master Commit: 1b400f74335e8c4b9e919aeeb72de60f16a44b4d URL: http://source.winehq.org/git/wine.git/?a=commit;h=1b400f74335e8c4b9e919aeeb7...
Author: Józef Kucia jkucia@codeweavers.com Date: Mon Feb 6 14:12:14 2017 +0100
wined3d: Implement applying state for compute pipeline.
Signed-off-by: Józef Kucia jkucia@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
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 c141d70..5ae1bdc 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 220ddee..d575159 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 0e969be..71bb929 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 9b16e14..ead8847 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)