[2/10] WineD3D: Load one bump mapping environment matrix into pixel
shaders if needed
Stefan Dösinger
stefan at codeweavers.com
Wed Feb 14 20:05:17 CST 2007
-------------- next part --------------
From 5c4503832041d1dad7f25a3a50c59c3ca28ce295 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Sun, 4 Feb 2007 11:39:29 +0100
Subject: [PATCH] WineD3D: Load one bump mapping environment matrix into pixel shaders if needed
---
dlls/wined3d/baseshader.c | 9 +++++++++
dlls/wined3d/directx.c | 9 ++++++++-
dlls/wined3d/glsl_shader.c | 18 ++++++++++++++++--
dlls/wined3d/pixelshader.c | 2 ++
dlls/wined3d/state.c | 12 ++++++++++++
dlls/wined3d/wined3d_private.h | 5 +++++
6 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index f13d448..3bbdb45 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -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
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 7e2fc05..398aca0 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -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:
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 9722312..566442b 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -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++) {
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 8958ee0..e83cab1 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -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
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index ad18b94..02c80c7 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -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) {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 6111f53..20c9072 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -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;
--
1.4.4.3
More information about the wine-patches
mailing list