diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index ba95de30300..ee56e9ce76b 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 820935d0a4b..776e6260db3 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -775,6 +775,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, 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_CreateStateBlock(IWineD3DDevice* iface, 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_CreateStateBlock(IWineD3DDevice* iface, 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_CreateStateBlock(IWineD3DDevice* iface, 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_SetVertexShaderConstantB( 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_GetVertexShaderConstantB( 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_SetVertexShaderConstantI( 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_GetVertexShaderConstantI( 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_SetVertexShaderConstantF( 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_GetVertexShaderConstantF( 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_SetPixelShaderConstantB( 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_SetPixelShaderConstantB( 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_GetPixelShaderConstantB( 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_SetPixelShaderConstantI( 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_SetPixelShaderConstantI( 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_GetPixelShaderConstantI( 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_SetPixelShaderConstantF( 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_SetPixelShaderConstantF( 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_GetPixelShaderConstantF( 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_GetHWND(IWineD3DDevice *iface, HWND *hW 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_BeginStateBlock(IWineD3DDevice *iface) 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 dea1cefb380..f75726513fc 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 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info, Display* display) { 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 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info, Display* display) { 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 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, 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_CreateDevice(IWineD3D *iface, UINT Adapter, 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_CreateDevice(IWineD3D *iface, UINT Adapter, 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 23f944cf3f7..ea99f4969ff 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 8f4b273f923..a1c8bf088a0 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -843,7 +843,7 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateShader( 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 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateShader( 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 5d266828460..d23d782e666 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -26,6 +26,38 @@ 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 IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) { 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) 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 only the changes get updated*/ } /* 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 only the changes get updated*/ } /* 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 8ec45559c09..80457456e6d 100644 --- a/dlls/wined3d/vertexdeclaration.c +++ b/dlls/wined3d/vertexdeclaration.c @@ -308,7 +308,8 @@ IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface; 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 2cd98c023c9..84f90f5edc3 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 @@ static VOID IWineD3DVertexShaderImpl_GenerateShader( 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 @@ static VOID IWineD3DVertexShaderImpl_GenerateShader( 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 9e83ddd18e5..fc2fc4a84e2 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -53,8 +53,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 c8d94022261..9616e7376c9 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;