libretro / parallel-n64

Optimized/rewritten Nintendo 64 emulator made specifically for Libretro. Originally based on Mupen64 Plus.
323 stars 128 forks source link

GlideN64: Zelda: Majora's Mask: Rendering bug #344

Closed orbea closed 8 years ago

orbea commented 8 years ago

OS: Slackware64-current mupen64plus-libretro-081e443_2016.06.21_master-x86_64-1_git RetroArch-1.3.4-x86_64-6_SBo mesa-154c0a4_2016.06.19_master-x86_64-1_git xf86-video-nouveau-1da8a93_2016.06.02_master-x86_64-1_git

This seems restricted to GlideN64 and I have noticed it in both Majora's Mask and Orcarina of Time, however its easy to test in the former.

When loading a savestate to an affected area it will look like this. 1

After moving around for a little bit it will start to look like. 2

Making a new savestate will reset the issue to the first image.

Here is an apitrace of the issue. http://ks392457.kimsufi.com/orbea/stuff/trace/libretro/retroarch-mupen64plus-gliden64-zelda-majora.trace.xz

And here is a savestate for testing. http://ks392457.kimsufi.com/orbea/stuff/games/n64/sstates/Legend%20of%20Zelda,%20The%20-%20Majora's%20Mask%20(U)%20%5b!%5d.state.xz Game MD5SUM: 2a0a8acb61538235bc1094d297fb6556 Legend of Zelda, The - Majora's Mask (U) [!].z64

The GLupeN64 project seems to also be experiencing this issue. https://github.com/loganmc10/GLupeN64/issues/2

loganmc10 commented 8 years ago

This isn't really a problem specifically with GLideN64, it is how libretro and GLideN64 interact. libretro uses a different default framebuffer than GLideN64 expects, as I understand it. It can be retrieved using glsm_get_current_framebuffer().

I'm not an OpenGL expert so I am still working on this and trying to figure it out, I would love some help if someone out there is really interested in getting GLideN64 to work with libretro.

There could also be some GL function/information not being saved in glsm_state_bind, I'm not sure.

inactive123 commented 8 years ago

@mudlord Sounds like you'd be the ideal guy to look into this.

ghost commented 8 years ago

Sorry for taking so long. The main thing is that all rendering to and from FBOs needs to be redirected. Maybe when glBindFramebuffer is 0, it binds the default libretro framebuffer instead. But then that might take a rewrite.

loganmc10 commented 8 years ago

I was afraid of that, I'm not much of a C++ guy, is there a way to overload/replace the glBindFramebuffer function and tell it to replace the "0" with the proper framebuffer?

loganmc10 commented 8 years ago

I guess sometime I'll try modifying the function:

https://github.com/libretro/libretro-common/blob/master/glsm/glsm.c#L1532

To replace "0" with the libretro framebuffer and see what happens

loganmc10 commented 8 years ago

I tried adding:

if (framebuffer == 0)
   framebuffer = hw_render.get_current_framebuffer();

To rglBindFrameBuffer with no success.

orbea commented 8 years ago

This is apparently a regression. It does not occur with commit a9f2030, but due to many build failures and segmentation faults between then and current mupen64plus-libretro I can not really git bisect it...

loganmc10 commented 8 years ago

I've gone through and manually replaced every instance of

glBindFramebuffer(GL_*_FRAMEBUFFER, 0);

with

glBindFramebuffer(GL_*_FRAMEBUFFER, glsm_get_current_framebuffer());

And the result is the same. Some games looks fine, like Super Mario, and some games have strange boxes like Zelda, or Smash Bros. Some games don't really show anything, like GoldenEye.

Any other ideas of what it might be @mudlord ?

loganmc10 commented 8 years ago

I'm quite interested in getting this working, I'll put a $50 USD "bounty" on this bug for whoever can get this working properly either here or with GLupeN64 (same bug)

https://github.com/loganmc10/GLupeN64/issues/2

It can be one of the RetroArch people, I don't care who solves it lol

loganmc10 commented 8 years ago

I finalllllly figured this out.

glVertexAttribPointer needs to be dealt with in glsm_state_bind

I'll work on this over the next few days to get it all working properly

orbea commented 8 years ago

RetroArch-1.3.6-x86_64-1_SBo

I applied the changes to glsm.c from loganmc10's GLupeN64 repo and found while it has improved the issue has not been fixed.

--- glsm.c  2016-07-28 10:27:48.675068382 -0700
+++ glsm_custom.c   2016-07-28 10:25:54.371087387 -0700
@@ -32,6 +32,16 @@
       GLuint *ids;
    } bind_textures;

+   struct
+   {
+      bool used[MAX_ATTRIB];
+      GLint size[MAX_ATTRIB];
+      GLenum type[MAX_ATTRIB];
+      GLboolean normalized[MAX_ATTRIB];
+      GLsizei stride[MAX_ATTRIB];
+      const GLvoid *pointer[MAX_ATTRIB];
+   } attrib_pointer;
+
 #ifndef HAVE_OPENGLES
    GLenum colorlogicop;
 #endif
@@ -1206,6 +1216,12 @@
       GLenum type, GLboolean normalized, GLsizei stride,
       const GLvoid* pointer)
 {
+   gl_state.attrib_pointer.used[name] = true;
+   gl_state.attrib_pointer.size[name] = size;
+   gl_state.attrib_pointer.type[name] = type;
+   gl_state.attrib_pointer.normalized[name] = normalized;
+   gl_state.attrib_pointer.stride[name] = stride;
+   gl_state.attrib_pointer.pointer[name] = pointer;
    glVertexAttribPointer(name, size, type, normalized, stride, pointer);
 }

@@ -1907,8 +1923,17 @@

    for (i = 0; i < MAX_ATTRIB; i++)
    {
-      if (gl_state.vertex_attrib_pointer.enabled[i])
+      if (gl_state.vertex_attrib_pointer.enabled[i]) {
          glEnableVertexAttribArray(i);
+         if (gl_state.attrib_pointer.used[i]){
+         glVertexAttribPointer(
+            i,
+            gl_state.attrib_pointer.size[i],
+            gl_state.attrib_pointer.type[i],
+            gl_state.attrib_pointer.normalized[i],
+            gl_state.attrib_pointer.stride[i],
+            gl_state.attrib_pointer.pointer[i]);}
+      }
       else
          glDisableVertexAttribArray(i);
    }

3 4 5 6

orbea commented 8 years ago

I tested with a fresh game and found it starts as soon as you reach that room with the first deku flower. With the glsm changes from the GLupeN64 repo it will look relatively correct anytime there is a dialog box, but will look wrong again as soon as that is closed.

7 8