-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Artifact in SOCOM U.S. Navy SEALs games #8973
Comments
From the log, what FBO is being destroyed when that image goes away? If you set a breakpoint, is anything else writing to that area of memory before the FBO is destroyed? We're probably not catching a memcpy/memset. FYI: I'm not gonna be around much this coming week. -[Unknown] |
|
That looks like it could be it, yes. It's doing three lbus and doing some averaging or something? But it seems to ultimately be clearing the memory. -[Unknown] |
SOCOM U.S. Navy SEALs Tactical Strike does not break.
|
Ah, I guess what's happening is that it draws the frame initially, but then it draws black, and it relies on memory being updated with the black too. If we did that, we'd bring back the problems #8804 fixed in other games... But maybe we could explicitly memset when a clear happens. If you step frame when the original logo is shown, does it ever do a clear (this is just a regular draw, but clear mode is on.) If so, we could use those to update memory when we first see them too. -[Unknown] |
Try finding this in DrawEngineGLES.cpp: int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2); And replace with: int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
// If easy, immediately clear the RAM too.
bool singleByteClear = (clearColor >> 16) == (clearColor && 0xFFFF) && (clearColor >> 24) == (clearColor & 0xFF);
if (g_Config.bBlockTransferGPU && colorMask && alphaMask && singleByteClear) {
const int bpp = gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2;
const int xoff = scissorX1 * bpp;
const int xlen = (scissorX2 - scissorX1) * bpp;
const int stride = gstate.FrameBufStride() * bpp;
u8 *const addr = Memory::GetPointer(gstate.getFrameBufAddress() + xoff);
for (int y = scissorY1; y < scissorY2; ++y) {
memset(addr + y * stride, clearColor, xlen);
}
} This is probably not a perfect fix - there are more cases to handle and maybe it could be more efficient, but if this works it might be a good option. Also, if this breaks other games then an improved version would likely also break other games. -[Unknown] |
Wait, that won't work here actually... but here's a version that should (definitely could be more optimal...) int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
// If easy, immediately clear the RAM too.
if (g_Config.bBlockTransferGPU && colorMask && alphaMask) {
u8 *addr = Memory::GetPointer(gstate.getFrameBufAddress());
const bool singleByteClear = (clearColor >> 16) == (clearColor && 0xFFFF) && (clearColor >> 24) == (clearColor & 0xFF);
if (singleByteClear) {
const int bpp = gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2;
const int xoff = scissorX1 * bpp;
const int stride = gstate.FrameBufStride() * bpp;
const int xlen = (scissorX2 - scissorX1) * bpp;
addr += xoff;
for (int y = scissorY1; y < scissorY2; ++y) {
memset(addr + y * stride, clearColor, xlen);
}
} else {
u32 *addr32 = (u32 *)addr;
const int stride = gstate.FrameBufStride();
for (int y = scissorY1; y < scissorY2; ++y) {
for (int x = scissorX1; x < scissorX2; ++x) {
addr32[y * stride + x] = clearColor;
}
}
}
}
} -[Unknown] |
Oops, I'm still wrong. Try this one (could really make this more optimal...): int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
// If easy, immediately clear the RAM too.
if (g_Config.bBlockTransferGPU && colorMask && alphaMask) {
u8 *addr = Memory::GetPointer(gstate.getFrameBufAddress());
const bool singleByteClear = (clearColor >> 16) == (clearColor && 0xFFFF) && (clearColor >> 24) == (clearColor & 0xFF);
const int bpp = gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2;
if (singleByteClear) {
const int xoff = scissorX1 * bpp;
const int stride = gstate.FrameBufStride() * bpp;
const int xlen = (scissorX2 - scissorX1) * bpp;
addr += xoff;
for (int y = scissorY1; y < scissorY2; ++y) {
memset(addr + y * stride, clearColor, xlen);
}
} else if (bpp == 4) {
u32 *addr32 = (u32 *)addr;
const int stride = gstate.FrameBufStride();
for (int y = scissorY1; y < scissorY2; ++y) {
for (int x = scissorX1; x < scissorX2; ++x) {
addr32[y * stride + x] = clearColor;
}
}
} else if (bpp == 2) {
u16 *addr32 = (u16 *)addr;
const int stride = gstate.FrameBufStride();
for (int y = scissorY1; y < scissorY2; ++y) {
for (int x = scissorX1; x < scissorX2; ++x) {
addr32[y * stride + x] = clearColor;
}
}
}
} -[Unknown] |
By the way it seems that there's likely something else wrong with SOCOM graphics as @daniel229 is saying that a framebuffer effect is missing. |
This should help synchronize block transfers better. Should improve hrydgard#8973.
This should help synchronize block transfers better. Should improve hrydgard#8973.
That commit has not been merged though. I'll look into doing that soon. |
I think this has been fixed for some time? |
Artifact in the middle of the screen,Since #8804
SOCOM U.S. Navy SEALs Fireteam Bravo 3
SOCOM U.S. Navy SEALs Tactical Strike
The text was updated successfully, but these errors were encountered: