Module: wine
Branch: master
Commit: 96bce8d6d49d92b524cca2f1f6722c83181951cd
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=96bce8d6d49d92b524cca2f…
Author: Stefan Dösinger <stefan(a)codeweavers.com>
Date: Sat Sep 23 19:09:06 2006 +0200
wined3d: Avoid wasting a uniform.
---
dlls/wined3d/arb_program_shader.c | 3 +++
dlls/wined3d/drawprim.c | 19 +++----------------
dlls/wined3d/glsl_shader.c | 10 ++++++++++
dlls/wined3d/vertexshader.c | 32 ++++++++++++++------------------
dlls/wined3d/wined3d_private.h | 9 +++++++++
5 files changed, 39 insertions(+), 34 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index e984b9d..47397d6 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -127,6 +127,9 @@ void shader_arb_load_constants(
GL_LIMITS(vshader_constantsF),
stateBlock->vertexShaderConstantF,
&stateBlock->set_vconstantsF);
+
+ /* Upload the position fixup */
+ GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, ARB_SHADER_PRIVCONST_POS, vshader_impl->wineD3DDevice->posFixup));
}
if (usePixelShader) {
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 2c31eb9..ff465a8 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -311,22 +311,9 @@ static void primitiveInitState(
/* Vertex Shader output is already transformed, so set up identity matrices */
if (useVS) {
- glMatrixMode(GL_MODELVIEW);
- checkGLcall("glMatrixMode");
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- checkGLcall("glMatrixMode");
- glLoadIdentity();
- /* Window Coord 0 is the middle of the first pixel, so translate by half
- a pixel (See comment above glTranslate above) */
- glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
- checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
- if (This->renderUpsideDown) {
- glMultMatrixf(invymat);
- checkGLcall("glMultMatrixf(invymat)");
- }
- This->modelview_valid = FALSE;
- This->proj_valid = FALSE;
+ This->posFixup[1] = This->renderUpsideDown ? -1.0 : 1.0;
+ This->posFixup[2] = 0.9 / This->stateBlock->viewport.Width;
+ This->posFixup[3] = -0.9 / This->stateBlock->viewport.Height;
}
This->last_was_rhw = FALSE;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 257b9e5..0554392 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -288,6 +288,7 @@ void shader_glsl_load_constants(
if (useVertexShader) {
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
IWineD3DVertexShaderImpl* vshader_impl = (IWineD3DVertexShaderImpl*) vshader;
+ GLint pos;
IWineD3DVertexDeclarationImpl* vertexDeclaration =
(IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
@@ -314,6 +315,12 @@ void shader_glsl_load_constants(
shader_glsl_load_constantsB(vshader, gl_info, programId, MAX_CONST_B,
stateBlock->vertexShaderConstantB,
stateBlock->set.vertexShaderConstantsB);
+
+ /* Upload the position fixup params */
+ pos = GL_EXTCALL(glGetUniformLocationARB(programId, "posFixup"));
+ checkGLcall("glGetUniformLocationARB");
+ glUniform4fvARB(pos, 1, &vshader_impl->wineD3DDevice->posFixup[0]);
+ checkGLcall("glUniform4fvARB");
}
if (usePixelShader) {
@@ -375,6 +382,9 @@ void shader_generate_glsl_declarations(
if (This->baseShader.limits.constant_bool > 0)
shader_addline(buffer, "uniform bool %cB[%u];\n", prefix, This->baseShader.limits.constant_bool);
+ if(!pshader)
+ shader_addline(buffer, "uniform vec4 posFixup;\n");
+
/* Declare texture samplers */
for (i = 0; i < This->baseShader.limits.sampler; i++) {
if (reg_maps->samplers[i]) {
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 9719264..2d7ab58 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -737,17 +737,16 @@ #endif
/* Write the final position.
*
* OpenGL coordinates specify the center of the pixel while d3d coords specify
- * the corner. For that reason a translation is done with the projection matrix,
- * which sets the offsets to move in the w coords of the matrix(see glTranslate manpage)
- * Add the w coordinates to x and y, this avoids the need for a full matrix
- * multiplication. The matrix is set up in drawprim.c, primitiveInitState.
+ * the corner. The offsets are stored in z and w in the 2nd row of the projection
+ * matrix to avoid wasting a free shader constant. Add them to the w and z coord
+ * of the 2nd row
*/
- shader_addline(&buffer, "gl_Position.x = gl_Position.x + gl_ProjectionMatrix[3][0];\n");
- shader_addline(&buffer, "gl_Position.y = gl_Position.y + gl_ProjectionMatrix[3][1];\n");
+ shader_addline(&buffer, "gl_Position.x = gl_Position.x + posFixup[2];\n");
+ shader_addline(&buffer, "gl_Position.y = gl_Position.y + posFixup[3];\n");
/* Account for any inverted textures (render to texture case) by reversing the y coordinate
* (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices)
*/
- shader_addline(&buffer, "gl_Position.y = gl_Position.y * gl_ProjectionMatrix[1][1];\n");
+ shader_addline(&buffer, "gl_Position.y = gl_Position.y * posFixup[1];\n");
shader_addline(&buffer, "}\n\0");
@@ -771,10 +770,9 @@ #endif
/* Base Declarations */
shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, &buffer, &GLINFO_LOCATION);
-
- /* We need the projection matrix to correctly render upside-down objects (render to texture) */
- shader_addline(&buffer, "PARAM PROJECTIONX = state.matrix.projection.row[0];\n");
- shader_addline(&buffer, "PARAM PROJECTIONY = state.matrix.projection.row[1];\n");
+
+ /* We need a constant to fixup the final position */
+ shader_addline(&buffer, "PARAM posFixup = program.env[%d];\n", ARB_SHADER_PRIVCONST_POS);
if (reg_maps->fog) {
This->usesFog = 1;
@@ -792,17 +790,15 @@ #endif
/* Write the final position.
*
* OpenGL coordinates specify the center of the pixel while d3d coords specify
- * the corner. For that reason a translation is done with the projection matrix,
- * which sets the offsets to move in the w coords of the matrix(see glTranslate manpage)
- * Add the w coordinates to x and y, this avoids the need for a full matrix
- * multiplication. The matrix is set up in drawprim.c, primitiveInitState.
+ * the corner. The offsets are stored in the 2nd row of the projection matrix,
+ * the x offset in z and the y offset in w. Add them to the resulting position
*/
- shader_addline(&buffer, "ADD result.position.x, TMP_OUT.x, PROJECTIONX.w;\n");
- shader_addline(&buffer, "ADD result.position.y, TMP_OUT.y, PROJECTIONY.w;\n");
+ shader_addline(&buffer, "ADD result.position.x, TMP_OUT.x, posFixup.z;\n");
+ shader_addline(&buffer, "ADD result.position.y, TMP_OUT.y, posFixup.w;\n");
/* Account for any inverted textures (render to texture case) by reversing the y coordinate
* (this is handled in drawPrim() when it sets the MODELVIEW and PROJECTION matrices)
*/
- shader_addline(&buffer, "MUL result.position.y, TMP_OUT.y, PROJECTIONY.y;\n");
+ shader_addline(&buffer, "MUL result.position.y, TMP_OUT.y, posFixup.y;\n");
shader_addline(&buffer, "END\n\0");
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index a4fae10..9921d4c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -581,6 +581,9 @@ #define NEEDS_DI
/* List of GLSL shader programs and their associated vertex & pixel shaders */
struct list glsl_shader_progs;
+
+ /* Final position fixup constant */
+ float posFixup[4];
} IWineD3DDeviceImpl;
extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl;
@@ -1667,6 +1670,12 @@ inline static BOOL shader_is_comment(DWO
return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
}
+/* 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_POS ARB_SHADER_PRIVCONST_BASE + 0
+
/*****************************************************************************
* IDirect3DVertexShader implementation structure
*/
Module: wine
Branch: master
Commit: 674af50174993baaed43a267e0d3d05ce8e81e71
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=674af50174993baaed43a26…
Author: Stefan Dösinger <stefan(a)codeweavers.com>
Date: Sat Sep 23 18:02:22 2006 +0200
wined3d: Stop fixing up a VBO if the declaration changes too often.
---
dlls/wined3d/vertexbuffer.c | 36 ++++++++++++++++++++++++++++++++++++
dlls/wined3d/wined3d_private.h | 1 +
2 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/dlls/wined3d/vertexbuffer.c b/dlls/wined3d/vertexbuffer.c
index bf734b5..5046d42 100644
--- a/dlls/wined3d/vertexbuffer.c
+++ b/dlls/wined3d/vertexbuffer.c
@@ -26,6 +26,9 @@ #include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
+#define VB_MAXDECLCHANGES 100 /* After that number we stop converting */
+#define VB_RESETDECLCHANGE 1000 /* Reset the changecount after that number of draws */
+
/* *******************************************
IWineD3DVertexBuffer IUnknown parts follow
******************************************* */
@@ -278,6 +281,39 @@ static void WINAPI IWineD3DVertexBuf
}
declChanged = IWineD3DVertexBufferImpl_FindDecl(This);
+
+ /* If applications change the declaration over and over, reconverting all the time is a huge
+ * performance hit. So count the declaration changes and release the VBO if there are too much
+ * of them(and thus stop converting)
+ */
+ if(declChanged) {
+ This->declChanges++;
+ This->draws = 0;
+
+ if(This->declChanges > VB_MAXDECLCHANGES) {
+ if(This->resource.allocatedMemory) {
+ FIXME("Too much declaration changes, stopping converting\n");
+ ENTER_GL();
+ GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo));
+ checkGLcall("glDeleteBuffersARB");
+ LEAVE_GL();
+ This->vbo = 0;
+ return;
+ }
+ /* Otherwise do not bother to release the VBO. If we're doing direct locking now,
+ * and the declarations changed the code below will fetch the VBO's contents, convert
+ * and on the next decl change the data will be in sysmem too and we can just release the VBO
+ */
+ }
+ } else {
+ /* However, it is perfectly fine to change the declaration every now and then. We don't want a game that
+ * changes it every minute drop the VBO after VB_MAX_DECL_CHANGES minutes. So count draws without
+ * decl changes and reset the decl change count after a specific number of them
+ */
+ This->draws++;
+ if(This->draws > VB_RESETDECLCHANGE) This->declChanges = 0;
+ }
+
if(declChanged) {
/* The declaration changed, reload the whole buffer */
WARN("Reloading buffer because of decl change\n");
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9b36a70..a4fae10 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -655,6 +655,7 @@ typedef struct IWineD3DVertexBufferImpl
UINT dirtystart, dirtyend;
LONG lockcount;
+ LONG declChanges, draws;
/* Last description of the buffer */
WineDirect3DVertexStridedData strided;
} IWineD3DVertexBufferImpl;