diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index e179a06e..dcd183f8 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -452,6 +452,7 @@ patch_enable_all () enable_wined3d_DrawIndirect="$1" enable_wined3d_Dual_Source_Blending="$1" enable_wined3d_GTX_560M="$1" + enable_wined3d_Indexed_Vertex_Blending="$1" enable_wined3d_Limit_Vram="$1" enable_wined3d_QUERY_Stubs="$1" enable_wined3d_Revert_Buffer_Upload="$1" @@ -1632,6 +1633,9 @@ patch_enable () wined3d-GTX_560M) enable_wined3d_GTX_560M="$2" ;; + wined3d-Indexed_Vertex_Blending) + enable_wined3d_Indexed_Vertex_Blending="$2" + ;; wined3d-Limit_Vram) enable_wined3d_Limit_Vram="$2" ;; @@ -2228,6 +2232,17 @@ if test "$enable_wined3d_conservative_depth" -eq 1; then enable_wined3d_Copy_Resource_Typeless=1 fi +if test "$enable_wined3d_Indexed_Vertex_Blending" -eq 1; then + if test "$enable_wined3d_DrawIndirect" -gt 1; then + abort "Patchset wined3d-DrawIndirect disabled, but wined3d-Indexed_Vertex_Blending depends on that." + fi + if test "$enable_wined3d_WINED3D_RS_COLORWRITEENABLE" -gt 1; then + abort "Patchset wined3d-WINED3D_RS_COLORWRITEENABLE disabled, but wined3d-Indexed_Vertex_Blending depends on that." + fi + enable_wined3d_DrawIndirect=1 + enable_wined3d_WINED3D_RS_COLORWRITEENABLE=1 +fi + if test "$enable_wined3d_WINED3D_RS_COLORWRITEENABLE" -eq 1; then if test "$enable_d3d11_Depth_Bias" -gt 1; then abort "Patchset d3d11-Depth_Bias disabled, but wined3d-WINED3D_RS_COLORWRITEENABLE depends on that." @@ -9745,6 +9760,58 @@ if test "$enable_wined3d_GTX_560M" -eq 1; then ) >> "$patchlist" fi +# Patchset wined3d-WINED3D_RS_COLORWRITEENABLE +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * d3d11-Depth_Bias +# | +# | Modified files: +# | * dlls/d3d11/device.c, dlls/d3d11/state.c, dlls/wined3d/context.c, dlls/wined3d/device.c, dlls/wined3d/drawprim.c, +# | dlls/wined3d/state.c, dlls/wined3d/stateblock.c, dlls/wined3d/surface.c, dlls/wined3d/utils.c, +# | dlls/wined3d/wined3d_private.h, include/wine/wined3d.h +# | +if test "$enable_wined3d_WINED3D_RS_COLORWRITEENABLE" -eq 1; then + patch_apply wined3d-WINED3D_RS_COLORWRITEENABLE/0001-wined3d-Implement-all-8-d3d11-color-write-masks.patch + ( + printf '%s\n' '+ { "Michael Müller", "wined3d: Implement all 8 d3d11 color write masks.", 1 },'; + ) >> "$patchlist" +fi + +# Patchset wined3d-Indexed_Vertex_Blending +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * wined3d-draw_primitive_arrays, wined3d-DrawIndirect, d3d11-Depth_Bias, wined3d-WINED3D_RS_COLORWRITEENABLE +# | +# | This patchset fixes the following Wine bugs: +# | * [#39057] Support for indexed vertex blending +# | +# | Modified files: +# | * dlls/d3d9/tests/visual.c, dlls/wined3d/device.c, dlls/wined3d/directx.c, dlls/wined3d/drawprim.c, +# | dlls/wined3d/glsl_shader.c, dlls/wined3d/utils.c, dlls/wined3d/vertexdeclaration.c, dlls/wined3d/wined3d_private.h +# | +if test "$enable_wined3d_Indexed_Vertex_Blending" -eq 1; then + patch_apply wined3d-Indexed_Vertex_Blending/0001-d3d9-tests-Add-test-for-indexed-vertex-blending.patch + patch_apply wined3d-Indexed_Vertex_Blending/0002-wined3d-Implement-hardware-indexed-vertex-blending-w.patch + patch_apply wined3d-Indexed_Vertex_Blending/0003-d3d9-tests-Test-normal-calculation-when-indexed-vert.patch + patch_apply wined3d-Indexed_Vertex_Blending/0004-wined3d-Fix-calculation-of-normal-when-vertex-blendi.patch + patch_apply wined3d-Indexed_Vertex_Blending/0005-wined3d-Move-matrix-inversion-functions-into-utils.c.patch + patch_apply wined3d-Indexed_Vertex_Blending/0006-wined3d-Implement-software-processing-for-indexed-ve.patch + patch_apply wined3d-Indexed_Vertex_Blending/0007-d3d9-tests-Check-MaxVertexBlendMatrixIndex-capabilit.patch + patch_apply wined3d-Indexed_Vertex_Blending/0008-wined3d-Report-correct-number-of-blend-matrices-when.patch + patch_apply wined3d-Indexed_Vertex_Blending/0009-wined3d-Track-updates-of-vertex-blend-matrices-separ.patch + ( + printf '%s\n' '+ { "Paul Gofman", "d3d9/tests: Add test for indexed vertex blending.", 1 },'; + printf '%s\n' '+ { "Paul Gofman", "wined3d: Implement hardware indexed vertex blending with 9 matrices.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "d3d9/tests: Test normal calculation when indexed vertex blending is enabled.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "wined3d: Fix calculation of normal when vertex blending is enabled.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "wined3d: Move matrix inversion functions into utils.c.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "wined3d: Implement software processing for indexed vertex blending.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "d3d9/tests: Check MaxVertexBlendMatrixIndex capability.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "wined3d: Report correct number of blend matrices when software vertex processing is used.", 1 },'; + printf '%s\n' '+ { "Sebastian Lackner", "wined3d: Track updates of vertex blend matrices separately.", 1 },'; + ) >> "$patchlist" +fi + # Patchset wined3d-Limit_Vram # | # | Modified files: @@ -9781,23 +9848,6 @@ if test "$enable_wined3d_WINED3DFMT_R32G32_UINT" -eq 1; then ) >> "$patchlist" fi -# Patchset wined3d-WINED3D_RS_COLORWRITEENABLE -# | -# | This patchset has the following (direct or indirect) dependencies: -# | * d3d11-Depth_Bias -# | -# | Modified files: -# | * dlls/d3d11/device.c, dlls/d3d11/state.c, dlls/wined3d/context.c, dlls/wined3d/device.c, dlls/wined3d/drawprim.c, -# | dlls/wined3d/state.c, dlls/wined3d/stateblock.c, dlls/wined3d/surface.c, dlls/wined3d/utils.c, -# | dlls/wined3d/wined3d_private.h, include/wine/wined3d.h -# | -if test "$enable_wined3d_WINED3D_RS_COLORWRITEENABLE" -eq 1; then - patch_apply wined3d-WINED3D_RS_COLORWRITEENABLE/0001-wined3d-Implement-all-8-d3d11-color-write-masks.patch - ( - printf '%s\n' '+ { "Michael Müller", "wined3d: Implement all 8 d3d11 color write masks.", 1 },'; - ) >> "$patchlist" -fi - # Patchset wined3d-buffer_create # | # | Modified files: diff --git a/patches/wined3d-CSMT_Main/9999-IfDefined.patch b/patches/wined3d-CSMT_Main/9999-IfDefined.patch index ca81486c..61f30823 100644 --- a/patches/wined3d-CSMT_Main/9999-IfDefined.patch +++ b/patches/wined3d-CSMT_Main/9999-IfDefined.patch @@ -198,7 +198,7 @@ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c wined3d_device_delete_opengl_contexts(device); if (device->fb.depth_stencil) -@@ -4220,6 +4223,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev +@@ -4211,6 +4214,7 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev return WINED3DERR_INVALIDCALL; } @@ -206,7 +206,7 @@ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c if (dst_texture->sub_resources[dst_sub_resource_idx].map_count) { WARN("Destination sub-resource %u is mapped.\n", dst_sub_resource_idx); -@@ -4230,6 +4234,19 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev +@@ -4221,6 +4225,19 @@ HRESULT CDECL wined3d_device_copy_sub_resource_region(struct wined3d_device *dev { WARN("Source sub-resource %u is mapped.\n", src_sub_resource_idx); return WINED3DERR_INVALIDCALL; @@ -226,7 +226,7 @@ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c } if (!src_box) -@@ -4323,8 +4340,10 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str +@@ -4314,8 +4331,10 @@ void CDECL wined3d_device_update_sub_resource(struct wined3d_device *device, str return; } @@ -237,7 +237,7 @@ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c wined3d_cs_emit_update_sub_resource(device->cs, resource, sub_resource_idx, box, data, row_pitch, depth_pitch); } -@@ -5273,3 +5292,58 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL +@@ -5264,3 +5283,58 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL else return CallWindowProcA(proc, window, message, wparam, lparam); } @@ -619,7 +619,7 @@ diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -2846,6 +2846,16 @@ static inline BOOL wined3d_dualblend_enabled(const struct wined3d_state *state, +@@ -2849,6 +2849,16 @@ static inline BOOL wined3d_dualblend_enabled(const struct wined3d_state *state, return FALSE; } @@ -636,7 +636,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h #define WINED3D_UNMAPPED_STAGE ~0u /* Multithreaded flag. Removed from the public header to signal that -@@ -2957,6 +2967,12 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL +@@ -2960,6 +2970,12 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; @@ -649,7 +649,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) { -@@ -3144,7 +3160,11 @@ struct wined3d_texture +@@ -3147,7 +3163,11 @@ struct wined3d_texture unsigned int map_count; DWORD locations; @@ -661,7 +661,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h } sub_resources[1]; }; -@@ -3459,6 +3479,9 @@ struct wined3d_cs_queue +@@ -3462,6 +3482,9 @@ struct wined3d_cs_queue struct wined3d_cs_ops { diff --git a/patches/wined3d-Indexed_Vertex_Blending/0001-d3d9-tests-Add-test-for-indexed-vertex-blending.patch b/patches/wined3d-Indexed_Vertex_Blending/0001-d3d9-tests-Add-test-for-indexed-vertex-blending.patch new file mode 100644 index 00000000..59eded57 --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0001-d3d9-tests-Add-test-for-indexed-vertex-blending.patch @@ -0,0 +1,282 @@ +From f007c8f6a7fc3498d525c70a7f6e6540faf425c1 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 17 Aug 2017 17:46:50 +0300 +Subject: d3d9/tests: Add test for indexed vertex blending. + +--- + dlls/d3d9/tests/visual.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 252 insertions(+) + +diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +index 1de7e5d186b..9b845b5ad44 100644 +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -19715,6 +19715,257 @@ done: + DestroyWindow(window); + } + ++static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char *test_id_str) ++{ ++ D3DCAPS9 caps; ++ D3DCOLOR color; ++ HRESULT hr; ++ unsigned int i; ++ ++ static const D3DMATRIX view_mat = ++ {{{ ++ 2.0f / 10.0f, 0.0f, 0.0f, 0.0f, ++ 0.0f, 2.0f / 10.0f, 0.0f, 0.0f, ++ 0.0f, 0.0f, 1.0f, 0.0f, ++ 0.0f, 0.0f, 0.0f, 1.0f ++ }}}, ++ upper_left = ++ {{{ ++ 1.0f, 0.0f, 0.0f, 0.0f, ++ 0.0f, 1.0f, 0.0f, 0.0f, ++ 0.0f, 0.0f, 1.0f, 0.0f, ++ -4.0f, 4.0f, 0.0f, 1.0f ++ }}}, ++ lower_left = ++ {{{ ++ 1.0f, 0.0f, 0.0f, 0.0f, ++ 0.0f, 1.0f, 0.0f, 0.0f, ++ 0.0f, 0.0f, 1.0f, 0.0f, ++ -4.0f, -4.0f, 0.0f, 1.0f ++ }}}, ++ upper_right = ++ {{{ ++ 1.0f, 0.0f, 0.0f, 0.0f, ++ 0.0f, 1.0f, 0.0f, 0.0f, ++ 0.0f, 0.0f, 1.0f, 0.0f, ++ 4.0f, 4.0f, 0.0f, 1.0f ++ }}}, ++ lower_right = ++ {{{ ++ 1.0f, 0.0f, 0.0f, 0.0f, ++ 0.0f, 1.0f, 0.0f, 0.0f, ++ 0.0f, 0.0f, 1.0f, 0.0f, ++ 4.0f, -4.0f, 0.0f, 1.0f ++ }}}; ++ ++ static const POINT quad_upper_right_points[] = ++ { ++ {576, 48}, {-1, -1}, ++ }, ++ quad_upper_right_empty_points[] = ++ { ++ {64, 48}, {64, 432}, {576, 432}, {320, 240}, {-1, -1} ++ }, ++ quad_center_points[] = ++ { ++ {320, 240}, {-1, -1} ++ }, ++ quad_center_empty_points[] = ++ { ++ {64, 48}, {576, 48}, {64, 432}, {576, 432}, {-1, -1} ++ }, ++ quad_upper_center_points[] = ++ { ++ {320, 48}, {-1, -1} ++ }, ++ quad_upper_center_empty_points[] = ++ { ++ {320, 240}, {64, 48}, {576, 48}, {-1, -1} ++ }, ++ quad_fullscreen_points[] = ++ { ++ {320, 48}, {320, 240}, {64, 48}, {576, 48}, {64, 432}, {576, 432}, {-1, -1} ++ }, ++ quad_fullscreen_empty_points[] = ++ { ++ {-1, -1} ++ }; ++ ++ static const struct ++ { ++ struct ++ { ++ struct vec3 position; ++ struct vec3 blendweights; ++ DWORD matrixIndices; ++ } ++ vertex_data[4]; ++ const POINT *quad_points; ++ const POINT *empty_points; ++ } ++ tests[] = ++ { ++ /* upper right */ ++ { ++ {{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}, ++ {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}, ++ {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}, ++ {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}}, ++ quad_upper_right_points, quad_upper_right_empty_points ++ }, ++ /* center */ ++ { ++ {{{-1.0f, -1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405}, ++ {{-1.0f, 1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405}, ++ {{ 1.0f, -1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405}, ++ {{ 1.0f, 1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405}}, ++ quad_center_points, quad_center_empty_points ++ }, ++ /* upper center */ ++ { ++ {{{-1.0f, -1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405}, ++ {{-1.0f, 1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405}, ++ {{ 1.0f, -1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405}, ++ {{ 1.0f, 1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405}}, ++ quad_upper_center_points, quad_upper_center_empty_points ++ }, ++ /* full screen */ ++ { ++ {{{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, 0x06070405}, ++ {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0x06070405}, ++ {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, 0x06070405}, ++ {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}}, ++ quad_fullscreen_points, quad_fullscreen_empty_points ++ } ++ }; ++ ++ memset(&caps, 0, sizeof(caps)); ++ hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); ++ ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); ++ if (caps.MaxVertexBlendMatrixIndex < 7 || caps.MaxVertexBlendMatrices < 4) ++ { ++ todo_wine win_skip("(%s) Too few vertex blend matrices supported: MaxVertexBlendMatrices=%u, MaxVertexBlendMatrixIndex=%u.\n", ++ test_id_str, caps.MaxVertexBlendMatrices, caps.MaxVertexBlendMatrixIndex); ++ return; ++ } ++ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE); ++ ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x.\n", hr); ++ ++ hr = IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &view_mat); ++ ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x.\n", hr); ++ ++ hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(5), &upper_left); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetTransform returned %08x.\n", test_id_str, hr); ++ hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(4), &lower_left); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetTransform returned %08x.\n", test_id_str, hr); ++ hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(7), &lower_right); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetTransform returned %08x.\n", test_id_str, hr); ++ hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(6), &upper_right); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetTransform returned %08x.\n", test_id_str, hr); ++ ++ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_VERTEXBLEND, D3DVBF_3WEIGHTS); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetRenderState failed %08x.\n", test_id_str, hr); ++ hr = IDirect3DDevice9_SetRenderState(device, D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetRenderState D3DRS_INDEXEDVERTEXBLENDENABLE failed %08x.\n", ++ test_id_str, hr); ++ ++ for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) ++ { ++ const POINT *point; ++ ++ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0); ++ ok(SUCCEEDED(hr), "Failed to clear, hr %08x.\n", hr); ++ ++ hr = IDirect3DDevice9_BeginScene(device); ++ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); ++ ++ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4); ++ ok(SUCCEEDED(hr), "(%s) Failed to set FVF, hr %#x.\n", test_id_str, hr); ++ ++ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, tests[i].vertex_data, ++ 6 * sizeof(float) + sizeof(DWORD)); ++ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); ++ ++ hr = IDirect3DDevice9_EndScene(device); ++ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); ++ ++ point = tests[i].quad_points; ++ while (point->x != -1 && point->y != -1) ++ { ++ color = getPixelColor(device, point->x, point->y); ++ ok(color_match(color, 0x00ffffff, 1), "(%s) Expected quad at %dx%d.\n", test_id_str, point->x, point->y); ++ ++point; ++ } ++ ++ point = tests[i].empty_points; ++ while (point->x != -1 && point->y != -1) ++ { ++ color = getPixelColor(device, point->x, point->y); ++ ok(color_match(color, 0x00000000, 1), "(%s) Unexpected quad at %dx%d.\n", test_id_str, point->x, point->y); ++ ++point; ++ } ++ ++ hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ++ ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); ++ } ++} ++ ++static void test_indexed_vertex_blending(void) ++{ ++ D3DPRESENT_PARAMETERS present_parameters = {0}; ++ IDirect3DDevice9 *device; ++ IDirect3D9 *d3d; ++ ULONG refcount; ++ HWND window; ++ ++ window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, ++ 0, 0, 640, 480, NULL, NULL, NULL, NULL); ++ d3d = Direct3DCreate9(D3D_SDK_VERSION); ++ ok(!!d3d, "Failed to create a D3D object.\n"); ++ ++ present_parameters.Windowed = TRUE; ++ present_parameters.hDeviceWindow = window; ++ present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; ++ present_parameters.BackBufferWidth = 640; ++ present_parameters.BackBufferHeight = 480; ++ present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8; ++ present_parameters.EnableAutoDepthStencil = TRUE; ++ present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8; ++ ++ if (SUCCEEDED(IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, ++ D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) ++ { ++ do_test_indexed_vertex_blending(device,"IVB hardware"); ++ refcount = IDirect3DDevice9_Release(device); ++ ok(!refcount, "Device has %u references left.\n", refcount); ++ } ++ else ++ skip("Failed to create a HAL device, skipping test.\n"); ++ ++ if (SUCCEEDED(IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, ++ D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) ++ { ++ do_test_indexed_vertex_blending(device,"IVB software"); ++ refcount = IDirect3DDevice9_Release(device); ++ ok(!refcount, "Device has %u references left.\n", refcount); ++ } ++ else ++ skip("Failed to create a HAL device with software processing, skipping test.\n"); ++ ++ if (SUCCEEDED(IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, ++ D3DCREATE_MIXED_VERTEXPROCESSING, &present_parameters, &device))) ++ { ++ do_test_indexed_vertex_blending(device,"IVB mixed"); ++ refcount = IDirect3DDevice9_Release(device); ++ ok(!refcount, "Device has %u references left.\n", refcount); ++ } ++ else ++ skip("Failed to create a HAL device with mixed processing, skipping tests.\n"); ++ ++ IDirect3D9_Release(d3d); ++ DestroyWindow(window); ++} ++ + static void test_updatetexture(void) + { + BOOL r32f_supported, ati2n_supported, do_visual_test; +@@ -22971,6 +23222,7 @@ START_TEST(visual) + test_multisample_mismatch(); + test_texcoordindex(); + test_vertex_blending(); ++ test_indexed_vertex_blending(); + test_updatetexture(); + test_depthbias(); + test_flip(); +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/0002-wined3d-Implement-hardware-indexed-vertex-blending-w.patch b/patches/wined3d-Indexed_Vertex_Blending/0002-wined3d-Implement-hardware-indexed-vertex-blending-w.patch new file mode 100644 index 00000000..1eb5042a --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0002-wined3d-Implement-hardware-indexed-vertex-blending-w.patch @@ -0,0 +1,218 @@ +From 0b8b0f04a03d358ee4560502568a695641368812 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Sat, 26 Aug 2017 00:59:29 +0200 +Subject: wined3d: Implement hardware indexed vertex blending with 9 matrices. + +--- + dlls/d3d9/tests/visual.c | 2 +- + dlls/wined3d/glsl_shader.c | 31 +++++++++++++++++++++---------- + dlls/wined3d/utils.c | 3 +++ + dlls/wined3d/vertexdeclaration.c | 9 +++++++++ + dlls/wined3d/wined3d_private.h | 18 +++++++++++++++++- + 5 files changed, 51 insertions(+), 12 deletions(-) + +diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +index 9b845b5ad44..3575b0be2e8 100644 +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -19844,7 +19844,7 @@ static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char + ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); + if (caps.MaxVertexBlendMatrixIndex < 7 || caps.MaxVertexBlendMatrices < 4) + { +- todo_wine win_skip("(%s) Too few vertex blend matrices supported: MaxVertexBlendMatrices=%u, MaxVertexBlendMatrixIndex=%u.\n", ++ win_skip("(%s) Too few vertex blend matrices supported: MaxVertexBlendMatrices=%u, MaxVertexBlendMatrixIndex=%u.\n", + test_id_str, caps.MaxVertexBlendMatrices, caps.MaxVertexBlendMatrixIndex); + return; + } +diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c +index 1aa23ee33ad..3e84ad0d717 100644 +--- a/dlls/wined3d/glsl_shader.c ++++ b/dlls/wined3d/glsl_shader.c +@@ -144,7 +144,7 @@ struct glsl_vs_program + GLint uniform_b_locations[WINED3D_MAX_CONSTS_B]; + GLint pos_fixup_location; + +- GLint modelview_matrix_location[MAX_VERTEX_BLENDS]; ++ GLint modelview_matrix_location[MAX_VERTEX_INDEX_BLENDS]; + GLint projection_matrix_location; + GLint normal_matrix_location; + GLint texture_matrix_location[MAX_TEXTURES]; +@@ -1786,7 +1786,7 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context + { + struct wined3d_matrix mat; + +- for (i = 1; i < MAX_VERTEX_BLENDS; ++i) ++ for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i) + { + if (prog->vs.modelview_matrix_location[i] == -1) + break; +@@ -8519,8 +8519,7 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + { + {"vec4", "ffp_attrib_position"}, /* WINED3D_FFP_POSITION */ + {"vec4", "ffp_attrib_blendweight"}, /* WINED3D_FFP_BLENDWEIGHT */ +- /* TODO: Indexed vertex blending */ +- {"float", ""}, /* WINED3D_FFP_BLENDINDICES */ ++ {"vec4", "ffp_attrib_blendindices"}, /* WINED3D_FFP_BLENDINDICES */ + {"vec3", "ffp_attrib_normal"}, /* WINED3D_FFP_NORMAL */ + {"float", "ffp_attrib_psize"}, /* WINED3D_FFP_PSIZE */ + {"vec4", "ffp_attrib_diffuse"}, /* WINED3D_FFP_DIFFUSE */ +@@ -8532,6 +8531,7 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + BOOL legacy_lighting = priv->legacy_lighting; + GLuint shader_obj; + unsigned int i; ++ char var[64]; + + string_buffer_clear(buffer); + +@@ -8550,7 +8550,7 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + } + shader_addline(buffer, "\n"); + +- shader_addline(buffer, "uniform mat4 ffp_modelview_matrix[%u];\n", MAX_VERTEX_BLENDS); ++ shader_addline(buffer, "uniform mat4 ffp_modelview_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS); + shader_addline(buffer, "uniform mat4 ffp_projection_matrix;\n"); + shader_addline(buffer, "uniform mat3 ffp_normal_matrix;\n"); + shader_addline(buffer, "uniform mat4 ffp_texture_matrix[%u];\n", MAX_TEXTURES); +@@ -8642,7 +8642,10 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + + shader_addline(buffer, "vec4 ec_pos = vec4(0.0);\n"); + for (i = 0; i < settings->vertexblends + 1; ++i) +- shader_addline(buffer, "ec_pos += ffp_attrib_blendweight[%u] * (ffp_modelview_matrix[%u] * ffp_attrib_position);\n", i, i); ++ { ++ sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); ++ shader_addline(buffer, "ec_pos += ffp_attrib_blendweight[%u] * (ffp_modelview_matrix[%s] * ffp_attrib_position);\n", i, var); ++ } + + shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); + if (settings->clipping) +@@ -8666,7 +8669,10 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + else + { + for (i = 0; i < settings->vertexblends + 1; ++i) +- shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (mat3(ffp_modelview_matrix[%u]) * ffp_attrib_normal);\n", i, i); ++ { ++ sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); ++ shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (mat3(ffp_modelview_matrix[%s]) * ffp_attrib_normal);\n", i, var); ++ } + } + + if (settings->normalize) +@@ -9539,7 +9545,7 @@ static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info * + + vs->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup")); + +- for (i = 0; i < MAX_VERTEX_BLENDS; ++i) ++ for (i = 0; i < MAX_VERTEX_INDEX_BLENDS; ++i) + { + string_buffer_sprintf(name, "ffp_modelview_matrix[%u]", i); + vs->modelview_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); +@@ -10114,7 +10120,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const + entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW + | WINED3D_SHADER_CONST_FFP_PROJ; + +- for (i = 1; i < MAX_VERTEX_BLENDS; ++i) ++ for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i) + { + if (entry->vs.modelview_matrix_location[i] != -1) + { +@@ -11076,7 +11082,7 @@ static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, + caps->ffp_generic_attributes = TRUE; + caps->max_active_lights = MAX_ACTIVE_LIGHTS; + caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS; +- caps->max_vertex_blend_matrix_index = 0; ++ caps->max_vertex_blend_matrix_index = MAX_VERTEX_INDEX_BLENDS - 1; + caps->vertex_processing_caps = WINED3DVTXPCAPS_TEXGEN + | WINED3DVTXPCAPS_MATERIALSOURCE7 + | WINED3DVTXPCAPS_VERTEXFOG +@@ -11494,6 +11500,11 @@ static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] = + {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, + {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, ++ {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(4)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(4)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, ++ {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(5)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(5)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, ++ {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(6)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(6)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, ++ {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(7)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(7)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, ++ {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(8)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(8)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, + {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, +diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c +index 5e29e7cd7a5..847429511b9 100644 +--- a/dlls/wined3d/utils.c ++++ b/dlls/wined3d/utils.c +@@ -5810,6 +5810,9 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_context *context, + break; + } + ++ if (use_indexed_vertex_blending(state, si)) ++ settings->vb_indices = 1; ++ + settings->clipping = state->render_states[WINED3D_RS_CLIPPING] + && state->render_states[WINED3D_RS_CLIPPLANEENABLE]; + settings->normal = !!(si->use_map & (1u << WINED3D_FFP_NORMAL)); +diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c +index 4fa6d54c37d..c6ab0ea09c9 100644 +--- a/dlls/wined3d/vertexdeclaration.c ++++ b/dlls/wined3d/vertexdeclaration.c +@@ -119,6 +119,15 @@ static BOOL declaration_element_valid_ffp(const struct wined3d_vertex_element *e + return FALSE; + } + ++ case WINED3D_DECL_USAGE_BLEND_INDICES: ++ switch(element->format) ++ { ++ case WINED3DFMT_R8G8B8A8_UINT: ++ return TRUE; ++ default: ++ return FALSE; ++ } ++ + case WINED3D_DECL_USAGE_NORMAL: + switch(element->format) + { +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 2c40b2d9838..7c20934ad40 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -272,6 +272,7 @@ static inline enum complex_fixup get_complex_fixup(struct color_fixup_desc fixup + #define MAX_UNORDERED_ACCESS_VIEWS 8 + #define MAX_TGSM_REGISTERS 8192 + #define MAX_VERTEX_BLENDS 4 ++#define MAX_VERTEX_INDEX_BLENDS 9 + #define MAX_MULTISAMPLE_TYPES 8 + #define MAX_RENDER_TARGETS 8 + +@@ -2723,7 +2724,8 @@ struct wined3d_ffp_vs_settings + DWORD ortho_fog : 1; + DWORD flatshading : 1; + DWORD swizzle_map : 16; /* MAX_ATTRIBS, 16 */ +- DWORD padding : 2; ++ DWORD vb_indices : 1; ++ DWORD padding : 1; + + DWORD texgen[MAX_TEXTURES]; + }; +@@ -4299,6 +4301,20 @@ static inline void *wined3d_calloc(SIZE_T count, SIZE_T size) + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * size); + } + ++static inline BOOL use_indexed_vertex_blending(const struct wined3d_state *state, const struct wined3d_stream_info *si) ++{ ++ if (!state->render_states[WINED3D_RS_INDEXEDVERTEXBLENDENABLE]) ++ return FALSE; ++ ++ if (state->render_states[WINED3D_RS_VERTEXBLEND] == WINED3D_VBF_DISABLE) ++ return FALSE; ++ ++ if (!(si->use_map & (1 << WINED3D_FFP_BLENDINDICES)) || !(si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT))) ++ return FALSE; ++ ++ return TRUE; ++} ++ + static inline BOOL use_vs(const struct wined3d_state *state) + { + /* Check state->vertex_declaration to allow this to be used before the +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/0003-d3d9-tests-Test-normal-calculation-when-indexed-vert.patch b/patches/wined3d-Indexed_Vertex_Blending/0003-d3d9-tests-Test-normal-calculation-when-indexed-vert.patch new file mode 100644 index 00000000..abc197d1 --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0003-d3d9-tests-Test-normal-calculation-when-indexed-vert.patch @@ -0,0 +1,221 @@ +From ca7e96f08d1a718817dcb6f0527a5348161daf82 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 31 Aug 2017 00:23:43 +0200 +Subject: d3d9/tests: Test normal calculation when indexed vertex blending is + enabled. + +--- + dlls/d3d9/tests/visual.c | 115 ++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 93 insertions(+), 22 deletions(-) + +diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +index 3575b0be2e8..863a3c513de 100644 +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -19717,6 +19717,7 @@ done: + + static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char *test_id_str) + { ++ IDirect3DPixelShader9 *ps; + D3DCAPS9 caps; + D3DCOLOR color; + HRESULT hr; +@@ -19733,31 +19734,49 @@ static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char + {{{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, +- 0.0f, 0.0f, 1.0f, 0.0f, ++ 0.0f, 0.0f, 2.0f, 0.0f, + -4.0f, 4.0f, 0.0f, 1.0f + }}}, + lower_left = + {{{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, +- 0.0f, 0.0f, 1.0f, 0.0f, ++ 0.0f, 0.0f, 2.0f, 0.0f, + -4.0f, -4.0f, 0.0f, 1.0f + }}}, + upper_right = + {{{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, +- 0.0f, 0.0f, 1.0f, 0.0f, ++ 0.0f, 0.0f, 2.0f, 0.0f, + 4.0f, 4.0f, 0.0f, 1.0f + }}}, + lower_right = + {{{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, +- 0.0f, 0.0f, 1.0f, 0.0f, ++ 0.0f, 0.0f, 2.0f, 0.0f, + 4.0f, -4.0f, 0.0f, 1.0f ++ }}}, ++ identity = ++ {{{ ++ 1.0f, 0.0f, 0.0f, 0.0f, ++ 0.0f, 1.0f, 0.0f, 0.0f, ++ 0.0f, 0.0f, 1.0f, 0.0f, ++ 0.0f, 0.0f, 0.0f, 1.0f + }}}; + ++ static const DWORD normal_ps[] = ++ { ++ 0xffff0200, /* ps_2_0 */ ++ 0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0 */ ++ 0x0200001f, 0x80000000, 0xb0070000, /* dcl t0.xyz */ ++ 0x02000001, 0x80170000, 0xb0e40000, /* mov_sat r0.xyz, t0 */ ++ 0x02000001, 0x80080000, 0xa0000000, /* mov r0.w, c0.x */ ++ 0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */ ++ 0x0000ffff, /* end */ ++ }; ++ + static const POINT quad_upper_right_points[] = + { + {576, 48}, {-1, -1}, +@@ -19798,6 +19817,7 @@ static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char + struct vec3 position; + struct vec3 blendweights; + DWORD matrixIndices; ++ struct vec3 normal; + } + vertex_data[4]; + const POINT *quad_points; +@@ -19807,34 +19827,34 @@ static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char + { + /* upper right */ + { +- {{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}, +- {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}, +- {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}, +- {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}}, ++ {{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}}, + quad_upper_right_points, quad_upper_right_empty_points + }, + /* center */ + { +- {{{-1.0f, -1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405}, +- {{-1.0f, 1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405}, +- {{ 1.0f, -1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405}, +- {{ 1.0f, 1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405}}, ++ {{{-1.0f, -1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{-1.0f, 1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{ 1.0f, -1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{ 1.0f, 1.0f, 0.0f}, {0.25f, 0.25f, 0.25f}, 0x06070405, {0.0f, 0.0f, 1.0f}}}, + quad_center_points, quad_center_empty_points + }, + /* upper center */ + { +- {{{-1.0f, -1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405}, +- {{-1.0f, 1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405}, +- {{ 1.0f, -1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405}, +- {{ 1.0f, 1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405}}, ++ {{{-1.0f, -1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{-1.0f, 1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{ 1.0f, -1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{ 1.0f, 1.0f, 0.0f}, {0.5f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}}, + quad_upper_center_points, quad_upper_center_empty_points + }, + /* full screen */ + { +- {{{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, 0x06070405}, +- {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0x06070405}, +- {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, 0x06070405}, +- {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405}}, ++ {{{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{-1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}, ++ {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0x06070405, {0.0f, 0.0f, 1.0f}}}, + quad_fullscreen_points, quad_fullscreen_empty_points + } + }; +@@ -19869,21 +19889,32 @@ static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char + ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetRenderState D3DRS_INDEXEDVERTEXBLENDENABLE failed %08x.\n", + test_id_str, hr); + ++ hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL | 1); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetTextureStageState failed %08x.\n", test_id_str, hr); ++ hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, &identity); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetTransform returned %08x.\n", test_id_str, hr); ++ ++ hr = IDirect3DDevice9_CreatePixelShader(device, normal_ps, &ps); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_CreatePixelShader failed %08x.\n", test_id_str, hr); ++ + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) + { + const POINT *point; + ++ hr = IDirect3DDevice9_SetPixelShader(device, NULL); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetPixelShader failed %08x.\n", test_id_str, hr); ++ + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %08x.\n", hr); + + hr = IDirect3DDevice9_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + +- hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4); ++ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4 | D3DFVF_NORMAL); + ok(SUCCEEDED(hr), "(%s) Failed to set FVF, hr %#x.\n", test_id_str, hr); + + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, tests[i].vertex_data, +- 6 * sizeof(float) + sizeof(DWORD)); ++ 9 * sizeof(float) + sizeof(DWORD)); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + hr = IDirect3DDevice9_EndScene(device); +@@ -19907,7 +19938,47 @@ static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char + + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); ++ ++ hr = IDirect3DDevice9_SetPixelShader(device, ps); ++ ok(hr == D3D_OK, "(%s) IDirect3DDevice9_SetPixelShader failed %08x.\n", test_id_str, hr); ++ ++ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0); ++ ok(SUCCEEDED(hr), "Failed to clear %08x.\n", hr); ++ ++ hr = IDirect3DDevice9_BeginScene(device); ++ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); ++ ++ hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4 | D3DFVF_NORMAL); ++ ok(SUCCEEDED(hr), "(%s) Failed to set FVF, hr %#x.\n", test_id_str, hr); ++ ++ hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, tests[i].vertex_data, ++ 9 * sizeof(float) + sizeof(DWORD)); ++ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); ++ ++ hr = IDirect3DDevice9_EndScene(device); ++ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); ++ ++ point = tests[i].quad_points; ++ while (point->x != -1 && point->y != -1) ++ { ++ color = getPixelColor(device, point->x, point->y); ++ todo_wine ok(color_match(color, 0x0000007f, 1), "(%s) Expected color 0x0000007f at %dx%d, got 0x%08x.\n", test_id_str, point->x, point->y, color); ++ ++point; ++ } ++ ++ point = tests[i].empty_points; ++ while (point->x != -1 && point->y != -1) ++ { ++ color = getPixelColor(device, point->x, point->y); ++ ok(color_match(color, 0x00000000, 1), "(%s) Expected color 0x00000000 at %dx%d, got 0x%08x", test_id_str, point->x, point->y, color); ++ ++point; ++ } ++ ++ hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ++ ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); + } ++ ++ IDirect3DVertexShader9_Release(ps); + } + + static void test_indexed_vertex_blending(void) +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/0004-wined3d-Fix-calculation-of-normal-when-vertex-blendi.patch b/patches/wined3d-Indexed_Vertex_Blending/0004-wined3d-Fix-calculation-of-normal-when-vertex-blendi.patch new file mode 100644 index 00000000..fe6ec80b --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0004-wined3d-Fix-calculation-of-normal-when-vertex-blendi.patch @@ -0,0 +1,173 @@ +From c0e0cc096b8e0dab0b7734424816dc70dca35261 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 31 Aug 2017 01:00:04 +0200 +Subject: wined3d: Fix calculation of normal when vertex blending is enabled. + +--- + dlls/d3d9/tests/visual.c | 2 +- + dlls/wined3d/glsl_shader.c | 76 +++++++++++++++++++++------------------------- + 2 files changed, 36 insertions(+), 42 deletions(-) + +diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +index 863a3c513de..49d519befb5 100644 +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -19962,7 +19962,7 @@ static void do_test_indexed_vertex_blending(IDirect3DDevice9 *device, const char + while (point->x != -1 && point->y != -1) + { + color = getPixelColor(device, point->x, point->y); +- todo_wine ok(color_match(color, 0x0000007f, 1), "(%s) Expected color 0x0000007f at %dx%d, got 0x%08x.\n", test_id_str, point->x, point->y, color); ++ ok(color_match(color, 0x0000007f, 1), "(%s) Expected color 0x0000007f at %dx%d, got 0x%08x.\n", test_id_str, point->x, point->y, color); + ++point; + } + +diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c +index 3e84ad0d717..2aa0d0db0a4 100644 +--- a/dlls/wined3d/glsl_shader.c ++++ b/dlls/wined3d/glsl_shader.c +@@ -145,8 +145,8 @@ struct glsl_vs_program + GLint pos_fixup_location; + + GLint modelview_matrix_location[MAX_VERTEX_INDEX_BLENDS]; ++ GLint normal_matrix_location[MAX_VERTEX_INDEX_BLENDS]; + GLint projection_matrix_location; +- GLint normal_matrix_location; + GLint texture_matrix_location[MAX_TEXTURES]; + GLint material_ambient_location; + GLint material_diffuse_location; +@@ -1496,33 +1496,6 @@ static BOOL invert_matrix(struct wined3d_matrix *out, struct wined3d_matrix *m) + return TRUE; + } + +-static void shader_glsl_ffp_vertex_normalmatrix_uniform(const struct wined3d_context *context, +- const struct wined3d_state *state, struct glsl_shader_prog_link *prog) +-{ +- const struct wined3d_gl_info *gl_info = context->gl_info; +- float mat[3 * 3]; +- struct wined3d_matrix mv; +- unsigned int i, j; +- +- if (prog->vs.normal_matrix_location == -1) +- return; +- +- get_modelview_matrix(context, state, 0, &mv); +- if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING) +- invert_matrix_3d(&mv, &mv); +- else +- invert_matrix(&mv, &mv); +- /* Tests show that singular modelview matrices are used unchanged as normal +- * matrices on D3D3 and older. There seems to be no clearly consistent +- * behavior on newer D3D versions so always follow older ddraw behavior. */ +- for (i = 0; i < 3; ++i) +- for (j = 0; j < 3; ++j) +- mat[i * 3 + j] = (&mv._11)[j * 4 + i]; +- +- GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location, 1, FALSE, mat)); +- checkGLcall("glUniformMatrix3fv"); +-} +- + static void shader_glsl_ffp_vertex_texmatrix_uniform(const struct wined3d_context *context, + const struct wined3d_state *state, unsigned int tex, struct glsl_shader_prog_link *prog) + { +@@ -1715,6 +1688,23 @@ static void shader_glsl_load_color_key_constant(const struct glsl_ps_program *ps + GL_EXTCALL(glUniform4fv(ps->color_key_location, 2, &float_key[0].r)); + } + ++/* Context activation is done by the caller. */ ++static void get_normal_matrix(struct wined3d_context *context, struct wined3d_matrix *mat, float *normal) ++{ ++ int i, j; ++ ++ if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING) ++ invert_matrix_3d(mat, mat); ++ else ++ invert_matrix(mat, mat); ++ /* Tests show that singular modelview matrices are used unchanged as normal ++ * matrices on D3D3 and older. There seems to be no clearly consistent ++ * behavior on newer D3D versions so always follow older ddraw behavior. */ ++ for (i = 0; i < 3; ++i) ++ for (j = 0; j < 3; ++j) ++ normal[i * 3 + j] = (&mat->_11)[j * 4 + i]; ++} ++ + /* Context activation is done by the caller (state handler). */ + static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context *context, + const struct wined3d_state *state) +@@ -1725,6 +1715,7 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context + const struct wined3d_gl_info *gl_info = context->gl_info; + struct shader_glsl_priv *priv = shader_priv; + float position_fixup[4]; ++ float normal[3 * 3]; + DWORD update_mask; + + struct glsl_shader_prog_link *prog = ctx_data->glsl_program; +@@ -1779,7 +1770,9 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context + GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[0], 1, FALSE, &mat._11)); + checkGLcall("glUniformMatrix4fv"); + +- shader_glsl_ffp_vertex_normalmatrix_uniform(context, state, prog); ++ get_normal_matrix(context, &mat, normal); ++ GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[0], 1, FALSE, normal)); ++ checkGLcall("glUniformMatrix3fv"); + } + + if (update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND) +@@ -1794,6 +1787,10 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context + get_modelview_matrix(context, state, i, &mat); + GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[i], 1, FALSE, &mat._11)); + checkGLcall("glUniformMatrix4fv"); ++ ++ get_normal_matrix(context, &mat, normal); ++ GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[i], 1, FALSE, normal)); ++ checkGLcall("glUniformMatrix3fv"); + } + } + +@@ -8551,8 +8548,8 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + shader_addline(buffer, "\n"); + + shader_addline(buffer, "uniform mat4 ffp_modelview_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS); ++ shader_addline(buffer, "uniform mat3 ffp_normal_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS); + shader_addline(buffer, "uniform mat4 ffp_projection_matrix;\n"); +- shader_addline(buffer, "uniform mat3 ffp_normal_matrix;\n"); + shader_addline(buffer, "uniform mat4 ffp_texture_matrix[%u];\n", MAX_TEXTURES); + + shader_addline(buffer, "uniform struct\n{\n"); +@@ -8662,17 +8659,10 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + shader_addline(buffer, "vec3 normal = vec3(0.0);\n"); + if (settings->normal) + { +- if (!settings->vertexblends) +- { +- shader_addline(buffer, "normal = ffp_normal_matrix * ffp_attrib_normal;\n"); +- } +- else ++ for (i = 0; i < settings->vertexblends + 1; ++i) + { +- for (i = 0; i < settings->vertexblends + 1; ++i) +- { +- sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); +- shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (mat3(ffp_modelview_matrix[%s]) * ffp_attrib_normal);\n", i, var); +- } ++ sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); ++ shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (ffp_normal_matrix[%s] * ffp_attrib_normal);\n", i, var); + } + + if (settings->normalize) +@@ -9550,8 +9540,12 @@ static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info * + string_buffer_sprintf(name, "ffp_modelview_matrix[%u]", i); + vs->modelview_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); + } ++ for (i = 0; i < MAX_VERTEX_INDEX_BLENDS; ++i) ++ { ++ string_buffer_sprintf(name, "ffp_normal_matrix[%u]", i); ++ vs->normal_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); ++ } + vs->projection_matrix_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_projection_matrix")); +- vs->normal_matrix_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_normal_matrix")); + for (i = 0; i < MAX_TEXTURES; ++i) + { + string_buffer_sprintf(name, "ffp_texture_matrix[%u]", i); +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/0005-wined3d-Move-matrix-inversion-functions-into-utils.c.patch b/patches/wined3d-Indexed_Vertex_Blending/0005-wined3d-Move-matrix-inversion-functions-into-utils.c.patch new file mode 100644 index 00000000..29db3899 --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0005-wined3d-Move-matrix-inversion-functions-into-utils.c.patch @@ -0,0 +1,599 @@ +From fadcafb0c6505447ba086d8dc4a6a024a040c61e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 31 Aug 2017 01:07:25 +0200 +Subject: wined3d: Move matrix inversion functions into utils.c + +--- + dlls/wined3d/glsl_shader.c | 275 ----------------------------------------- + dlls/wined3d/utils.c | 275 +++++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/wined3d_private.h | 2 + + 3 files changed, 277 insertions(+), 275 deletions(-) + +diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c +index 2aa0d0db0a4..aaca2f63441 100644 +--- a/dlls/wined3d/glsl_shader.c ++++ b/dlls/wined3d/glsl_shader.c +@@ -1221,281 +1221,6 @@ static void shader_glsl_load_np2fixup_constants(const struct glsl_ps_program *ps + GL_EXTCALL(glUniform4fv(ps->np2_fixup_location, ps->np2_fixup_info->num_consts, &np2fixup_constants[0].sx)); + } + +-/* Taken and adapted from Mesa. */ +-static BOOL invert_matrix_3d(struct wined3d_matrix *out, const struct wined3d_matrix *in) +-{ +- float pos, neg, t, det; +- struct wined3d_matrix temp; +- +- /* Calculate the determinant of upper left 3x3 submatrix and +- * determine if the matrix is singular. */ +- pos = neg = 0.0f; +- t = in->_11 * in->_22 * in->_33; +- if (t >= 0.0f) +- pos += t; +- else +- neg += t; +- +- t = in->_21 * in->_32 * in->_13; +- if (t >= 0.0f) +- pos += t; +- else +- neg += t; +- t = in->_31 * in->_12 * in->_23; +- if (t >= 0.0f) +- pos += t; +- else +- neg += t; +- +- t = -in->_31 * in->_22 * in->_13; +- if (t >= 0.0f) +- pos += t; +- else +- neg += t; +- t = -in->_21 * in->_12 * in->_33; +- if (t >= 0.0f) +- pos += t; +- else +- neg += t; +- +- t = -in->_11 * in->_32 * in->_23; +- if (t >= 0.0f) +- pos += t; +- else +- neg += t; +- +- det = pos + neg; +- +- if (fabsf(det) < 1e-25f) +- return FALSE; +- +- det = 1.0f / det; +- temp._11 = (in->_22 * in->_33 - in->_32 * in->_23) * det; +- temp._12 = -(in->_12 * in->_33 - in->_32 * in->_13) * det; +- temp._13 = (in->_12 * in->_23 - in->_22 * in->_13) * det; +- temp._21 = -(in->_21 * in->_33 - in->_31 * in->_23) * det; +- temp._22 = (in->_11 * in->_33 - in->_31 * in->_13) * det; +- temp._23 = -(in->_11 * in->_23 - in->_21 * in->_13) * det; +- temp._31 = (in->_21 * in->_32 - in->_31 * in->_22) * det; +- temp._32 = -(in->_11 * in->_32 - in->_31 * in->_12) * det; +- temp._33 = (in->_11 * in->_22 - in->_21 * in->_12) * det; +- +- *out = temp; +- return TRUE; +-} +- +-static void swap_rows(float **a, float **b) +-{ +- float *tmp = *a; +- +- *a = *b; +- *b = tmp; +-} +- +-static BOOL invert_matrix(struct wined3d_matrix *out, struct wined3d_matrix *m) +-{ +- float wtmp[4][8]; +- float m0, m1, m2, m3, s; +- float *r0, *r1, *r2, *r3; +- +- r0 = wtmp[0]; +- r1 = wtmp[1]; +- r2 = wtmp[2]; +- r3 = wtmp[3]; +- +- r0[0] = m->_11; +- r0[1] = m->_12; +- r0[2] = m->_13; +- r0[3] = m->_14; +- r0[4] = 1.0f; +- r0[5] = r0[6] = r0[7] = 0.0f; +- +- r1[0] = m->_21; +- r1[1] = m->_22; +- r1[2] = m->_23; +- r1[3] = m->_24; +- r1[5] = 1.0f; +- r1[4] = r1[6] = r1[7] = 0.0f; +- +- r2[0] = m->_31; +- r2[1] = m->_32; +- r2[2] = m->_33; +- r2[3] = m->_34; +- r2[6] = 1.0f; +- r2[4] = r2[5] = r2[7] = 0.0f; +- +- r3[0] = m->_41; +- r3[1] = m->_42; +- r3[2] = m->_43; +- r3[3] = m->_44; +- r3[7] = 1.0f; +- r3[4] = r3[5] = r3[6] = 0.0f; +- +- /* Choose pivot - or die. */ +- if (fabsf(r3[0]) > fabsf(r2[0])) +- swap_rows(&r3, &r2); +- if (fabsf(r2[0]) > fabsf(r1[0])) +- swap_rows(&r2, &r1); +- if (fabsf(r1[0]) > fabsf(r0[0])) +- swap_rows(&r1, &r0); +- if (r0[0] == 0.0f) +- return FALSE; +- +- /* Eliminate first variable. */ +- m1 = r1[0] / r0[0]; m2 = r2[0] / r0[0]; m3 = r3[0] / r0[0]; +- s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s; +- s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s; +- s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s; +- s = r0[4]; +- if (s != 0.0f) +- { +- r1[4] -= m1 * s; +- r2[4] -= m2 * s; +- r3[4] -= m3 * s; +- } +- s = r0[5]; +- if (s != 0.0f) +- { +- r1[5] -= m1 * s; +- r2[5] -= m2 * s; +- r3[5] -= m3 * s; +- } +- s = r0[6]; +- if (s != 0.0f) +- { +- r1[6] -= m1 * s; +- r2[6] -= m2 * s; +- r3[6] -= m3 * s; +- } +- s = r0[7]; +- if (s != 0.0f) +- { +- r1[7] -= m1 * s; +- r2[7] -= m2 * s; +- r3[7] -= m3 * s; +- } +- +- /* Choose pivot - or die. */ +- if (fabsf(r3[1]) > fabsf(r2[1])) +- swap_rows(&r3, &r2); +- if (fabsf(r2[1]) > fabsf(r1[1])) +- swap_rows(&r2, &r1); +- if (r1[1] == 0.0f) +- return FALSE; +- +- /* Eliminate second variable. */ +- m2 = r2[1] / r1[1]; m3 = r3[1] / r1[1]; +- r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2]; +- r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3]; +- s = r1[4]; +- if (s != 0.0f) +- { +- r2[4] -= m2 * s; +- r3[4] -= m3 * s; +- } +- s = r1[5]; +- if (s != 0.0f) +- { +- r2[5] -= m2 * s; +- r3[5] -= m3 * s; +- } +- s = r1[6]; +- if (s != 0.0f) +- { +- r2[6] -= m2 * s; +- r3[6] -= m3 * s; +- } +- s = r1[7]; +- if (s != 0.0f) +- { +- r2[7] -= m2 * s; +- r3[7] -= m3 * s; +- } +- +- /* Choose pivot - or die. */ +- if (fabsf(r3[2]) > fabsf(r2[2])) +- swap_rows(&r3, &r2); +- if (r2[2] == 0.0f) +- return FALSE; +- +- /* Eliminate third variable. */ +- m3 = r3[2] / r2[2]; +- r3[3] -= m3 * r2[3]; +- r3[4] -= m3 * r2[4]; +- r3[5] -= m3 * r2[5]; +- r3[6] -= m3 * r2[6]; +- r3[7] -= m3 * r2[7]; +- +- /* Last check. */ +- if (r3[3] == 0.0f) +- return FALSE; +- +- /* Back substitute row 3. */ +- s = 1.0f / r3[3]; +- r3[4] *= s; +- r3[5] *= s; +- r3[6] *= s; +- r3[7] *= s; +- +- /* Back substitute row 2. */ +- m2 = r2[3]; +- s = 1.0f / r2[2]; +- r2[4] = s * (r2[4] - r3[4] * m2); +- r2[5] = s * (r2[5] - r3[5] * m2); +- r2[6] = s * (r2[6] - r3[6] * m2); +- r2[7] = s * (r2[7] - r3[7] * m2); +- m1 = r1[3]; +- r1[4] -= r3[4] * m1; +- r1[5] -= r3[5] * m1; +- r1[6] -= r3[6] * m1; +- r1[7] -= r3[7] * m1; +- m0 = r0[3]; +- r0[4] -= r3[4] * m0; +- r0[5] -= r3[5] * m0; +- r0[6] -= r3[6] * m0; +- r0[7] -= r3[7] * m0; +- +- /* Back substitute row 1. */ +- m1 = r1[2]; +- s = 1.0f / r1[1]; +- r1[4] = s * (r1[4] - r2[4] * m1); +- r1[5] = s * (r1[5] - r2[5] * m1); +- r1[6] = s * (r1[6] - r2[6] * m1); +- r1[7] = s * (r1[7] - r2[7] * m1); +- m0 = r0[2]; +- r0[4] -= r2[4] * m0; +- r0[5] -= r2[5] * m0; +- r0[6] -= r2[6] * m0; +- r0[7] -= r2[7] * m0; +- +- /* Back substitute row 0. */ +- m0 = r0[1]; +- s = 1.0f / r0[0]; +- r0[4] = s * (r0[4] - r1[4] * m0); +- r0[5] = s * (r0[5] - r1[5] * m0); +- r0[6] = s * (r0[6] - r1[6] * m0); +- r0[7] = s * (r0[7] - r1[7] * m0); +- +- out->_11 = r0[4]; +- out->_12 = r0[5]; +- out->_13 = r0[6]; +- out->_14 = r0[7]; +- out->_21 = r1[4]; +- out->_22 = r1[5]; +- out->_23 = r1[6]; +- out->_24 = r1[7]; +- out->_31 = r2[4]; +- out->_32 = r2[5]; +- out->_33 = r2[6]; +- out->_34 = r2[7]; +- out->_41 = r3[4]; +- out->_42 = r3[5]; +- out->_43 = r3[6]; +- out->_44 = r3[7]; +- +- return TRUE; +-} +- + static void shader_glsl_ffp_vertex_texmatrix_uniform(const struct wined3d_context *context, + const struct wined3d_state *state, unsigned int tex, struct glsl_shader_prog_link *prog) + { +diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c +index 847429511b9..b2effb5c2ec 100644 +--- a/dlls/wined3d/utils.c ++++ b/dlls/wined3d/utils.c +@@ -5234,6 +5234,281 @@ void multiply_matrix(struct wined3d_matrix *dst, const struct wined3d_matrix *sr + *dst = tmp; + } + ++/* Taken and adapted from Mesa. */ ++BOOL invert_matrix_3d(struct wined3d_matrix *out, const struct wined3d_matrix *in) ++{ ++ float pos, neg, t, det; ++ struct wined3d_matrix temp; ++ ++ /* Calculate the determinant of upper left 3x3 submatrix and ++ * determine if the matrix is singular. */ ++ pos = neg = 0.0f; ++ t = in->_11 * in->_22 * in->_33; ++ if (t >= 0.0f) ++ pos += t; ++ else ++ neg += t; ++ ++ t = in->_21 * in->_32 * in->_13; ++ if (t >= 0.0f) ++ pos += t; ++ else ++ neg += t; ++ t = in->_31 * in->_12 * in->_23; ++ if (t >= 0.0f) ++ pos += t; ++ else ++ neg += t; ++ ++ t = -in->_31 * in->_22 * in->_13; ++ if (t >= 0.0f) ++ pos += t; ++ else ++ neg += t; ++ t = -in->_21 * in->_12 * in->_33; ++ if (t >= 0.0f) ++ pos += t; ++ else ++ neg += t; ++ ++ t = -in->_11 * in->_32 * in->_23; ++ if (t >= 0.0f) ++ pos += t; ++ else ++ neg += t; ++ ++ det = pos + neg; ++ ++ if (fabsf(det) < 1e-25f) ++ return FALSE; ++ ++ det = 1.0f / det; ++ temp._11 = (in->_22 * in->_33 - in->_32 * in->_23) * det; ++ temp._12 = -(in->_12 * in->_33 - in->_32 * in->_13) * det; ++ temp._13 = (in->_12 * in->_23 - in->_22 * in->_13) * det; ++ temp._21 = -(in->_21 * in->_33 - in->_31 * in->_23) * det; ++ temp._22 = (in->_11 * in->_33 - in->_31 * in->_13) * det; ++ temp._23 = -(in->_11 * in->_23 - in->_21 * in->_13) * det; ++ temp._31 = (in->_21 * in->_32 - in->_31 * in->_22) * det; ++ temp._32 = -(in->_11 * in->_32 - in->_31 * in->_12) * det; ++ temp._33 = (in->_11 * in->_22 - in->_21 * in->_12) * det; ++ ++ *out = temp; ++ return TRUE; ++} ++ ++static void swap_rows(float **a, float **b) ++{ ++ float *tmp = *a; ++ ++ *a = *b; ++ *b = tmp; ++} ++ ++BOOL invert_matrix(struct wined3d_matrix *out, struct wined3d_matrix *m) ++{ ++ float wtmp[4][8]; ++ float m0, m1, m2, m3, s; ++ float *r0, *r1, *r2, *r3; ++ ++ r0 = wtmp[0]; ++ r1 = wtmp[1]; ++ r2 = wtmp[2]; ++ r3 = wtmp[3]; ++ ++ r0[0] = m->_11; ++ r0[1] = m->_12; ++ r0[2] = m->_13; ++ r0[3] = m->_14; ++ r0[4] = 1.0f; ++ r0[5] = r0[6] = r0[7] = 0.0f; ++ ++ r1[0] = m->_21; ++ r1[1] = m->_22; ++ r1[2] = m->_23; ++ r1[3] = m->_24; ++ r1[5] = 1.0f; ++ r1[4] = r1[6] = r1[7] = 0.0f; ++ ++ r2[0] = m->_31; ++ r2[1] = m->_32; ++ r2[2] = m->_33; ++ r2[3] = m->_34; ++ r2[6] = 1.0f; ++ r2[4] = r2[5] = r2[7] = 0.0f; ++ ++ r3[0] = m->_41; ++ r3[1] = m->_42; ++ r3[2] = m->_43; ++ r3[3] = m->_44; ++ r3[7] = 1.0f; ++ r3[4] = r3[5] = r3[6] = 0.0f; ++ ++ /* Choose pivot - or die. */ ++ if (fabsf(r3[0]) > fabsf(r2[0])) ++ swap_rows(&r3, &r2); ++ if (fabsf(r2[0]) > fabsf(r1[0])) ++ swap_rows(&r2, &r1); ++ if (fabsf(r1[0]) > fabsf(r0[0])) ++ swap_rows(&r1, &r0); ++ if (r0[0] == 0.0f) ++ return FALSE; ++ ++ /* Eliminate first variable. */ ++ m1 = r1[0] / r0[0]; m2 = r2[0] / r0[0]; m3 = r3[0] / r0[0]; ++ s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s; ++ s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s; ++ s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s; ++ s = r0[4]; ++ if (s != 0.0f) ++ { ++ r1[4] -= m1 * s; ++ r2[4] -= m2 * s; ++ r3[4] -= m3 * s; ++ } ++ s = r0[5]; ++ if (s != 0.0f) ++ { ++ r1[5] -= m1 * s; ++ r2[5] -= m2 * s; ++ r3[5] -= m3 * s; ++ } ++ s = r0[6]; ++ if (s != 0.0f) ++ { ++ r1[6] -= m1 * s; ++ r2[6] -= m2 * s; ++ r3[6] -= m3 * s; ++ } ++ s = r0[7]; ++ if (s != 0.0f) ++ { ++ r1[7] -= m1 * s; ++ r2[7] -= m2 * s; ++ r3[7] -= m3 * s; ++ } ++ ++ /* Choose pivot - or die. */ ++ if (fabsf(r3[1]) > fabsf(r2[1])) ++ swap_rows(&r3, &r2); ++ if (fabsf(r2[1]) > fabsf(r1[1])) ++ swap_rows(&r2, &r1); ++ if (r1[1] == 0.0f) ++ return FALSE; ++ ++ /* Eliminate second variable. */ ++ m2 = r2[1] / r1[1]; m3 = r3[1] / r1[1]; ++ r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2]; ++ r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3]; ++ s = r1[4]; ++ if (s != 0.0f) ++ { ++ r2[4] -= m2 * s; ++ r3[4] -= m3 * s; ++ } ++ s = r1[5]; ++ if (s != 0.0f) ++ { ++ r2[5] -= m2 * s; ++ r3[5] -= m3 * s; ++ } ++ s = r1[6]; ++ if (s != 0.0f) ++ { ++ r2[6] -= m2 * s; ++ r3[6] -= m3 * s; ++ } ++ s = r1[7]; ++ if (s != 0.0f) ++ { ++ r2[7] -= m2 * s; ++ r3[7] -= m3 * s; ++ } ++ ++ /* Choose pivot - or die. */ ++ if (fabsf(r3[2]) > fabsf(r2[2])) ++ swap_rows(&r3, &r2); ++ if (r2[2] == 0.0f) ++ return FALSE; ++ ++ /* Eliminate third variable. */ ++ m3 = r3[2] / r2[2]; ++ r3[3] -= m3 * r2[3]; ++ r3[4] -= m3 * r2[4]; ++ r3[5] -= m3 * r2[5]; ++ r3[6] -= m3 * r2[6]; ++ r3[7] -= m3 * r2[7]; ++ ++ /* Last check. */ ++ if (r3[3] == 0.0f) ++ return FALSE; ++ ++ /* Back substitute row 3. */ ++ s = 1.0f / r3[3]; ++ r3[4] *= s; ++ r3[5] *= s; ++ r3[6] *= s; ++ r3[7] *= s; ++ ++ /* Back substitute row 2. */ ++ m2 = r2[3]; ++ s = 1.0f / r2[2]; ++ r2[4] = s * (r2[4] - r3[4] * m2); ++ r2[5] = s * (r2[5] - r3[5] * m2); ++ r2[6] = s * (r2[6] - r3[6] * m2); ++ r2[7] = s * (r2[7] - r3[7] * m2); ++ m1 = r1[3]; ++ r1[4] -= r3[4] * m1; ++ r1[5] -= r3[5] * m1; ++ r1[6] -= r3[6] * m1; ++ r1[7] -= r3[7] * m1; ++ m0 = r0[3]; ++ r0[4] -= r3[4] * m0; ++ r0[5] -= r3[5] * m0; ++ r0[6] -= r3[6] * m0; ++ r0[7] -= r3[7] * m0; ++ ++ /* Back substitute row 1. */ ++ m1 = r1[2]; ++ s = 1.0f / r1[1]; ++ r1[4] = s * (r1[4] - r2[4] * m1); ++ r1[5] = s * (r1[5] - r2[5] * m1); ++ r1[6] = s * (r1[6] - r2[6] * m1); ++ r1[7] = s * (r1[7] - r2[7] * m1); ++ m0 = r0[2]; ++ r0[4] -= r2[4] * m0; ++ r0[5] -= r2[5] * m0; ++ r0[6] -= r2[6] * m0; ++ r0[7] -= r2[7] * m0; ++ ++ /* Back substitute row 0. */ ++ m0 = r0[1]; ++ s = 1.0f / r0[0]; ++ r0[4] = s * (r0[4] - r1[4] * m0); ++ r0[5] = s * (r0[5] - r1[5] * m0); ++ r0[6] = s * (r0[6] - r1[6] * m0); ++ r0[7] = s * (r0[7] - r1[7] * m0); ++ ++ out->_11 = r0[4]; ++ out->_12 = r0[5]; ++ out->_13 = r0[6]; ++ out->_14 = r0[7]; ++ out->_21 = r1[4]; ++ out->_22 = r1[5]; ++ out->_23 = r1[6]; ++ out->_24 = r1[7]; ++ out->_31 = r2[4]; ++ out->_32 = r2[5]; ++ out->_33 = r2[6]; ++ out->_34 = r2[7]; ++ out->_41 = r3[4]; ++ out->_42 = r3[5]; ++ out->_43 = r3[6]; ++ out->_44 = r3[7]; ++ ++ return TRUE; ++} ++ + DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) { + DWORD size = 0; + int i; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 7c20934ad40..08f4f01f7e6 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -3889,6 +3889,8 @@ GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) DE + /* Math utils */ + void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1, + const struct wined3d_matrix *src2) DECLSPEC_HIDDEN; ++BOOL invert_matrix_3d(struct wined3d_matrix *out, const struct wined3d_matrix *in) DECLSPEC_HIDDEN; ++BOOL invert_matrix(struct wined3d_matrix *out, struct wined3d_matrix *m) DECLSPEC_HIDDEN; + + void wined3d_release_dc(HWND window, HDC dc) DECLSPEC_HIDDEN; + +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/0006-wined3d-Implement-software-processing-for-indexed-ve.patch b/patches/wined3d-Indexed_Vertex_Blending/0006-wined3d-Implement-software-processing-for-indexed-ve.patch new file mode 100644 index 00000000..0000e36a --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0006-wined3d-Implement-software-processing-for-indexed-ve.patch @@ -0,0 +1,310 @@ +From 97d6b11b95d8cdcc0d777b11f6f00e9d6054adfb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 31 Aug 2017 01:26:38 +0200 +Subject: wined3d: Implement software processing for indexed vertex blending. + +--- + dlls/wined3d/device.c | 16 ------ + dlls/wined3d/drawprim.c | 107 +++++++++++++++++++++++++++++++++++++++-- + dlls/wined3d/glsl_shader.c | 32 ++++++++---- + dlls/wined3d/utils.c | 7 ++- + dlls/wined3d/wined3d_private.h | 16 +++++- + 5 files changed, 148 insertions(+), 30 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index d3ee3b0a839..31c7ea431d8 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3963,31 +3963,15 @@ HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device + + void CDECL wined3d_device_set_software_vertex_processing(struct wined3d_device *device, BOOL software) + { +- static BOOL warned; +- + TRACE("device %p, software %#x.\n", device, software); + +- if (!warned) +- { +- FIXME("device %p, software %#x stub!\n", device, software); +- warned = TRUE; +- } +- + device->softwareVertexProcessing = software; + } + + BOOL CDECL wined3d_device_get_software_vertex_processing(const struct wined3d_device *device) + { +- static BOOL warned; +- + TRACE("device %p.\n", device); + +- if (!warned) +- { +- TRACE("device %p stub!\n", device); +- warned = TRUE; +- } +- + return device->softwareVertexProcessing; + } + +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index 51460e54d1a..6adb7934134 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -200,6 +200,101 @@ static void draw_primitive_arrays_indirect(struct wined3d_context *context, cons + checkGLcall("draw indirect"); + } + ++static const BYTE *software_vertex_blending(struct wined3d_context *context, ++ const struct wined3d_state *state, const struct wined3d_stream_info *si, ++ unsigned int element_idx, unsigned int stride_idx, float *result) ++{ ++#define SI_FORMAT(idx) (si->elements[(idx)].format->emit_idx) ++#define SI_PTR(idx1, idx2) (si->elements[(idx1)].data.addr + si->elements[(idx1)].stride * (idx2)) ++ ++ const float *data = (const float *)SI_PTR(element_idx, stride_idx); ++ float vector[4] = {0.0f, 0.0f, 0.0f, 1.0f}; ++ float cur_weight, weight_sum = 0.0f; ++ struct wined3d_matrix m; ++ const BYTE *blend_index; ++ const float *weights; ++ int i, num_weights; ++ ++ if (element_idx != WINED3D_FFP_POSITION && element_idx != WINED3D_FFP_NORMAL) ++ return (BYTE *)data; ++ ++ if (!use_indexed_vertex_blending(state, si) || !use_software_vertex_processing(context->device)) ++ return (BYTE *)data; ++ ++ if (!si->elements[WINED3D_FFP_BLENDINDICES].data.addr || ++ !si->elements[WINED3D_FFP_BLENDWEIGHT].data.addr) ++ { ++ FIXME("no blend indices / weights set\n"); ++ return (BYTE *)data; ++ } ++ ++ if (SI_FORMAT(WINED3D_FFP_BLENDINDICES) != WINED3D_FFP_EMIT_UBYTE4) ++ { ++ FIXME("unsupported blend index format: %u\n", SI_FORMAT(WINED3D_FFP_BLENDINDICES)); ++ return (BYTE *)data; ++ } ++ ++ /* FIXME: validate weight format */ ++ switch (state->render_states[WINED3D_RS_VERTEXBLEND]) ++ { ++ case WINED3D_VBF_0WEIGHTS: num_weights = 0; break; ++ case WINED3D_VBF_1WEIGHTS: num_weights = 1; break; ++ case WINED3D_VBF_2WEIGHTS: num_weights = 2; break; ++ case WINED3D_VBF_3WEIGHTS: num_weights = 3; break; ++ default: ++ FIXME("unsupported vertex blend render state: %u\n", state->render_states[WINED3D_RS_VERTEXBLEND]); ++ return (BYTE *)data; ++ } ++ ++ switch (SI_FORMAT(element_idx)) ++ { ++ case WINED3D_FFP_EMIT_FLOAT4: vector[3] = data[3]; ++ case WINED3D_FFP_EMIT_FLOAT3: vector[2] = data[2]; ++ case WINED3D_FFP_EMIT_FLOAT2: vector[1] = data[1]; ++ case WINED3D_FFP_EMIT_FLOAT1: vector[0] = data[0]; break; ++ default: ++ FIXME("unsupported value format: %u\n", SI_FORMAT(element_idx)); ++ return (BYTE *)data; ++ } ++ ++ blend_index = SI_PTR(WINED3D_FFP_BLENDINDICES, stride_idx); ++ weights = (const float *)SI_PTR(WINED3D_FFP_BLENDWEIGHT, stride_idx); ++ result[0] = result[1] = result[2] = result[3] = 0.0f; ++ ++ for (i = 0; i < num_weights + 1; i++) ++ { ++ cur_weight = (i < num_weights) ? weights[i] : 1.0f - weight_sum; ++ get_modelview_matrix(context, state, blend_index[i], &m); ++ ++ if (element_idx == WINED3D_FFP_POSITION) ++ { ++ result[0] += cur_weight * (vector[0] * m._11 + vector[1] * m._21 + vector[2] * m._31 + vector[3] * m._41); ++ result[1] += cur_weight * (vector[0] * m._12 + vector[1] * m._22 + vector[2] * m._32 + vector[3] * m._42); ++ result[2] += cur_weight * (vector[0] * m._13 + vector[1] * m._23 + vector[2] * m._33 + vector[3] * m._43); ++ result[3] += cur_weight * (vector[0] * m._14 + vector[1] * m._24 + vector[2] * m._34 + vector[3] * m._44); ++ } ++ else ++ { ++ if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING) ++ invert_matrix_3d(&m, &m); ++ else ++ invert_matrix(&m, &m); ++ ++ /* multiply with transposed M */ ++ result[0] += cur_weight * (vector[0] * m._11 + vector[1] * m._12 + vector[2] * m._13); ++ result[1] += cur_weight * (vector[0] * m._21 + vector[1] * m._22 + vector[2] * m._23); ++ result[2] += cur_weight * (vector[0] * m._31 + vector[1] * m._32 + vector[2] * m._33); ++ } ++ ++ weight_sum += weights[i]; ++ } ++ ++#undef SI_FORMAT ++#undef SI_PTR ++ ++ return (BYTE *)result; ++} ++ + static unsigned int get_stride_idx(const void *idx_data, unsigned int idx_size, + unsigned int base_vertex_idx, unsigned int start_idx, unsigned int vertex_idx) + { +@@ -228,6 +323,7 @@ static void draw_primitive_immediate_mode(struct wined3d_context *context, const + BOOL specular_fog = FALSE; + BOOL ps = use_ps(state); + const void *ptr; ++ float tmp[4]; + + static unsigned int once; + +@@ -264,7 +360,7 @@ static void draw_primitive_immediate_mode(struct wined3d_context *context, const + if (!(use_map & 1u << element_idx)) + continue; + +- ptr = si->elements[element_idx].data.addr + si->elements[element_idx].stride * stride_idx; ++ ptr = software_vertex_blending(context, state, si, element_idx, stride_idx, tmp); + ops->generic[si->elements[element_idx].format->emit_idx](element_idx, ptr); + } + } +@@ -376,7 +472,7 @@ static void draw_primitive_immediate_mode(struct wined3d_context *context, const + + if (normal) + { +- ptr = normal + stride_idx * si->elements[WINED3D_FFP_NORMAL].stride; ++ ptr = software_vertex_blending(context, state, si, WINED3D_FFP_NORMAL, stride_idx, tmp); + ops->normal[si->elements[WINED3D_FFP_NORMAL].format->emit_idx](ptr); + } + +@@ -421,7 +517,7 @@ static void draw_primitive_immediate_mode(struct wined3d_context *context, const + + if (position) + { +- ptr = position + stride_idx * si->elements[WINED3D_FFP_POSITION].stride; ++ ptr = software_vertex_blending(context, state, si, WINED3D_FFP_POSITION, stride_idx, tmp); + ops->position[si->elements[WINED3D_FFP_POSITION].format->emit_idx](ptr); + } + } +@@ -636,6 +732,11 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s + WARN_(d3d_perf)("Using software emulation because manual fog coordinates are provided.\n"); + emulation = TRUE; + } ++ else if (use_indexed_vertex_blending(state, stream_info) && use_software_vertex_processing(context->device)) ++ { ++ WARN_(d3d_perf)("Using software emulation because application requested SVP.\n"); ++ emulation = TRUE; ++ } + + if (emulation) + { +diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c +index aaca2f63441..a3050590dfb 100644 +--- a/dlls/wined3d/glsl_shader.c ++++ b/dlls/wined3d/glsl_shader.c +@@ -8359,14 +8359,21 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + } + else + { +- for (i = 0; i < settings->vertexblends; ++i) +- shader_addline(buffer, "ffp_attrib_blendweight[%u] -= ffp_attrib_blendweight[%u];\n", settings->vertexblends, i); ++ if (!settings->sw_blending) ++ { ++ for (i = 0; i < settings->vertexblends; ++i) ++ shader_addline(buffer, "ffp_attrib_blendweight[%u] -= ffp_attrib_blendweight[%u];\n", settings->vertexblends, i); + +- shader_addline(buffer, "vec4 ec_pos = vec4(0.0);\n"); +- for (i = 0; i < settings->vertexblends + 1; ++i) ++ shader_addline(buffer, "vec4 ec_pos = vec4(0.0);\n"); ++ for (i = 0; i < settings->vertexblends + 1; ++i) ++ { ++ sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); ++ shader_addline(buffer, "ec_pos += ffp_attrib_blendweight[%u] * (ffp_modelview_matrix[%s] * ffp_attrib_position);\n", i, var); ++ } ++ } ++ else + { +- sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); +- shader_addline(buffer, "ec_pos += ffp_attrib_blendweight[%u] * (ffp_modelview_matrix[%s] * ffp_attrib_position);\n", i, var); ++ shader_addline(buffer, "vec4 ec_pos = ffp_attrib_position;\n"); + } + + shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); +@@ -8384,10 +8391,17 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *pr + shader_addline(buffer, "vec3 normal = vec3(0.0);\n"); + if (settings->normal) + { +- for (i = 0; i < settings->vertexblends + 1; ++i) ++ if (!settings->sw_blending) ++ { ++ for (i = 0; i < settings->vertexblends + 1; ++i) ++ { ++ sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); ++ shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (ffp_normal_matrix[%s] * ffp_attrib_normal);\n", i, var); ++ } ++ } ++ else + { +- sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); +- shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (ffp_normal_matrix[%s] * ffp_attrib_normal);\n", i, var); ++ shader_addline(buffer, "normal = ffp_attrib_normal;\n"); + } + + if (settings->normalize) +diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c +index b2effb5c2ec..438dfc6fef3 100644 +--- a/dlls/wined3d/utils.c ++++ b/dlls/wined3d/utils.c +@@ -6086,7 +6086,12 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_context *context, + } + + if (use_indexed_vertex_blending(state, si)) +- settings->vb_indices = 1; ++ { ++ if (use_software_vertex_processing(context->device)) ++ settings->sw_blending = 1; ++ else ++ settings->vb_indices = 1; ++ } + + settings->clipping = state->render_states[WINED3D_RS_CLIPPING] + && state->render_states[WINED3D_RS_CLIPPLANEENABLE]; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 08f4f01f7e6..a2be7326834 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2725,7 +2725,7 @@ struct wined3d_ffp_vs_settings + DWORD flatshading : 1; + DWORD swizzle_map : 16; /* MAX_ATTRIBS, 16 */ + DWORD vb_indices : 1; +- DWORD padding : 1; ++ DWORD sw_blending : 1; + + DWORD texgen[MAX_TEXTURES]; + }; +@@ -4317,6 +4317,20 @@ static inline BOOL use_indexed_vertex_blending(const struct wined3d_state *state + return TRUE; + } + ++static inline BOOL use_software_vertex_processing(const struct wined3d_device *device) ++{ ++ if (device->shader_backend != &glsl_shader_backend) ++ return FALSE; ++ ++ if (device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING) ++ return TRUE; ++ ++ if (!(device->create_parms.flags & WINED3DCREATE_MIXED_VERTEXPROCESSING)) ++ return FALSE; ++ ++ return device->softwareVertexProcessing; ++} ++ + static inline BOOL use_vs(const struct wined3d_state *state) + { + /* Check state->vertex_declaration to allow this to be used before the +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/0007-d3d9-tests-Check-MaxVertexBlendMatrixIndex-capabilit.patch b/patches/wined3d-Indexed_Vertex_Blending/0007-d3d9-tests-Check-MaxVertexBlendMatrixIndex-capabilit.patch new file mode 100644 index 00000000..ca4788fb --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0007-d3d9-tests-Check-MaxVertexBlendMatrixIndex-capabilit.patch @@ -0,0 +1,68 @@ +From 910fbdd6cd674e2ba1c9ca201787540db9de10f3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 31 Aug 2017 01:47:49 +0200 +Subject: d3d9/tests: Check MaxVertexBlendMatrixIndex capability. + +--- + dlls/d3d9/tests/visual.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +index 49d519befb5..e7e6cf6e9e9 100644 +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -19987,7 +19987,9 @@ static void test_indexed_vertex_blending(void) + IDirect3DDevice9 *device; + IDirect3D9 *d3d; + ULONG refcount; ++ D3DCAPS9 caps; + HWND window; ++ HRESULT hr; + + window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, 640, 480, NULL, NULL, NULL, NULL); +@@ -20016,7 +20018,14 @@ static void test_indexed_vertex_blending(void) + if (SUCCEEDED(IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) + { ++ memset(&caps, 0, sizeof(caps)); ++ hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); ++ ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); ++ todo_wine ok(caps.MaxVertexBlendMatrixIndex == 255, "Expected 255 as maximum blend matrix index, got %u.\n", ++ caps.MaxVertexBlendMatrixIndex); ++ + do_test_indexed_vertex_blending(device,"IVB software"); ++ + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + } +@@ -20026,7 +20035,26 @@ static void test_indexed_vertex_blending(void) + if (SUCCEEDED(IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + D3DCREATE_MIXED_VERTEXPROCESSING, &present_parameters, &device))) + { ++ memset(&caps, 0, sizeof(caps)); ++ hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); ++ ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); ++ ok(caps.MaxVertexBlendMatrixIndex < 255, "Expected less than 255 as maximum blend matrix index, got %u.\n", ++ caps.MaxVertexBlendMatrixIndex); ++ ++ hr = IDirect3DDevice9_SetSoftwareVertexProcessing(device, TRUE); ++ ok(SUCCEEDED(hr), "Failed to enable software processing, hr %#x.\n", hr); ++ ++ memset(&caps, 0, sizeof(caps)); ++ hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); ++ ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); ++ todo_wine ok(caps.MaxVertexBlendMatrixIndex == 255, "Expected 255 as maximum blend matrix index, got %u.\n", ++ caps.MaxVertexBlendMatrixIndex); ++ ++ hr = IDirect3DDevice9_SetSoftwareVertexProcessing(device, FALSE); ++ ok(SUCCEEDED(hr), "Failed to disable software processing, hr %#x.\n", hr); ++ + do_test_indexed_vertex_blending(device,"IVB mixed"); ++ + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + } +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/0008-wined3d-Report-correct-number-of-blend-matrices-when.patch b/patches/wined3d-Indexed_Vertex_Blending/0008-wined3d-Report-correct-number-of-blend-matrices-when.patch new file mode 100644 index 00000000..8aff61bc --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0008-wined3d-Report-correct-number-of-blend-matrices-when.patch @@ -0,0 +1,76 @@ +From 405f1ca63e69fb5d9143ea26ec375ffef815e0a5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Thu, 31 Aug 2017 01:54:22 +0200 +Subject: wined3d: Report correct number of blend matrices when software vertex + processing is used. + +--- + dlls/d3d9/tests/visual.c | 4 ++-- + dlls/wined3d/device.c | 9 ++++++++- + dlls/wined3d/directx.c | 5 ++++- + 3 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +index e7e6cf6e9e9..1c219ab7cf4 100644 +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -20021,7 +20021,7 @@ static void test_indexed_vertex_blending(void) + memset(&caps, 0, sizeof(caps)); + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); +- todo_wine ok(caps.MaxVertexBlendMatrixIndex == 255, "Expected 255 as maximum blend matrix index, got %u.\n", ++ ok(caps.MaxVertexBlendMatrixIndex == 255, "Expected 255 as maximum blend matrix index, got %u.\n", + caps.MaxVertexBlendMatrixIndex); + + do_test_indexed_vertex_blending(device,"IVB software"); +@@ -20047,7 +20047,7 @@ static void test_indexed_vertex_blending(void) + memset(&caps, 0, sizeof(caps)); + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); +- todo_wine ok(caps.MaxVertexBlendMatrixIndex == 255, "Expected 255 as maximum blend matrix index, got %u.\n", ++ ok(caps.MaxVertexBlendMatrixIndex == 255, "Expected 255 as maximum blend matrix index, got %u.\n", + caps.MaxVertexBlendMatrixIndex); + + hr = IDirect3DDevice9_SetSoftwareVertexProcessing(device, FALSE); +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 31c7ea431d8..6b92bc679c2 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3530,10 +3530,17 @@ struct wined3d_texture * CDECL wined3d_device_get_texture(const struct wined3d_d + + HRESULT CDECL wined3d_device_get_device_caps(const struct wined3d_device *device, WINED3DCAPS *caps) + { ++ HRESULT hr; ++ + TRACE("device %p, caps %p.\n", device, caps); + +- return wined3d_get_device_caps(device->wined3d, device->adapter->ordinal, ++ hr = wined3d_get_device_caps(device->wined3d, device->adapter->ordinal, + device->create_parms.device_type, caps); ++ ++ if (SUCCEEDED(hr) && use_software_vertex_processing(device)) ++ caps->MaxVertexBlendMatrixIndex = 255; ++ ++ return hr; + } + + HRESULT CDECL wined3d_device_get_display_mode(const struct wined3d_device *device, UINT swapchain_idx, +diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c +index a34ead003cc..fe12e81b915 100644 +--- a/dlls/wined3d/directx.c ++++ b/dlls/wined3d/directx.c +@@ -5981,7 +5981,10 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte + caps->MaxUserClipPlanes = vertex_caps.max_user_clip_planes; + caps->MaxActiveLights = vertex_caps.max_active_lights; + caps->MaxVertexBlendMatrices = vertex_caps.max_vertex_blend_matrices; +- caps->MaxVertexBlendMatrixIndex = vertex_caps.max_vertex_blend_matrix_index; ++ if (device_type == WINED3D_DEVICE_TYPE_HAL) ++ caps->MaxVertexBlendMatrixIndex = vertex_caps.max_vertex_blend_matrix_index; ++ else ++ caps->MaxVertexBlendMatrixIndex = 255; + caps->VertexProcessingCaps = vertex_caps.vertex_processing_caps; + caps->FVFCaps = vertex_caps.fvf_caps; + caps->RasterCaps |= vertex_caps.raster_caps; +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/0009-wined3d-Track-updates-of-vertex-blend-matrices-separ.patch b/patches/wined3d-Indexed_Vertex_Blending/0009-wined3d-Track-updates-of-vertex-blend-matrices-separ.patch new file mode 100644 index 00000000..1fb71ef7 --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/0009-wined3d-Track-updates-of-vertex-blend-matrices-separ.patch @@ -0,0 +1,56 @@ +From 8a4c30330dab1a81ffd0bd51215ffdd2f6bf9a61 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Thu, 31 Aug 2017 07:42:31 +0200 +Subject: wined3d: Track updates of vertex blend matrices separately. + +--- + dlls/wined3d/glsl_shader.c | 5 ++++- + dlls/wined3d/wined3d_private.h | 3 ++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c +index a3050590dfb..31b892faf65 100644 +--- a/dlls/wined3d/glsl_shader.c ++++ b/dlls/wined3d/glsl_shader.c +@@ -1508,6 +1508,8 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context + { + if (prog->vs.modelview_matrix_location[i] == -1) + break; ++ if (!(update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i))) ++ continue; + + get_modelview_matrix(context, state, i, &mat); + GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[i], 1, FALSE, &mat._11)); +@@ -11002,7 +11004,8 @@ static void glsl_vertex_pipe_world(struct wined3d_context *context, + static void glsl_vertex_pipe_vertexblend(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) + { +- context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND; ++ int i = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)); ++ context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i); + } + + static void glsl_vertex_pipe_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index a2be7326834..5089e6b8c32 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -435,13 +435,14 @@ enum wined3d_shader_resource_type + #define WINED3D_SHADER_CONST_PS_Y_CORR 0x00001000 + #define WINED3D_SHADER_CONST_PS_NP2_FIXUP 0x00002000 + #define WINED3D_SHADER_CONST_FFP_MODELVIEW 0x00004000 +-#define WINED3D_SHADER_CONST_FFP_VERTEXBLEND 0x00008000 + #define WINED3D_SHADER_CONST_FFP_PROJ 0x00010000 + #define WINED3D_SHADER_CONST_FFP_TEXMATRIX 0x00020000 + #define WINED3D_SHADER_CONST_FFP_MATERIAL 0x00040000 + #define WINED3D_SHADER_CONST_FFP_LIGHTS 0x00080000 + #define WINED3D_SHADER_CONST_FFP_PS 0x00100000 + #define WINED3D_SHADER_CONST_FFP_COLOR_KEY 0x00200000 ++#define WINED3D_SHADER_CONST_FFP_VERTEXBLEND 0xff000000 ++#define WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i) (0x01000000 << ((i) - 1)) + + enum wined3d_shader_register_type + { +-- +2.14.1 + diff --git a/patches/wined3d-Indexed_Vertex_Blending/definition b/patches/wined3d-Indexed_Vertex_Blending/definition new file mode 100644 index 00000000..b290e665 --- /dev/null +++ b/patches/wined3d-Indexed_Vertex_Blending/definition @@ -0,0 +1,3 @@ +Fixes: [39057] Support for indexed vertex blending +Depends: wined3d-WINED3D_RS_COLORWRITEENABLE +Depends: wined3d-DrawIndirect