wined3d: Load one bump mapping environment matrix into pixel shaders if needed.

This commit is contained in:
Stefan Dösinger 2007-02-15 03:05:17 +01:00 committed by Alexandre Julliard
parent efbd6d6332
commit 49a49fcfec
6 changed files with 52 additions and 3 deletions

View File

@ -344,6 +344,15 @@ HRESULT shader_get_registers_used(
reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
}
}
/* texbem is only valid with < 1.4 pixel shaders */
if(WINED3DSIO_TEXBEM == curOpcode->opcode) {
if(reg_maps->bumpmat != 0 && reg_maps->bumpmat != sampler_code) {
FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n");
} else {
reg_maps->bumpmat = sampler_code;
}
}
}
/* This will loop over all the registers and try to

View File

@ -284,10 +284,17 @@ void select_shader_max_constants(
switch (ps_selected_mode) {
case SHADER_GLSL:
/* Subtract the other potential uniforms from the max available (bools & ints) */
/* Subtract the other potential uniforms from the max available (bools & ints).
* 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 - MAX_CONST_I;
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 no need to reduce the number of available constants.
*/
gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
break;
case SHADER_SW:

View File

@ -283,7 +283,8 @@ void shader_glsl_load_constants(
GLhandleARB *constant_locations;
struct list *constant_list;
GLhandleARB programId;
GLint pos;
if (!stateBlock->glsl_program) {
/* No GLSL program set - nothing to do. */
return;
@ -336,11 +337,22 @@ void shader_glsl_load_constants(
shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
stateBlock->pixelShaderConstantI,
stateBlock->set.pixelShaderConstantsI);
/* Load DirectX 9 boolean constants/uniforms for pixel shader */
shader_glsl_load_constantsB(pshader, gl_info, programId, MAX_CONST_B,
stateBlock->pixelShaderConstantB,
stateBlock->set.pixelShaderConstantsB);
/* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from.
* It can't be 0 for a valid texbem instruction.
*/
if(((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat != 0) {
float *data = (float *) &stateBlock->textureState[(int) ((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat][WINED3DTSS_BUMPENVMAT00];
pos = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat"));
checkGLcall("glGetUniformLocationARB");
GL_EXTCALL(glUniform4fvARB(pos, 1, data));
checkGLcall("glUniform4fvARB");
}
}
}
@ -379,6 +391,8 @@ void shader_generate_glsl_declarations(
if(!pshader)
shader_addline(buffer, "uniform vec4 posFixup;\n");
else if(reg_maps->bumpmat)
shader_addline(buffer, "uniform vec4 bumpenvmat;\n");
/* Declare texture samplers */
for (i = 0; i < This->baseShader.limits.sampler; i++) {

View File

@ -914,6 +914,8 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateShader(
}
}
This->needsbumpmat = reg_maps->bumpmat;
#if 1 /* if were using the data buffer of device then we don't need to free it */
HeapFree(GetProcessHeap(), 0, buffer.buffer);
#endif

View File

@ -1951,6 +1951,18 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
}
static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
if(stateblock->pixelShader && stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) {
/* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
* anyway
*/
if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
!isStateDirty(context, STATE_PIXELSHADER)) {
shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
}
}
}
static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {

View File

@ -1468,6 +1468,7 @@ typedef struct shader_reg_maps {
/* Sampler usage tokens
* Use 0 as default (bit 31 is always 1 on a valid token) */
DWORD samplers[MAX_SAMPLERS];
char bumpmat;
/* Whether or not a loop is used in this shader */
char loop;
@ -1834,6 +1835,10 @@ typedef struct IWineD3DPixelShaderImpl {
/* run time data */
PSHADERDATA *data;
/* Some information about the shader behavior */
char needsbumpmat;
UINT bumpenvmatconst;
#if 0 /* needs reworking */
PSHADERINPUTDATA input;
PSHADEROUTPUTDATA output;