wined3d: Watch out about higher constants when clamping ps 1.x consts.

ps 1.x supports only 8 constants, so the shader load code dirtifies the
first 8 on a shader switch. However, the constant load code reloaded all dirty
consts with clamping. That potentially left constants > 8 clamped.
This commit is contained in:
Stefan Dösinger 2009-08-06 20:30:20 +02:00 committed by Alexandre Julliard
parent 85fe381daf
commit 14eedc5be7
1 changed files with 35 additions and 24 deletions

View File

@ -284,7 +284,7 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, con
GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts) GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts)
{ {
local_constant* lconst; local_constant* lconst;
DWORD i, j; DWORD i = 0, j;
unsigned int ret; unsigned int ret;
if (TRACE_ON(d3d_shader)) { if (TRACE_ON(d3d_shader)) {
@ -299,7 +299,10 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, con
if (target_type == GL_FRAGMENT_PROGRAM_ARB && This->baseShader.reg_maps.shader_version.major == 1) if (target_type == GL_FRAGMENT_PROGRAM_ARB && This->baseShader.reg_maps.shader_version.major == 1)
{ {
float lcl_const[4]; float lcl_const[4];
for(i = 0; i < max_constants; i++) { /* ps 1.x supports only 8 constants, clamp only those. When switching between 1.x and higher
* shaders, the first 8 constants are marked dirty for reload
*/
for(; i < min(8, max_constants); i++) {
if(!dirty_consts[i]) continue; if(!dirty_consts[i]) continue;
dirty_consts[i] = 0; dirty_consts[i] = 0;
@ -322,14 +325,23 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, con
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const)); GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const));
} }
} else {
/* If further constants are dirty, reload them without clamping.
*
* The alternative is not to touch them, but then we cannot reset the dirty constant count
* to zero. That's bad for apps that only use PS 1.x shaders, because in that case the code
* above would always re-check the first 8 constants since max_constant remains at the init
* value
*/
}
if(GL_SUPPORT(EXT_GPU_PROGRAM_PARAMETERS)) { if(GL_SUPPORT(EXT_GPU_PROGRAM_PARAMETERS)) {
/* TODO: Benchmark if we're better of with finding the dirty constants ourselves, /* TODO: Benchmark if we're better of with finding the dirty constants ourselves,
* or just reloading *all* constants at once * or just reloading *all* constants at once
* *
GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, 0, max_constants, constants)); GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, i, max_constants, constants + (i * 4)));
*/ */
for(i = 0; i < max_constants; i++) { for(; i < max_constants; i++) {
if(!dirty_consts[i]) continue; if(!dirty_consts[i]) continue;
/* Find the next block of dirty constants */ /* Find the next block of dirty constants */
@ -342,14 +354,13 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, con
GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, j, i - j, constants + (j * 4))); GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, j, i - j, constants + (j * 4)));
} }
} else { } else {
for(i = 0; i < max_constants; i++) { for(; i < max_constants; i++) {
if(dirty_consts[i]) { if(dirty_consts[i]) {
dirty_consts[i] = 0; dirty_consts[i] = 0;
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4))); GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4)));
} }
} }
} }
}
checkGLcall("glProgramEnvParameter4fvARB()"); checkGLcall("glProgramEnvParameter4fvARB()");
/* Load immediate constants */ /* Load immediate constants */