wined3d: Deal with reserved shader constants in the backend.

This moves the GLSL and ARB specific reserved constants out of directx.c into
the get_caps methods of the shader backends. That way the number of reserved
constants remains in the backend.

GL_LIMITS({v/p}shader_constantsF) now contains the real number of constants as
advertised by GL instead of some mixture of GL info and backend implementation
specifics. This makes it easier for backends to decide how many constants to
use.
This commit is contained in:
Stefan Dösinger 2009-03-22 12:24:28 +01:00 committed by Alexandre Julliard
parent 0af0bafd6a
commit 754b5cf2ad
5 changed files with 51 additions and 28 deletions

View File

@ -40,10 +40,20 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d);
#define GLINFO_LOCATION (*gl_info)
/* We have to subtract any other PARAMs that we might use in our shader programs.
* ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
* and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
#define ARB_SHADER_RESERVED_VS_CONSTS 3
/* The arb shader only loads the bump mapping environment matrix into the shader if it finds
* a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
*/
#define ARB_SHADER_RESERVED_PS_CONSTS 2
/* Internally used shader constants. Applications can use constants 0 to GL_LIMITS(vshader_constantsF) - 1,
* so upload them above that
*/
#define ARB_SHADER_PRIVCONST_BASE GL_LIMITS(vshader_constantsF)
#define ARB_SHADER_PRIVCONST_BASE (GL_LIMITS(vshader_constantsF) - ARB_SHADER_RESERVED_VS_CONSTS)
#define ARB_SHADER_PRIVCONST_POS ARB_SHADER_PRIVCONST_BASE + 0
/* ARB_program_shader private data */
@ -258,7 +268,8 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh
DWORD i, cur;
char pshader = shader_is_pshader_version(reg_maps->shader_version);
unsigned max_constantsF = min(This->baseShader.limits.constant_float,
(pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
(pshader ? GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS :
GL_LIMITS(vshader_constantsF) - ARB_SHADER_RESERVED_VS_CONSTS));
UINT extra_constants_needed = 0;
const local_constant *lconst;
@ -300,13 +311,13 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh
* the stateblock into the shader. If no constant is available don't load, texbem will then just sample the texture without applying
* bump mapping.
*/
if(max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF)) {
if(max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS) {
ps->bumpenvmatconst[cur].const_num = max_constantsF + extra_constants_needed;
shader_addline(buffer, "PARAM bumpenvmat%d = program.env[%d];\n",
i, ps->bumpenvmatconst[cur].const_num);
extra_constants_needed++;
if(reg_maps->luminanceparams && max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF)) {
if(reg_maps->luminanceparams && max_constantsF + extra_constants_needed < GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS) {
((IWineD3DPixelShaderImpl *)This)->luminanceconst[cur].const_num = max_constantsF + extra_constants_needed;
shader_addline(buffer, "PARAM luminance%d = program.env[%d];\n",
i, ps->luminanceconst[cur].const_num);
@ -2170,13 +2181,14 @@ static void shader_arb_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *g
if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF) - ARB_SHADER_RESERVED_VS_CONSTS;
}
if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
pCaps->PixelShader1xMaxValue = 8.0;
TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
pCaps->MaxPixelShaderConst = GL_LIMITS(pshader_constantsF) - ARB_SHADER_RESERVED_PS_CONSTS;
}
}

View File

@ -4070,7 +4070,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
iface, srcData, start, count);
/* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
if (srcData == NULL || start + count > This->d3d_vshader_constantF || start > This->d3d_vshader_constantF)
return WINED3DERR_INVALIDCALL;
memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
@ -4099,7 +4099,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
int cnt = min(count, This->d3d_vshader_constantF - start);
TRACE("(iface %p, dstData %p, start %d, count %d)\n",
iface, dstData, start, count);
@ -4462,7 +4462,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
iface, srcData, start, count);
/* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
if (srcData == NULL || start + count > This->d3d_pshader_constantF || start > This->d3d_pshader_constantF)
return WINED3DERR_INVALIDCALL;
memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
@ -4491,7 +4491,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
UINT count) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
int cnt = min(count, This->d3d_pshader_constantF - start);
TRACE("(iface %p, dstData %p, start %d, count %d)\n",
iface, dstData, start, count);

View File

@ -424,14 +424,10 @@ static void select_shader_max_constants(
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 / 4) - MAX_CONST_I - 1;
gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
break;
case SHADER_ARB:
/* We have to subtract any other PARAMs that we might use in our shader programs.
* ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
* and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
break;
default:
gl_info->max_vshader_constantsF = 0;
@ -440,18 +436,10 @@ static void select_shader_max_constants(
switch (ps_selected_mode) {
case SHADER_GLSL:
/* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
* In theory the texbem instruction may need one more shader constant too. But lets assume
* that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
* and lets not take away a uniform needlessly from all other shaders.
*/
gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
break;
case SHADER_ARB:
/* The arb shader only loads the bump mapping environment matrix into the shader if it finds
* a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
*/
gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
break;
default:
gl_info->max_pshader_constantsF = 0;
@ -3734,6 +3722,7 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
const struct fragment_pipeline *frag_pipeline = NULL;
int i;
struct fragment_caps ffp_caps;
struct shader_caps shader_caps;
HRESULT hr;
/* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
@ -3789,6 +3778,11 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
&object->ps_selected_mode, &object->vs_selected_mode);
object->shader_backend = select_shader_backend(adapter, DeviceType);
memset(&shader_caps, 0, sizeof(shader_caps));
object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
memset(&ffp_caps, 0, sizeof(ffp_caps));
frag_pipeline = select_fragment_implementation(adapter, DeviceType);
object->frag_pipe = frag_pipeline;

View File

@ -698,8 +698,15 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
/* Declare the constants (aka uniforms) */
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)));
unsigned max_constantsF;
if(pshader) {
max_constantsF = GL_LIMITS(pshader_constantsF) - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
max_constantsF = min(This->baseShader.limits.constant_float, max_constantsF);
} else {
/* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
max_constantsF = GL_LIMITS(vshader_constantsF) - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
max_constantsF = min(This->baseShader.limits.constant_float, max_constantsF);
}
shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, max_constantsF);
}
@ -4118,7 +4125,8 @@ static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *
else
pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (pCaps->VertexShaderVersion >> 8) & 0xff, pCaps->VertexShaderVersion & 0xff);
pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
/* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF) - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
/* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
* In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
@ -4136,6 +4144,13 @@ static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *
else
pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
/* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
* In theory the texbem instruction may need one more shader constant too. But lets assume
* that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
* and lets not take away a uniform needlessly from all other shaders.
*/
pCaps->MaxPixelShaderConst = GL_LIMITS(pshader_constantsF) - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
/* FIXME: The following line is card dependent. -8.0 to 8.0 is the
* Direct3D minimum requirement.
*

View File

@ -487,6 +487,7 @@ struct shader_caps {
DWORD PixelShaderVersion;
float PixelShader1xMaxValue;
DWORD MaxPixelShaderConst;
WINED3DVSHADERCAPS2_0 VS20Caps;
WINED3DPSHADERCAPS2_0 PS20Caps;
@ -1216,6 +1217,7 @@ struct IWineD3DDeviceImpl
const struct blit_shader *blitter;
unsigned int max_ffp_textures, max_ffp_texture_stages;
DWORD d3d_vshader_constantF, d3d_pshader_constantF; /* Advertised d3d caps, not GL ones */
WORD view_ident : 1; /* true iff view matrix is identity */
WORD untransformed : 1;