From ee17d52379ab1bf8ed5c19ce3658a1996d19808b Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Mon, 25 Feb 2019 15:23:33 +0300
Subject: [PATCH] wined3d: Support SWVP mode vertex shaders.

---
 dlls/d3d9/tests/device.c       | 16 ++------
 dlls/d3d9/tests/visual.c       |  5 +--
 dlls/wined3d/device.c          |  8 ++++
 dlls/wined3d/glsl_shader.c     | 71 +++++++++++++++++++++++++---------
 dlls/wined3d/shader.c          | 44 ++++++++++++++-------
 dlls/wined3d/shader_sm1.c      |  2 +-
 dlls/wined3d/wined3d_private.h |  7 ++++
 7 files changed, 104 insertions(+), 49 deletions(-)

diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 09446d0be6..7d62fd5823 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -6901,15 +6901,11 @@ float4 main(const float4 color : COLOR) : SV_TARGET
 
     vs = NULL;
     hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
-    todo_wine
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-    if (vs)
-        IDirect3DVertexShader9_Release(vs);
+    IDirect3DVertexShader9_Release(vs);
     hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
-    todo_wine
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-    if (vs)
-        IDirect3DVertexShader9_Release(vs);
+    IDirect3DVertexShader9_Release(vs);
 
     refcount = IDirect3DDevice9_Release(device);
     ok(!refcount, "Device has %u references left.\n", refcount);
@@ -6926,20 +6922,16 @@ float4 main(const float4 color : COLOR) : SV_TARGET
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
 
     hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
-    todo_wine
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     hr = IDirect3DDevice9_SetVertexShader(device, vs);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-    if (vs)
-        IDirect3DVertexShader9_Release(vs);
+    IDirect3DVertexShader9_Release(vs);
 
     hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
-    todo_wine
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     hr = IDirect3DDevice9_SetVertexShader(device, vs);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-    if (vs)
-        IDirect3DVertexShader9_Release(vs);
+    IDirect3DVertexShader9_Release(vs);
 
 cleanup:
     refcount = IDirect3DDevice9_Release(device);
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 0ae4eb7a34..0463df7a56 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -24803,7 +24803,6 @@ static void test_mvp_software_vertex_shaders(void)
     hr = IDirect3DDevice9_CreateVertexShader(device, reladdr_shader_code, &reladdr_shader);
     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
     hr = IDirect3DDevice9_CreateVertexShader(device, pure_sw_shader_code, &pure_sw_shader);
-    todo_wine
     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
     ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
@@ -24841,7 +24840,7 @@ static void test_mvp_software_vertex_shaders(void)
 
     expected_color = 0x00ff0000; /* Color from vertex data and not from the shader. */
     color = getPixelColor(device, 5, 5);
-    ok(color == expected_color, "Expected color 0x%08x, got 0x%08x (sw shader in hw mode, second attempt).\n",
+    todo_wine ok(color == expected_color, "Expected color 0x%08x, got 0x%08x (sw shader in hw mode, second attempt).\n",
             expected_color, color);
 
     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
@@ -24860,7 +24859,6 @@ static void test_mvp_software_vertex_shaders(void)
 
     expected_color = 0x00ffffff;
     color = getPixelColor(device, 5, 5);
-    todo_wine
     ok(color == expected_color, "Expected color 0x%08x, got 0x%08x (sw shader in sw mode).\n",
             expected_color, color);
 
@@ -24910,7 +24908,6 @@ static void test_mvp_software_vertex_shaders(void)
 
     expected_color = 0x0000ffff; /* c[256] is c_color for SW shader. */
     color = getPixelColor(device, 5, 5);
-    todo_wine
     ok(color == expected_color, "Expected color 0x%08x, got 0x%08x (shader in sw mode).\n",
             expected_color, color);
 
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 1db974f118..844d2f60ec 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4256,6 +4256,14 @@ void CDECL wined3d_device_set_software_vertex_processing(struct wined3d_device *
         warned = TRUE;
     }
 
+    wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
+    if (!device->softwareVertexProcessing != !software)
+    {
+        unsigned int i;
+
+        for (i = 0; i < device->context_count; ++i)
+            device->contexts[i]->constant_update_mask |= WINED3D_SHADER_CONST_VS_F;
+    }
     device->softwareVertexProcessing = software;
 }
 
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index a88f92cc03..3ae361024e 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -140,7 +140,9 @@ struct shader_glsl_priv
 
     BOOL consts_ubo;
     GLuint ubo_vs_c;
