-- v2: wined3d: Store push constants in wined3d_buffers in struct wined3d_state.
From: Zebediah Figura zfigura@codeweavers.com
All other code touching stateblocks is in stateblock.c; this is a more intuitive and modular place for it. This may merit renaming the function, but should be a subsequent commit. --- dlls/wined3d/device.c | 934 --------------------------------- dlls/wined3d/stateblock.c | 1034 +++++++++++++++++++++++++++++++++++++ 2 files changed, 1034 insertions(+), 934 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index deb6d3dc210..8bb879b41cd 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1537,32 +1537,6 @@ HRESULT CDECL wined3d_device_context_get_stream_source(const struct wined3d_devi return WINED3D_OK; }
-static void wined3d_device_set_transform(struct wined3d_device *device, - enum wined3d_transform_state state, const struct wined3d_matrix *matrix) -{ - TRACE("device %p, state %s, matrix %p.\n", - device, debug_d3dtstype(state), matrix); - TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14); - TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24); - TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34); - TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44); - - /* If the new matrix is the same as the current one, - * we cut off any further processing. this seems to be a reasonable - * optimization because as was noticed, some apps (warcraft3 for example) - * tend towards setting the same matrix repeatedly for some reason. - * - * From here on we assume that the new matrix is different, wherever it matters. */ - if (!memcmp(&device->cs->c.state->transforms[state], matrix, sizeof(*matrix))) - { - TRACE("The application is setting the same matrix over again.\n"); - return; - } - - device->cs->c.state->transforms[state] = *matrix; - wined3d_device_context_emit_set_transform(&device->cs->c, state, matrix); -} - static void wined3d_device_get_transform(const struct wined3d_device *device, enum wined3d_transform_state state, struct wined3d_matrix *matrix) { @@ -1676,56 +1650,6 @@ static void wined3d_device_context_set_light(struct wined3d_device_context *cont wined3d_device_context_emit_set_light(context, object); }
-static void wined3d_device_set_light_enable(struct wined3d_device *device, UINT light_idx, BOOL enable) -{ - struct wined3d_light_state *light_state = &device->cs->c.state->light_state; - struct wined3d_light_info *light_info; - - TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable); - - /* Special case - enabling an undefined light creates one with a strict set of parameters. */ - if (!(light_info = wined3d_light_state_get_light(light_state, light_idx))) - { - TRACE("Light enabled requested but light not defined, so defining one!\n"); - wined3d_device_context_set_light(&device->cs->c, light_idx, &WINED3D_default_light); - - if (!(light_info = wined3d_light_state_get_light(light_state, light_idx))) - { - FIXME("Adding default lights has failed dismally\n"); - return; - } - } - - if (wined3d_light_state_enable_light(light_state, &device->adapter->d3d_info, light_info, enable)) - wined3d_device_context_emit_set_light_enable(&device->cs->c, light_idx, enable); -} - -static HRESULT wined3d_device_set_clip_plane(struct wined3d_device *device, - UINT plane_idx, const struct wined3d_vec4 *plane) -{ - struct wined3d_vec4 *clip_planes = device->cs->c.state->clip_planes; - - TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane); - - if (plane_idx >= device->adapter->d3d_info.limits.max_clip_distances) - { - TRACE("Application has requested clipplane this device doesn't support.\n"); - return WINED3DERR_INVALIDCALL; - } - - if (!memcmp(&clip_planes[plane_idx], plane, sizeof(*plane))) - { - TRACE("Application is setting old values over, nothing to do.\n"); - return WINED3D_OK; - } - - clip_planes[plane_idx] = *plane; - - wined3d_device_context_emit_set_clip_plane(&device->cs->c, plane_idx, plane); - - return WINED3D_OK; -} - HRESULT CDECL wined3d_device_set_clip_status(struct wined3d_device *device, const struct wined3d_clip_status *clip_status) { @@ -1748,14 +1672,6 @@ HRESULT CDECL wined3d_device_get_clip_status(const struct wined3d_device *device return WINED3D_OK; }
-static void wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material) -{ - TRACE("device %p, material %p.\n", device, material); - - device->cs->c.state->material = *material; - wined3d_device_context_emit_set_material(&device->cs->c, material); -} - struct wined3d_buffer * CDECL wined3d_device_context_get_index_buffer(const struct wined3d_device_context *context, enum wined3d_format_id *format, unsigned int *offset) { @@ -1769,13 +1685,6 @@ struct wined3d_buffer * CDECL wined3d_device_context_get_index_buffer(const stru return state->index_buffer; }
-static void wined3d_device_set_base_vertex_index(struct wined3d_device *device, int base_index) -{ - TRACE("device %p, base_index %d.\n", device, base_index); - - device->cs->c.state->base_vertex_index = base_index; -} - void CDECL wined3d_device_context_get_viewports(const struct wined3d_device_context *context, unsigned int *viewport_count, struct wined3d_viewport *viewports) { @@ -1791,25 +1700,6 @@ void CDECL wined3d_device_context_get_viewports(const struct wined3d_device_cont *viewport_count = state->viewport_count; }
-static void resolve_depth_buffer(struct wined3d_device *device) -{ - const struct wined3d_state *state = device->cs->c.state; - struct wined3d_rendertarget_view *src_view; - struct wined3d_resource *dst_resource; - struct wined3d_texture *dst_texture; - - if (!(dst_texture = state->textures[0])) - return; - dst_resource = &dst_texture->resource; - if (!dst_resource->format->depth_size) - return; - if (!(src_view = state->fb.depth_stencil)) - return; - - wined3d_device_context_resolve_sub_resource(&device->cs->c, dst_resource, 0, - src_view->resource, src_view->sub_resource_idx, dst_resource->format->id); -} - struct wined3d_blend_state * CDECL wined3d_device_context_get_blend_state(const struct wined3d_device_context *context, struct wined3d_color *blend_factor, unsigned int *sample_mask) { @@ -1841,46 +1731,6 @@ struct wined3d_rasterizer_state * CDECL wined3d_device_context_get_rasterizer_st return context->state->rasterizer_state; }
-static void wined3d_device_set_render_state(struct wined3d_device *device, - enum wined3d_render_state state, DWORD value) -{ - if (state > WINEHIGHEST_RENDER_STATE) - { - WARN("Unhandled render state %#x.\n", state); - return; - } - - if (value == device->cs->c.state->render_states[state]) - TRACE("Application is setting the old value over, nothing to do.\n"); - else - { - device->cs->c.state->render_states[state] = value; - wined3d_device_context_emit_set_render_state(&device->cs->c, state, value); - } - - if (state == WINED3D_RS_POINTSIZE && value == WINED3D_RESZ_CODE) - { - TRACE("RESZ multisampled depth buffer resolve triggered.\n"); - resolve_depth_buffer(device); - } -} - -static void wined3d_device_set_sampler_state(struct wined3d_device *device, - UINT sampler_idx, enum wined3d_sampler_state state, DWORD value) -{ - TRACE("device %p, sampler_idx %u, state %s, value %#lx.\n", - device, sampler_idx, debug_d3dsamplerstate(state), value); - - if (value == device->cs->c.state->sampler_states[sampler_idx][state]) - { - TRACE("Application is setting the old value over, nothing to do.\n"); - return; - } - - device->cs->c.state->sampler_states[sampler_idx][state] = value; - wined3d_device_context_emit_set_sampler_state(&device->cs->c, sampler_idx, state, value); -} - void CDECL wined3d_device_context_get_scissor_rects(const struct wined3d_device_context *context, unsigned int *rect_count, RECT *rects) { @@ -2747,114 +2597,6 @@ struct wined3d_sampler * CDECL wined3d_device_context_get_sampler(const struct w return context->state->sampler[shader_type][idx]; }
-static void wined3d_device_set_vs_consts_b(struct wined3d_device *device, - unsigned int start_idx, unsigned int count, const BOOL *constants) -{ - unsigned int i; - - TRACE("device %p, start_idx %u, count %u, constants %p.\n", - device, start_idx, count, constants); - - memcpy(&device->cs->c.state->vs_consts_b[start_idx], constants, count * sizeof(*constants)); - if (TRACE_ON(d3d)) - { - for (i = 0; i < count; ++i) - TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]); - } - - wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_B, start_idx, count, constants); -} - -static void wined3d_device_set_vs_consts_i(struct wined3d_device *device, - unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants) -{ - unsigned int i; - - TRACE("device %p, start_idx %u, count %u, constants %p.\n", - device, start_idx, count, constants); - - memcpy(&device->cs->c.state->vs_consts_i[start_idx], constants, count * sizeof(*constants)); - if (TRACE_ON(d3d)) - { - for (i = 0; i < count; ++i) - TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i])); - } - - wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_I, start_idx, count, constants); -} - -static void wined3d_device_set_vs_consts_f(struct wined3d_device *device, - unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants) -{ - unsigned int i; - - TRACE("device %p, start_idx %u, count %u, constants %p.\n", - device, start_idx, count, constants); - - memcpy(&device->cs->c.state->vs_consts_f[start_idx], constants, count * sizeof(*constants)); - if (TRACE_ON(d3d)) - { - for (i = 0; i < count; ++i) - TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i])); - } - - wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_F, start_idx, count, constants); -} - -static void wined3d_device_set_ps_consts_b(struct wined3d_device *device, - unsigned int start_idx, unsigned int count, const BOOL *constants) -{ - unsigned int i; - - TRACE("device %p, start_idx %u, count %u, constants %p.\n", - device, start_idx, count, constants); - - memcpy(&device->cs->c.state->ps_consts_b[start_idx], constants, count * sizeof(*constants)); - if (TRACE_ON(d3d)) - { - for (i = 0; i < count; ++i) - TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]); - } - - wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_B, start_idx, count, constants); -} - -static void wined3d_device_set_ps_consts_i(struct wined3d_device *device, - unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants) -{ - unsigned int i; - - TRACE("device %p, start_idx %u, count %u, constants %p.\n", - device, start_idx, count, constants); - - memcpy(&device->cs->c.state->ps_consts_i[start_idx], constants, count * sizeof(*constants)); - if (TRACE_ON(d3d)) - { - for (i = 0; i < count; ++i) - TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i])); - } - - wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_I, start_idx, count, constants); -} - -static void wined3d_device_set_ps_consts_f(struct wined3d_device *device, - unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants) -{ - unsigned int i; - - TRACE("device %p, start_idx %u, count %u, constants %p.\n", - device, start_idx, count, constants); - - memcpy(&device->cs->c.state->ps_consts_f[start_idx], constants, count * sizeof(*constants)); - if (TRACE_ON(d3d)) - { - for (i = 0; i < count; ++i) - TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i])); - } - - wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_F, start_idx, count, constants); -} - struct wined3d_unordered_access_view * CDECL wined3d_device_context_get_unordered_access_view( const struct wined3d_device_context *context, enum wined3d_pipeline pipeline, unsigned int idx) { @@ -3826,682 +3568,6 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device, return hr; }
-static void wined3d_device_set_texture_stage_state(struct wined3d_device *device, - UINT stage, enum wined3d_texture_stage_state state, DWORD value) -{ - const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; - - TRACE("device %p, stage %u, state %s, value %lx.\n", - device, stage, debug_d3dtexturestate(state), value); - - if (stage >= d3d_info->limits.ffp_blend_stages) - { - WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n", - stage, d3d_info->limits.ffp_blend_stages - 1); - return; - } - - if (value == device->cs->c.state->texture_states[stage][state]) - { - TRACE("Application is setting the old value over, nothing to do.\n"); - return; - } - - device->cs->c.state->texture_states[stage][state] = value; - - wined3d_device_context_emit_set_texture_state(&device->cs->c, stage, state, value); -} - -static void wined3d_device_set_texture(struct wined3d_device *device, - UINT stage, struct wined3d_texture *texture) -{ - struct wined3d_state *state = device->cs->c.state; - struct wined3d_texture *prev; - - TRACE("device %p, stage %u, texture %p.\n", device, stage, texture); - - /* Windows accepts overflowing this array... we do not. */ - if (stage >= ARRAY_SIZE(state->textures)) - { - WARN("Ignoring invalid stage %u.\n", stage); - return; - } - - prev = state->textures[stage]; - TRACE("Previous texture %p.\n", prev); - - if (texture == prev) - { - TRACE("App is setting the same texture again, nothing to do.\n"); - return; - } - - TRACE("Setting new texture to %p.\n", texture); - state->textures[stage] = texture; - - if (texture) - wined3d_texture_incref(texture); - wined3d_device_context_emit_set_texture(&device->cs->c, stage, texture); - if (prev) - wined3d_texture_decref(prev); - - return; -} - -void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, - struct wined3d_stateblock *stateblock) -{ - BOOL set_blend_state = FALSE, set_depth_stencil_state = FALSE, set_rasterizer_state = FALSE; - const struct wined3d_stateblock_state *state = &stateblock->stateblock_state; - const struct wined3d_saved_states *changed = &stateblock->changed; - const unsigned int word_bit_count = sizeof(DWORD) * CHAR_BIT; - struct wined3d_device_context *context = &device->cs->c; - unsigned int i, j, start, idx; - bool set_depth_bounds = false; - struct wined3d_range range; - uint32_t map; - - TRACE("device %p, stateblock %p.\n", device, stateblock); - - if (changed->vertexShader) - wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_VERTEX, state->vs); - if (changed->pixelShader) - wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_PIXEL, state->ps); - - for (start = 0; ; start = range.offset + range.size) - { - if (!wined3d_bitmap_get_range(changed->vs_consts_f, WINED3D_MAX_VS_CONSTS_F, start, &range)) - break; - - wined3d_device_set_vs_consts_f(device, range.offset, range.size, &state->vs_consts_f[range.offset]); - } - - map = changed->vertexShaderConstantsI; - for (start = 0; ; start = range.offset + range.size) - { - if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range)) - break; - - wined3d_device_set_vs_consts_i(device, range.offset, range.size, &state->vs_consts_i[range.offset]); - } - - map = changed->vertexShaderConstantsB; - for (start = 0; ; start = range.offset + range.size) - { - if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range)) - break; - - wined3d_device_set_vs_consts_b(device, range.offset, range.size, &state->vs_consts_b[range.offset]); - } - - for (start = 0; ; start = range.offset + range.size) - { - if (!wined3d_bitmap_get_range(changed->ps_consts_f, WINED3D_MAX_PS_CONSTS_F, start, &range)) - break; - - wined3d_device_set_ps_consts_f(device, range.offset, range.size, &state->ps_consts_f[range.offset]); - } - - map = changed->pixelShaderConstantsI; - for (start = 0; ; start = range.offset + range.size) - { - if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range)) - break; - - wined3d_device_set_ps_consts_i(device, range.offset, range.size, &state->ps_consts_i[range.offset]); - } - - map = changed->pixelShaderConstantsB; - for (start = 0; ; start = range.offset + range.size) - { - if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range)) - break; - - wined3d_device_set_ps_consts_b(device, range.offset, range.size, &state->ps_consts_b[range.offset]); - } - - if (changed->lights) - { - struct wined3d_light_info *light, *cursor; - - LIST_FOR_EACH_ENTRY_SAFE(light, cursor, &changed->changed_lights, struct wined3d_light_info, changed_entry) - { - wined3d_device_context_set_light(context, light->OriginalIndex, &light->OriginalParms); - wined3d_device_set_light_enable(device, light->OriginalIndex, light->glIndex != -1); - list_remove(&light->changed_entry); - light->changed = false; - } - } - - for (i = 0; i < ARRAY_SIZE(changed->renderState); ++i) - { - map = changed->renderState[i]; - while (map) - { - j = wined3d_bit_scan(&map); - idx = i * word_bit_count + j; - - switch (idx) - { - case WINED3D_RS_BLENDFACTOR: - case WINED3D_RS_MULTISAMPLEMASK: - case WINED3D_RS_ALPHABLENDENABLE: - case WINED3D_RS_SRCBLEND: - case WINED3D_RS_DESTBLEND: - case WINED3D_RS_BLENDOP: - case WINED3D_RS_SEPARATEALPHABLENDENABLE: - case WINED3D_RS_SRCBLENDALPHA: - case WINED3D_RS_DESTBLENDALPHA: - case WINED3D_RS_BLENDOPALPHA: - case WINED3D_RS_COLORWRITEENABLE: - case WINED3D_RS_COLORWRITEENABLE1: - case WINED3D_RS_COLORWRITEENABLE2: - case WINED3D_RS_COLORWRITEENABLE3: - set_blend_state = TRUE; - break; - - case WINED3D_RS_BACK_STENCILFAIL: - case WINED3D_RS_BACK_STENCILFUNC: - case WINED3D_RS_BACK_STENCILPASS: - case WINED3D_RS_BACK_STENCILZFAIL: - case WINED3D_RS_STENCILENABLE: - case WINED3D_RS_STENCILFAIL: - case WINED3D_RS_STENCILFUNC: - case WINED3D_RS_STENCILREF: - case WINED3D_RS_STENCILMASK: - case WINED3D_RS_STENCILPASS: - case WINED3D_RS_STENCILWRITEMASK: - case WINED3D_RS_STENCILZFAIL: - case WINED3D_RS_TWOSIDEDSTENCILMODE: - case WINED3D_RS_ZENABLE: - case WINED3D_RS_ZFUNC: - case WINED3D_RS_ZWRITEENABLE: - set_depth_stencil_state = TRUE; - break; - - case WINED3D_RS_FILLMODE: - case WINED3D_RS_CULLMODE: - case WINED3D_RS_SLOPESCALEDEPTHBIAS: - case WINED3D_RS_DEPTHBIAS: - case WINED3D_RS_SCISSORTESTENABLE: - case WINED3D_RS_ANTIALIASEDLINEENABLE: - set_rasterizer_state = TRUE; - break; - - case WINED3D_RS_ADAPTIVETESS_X: - case WINED3D_RS_ADAPTIVETESS_Z: - case WINED3D_RS_ADAPTIVETESS_W: - set_depth_bounds = true; - break; - - case WINED3D_RS_ADAPTIVETESS_Y: - break; - - case WINED3D_RS_ANTIALIAS: - if (state->rs[WINED3D_RS_ANTIALIAS]) - FIXME("Antialias not supported yet.\n"); - break; - - case WINED3D_RS_TEXTUREPERSPECTIVE: - break; - - case WINED3D_RS_WRAPU: - if (state->rs[WINED3D_RS_WRAPU]) - FIXME("Render state WINED3D_RS_WRAPU not implemented yet.\n"); - break; - - case WINED3D_RS_WRAPV: - if (state->rs[WINED3D_RS_WRAPV]) - FIXME("Render state WINED3D_RS_WRAPV not implemented yet.\n"); - break; - - case WINED3D_RS_MONOENABLE: - if (state->rs[WINED3D_RS_MONOENABLE]) - FIXME("Render state WINED3D_RS_MONOENABLE not implemented yet.\n"); - break; - - case WINED3D_RS_ROP2: - if (state->rs[WINED3D_RS_ROP2]) - FIXME("Render state WINED3D_RS_ROP2 not implemented yet.\n"); - break; - - case WINED3D_RS_PLANEMASK: - if (state->rs[WINED3D_RS_PLANEMASK]) - FIXME("Render state WINED3D_RS_PLANEMASK not implemented yet.\n"); - break; - - case WINED3D_RS_LASTPIXEL: - if (!state->rs[WINED3D_RS_LASTPIXEL]) - { - static bool warned; - if (!warned) - { - FIXME("Last Pixel Drawing Disabled, not handled yet.\n"); - warned = true; - } - } - break; - - case WINED3D_RS_ZVISIBLE: - if (state->rs[WINED3D_RS_ZVISIBLE]) - FIXME("WINED3D_RS_ZVISIBLE not implemented.\n"); - break; - - case WINED3D_RS_SUBPIXEL: - if (state->rs[WINED3D_RS_SUBPIXEL]) - FIXME("Render state WINED3D_RS_SUBPIXEL not implemented yet.\n"); - break; - - case WINED3D_RS_SUBPIXELX: - if (state->rs[WINED3D_RS_SUBPIXELX]) - FIXME("Render state WINED3D_RS_SUBPIXELX not implemented yet.\n"); - break; - - case WINED3D_RS_STIPPLEDALPHA: - if (state->rs[WINED3D_RS_STIPPLEDALPHA]) - FIXME("Stippled Alpha not supported yet.\n"); - break; - - case WINED3D_RS_STIPPLEENABLE: - if (state->rs[WINED3D_RS_STIPPLEENABLE]) - FIXME("Render state WINED3D_RS_STIPPLEENABLE not implemented yet.\n"); - break; - - case WINED3D_RS_MIPMAPLODBIAS: - if (state->rs[WINED3D_RS_MIPMAPLODBIAS]) - FIXME("Render state WINED3D_RS_MIPMAPLODBIAS not implemented yet.\n"); - break; - - case WINED3D_RS_ANISOTROPY: - if (state->rs[WINED3D_RS_ANISOTROPY]) - FIXME("Render state WINED3D_RS_ANISOTROPY not implemented yet.\n"); - break; - - case WINED3D_RS_FLUSHBATCH: - if (state->rs[WINED3D_RS_FLUSHBATCH]) - FIXME("Render state WINED3D_RS_FLUSHBATCH not implemented yet.\n"); - break; - - case WINED3D_RS_TRANSLUCENTSORTINDEPENDENT: - if (state->rs[WINED3D_RS_TRANSLUCENTSORTINDEPENDENT]) - FIXME("Render state WINED3D_RS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n"); - break; - - case WINED3D_RS_WRAP0: - case WINED3D_RS_WRAP1: - case WINED3D_RS_WRAP2: - case WINED3D_RS_WRAP3: - case WINED3D_RS_WRAP4: - case WINED3D_RS_WRAP5: - case WINED3D_RS_WRAP6: - case WINED3D_RS_WRAP7: - case WINED3D_RS_WRAP8: - case WINED3D_RS_WRAP9: - case WINED3D_RS_WRAP10: - case WINED3D_RS_WRAP11: - case WINED3D_RS_WRAP12: - case WINED3D_RS_WRAP13: - case WINED3D_RS_WRAP14: - case WINED3D_RS_WRAP15: - { - static unsigned int once; - - if ((state->rs[idx]) && !once++) - FIXME("(WINED3D_RS_WRAP0) Texture wrapping not yet supported.\n"); - break; - } - - case WINED3D_RS_EXTENTS: - if (state->rs[WINED3D_RS_EXTENTS]) - FIXME("Render state WINED3D_RS_EXTENTS not implemented yet.\n"); - break; - - case WINED3D_RS_COLORKEYBLENDENABLE: - if (state->rs[WINED3D_RS_COLORKEYBLENDENABLE]) - FIXME("Render state WINED3D_RS_COLORKEYBLENDENABLE not implemented yet.\n"); - break; - - case WINED3D_RS_SOFTWAREVERTEXPROCESSING: - { - static unsigned int once; - - if ((state->rs[WINED3D_RS_SOFTWAREVERTEXPROCESSING]) && !once++) - FIXME("Software vertex processing not implemented.\n"); - break; - } - - case WINED3D_RS_PATCHEDGESTYLE: - if (state->rs[WINED3D_RS_PATCHEDGESTYLE] != WINED3D_PATCH_EDGE_DISCRETE) - FIXME("WINED3D_RS_PATCHEDGESTYLE %#x not yet implemented.\n", - state->rs[WINED3D_RS_PATCHEDGESTYLE]); - break; - - case WINED3D_RS_PATCHSEGMENTS: - { - union - { - DWORD d; - float f; - } tmpvalue; - tmpvalue.f = 1.0f; - - if (state->rs[WINED3D_RS_PATCHSEGMENTS] != tmpvalue.d) - { - static bool displayed = false; - - tmpvalue.d = state->rs[WINED3D_RS_PATCHSEGMENTS]; - if(!displayed) - FIXME("(WINED3D_RS_PATCHSEGMENTS,%f) not yet implemented.\n", tmpvalue.f); - - displayed = true; - } - break; - } - - case WINED3D_RS_DEBUGMONITORTOKEN: - WARN("token: %#x.\n", state->rs[WINED3D_RS_DEBUGMONITORTOKEN]); - break; - - case WINED3D_RS_INDEXEDVERTEXBLENDENABLE: - break; - - case WINED3D_RS_TWEENFACTOR: - break; - - case WINED3D_RS_POSITIONDEGREE: - if (state->rs[WINED3D_RS_POSITIONDEGREE] != WINED3D_DEGREE_CUBIC) - FIXME("WINED3D_RS_POSITIONDEGREE %#x not yet implemented.\n", - state->rs[WINED3D_RS_POSITIONDEGREE]); - break; - - case WINED3D_RS_NORMALDEGREE: - if (state->rs[WINED3D_RS_NORMALDEGREE] != WINED3D_DEGREE_LINEAR) - FIXME("WINED3D_RS_NORMALDEGREE %#x not yet implemented.\n", - state->rs[WINED3D_RS_NORMALDEGREE]); - break; - - case WINED3D_RS_MINTESSELLATIONLEVEL: - break; - - case WINED3D_RS_MAXTESSELLATIONLEVEL: - break; - - case WINED3D_RS_ENABLEADAPTIVETESSELLATION: - if (state->rs[WINED3D_RS_ENABLEADAPTIVETESSELLATION]) - FIXME("WINED3D_RS_ENABLEADAPTIVETESSELLATION %#x not yet implemented.\n", - state->rs[WINED3D_RS_ENABLEADAPTIVETESSELLATION]); - break; - - default: - wined3d_device_set_render_state(device, idx, state->rs[idx]); - break; - } - } - } - - if (set_rasterizer_state) - { - struct wined3d_rasterizer_state *rasterizer_state; - struct wined3d_rasterizer_state_desc desc; - struct wine_rb_entry *entry; - union - { - DWORD d; - float f; - } bias; - - memset(&desc, 0, sizeof(desc)); - desc.fill_mode = state->rs[WINED3D_RS_FILLMODE]; - desc.cull_mode = state->rs[WINED3D_RS_CULLMODE]; - bias.d = state->rs[WINED3D_RS_DEPTHBIAS]; - desc.depth_bias = bias.f; - bias.d = state->rs[WINED3D_RS_SLOPESCALEDEPTHBIAS]; - desc.scale_bias = bias.f; - desc.depth_clip = TRUE; - desc.scissor = state->rs[WINED3D_RS_SCISSORTESTENABLE]; - desc.line_antialias = state->rs[WINED3D_RS_ANTIALIASEDLINEENABLE]; - - if ((entry = wine_rb_get(&device->rasterizer_states, &desc))) - { - rasterizer_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_rasterizer_state, entry); - wined3d_device_context_set_rasterizer_state(context, rasterizer_state); - } - else if (SUCCEEDED(wined3d_rasterizer_state_create(device, &desc, NULL, - &wined3d_null_parent_ops, &rasterizer_state))) - { - wined3d_device_context_set_rasterizer_state(context, rasterizer_state); - if (wine_rb_put(&device->rasterizer_states, &desc, &rasterizer_state->entry) == -1) - { - ERR("Failed to insert rasterizer state.\n"); - wined3d_rasterizer_state_decref(rasterizer_state); - } - } - } - - if (set_blend_state || changed->alpha_to_coverage - || wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_ADAPTIVETESS_Y)) - { - struct wined3d_blend_state *blend_state; - struct wined3d_blend_state_desc desc; - struct wine_rb_entry *entry; - struct wined3d_color colour; - unsigned int sample_mask; - - memset(&desc, 0, sizeof(desc)); - desc.alpha_to_coverage = state->alpha_to_coverage; - desc.independent = FALSE; - if (state->rs[WINED3D_RS_ADAPTIVETESS_Y] == WINED3DFMT_ATOC) - desc.alpha_to_coverage = TRUE; - desc.rt[0].enable = state->rs[WINED3D_RS_ALPHABLENDENABLE]; - desc.rt[0].src = state->rs[WINED3D_RS_SRCBLEND]; - desc.rt[0].dst = state->rs[WINED3D_RS_DESTBLEND]; - desc.rt[0].op = state->rs[WINED3D_RS_BLENDOP]; - if (state->rs[WINED3D_RS_SEPARATEALPHABLENDENABLE]) - { - desc.rt[0].src_alpha = state->rs[WINED3D_RS_SRCBLENDALPHA]; - desc.rt[0].dst_alpha = state->rs[WINED3D_RS_DESTBLENDALPHA]; - desc.rt[0].op_alpha = state->rs[WINED3D_RS_BLENDOPALPHA]; - } - else - { - desc.rt[0].src_alpha = state->rs[WINED3D_RS_SRCBLEND]; - desc.rt[0].dst_alpha = state->rs[WINED3D_RS_DESTBLEND]; - desc.rt[0].op_alpha = state->rs[WINED3D_RS_BLENDOP]; - } - desc.rt[0].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE]; - desc.rt[1].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE1]; - desc.rt[2].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE2]; - desc.rt[3].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE3]; - if (desc.rt[1].writemask != desc.rt[0].writemask - || desc.rt[2].writemask != desc.rt[0].writemask - || desc.rt[3].writemask != desc.rt[0].writemask) - { - desc.independent = TRUE; - for (i = 1; i < 4; ++i) - { - desc.rt[i].enable = desc.rt[0].enable; - desc.rt[i].src = desc.rt[0].src; - desc.rt[i].dst = desc.rt[0].dst; - desc.rt[i].op = desc.rt[0].op; - desc.rt[i].src_alpha = desc.rt[0].src_alpha; - desc.rt[i].dst_alpha = desc.rt[0].dst_alpha; - desc.rt[i].op_alpha = desc.rt[0].op_alpha; - } - } - - if (wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_BLENDFACTOR)) - wined3d_color_from_d3dcolor(&colour, state->rs[WINED3D_RS_BLENDFACTOR]); - else - wined3d_device_context_get_blend_state(context, &colour, &sample_mask); - - if ((entry = wine_rb_get(&device->blend_states, &desc))) - { - blend_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_blend_state, entry); - wined3d_device_context_set_blend_state(context, blend_state, &colour, - state->rs[WINED3D_RS_MULTISAMPLEMASK]); - } - else if (SUCCEEDED(wined3d_blend_state_create(device, &desc, NULL, - &wined3d_null_parent_ops, &blend_state))) - { - wined3d_device_context_set_blend_state(context, blend_state, &colour, - state->rs[WINED3D_RS_MULTISAMPLEMASK]); - if (wine_rb_put(&device->blend_states, &desc, &blend_state->entry) == -1) - { - ERR("Failed to insert blend state.\n"); - wined3d_blend_state_decref(blend_state); - } - } - } - - if (set_depth_stencil_state) - { - struct wined3d_depth_stencil_state *depth_stencil_state; - struct wined3d_depth_stencil_state_desc desc; - struct wine_rb_entry *entry; - unsigned int stencil_ref; - - memset(&desc, 0, sizeof(desc)); - switch (state->rs[WINED3D_RS_ZENABLE]) - { - case WINED3D_ZB_FALSE: - desc.depth = FALSE; - break; - - case WINED3D_ZB_USEW: - FIXME("W buffer is not well handled.\n"); - case WINED3D_ZB_TRUE: - desc.depth = TRUE; - break; - - default: - FIXME("Unrecognized depth buffer type %#x.\n", state->rs[WINED3D_RS_ZENABLE]); - } - desc.depth_write = state->rs[WINED3D_RS_ZWRITEENABLE]; - desc.depth_func = state->rs[WINED3D_RS_ZFUNC]; - desc.stencil = state->rs[WINED3D_RS_STENCILENABLE]; - desc.stencil_read_mask = state->rs[WINED3D_RS_STENCILMASK]; - desc.stencil_write_mask = state->rs[WINED3D_RS_STENCILWRITEMASK]; - desc.front.fail_op = state->rs[WINED3D_RS_STENCILFAIL]; - desc.front.depth_fail_op = state->rs[WINED3D_RS_STENCILZFAIL]; - desc.front.pass_op = state->rs[WINED3D_RS_STENCILPASS]; - desc.front.func = state->rs[WINED3D_RS_STENCILFUNC]; - - if (state->rs[WINED3D_RS_TWOSIDEDSTENCILMODE]) - { - desc.back.fail_op = state->rs[WINED3D_RS_BACK_STENCILFAIL]; - desc.back.depth_fail_op = state->rs[WINED3D_RS_BACK_STENCILZFAIL]; - desc.back.pass_op = state->rs[WINED3D_RS_BACK_STENCILPASS]; - desc.back.func = state->rs[WINED3D_RS_BACK_STENCILFUNC]; - } - else - { - desc.back = desc.front; - } - - if (wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_STENCILREF)) - stencil_ref = state->rs[WINED3D_RS_STENCILREF]; - else - wined3d_device_context_get_depth_stencil_state(context, &stencil_ref); - - if ((entry = wine_rb_get(&device->depth_stencil_states, &desc))) - { - depth_stencil_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_depth_stencil_state, entry); - wined3d_device_context_set_depth_stencil_state(context, depth_stencil_state, stencil_ref); - } - else if (SUCCEEDED(wined3d_depth_stencil_state_create(device, &desc, NULL, - &wined3d_null_parent_ops, &depth_stencil_state))) - { - wined3d_device_context_set_depth_stencil_state(context, depth_stencil_state, stencil_ref); - if (wine_rb_put(&device->depth_stencil_states, &desc, &depth_stencil_state->entry) == -1) - { - ERR("Failed to insert depth/stencil state.\n"); - wined3d_depth_stencil_state_decref(depth_stencil_state); - } - } - } - - if (set_depth_bounds) - { - wined3d_device_context_set_depth_bounds(context, - state->rs[WINED3D_RS_ADAPTIVETESS_X] == WINED3DFMT_NVDB, - int_to_float(state->rs[WINED3D_RS_ADAPTIVETESS_Z]), - int_to_float(state->rs[WINED3D_RS_ADAPTIVETESS_W])); - } - - for (i = 0; i < ARRAY_SIZE(changed->textureState); ++i) - { - map = changed->textureState[i]; - while (map) - { - j = wined3d_bit_scan(&map); - wined3d_device_set_texture_stage_state(device, i, j, state->texture_states[i][j]); - } - } - - for (i = 0; i < ARRAY_SIZE(changed->samplerState); ++i) - { - map = changed->samplerState[i]; - while (map) - { - j = wined3d_bit_scan(&map); - wined3d_device_set_sampler_state(device, i, j, state->sampler_states[i][j]); - } - } - - if (changed->transforms) - { - for (i = 0; i < ARRAY_SIZE(changed->transform); ++i) - { - map = changed->transform[i]; - while (map) - { - j = wined3d_bit_scan(&map); - idx = i * word_bit_count + j; - wined3d_device_set_transform(device, idx, &state->transforms[idx]); - } - } - } - - if (changed->indices) - wined3d_device_context_set_index_buffer(context, state->index_buffer, state->index_format, 0); - wined3d_device_set_base_vertex_index(device, state->base_vertex_index); - if (changed->vertexDecl) - wined3d_device_context_set_vertex_declaration(context, state->vertex_declaration); - if (changed->material) - wined3d_device_set_material(device, &state->material); - if (changed->viewport) - wined3d_device_context_set_viewports(context, 1, &state->viewport); - if (changed->scissorRect) - wined3d_device_context_set_scissor_rects(context, 1, &state->scissor_rect); - - map = changed->streamSource | changed->streamFreq; - while (map) - { - i = wined3d_bit_scan(&map); - wined3d_device_context_set_stream_sources(context, i, 1, &state->streams[i]); - } - - map = changed->textures; - while (map) - { - i = wined3d_bit_scan(&map); - wined3d_device_set_texture(device, i, state->textures[i]); - } - - map = changed->clipplane; - while (map) - { - i = wined3d_bit_scan(&map); - wined3d_device_set_clip_plane(device, i, &state->clip_planes[i]); - } - - assert(list_empty(&stateblock->changed.changed_lights)); - memset(&stateblock->changed, 0, sizeof(stateblock->changed)); - list_init(&stateblock->changed.changed_lights); - - TRACE("Applied stateblock %p.\n", stateblock); -} - HRESULT CDECL wined3d_device_get_device_caps(const struct wined3d_device *device, struct wined3d_caps *caps) { TRACE("device %p, caps %p.\n", device, caps); diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 3d6edbfa7f3..b118daeba19 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -6,6 +6,7 @@ * Copyright 2005 Oliver Stieber * Copyright 2007 Stefan Dösinger for CodeWeavers * Copyright 2009 Henri Verbeet for CodeWeavers + * Copyright 2019,2020,2022 Zebediah Figura for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -2078,3 +2079,1036 @@ void CDECL wined3d_stateblock_reset(struct wined3d_stateblock *stateblock) stateblock->stateblock_state.light_state = &stateblock->light_state; wined3d_stateblock_state_init(&stateblock->stateblock_state, stateblock->device, WINED3D_STATE_INIT_DEFAULT); } + +static void wined3d_device_set_base_vertex_index(struct wined3d_device *device, int base_index) +{ + TRACE("device %p, base_index %d.\n", device, base_index); + + device->cs->c.state->base_vertex_index = base_index; +} + +static void wined3d_device_set_vs_consts_b(struct wined3d_device *device, + unsigned int start_idx, unsigned int count, const BOOL *constants) +{ + unsigned int i; + + TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants); + + memcpy(&device->cs->c.state->vs_consts_b[start_idx], constants, count * sizeof(*constants)); + if (TRACE_ON(d3d)) + { + for (i = 0; i < count; ++i) + TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]); + } + + wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_B, start_idx, count, constants); +} + +static void wined3d_device_set_vs_consts_i(struct wined3d_device *device, + unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants) +{ + unsigned int i; + + TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants); + + memcpy(&device->cs->c.state->vs_consts_i[start_idx], constants, count * sizeof(*constants)); + if (TRACE_ON(d3d)) + { + for (i = 0; i < count; ++i) + TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i])); + } + + wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_I, start_idx, count, constants); +} + +static void wined3d_device_set_vs_consts_f(struct wined3d_device *device, + unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants) +{ + unsigned int i; + + TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants); + + memcpy(&device->cs->c.state->vs_consts_f[start_idx], constants, count * sizeof(*constants)); + if (TRACE_ON(d3d)) + { + for (i = 0; i < count; ++i) + TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i])); + } + + wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_F, start_idx, count, constants); +} + +static void wined3d_device_set_ps_consts_b(struct wined3d_device *device, + unsigned int start_idx, unsigned int count, const BOOL *constants) +{ + unsigned int i; + + TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants); + + memcpy(&device->cs->c.state->ps_consts_b[start_idx], constants, count * sizeof(*constants)); + if (TRACE_ON(d3d)) + { + for (i = 0; i < count; ++i) + TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]); + } + + wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_B, start_idx, count, constants); +} + +static void wined3d_device_set_ps_consts_i(struct wined3d_device *device, + unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants) +{ + unsigned int i; + + TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants); + + memcpy(&device->cs->c.state->ps_consts_i[start_idx], constants, count * sizeof(*constants)); + if (TRACE_ON(d3d)) + { + for (i = 0; i < count; ++i) + TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i])); + } + + wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_I, start_idx, count, constants); +} + +static void wined3d_device_set_ps_consts_f(struct wined3d_device *device, + unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants) +{ + unsigned int i; + + TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants); + + memcpy(&device->cs->c.state->ps_consts_f[start_idx], constants, count * sizeof(*constants)); + if (TRACE_ON(d3d)) + { + for (i = 0; i < count; ++i) + TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i])); + } + + wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_F, start_idx, count, constants); +} + +/* Note lights are real special cases. Although the device caps state only + * e.g. 8 are supported, you can reference any indexes you want as long as + * that number max are enabled at any one point in time. Therefore since the + * indices can be anything, we need a hashmap of them. However, this causes + * stateblock problems. When capturing the state block, I duplicate the + * hashmap, but when recording, just build a chain pretty much of commands to + * be replayed. */ +static void wined3d_device_context_set_light(struct wined3d_device_context *context, + unsigned int light_idx, const struct wined3d_light *light) +{ + struct wined3d_light_info *object = NULL; + float rho; + + if (FAILED(wined3d_light_state_set_light(&context->state->light_state, light_idx, light, &object))) + return; + + /* Initialize the object. */ + TRACE("Light %u setting to type %#x, diffuse %s, specular %s, ambient %s, " + "position {%.8e, %.8e, %.8e}, direction {%.8e, %.8e, %.8e}, " + "range %.8e, falloff %.8e, theta %.8e, phi %.8e.\n", + light_idx, light->type, debug_color(&light->diffuse), + debug_color(&light->specular), debug_color(&light->ambient), + light->position.x, light->position.y, light->position.z, + light->direction.x, light->direction.y, light->direction.z, + light->range, light->falloff, light->theta, light->phi); + + switch (light->type) + { + case WINED3D_LIGHT_POINT: + /* Position */ + object->position.x = light->position.x; + object->position.y = light->position.y; + object->position.z = light->position.z; + object->position.w = 1.0f; + object->cutoff = 180.0f; + /* FIXME: Range */ + break; + + case WINED3D_LIGHT_DIRECTIONAL: + /* Direction */ + object->direction.x = -light->direction.x; + object->direction.y = -light->direction.y; + object->direction.z = -light->direction.z; + object->direction.w = 0.0f; + object->exponent = 0.0f; + object->cutoff = 180.0f; + break; + + case WINED3D_LIGHT_SPOT: + /* Position */ + object->position.x = light->position.x; + object->position.y = light->position.y; + object->position.z = light->position.z; + object->position.w = 1.0f; + + /* Direction */ + object->direction.x = light->direction.x; + object->direction.y = light->direction.y; + object->direction.z = light->direction.z; + object->direction.w = 0.0f; + + /* opengl-ish and d3d-ish spot lights use too different models + * for the light "intensity" as a function of the angle towards + * the main light direction, so we only can approximate very + * roughly. However, spot lights are rather rarely used in games + * (if ever used at all). Furthermore if still used, probably + * nobody pays attention to such details. */ + if (!light->falloff) + { + /* Falloff = 0 is easy, because d3d's and opengl's spot light + * equations have the falloff resp. exponent parameter as an + * exponent, so the spot light lighting will always be 1.0 for + * both of them, and we don't have to care for the rest of the + * rather complex calculation. */ + object->exponent = 0.0f; + } + else + { + rho = light->theta + (light->phi - light->theta) / (2 * light->falloff); + if (rho < 0.0001f) + rho = 0.0001f; + object->exponent = -0.3f / logf(cosf(rho / 2)); + } + + if (object->exponent > 128.0f) + object->exponent = 128.0f; + + object->cutoff = (float)(light->phi * 90 / M_PI); + /* FIXME: Range */ + break; + + case WINED3D_LIGHT_PARALLELPOINT: + object->position.x = light->position.x; + object->position.y = light->position.y; + object->position.z = light->position.z; + object->position.w = 1.0f; + break; + + default: + FIXME("Unrecognized light type %#x.\n", light->type); + } + + wined3d_device_context_emit_set_light(context, object); +} + +static void wined3d_device_set_light_enable(struct wined3d_device *device, unsigned int light_idx, bool enable) +{ + struct wined3d_light_state *light_state = &device->cs->c.state->light_state; + struct wined3d_light_info *light_info; + + TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable); + + /* Special case - enabling an undefined light creates one with a strict set of parameters. */ + if (!(light_info = wined3d_light_state_get_light(light_state, light_idx))) + { + TRACE("Light enabled requested but light not defined, so defining one!\n"); + wined3d_device_context_set_light(&device->cs->c, light_idx, &WINED3D_default_light); + + if (!(light_info = wined3d_light_state_get_light(light_state, light_idx))) + { + ERR("Adding default lights has failed dismally.\n"); + return; + } + } + + if (wined3d_light_state_enable_light(light_state, &device->adapter->d3d_info, light_info, enable)) + wined3d_device_context_emit_set_light_enable(&device->cs->c, light_idx, enable); +} + +static HRESULT wined3d_device_set_clip_plane(struct wined3d_device *device, + unsigned int plane_idx, const struct wined3d_vec4 *plane) +{ + struct wined3d_vec4 *clip_planes = device->cs->c.state->clip_planes; + + TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane); + + if (plane_idx >= device->adapter->d3d_info.limits.max_clip_distances) + { + TRACE("Application has requested clipplane this device doesn't support.\n"); + return WINED3DERR_INVALIDCALL; + } + + if (!memcmp(&clip_planes[plane_idx], plane, sizeof(*plane))) + { + TRACE("Application is setting old values over, nothing to do.\n"); + return WINED3D_OK; + } + + clip_planes[plane_idx] = *plane; + + wined3d_device_context_emit_set_clip_plane(&device->cs->c, plane_idx, plane); + + return WINED3D_OK; +} + +static void resolve_depth_buffer(struct wined3d_device *device) +{ + const struct wined3d_state *state = device->cs->c.state; + struct wined3d_rendertarget_view *src_view; + struct wined3d_resource *dst_resource; + struct wined3d_texture *dst_texture; + + if (!(dst_texture = state->textures[0])) + return; + dst_resource = &dst_texture->resource; + if (!dst_resource->format->depth_size) + return; + if (!(src_view = state->fb.depth_stencil)) + return; + + wined3d_device_context_resolve_sub_resource(&device->cs->c, dst_resource, 0, + src_view->resource, src_view->sub_resource_idx, dst_resource->format->id); +} + +static void wined3d_device_set_render_state(struct wined3d_device *device, + enum wined3d_render_state state, unsigned int value) +{ + if (state > WINEHIGHEST_RENDER_STATE) + { + WARN("Unhandled render state %#x.\n", state); + return; + } + + if (value == device->cs->c.state->render_states[state]) + { + TRACE("Application is setting the old value over, nothing to do.\n"); + } + else + { + device->cs->c.state->render_states[state] = value; + wined3d_device_context_emit_set_render_state(&device->cs->c, state, value); + } + + if (state == WINED3D_RS_POINTSIZE && value == WINED3D_RESZ_CODE) + { + TRACE("RESZ multisampled depth buffer resolve triggered.\n"); + resolve_depth_buffer(device); + } +} + +static void wined3d_device_set_texture_stage_state(struct wined3d_device *device, + unsigned int stage, enum wined3d_texture_stage_state state, uint32_t value) +{ + const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info; + + TRACE("device %p, stage %u, state %s, value %#x.\n", + device, stage, debug_d3dtexturestate(state), value); + + if (stage >= d3d_info->limits.ffp_blend_stages) + { + WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n", + stage, d3d_info->limits.ffp_blend_stages - 1); + return; + } + + if (value == device->cs->c.state->texture_states[stage][state]) + { + TRACE("Application is setting the old value over, nothing to do.\n"); + return; + } + + device->cs->c.state->texture_states[stage][state] = value; + + wined3d_device_context_emit_set_texture_state(&device->cs->c, stage, state, value); +} + +static void wined3d_device_set_sampler_state(struct wined3d_device *device, + unsigned int sampler_idx, enum wined3d_sampler_state state, unsigned int value) +{ + TRACE("device %p, sampler_idx %u, state %s, value %#x.\n", + device, sampler_idx, debug_d3dsamplerstate(state), value); + + if (value == device->cs->c.state->sampler_states[sampler_idx][state]) + { + TRACE("Application is setting the old value over, nothing to do.\n"); + return; + } + + device->cs->c.state->sampler_states[sampler_idx][state] = value; + wined3d_device_context_emit_set_sampler_state(&device->cs->c, sampler_idx, state, value); +} + +static void wined3d_device_set_texture(struct wined3d_device *device, + unsigned int stage, struct wined3d_texture *texture) +{ + struct wined3d_state *state = device->cs->c.state; + struct wined3d_texture *prev; + + TRACE("device %p, stage %u, texture %p.\n", device, stage, texture); + + if (stage >= ARRAY_SIZE(state->textures)) + { + WARN("Ignoring invalid stage %u.\n", stage); + return; + } + + prev = state->textures[stage]; + TRACE("Previous texture %p.\n", prev); + + if (texture == prev) + { + TRACE("App is setting the same texture again, nothing to do.\n"); + return; + } + + TRACE("Setting new texture to %p.\n", texture); + state->textures[stage] = texture; + + if (texture) + wined3d_texture_incref(texture); + wined3d_device_context_emit_set_texture(&device->cs->c, stage, texture); + if (prev) + wined3d_texture_decref(prev); + + return; +} + +static void wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material) +{ + TRACE("device %p, material %p.\n", device, material); + + device->cs->c.state->material = *material; + wined3d_device_context_emit_set_material(&device->cs->c, material); +} + +static void wined3d_device_set_transform(struct wined3d_device *device, + enum wined3d_transform_state state, const struct wined3d_matrix *matrix) +{ + TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix); + TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14); + TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24); + TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34); + TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44); + + /* If the new matrix is the same as the current one, + * we cut off any further processing. this seems to be a reasonable + * optimization because as was noticed, some apps (warcraft3 for example) + * tend towards setting the same matrix repeatedly for some reason. + * + * From here on we assume that the new matrix is different, wherever it matters. */ + if (!memcmp(&device->cs->c.state->transforms[state], matrix, sizeof(*matrix))) + { + TRACE("The application is setting the same matrix over again.\n"); + return; + } + + device->cs->c.state->transforms[state] = *matrix; + wined3d_device_context_emit_set_transform(&device->cs->c, state, matrix); +} + +void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, + struct wined3d_stateblock *stateblock) +{ + bool set_blend_state = false, set_depth_stencil_state = false, set_rasterizer_state = false; + const struct wined3d_stateblock_state *state = &stateblock->stateblock_state; + const struct wined3d_saved_states *changed = &stateblock->changed; + const unsigned int word_bit_count = sizeof(DWORD) * CHAR_BIT; + struct wined3d_device_context *context = &device->cs->c; + unsigned int i, j, start, idx; + bool set_depth_bounds = false; + struct wined3d_range range; + uint32_t map; + + TRACE("device %p, stateblock %p.\n", device, stateblock); + + if (changed->vertexShader) + wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_VERTEX, state->vs); + if (changed->pixelShader) + wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_PIXEL, state->ps); + + for (start = 0; ; start = range.offset + range.size) + { + if (!wined3d_bitmap_get_range(changed->vs_consts_f, WINED3D_MAX_VS_CONSTS_F, start, &range)) + break; + + wined3d_device_set_vs_consts_f(device, range.offset, range.size, &state->vs_consts_f[range.offset]); + } + + map = changed->vertexShaderConstantsI; + for (start = 0; ; start = range.offset + range.size) + { + if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range)) + break; + + wined3d_device_set_vs_consts_i(device, range.offset, range.size, &state->vs_consts_i[range.offset]); + } + + map = changed->vertexShaderConstantsB; + for (start = 0; ; start = range.offset + range.size) + { + if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range)) + break; + + wined3d_device_set_vs_consts_b(device, range.offset, range.size, &state->vs_consts_b[range.offset]); + } + + for (start = 0; ; start = range.offset + range.size) + { + if (!wined3d_bitmap_get_range(changed->ps_consts_f, WINED3D_MAX_PS_CONSTS_F, start, &range)) + break; + + wined3d_device_set_ps_consts_f(device, range.offset, range.size, &state->ps_consts_f[range.offset]); + } + + map = changed->pixelShaderConstantsI; + for (start = 0; ; start = range.offset + range.size) + { + if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range)) + break; + + wined3d_device_set_ps_consts_i(device, range.offset, range.size, &state->ps_consts_i[range.offset]); + } + + map = changed->pixelShaderConstantsB; + for (start = 0; ; start = range.offset + range.size) + { + if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range)) + break; + + wined3d_device_set_ps_consts_b(device, range.offset, range.size, &state->ps_consts_b[range.offset]); + } + + if (changed->lights) + { + struct wined3d_light_info *light, *cursor; + + LIST_FOR_EACH_ENTRY_SAFE(light, cursor, &changed->changed_lights, struct wined3d_light_info, changed_entry) + { + wined3d_device_context_set_light(context, light->OriginalIndex, &light->OriginalParms); + wined3d_device_set_light_enable(device, light->OriginalIndex, light->glIndex != -1); + list_remove(&light->changed_entry); + light->changed = false; + } + } + + for (i = 0; i < ARRAY_SIZE(changed->renderState); ++i) + { + map = changed->renderState[i]; + while (map) + { + j = wined3d_bit_scan(&map); + idx = i * word_bit_count + j; + + switch (idx) + { + case WINED3D_RS_BLENDFACTOR: + case WINED3D_RS_MULTISAMPLEMASK: + case WINED3D_RS_ALPHABLENDENABLE: + case WINED3D_RS_SRCBLEND: + case WINED3D_RS_DESTBLEND: + case WINED3D_RS_BLENDOP: + case WINED3D_RS_SEPARATEALPHABLENDENABLE: + case WINED3D_RS_SRCBLENDALPHA: + case WINED3D_RS_DESTBLENDALPHA: + case WINED3D_RS_BLENDOPALPHA: + case WINED3D_RS_COLORWRITEENABLE: + case WINED3D_RS_COLORWRITEENABLE1: + case WINED3D_RS_COLORWRITEENABLE2: + case WINED3D_RS_COLORWRITEENABLE3: + set_blend_state = true; + break; + + case WINED3D_RS_BACK_STENCILFAIL: + case WINED3D_RS_BACK_STENCILFUNC: + case WINED3D_RS_BACK_STENCILPASS: + case WINED3D_RS_BACK_STENCILZFAIL: + case WINED3D_RS_STENCILENABLE: + case WINED3D_RS_STENCILFAIL: + case WINED3D_RS_STENCILFUNC: + case WINED3D_RS_STENCILREF: + case WINED3D_RS_STENCILMASK: + case WINED3D_RS_STENCILPASS: + case WINED3D_RS_STENCILWRITEMASK: + case WINED3D_RS_STENCILZFAIL: + case WINED3D_RS_TWOSIDEDSTENCILMODE: + case WINED3D_RS_ZENABLE: + case WINED3D_RS_ZFUNC: + case WINED3D_RS_ZWRITEENABLE: + set_depth_stencil_state = true; + break; + + case WINED3D_RS_FILLMODE: + case WINED3D_RS_CULLMODE: + case WINED3D_RS_SLOPESCALEDEPTHBIAS: + case WINED3D_RS_DEPTHBIAS: + case WINED3D_RS_SCISSORTESTENABLE: + case WINED3D_RS_ANTIALIASEDLINEENABLE: + set_rasterizer_state = true; + break; + + case WINED3D_RS_ADAPTIVETESS_X: + case WINED3D_RS_ADAPTIVETESS_Z: + case WINED3D_RS_ADAPTIVETESS_W: + set_depth_bounds = true; + break; + + case WINED3D_RS_ADAPTIVETESS_Y: + break; + + case WINED3D_RS_ANTIALIAS: + if (state->rs[WINED3D_RS_ANTIALIAS]) + FIXME("Antialias not supported yet.\n"); + break; + + case WINED3D_RS_TEXTUREPERSPECTIVE: + break; + + case WINED3D_RS_WRAPU: + if (state->rs[WINED3D_RS_WRAPU]) + FIXME("Render state WINED3D_RS_WRAPU not implemented yet.\n"); + break; + + case WINED3D_RS_WRAPV: + if (state->rs[WINED3D_RS_WRAPV]) + FIXME("Render state WINED3D_RS_WRAPV not implemented yet.\n"); + break; + + case WINED3D_RS_MONOENABLE: + if (state->rs[WINED3D_RS_MONOENABLE]) + FIXME("Render state WINED3D_RS_MONOENABLE not implemented yet.\n"); + break; + + case WINED3D_RS_ROP2: + if (state->rs[WINED3D_RS_ROP2]) + FIXME("Render state WINED3D_RS_ROP2 not implemented yet.\n"); + break; + + case WINED3D_RS_PLANEMASK: + if (state->rs[WINED3D_RS_PLANEMASK]) + FIXME("Render state WINED3D_RS_PLANEMASK not implemented yet.\n"); + break; + + case WINED3D_RS_LASTPIXEL: + if (!state->rs[WINED3D_RS_LASTPIXEL]) + { + static bool warned; + if (!warned) + { + FIXME("Last Pixel Drawing Disabled, not handled yet.\n"); + warned = true; + } + } + break; + + case WINED3D_RS_ZVISIBLE: + if (state->rs[WINED3D_RS_ZVISIBLE]) + FIXME("WINED3D_RS_ZVISIBLE not implemented.\n"); + break; + + case WINED3D_RS_SUBPIXEL: + if (state->rs[WINED3D_RS_SUBPIXEL]) + FIXME("Render state WINED3D_RS_SUBPIXEL not implemented yet.\n"); + break; + + case WINED3D_RS_SUBPIXELX: + if (state->rs[WINED3D_RS_SUBPIXELX]) + FIXME("Render state WINED3D_RS_SUBPIXELX not implemented yet.\n"); + break; + + case WINED3D_RS_STIPPLEDALPHA: + if (state->rs[WINED3D_RS_STIPPLEDALPHA]) + FIXME("Stippled Alpha not supported yet.\n"); + break; + + case WINED3D_RS_STIPPLEENABLE: + if (state->rs[WINED3D_RS_STIPPLEENABLE]) + FIXME("Render state WINED3D_RS_STIPPLEENABLE not implemented yet.\n"); + break; + + case WINED3D_RS_MIPMAPLODBIAS: + if (state->rs[WINED3D_RS_MIPMAPLODBIAS]) + FIXME("Render state WINED3D_RS_MIPMAPLODBIAS not implemented yet.\n"); + break; + + case WINED3D_RS_ANISOTROPY: + if (state->rs[WINED3D_RS_ANISOTROPY]) + FIXME("Render state WINED3D_RS_ANISOTROPY not implemented yet.\n"); + break; + + case WINED3D_RS_FLUSHBATCH: + if (state->rs[WINED3D_RS_FLUSHBATCH]) + FIXME("Render state WINED3D_RS_FLUSHBATCH not implemented yet.\n"); + break; + + case WINED3D_RS_TRANSLUCENTSORTINDEPENDENT: + if (state->rs[WINED3D_RS_TRANSLUCENTSORTINDEPENDENT]) + FIXME("Render state WINED3D_RS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n"); + break; + + case WINED3D_RS_WRAP0: + case WINED3D_RS_WRAP1: + case WINED3D_RS_WRAP2: + case WINED3D_RS_WRAP3: + case WINED3D_RS_WRAP4: + case WINED3D_RS_WRAP5: + case WINED3D_RS_WRAP6: + case WINED3D_RS_WRAP7: + case WINED3D_RS_WRAP8: + case WINED3D_RS_WRAP9: + case WINED3D_RS_WRAP10: + case WINED3D_RS_WRAP11: + case WINED3D_RS_WRAP12: + case WINED3D_RS_WRAP13: + case WINED3D_RS_WRAP14: + case WINED3D_RS_WRAP15: + { + static unsigned int once; + + if ((state->rs[idx]) && !once++) + FIXME("(WINED3D_RS_WRAP0) Texture wrapping not yet supported.\n"); + break; + } + + case WINED3D_RS_EXTENTS: + if (state->rs[WINED3D_RS_EXTENTS]) + FIXME("Render state WINED3D_RS_EXTENTS not implemented yet.\n"); + break; + + case WINED3D_RS_COLORKEYBLENDENABLE: + if (state->rs[WINED3D_RS_COLORKEYBLENDENABLE]) + FIXME("Render state WINED3D_RS_COLORKEYBLENDENABLE not implemented yet.\n"); + break; + + case WINED3D_RS_SOFTWAREVERTEXPROCESSING: + { + static unsigned int once; + + if ((state->rs[WINED3D_RS_SOFTWAREVERTEXPROCESSING]) && !once++) + FIXME("Software vertex processing not implemented.\n"); + break; + } + + case WINED3D_RS_PATCHEDGESTYLE: + if (state->rs[WINED3D_RS_PATCHEDGESTYLE] != WINED3D_PATCH_EDGE_DISCRETE) + FIXME("WINED3D_RS_PATCHEDGESTYLE %#x not yet implemented.\n", + state->rs[WINED3D_RS_PATCHEDGESTYLE]); + break; + + case WINED3D_RS_PATCHSEGMENTS: + { + union + { + uint32_t d; + float f; + } tmpvalue; + tmpvalue.f = 1.0f; + + if (state->rs[WINED3D_RS_PATCHSEGMENTS] != tmpvalue.d) + { + static bool displayed = false; + + tmpvalue.d = state->rs[WINED3D_RS_PATCHSEGMENTS]; + if(!displayed) + FIXME("(WINED3D_RS_PATCHSEGMENTS,%f) not yet implemented.\n", tmpvalue.f); + + displayed = true; + } + break; + } + + case WINED3D_RS_DEBUGMONITORTOKEN: + WARN("token: %#x.\n", state->rs[WINED3D_RS_DEBUGMONITORTOKEN]); + break; + + case WINED3D_RS_INDEXEDVERTEXBLENDENABLE: + break; + + case WINED3D_RS_TWEENFACTOR: + break; + + case WINED3D_RS_POSITIONDEGREE: + if (state->rs[WINED3D_RS_POSITIONDEGREE] != WINED3D_DEGREE_CUBIC) + FIXME("WINED3D_RS_POSITIONDEGREE %#x not yet implemented.\n", + state->rs[WINED3D_RS_POSITIONDEGREE]); + break; + + case WINED3D_RS_NORMALDEGREE: + if (state->rs[WINED3D_RS_NORMALDEGREE] != WINED3D_DEGREE_LINEAR) + FIXME("WINED3D_RS_NORMALDEGREE %#x not yet implemented.\n", + state->rs[WINED3D_RS_NORMALDEGREE]); + break; + + case WINED3D_RS_MINTESSELLATIONLEVEL: + break; + + case WINED3D_RS_MAXTESSELLATIONLEVEL: + break; + + case WINED3D_RS_ENABLEADAPTIVETESSELLATION: + if (state->rs[WINED3D_RS_ENABLEADAPTIVETESSELLATION]) + FIXME("WINED3D_RS_ENABLEADAPTIVETESSELLATION %#x not yet implemented.\n", + state->rs[WINED3D_RS_ENABLEADAPTIVETESSELLATION]); + break; + + default: + wined3d_device_set_render_state(device, idx, state->rs[idx]); + break; + } + } + } + + if (set_rasterizer_state) + { + struct wined3d_rasterizer_state *rasterizer_state; + struct wined3d_rasterizer_state_desc desc; + struct wine_rb_entry *entry; + union + { + DWORD d; + float f; + } bias; + + memset(&desc, 0, sizeof(desc)); + desc.fill_mode = state->rs[WINED3D_RS_FILLMODE]; + desc.cull_mode = state->rs[WINED3D_RS_CULLMODE]; + bias.d = state->rs[WINED3D_RS_DEPTHBIAS]; + desc.depth_bias = bias.f; + bias.d = state->rs[WINED3D_RS_SLOPESCALEDEPTHBIAS]; + desc.scale_bias = bias.f; + desc.depth_clip = TRUE; + desc.scissor = state->rs[WINED3D_RS_SCISSORTESTENABLE]; + desc.line_antialias = state->rs[WINED3D_RS_ANTIALIASEDLINEENABLE]; + + if ((entry = wine_rb_get(&device->rasterizer_states, &desc))) + { + rasterizer_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_rasterizer_state, entry); + wined3d_device_context_set_rasterizer_state(context, rasterizer_state); + } + else if (SUCCEEDED(wined3d_rasterizer_state_create(device, &desc, NULL, + &wined3d_null_parent_ops, &rasterizer_state))) + { + wined3d_device_context_set_rasterizer_state(context, rasterizer_state); + if (wine_rb_put(&device->rasterizer_states, &desc, &rasterizer_state->entry) == -1) + { + ERR("Failed to insert rasterizer state.\n"); + wined3d_rasterizer_state_decref(rasterizer_state); + } + } + } + + if (set_blend_state || changed->alpha_to_coverage + || wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_ADAPTIVETESS_Y)) + { + struct wined3d_blend_state *blend_state; + struct wined3d_blend_state_desc desc; + struct wine_rb_entry *entry; + struct wined3d_color colour; + unsigned int sample_mask; + + memset(&desc, 0, sizeof(desc)); + desc.alpha_to_coverage = state->alpha_to_coverage; + desc.independent = FALSE; + if (state->rs[WINED3D_RS_ADAPTIVETESS_Y] == WINED3DFMT_ATOC) + desc.alpha_to_coverage = TRUE; + desc.rt[0].enable = state->rs[WINED3D_RS_ALPHABLENDENABLE]; + desc.rt[0].src = state->rs[WINED3D_RS_SRCBLEND]; + desc.rt[0].dst = state->rs[WINED3D_RS_DESTBLEND]; + desc.rt[0].op = state->rs[WINED3D_RS_BLENDOP]; + if (state->rs[WINED3D_RS_SEPARATEALPHABLENDENABLE]) + { + desc.rt[0].src_alpha = state->rs[WINED3D_RS_SRCBLENDALPHA]; + desc.rt[0].dst_alpha = state->rs[WINED3D_RS_DESTBLENDALPHA]; + desc.rt[0].op_alpha = state->rs[WINED3D_RS_BLENDOPALPHA]; + } + else + { + desc.rt[0].src_alpha = state->rs[WINED3D_RS_SRCBLEND]; + desc.rt[0].dst_alpha = state->rs[WINED3D_RS_DESTBLEND]; + desc.rt[0].op_alpha = state->rs[WINED3D_RS_BLENDOP]; + } + desc.rt[0].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE]; + desc.rt[1].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE1]; + desc.rt[2].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE2]; + desc.rt[3].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE3]; + if (desc.rt[1].writemask != desc.rt[0].writemask + || desc.rt[2].writemask != desc.rt[0].writemask + || desc.rt[3].writemask != desc.rt[0].writemask) + { + desc.independent = TRUE; + for (i = 1; i < 4; ++i) + { + desc.rt[i].enable = desc.rt[0].enable; + desc.rt[i].src = desc.rt[0].src; + desc.rt[i].dst = desc.rt[0].dst; + desc.rt[i].op = desc.rt[0].op; + desc.rt[i].src_alpha = desc.rt[0].src_alpha; + desc.rt[i].dst_alpha = desc.rt[0].dst_alpha; + desc.rt[i].op_alpha = desc.rt[0].op_alpha; + } + } + + if (wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_BLENDFACTOR)) + wined3d_color_from_d3dcolor(&colour, state->rs[WINED3D_RS_BLENDFACTOR]); + else + wined3d_device_context_get_blend_state(context, &colour, &sample_mask); + + if ((entry = wine_rb_get(&device->blend_states, &desc))) + { + blend_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_blend_state, entry); + wined3d_device_context_set_blend_state(context, blend_state, &colour, + state->rs[WINED3D_RS_MULTISAMPLEMASK]); + } + else if (SUCCEEDED(wined3d_blend_state_create(device, &desc, NULL, + &wined3d_null_parent_ops, &blend_state))) + { + wined3d_device_context_set_blend_state(context, blend_state, &colour, + state->rs[WINED3D_RS_MULTISAMPLEMASK]); + if (wine_rb_put(&device->blend_states, &desc, &blend_state->entry) == -1) + { + ERR("Failed to insert blend state.\n"); + wined3d_blend_state_decref(blend_state); + } + } + } + + if (set_depth_stencil_state) + { + struct wined3d_depth_stencil_state *depth_stencil_state; + struct wined3d_depth_stencil_state_desc desc; + struct wine_rb_entry *entry; + unsigned int stencil_ref; + + memset(&desc, 0, sizeof(desc)); + switch (state->rs[WINED3D_RS_ZENABLE]) + { + case WINED3D_ZB_FALSE: + desc.depth = FALSE; + break; + + case WINED3D_ZB_USEW: + FIXME("W buffer is not well handled.\n"); + case WINED3D_ZB_TRUE: + desc.depth = TRUE; + break; + + default: + FIXME("Unrecognized depth buffer type %#x.\n", state->rs[WINED3D_RS_ZENABLE]); + } + desc.depth_write = state->rs[WINED3D_RS_ZWRITEENABLE]; + desc.depth_func = state->rs[WINED3D_RS_ZFUNC]; + desc.stencil = state->rs[WINED3D_RS_STENCILENABLE]; + desc.stencil_read_mask = state->rs[WINED3D_RS_STENCILMASK]; + desc.stencil_write_mask = state->rs[WINED3D_RS_STENCILWRITEMASK]; + desc.front.fail_op = state->rs[WINED3D_RS_STENCILFAIL]; + desc.front.depth_fail_op = state->rs[WINED3D_RS_STENCILZFAIL]; + desc.front.pass_op = state->rs[WINED3D_RS_STENCILPASS]; + desc.front.func = state->rs[WINED3D_RS_STENCILFUNC]; + + if (state->rs[WINED3D_RS_TWOSIDEDSTENCILMODE]) + { + desc.back.fail_op = state->rs[WINED3D_RS_BACK_STENCILFAIL]; + desc.back.depth_fail_op = state->rs[WINED3D_RS_BACK_STENCILZFAIL]; + desc.back.pass_op = state->rs[WINED3D_RS_BACK_STENCILPASS]; + desc.back.func = state->rs[WINED3D_RS_BACK_STENCILFUNC]; + } + else + { + desc.back = desc.front; + } + + if (wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_STENCILREF)) + stencil_ref = state->rs[WINED3D_RS_STENCILREF]; + else + wined3d_device_context_get_depth_stencil_state(context, &stencil_ref); + + if ((entry = wine_rb_get(&device->depth_stencil_states, &desc))) + { + depth_stencil_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_depth_stencil_state, entry); + wined3d_device_context_set_depth_stencil_state(context, depth_stencil_state, stencil_ref); + } + else if (SUCCEEDED(wined3d_depth_stencil_state_create(device, &desc, NULL, + &wined3d_null_parent_ops, &depth_stencil_state))) + { + wined3d_device_context_set_depth_stencil_state(context, depth_stencil_state, stencil_ref); + if (wine_rb_put(&device->depth_stencil_states, &desc, &depth_stencil_state->entry) == -1) + { + ERR("Failed to insert depth/stencil state.\n"); + wined3d_depth_stencil_state_decref(depth_stencil_state); + } + } + } + + if (set_depth_bounds) + { + wined3d_device_context_set_depth_bounds(context, + state->rs[WINED3D_RS_ADAPTIVETESS_X] == WINED3DFMT_NVDB, + int_to_float(state->rs[WINED3D_RS_ADAPTIVETESS_Z]), + int_to_float(state->rs[WINED3D_RS_ADAPTIVETESS_W])); + } + + for (i = 0; i < ARRAY_SIZE(changed->textureState); ++i) + { + map = changed->textureState[i]; + while (map) + { + j = wined3d_bit_scan(&map); + wined3d_device_set_texture_stage_state(device, i, j, state->texture_states[i][j]); + } + } + + for (i = 0; i < ARRAY_SIZE(changed->samplerState); ++i) + { + map = changed->samplerState[i]; + while (map) + { + j = wined3d_bit_scan(&map); + wined3d_device_set_sampler_state(device, i, j, state->sampler_states[i][j]); + } + } + + if (changed->transforms) + { + for (i = 0; i < ARRAY_SIZE(changed->transform); ++i) + { + map = changed->transform[i]; + while (map) + { + j = wined3d_bit_scan(&map); + idx = i * word_bit_count + j; + wined3d_device_set_transform(device, idx, &state->transforms[idx]); + } + } + } + + if (changed->indices) + wined3d_device_context_set_index_buffer(context, state->index_buffer, state->index_format, 0); + wined3d_device_set_base_vertex_index(device, state->base_vertex_index); + if (changed->vertexDecl) + wined3d_device_context_set_vertex_declaration(context, state->vertex_declaration); + if (changed->material) + wined3d_device_set_material(device, &state->material); + if (changed->viewport) + wined3d_device_context_set_viewports(context, 1, &state->viewport); + if (changed->scissorRect) + wined3d_device_context_set_scissor_rects(context, 1, &state->scissor_rect); + + map = changed->streamSource | changed->streamFreq; + while (map) + { + i = wined3d_bit_scan(&map); + wined3d_device_context_set_stream_sources(context, i, 1, &state->streams[i]); + } + + map = changed->textures; + while (map) + { + i = wined3d_bit_scan(&map); + wined3d_device_set_texture(device, i, state->textures[i]); + } + + map = changed->clipplane; + while (map) + { + i = wined3d_bit_scan(&map); + wined3d_device_set_clip_plane(device, i, &state->clip_planes[i]); + } + + assert(list_empty(&stateblock->changed.changed_lights)); + memset(&stateblock->changed, 0, sizeof(stateblock->changed)); + list_init(&stateblock->changed.changed_lights); + + TRACE("Applied stateblock %p.\n", stateblock); +}
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/device.c | 164 +----------------------------------------- 1 file changed, 1 insertion(+), 163 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 8bb879b41cd..711bc4e7bc5 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1545,111 +1545,6 @@ static void wined3d_device_get_transform(const struct wined3d_device *device, *matrix = device->cs->c.state->transforms[state]; }
-/* Note lights are real special cases. Although the device caps state only - * e.g. 8 are supported, you can reference any indexes you want as long as - * that number max are enabled at any one point in time. Therefore since the - * indices can be anything, we need a hashmap of them. However, this causes - * stateblock problems. When capturing the state block, I duplicate the - * hashmap, but when recording, just build a chain pretty much of commands to - * be replayed. */ -static void wined3d_device_context_set_light(struct wined3d_device_context *context, - unsigned int light_idx, const struct wined3d_light *light) -{ - struct wined3d_light_info *object = NULL; - float rho; - - if (FAILED(wined3d_light_state_set_light(&context->state->light_state, light_idx, light, &object))) - return; - - /* Initialize the object. */ - TRACE("Light %u setting to type %#x, diffuse %s, specular %s, ambient %s, " - "position {%.8e, %.8e, %.8e}, direction {%.8e, %.8e, %.8e}, " - "range %.8e, falloff %.8e, theta %.8e, phi %.8e.\n", - light_idx, light->type, debug_color(&light->diffuse), - debug_color(&light->specular), debug_color(&light->ambient), - light->position.x, light->position.y, light->position.z, - light->direction.x, light->direction.y, light->direction.z, - light->range, light->falloff, light->theta, light->phi); - - switch (light->type) - { - case WINED3D_LIGHT_POINT: - /* Position */ - object->position.x = light->position.x; - object->position.y = light->position.y; - object->position.z = light->position.z; - object->position.w = 1.0f; - object->cutoff = 180.0f; - /* FIXME: Range */ - break; - - case WINED3D_LIGHT_DIRECTIONAL: - /* Direction */ - object->direction.x = -light->direction.x; - object->direction.y = -light->direction.y; - object->direction.z = -light->direction.z; - object->direction.w = 0.0f; - object->exponent = 0.0f; - object->cutoff = 180.0f; - break; - - case WINED3D_LIGHT_SPOT: - /* Position */ - object->position.x = light->position.x; - object->position.y = light->position.y; - object->position.z = light->position.z; - object->position.w = 1.0f; - - /* Direction */ - object->direction.x = light->direction.x; - object->direction.y = light->direction.y; - object->direction.z = light->direction.z; - object->direction.w = 0.0f; - - /* opengl-ish and d3d-ish spot lights use too different models - * for the light "intensity" as a function of the angle towards - * the main light direction, so we only can approximate very - * roughly. However, spot lights are rather rarely used in games - * (if ever used at all). Furthermore if still used, probably - * nobody pays attention to such details. */ - if (!light->falloff) - { - /* Falloff = 0 is easy, because d3d's and opengl's spot light - * equations have the falloff resp. exponent parameter as an - * exponent, so the spot light lighting will always be 1.0 for - * both of them, and we don't have to care for the rest of the - * rather complex calculation. */ - object->exponent = 0.0f; - } - else - { - rho = light->theta + (light->phi - light->theta) / (2 * light->falloff); - if (rho < 0.0001f) - rho = 0.0001f; - object->exponent = -0.3f / logf(cosf(rho / 2)); - } - - if (object->exponent > 128.0f) - object->exponent = 128.0f; - - object->cutoff = (float)(light->phi * 90 / M_PI); - /* FIXME: Range */ - break; - - case WINED3D_LIGHT_PARALLELPOINT: - object->position.x = light->position.x; - object->position.y = light->position.y; - object->position.z = light->position.z; - object->position.w = 1.0f; - break; - - default: - FIXME("Unrecognized light type %#x.\n", light->type); - } - - wined3d_device_context_emit_set_light(context, object); -} - HRESULT CDECL wined3d_device_set_clip_status(struct wined3d_device *device, const struct wined3d_clip_status *clip_status) { @@ -1758,8 +1653,7 @@ void CDECL wined3d_device_context_reset_state(struct wined3d_device_context *con
void CDECL wined3d_device_context_set_state(struct wined3d_device_context *context, struct wined3d_state *state) { - struct wined3d_light_info *light; - unsigned int i, j; + unsigned int i;
TRACE("context %p, state %p.\n", context, state);
@@ -1795,65 +1689,9 @@ void CDECL wined3d_device_context_set_state(struct wined3d_device_context *conte wined3d_device_context_emit_set_unordered_access_views(context, i, 0, MAX_UNORDERED_ACCESS_VIEWS, state->unordered_access_view[i], NULL);
- wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_VS_F, - 0, WINED3D_MAX_VS_CONSTS_F, state->vs_consts_f); - wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_VS_I, - 0, WINED3D_MAX_CONSTS_I, state->vs_consts_i); - wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_VS_B, - 0, WINED3D_MAX_CONSTS_B, state->vs_consts_b); - - wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_PS_F, - 0, WINED3D_MAX_PS_CONSTS_F, state->ps_consts_f); - wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_PS_I, - 0, WINED3D_MAX_CONSTS_I, state->ps_consts_i); - wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_PS_B, - 0, WINED3D_MAX_CONSTS_B, state->ps_consts_b); - - for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) - { - wined3d_device_context_emit_set_texture(context, i, state->textures[i]); - for (j = 0; j < WINED3D_HIGHEST_SAMPLER_STATE + 1; ++j) - { - wined3d_device_context_emit_set_sampler_state(context, i, j, state->sampler_states[i][j]); - } - } - - for (i = 0; i < WINED3D_MAX_TEXTURES; ++i) - { - for (j = 0; j < WINED3D_HIGHEST_TEXTURE_STATE + 1; ++j) - { - wined3d_device_context_emit_set_texture_state(context, i, j, state->texture_states[i][j]); - } - } - - for (i = 0; i < WINED3D_HIGHEST_TRANSFORM_STATE + 1; ++i) - { - if (context->device->state_table[STATE_TRANSFORM(i)].representative) - wined3d_device_context_emit_set_transform(context, i, state->transforms + i); - } - - for (i = 0; i < WINED3D_MAX_CLIP_DISTANCES; ++i) - { - wined3d_device_context_emit_set_clip_plane(context, i, state->clip_planes + i); - } - - wined3d_device_context_emit_set_material(context, &state->material); - wined3d_device_context_emit_set_viewports(context, state->viewport_count, state->viewports); wined3d_device_context_emit_set_scissor_rects(context, state->scissor_rect_count, state->scissor_rects);
- RB_FOR_EACH_ENTRY(light, &state->light_state.lights_tree, struct wined3d_light_info, entry) - { - wined3d_device_context_set_light(context, light->OriginalIndex, &light->OriginalParms); - wined3d_device_context_emit_set_light_enable(context, light->OriginalIndex, light->glIndex != -1); - } - - for (i = 0; i < WINEHIGHEST_RENDER_STATE + 1; ++i) - { - if (context->device->state_table[STATE_RENDER(i)].representative) - wined3d_device_context_emit_set_render_state(context, i, state->render_states[i]); - } - wined3d_device_context_emit_set_blend_state(context, state->blend_state, &state->blend_factor, state->sample_mask); wined3d_device_context_emit_set_depth_stencil_state(context, state->depth_stencil_state, state->stencil_ref); wined3d_device_context_emit_set_rasterizer_state(context, state->rasterizer_state);
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/d3d8/device.c | 26 ++++-------- dlls/d3d9/device.c | 71 ++++++++------------------------ dlls/wined3d/stateblock.c | 86 +++++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 6 +++ include/wine/wined3d.h | 12 ++++++ 5 files changed, 129 insertions(+), 72 deletions(-)
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 7a95654d343..e13a1ad465a 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -3051,26 +3051,15 @@ static HRESULT WINAPI d3d8_device_GetVertexShaderConstant(IDirect3DDevice8 *ifac DWORD start_idx, void *constants, DWORD count) { struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); - const struct wined3d_vec4 *src; + HRESULT hr;
TRACE("iface %p, start_idx %lu, constants %p, count %lu.\n", iface, start_idx, constants, count);
- if (!constants) - return D3DERR_INVALIDCALL; - - if (!wined3d_bound_range(start_idx, count, device->vs_uniform_count)) - { - WARN("Trying to access %lu constants, but d3d8 only supports %u.\n", - start_idx + count, device->vs_uniform_count); - return D3DERR_INVALIDCALL; - } - wined3d_mutex_lock(); - src = device->stateblock_state->vs_consts_f; - memcpy(constants, &src[start_idx], count * sizeof(*src)); + hr = wined3d_stateblock_get_vs_consts_f(device->state, start_idx, count, constants); wined3d_mutex_unlock();
- return D3D_OK; + return hr; }
static HRESULT WINAPI d3d8_device_GetVertexShaderDeclaration(IDirect3DDevice8 *iface, @@ -3353,19 +3342,18 @@ static HRESULT WINAPI d3d8_device_GetPixelShaderConstant(IDirect3DDevice8 *iface DWORD start_idx, void *constants, DWORD count) { struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); - const struct wined3d_vec4 *src; + HRESULT hr;
TRACE("iface %p, start_idx %lu, constants %p, count %lu.\n", iface, start_idx, constants, count);
- if (!constants || !wined3d_bound_range(start_idx, count, D3D8_MAX_PIXEL_SHADER_CONSTANTF)) + if (!wined3d_bound_range(start_idx, count, D3D8_MAX_PIXEL_SHADER_CONSTANTF)) return WINED3DERR_INVALIDCALL;
wined3d_mutex_lock(); - src = device->stateblock_state->ps_consts_f; - memcpy(constants, &src[start_idx], count * sizeof(*src)); + hr = wined3d_stateblock_get_ps_consts_f(device->state, start_idx, count, constants); wined3d_mutex_unlock();
- return D3D_OK; + return hr; }
static HRESULT WINAPI d3d8_device_GetPixelShaderFunction(IDirect3DDevice8 *iface, diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index b4bf51f9426..4351f005eb9 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -3678,26 +3678,15 @@ static HRESULT WINAPI d3d9_device_GetVertexShaderConstantF(IDirect3DDevice9Ex *i UINT start_idx, float *constants, UINT count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - const struct wined3d_vec4 *src; + HRESULT hr;
TRACE("iface %p, start_idx %u, constants %p, count %u.\n", iface, start_idx, constants, count);
- if (!constants) - return D3DERR_INVALIDCALL; - - if (!wined3d_bound_range(start_idx, count, device->vs_uniform_count)) - { - WARN("Trying to access %u constants, but d3d9 only supports %u\n", - start_idx + count, device->vs_uniform_count); - return D3DERR_INVALIDCALL; - } - wined3d_mutex_lock(); - src = device->stateblock_state->vs_consts_f; - memcpy(constants, &src[start_idx], count * sizeof(*src)); + hr = wined3d_stateblock_get_vs_consts_f(device->state, start_idx, count, (struct wined3d_vec4 *)constants); wined3d_mutex_unlock();
- return D3D_OK; + return hr; }
static HRESULT WINAPI d3d9_device_SetVertexShaderConstantI(IDirect3DDevice9Ex *iface, @@ -3720,21 +3709,15 @@ static HRESULT WINAPI d3d9_device_GetVertexShaderConstantI(IDirect3DDevice9Ex *i UINT start_idx, int *constants, UINT count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - const struct wined3d_ivec4 *src; + HRESULT hr;
TRACE("iface %p, start_idx %u, constants %p, count %u.\n", iface, start_idx, constants, count);
- if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) - return WINED3DERR_INVALIDCALL; - if (count > WINED3D_MAX_CONSTS_I - start_idx) - count = WINED3D_MAX_CONSTS_I - start_idx; - wined3d_mutex_lock(); - src = device->stateblock_state->vs_consts_i; - memcpy(constants, &src[start_idx], count * sizeof(*src)); + hr = wined3d_stateblock_get_vs_consts_i(device->state, start_idx, count, (struct wined3d_ivec4 *)constants); wined3d_mutex_unlock();
- return D3D_OK; + return hr; }
static HRESULT WINAPI d3d9_device_SetVertexShaderConstantB(IDirect3DDevice9Ex *iface, @@ -3756,19 +3739,15 @@ static HRESULT WINAPI d3d9_device_GetVertexShaderConstantB(IDirect3DDevice9Ex *i UINT start_idx, BOOL *constants, UINT count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); + HRESULT hr;
TRACE("iface %p, start_idx %u, constants %p, count %u.\n", iface, start_idx, constants, count);
- if (!constants || start_idx >= WINED3D_MAX_CONSTS_B) - return WINED3DERR_INVALIDCALL; - if (count > WINED3D_MAX_CONSTS_B - start_idx) - count = WINED3D_MAX_CONSTS_B - start_idx; - wined3d_mutex_lock(); - memcpy(constants, &device->stateblock_state->vs_consts_b[start_idx], count * sizeof(*constants)); + hr = wined3d_stateblock_get_vs_consts_b(device->state, start_idx, count, constants); wined3d_mutex_unlock();
- return D3D_OK; + return hr; }
static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface, @@ -4028,19 +4007,15 @@ static HRESULT WINAPI d3d9_device_GetPixelShaderConstantF(IDirect3DDevice9Ex *if UINT start_idx, float *constants, UINT count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - const struct wined3d_vec4 *src; + HRESULT hr;
TRACE("iface %p, start_idx %u, constants %p, count %u.\n", iface, start_idx, constants, count);
- if (!constants || !wined3d_bound_range(start_idx, count, WINED3D_MAX_PS_CONSTS_F)) - return WINED3DERR_INVALIDCALL; - wined3d_mutex_lock(); - src = device->stateblock_state->ps_consts_f; - memcpy(constants, &src[start_idx], count * sizeof(*src)); + hr = wined3d_stateblock_get_ps_consts_f(device->state, start_idx, count, (struct wined3d_vec4 *)constants); wined3d_mutex_unlock();
- return D3D_OK; + return hr; }
static HRESULT WINAPI d3d9_device_SetPixelShaderConstantI(IDirect3DDevice9Ex *iface, @@ -4063,21 +4038,15 @@ static HRESULT WINAPI d3d9_device_GetPixelShaderConstantI(IDirect3DDevice9Ex *if UINT start_idx, int *constants, UINT count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); - const struct wined3d_ivec4 *src; + HRESULT hr;
TRACE("iface %p, start_idx %u, constants %p, count %u.\n", iface, start_idx, constants, count);
- if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) - return WINED3DERR_INVALIDCALL; - if (count > WINED3D_MAX_CONSTS_I - start_idx) - count = WINED3D_MAX_CONSTS_I - start_idx; - wined3d_mutex_lock(); - src = device->stateblock_state->ps_consts_i; - memcpy(constants, &src[start_idx], count * sizeof(*src)); + hr = wined3d_stateblock_get_ps_consts_i(device->state, start_idx, count, (struct wined3d_ivec4 *)constants); wined3d_mutex_unlock();
- return D3D_OK; + return hr; }
static HRESULT WINAPI d3d9_device_SetPixelShaderConstantB(IDirect3DDevice9Ex *iface, @@ -4099,19 +4068,15 @@ static HRESULT WINAPI d3d9_device_GetPixelShaderConstantB(IDirect3DDevice9Ex *if UINT start_idx, BOOL *constants, UINT count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); + HRESULT hr;
TRACE("iface %p, start_idx %u, constants %p, count %u.\n", iface, start_idx, constants, count);
- if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) - return WINED3DERR_INVALIDCALL; - if (count > WINED3D_MAX_CONSTS_I - start_idx) - count = WINED3D_MAX_CONSTS_I - start_idx; - wined3d_mutex_lock(); - memcpy(constants, &device->stateblock_state->ps_consts_b[start_idx], count * sizeof(*constants)); + hr = wined3d_stateblock_get_ps_consts_b(device->state, start_idx, count, constants); wined3d_mutex_unlock();
- return D3D_OK; + return hr; }
static HRESULT WINAPI d3d9_device_DrawRectPatch(IDirect3DDevice9Ex *iface, UINT handle, diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index b118daeba19..da5c79c7813 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -1245,6 +1245,50 @@ HRESULT CDECL wined3d_stateblock_set_vs_consts_b(struct wined3d_stateblock *stat return WINED3D_OK; }
+HRESULT CDECL wined3d_stateblock_get_vs_consts_f(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants) +{ + const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info; + + TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants); + + if (!constants || !wined3d_bound_range(start_idx, count, d3d_info->limits.vs_uniform_count)) + return WINED3DERR_INVALIDCALL; + + memcpy(constants, &stateblock->stateblock_state.vs_consts_f[start_idx], count * sizeof(*constants)); + return WINED3D_OK; +} + +HRESULT CDECL wined3d_stateblock_get_vs_consts_i(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants) +{ + TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants); + + if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) + return WINED3DERR_INVALIDCALL; + + if (count > WINED3D_MAX_CONSTS_I - start_idx) + count = WINED3D_MAX_CONSTS_I - start_idx; + + memcpy(constants, &stateblock->stateblock_state.vs_consts_i[start_idx], count * sizeof(*constants)); + return WINED3D_OK; +} + +HRESULT CDECL wined3d_stateblock_get_vs_consts_b(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, BOOL *constants) +{ + TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants); + + if (!constants || start_idx >= WINED3D_MAX_CONSTS_B) + return WINED3DERR_INVALIDCALL; + + if (count > WINED3D_MAX_CONSTS_B - start_idx) + count = WINED3D_MAX_CONSTS_B - start_idx; + + memcpy(constants, &stateblock->stateblock_state.vs_consts_b[start_idx], count * sizeof(*constants)); + return WINED3D_OK; +} + void CDECL wined3d_stateblock_set_pixel_shader(struct wined3d_stateblock *stateblock, struct wined3d_shader *shader) { TRACE("stateblock %p, shader %p.\n", stateblock, shader); @@ -1313,6 +1357,48 @@ HRESULT CDECL wined3d_stateblock_set_ps_consts_b(struct wined3d_stateblock *stat return WINED3D_OK; }
+HRESULT CDECL wined3d_stateblock_get_ps_consts_f(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants) +{ + TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants); + + if (!constants || !wined3d_bound_range(start_idx, count, WINED3D_MAX_PS_CONSTS_F)) + return WINED3DERR_INVALIDCALL; + + memcpy(constants, &stateblock->stateblock_state.ps_consts_f[start_idx], count * sizeof(*constants)); + return WINED3D_OK; +} + +HRESULT CDECL wined3d_stateblock_get_ps_consts_i(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants) +{ + TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants); + + if (!constants || start_idx >= WINED3D_MAX_CONSTS_I) + return WINED3DERR_INVALIDCALL; + + if (count > WINED3D_MAX_CONSTS_I - start_idx) + count = WINED3D_MAX_CONSTS_I - start_idx; + + memcpy(constants, &stateblock->stateblock_state.ps_consts_i[start_idx], count * sizeof(*constants)); + return WINED3D_OK; +} + +HRESULT CDECL wined3d_stateblock_get_ps_consts_b(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, BOOL *constants) +{ + TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants); + + if (!constants || start_idx >= WINED3D_MAX_CONSTS_B) + return WINED3DERR_INVALIDCALL; + + if (count > WINED3D_MAX_CONSTS_B - start_idx) + count = WINED3D_MAX_CONSTS_B - start_idx; + + memcpy(constants, &stateblock->stateblock_state.ps_consts_b[start_idx], count * sizeof(*constants)); + return WINED3D_OK; +} + void CDECL wined3d_stateblock_set_vertex_declaration(struct wined3d_stateblock *stateblock, struct wined3d_vertex_declaration *declaration) { diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 8f75dffc142..39a0dd3a299 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -231,7 +231,13 @@ @ cdecl wined3d_stateblock_create(ptr ptr long ptr) @ cdecl wined3d_stateblock_decref(ptr) @ cdecl wined3d_stateblock_get_light(ptr long ptr ptr) +@ cdecl wined3d_stateblock_get_ps_consts_b(ptr long long ptr) +@ cdecl wined3d_stateblock_get_ps_consts_f(ptr long long ptr) +@ cdecl wined3d_stateblock_get_ps_consts_i(ptr long long ptr) @ cdecl wined3d_stateblock_get_state(ptr) +@ cdecl wined3d_stateblock_get_vs_consts_b(ptr long long ptr) +@ cdecl wined3d_stateblock_get_vs_consts_f(ptr long long ptr) +@ cdecl wined3d_stateblock_get_vs_consts_i(ptr long long ptr) @ cdecl wined3d_stateblock_incref(ptr) @ cdecl wined3d_stateblock_init_contained_states(ptr) @ cdecl wined3d_stateblock_multiply_transform(ptr long ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index c9790efccbb..2317dc17078 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2753,7 +2753,19 @@ HRESULT __cdecl wined3d_stateblock_create(struct wined3d_device *device, const s ULONG __cdecl wined3d_stateblock_decref(struct wined3d_stateblock *stateblock); HRESULT __cdecl wined3d_stateblock_get_light(const struct wined3d_stateblock *stateblock, UINT light_idx, struct wined3d_light *light, BOOL *enabled); +HRESULT __cdecl wined3d_stateblock_get_ps_consts_b(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, BOOL *constants); +HRESULT __cdecl wined3d_stateblock_get_ps_consts_f(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants); +HRESULT __cdecl wined3d_stateblock_get_ps_consts_i(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants); const struct wined3d_stateblock_state * __cdecl wined3d_stateblock_get_state(const struct wined3d_stateblock *stateblock); +HRESULT __cdecl wined3d_stateblock_get_vs_consts_b(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, BOOL *constants); +HRESULT __cdecl wined3d_stateblock_get_vs_consts_f(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants); +HRESULT __cdecl wined3d_stateblock_get_vs_consts_i(struct wined3d_stateblock *stateblock, + unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants); ULONG __cdecl wined3d_stateblock_incref(struct wined3d_stateblock *stateblock); void __cdecl wined3d_stateblock_init_contained_states(struct wined3d_stateblock *stateblock); void __cdecl wined3d_stateblock_multiply_transform(struct wined3d_stateblock *stateblock,
From: Zebediah Figura zfigura@codeweavers.com
We will need them in buffers for Vulkan, as well as for software vertex shaders. Currently we simply store them in sysmem buffers and read directly back out of them to load GL uniforms.
This does decrease memory usage a bit for d3d10+. --- dlls/wined3d/arb_program_shader.c | 69 +++++++++++++------- dlls/wined3d/buffer.c | 2 +- dlls/wined3d/context_gl.c | 2 +- dlls/wined3d/cs.c | 105 ++++++++++++++++-------------- dlls/wined3d/glsl_shader.c | 69 +++++++++++++------- dlls/wined3d/stateblock.c | 6 -- dlls/wined3d/wined3d_private.h | 44 +++++-------- 7 files changed, 166 insertions(+), 131 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 592216051c2..d8a0805bad5 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -520,11 +520,15 @@ static void shader_arb_load_np2fixup_constants(const struct arb_ps_np2fixup_info
/* Context activation is done by the caller. */ static void shader_arb_ps_local_constants(const struct arb_ps_compiled_shader *gl_shader, - const struct wined3d_context_gl *context_gl, const struct wined3d_state *state, unsigned int rt_height) + struct wined3d_context_gl *context_gl, const struct wined3d_state *state, unsigned int rt_height) { const struct wined3d_gl_info *gl_info = context_gl->gl_info; + struct wined3d_device *device = context_gl->c.device; + const struct wined3d_ivec4 *int_consts; unsigned char i;
+ int_consts = wined3d_buffer_load_sysmem(device->push_constants[WINED3D_PUSH_CONSTANTS_PS_I], &context_gl->c); + for(i = 0; i < gl_shader->numbumpenvmatconsts; i++) { int texunit = gl_shader->bumpenvmatconst[i].texunit; @@ -571,9 +575,9 @@ static void shader_arb_ps_local_constants(const struct arb_ps_compiled_shader *g if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED) { float val[4]; - val[0] = (float)state->ps_consts_i[i].x; - val[1] = (float)state->ps_consts_i[i].y; - val[2] = (float)state->ps_consts_i[i].z; + val[0] = (float)int_consts[i].x; + val[1] = (float)int_consts[i].y; + val[2] = (float)int_consts[i].z; val[3] = -1.0f;
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->int_consts[i], val)); @@ -584,9 +588,11 @@ static void shader_arb_ps_local_constants(const struct arb_ps_compiled_shader *g
/* Context activation is done by the caller. */ static void shader_arb_vs_local_constants(const struct arb_vs_compiled_shader *gl_shader, - const struct wined3d_context_gl *context_gl, const struct wined3d_state *state) + struct wined3d_context_gl *context_gl, const struct wined3d_state *state) { const struct wined3d_gl_info *gl_info = context_gl->gl_info; + struct wined3d_device *device = context_gl->c.device; + const struct wined3d_ivec4 *int_consts; float position_fixup[4]; unsigned char i;
@@ -596,14 +602,16 @@ static void shader_arb_vs_local_constants(const struct arb_vs_compiled_shader *g
if (!gl_shader->num_int_consts) return;
+ int_consts = wined3d_buffer_load_sysmem(device->push_constants[WINED3D_PUSH_CONSTANTS_VS_I], &context_gl->c); + for (i = 0; i < WINED3D_MAX_CONSTS_I; ++i) { if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED) { float val[4]; - val[0] = (float)state->vs_consts_i[i].x; - val[1] = (float)state->vs_consts_i[i].y; - val[2] = (float)state->vs_consts_i[i].z; + val[0] = (float)int_consts[i].x; + val[1] = (float)int_consts[i].y; + val[2] = (float)int_consts[i].z; val[3] = -1.0f;
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->int_consts[i], val)); @@ -627,6 +635,7 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv, str { const struct wined3d_d3d_info *d3d_info = context_gl->c.d3d_info; const struct wined3d_gl_info *gl_info = context_gl->gl_info; + struct wined3d_device *device = context_gl->c.device;
if (!from_shader_select) { @@ -670,8 +679,10 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv, str const struct arb_vs_compiled_shader *gl_shader = priv->compiled_vprog;
/* Load DirectX 9 float constants for vertex shader */ - priv->highest_dirty_vs_const = shader_arb_load_constants_f(vshader, gl_info, GL_VERTEX_PROGRAM_ARB, - priv->highest_dirty_vs_const, state->vs_consts_f, priv->vshader_const_dirty); + priv->highest_dirty_vs_const = shader_arb_load_constants_f(vshader, + gl_info, GL_VERTEX_PROGRAM_ARB, priv->highest_dirty_vs_const, + wined3d_buffer_load_sysmem(device->push_constants[WINED3D_PUSH_CONSTANTS_VS_F], &context_gl->c), + priv->vshader_const_dirty); shader_arb_vs_local_constants(gl_shader, context_gl, state); }
@@ -682,8 +693,10 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv, str UINT rt_height = state->fb.render_targets[0]->height;
/* Load DirectX 9 float constants for pixel shader */ - priv->highest_dirty_ps_const = shader_arb_load_constants_f(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, - priv->highest_dirty_ps_const, state->ps_consts_f, priv->pshader_const_dirty); + priv->highest_dirty_ps_const = shader_arb_load_constants_f(pshader, + gl_info, GL_FRAGMENT_PROGRAM_ARB, priv->highest_dirty_ps_const, + wined3d_buffer_load_sysmem(device->push_constants[WINED3D_PUSH_CONSTANTS_PS_F], &context_gl->c), + priv->pshader_const_dirty); shader_arb_ps_local_constants(gl_shader, context_gl, state, rt_height);
if (context_gl->c.constant_update_mask & WINED3D_SHADER_CONST_PS_NP2_FIXUP) @@ -4406,14 +4419,20 @@ static struct arb_vs_compiled_shader *find_arb_vshader(struct wined3d_shader *sh }
static void find_arb_ps_compile_args(const struct wined3d_state *state, - const struct wined3d_context_gl *context_gl, const struct wined3d_shader *shader, + struct wined3d_context_gl *context_gl, const struct wined3d_shader *shader, struct arb_ps_compile_args *args) { const struct wined3d_d3d_info *d3d_info = context_gl->c.d3d_info; const struct wined3d_gl_info *gl_info = context_gl->gl_info; + struct wined3d_device *device = context_gl->c.device; + const struct wined3d_ivec4 *int_consts; + const BOOL *bool_consts; int i; WORD int_skip;
+ bool_consts = wined3d_buffer_load_sysmem(device->push_constants[WINED3D_PUSH_CONSTANTS_PS_B], &context_gl->c); + int_consts = wined3d_buffer_load_sysmem(device->push_constants[WINED3D_PUSH_CONSTANTS_PS_I], &context_gl->c); + find_ps_compile_args(state, shader, context_gl->c.stream_info.position_transformed, &args->super, &context_gl->c);
/* This forces all local boolean constants to 1 to make them stateblock independent */ @@ -4421,7 +4440,7 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
for (i = 0; i < WINED3D_MAX_CONSTS_B; ++i) { - if (state->ps_consts_b[i]) + if (bool_consts[i]) args->bools |= ( 1u << i); }
@@ -4454,24 +4473,29 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state, } else { - args->loop_ctrl[i][0] = state->ps_consts_i[i].x; - args->loop_ctrl[i][1] = state->ps_consts_i[i].y; - args->loop_ctrl[i][2] = state->ps_consts_i[i].z; + args->loop_ctrl[i][0] = int_consts[i].x; + args->loop_ctrl[i][1] = int_consts[i].y; + args->loop_ctrl[i][2] = int_consts[i].z; } } }
static void find_arb_vs_compile_args(const struct wined3d_state *state, - const struct wined3d_context_gl *context_gl, const struct wined3d_shader *shader, + struct wined3d_context_gl *context_gl, const struct wined3d_shader *shader, struct arb_vs_compile_args *args) { const struct wined3d_d3d_info *d3d_info = context_gl->c.d3d_info; const struct wined3d_gl_info *gl_info = context_gl->gl_info; const struct wined3d_device *device = shader->device; const struct wined3d_adapter *adapter = device->adapter; + const struct wined3d_ivec4 *int_consts; + const BOOL *bool_consts; int i; WORD int_skip;
+ bool_consts = wined3d_buffer_load_sysmem(device->push_constants[WINED3D_PUSH_CONSTANTS_VS_B], &context_gl->c); + int_consts = wined3d_buffer_load_sysmem(device->push_constants[WINED3D_PUSH_CONSTANTS_VS_I], &context_gl->c); + find_vs_compile_args(state, shader, &args->super, &context_gl->c);
args->clip.boolclip_compare = 0; @@ -4500,10 +4524,9 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
/* This forces all local boolean constants to 1 to make them stateblock independent */ args->clip.boolclip.bools = shader->reg_maps.local_bool_consts; - /* TODO: Figure out if it would be better to store bool constants as bitmasks in the stateblock */ for (i = 0; i < WINED3D_MAX_CONSTS_B; ++i) { - if (state->vs_consts_b[i]) + if (bool_consts[i]) args->clip.boolclip.bools |= (1u << i); }
@@ -4531,9 +4554,9 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state, } else { - args->loop_ctrl[i][0] = state->vs_consts_i[i].x; - args->loop_ctrl[i][1] = state->vs_consts_i[i].y; - args->loop_ctrl[i][2] = state->vs_consts_i[i].z; + args->loop_ctrl[i][0] = int_consts[i].x; + args->loop_ctrl[i][1] = int_consts[i].y; + args->loop_ctrl[i][2] = int_consts[i].z; } } } diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index a3881438976..a6d3cd194f3 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -667,7 +667,7 @@ BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, }
/* Context activation is done by the caller. */ -BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) +void *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) { if (wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_SYSMEM)) buffer->resource.pin_sysmem = 1; diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index a8c5160a5b3..dd70c4efe99 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -4838,7 +4838,7 @@ static void draw_primitive_immediate_mode(struct wined3d_context_gl *context_gl, /* Immediate mode drawing can't make use of indices in a VBO - get the * data from the index buffer. */ if (idx_size) - idx_data = wined3d_buffer_load_sysmem(state->index_buffer, &context_gl->c) + state->index_offset; + idx_data = (uint8_t *)wined3d_buffer_load_sysmem(state->index_buffer, &context_gl->c) + state->index_offset;
ops = &d3d_info->ffp_attrib_ops;
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 04e37f5e712..029ca5d884d 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -416,7 +416,6 @@ struct wined3d_cs_push_constants enum wined3d_push_constants type; unsigned int start_idx; unsigned int count; - BYTE constants[1]; };
struct wined3d_cs_reset_state @@ -2107,76 +2106,95 @@ void wined3d_device_context_emit_set_feature_level(struct wined3d_device_context wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT); }
-static const struct +static const struct push_constant_info { - size_t offset; size_t size; + unsigned int max_count; DWORD mask; } wined3d_cs_push_constant_info[] = { - /* WINED3D_PUSH_CONSTANTS_VS_F */ - {FIELD_OFFSET(struct wined3d_state, vs_consts_f), sizeof(struct wined3d_vec4), WINED3D_SHADER_CONST_VS_F}, - /* WINED3D_PUSH_CONSTANTS_PS_F */ - {FIELD_OFFSET(struct wined3d_state, ps_consts_f), sizeof(struct wined3d_vec4), WINED3D_SHADER_CONST_PS_F}, - /* WINED3D_PUSH_CONSTANTS_VS_I */ - {FIELD_OFFSET(struct wined3d_state, vs_consts_i), sizeof(struct wined3d_ivec4), WINED3D_SHADER_CONST_VS_I}, - /* WINED3D_PUSH_CONSTANTS_PS_I */ - {FIELD_OFFSET(struct wined3d_state, ps_consts_i), sizeof(struct wined3d_ivec4), WINED3D_SHADER_CONST_PS_I}, - /* WINED3D_PUSH_CONSTANTS_VS_B */ - {FIELD_OFFSET(struct wined3d_state, vs_consts_b), sizeof(BOOL), WINED3D_SHADER_CONST_VS_B}, - /* WINED3D_PUSH_CONSTANTS_PS_B */ - {FIELD_OFFSET(struct wined3d_state, ps_consts_b), sizeof(BOOL), WINED3D_SHADER_CONST_PS_B}, + [WINED3D_PUSH_CONSTANTS_VS_F] = {sizeof(struct wined3d_vec4), WINED3D_MAX_VS_CONSTS_F, WINED3D_SHADER_CONST_VS_F}, + [WINED3D_PUSH_CONSTANTS_PS_F] = {sizeof(struct wined3d_vec4), WINED3D_MAX_PS_CONSTS_F, WINED3D_SHADER_CONST_PS_F}, + [WINED3D_PUSH_CONSTANTS_VS_I] = {sizeof(struct wined3d_ivec4), WINED3D_MAX_CONSTS_I, WINED3D_SHADER_CONST_VS_I}, + [WINED3D_PUSH_CONSTANTS_PS_I] = {sizeof(struct wined3d_ivec4), WINED3D_MAX_CONSTS_I, WINED3D_SHADER_CONST_PS_I}, + [WINED3D_PUSH_CONSTANTS_VS_B] = {sizeof(BOOL), WINED3D_MAX_CONSTS_B, WINED3D_SHADER_CONST_VS_B}, + [WINED3D_PUSH_CONSTANTS_PS_B] = {sizeof(BOOL), WINED3D_MAX_CONSTS_B, WINED3D_SHADER_CONST_PS_B}, };
-static void wined3d_cs_st_push_constants(struct wined3d_device_context *context, enum wined3d_push_constants p, - unsigned int start_idx, unsigned int count, const void *constants) +static bool prepare_push_constant_buffer(struct wined3d_device *device, enum wined3d_push_constants type) { - struct wined3d_cs *cs = wined3d_cs_from_context(context); - struct wined3d_device *device = cs->c.device; - unsigned int context_count; - unsigned int i; - size_t offset; + const struct push_constant_info *info = &wined3d_cs_push_constant_info[type]; + HRESULT hr;
- if (p == WINED3D_PUSH_CONSTANTS_VS_F) - device->shader_backend->shader_update_float_vertex_constants(device, start_idx, count); - else if (p == WINED3D_PUSH_CONSTANTS_PS_F) - device->shader_backend->shader_update_float_pixel_constants(device, start_idx, count); + const struct wined3d_buffer_desc desc = + { + .byte_width = info->max_count * info->size, + .bind_flags = 0, + .access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W, + };
- offset = wined3d_cs_push_constant_info[p].offset + start_idx * wined3d_cs_push_constant_info[p].size; - memcpy((BYTE *)&cs->state + offset, constants, count * wined3d_cs_push_constant_info[p].size); - for (i = 0, context_count = device->context_count; i < context_count; ++i) + if (!device->push_constants[type] && FAILED(hr = wined3d_buffer_create(device, + &desc, NULL, NULL, &wined3d_null_parent_ops, &device->push_constants[type]))) { - device->contexts[i]->constant_update_mask |= wined3d_cs_push_constant_info[p].mask; + ERR("Failed to create push constant buffer, hr %#lx.\n", hr); + return false; } + + return true; }
static void wined3d_cs_exec_push_constants(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_push_constants *op = data; + struct wined3d_device *device = cs->c.device; + unsigned int context_count, i; + + /* The constant buffers were already updated; this op is just to mark the + * constants as invalid in the device state. */
- wined3d_cs_st_push_constants(&cs->c, op->type, op->start_idx, op->count, op->constants); + if (op->type == WINED3D_PUSH_CONSTANTS_VS_F) + device->shader_backend->shader_update_float_vertex_constants(device, op->start_idx, op->count); + else if (op->type == WINED3D_PUSH_CONSTANTS_PS_F) + device->shader_backend->shader_update_float_pixel_constants(device, op->start_idx, op->count); + + for (i = 0, context_count = device->context_count; i < context_count; ++i) + device->contexts[i]->constant_update_mask |= wined3d_cs_push_constant_info[op->type].mask; }
-static void wined3d_cs_mt_push_constants(struct wined3d_device_context *context, enum wined3d_push_constants p, - unsigned int start_idx, unsigned int count, const void *constants) +static void wined3d_device_context_emit_push_constants(struct wined3d_device_context *context, + enum wined3d_push_constants type, unsigned int start_idx, unsigned int count) { struct wined3d_cs *cs = wined3d_cs_from_context(context); struct wined3d_cs_push_constants *op; - size_t size;
- size = count * wined3d_cs_push_constant_info[p].size; - op = wined3d_device_context_require_space(&cs->c, FIELD_OFFSET(struct wined3d_cs_push_constants, constants[size]), - WINED3D_CS_QUEUE_DEFAULT); + op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); op->opcode = WINED3D_CS_OP_PUSH_CONSTANTS; - op->type = p; + op->type = type; op->start_idx = start_idx; op->count = count; - memcpy(op->constants, constants, size);
wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_DEFAULT); }
+void wined3d_device_context_push_constants(struct wined3d_device_context *context, + enum wined3d_push_constants type, unsigned int start_idx, + unsigned int count, const void *constants) +{ + const struct push_constant_info *info = &wined3d_cs_push_constant_info[type]; + unsigned int byte_offset = start_idx * info->size; + unsigned int byte_size = count * info->size; + struct wined3d_box box; + + if (!prepare_push_constant_buffer(context->device, type)) + return; + + wined3d_box_set(&box, byte_offset, 0, byte_offset + byte_size, 1, 0, 1); + wined3d_device_context_emit_update_sub_resource(context, + &context->device->push_constants[type]->resource, 0, &box, constants, byte_size, byte_size); + wined3d_device_context_emit_push_constants(context, type, start_idx, count); +} + static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) { const struct wined3d_device *device = cs->c.device; @@ -3145,7 +3163,6 @@ static const struct wined3d_device_context_ops wined3d_cs_st_ops = wined3d_cs_st_require_space, wined3d_cs_st_submit, wined3d_cs_st_finish, - wined3d_cs_st_push_constants, wined3d_cs_map_upload_bo, wined3d_cs_unmap_upload_bo, wined3d_cs_issue_query, @@ -3272,7 +3289,6 @@ static const struct wined3d_device_context_ops wined3d_cs_mt_ops = wined3d_cs_mt_require_space, wined3d_cs_mt_submit, wined3d_cs_mt_finish, - wined3d_cs_mt_push_constants, wined3d_cs_map_upload_bo, wined3d_cs_unmap_upload_bo, wined3d_cs_issue_query, @@ -4099,12 +4115,6 @@ static void wined3d_deferred_context_finish(struct wined3d_device_context *conte ERR("Ignoring finish() on a deferred context.\n"); }
-static void wined3d_deferred_context_push_constants(struct wined3d_device_context *context, - enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants) -{ - FIXME("context %p, p %#x, start_idx %u, count %u, constants %p, stub!\n", context, p, start_idx, count, constants); -} - static struct wined3d_deferred_upload *deferred_context_get_upload(struct wined3d_deferred_context *deferred, struct wined3d_resource *resource, unsigned int sub_resource_idx) { @@ -4276,7 +4286,6 @@ static const struct wined3d_device_context_ops wined3d_deferred_context_ops = wined3d_deferred_context_require_space, wined3d_deferred_context_submit, wined3d_deferred_context_finish, - wined3d_deferred_context_push_constants, wined3d_deferred_context_map_upload_bo, wined3d_deferred_context_unmap_upload_bo, wined3d_deferred_context_issue_query, diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 7dc0de1b596..0d8527181ff 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -1178,18 +1178,24 @@ static void walk_constant_heap_clamped(const struct wined3d_gl_info *gl_info, }
/* Context activation is done by the caller. */ -static void shader_glsl_load_constants_f(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, - const struct wined3d_vec4 *constants, const GLint *constant_locations, const struct constant_heap *heap, +static void shader_glsl_load_constants_f(const struct wined3d_shader *shader, struct wined3d_context_gl *context_gl, + struct wined3d_buffer *constant_buffer, const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, unsigned int version) { + const struct wined3d_gl_info *gl_info = context_gl->gl_info; const struct wined3d_shader_lconst *lconst;
- /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */ - if (shader->reg_maps.shader_version.major == 1 - && shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_PIXEL) - walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version); - else - walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version); + if (constant_buffer) + { + const struct wined3d_vec4 *constants = wined3d_buffer_load_sysmem(constant_buffer, &context_gl->c); + + /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */ + if (shader->reg_maps.shader_version.major == 1 + && shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_PIXEL) + walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version); + else + walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version); + }
if (!shader->load_local_constsF) { @@ -1206,17 +1212,23 @@ static void shader_glsl_load_constants_f(const struct wined3d_shader *shader, co }
/* Context activation is done by the caller. */ -static void shader_glsl_load_constants_i(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, - const struct wined3d_ivec4 *constants, const GLint locations[WINED3D_MAX_CONSTS_I], uint32_t constants_set) +static void shader_glsl_load_constants_i(const struct wined3d_shader *shader, struct wined3d_context_gl *context_gl, + struct wined3d_buffer *constant_buffer, const GLint locations[WINED3D_MAX_CONSTS_I], uint32_t constants_set) { + const struct wined3d_gl_info *gl_info = context_gl->gl_info; unsigned int i; struct list* ptr;
- while (constants_set) + if (constant_buffer) { - /* We found this uniform name in the program - go ahead and send the data */ - i = wined3d_bit_scan(&constants_set); - GL_EXTCALL(glUniform4iv(locations[i], 1, &constants[i].x)); + const struct wined3d_ivec4 *constants = wined3d_buffer_load_sysmem(constant_buffer, &context_gl->c); + + while (constants_set) + { + /* We found this uniform name in the program - go ahead and send the data */ + i = wined3d_bit_scan(&constants_set); + GL_EXTCALL(glUniform4iv(locations[i], 1, &constants[i].x)); + } }
/* Load immediate constants */ @@ -1235,16 +1247,22 @@ static void shader_glsl_load_constants_i(const struct wined3d_shader *shader, co }
/* Context activation is done by the caller. */ -static void shader_glsl_load_constants_b(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, - const BOOL *constants, const GLint locations[WINED3D_MAX_CONSTS_B], uint32_t constants_set) +static void shader_glsl_load_constants_b(const struct wined3d_shader *shader, struct wined3d_context_gl *context_gl, + struct wined3d_buffer *constant_buffer, const GLint locations[WINED3D_MAX_CONSTS_B], uint32_t constants_set) { + const struct wined3d_gl_info *gl_info = context_gl->gl_info; unsigned int i; struct list* ptr;
- while (constants_set) + if (constant_buffer) { - i = wined3d_bit_scan(&constants_set); - GL_EXTCALL(glUniform1iv(locations[i], 1, &constants[i])); + const BOOL *constants = wined3d_buffer_load_sysmem(constant_buffer, &context_gl->c); + + while (constants_set) + { + i = wined3d_bit_scan(&constants_set); + GL_EXTCALL(glUniform1iv(locations[i], 1, &constants[i])); + } }
/* Load immediate constants */ @@ -1520,6 +1538,7 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context struct glsl_shader_prog_link *prog = ctx_data->glsl_program; const struct wined3d_gl_info *gl_info = context_gl->gl_info; float position_fixup[4 * WINED3D_MAX_VIEWPORTS]; + struct wined3d_device *device = context->device; struct shader_glsl_priv *priv = shader_priv; unsigned int constant_version; DWORD update_mask; @@ -1533,15 +1552,15 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context update_mask = context->constant_update_mask & prog->constant_update_mask;
if (update_mask & WINED3D_SHADER_CONST_VS_F) - shader_glsl_load_constants_f(vshader, gl_info, state->vs_consts_f, + shader_glsl_load_constants_f(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_F], prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version);
if (update_mask & WINED3D_SHADER_CONST_VS_I) - shader_glsl_load_constants_i(vshader, gl_info, state->vs_consts_i, + shader_glsl_load_constants_i(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_I], prog->vs.uniform_i_locations, vshader->reg_maps.integer_constants);
if (update_mask & WINED3D_SHADER_CONST_VS_B) - shader_glsl_load_constants_b(vshader, gl_info, state->vs_consts_b, + shader_glsl_load_constants_b(vshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_VS_B], prog->vs.uniform_b_locations, vshader->reg_maps.boolean_constants);
if (update_mask & WINED3D_SHADER_CONST_VS_CLIP_PLANES) @@ -1686,15 +1705,15 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context }
if (update_mask & WINED3D_SHADER_CONST_PS_F) - shader_glsl_load_constants_f(pshader, gl_info, state->ps_consts_f, + shader_glsl_load_constants_f(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_F], prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version);
if (update_mask & WINED3D_SHADER_CONST_PS_I) - shader_glsl_load_constants_i(pshader, gl_info, state->ps_consts_i, + shader_glsl_load_constants_i(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_I], prog->ps.uniform_i_locations, pshader->reg_maps.integer_constants);
if (update_mask & WINED3D_SHADER_CONST_PS_B) - shader_glsl_load_constants_b(pshader, gl_info, state->ps_consts_b, + shader_glsl_load_constants_b(pshader, context_gl, device->push_constants[WINED3D_PUSH_CONSTANTS_PS_B], prog->ps.uniform_b_locations, pshader->reg_maps.boolean_constants);
if (update_mask & WINED3D_SHADER_CONST_PS_BUMP_ENV) diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index da5c79c7813..2dfc53a8359 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -2180,7 +2180,6 @@ static void wined3d_device_set_vs_consts_b(struct wined3d_device *device,
TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
- memcpy(&device->cs->c.state->vs_consts_b[start_idx], constants, count * sizeof(*constants)); if (TRACE_ON(d3d)) { for (i = 0; i < count; ++i) @@ -2197,7 +2196,6 @@ static void wined3d_device_set_vs_consts_i(struct wined3d_device *device,
TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
- memcpy(&device->cs->c.state->vs_consts_i[start_idx], constants, count * sizeof(*constants)); if (TRACE_ON(d3d)) { for (i = 0; i < count; ++i) @@ -2214,7 +2212,6 @@ static void wined3d_device_set_vs_consts_f(struct wined3d_device *device,
TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
- memcpy(&device->cs->c.state->vs_consts_f[start_idx], constants, count * sizeof(*constants)); if (TRACE_ON(d3d)) { for (i = 0; i < count; ++i) @@ -2231,7 +2228,6 @@ static void wined3d_device_set_ps_consts_b(struct wined3d_device *device,
TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
- memcpy(&device->cs->c.state->ps_consts_b[start_idx], constants, count * sizeof(*constants)); if (TRACE_ON(d3d)) { for (i = 0; i < count; ++i) @@ -2248,7 +2244,6 @@ static void wined3d_device_set_ps_consts_i(struct wined3d_device *device,
TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
- memcpy(&device->cs->c.state->ps_consts_i[start_idx], constants, count * sizeof(*constants)); if (TRACE_ON(d3d)) { for (i = 0; i < count; ++i) @@ -2265,7 +2260,6 @@ static void wined3d_device_set_ps_consts_f(struct wined3d_device *device,
TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
- memcpy(&device->cs->c.state->ps_consts_f[start_idx], constants, count * sizeof(*constants)); if (TRACE_ON(d3d)) { for (i = 0; i < count; ++i) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6e2bdc8aaf1..25c179dc45d 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3365,6 +3365,17 @@ void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN;
BOOL wined3d_get_app_name(char *app_name, unsigned int app_name_size) DECLSPEC_HIDDEN;
+enum wined3d_push_constants +{ + WINED3D_PUSH_CONSTANTS_VS_F, + WINED3D_PUSH_CONSTANTS_PS_F, + WINED3D_PUSH_CONSTANTS_VS_I, + WINED3D_PUSH_CONSTANTS_PS_I, + WINED3D_PUSH_CONSTANTS_VS_B, + WINED3D_PUSH_CONSTANTS_PS_B, + WINED3D_PUSH_CONSTANTS_COUNT, +}; + struct wined3d_blend_state { LONG refcount; @@ -3448,14 +3459,6 @@ struct wined3d_state struct wined3d_shader_resource_view *shader_resource_view[WINED3D_SHADER_TYPE_COUNT][MAX_SHADER_RESOURCE_VIEWS]; struct wined3d_unordered_access_view *unordered_access_view[WINED3D_PIPELINE_COUNT][MAX_UNORDERED_ACCESS_VIEWS];
- struct wined3d_vec4 vs_consts_f[WINED3D_MAX_VS_CONSTS_F]; - struct wined3d_ivec4 vs_consts_i[WINED3D_MAX_CONSTS_I]; - BOOL vs_consts_b[WINED3D_MAX_CONSTS_B]; - - struct wined3d_vec4 ps_consts_f[WINED3D_MAX_PS_CONSTS_F]; - struct wined3d_ivec4 ps_consts_i[WINED3D_MAX_CONSTS_I]; - BOOL ps_consts_b[WINED3D_MAX_CONSTS_B]; - struct wined3d_texture *textures[WINED3D_MAX_COMBINED_SAMPLERS]; uint32_t sampler_states[WINED3D_MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1]; uint32_t texture_states[WINED3D_MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1]; @@ -3596,6 +3599,8 @@ struct wined3d_device /* Command stream */ struct wined3d_cs *cs;
+ struct wined3d_buffer *push_constants[WINED3D_PUSH_CONSTANTS_COUNT]; + /* Context management */ struct wined3d_context **contexts; UINT context_count; @@ -4427,16 +4432,6 @@ enum wined3d_cs_queue_id WINED3D_CS_QUEUE_COUNT, };
-enum wined3d_push_constants -{ - WINED3D_PUSH_CONSTANTS_VS_F, - WINED3D_PUSH_CONSTANTS_PS_F, - WINED3D_PUSH_CONSTANTS_VS_I, - WINED3D_PUSH_CONSTANTS_PS_I, - WINED3D_PUSH_CONSTANTS_VS_B, - WINED3D_PUSH_CONSTANTS_PS_B, -}; - #define WINED3D_CS_QUERY_POLL_INTERVAL 10u #if defined(_WIN64) #define WINED3D_CS_QUEUE_SIZE 0x1000000u @@ -4459,8 +4454,6 @@ struct wined3d_device_context_ops void *(*require_space)(struct wined3d_device_context *context, size_t size, enum wined3d_cs_queue_id queue_id); void (*submit)(struct wined3d_device_context *context, enum wined3d_cs_queue_id queue_id); void (*finish)(struct wined3d_device_context *context, enum wined3d_cs_queue_id queue_id); - void (*push_constants)(struct wined3d_device_context *context, enum wined3d_push_constants p, - unsigned int start_idx, unsigned int count, const void *constants); bool (*map_upload_bo)(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx, struct wined3d_map_desc *map_desc, const struct wined3d_box *box, uint32_t flags); @@ -4544,12 +4537,6 @@ static inline void wined3d_cs_finish(struct wined3d_cs *cs, enum wined3d_cs_queu cs->c.ops->finish(&cs->c, queue_id); }
-static inline void wined3d_device_context_push_constants(struct wined3d_device_context *context, - enum wined3d_push_constants p, unsigned int start_idx, unsigned int count, const void *constants) -{ - context->ops->push_constants(context, p, start_idx, count, constants); -} - void wined3d_device_context_emit_blt_sub_resource(struct wined3d_device_context *context, struct wined3d_resource *dst_resource, unsigned int dst_sub_resource_idx, const struct wined3d_box *dst_box, struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, @@ -4635,6 +4622,9 @@ void wined3d_device_context_emit_update_sub_resource(struct wined3d_device_conte const void *data, unsigned int row_pitch, unsigned int slice_pitch) DECLSPEC_HIDDEN; HRESULT wined3d_device_context_emit_unmap(struct wined3d_device_context *context, struct wined3d_resource *resource, unsigned int sub_resource_idx) DECLSPEC_HIDDEN; +void wined3d_device_context_push_constants(struct wined3d_device_context *context, + enum wined3d_push_constants type, unsigned int start_idx, + unsigned int count, const void *constants) DECLSPEC_HIDDEN;
static inline void wined3d_resource_reference(struct wined3d_resource *resource) { @@ -4743,7 +4733,7 @@ void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context * const struct wined3d_state *state) DECLSPEC_HIDDEN; BOOL wined3d_buffer_load_location(struct wined3d_buffer *buffer, struct wined3d_context *context, uint32_t location) DECLSPEC_HIDDEN; -BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) DECLSPEC_HIDDEN; +void *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) DECLSPEC_HIDDEN; BOOL wined3d_buffer_prepare_location(struct wined3d_buffer *buffer, struct wined3d_context *context, unsigned int location) DECLSPEC_HIDDEN; void wined3d_buffer_update_sub_resource(struct wined3d_buffer *buffer, struct wined3d_context *context,
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=135039
Your paranoid android.
=== debian11b (64 bit WoW report) ===
d2d1: Unhandled exception: page fault on read access to 0x0000000017819870 in 64-bit code (0x000000004c1b68).
Gah... I fixed that, but I accidentally pushed an old version of the patch. Should be fixed in v2.
This merge request was approved by Jan Sikorski.