[PATCH 2/7] wined3d: Store vs_clipping in the adapter

Stefan Dösinger stefan at codeweavers.com
Fri Apr 19 04:20:52 CDT 2013


The problem this and the following patches address is that in general we
can't access the device without synchronization. This is no problem for
cached limit information because it never changes once the device is
initialized. However, this is not obvious from reading the code.

Beyond this, the adapter already decides which shader implementation to
use and thus already sets this limit.

Potential alternatives include keeping the status quo or introducing a
separate structure that holds these derived limits that is owned by the
device and linked in the contexts. We could also put it into gl_info,
but I dislike this idea because these limits are not GL limits, but
limits of our shader and fixed function pipeline implementations.
---
 dlls/wined3d/arb_program_shader.c | 15 +++++++++------
 dlls/wined3d/context.c            |  1 +
 dlls/wined3d/device.c             |  1 -
 dlls/wined3d/directx.c            |  4 ++++
 dlls/wined3d/state.c              | 12 +++++++-----
 dlls/wined3d/utils.c              |  2 +-
 dlls/wined3d/wined3d_private.h    |  5 ++++-
 7 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 6683829..83af0e1 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -4291,7 +4291,8 @@ static struct arb_ps_compiled_shader *find_arb_pshader(struct wined3d_shader *sh
         const struct arb_ps_compile_args *args)
 {
     struct wined3d_device *device = shader->device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_adapter *adapter = device->adapter;
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
     UINT i;
     DWORD new_size;
     struct arb_ps_compiled_shader *new_array;
@@ -4314,7 +4315,7 @@ static struct arb_ps_compiled_shader *find_arb_pshader(struct wined3d_shader *sh
 
         TRACE("Shader got assigned input signature index %u\n", shader_data->input_signature_idx);
 
-        if (!device->vs_clipping)
+        if (!adapter->vs_clipping)
             shader_data->clipplane_emulation = shader_find_free_input_register(&shader->reg_maps,
                     gl_info->limits.texture_stages - 1);
         else
@@ -4473,7 +4474,8 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
         const struct wined3d_shader *shader, struct arb_ps_compile_args *args)
 {
     struct wined3d_device *device = shader->device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_adapter *adapter = device->adapter;
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
     int i;
     WORD int_skip;
 
@@ -4492,7 +4494,7 @@ static void find_arb_ps_compile_args(const struct wined3d_state *state,
      * is quite expensive because it forces the driver to disable early Z discards. It is cheaper to
      * duplicate the shader than have a no-op KIL instruction in every shader
      */
-    if (!device->vs_clipping && use_vs(state)
+    if (!adapter->vs_clipping && use_vs(state)
             && state->render_states[WINED3D_RS_CLIPPING]
             && state->render_states[WINED3D_RS_CLIPPLANEENABLE])
         args->clip = 1;
@@ -4528,7 +4530,8 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
         const struct wined3d_shader *shader, struct arb_vs_compile_args *args)
 {
     struct wined3d_device *device = shader->device;
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    const struct wined3d_adapter *adapter = device->adapter;
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
     int i;
     WORD int_skip;
 
@@ -4546,7 +4549,7 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
     else
     {
         args->ps_signature = ~0;
-        if (!device->vs_clipping && device->adapter->fragment_pipe == &arbfp_fragment_pipeline)
+        if (!adapter->vs_clipping && adapter->fragment_pipe == &arbfp_fragment_pipeline)
         {
             args->clip.boolclip.clip_texcoord = ffp_clip_emul(state) ? gl_info->limits.texture_stages : 0;
         }
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 516e8c2..58827e2 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1398,6 +1398,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
 
     ret->gl_info = gl_info;
     ret->state_table = device->StateTable;
+    ret->adapter = device->adapter;
 
     /* Mark all states dirty to force a proper initialization of the states
      * on the first use of the context. */
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 32029c8..08309fe 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -5447,7 +5447,6 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
     device->ps_version = shader_caps.ps_version;
     device->d3d_vshader_constantF = shader_caps.vs_uniform_count;
     device->d3d_pshader_constantF = shader_caps.ps_uniform_count;
-    device->vs_clipping = shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING;
 
     fragment_pipeline = adapter->fragment_pipe;
     fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index b9640f9..47ef8d2 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2594,6 +2594,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     struct wined3d_gl_info *gl_info = &adapter->gl_info;
     enum wined3d_pci_vendor card_vendor;
     struct fragment_caps fragment_caps;
+    struct shader_caps shader_caps;
     const char *WGL_Extensions = NULL;
     const char *GL_Extensions = NULL;
     enum wined3d_gl_vendor gl_vendor;
@@ -2802,6 +2803,9 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     adapter->fragment_pipe = select_fragment_implementation(gl_info, adapter->shader_backend);
     adapter->blitter = select_blit_implementation(gl_info, adapter->shader_backend);
 
+    adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
+    adapter->vs_clipping = shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING;
+
     adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
     gl_info->limits.texture_stages = fragment_caps.MaxTextureBlendStages;
     TRACE("Max texture stages: %u.\n", gl_info->limits.texture_stages);
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 88426a2..bc03067 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -610,9 +610,7 @@ static void state_clipping(struct wined3d_context *context, const struct wined3d
 
     if (use_vs(state))
     {
-        const struct wined3d_device *device = context->swapchain->device;
-
-        if (!device->vs_clipping)
+        if (!context->adapter->vs_clipping)
         {
             /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
              * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
@@ -4620,8 +4618,11 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
         {
             updateFog = TRUE;
 
-            if (!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE)))
+            if (!context->adapter->vs_clipping
+                    && !isStateDirty(context, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE)))
+            {
                 state_clipping(context, state, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE));
+            }
 
             for (i = 0; i < gl_info->limits.clipplanes; ++i)
             {
@@ -4635,7 +4636,8 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine
     {
         if(!context->last_was_vshader) {
             static BOOL warned = FALSE;
-            if(!device->vs_clipping) {
+            if (!context->adapter->vs_clipping)
+            {
                 /* Disable all clip planes to get defined results on all drivers. See comment in the
                  * state_clipping state handler
                  */
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 92ae892..86b7fa6 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -3226,7 +3226,7 @@ void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_s
     } else {
         settings->sRGB_write = 0;
     }
-    if (device->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
+    if (device->adapter->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
             || !state->render_states[WINED3D_RS_CLIPPLANEENABLE])
     {
         /* No need to emulate clipplanes if GL supports native vertex shader clipping or if
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 5c183ca..c799635 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1067,6 +1067,7 @@ struct wined3d_context
 {
     const struct wined3d_gl_info *gl_info;
     const struct StateEntry *state_table;
+    const struct wined3d_adapter *adapter;
     /* State dirtification
      * dirtyArray is an array that contains markers for dirty states. numDirtyEntries states are dirty, their numbers are in indices
      * 0...numDirtyEntries - 1. isStateDirty is a redundant copy of the dirtyArray. Technically only one of them would be needed,
@@ -1588,6 +1589,9 @@ struct wined3d_adapter
     const struct fragment_pipeline *fragment_pipe;
     const struct wined3d_shader_backend_ops *shader_backend;
     const struct blit_shader *blitter;
+
+    /* Cached backend limits */
+    DWORD vs_clipping;
 };
 
 BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter) DECLSPEC_HIDDEN;
@@ -1705,7 +1709,6 @@ struct wined3d_device
     unsigned int max_ffp_textures;
     UINT vs_version, gs_version, ps_version;
     DWORD d3d_vshader_constantF, d3d_pshader_constantF; /* Advertised d3d caps, not GL ones */
-    DWORD vs_clipping;
     UINT instance_count;
 
     WORD vertexBlendUsed : 1;           /* To avoid needless setting of the blend matrices */
-- 
1.8.1.5




More information about the wine-patches mailing list