Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wined3d/device.c | 25 +++++++++++++++++---- dlls/wined3d/stateblock.c | 40 ++++++++++++++++++++++++---------- dlls/wined3d/wined3d_private.h | 10 +++++++++ 3 files changed, 60 insertions(+), 15 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index a7e274dd5a..b7071dbcc1 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -486,6 +486,8 @@ ULONG CDECL wined3d_device_decref(struct wined3d_device *device) { UINT i;
+ wined3d_stateblock_state_cleanup(&device->stateblock_state); + wined3d_cs_destroy(device->cs);
if (device->recording && wined3d_stateblock_decref(device->recording)) @@ -2208,21 +2210,29 @@ struct wined3d_vertex_declaration * CDECL wined3d_device_get_vertex_declaration(
void CDECL wined3d_device_set_vertex_shader(struct wined3d_device *device, struct wined3d_shader *shader) { - struct wined3d_shader *prev = device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX]; + struct wined3d_shader *prev = device->state.shader[WINED3D_SHADER_TYPE_VERTEX];
TRACE("device %p, shader %p.\n", device, shader);
+ if (shader) + wined3d_shader_incref(shader); + if (device->update_stateblock_state->vs) + wined3d_shader_decref(device->update_stateblock_state->vs); + device->update_stateblock_state->vs = shader; + if (device->recording) + { device->recording->changed.vertexShader = TRUE; + return; + }
if (shader == prev) return;
if (shader) wined3d_shader_incref(shader); - device->update_state->shader[WINED3D_SHADER_TYPE_VERTEX] = shader; - if (!device->recording) - wined3d_cs_emit_set_shader(device->cs, WINED3D_SHADER_TYPE_VERTEX, shader); + device->state.shader[WINED3D_SHADER_TYPE_VERTEX] = shader; + wined3d_cs_emit_set_shader(device->cs, WINED3D_SHADER_TYPE_VERTEX, shader); if (prev) wined3d_shader_decref(prev); } @@ -3552,6 +3562,7 @@ HRESULT CDECL wined3d_device_begin_stateblock(struct wined3d_device *device)
device->recording = stateblock; device->update_state = &stateblock->state; + device->update_stateblock_state = &stateblock->stateblock_state;
TRACE("Recording stateblock %p.\n", stateblock);
@@ -3577,6 +3588,7 @@ HRESULT CDECL wined3d_device_end_stateblock(struct wined3d_device *device, *stateblock = object; device->recording = NULL; device->update_state = &device->state; + device->update_stateblock_state = &device->stateblock_state;
TRACE("Returning stateblock %p.\n", *stateblock);
@@ -4998,6 +5010,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, } wined3d_cs_emit_reset_state(device->cs); state_cleanup(&device->state); + wined3d_stateblock_state_cleanup(&device->stateblock_state);
if (device->d3d_initialized) wined3d_device_delete_opengl_contexts(device); @@ -5005,6 +5018,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, memset(&device->state, 0, sizeof(device->state)); state_init(&device->state, &device->fb, &device->adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT); device->update_state = &device->state; + memset(&device->stateblock_state, 0, sizeof(device->stateblock_state)); + device->update_stateblock_state = &device->stateblock_state;
device_init_swapchain_state(device, swapchain); if (wined3d_settings.logo) @@ -5279,6 +5294,7 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
state_init(&device->state, &device->fb, &adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT); device->update_state = &device->state; + device->update_stateblock_state = &device->stateblock_state;
device->max_frame_latency = 3;
@@ -5286,6 +5302,7 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d, { WARN("Failed to create command stream.\n"); state_cleanup(&device->state); + wined3d_stateblock_state_cleanup(&device->stateblock_state); hr = E_FAIL; goto err; } diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 9539ae0696..4ead27b1d6 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -521,6 +521,17 @@ void state_unbind_resources(struct wined3d_state *state) } }
+void wined3d_stateblock_state_cleanup(struct wined3d_stateblock_state *state) +{ + struct wined3d_shader *shader; + + if ((shader = state->vs)) + { + state->vs = NULL; + wined3d_shader_decref(shader); + } +} + void state_cleanup(struct wined3d_state *state) { unsigned int counter; @@ -554,6 +565,7 @@ ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock) if (!refcount) { state_cleanup(&stateblock->state); + wined3d_stateblock_state_cleanup(&stateblock->stateblock_state); heap_free(stateblock); }
@@ -669,6 +681,7 @@ static void wined3d_state_record_lights(struct wined3d_state *dst_state, const s
void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock) { + const struct wined3d_stateblock_state *state = &stateblock->device->stateblock_state; const struct wined3d_state *src_state = &stateblock->device->state; unsigned int i; DWORD map; @@ -677,18 +690,15 @@ void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock)
TRACE("Capturing state %p.\n", src_state);
- if (stateblock->changed.vertexShader && stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX] - != src_state->shader[WINED3D_SHADER_TYPE_VERTEX]) + if (stateblock->changed.vertexShader && stateblock->stateblock_state.vs != state->vs) { - TRACE("Updating vertex shader from %p to %p\n", - stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX], - src_state->shader[WINED3D_SHADER_TYPE_VERTEX]); + TRACE("Updating vertex shader from %p to %p.\n", stateblock->stateblock_state.vs, state->vs);
- if (src_state->shader[WINED3D_SHADER_TYPE_VERTEX]) - wined3d_shader_incref(src_state->shader[WINED3D_SHADER_TYPE_VERTEX]); - if (stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX]) - wined3d_shader_decref(stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX]); - stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX] = src_state->shader[WINED3D_SHADER_TYPE_VERTEX]; + if (state->vs) + wined3d_shader_incref(state->vs); + if (stateblock->stateblock_state.vs) + wined3d_shader_decref(stateblock->stateblock_state.vs); + stateblock->stateblock_state.vs = state->vs; }
/* Vertex shader float constants. */ @@ -978,6 +988,7 @@ static void apply_lights(struct wined3d_device *device, const struct wined3d_sta
void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock) { + struct wined3d_stateblock_state *state = &stateblock->device->stateblock_state; struct wined3d_device *device = stateblock->device; unsigned int i; DWORD map; @@ -985,7 +996,14 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock) TRACE("Applying stateblock %p to device %p.\n", stateblock, device);
if (stateblock->changed.vertexShader) - wined3d_device_set_vertex_shader(device, stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX]); + { + if (stateblock->stateblock_state.vs) + wined3d_shader_incref(stateblock->stateblock_state.vs); + if (state->vs) + wined3d_shader_decref(state->vs); + state->vs = stateblock->stateblock_state.vs; + wined3d_device_set_vertex_shader(device, stateblock->stateblock_state.vs); + }
/* Vertex Shader Constants. */ for (i = 0; i < stateblock->num_contained_vs_consts_f; ++i) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 7b265f3662..e45ee7be33 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2968,6 +2968,11 @@ struct wined3d_dummy_textures * wined3d_device_create() ignores it. */ #define WINED3DCREATE_MULTITHREADED 0x00000004
+struct wined3d_stateblock_state +{ + struct wined3d_shader *vs; +}; + struct wined3d_device { LONG ref; @@ -3006,6 +3011,8 @@ struct wined3d_device struct wined3d_state state; struct wined3d_state *update_state; struct wined3d_stateblock *recording; + struct wined3d_stateblock_state stateblock_state; + struct wined3d_stateblock_state *update_stateblock_state;
/* Internal use fields */ struct wined3d_device_creation_parameters create_parms; @@ -3556,6 +3563,7 @@ struct wined3d_stateblock /* Array indicating whether things have been set or changed */ struct wined3d_saved_states changed; struct wined3d_state state; + struct wined3d_stateblock_state stateblock_state;
/* Contained state management */ DWORD contained_render_states[WINEHIGHEST_RENDER_STATE + 1]; @@ -3582,6 +3590,8 @@ struct wined3d_stateblock
void stateblock_init_contained_states(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN;
+void wined3d_stateblock_state_cleanup(struct wined3d_stateblock_state *state) DECLSPEC_HIDDEN; + void state_cleanup(struct wined3d_state *state) DECLSPEC_HIDDEN; void wined3d_state_enable_light(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info, struct wined3d_light_info *light_info, BOOL enable) DECLSPEC_HIDDEN;