wined3d: Make the number of floating point shader constants dynamic (Take 3)

Jason Green jave27 at gmail.com
Tue Jul 18 23:06:07 CDT 2006


-------------- next part --------------
From nobody Mon Sep 17 00:00:00 2001
From: Jason <jason at jave02.(none)>
Date: Tue, 18 Jul 2006 21:22:57 -0400
Subject: [PATCH] Make the number of shader float constants dynamic

- Affects both ARB and GLSL shaders
- Pull the number of available constants from GL and report that to the app (minus a few - see source comments)
- Dynamically allocate the space needed on the stateblock for the constants and their set/changed flags
- Remove hack for MESA drivers

---

 dlls/wined3d/arb_program_shader.c |   16 ++++---
 dlls/wined3d/device.c             |   55 ++++++++++++++---------
 dlls/wined3d/directx.c            |   56 +++++++++++++++++------
 dlls/wined3d/glsl_shader.c        |   16 ++++---
 dlls/wined3d/pixelshader.c        |    4 +-
 dlls/wined3d/stateblock.c         |   90 ++++++++++++++++++++++++++++++-------
 dlls/wined3d/vertexdeclaration.c  |    3 +
 dlls/wined3d/vertexshader.c       |    6 +-
 dlls/wined3d/wined3d_private.h    |   36 ++++++++-------
 include/wine/wined3d_gl.h         |    8 +++
 10 files changed, 205 insertions(+), 85 deletions(-)

f316d03f4a11be4db96251d74926ada653323981
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index ba95de3..ee56e9c 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -108,13 +108,13 @@ void shader_arb_load_constants(
         if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
             /* Load DirectX 8 float constants for vertex shader */
             shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
-                                       WINED3D_VSHADER_MAX_CONSTANTS,
+                                       GL_LIMITS(vshader_constantsF),
                                        vertexDeclaration->constants, NULL);
         }
 
         /* Load DirectX 9 float constants for vertex shader */
         shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
-                                   WINED3D_VSHADER_MAX_CONSTANTS,
+                                   GL_LIMITS(vshader_constantsF),
                                    stateBlock->vertexShaderConstantF,
                                    stateBlock->set.vertexShaderConstantsF);
     }
@@ -124,7 +124,8 @@ void shader_arb_load_constants(
         IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
 
         /* Load DirectX 9 float constants for pixel shader */
-        shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, WINED3D_PSHADER_MAX_CONSTANTS,
+        shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, 
+                                   GL_LIMITS(pshader_constantsF),
                                    stateBlock->pixelShaderConstantF,
                                    stateBlock->set.pixelShaderConstantsF);
     }
@@ -134,10 +135,14 @@ void shader_arb_load_constants(
 void shader_generate_arb_declarations(
     IWineD3DBaseShader *iface,
     shader_reg_maps* reg_maps,
-    SHADER_BUFFER* buffer) {
+    SHADER_BUFFER* buffer,
+    WineD3D_GL_Info* gl_info) {
 
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     DWORD i;
+    char pshader = shader_is_pshader_version(This->baseShader.hex_version);
+    unsigned max_constantsF = min(This->baseShader.limits.constant_float, 
+            (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
 
     for(i = 0; i < This->baseShader.limits.temporary; i++) {
         if (reg_maps->temporary[i])
@@ -162,8 +167,7 @@ void shader_generate_arb_declarations(
 
     /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
     shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
-                   This->baseShader.limits.constant_float,
-                   This->baseShader.limits.constant_float - 1);
+                   max_constantsF, max_constantsF - 1);
 }
 
 static const char* shift_tab[] = {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 820935d..776e626 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -775,6 +775,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DStateBlockImpl *object;
     int i, j;
+    HRESULT temp_result;
 
     D3DCREATEOBJECTINSTANCE(object, StateBlock)
     object->blockType     = Type;
@@ -786,6 +787,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl
            be freed due to circular dependencies                                   */
         return WINED3D_OK;
     }
+    
+    temp_result = allocate_shader_constants(object);
+    if (WINED3D_OK != temp_result)
+        return temp_result;
 
     /* Otherwise, might as well set the whole state block to the appropriate values  */
     if ( This->stateBlock != NULL) {
@@ -813,11 +818,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         object->changed.pixelShader = TRUE;
 
         /* Pixel Shader Constants */
-        for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
+        for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
             object->changed.pixelShaderConstantsF[i] = TRUE;
+        for (i = 0; i < MAX_CONST_B; ++i)
             object->changed.pixelShaderConstantsB[i] = TRUE;
+        for (i = 0; i < MAX_CONST_I; ++i)
             object->changed.pixelShaderConstantsI[i] = TRUE;
-        }
+        
         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
         }
@@ -841,11 +848,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         object->changed.vertexShader = TRUE;
 
         /* Vertex Shader Constants */
-        for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
+        for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
             object->changed.vertexShaderConstantsF[i] = TRUE;
+        for (i = 0; i < MAX_CONST_B; ++i)
             object->changed.vertexShaderConstantsB[i] = TRUE;
+        for (i = 0; i < MAX_CONST_I; ++i)
             object->changed.vertexShaderConstantsI[i] = TRUE;
-        }
+ 
         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
         }
@@ -4606,7 +4615,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int i, cnt = min(count, MAX_VSHADER_CONSTANTS - start);
+    int i, cnt = min(count, MAX_CONST_B - start);
 
     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
             iface, srcData, start, count);
@@ -4633,7 +4642,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int cnt = min(count, MAX_VSHADER_CONSTANTS - start);
+    int cnt = min(count, MAX_CONST_B - start);
 
     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
             iface, dstData, start, count);
@@ -4652,7 +4661,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int i, cnt = min(count, MAX_VSHADER_CONSTANTS - start);
+    int i, cnt = min(count, MAX_CONST_I - start);
 
     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
             iface, srcData, start, count);
@@ -4680,7 +4689,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int cnt = min(count, MAX_VSHADER_CONSTANTS - start);
+    int cnt = min(count, MAX_CONST_I - start);
 
     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
             iface, dstData, start, count);
@@ -4699,7 +4708,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int i, cnt = min(count, MAX_VSHADER_CONSTANTS - start);
+    int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
 
     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
             iface, srcData, start, count);
@@ -4727,7 +4736,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int cnt = min(count, MAX_VSHADER_CONSTANTS - start);
+    int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
 
     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
             iface, dstData, start, count);
@@ -4788,7 +4797,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int i, cnt = min(count, MAX_PSHADER_CONSTANTS - start);
+    int i, cnt = min(count, MAX_CONST_B - start);
 
     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
             iface, srcData, start, count);
@@ -4798,7 +4807,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
     for (i = 0; i < cnt; i++)
-        TRACE("Set BOOL constant %u to %s\n", i, srcData[i]? "true":"false");
+        TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
 
     for (i = start; i < cnt + start; ++i) {
         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
@@ -4815,7 +4824,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int cnt = min(count, MAX_PSHADER_CONSTANTS - start);
+    int cnt = min(count, MAX_CONST_B - start);
 
     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
             iface, dstData, start, count);
@@ -4834,7 +4843,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int i, cnt = min(count, MAX_PSHADER_CONSTANTS - start);
+    int i, cnt = min(count, MAX_CONST_I - start);
 
     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
             iface, srcData, start, count);
@@ -4844,7 +4853,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
     for (i = 0; i < cnt; i++)
-        TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", i,
+        TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
 
     for (i = start; i < cnt + start; ++i) {
@@ -4862,7 +4871,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int cnt = min(count, MAX_PSHADER_CONSTANTS - start);
+    int cnt = min(count, MAX_CONST_I - start);
 
     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
             iface, dstData, start, count);
@@ -4881,7 +4890,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int i, cnt = min(count, MAX_PSHADER_CONSTANTS - start);
+    int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
 
     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
             iface, srcData, start, count);
@@ -4891,7 +4900,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
     for (i = 0; i < cnt; i++)
-        TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", i,
+        TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
 
     for (i = start; i < cnt + start; ++i) {
@@ -4909,7 +4918,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     UINT count) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-    int cnt = min(count, MAX_PSHADER_CONSTANTS - start);
+    int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
 
     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
             iface, dstData, start, count);
