[WINED3D] Make the shader mode selections per device

Ivan Gyurdiev ivg231 at gmail.com
Sat Oct 7 22:12:03 CDT 2006


I remember when the modes were added, H. Verbeet asked:
"Why not make them per device now, rather than change them later"

Well, because I wasn't sufficiently smart to realize that then - have 
gotten wiser since.
Actually, probably not... but better late than never :)

It needs to be per device, not per adapter, because flags that control 
the type of shader can be passed into the device constructor. In fact, 
the copy of select_shader_mode() that's ran by CreateDevice should 
probably be a different function than the one called by GetDeviceCaps(), 
and should account for those flags. Offscreen mode selection will be 
added in the future, and it should also be per device (or per adapter).

-------------- next part --------------
---
 dlls/wined3d/device.c          |    8 ++++----
 dlls/wined3d/directx.c         |   39 ++++++++++++++++++++++++---------------
 dlls/wined3d/drawprim.c        |   25 ++++++++++++-------------
 dlls/wined3d/pixelshader.c     |    5 +++--
 dlls/wined3d/vertexshader.c    |    2 +-
 dlls/wined3d/wined3d_main.c    |    2 --
 dlls/wined3d/wined3d_private.h |    6 ++++--
 7 files changed, 48 insertions(+), 39 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 13ea67a..d1ecc14 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -317,7 +317,7 @@ void set_glsl_shader_program(IWineD3DDev
     This->stateBlock->glsl_program = newLink;
    
     /* Attach GLSL vshader */ 
-    if (NULL != vshader && wined3d_settings.vs_selected_mode == SHADER_GLSL) {
+    if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) {
         int i;
         int max_attribs = 16;   /* TODO: Will this always be the case? It is at the moment... */
         char tmp_name[10];
@@ -343,7 +343,7 @@ void set_glsl_shader_program(IWineD3DDev
     }
     
     /* Attach GLSL pshader */
-    if (NULL != pshader && wined3d_settings.ps_selected_mode == SHADER_GLSL) {
+    if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) {
         TRACE("Attaching pixel shader to GLSL program\n");
         attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
         newLink->pixelShader = pshader;
@@ -574,8 +574,8 @@ static ULONG WINAPI IWineD3DDeviceImpl_R
         ** ***************************/
 
         /* Delete any GLSL shader programs that may exist */
-        if (wined3d_settings.vs_selected_mode == SHADER_GLSL ||
-            wined3d_settings.ps_selected_mode == SHADER_GLSL)
+        if (This->vs_selected_mode == SHADER_GLSL ||
+            This->ps_selected_mode == SHADER_GLSL)
             delete_glsl_shader_list(iface);
     
         /* Release the update stateblock */
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index bf2f059..0a1dd49 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -238,9 +238,12 @@ static void select_shader_mode(
 }
 
 /** Select the number of report maximum shader constants based on the selected shader modes */
-void select_shader_max_constants(WineD3D_GL_Info *gl_info) {
+void select_shader_max_constants(
+    int ps_selected_mode,
+    int vs_selected_mode,
+    WineD3D_GL_Info *gl_info) {
 
-    switch (wined3d_settings.vs_selected_mode) {
+    switch (vs_selected_mode) {
         case SHADER_GLSL:
             /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
             gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I - 1;
@@ -259,7 +262,7 @@ void select_shader_max_constants(WineD3D
             break;
     }
 
-    switch (wined3d_settings.ps_selected_mode) {
+    switch (ps_selected_mode) {
         case SHADER_GLSL:
             /* Subtract the other potential uniforms from the max available (bools & ints) */
             gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
@@ -1808,6 +1811,8 @@ static HRESULT  WINAPI IWineD3DImpl_Chec
 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
 
     IWineD3DImpl    *This = (IWineD3DImpl *)iface;
+    int vs_selected_mode;
+    int ps_selected_mode;
 
     TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
 
@@ -1825,9 +1830,11 @@ static HRESULT WINAPI IWineD3DImpl_GetDe
         /* We are running off a real context, save the values */
         if (rc) This->isGLInfoValid = TRUE;
     }
-    select_shader_mode(&This->gl_info, DeviceType,
-        &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
-    select_shader_max_constants(&This->gl_info);
+    select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
+
+    /* This function should *not* be modifying GL caps
+     * TODO: move the functionality where it belongs */
+    select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
 
     /* ------------------------------------------------
        The following fields apply to both d3d8 and d3d9
@@ -2193,7 +2200,7 @@ #endif
     *pCaps->MaxStreamStride     = 1024;
 
     /* FIXME: the shader mode should be per adapter */
-    if (wined3d_settings.vs_selected_mode == SHADER_GLSL) {
+    if (vs_selected_mode == SHADER_GLSL) {
         /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
            models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
            vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
@@ -2203,10 +2210,10 @@ #endif
         else
             *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
         TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
-    } else if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
+    } else if (vs_selected_mode == SHADER_ARB) {
         *pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
         TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
-    } else if (wined3d_settings.vs_selected_mode == SHADER_SW) {
+    } else if (vs_selected_mode == SHADER_SW) {
         *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
         TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
     } else {
@@ -2217,7 +2224,7 @@ #endif
     *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
 
     /* FIXME: the shader mode should be per adapter */
-    if (wined3d_settings.ps_selected_mode == SHADER_GLSL) {
+    if (ps_selected_mode == SHADER_GLSL) {
         /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
            in case of GeforceFX cards. */
         if(This->gl_info.ps_nv_version == PS_VERSION_20)
@@ -2227,12 +2234,12 @@ #endif
         /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
         *pCaps->PixelShader1xMaxValue = 1.0;
         TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
-    } else if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
+    } else if (ps_selected_mode == SHADER_ARB) {
         *pCaps->PixelShaderVersion    = D3DPS_VERSION(1,4);
         *pCaps->PixelShader1xMaxValue = 1.0;
         TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
     /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
-    } else if (wined3d_settings.ps_selected_mode = SHADER_SW) {
+    } else if (ps_selected_mode = SHADER_SW) {
         *pCaps->PixelShaderVersion    = D3DPS_VERSION(3,0);
         *pCaps->PixelShader1xMaxValue = 1.0;
         TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
@@ -2416,9 +2423,11 @@ static HRESULT  WINAPI IWineD3DImpl_Crea
     /* FIXME: both of those should be made per adapter */
     IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
     LEAVE_GL();
-    select_shader_mode(&This->gl_info, DeviceType,
-        &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
-    select_shader_max_constants(&This->gl_info);
+    select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
+
+    /* This function should *not* be modifying GL caps
+     * TODO: move the functionality where it belongs */
+    select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
 
     temp_result = allocate_shader_constants(object->updateStateBlock);
     if (WINED3D_OK != temp_result)
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 95f7692..9511b8c 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1797,15 +1797,14 @@ #undef BUFFER_OR_DATA
     }
     /* If GLSL is used for either pixel or vertex shaders, make a GLSL program 
      * Otherwise set NULL, to restore fixed function */
-    if ((wined3d_settings.vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
-        (wined3d_settings.ps_selected_mode == SHADER_GLSL && usePixelShaderFunction)) 
+    if ((This->vs_selected_mode == SHADER_GLSL && useVertexShaderFunction) ||
+        (This->ps_selected_mode == SHADER_GLSL && usePixelShaderFunction)) 
         set_glsl_shader_program(iface);
     else
         This->stateBlock->glsl_program = NULL;
 
     /* If GLSL is used now, or might have been used before, (re)set the program */
-    if (wined3d_settings.vs_selected_mode == SHADER_GLSL || 
-        wined3d_settings.ps_selected_mode == SHADER_GLSL) {
+    if (This->vs_selected_mode == SHADER_GLSL || This->ps_selected_mode == SHADER_GLSL) {
 
         GLhandleARB progId = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;
         if (progId)
@@ -1818,7 +1817,7 @@ #undef BUFFER_OR_DATA
 
         TRACE("Using vertex shader\n");
 
-        if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
+        if (This->vs_selected_mode == SHADER_ARB) {
             /* Bind the vertex program */
             GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
                 ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
@@ -1836,7 +1835,7 @@ #undef BUFFER_OR_DATA
 
         TRACE("Using pixel shader\n");
 
-        if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
+        if (This->ps_selected_mode == SHADER_ARB) {
              /* Bind the fragment program */
              GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
                  ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
@@ -1848,12 +1847,12 @@ #undef BUFFER_OR_DATA
              TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n",
                  This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
         }
-        }
+    }
        
     /* Load any global constants/uniforms that may have been set by the application */
-    if (wined3d_settings.vs_selected_mode == SHADER_GLSL || wined3d_settings.ps_selected_mode == SHADER_GLSL)
+    if (This->vs_selected_mode == SHADER_GLSL || This->ps_selected_mode == SHADER_GLSL)
         shader_glsl_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction);
-    else if (wined3d_settings.vs_selected_mode== SHADER_ARB || wined3d_settings.ps_selected_mode == SHADER_ARB)
+    else if (This->vs_selected_mode == SHADER_ARB || This->ps_selected_mode == SHADER_ARB)
         shader_arb_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction); 
         
     /* Draw vertex-by-vertex */
@@ -1866,14 +1865,14 @@ #undef BUFFER_OR_DATA
     if (useVertexShaderFunction) {
         unloadNumberedArrays(iface);
 
-        if (wined3d_settings.vs_selected_mode == SHADER_ARB)
+        if (This->vs_selected_mode == SHADER_ARB)
             glDisable(GL_VERTEX_PROGRAM_ARB);
     } else {
         unloadVertexData(iface);
     }
 
     /* Cleanup fragment program */
-    if (usePixelShaderFunction && wined3d_settings.ps_selected_mode == SHADER_ARB) 
+    if (usePixelShaderFunction && This->ps_selected_mode == SHADER_ARB) 
         glDisable(GL_FRAGMENT_PROGRAM_ARB);
 }
 
@@ -2100,11 +2099,11 @@ void drawPrimitive(IWineD3DDevice *iface
 
     /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software - 
      * here simply check whether a shader was set, or the user disabled shaders */
-    if (wined3d_settings.vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader && 
+    if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader && 
         ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function != NULL) 
         useVertexShaderFunction = TRUE;
 
-    if (wined3d_settings.ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
+    if (This->ps_selected_mode != SHADER_NONE && This->stateBlock->pixelShader &&
         ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function) 
         usePixelShaderFunction = TRUE;
 
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 9fc88cf..de4d983 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -870,7 +870,7 @@ #endif
         /* Store the shader object */
         This->baseShader.prgId = shader_obj;
 
-    } else if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
+    } else if (This->baseShader.shader_mode == SHADER_ARB) {
         /*  Create the hw ARB shader */
         shader_addline(&buffer, "!!ARBfp1.0\n");
 
@@ -921,6 +921,7 @@ #endif
 static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
 
     IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
+    IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
 
     TRACE("(%p) : pFunction %p\n", iface, pFunction);
 
@@ -933,7 +934,7 @@ static HRESULT WINAPI IWineD3DPixelShade
     list_init(&This->baseShader.constantsB);
     list_init(&This->baseShader.constantsI);
 
-    This->baseShader.shader_mode = wined3d_settings.ps_selected_mode;
+    This->baseShader.shader_mode = deviceImpl->ps_selected_mode;
 
     TRACE("(%p) : Copying the function\n", This);
     if (NULL != pFunction) {
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index a229248..0ba8d47 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -1207,7 +1207,7 @@ static HRESULT WINAPI IWineD3DVertexShad
        This->semantics_in, This->semantics_out, pFunction, deviceImpl->stateBlock);
     if (hr != WINED3D_OK) return hr;
 
-    This->baseShader.shader_mode = wined3d_settings.vs_selected_mode;
+    This->baseShader.shader_mode = deviceImpl->vs_selected_mode;
 
     /* copy the function ... because it will certainly be released by application */
     if (NULL != pFunction) {
diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c
index 872165a..8a7d631 100644
--- a/dlls/wined3d/wined3d_main.c
+++ b/dlls/wined3d/wined3d_main.c
@@ -40,8 +40,6 @@ wined3d_settings_t wined3d_settings = 
     PS_HW,          /* Hardware by default */
     VBO_HW,         /* Hardware by default */
     FALSE,          /* Use of GLSL disabled by default */
-    SHADER_ARB,     /* Use ARB vertex programs, when available */
-    SHADER_ARB,     /* Use ARB fragment programs, when available */
     NP2_NATIVE,     /* Use native NPOT textures, when available */
     RTL_AUTO,       /* Automatically determine best locking method */
     64*1024*1024    /* 64MB texture memory by default */
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 208ffa4..796c01c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -157,8 +157,6 @@ typedef struct wined3d_settings_s {
     we should use it.  However, until it's fully implemented, we'll leave it as a registry
     setting for developers. */
   BOOL glslRequested;
-  int vs_selected_mode;
-  int ps_selected_mode;
 /* nonpower 2 function */
   int nonpower2_mode;
   int rendertargetlock_mode;
@@ -499,6 +497,10 @@ typedef struct IWineD3DDeviceImpl
     /* X and GL Information */
     GLint                   maxConcurrentLights;
 
+    /* Selected capabilities */
+    int vs_selected_mode;
+    int ps_selected_mode;
+
     /* Optimization */
     BOOL                    modelview_valid;
     BOOL                    proj_valid;
-- 
1.4.2.1



More information about the wine-patches mailing list