mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-08-18 08:17:28 -05:00
VideoCommon: ignore zero-stride EFB/XFB copies
just clear if requested
This commit is contained in:
@@ -298,75 +298,78 @@ static void BPWritten(PixelShaderManager& pixel_shader_manager, XFStateManager&
|
||||
const u32 copy_width = srcRect.GetWidth();
|
||||
const u32 copy_height = srcRect.GetHeight();
|
||||
|
||||
// Check if we are to copy from the EFB or draw to the XFB
|
||||
if (PE_copy.copy_to_xfb == 0)
|
||||
if (destStride != 0)
|
||||
{
|
||||
// bpmem.zcontrol.pixel_format to PixelFormat::Z24 is when the game wants to copy from ZBuffer
|
||||
// (Zbuffer uses 24-bit Format)
|
||||
bool is_depth_copy = bpmem.zcontrol.pixel_format == PixelFormat::Z24;
|
||||
g_texture_cache->CopyRenderTargetToTexture(
|
||||
destAddr, PE_copy.tp_realFormat(), copy_width, copy_height, destStride, is_depth_copy,
|
||||
srcRect, PE_copy.intensity_fmt && PE_copy.auto_conv, PE_copy.half_scale, 1.0f,
|
||||
s_gammaLUT[PE_copy.gamma], bpmem.triggerEFBCopy.clamp_top,
|
||||
bpmem.triggerEFBCopy.clamp_bottom, bpmem.copyfilter.GetCoefficients());
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should be able to get away with deactivating the current bbox tracking
|
||||
// here. Not sure if there's a better spot to put this.
|
||||
// the number of lines copied is determined by the y scale * source efb height
|
||||
g_bounding_box->Disable(pixel_shader_manager);
|
||||
|
||||
float yScale;
|
||||
if (PE_copy.scale_invert)
|
||||
yScale = 256.0f / static_cast<float>(bpmem.dispcopyyscale);
|
||||
else
|
||||
yScale = static_cast<float>(bpmem.dispcopyyscale) / 256.0f;
|
||||
|
||||
float num_xfb_lines = 1.0f + bpmem.copyTexSrcWH.y * yScale;
|
||||
|
||||
u32 height = static_cast<u32>(num_xfb_lines);
|
||||
|
||||
DEBUG_LOG_FMT(VIDEO,
|
||||
"RenderToXFB: destAddr: {:08x} | srcRect [{} {} {} {}] | fbWidth: {} | "
|
||||
"fbStride: {} | fbHeight: {} | yScale: {}",
|
||||
destAddr, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom,
|
||||
bpmem.copyTexSrcWH.x + 1, destStride, height, yScale);
|
||||
|
||||
bool is_depth_copy = bpmem.zcontrol.pixel_format == PixelFormat::Z24;
|
||||
g_texture_cache->CopyRenderTargetToTexture(
|
||||
destAddr, EFBCopyFormat::XFB, copy_width, height, destStride, is_depth_copy, srcRect,
|
||||
false, false, yScale, s_gammaLUT[PE_copy.gamma], bpmem.triggerEFBCopy.clamp_top,
|
||||
bpmem.triggerEFBCopy.clamp_bottom, bpmem.copyfilter.GetCoefficients());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
|
||||
// This is as closest as we have to an "end of the frame"
|
||||
// It works 99% of the time.
|
||||
// But sometimes games want to render an XFB larger than the EFB's 640x528 pixel resolution
|
||||
// (especially when using the 3xMSAA mode, which cuts EFB resolution to 640x264). So they
|
||||
// render multiple sub-frames and arrange the XFB copies in next to each-other in main memory
|
||||
// so they form a single completed XFB.
|
||||
// See https://dolphin-emu.org/blog/2017/11/19/hybridxfb/ for examples and more detail.
|
||||
system.GetVideoEvents().after_frame_event.Trigger(system);
|
||||
|
||||
// Note: Theoretically, in the future we could track the VI configuration and try to detect
|
||||
// when an XFB is the last XFB copy of a frame. Not only would we get a clean "end of
|
||||
// the frame", but we would also be able to use ImmediateXFB even for these games.
|
||||
// Might also clean up some issues with games doing XFB copies they don't intend to
|
||||
// display.
|
||||
|
||||
if (g_ActiveConfig.bImmediateXFB)
|
||||
// Check if we are to copy from the EFB or draw to the XFB
|
||||
if (PE_copy.copy_to_xfb == 0)
|
||||
{
|
||||
// below div two to convert from bytes to pixels - it expects width, not stride
|
||||
g_presenter->ImmediateSwap(destAddr, destStride / 2, destStride, height);
|
||||
// bpmem.zcontrol.pixel_format to PixelFormat::Z24 is when the game wants to copy from
|
||||
// ZBuffer (Zbuffer uses 24-bit Format)
|
||||
bool is_depth_copy = bpmem.zcontrol.pixel_format == PixelFormat::Z24;
|
||||
g_texture_cache->CopyRenderTargetToTexture(
|
||||
destAddr, PE_copy.tp_realFormat(), copy_width, copy_height, destStride, is_depth_copy,
|
||||
srcRect, PE_copy.intensity_fmt && PE_copy.auto_conv, PE_copy.half_scale, 1.0f,
|
||||
s_gammaLUT[PE_copy.gamma], bpmem.triggerEFBCopy.clamp_top,
|
||||
bpmem.triggerEFBCopy.clamp_bottom, bpmem.copyfilter.GetCoefficients());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (system.GetFifoPlayer().IsRunningWithFakeVideoInterfaceUpdates())
|
||||
// We should be able to get away with deactivating the current bbox tracking
|
||||
// here. Not sure if there's a better spot to put this.
|
||||
// the number of lines copied is determined by the y scale * source efb height
|
||||
g_bounding_box->Disable(pixel_shader_manager);
|
||||
|
||||
float yScale;
|
||||
if (PE_copy.scale_invert)
|
||||
yScale = 256.0f / static_cast<float>(bpmem.dispcopyyscale);
|
||||
else
|
||||
yScale = static_cast<float>(bpmem.dispcopyyscale) / 256.0f;
|
||||
|
||||
float num_xfb_lines = 1.0f + bpmem.copyTexSrcWH.y * yScale;
|
||||
|
||||
u32 height = static_cast<u32>(num_xfb_lines);
|
||||
|
||||
DEBUG_LOG_FMT(VIDEO,
|
||||
"RenderToXFB: destAddr: {:08x} | srcRect [{} {} {} {}] | fbWidth: {} | "
|
||||
"fbStride: {} | fbHeight: {} | yScale: {}",
|
||||
destAddr, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom,
|
||||
bpmem.copyTexSrcWH.x + 1, destStride, height, yScale);
|
||||
|
||||
bool is_depth_copy = bpmem.zcontrol.pixel_format == PixelFormat::Z24;
|
||||
g_texture_cache->CopyRenderTargetToTexture(
|
||||
destAddr, EFBCopyFormat::XFB, copy_width, height, destStride, is_depth_copy, srcRect,
|
||||
false, false, yScale, s_gammaLUT[PE_copy.gamma], bpmem.triggerEFBCopy.clamp_top,
|
||||
bpmem.triggerEFBCopy.clamp_bottom, bpmem.copyfilter.GetCoefficients());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
|
||||
// This is as closest as we have to an "end of the frame"
|
||||
// It works 99% of the time.
|
||||
// But sometimes games want to render an XFB larger than the EFB's 640x528 pixel resolution
|
||||
// (especially when using the 3xMSAA mode, which cuts EFB resolution to 640x264). So they
|
||||
// render multiple sub-frames and arrange the XFB copies in next to each-other in main
|
||||
// memory so they form a single completed XFB. See
|
||||
// https://dolphin-emu.org/blog/2017/11/19/hybridxfb/ for examples and more detail.
|
||||
system.GetVideoEvents().after_frame_event.Trigger(system);
|
||||
|
||||
// Note: Theoretically, in the future we could track the VI configuration and try to detect
|
||||
// when an XFB is the last XFB copy of a frame. Not only would we get a clean "end of
|
||||
// the frame", but we would also be able to use ImmediateXFB even for these games.
|
||||
// Might also clean up some issues with games doing XFB copies they don't intend to
|
||||
// display.
|
||||
|
||||
if (g_ActiveConfig.bImmediateXFB)
|
||||
{
|
||||
auto& vi = system.GetVideoInterface();
|
||||
vi.FakeVIUpdate(destAddr, srcRect.GetWidth(), destStride, height);
|
||||
// below div two to convert from bytes to pixels - it expects width, not stride
|
||||
g_presenter->ImmediateSwap(destAddr, destStride / 2, destStride, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (system.GetFifoPlayer().IsRunningWithFakeVideoInterfaceUpdates())
|
||||
{
|
||||
auto& vi = system.GetVideoInterface();
|
||||
vi.FakeVIUpdate(destAddr, srcRect.GetWidth(), destStride, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user