@@ -5746,6 +5755,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DStateBlockImpl *object;
+    HRESULT temp_result;
+    
     TRACE("(%p)", This);
     
     if (This->isRecordingState) {
@@ -5757,13 +5768,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         FIXME("(%p)Error allocating memory for stateblock\n", This);
         return E_OUTOFMEMORY;
     }
-    TRACE("(%p) creted object %p\n", This, object);
+    TRACE("(%p) created object %p\n", This, object);
     object->wineD3DDevice= This;
     /** FIXME: object->parent       = parent; **/
     object->parent       = NULL;
     object->blockType    = WINED3DSBT_ALL;
     object->ref          = 1;
     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
+    
+    temp_result = allocate_shader_constants(object);
+    if (WINED3D_OK != temp_result)
+        return temp_result;
 
     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
     This->updateStateBlock = object;
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index dea1cef..f757265 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -208,32 +208,45 @@ static void select_shader_mode(
     int* ps_selected,
     int* vs_selected) {
 
+    /* Default # of constants to 0 */
+    gl_info->max_vshader_constantsF = 0;
+    gl_info->max_pshader_constantsF = 0;
+
     /* Give priority to user disable/emulation request.
      * Then respect REF device for software.
      * Then check capabilities for hardware, and fallback to software */
 
-    if (wined3d_settings.vs_mode == VS_NONE)
+    if (wined3d_settings.vs_mode == VS_NONE) {
         *vs_selected = SHADER_NONE;
-    else if (DeviceType == WINED3DDEVTYPE_REF || wined3d_settings.vs_mode == VS_SW)
+    } else if (DeviceType == WINED3DDEVTYPE_REF || wined3d_settings.vs_mode == VS_SW) {
         *vs_selected = SHADER_SW;
-    else if (gl_info->supported[ARB_SHADING_LANGUAGE_100] && wined3d_settings.glslRequested)
+    } else if (gl_info->supported[ARB_SHADING_LANGUAGE_100] && wined3d_settings.glslRequested) {
         *vs_selected = SHADER_GLSL;
-    else if (gl_info->supported[ARB_VERTEX_PROGRAM])
+        /* Subtract the other potential uniforms from the max available (bools & ints) */
+        gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
+    } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
         *vs_selected = SHADER_ARB;
-    else
+        /* ARB shaders seem to have an implicit PARAM when fog is used, so we need to subtract 1 from the total available */
+        gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 1;
+    } else {
         *vs_selected = SHADER_SW;
+    }
 
     /* Fallback to SHADER_NONE where software pixel shaders should be used */
