Re: Broken character models in dx8/9 games in wined3d

2006-07-26 Thread Jason Green

Well, we discussed a few different ways of handling this, and here are
the results:

1) We can flip the texture we get from the framebuffer in
Device_LoadTexture.  Getting images from the back framebuffer always
are upside down, so we'll need to manually flip it before setting it
as the next render target.

a) Use glCopyTexSubImage2D() to swap each row

b) Use glReadPixels() to copy to a buffer, flip the image, then use
glTexImage2D() to write it back.

Both of these methods fixed the upside down rendering, but the issue
of the disconnected/broken models is still there, although less
prevalent now that things look more normal to begin with.  I've
attached both patches.  However, performance takes a pretty serious
hit:

Max Payne 2 with pixel shaders enabled in High detail mode (there are
still some lighting bugs, though):
Current git (upside-down):  ~65 fps
1a:  ~35 fps
1b:  ~15 fps

Civ4 with pixel shaders enabled
Current git (some upside-down stuff and very broken models): 30-50 fps
1a (still some broken models):  ~35 fps
1b (still some broken modles):  25-35 fps


2) Try to do some kind of fixup in the shader itself.  I'm not
entirely sure how to do this other than being creative with the small
hack I posted originally.  There are no noticable performance losses,
but visually, some things are broken (the sky in Tomb Raider Legends
as well as Half Life 2 are completely wrong, but Max Payne is about
99% right).

Any other suggestions?  Also, the models are still broke, so that may
be a separate topic and not related like I thought it was.
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 323a2f5..f0fe2ec 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3463,25 +3463,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 case D3DCULL_CW:
 glEnable(GL_CULL_FACE);
 checkGLcall(glEnable GL_CULL_FACE);
-if (This-renderUpsideDown) {
-glFrontFace(GL_CW);
-checkGLcall(glFrontFace GL_CW);
-} else {
-glFrontFace(GL_CCW);
-checkGLcall(glFrontFace GL_CCW);
-}
+glFrontFace(GL_CCW);
+checkGLcall(glFrontFace GL_CCW);
 glCullFace(GL_BACK);
 break;
 case D3DCULL_CCW:
 glEnable(GL_CULL_FACE);
 checkGLcall(glEnable GL_CULL_FACE);
-if (This-renderUpsideDown) {
-glFrontFace(GL_CCW);
-checkGLcall(glFrontFace GL_CCW);
-} else {
-glFrontFace(GL_CW);
-checkGLcall(glFrontFace GL_CW);
-}
+glFrontFace(GL_CW);
+checkGLcall(glFrontFace GL_CW);
 glCullFace(GL_BACK);
 break;
 default:
@@ -7385,28 +7375,9 @@ #endif
 IWineD3DSurface_AddRef(This-renderTarget);
 IWineD3DSurface_Release(tmp);
 
-{
-DWORD value;
-
-/* The surface must be rendered upside down to cancel the flip produce 
by glCopyTexImage */
-/* Check that the container is not a swapchain member */
-
-IWineD3DSwapChain *tmpSwapChain;
-if (WINED3D_OK != IWineD3DSurface_GetContainer(This-renderTarget, 
IID_IWineD3DSwapChain, (void **)tmpSwapChain)) {
-This-renderUpsideDown = TRUE;
-}else{
-This-renderUpsideDown = FALSE;
-IWineD3DSwapChain_Release(tmpSwapChain);
-}
-/* Force updating the cull mode */
-TRACE(setting render state\n);
-IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, value);
-IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
-
-/* Force updating projection matrix */
-This-last_was_rhw = FALSE;
-This-proj_valid = FALSE;
-}
+/* Force updating projection matrix */
+This-last_was_rhw = FALSE;
+This-proj_valid = FALSE;
 
 /* Restore recording state */
 This-isRecordingState = oldRecording;
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index bb48982..485e0fe 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -148,12 +148,6 @@ static void init_materials(IWineD3DDevic
 
 }
 