-    struct wined3d_vec4 vs_c_buffer[WINED3D_MAX_VS_CONSTS_F];
+    BOOL prev_device_swvp;
+    struct wined3d_vec4 vs_c_buffer[WINED3D_MAX_VS_CONSTS_F_SWVP];
+    unsigned int max_vs_consts_f;
 
     const struct wined3d_vertex_pipe_ops *vertex_pipe;
     const struct wined3d_fragment_pipe_ops *fragment_pipe;
@@ -155,7 +157,7 @@ struct glsl_vs_program
     struct list shader_entry;
     GLuint id;
     GLenum vertex_color_clamp;
-    GLint uniform_f_locations[WINED3D_MAX_VS_CONSTS_F];
+    GLint uniform_f_locations[WINED3D_MAX_VS_CONSTS_F_SWVP];
     GLint uniform_i_locations[WINED3D_MAX_CONSTS_I];
     GLint uniform_b_locations[WINED3D_MAX_CONSTS_B];
     GLint pos_fixup_location;
@@ -1195,7 +1197,7 @@ static void bind_and_orphan_consts_ubo(const struct wined3d_gl_info *gl_info, st
 {
     GL_EXTCALL(glBindBuffer(GL_UNIFORM_BUFFER, priv->ubo_vs_c));
     checkGLcall("glBindBuffer");
-    GL_EXTCALL(glBufferData(GL_UNIFORM_BUFFER, WINED3D_MAX_VS_CONSTS_F * sizeof(struct wined3d_vec4),
+    GL_EXTCALL(glBufferData(GL_UNIFORM_BUFFER, priv->max_vs_consts_f * sizeof(struct wined3d_vec4),
             NULL, GL_STREAM_DRAW));
     checkGLcall("glBufferData");
 }
@@ -1203,14 +1205,16 @@ static void bind_and_orphan_consts_ubo(const struct wined3d_gl_info *gl_info, st
 /* 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,
-        unsigned char *stack, unsigned int version, struct shader_glsl_priv *priv)
+        unsigned char *stack, unsigned int version, struct shader_glsl_priv *priv, BOOL device_swvp)
 {
     const struct wined3d_shader_lconst *lconst;
     BOOL is_vertex_shader = shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_VERTEX;
 
     if (is_vertex_shader && priv->consts_ubo)
     {
+        BOOL zero_sw_constants = !device_swvp && priv->prev_device_swvp;
         const struct wined3d_vec4 *data;
+        unsigned int const_count;
         unsigned max_const_used;
 
         if (priv->ubo_vs_c == -1)
@@ -1220,22 +1224,32 @@ static void shader_glsl_load_constants_f(const struct wined3d_shader *shader, co
         }
 
         bind_and_orphan_consts_ubo(gl_info, priv);
-        max_const_used = shader->reg_maps.usesrelconstF
-                ? WINED3D_MAX_VS_CONSTS_F : shader->reg_maps.constant_float_count;
-        if (shader->load_local_constsF)
+        const_count = device_swvp ? priv->max_vs_consts_f : WINED3D_MAX_VS_CONSTS_F;
+        max_const_used = shader->reg_maps.usesrelconstF ? const_count : shader->reg_maps.constant_float_count;
+        if (shader->load_local_constsF || (zero_sw_constants && shader->reg_maps.usesrelconstF))
         {
             data = priv->vs_c_buffer;
             memcpy(priv->vs_c_buffer, constants, max_const_used * sizeof(*constants));
-            LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
+            if (zero_sw_constants)
             {
-                priv->vs_c_buffer[lconst->idx] = *(const struct wined3d_vec4 *)lconst->value;
+                memset(&priv->vs_c_buffer[const_count], 0, (priv->max_vs_consts_f - WINED3D_MAX_VS_CONSTS_F)
+                        * sizeof(*constants));
+                priv->prev_device_swvp = FALSE;
+            }
+            if (shader->load_local_constsF)
+            {
+                LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
+                {
+                    priv->vs_c_buffer[lconst->idx] = *(const struct wined3d_vec4 *)lconst->value;
+                }
             }
         }
         else
         {
             data = constants;
         }
-        GL_EXTCALL(glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(*constants) * max_const_used, data));
+        GL_EXTCALL(glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(*constants)
+                * (zero_sw_constants ? priv->max_vs_consts_f : max_const_used), data));
         checkGLcall("glBufferSubData");
         return;
     }
@@ -1603,7 +1617,7 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
                 GL_EXTCALL(glGenBuffers(1, &priv->ubo_vs_c));
                 GL_EXTCALL(glBindBuffer(GL_UNIFORM_BUFFER, priv->ubo_vs_c));
                 checkGLcall("glBindBuffer (UBO)");
-                GL_EXTCALL(glBufferData(GL_UNIFORM_BUFFER, WINED3D_MAX_VS_CONSTS_F * sizeof(struct wined3d_vec4),
+                GL_EXTCALL(glBufferData(GL_UNIFORM_BUFFER, priv->max_vs_consts_f * sizeof(struct wined3d_vec4),
                         NULL, GL_STREAM_DRAW));
                 checkGLcall("glBufferData");
             }
@@ -1615,7 +1629,8 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
 
     if (update_mask & WINED3D_SHADER_CONST_VS_F)
         shader_glsl_load_constants_f(vshader, gl_info, state->vs_consts_f,
-                prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version, priv);
+                prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack,
+                constant_version, priv, wined3d_device_is_swvp_mode(context->device));
 
     if (update_mask & WINED3D_SHADER_CONST_VS_I)
         shader_glsl_load_constants_i(vshader, gl_info, state->vs_consts_i,
@@ -1768,7 +1783,8 @@ 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,
-                prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version, priv);
+                prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version,
+                priv, FALSE);
 
     if (update_mask & WINED3D_SHADER_CONST_PS_I)
         shader_glsl_load_constants_i(pshader, gl_info, state->ps_consts_i,
@@ -1913,7 +1929,7 @@ static void shader_glsl_update_float_vertex_constants(struct wined3d_device *dev
     if (priv->consts_ubo)
         return;
 
-    for (i = start; i < min(WINED3D_MAX_VS_CONSTS_F, count + start); ++i)
+    for (i = start; i < count + start; ++i)
     {
         update_heap_entry(heap, i, priv->next_constant_version);
     }
@@ -2275,7 +2291,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context_gl *c
         shader_addline(buffer,"layout(std140) uniform vs_c_ubo\n"
                 "{ \n"
                 "    vec4 %s_c[%u];\n"
-                "};\n", prefix, min(shader->limits->constant_float, WINED3D_MAX_VS_CONSTS_F));
+                "};\n", prefix, min(shader->limits->constant_float, priv->max_vs_consts_f));
     }
     else if (shader->limits->constant_float > 0)
     {
@@ -10003,12 +10019,13 @@ static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info *
     }
     else if (!priv->consts_ubo)
     {
-        for (i = 0; i < vs_c_count; ++i)
+        for (i = 0; i < min(vs_c_count, priv->max_vs_consts_f); ++i)
         {
             string_buffer_sprintf(name, "vs_c[%u]", i);
             vs->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
         }
-        memset(&vs->uniform_f_locations[vs_c_count], 0xff, (WINED3D_MAX_VS_CONSTS_F - vs_c_count) * sizeof(GLuint));
+        if (vs_c_count < priv->max_vs_consts_f)
+            memset(&vs->uniform_f_locations[vs_c_count], 0xff, (priv->max_vs_consts_f - vs_c_count) * sizeof(GLuint));
     }
 
     for (i = 0; i < WINED3D_MAX_CONSTS_I; ++i)
@@ -10326,6 +10343,10 @@ static void set_glsl_shader_program(const struct wined3d_context_gl *context_gl,
         vs_list = &ffp_shader->linked_programs;
     }
 
+    if (vshader && vshader->reg_maps.constant_float_count > WINED3D_MAX_VS_CONSTS_F
+            && !wined3d_device_is_swvp_mode(context_gl->c.device))
+        FIXME("Applying context with SW shader in HW mode.\n");
+
     hshader = state->shader[WINED3D_SHADER_TYPE_HULL];
     if (!(context_gl->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_HULL)) && ctx_data->glsl_program)
         hs_id = ctx_data->glsl_program->hs.id;
@@ -11083,7 +11104,7 @@ static void constant_heap_free(struct constant_heap *heap)
 static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe,
         const struct wined3d_fragment_pipe_ops *fragment_pipe)
 {
-    SIZE_T stack_size = wined3d_log2i(max(WINED3D_MAX_VS_CONSTS_F, WINED3D_MAX_PS_CONSTS_F)) + 1;
+    SIZE_T stack_size;
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     struct fragment_caps fragment_caps;
     void *vertex_priv, *fragment_priv;
@@ -11094,6 +11115,18 @@ static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct win
 
     priv->consts_ubo = (device->adapter->d3d_info.wined3d_creation_flags & WINED3D_LEGACY_SHADER_CONSTANTS)
             && gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT];
+    priv->max_vs_consts_f = min(WINED3D_MAX_VS_CONSTS_F_SWVP, priv->consts_ubo
+            ? gl_info->limits.glsl_max_uniform_block_size / sizeof(struct wined3d_vec4)
+            : gl_info->limits.glsl_vs_float_constants);
+
+    if (!(device->create_parms.flags & (WINED3DCREATE_SOFTWARE_VERTEXPROCESSING | WINED3DCREATE_MIXED_VERTEXPROCESSING)))
+        priv->max_vs_consts_f = min(priv->max_vs_consts_f, WINED3D_MAX_VS_CONSTS_F);
+
+    stack_size = priv->consts_ubo
+            ? wined3d_log2i(WINED3D_MAX_PS_CONSTS_F) + 1
+            : wined3d_log2i(max(priv->max_vs_consts_f, WINED3D_MAX_PS_CONSTS_F)) + 1;
+    TRACE("consts_ubo %#x, max_vs_consts_f %u.\n", priv->consts_ubo, priv->max_vs_consts_f);
+
     string_buffer_list_init(&priv->string_buffers);
 
     if (!(vertex_priv = vertex_pipe->vp_alloc(&glsl_shader_backend, priv)))
@@ -11123,7 +11156,7 @@ static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct win
         goto fail;
     }
 
-    if (!constant_heap_init(&priv->vconst_heap, WINED3D_MAX_VS_CONSTS_F))
+    if (!priv->consts_ubo && !constant_heap_init(&priv->vconst_heap, priv->max_vs_consts_f))
     {
         ERR("Failed to initialize vertex shader constant heap\n");
         goto fail;
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index f29b49b902..294b65260e 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -592,7 +592,7 @@ static void shader_delete_constant_list(struct list *clist)
     list_init(clist);
 }
 
-static void shader_set_limits(struct wined3d_shader *shader)
+static void shader_set_limits(struct wined3d_shader *shader, BOOL swvp)
 {
     static const struct limits_entry
     {
@@ -615,6 +615,19 @@ static void shader_set_limits(struct wined3d_shader *shader)
         {WINED3D_SHADER_VERSION(4, 1), WINED3D_SHADER_VERSION(5, 0), {16,  0,   0,  0, 32,  0}},
         {0}
     },
+    vs_limits_swvp[] =
+    {
+        /* min_version, max_version, sampler, constant_int, constant_float, constant_bool, packed_output, packed_input */
+        {WINED3D_SHADER_VERSION(1, 0), WINED3D_SHADER_VERSION(1, 1),   { 0,  0, 8192,  0, 12,  0}},
+        {WINED3D_SHADER_VERSION(2, 0), WINED3D_SHADER_VERSION(2, 255), { 0, 16, 8192, 16, 12,  0}},
+        /* DX10 cards on Windows advertise a D3D9 constant limit of 256
+         * even though they are capable of supporting much more (GL
+         * drivers advertise 1024). d3d9.dll and d3d8.dll clamp the
+         * wined3d-advertised maximum. Clamp the constant limit for <= 3.0
+         * shaders to 256. */
+        {WINED3D_SHADER_VERSION(3, 0), WINED3D_SHADER_VERSION(3, 255), { 4, 16, 8192, 16, 12,  0}},
+        {0}
+    },
     hs_limits[] =
     {
         /* min_version, max_version, sampler, constant_int, constant_float, constant_bool, packed_output, packet_input */
@@ -659,7 +672,7 @@ static void shader_set_limits(struct wined3d_shader *shader)
             FIXME("Unexpected shader type %u found.\n", shader->reg_maps.shader_version.type);
             /* Fall-through. */
         case WINED3D_SHADER_TYPE_VERTEX:
-            limits_array = vs_limits;
+            limits_array = swvp ? vs_limits_swvp : vs_limits;
             break;
         case WINED3D_SHADER_TYPE_HULL:
             limits_array = hs_limits;
@@ -1027,7 +1040,7 @@ static HRESULT shader_scan_output_signature(struct wined3d_shader *shader)
 }
 
 /* Note that this does not count the loop register as an address register. */
-static HRESULT shader_get_registers_used(struct wined3d_shader *shader, DWORD constf_size)
+static HRESULT shader_get_registers_used(struct wined3d_shader *shader, DWORD constf_size, BOOL swvp)
 {
     struct wined3d_shader_signature_element input_signature_elements[max(MAX_ATTRIBS, MAX_REG_INPUT)];
     struct wined3d_shader_signature_element output_signature_elements[MAX_REG_OUTPUT];
@@ -1053,7 +1066,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, DWORD co
     prev_ins = current_ins = ptr;
     reg_maps->shader_version = shader_version;
 
-    shader_set_limits(shader);
+    shader_set_limits(shader, swvp);
 
     if (!(reg_maps->constf = heap_calloc(((min(shader->limits->constant_float, constf_size) + 31) / 32),
             sizeof(*reg_maps->constf))))
@@ -3324,7 +3337,7 @@ static unsigned int shader_max_version_from_feature_level(enum wined3d_feature_l
 }
 
 static HRESULT shader_set_function(struct wined3d_shader *shader, struct wined3d_device *device,
-        enum wined3d_shader_type type, unsigned int float_const_count)
+        enum wined3d_shader_type type, unsigned int float_const_count, BOOL swvp)
 {
     const struct wined3d_d3d_info *d3d_info = &shader->device->adapter->d3d_info;
     struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
@@ -3349,7 +3362,7 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, struct wined3d
         shader_trace_init(fe, shader->frontend_data);
 
     /* Second pass: figure out which registers are used, what the semantics are, etc. */
-    if (FAILED(hr = shader_get_registers_used(shader, float_const_count)))
+    if (FAILED(hr = shader_get_registers_used(shader, float_const_count, swvp)))
         return hr;
 
     if (version->type != type)
@@ -3688,14 +3701,19 @@ static HRESULT vertex_shader_init(struct wined3d_shader *shader, struct wined3d_
         const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    unsigned int vs_uniform_count;
     unsigned int i;
     HRESULT hr;
+    BOOL swvp = device->create_parms.flags & (WINED3DCREATE_SOFTWARE_VERTEXPROCESSING
+            | WINED3DCREATE_MIXED_VERTEXPROCESSING);
 
     if (FAILED(hr = shader_init(shader, device, desc, parent, parent_ops)))
         return hr;
 
+    vs_uniform_count = swvp ? device->adapter->d3d_info.limits.vs_uniform_count_swvp
+            : device->adapter->d3d_info.limits.vs_uniform_count;
     if (FAILED(hr = shader_set_function(shader, device,
-            WINED3D_SHADER_TYPE_VERTEX, device->adapter->d3d_info.limits.vs_uniform_count)))
+            WINED3D_SHADER_TYPE_VERTEX, vs_uniform_count, swvp)))
     {
         shader_cleanup(shader);
         return hr;
@@ -3799,7 +3817,7 @@ static HRESULT geometry_shader_init_stream_output(struct wined3d_shader *shader,
     {
         shader->reg_maps.shader_version = shader_version;
         shader->reg_maps.shader_version.type = WINED3D_SHADER_TYPE_GEOMETRY;
-        shader_set_limits(shader);
+        shader_set_limits(shader, 0);
         if (FAILED(hr = shader_scan_output_signature(shader)))
             return hr;
     }
@@ -3852,7 +3870,7 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3
         goto fail;
 
     if (shader->function
-            && FAILED(hr = shader_set_function(shader, device, WINED3D_SHADER_TYPE_GEOMETRY, 0)))
+            && FAILED(hr = shader_set_function(shader, device, WINED3D_SHADER_TYPE_GEOMETRY, 0, 0)))
         goto fail;
 
     return WINED3D_OK;
@@ -4182,7 +4200,7 @@ static HRESULT pixel_shader_init(struct wined3d_shader *shader, struct wined3d_d
         return hr;
 
     if (FAILED(hr = shader_set_function(shader, device,
-            WINED3D_SHADER_TYPE_PIXEL, device->adapter->d3d_info.limits.ps_uniform_count)))
+            WINED3D_SHADER_TYPE_PIXEL, device->adapter->d3d_info.limits.ps_uniform_count, 0)))
     {
         shader_cleanup(shader);
         return hr;
@@ -4274,7 +4292,7 @@ HRESULT CDECL wined3d_shader_create_cs(struct wined3d_device *device, const stru
         return hr;
     }
 
-    if (FAILED(hr = shader_set_function(object, device, WINED3D_SHADER_TYPE_COMPUTE, 0)))
+    if (FAILED(hr = shader_set_function(object, device, WINED3D_SHADER_TYPE_COMPUTE, 0, 0)))
     {
         shader_cleanup(object);
         heap_free(object);
@@ -4308,7 +4326,7 @@ HRESULT CDECL wined3d_shader_create_ds(struct wined3d_device *device, const stru
         return hr;
     }
 
-    if (FAILED(hr = shader_set_function(object, device, WINED3D_SHADER_TYPE_DOMAIN, 0)))
+    if (FAILED(hr = shader_set_function(object, device, WINED3D_SHADER_TYPE_DOMAIN, 0, 0)))
     {
         shader_cleanup(object);
         heap_free(object);
@@ -4370,7 +4388,7 @@ HRESULT CDECL wined3d_shader_create_hs(struct wined3d_device *device, const stru
         return hr;
     }
 
-    if (FAILED(hr = shader_set_function(object, device, WINED3D_SHADER_TYPE_HULL, 0)))
+    if (FAILED(hr = shader_set_function(object, device, WINED3D_SHADER_TYPE_HULL, 0, 0)))
     {
         shader_cleanup(object);
         heap_free(object);
diff --git a/dlls/wined3d/shader_sm1.c b/dlls/wined3d/shader_sm1.c
index 0c6bb93317..1051307e88 100644
--- a/dlls/wined3d/shader_sm1.c
+++ b/dlls/wined3d/shader_sm1.c
@@ -543,7 +543,7 @@ static void *shader_sm1_init(const DWORD *byte_code, size_t byte_code_size,
 
     major = WINED3D_SM1_VERSION_MAJOR(*byte_code);
     minor = WINED3D_SM1_VERSION_MINOR(*byte_code);
-    if (WINED3D_SHADER_VERSION(major, minor) > WINED3D_SHADER_VERSION(3, 0))
+    if (WINED3D_SHADER_VERSION(major, minor) > WINED3D_SHADER_VERSION(3, 255))
     {
         WARN("Invalid shader version %u.%u (%#x).\n", major, minor, *byte_code);
         return NULL;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index eef5d4fec2..cdfce0bea4 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3354,6 +3354,13 @@ HRESULT wined3d_device_set_implicit_swapchain(struct wined3d_device *device,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
 void wined3d_device_uninit_3d(struct wined3d_device *device) DECLSPEC_HIDDEN;
 
+static inline BOOL wined3d_device_is_swvp_mode(const struct wined3d_device *device)
+{
+    return (device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING)
+            || ((device->create_parms.flags & WINED3DCREATE_MIXED_VERTEXPROCESSING)
+            && device->softwareVertexProcessing);
+}
+
 static inline unsigned int wined3d_device_get_vs_uniform_count(const struct wined3d_device *device)
 {
     const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
-- 
2.25.1