-    if (wined3d_settings.ps_mode == PS_NONE)
+    if (wined3d_settings.ps_mode == PS_NONE) {
         *ps_selected = SHADER_NONE;
-    else if (DeviceType == WINED3DDEVTYPE_REF)
+    } else if (DeviceType == WINED3DDEVTYPE_REF) {
         *ps_selected = SHADER_NONE;
-    else if (gl_info->supported[ARB_SHADING_LANGUAGE_100] && wined3d_settings.glslRequested)
+    } else if (gl_info->supported[ARB_SHADING_LANGUAGE_100] && wined3d_settings.glslRequested) {
         *ps_selected = SHADER_GLSL;
-    else if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        /* 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;
+    } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
         *ps_selected = SHADER_ARB;
-    else
+        gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
+    } else {
         *ps_selected = SHADER_NONE;
+    }
 }
 
 /**********************************************************
@@ -528,12 +541,21 @@ #undef USE_GL_FUNC
                 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
                 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
                 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
+                glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max);
+                TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
+                gl_info->ps_arb_constantsF = gl_max;
             } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
                 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
                 gl_info->supported[ARB_IMAGING] = TRUE;
             } else if (strcmp(ThisExtn, "GL_ARB_shading_language_100") == 0) {
                 TRACE_(d3d_caps)(" FOUND: GL Shading Language v100 support\n");
                 gl_info->supported[ARB_SHADING_LANGUAGE_100] = TRUE;
+                glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
+                TRACE_(d3d_caps)(" FOUND: GL Shading Language support - max float vs constants=%u\n", gl_max);
+                gl_info->vs_glsl_constantsF = gl_max;
+                glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
+                TRACE_(d3d_caps)(" FOUND: GL Shading Language support - max float ps constants=%u\n", gl_max);
+                gl_info->ps_glsl_constantsF = gl_max;
             } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
                 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
                 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
@@ -580,6 +602,9 @@ #undef USE_GL_FUNC
                 gl_info->vs_arb_version = VS_VERSION_11;
                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
                 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
+                glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max);
+                TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
+                gl_info->vs_arb_constantsF = gl_max;
             } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
                 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
                 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
@@ -1765,11 +1790,7 @@ #endif
         TRACE_(d3d_caps)("Vertex shader functionality not available\n");
     }
 
-    if (This->gl_info.gl_vendor == VENDOR_MESA || This->gl_info.gl_vendor == VENDOR_WINE) {
-        *pCaps->MaxVertexShaderConst = 95;
-    } else {
-        *pCaps->MaxVertexShaderConst = WINED3D_VSHADER_MAX_CONSTANTS;
-    }
+    *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
 
     /* FIXME: the shader ode should be per adapter */
     if (wined3d_settings.ps_selected_mode == SHADER_GLSL) {
@@ -1839,6 +1860,7 @@ static HRESULT  WINAPI IWineD3DImpl_Crea
     IWineD3DDeviceImpl *object  = NULL;
     IWineD3DImpl       *This    = (IWineD3DImpl *)iface;
     HDC hDC;
+    HRESULT temp_result;
 
     /* Validate the adapter number */
     if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
@@ -1898,6 +1920,10 @@ static HRESULT  WINAPI IWineD3DImpl_Crea
     select_shader_mode(&This->gl_info, DeviceType,
         &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
 
+    temp_result = allocate_shader_constants(object->updateStateBlock);
+    if (WINED3D_OK != temp_result)
+        return temp_result;
+
     /* set the state of the device to valid */
     object->state = WINED3D_OK;
 
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 23f944c..ea99f49 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -274,12 +274,12 @@ void shader_glsl_load_constants(
 
         if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
             /* Load DirectX 8 float constants/uniforms for vertex shader */
-            shader_glsl_load_constantsF(vshader, gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
+            shader_glsl_load_constantsF(vshader, gl_info, programId, GL_LIMITS(vshader_constantsF),
                                         vertexDeclaration->constants, NULL);
         }
 
         /* Load DirectX 9 float constants/uniforms for vertex shader */
-        shader_glsl_load_constantsF(vshader, gl_info, programId, WINED3D_VSHADER_MAX_CONSTANTS,
+        shader_glsl_load_constantsF(vshader, gl_info, programId, GL_LIMITS(vshader_constantsF),
                                     stateBlock->vertexShaderConstantF, 
                                     stateBlock->set.vertexShaderConstantsF);
 
@@ -302,7 +302,7 @@ void shader_glsl_load_constants(
         shader_glsl_load_psamplers(gl_info, iface);
 
         /* Load DirectX 9 float constants/uniforms for pixel shader */
-        shader_glsl_load_constantsF(pshader, gl_info, programId, WINED3D_PSHADER_MAX_CONSTANTS,
+        shader_glsl_load_constantsF(pshader, gl_info, programId, GL_LIMITS(pshader_constantsF),
                                     stateBlock->pixelShaderConstantF,
                                     stateBlock->set.pixelShaderConstantsF);
 
@@ -322,7 +322,8 @@ void shader_glsl_load_constants(
 void shader_generate_glsl_declarations(
     IWineD3DBaseShader *iface,
     shader_reg_maps* reg_maps,
-    SHADER_BUFFER* buffer) {
+    SHADER_BUFFER* buffer,
+    WineD3D_GL_Info* gl_info) {
 
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     int i;
@@ -338,8 +339,11 @@ void shader_generate_glsl_declarations(
     }
 
     /* Declare the constants (aka uniforms) */
-    if (This->baseShader.limits.constant_float > 0)
-        shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, This->baseShader.limits.constant_float);
+    if (This->baseShader.limits.constant_float > 0) {
+        unsigned max_constantsF = min(This->baseShader.limits.constant_float, 
+                (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
+        shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, max_constantsF);
+    }
 
     if (This->baseShader.limits.constant_int > 0)
         shader_addline(buffer, "uniform ivec4 %cI[%u];\n", prefix, This->baseShader.limits.constant_int);
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 8f4b273..a1c8bf0 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -843,7 +843,7 @@ #endif
         GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
 
         /* Base Declarations */
-        shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer);
+        shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
 
         /* Pack 3.0 inputs */
         if (This->baseShader.hex_version >= D3DPS_VERSION(3,0))
@@ -879,7 +879,7 @@ #endif
         shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
 
         /* Base Declarations */
-        shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer);
+        shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
 
         /* Base Shader Body */
         shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 5d26682..d23d782 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -26,6 +26,38 @@ #include "wined3d_private.h"
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
 
+/***************************************
+ * Stateblock helper functions follow
+ **************************************/
+
+/** Allocates the correct amount of space for pixel and vertex shader constants, 
+ * along with their set/changed flags on the given stateblock object
+ */
+HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object) {
+    
+    IWineD3DStateBlockImpl *This = object;
+
+#define WINED3D_MEMCHECK(_object) if (NULL == _object) { FIXME("Out of memory!\n"); return E_OUTOFMEMORY; }
+
+    /* Allocate space for floating point constants */
+    object->pixelShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
+    WINED3D_MEMCHECK(object->pixelShaderConstantF);
+    object->set.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(pshader_constantsF) );
+    WINED3D_MEMCHECK(object->set.pixelShaderConstantsF);
+    object->changed.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(pshader_constantsF));
+    WINED3D_MEMCHECK(object->changed.pixelShaderConstantsF);
+    object->vertexShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
+    WINED3D_MEMCHECK(object->vertexShaderConstantF);
+    object->set.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(vshader_constantsF));
+    WINED3D_MEMCHECK(object->set.vertexShaderConstantsF);
+    object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(vshader_constantsF));
+    WINED3D_MEMCHECK(object->changed.vertexShaderConstantsF);
+
+#undef WINED3D_MEMCHECK
+
+    return WINED3D_OK;
+}
+
 /**********************************************************
  * IWineD3DStateBlockImpl IUnknown parts follows
  **********************************************************/
@@ -88,7 +120,14 @@ static ULONG  WINAPI IWineD3DStateBlockI
             if (NULL != This->vertexDecl) {
                 IWineD3DVertexDeclaration_Release(This->vertexDecl);
             }
-
+            
+            HeapFree(GetProcessHeap(), 0, This->vertexShaderConstantF);
+            HeapFree(GetProcessHeap(), 0, This->set.vertexShaderConstantsF);
+            HeapFree(GetProcessHeap(), 0, This->changed.vertexShaderConstantsF);
+            HeapFree(GetProcessHeap(), 0, This->pixelShaderConstantF);
+            HeapFree(GetProcessHeap(), 0, This->set.pixelShaderConstantsF);
+            HeapFree(GetProcessHeap(), 0, This->changed.pixelShaderConstantsF);
+ 
             /* NOTE: according to MSDN: The application is responsible for making sure the texture references are cleared down */
             for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
                 if (This->textures[counter]) {
@@ -166,9 +205,8 @@ static HRESULT  WINAPI IWineD3DStateBloc
             This->vertexShader = targetStateBlock->vertexShader;
         }
 
-        /* Vertex Shader Constants */
-        for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
-
+        /* Vertex Shader Float Constants */
+        for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
             if (This->set.vertexShaderConstantsF[i]) {
                 TRACE("Setting %p from %p %d to { %f, %f, %f, %f }\n", This, targetStateBlock, i,
                     targetStateBlock->vertexShaderConstantF[i * 4],
@@ -181,7 +219,10 @@ static HRESULT  WINAPI IWineD3DStateBloc
                 This->vertexShaderConstantF[i * 4 + 2]  = targetStateBlock->vertexShaderConstantF[i * 4 + 2];
                 This->vertexShaderConstantF[i * 4 + 3]  = targetStateBlock->vertexShaderConstantF[i * 4 + 3];
             }
-
+        }
+        
+        /* Vertex Shader Integer Constants */
+        for (i = 0; i < MAX_CONST_I; ++i) {
             if (This->set.vertexShaderConstantsI[i]) {
                 TRACE("Setting %p from %p %d to { %d, %d, %d, %d }\n", This, targetStateBlock, i,
                     targetStateBlock->vertexShaderConstantI[i * 4],
@@ -194,7 +235,10 @@ static HRESULT  WINAPI IWineD3DStateBloc
                 This->vertexShaderConstantI[i * 4 + 2]  = targetStateBlock->vertexShaderConstantI[i * 4 + 2];
                 This->vertexShaderConstantI[i * 4 + 3]  = targetStateBlock->vertexShaderConstantI[i * 4 + 3];
             }
-
+        }
+        
+        /* Vertex Shader Boolean Constants */
+        for (i = 0; i < MAX_CONST_B; ++i) {
             if (This->set.vertexShaderConstantsB[i]) {
                 TRACE("Setting %p from %p %d to %s\n", This, targetStateBlock, i,
                     targetStateBlock->vertexShaderConstantB[i]? "TRUE":"FALSE");
@@ -202,7 +246,7 @@ static HRESULT  WINAPI IWineD3DStateBloc
                 This->vertexShaderConstantB[i] =  targetStateBlock->vertexShaderConstantB[i];
             }
         }
-
+        
         /* Lights... For a recorded state block, we just had a chain of actions to perform,
              so we need to walk that chain and update any actions which differ */
         src = This->lights;
@@ -249,8 +293,8 @@ static HRESULT  WINAPI IWineD3DStateBloc
             This->pixelShader = targetStateBlock->pixelShader;
         }
 
-        for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
-
+        /* Pixel Shader Float Constants */
+        for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
             if (This->set.pixelShaderConstantsF[i]) {
                 TRACE("Setting %p from %p %d to { %f, %f, %f, %f }\n", This, targetStateBlock, i,
                     targetStateBlock->pixelShaderConstantF[i * 4],
@@ -263,7 +307,10 @@ static HRESULT  WINAPI IWineD3DStateBloc
                 This->pixelShaderConstantF[i * 4 + 2]  = targetStateBlock->pixelShaderConstantF[i * 4 + 2];
                 This->pixelShaderConstantF[i * 4 + 3]  = targetStateBlock->pixelShaderConstantF[i * 4 + 3];
             }
-
+        }
+        
+        /* Pixel Shader Integer Constants */
+        for (i = 0; i < MAX_CONST_I; ++i) {
             if (This->set.pixelShaderConstantsI[i]) {
                 TRACE("Setting %p from %p %d to { %d, %d, %d, %d }\n", This, targetStateBlock, i,
                     targetStateBlock->pixelShaderConstantI[i * 4],
@@ -276,7 +323,10 @@ static HRESULT  WINAPI IWineD3DStateBloc
                 This->pixelShaderConstantI[i * 4 + 2]  = targetStateBlock->pixelShaderConstantI[i * 4 + 2];
                 This->pixelShaderConstantI[i * 4 + 3]  = targetStateBlock->pixelShaderConstantI[i * 4 + 3];
             }
-
+        }
+        
+        /* Pixel Shader Boolean Constants */
+        for (i = 0; i < MAX_CONST_B; ++i) {
             if (This->set.pixelShaderConstantsB[i]) {
                 TRACE("Setting %p from %p %d to %s\n", This, targetStateBlock, i,
                     targetStateBlock->pixelShaderConstantB[i]? "TRUE":"FALSE");
@@ -442,13 +492,17 @@ should really perform a delta so that on
         }
 
         /* Vertex Shader Constants */
-        for (i = 0; i < MAX_VSHADER_CONSTANTS; ++i) {
+        for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
             if (This->set.vertexShaderConstantsF[i] && This->changed.vertexShaderConstantsF[i])
                 IWineD3DDevice_SetVertexShaderConstantF(pDevice, i, This->vertexShaderConstantF + i * 4, 1);
-
+        }
+        
+        for (i = 0; i < MAX_CONST_I; i++) {
             if (This->set.vertexShaderConstantsI[i] && This->changed.vertexShaderConstantsI[i])
                 IWineD3DDevice_SetVertexShaderConstantI(pDevice, i, This->vertexShaderConstantI + i * 4, 1);
-
+        }
+        
+        for (i = 0; i < MAX_CONST_B; i++) {
             if (This->set.vertexShaderConstantsB[i] && This->changed.vertexShaderConstantsB[i])
                 IWineD3DDevice_SetVertexShaderConstantB(pDevice, i, This->vertexShaderConstantB + i, 1);
         }
@@ -462,13 +516,17 @@ should really perform a delta so that on
         }
 
         /* Pixel Shader Constants */
-        for (i = 0; i < MAX_PSHADER_CONSTANTS; ++i) {
+        for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
             if (This->set.pixelShaderConstantsF[i] && This->changed.pixelShaderConstantsF[i])
                 IWineD3DDevice_SetPixelShaderConstantF(pDevice, i, This->pixelShaderConstantF + i * 4, 1);
+        }
 
+        for (i = 0; i < MAX_CONST_I; ++i) {
             if (This->set.pixelShaderConstantsI[i] && This->changed.pixelShaderConstantsI[i])
                 IWineD3DDevice_SetPixelShaderConstantI(pDevice, i, This->pixelShaderConstantI + i * 4, 1);
-
+        }
+        
+        for (i = 0; i < MAX_CONST_B; ++i) {
             if (This->set.pixelShaderConstantsB[i] && This->changed.pixelShaderConstantsB[i])
                 IWineD3DDevice_SetPixelShaderConstantB(pDevice, i, This->pixelShaderConstantB + i, 1);
         }
diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c
index 8ec4555..8045745 100644
--- a/dlls/wined3d/vertexdeclaration.c
+++ b/dlls/wined3d/vertexdeclaration.c
@@ -308,7 +308,8 @@ #define MAKE_LOOKUP(_reg,_usage,_usagein
             DWORD count        = ((token & D3DVSD_CONSTCOUNTMASK)   >> D3DVSD_CONSTCOUNTSHIFT);
             DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT);
             if (This->constants == NULL ) {
-                This->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_VSHADER_CONSTANTS * 4 * sizeof(float));
+                This->constants = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+                        ((IWineD3DImpl*)This->wineD3DDevice->wineD3D)->gl_info.max_vshader_constantsF * 4 * sizeof(float));
             }
             TRACE(" 0x%08lx CONST(%lu, %lu)\n", token, constaddress, count);
             for (i = 0; i < count; ++i) {
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 2cd98c0..84f90f5 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -567,7 +567,7 @@ static void vshader_set_limits(
       This->baseShader.limits.packed_input = 0;
 
       /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
-      This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
+      This->baseShader.limits.constant_float = GL_LIMITS(vshader_constantsF);
 
       switch (This->baseShader.hex_version) {
           case D3DVS_VERSION(1,0):
@@ -704,7 +704,7 @@ #endif
         GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
 
         /* Base Declarations */
-        shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer);
+        shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
 
         /* Base Shader Body */
         shader_generate_main( (IWineD3DBaseShader*) This, &buffer, reg_maps, pFunction);
@@ -740,7 +740,7 @@ #endif
                 min(95, This->baseShader.limits.constant_float);
 
         /* Base Declarations */
-        shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer);
+        shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
 
         if (reg_maps->fog) {
             This->usesFog = 1;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9e83ddd..fc2fc4a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -53,8 +53,8 @@ #define MAX_ACTIVE_LIGHTS 8
 #define MAX_CLIPPLANES    D3DMAXUSERCLIPPLANES
 #define MAX_LEVELS        256
 
-#define MAX_VSHADER_CONSTANTS 96
-#define MAX_PSHADER_CONSTANTS 32
+#define MAX_CONST_I 16
+#define MAX_CONST_B 16
 
 /* Used for CreateStateBlock */
 #define NUM_SAVEDPIXELSTATES_R     35
@@ -1021,13 +1021,13 @@ typedef struct SAVEDSTATES {
         BOOL                      clipplane[MAX_CLIPPLANES];
         BOOL                      vertexDecl;
         BOOL                      pixelShader;
-        BOOL                      pixelShaderConstantsB[MAX_PSHADER_CONSTANTS];
-        BOOL                      pixelShaderConstantsI[MAX_PSHADER_CONSTANTS];
-        BOOL                      pixelShaderConstantsF[MAX_PSHADER_CONSTANTS];
+        BOOL                      pixelShaderConstantsB[MAX_CONST_B];
+        BOOL                      pixelShaderConstantsI[MAX_CONST_I];
+        BOOL                     *pixelShaderConstantsF;
         BOOL                      vertexShader;
-        BOOL                      vertexShaderConstantsB[MAX_VSHADER_CONSTANTS];
-        BOOL                      vertexShaderConstantsI[MAX_VSHADER_CONSTANTS];
-        BOOL                      vertexShaderConstantsF[MAX_VSHADER_CONSTANTS];
+        BOOL                      vertexShaderConstantsB[MAX_CONST_B];
+        BOOL                      vertexShaderConstantsI[MAX_CONST_I];
+        BOOL                     *vertexShaderConstantsF;
 } SAVEDSTATES;
 
 struct IWineD3DStateBlockImpl
@@ -1053,9 +1053,9 @@ struct IWineD3DStateBlockImpl
     IWineD3DVertexShader      *vertexShader;
 
     /* Vertex Shader Constants */
-    BOOL                       vertexShaderConstantB[MAX_VSHADER_CONSTANTS];
-    INT                        vertexShaderConstantI[MAX_VSHADER_CONSTANTS * 4];
-    float                      vertexShaderConstantF[MAX_VSHADER_CONSTANTS * 4];
+    BOOL                       vertexShaderConstantB[MAX_CONST_B];
+    INT                        vertexShaderConstantI[MAX_CONST_I * 4];
+    float                     *vertexShaderConstantF;
 
     /* Stream Source */
     BOOL                      streamIsUP;
@@ -1089,9 +1089,9 @@ struct IWineD3DStateBlockImpl
     IWineD3DPixelShader      *pixelShader;
 
     /* Pixel Shader Constants */
-    BOOL                       pixelShaderConstantB[MAX_PSHADER_CONSTANTS];
-    INT                        pixelShaderConstantI[MAX_PSHADER_CONSTANTS * 4];
-    float                      pixelShaderConstantF[MAX_PSHADER_CONSTANTS * 4];
+    BOOL                       pixelShaderConstantB[MAX_CONST_B];
+    INT                        pixelShaderConstantI[MAX_CONST_I * 4];
+    float                     *pixelShaderConstantF;
 
     /* Indexed Vertex Blending */
     D3DVERTEXBLENDFLAGS       vertex_blend;
@@ -1417,6 +1417,8 @@ extern BOOL vshader_input_is_color(
     IWineD3DVertexShader* iface,
     unsigned int regnum);
 
+extern HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object);
+
 /* ARB_[vertex/fragment]_program helper functions */
 extern void shader_arb_load_constants(
     IWineD3DStateBlock* iface,
@@ -1545,12 +1547,14 @@ extern HRESULT shader_get_registers_used
 extern void shader_generate_glsl_declarations(
     IWineD3DBaseShader *iface,
     shader_reg_maps* reg_maps,
-    SHADER_BUFFER* buffer);
+    SHADER_BUFFER* buffer,
+    WineD3D_GL_Info* gl_info);
 
 extern void shader_generate_arb_declarations(
     IWineD3DBaseShader *iface,
     shader_reg_maps* reg_maps,
-    SHADER_BUFFER* buffer);
+    SHADER_BUFFER* buffer,
+    WineD3D_GL_Info* gl_info);
 
 extern void shader_generate_main(
     IWineD3DBaseShader *iface,
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index c8d9402..9616e73 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -1680,6 +1680,14 @@ typedef struct _WineD3D_GL_Info {
   UINT   max_blends;
   UINT   max_anisotropy;
 
+  unsigned max_vshader_constantsF;
+  unsigned max_pshader_constantsF;
+
+  unsigned vs_arb_constantsF;
+  unsigned ps_arb_constantsF;
+  unsigned vs_glsl_constantsF;
+  unsigned ps_glsl_constantsF;
+
   GL_PSVersion ps_arb_version;
   GL_PSVersion ps_nv_version;
 
-- 
1.3.3


More information about the wine-patches mailing list