-static GLfloat invymat[16] = {
-   1.0f, 0.0f, 0.0f, 0.0f,
-   0.0f, -1.0f, 0.0f, 0.0f,
-   0.0f, 0.0f, 1.0f, 0.0f,
-   0.0f, 0.0f, 0.0f, 1.0f};
-
 void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
 /* If the last draw was transformed as well, no need to reapply all the 
matrixes */
 if ( (!This-last_was_rhw) || (This-viewport_changed) ) {
@@ -190,10 +184,6 @@ void d3ddevice_set_ortho(IWineD3DDeviceI
 a pixel (See comment above glTranslate below)  
   */
 glTranslatef(0.375, 0.375, 0);
 checkGLcall(glTranslatef(0.375, 0.375, 0));
-if (This-renderUpsideDown) {
-glMultMatrixf(invymat);
-checkGLcall(glMultMatrixf(invymat));
-}
 
 /* Vertex fog on transformed 

Re: Broken character models in dx8/9 games in wined3d

2006-07-26 Thread Frank Richter
On 25.07.2006 14:48, Jason Green wrote:
 However, when you use a shader, you don't use those matrices at all,
 you pass your own vec4 (4 component float vector) constants into the
 shader program, and you don't just have 4 of them to use as a matrix,
 you have as many as the hardware allows (typically 96 or 256 with
 current hardware).  So, we don't know which ones the shader will use
 as it's MV/P matrix, so we can't perform any type of y-flip at that
 spot because we might mess up the other constants that the shader
 needs to perform its calculations.  

However, you do know the register into which the output position will be
written by the VP. Could flipping the Y of the output position at the
very end of the VP work?

-f.r.




Re: Broken character models in dx8/9 games in wined3d

2006-07-26 Thread H. Verbeet

On 26/07/06, Jason Green [EMAIL PROTECTED] wrote:

2) Try to do some kind of fixup in the shader itself.  I'm not
entirely sure how to do this other than being creative with the small
hack I posted originally.  There are no noticable performance losses,

It might be possible to fixup the inputs to the sample functions, but
it would require regular surfaces to be upside down instead. Not sure
if that would be cheaper than flipping the render targets, but regular
surfaces typically don't get modified as much. It would also require
modifying the texture matrix for the fixed function pipeline.




Re: Broken character models in dx8/9 games in wined3d

2006-07-26 Thread H. Verbeet

On 26/07/06, Frank Richter [EMAIL PROTECTED] wrote:

On 25.07.2006 14:48, Jason Green wrote:
 However, when you use a shader, you don't use those matrices at all,
 you pass your own vec4 (4 component float vector) constants into the
 shader program, and you don't just have 4 of them to use as a matrix,
 you have as many as the hardware allows (typically 96 or 256 with
 current hardware).  So, we don't know which ones the shader will use
 as it's MV/P matrix, so we can't perform any type of y-flip at that
 spot because we might mess up the other constants that the shader
 needs to perform its calculations.

However, you do know the register into which the output position will be
written by the VP. Could flipping the Y of the output position at the
very end of the VP work?

-f.r.

Well, you can't really do that, since it's not guaranteed the mvp
matrix will only be used for position transformations. A shader could
use it for eg. lighting calculations.




Re: Broken character models in dx8/9 games in wined3d

2006-07-26 Thread Frank Richter
On 26.07.2006 14:31, H. Verbeet wrote:
 However, you do know the register into which the output position will be
 written by the VP. Could flipping the Y of the output position at the
 very end of the VP work?

 Well, you can't really do that, since it's not guaranteed the mvp
 matrix will only be used for position transformations. A shader could
 use it for eg. lighting calculations.

I thought more along the lines of flip result.position.y, not changing
the MVP matrix.

-f.r.





Re: Broken character models in dx8/9 games in wined3d

2006-07-25 Thread Stefan Dösinger
Am Dienstag 25 Juli 2006 04:21 schrieb Jason Green:
 I've spent a couple of days researching the issue of
 broken/upside-down character/object models in Wine in almost all newer
 games when you have vertex shaders enabled (Civ4, Half Life 2,
 Oblivion, Max Payne 2, etc.).  I think I've boiled it down to a single
 case:  When device-renderUpsideDown is set in the case where vertex
 shaders are enabled.  That flag gets set in device.c:7395 when the
 current renderTarget is not on the current swapchain.  The comments in
 the source say that the upside-downedness is produced by
 glCopyTexImage, so it sets a flag to flip everything over.

 In the case w/o shaders, there is code in drawprim.c which loads the
 WORLDVIEW and PROJECTION matrices and then multiplies those matrices
 by one which inverts the y coordinates when that flag is set. That
 seems to work in the case without vertex shaders, but when shaders are
 enabled, they bypass the WORLD, VIEW, and PROJECTION matrices
 entirely.  The shader case was written when only software shaders
 worked, but that is no longer true.   It loads identity matrices and
 performs the y flip, but that code is entirely irrelevant since the
 vertex shader doesn't reference those matrices; it only uses constants
 that are passed by the app, which we can't perform any type of fixup
 on since we don't know which constants will be used for which
 calculation.

 So, I think what we need to do is prevent ourselves from having to do
 any flipping whatsoever.  That's the part that I'm not sure how to do
 and is the reason for this email.  Can we load the textures in system
 memory first, perform a software reversing process, then load that up
 with glCopyTexImage instead?  Will we need to do that type of fixup
 every time the app locks/unlocks/changes part of the texture?  Or, is
 there a better way?

 I think I've figured out the problem, it's just the next step of
 fixing it that I'm unsure of.  :-)
Can we flip around the y axis in the shader? Or can we flip around the texture 
coords when drawing from the offscreen texture? If I understand it correctly 
this only affects offscreen rendering.


pgpPpY2mHFExV.pgp
Description: PGP signature



Re: Broken character models in dx8/9 games in wined3d

2006-07-25 Thread H. Verbeet

On 25/07/06, Stefan Dösinger [EMAIL PROTECTED] wrote:

Can we flip around the y axis in the shader?

Well, that is essentially what Jason's hack does :-)


Or can we flip around the texture
coords when drawing from the offscreen texture? If I understand it correctly
this only affects offscreen rendering.

I was hoping you would know :-)
We would have to do some fixups when locking the surface as well, but
I don't think that should be a problem.




Re: Broken character models in dx8/9 games in wined3d

2006-07-25 Thread Jason Green

On 7/25/06, Stefan Dösinger [EMAIL PROTECTED] wrote:

Can we flip around the y axis in the shader?


It's not quite so easy.  At the moment in the case w/o shaders, we
multiply the WORLDVIEW and/or PROJECTION matrices by a matrix that
flips the y axis on the whole matrix, like so:

1 1 1 1 1  0  0  0
2 2 2 2 0 -1  0  0
3 3 3 3  *  0  0  1  0
4 4 4 4 0  0  0  1

=

1 -1  1  1
2 -2  2  2
3 -3  3  3
4 -4  4  4

However, when you use a shader, you don't use those matrices at all,
you pass your own vec4 (4 component float vector) constants into the
shader program, and you don't just have 4 of them to use as a matrix,
you have as many as the hardware allows (typically 96 or 256 with
current hardware).  So, we don't know which ones the shader will use
as it's MV/P matrix, so we can't perform any type of y-flip at that
spot because we might mess up the other constants that the shader
needs to perform its calculations.  Plus, the same shader can be used
for multiple render targets - some upside-down and some not.

Flipping the y position in the shader based on the current MVP matrix
fixes the issue in some cases, but only when the shader's effective
MVP matrix is the identity matrix.  If the constants that the app
passes to the shader differ from the identity matrix, then our y-flip
isn't taking any of the other rows y-flip into account, so the
calculations are wrong and hence the models are broken.




Re: Broken character models in dx8/9 games in wined3d

2006-07-25 Thread Jason Green

On 7/25/06, H. Verbeet [EMAIL PROTECTED] wrote:


Can't we just correct the texture coordinates / start writing the
surface contents at the bottom? Also, if we use EXT_framebuffer_object
instead, we probably won't have to use glCopyTexImage in the first
place.


No idea, but that's the type of answer I was looking for.  :-)

http://www.winehq.com/hypermail/wine-patches/2004/04/0433.html

is the patch which first started this whole concept of flipping to
begin with, if that helps.




Re: Broken character models in dx8/9 games in wined3d

2006-07-25 Thread Stefan Dösinger
Am Dienstag 25 Juli 2006 11:54 schrieb H. Verbeet:
 On 25/07/06, Stefan Dösinger [EMAIL PROTECTED] wrote:
  Can we flip around the y axis in the shader?

 Well, that is essentially what Jason's hack does :-)

  Or can we flip around the texture
  coords when drawing from the offscreen texture? If I understand it
  correctly this only affects offscreen rendering.

 I was hoping you would know :-)
 We would have to do some fixups when locking the surface as well, but
 I don't think that should be a problem.
Well, I'm not the shader expert in here, but if the y flip only affects 
offscreen render targets and we can find out in which conditions it needs 
flipping then we can just create a SFLAG_INVY surface flag(there are quite a 
lot of them already :-| ). The tricky part is to actually flip it around when 
drawing because we have to modify the vertices. This could be a case for 
drawStridedSlow or VBO vertex fixups. Or do the texture matrices help here? 
(/me reads up the red book)

Surface locking is the least problem, just check the flag and order reversed 
coordinates from opengl or flip the lines in software.


pgpSHX6XuGTlw.pgp
Description: PGP signature



Re: Broken character models in dx8/9 games in wined3d

2006-07-25 Thread H. Verbeet

On 25/07/06, Stefan Dösinger [EMAIL PROTECTED] wrote:

lot of them already :-| ). The tricky part is to actually flip it around when
drawing because we have to modify the vertices. This could be a case for
drawStridedSlow or VBO vertex fixups. Or do the texture matrices help here?

Well yes, you would modify the texture matrix, rather than the
individual coordinates.




Re: Broken character models in dx8/9 games in wined3d

2006-07-24 Thread Jesse Allen

On 7/24/06, Jason Green [EMAIL PROTECTED] wrote:

I've spent a couple of days researching the issue of
broken/upside-down character/object models in Wine in almost all newer
games when you have vertex shaders enabled (Civ4, Half Life 2,
Oblivion, Max Payne 2, etc.).


Yes, I remember some talk on IRC, and wanted to comment, but will do now.


 I think I've boiled it down to a single
case:  When device-renderUpsideDown is set in the case where vertex
shaders are enabled.  That flag gets set in device.c:7395 when the
current renderTarget is not on the current swapchain.  The comments in
the source say that the upside-downedness is produced by
glCopyTexImage, so it sets a flag to flip everything over.

In the case w/o shaders, there is code in drawprim.c which loads the
WORLDVIEW and PROJECTION matrices and then multiplies those matrices
by one which inverts the y coordinates when that flag is set. That
seems to work in the case without vertex shaders, but when shaders are
enabled, they bypass the WORLD, VIEW, and PROJECTION matrices
entirely.  The shader case was written when only software shaders
worked, but that is no longer true.   It loads identity matrices and
performs the y flip, but that code is entirely irrelevant since the
vertex shader doesn't reference those matrices; it only uses constants
that are passed by the app, which we can't perform any type of fixup
on since we don't know which constants will be used for which
calculation.


Yeah, I've noticed all this with Star Wars Battlefront. See bug 5247.

Without vertex shaders, I have a very simple hack to fix the one issue
of an upside down skybox. What I did should be quite obvious to you.
With vertex shaders (note: I make brief mention in bug comments about
how to get them working with dri, you might remember this from IRC
too) having them enabled, the problem gets a little worse as certain
parts of the skybox are correctly up and others upside down. If you
apply the hack, then *everything* got flipped -- those that were
correct were now upside down, and vice-versa. Also parts of the box
got shifted a bit. This is with ARB shaders BTW. I'll post screen
shots when I get the chance.  I wonder if there was a reason for the
flip code because it does flip some things correctly.




So, I think what we need to do is prevent ourselves from having to do
any flipping whatsoever. That's the part that I'm not sure how to do
and is the reason for this email.


That I'd agree with. There are certainly things it does wrong. But I
think I need to go back studying the code before I make any
recommendations. :) I'll try to get back to you later.

Jesse