Compare commits

...

14 Commits

Author SHA1 Message Date
refractionpcsx2
4d37e35675 GS/TC: Delete dirty rt's in src lookup + usert in rt on 3 draw old rt's 2025-05-18 11:13:35 +02:00
refractionpcsx2
df3868a280 GS/HW: Avoid target height mistakes on shuffles + Update new src == rt 2025-05-18 11:13:35 +02:00
lightningterror
0799bb8cf1 GS/DX: DX requires a copy to sample the depth buffer. 2025-05-17 22:54:04 +02:00
lightningterror
69048dede4 GS/DX11: Merge CloneTexture with CopyRect.
Unified between renderers, easier to make shared changes.
2025-05-17 22:54:04 +02:00
lightningterror
76df6d1f43 GS/GL: Check for texture creation hazard for fb copy. 2025-05-17 22:54:04 +02:00
refractionpcsx2
2d03b21f2b Formatting: Clean up some if spaces 2025-05-17 22:47:38 +02:00
refractionpcsx2
62cbd44933 GS/HW: Fix up offset Z behaviour + work even when RT isn't offset. 2025-05-17 22:47:38 +02:00
refractionpcsx2
44c8f6d8b0 GS/HW: Correct valid area for depth when taking alpha from rt. Add Tex in RT to Area 51 2025-05-17 22:47:38 +02:00
refractionpcsx2
f3fc1dd59c GS/HW: Fix some regressions relating to overlapping targets and valid rect + rgb 2025-05-17 22:47:38 +02:00
lightningterror
708931e48b GS/HW: Clean up HandleTextureHazards.
Warnings, initializations, dereferencing null pointers.
2025-05-17 22:46:37 +02:00
TheLastRar
81800d2883 CMake: Support more package configurations to import with a Devel build 2025-05-17 09:39:56 -04:00
TellowKrinkle
d0411d7ddf Core:macOS: Initialize all address variables passed to vm_map 2025-05-16 12:41:09 +02:00
Ty
70e232cab3 GitHub: Make authors disclose whether they used AI or not.
Using checkboxes implicitly made it a task list that cluttered up the PR list.

[ci skip]
2025-05-16 12:27:15 +02:00
refractionpcsx2
f90396bda4 GS/DX12: Fix command list not flushing when in surfaceless mode. 2025-05-16 12:25:16 +02:00
40 changed files with 469 additions and 269 deletions

View File

@@ -8,7 +8,4 @@
<!-- If applicable, including examples you've already tested with / recommendations for how to test further is very helpful! -->
### Did you use AI to help find, test, or implement this issue or feature?
<!-- Insert an X in one of the boxes. This is a required field. -->
- [ ] No, I did not use AI.
- [ ] Yes (please explain briefly):
<!-- Answer yes or no. If you answer yes, please provide a brief explanation how. -->

View File

@@ -13656,6 +13656,7 @@ SLED-53440:
name: "Area 51"
region: "PAL-Unk"
gsHWFixes:
textureInsideRT: 1 # Fixes shadows in some scenarios.
halfPixelOffset: 2 # Fixes misaligned lighting and other effects, needs Special otherwise lights flicker.
nativeScaling: 2 # Fixes lights.
SLED-53442:
@@ -20228,6 +20229,7 @@ SLES-52570:
region: "PAL-M5"
compat: 5
gsHWFixes:
textureInsideRT: 1 # Fixes shadows in some scenarios.
halfPixelOffset: 2 # Fixes misaligned lighting and other effects, needs Special otherwise lights flicker.
nativeScaling: 2 # Fixes lights.
SLES-52571:
@@ -21857,6 +21859,7 @@ SLES-53075:
name: "Area 51"
region: "PAL-M5"
gsHWFixes:
textureInsideRT: 1 # Fixes shadows in some scenarios.
halfPixelOffset: 2 # Fixes misaligned lighting and other effects, needs Special otherwise lights flicker.
nativeScaling: 2 # Fixes lights.
SLES-53076:
@@ -28944,6 +28947,7 @@ SLES-55349:
region: "PAL-E"
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
bilinearUpscale: 2 # Fixes sun glare textures.
gpuTargetCLUT: 1 # Fixes sun penetration.
@@ -28966,6 +28970,7 @@ SLES-55350:
region: "PAL-F-G"
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
bilinearUpscale: 2 # Fixes sun glare textures.
gpuTargetCLUT: 1 # Fixes sun penetration.
@@ -28988,6 +28993,7 @@ SLES-55351:
region: "PAL-I-S"
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
bilinearUpscale: 2 # Fixes sun glare textures.
gpuTargetCLUT: 1 # Fixes sun penetration.
@@ -29011,6 +29017,7 @@ SLES-55352:
compat: 5
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
bilinearUpscale: 2 # Fixes sun glare textures.
gpuTargetCLUT: 1 # Fixes sun penetration.
@@ -29033,6 +29040,7 @@ SLES-55353:
region: "PAL-M6"
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
bilinearUpscale: 2 # Fixes sun glare textures.
gpuTargetCLUT: 1 # Fixes sun penetration.
@@ -32190,6 +32198,7 @@ SLKA-25446:
region: "NTSC-K"
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
getSkipCount: "GSC_NFSUndercover"
memcardFilters:
@@ -33055,6 +33064,7 @@ SLPM-55127:
region: "NTSC-J"
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
bilinearUpscale: 2 # Fixes sun glare textures.
gpuTargetCLUT: 1 # Fixes sun penetration.
@@ -33653,6 +33663,7 @@ SLPM-55244:
region: "NTSC-J"
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
bilinearUpscale: 2 # Fixes sun glare textures.
gpuTargetCLUT: 1 # Fixes sun penetration.
@@ -48415,6 +48426,7 @@ SLPM-66468:
name-en: "Area 51"
region: "NTSC-J"
gsHWFixes:
textureInsideRT: 1 # Fixes shadows in some scenarios.
halfPixelOffset: 2 # Fixes misaligned lighting and other effects, needs Special otherwise lights flicker.
nativeScaling: 2 # Fixes lights.
SLPM-66469:
@@ -65100,6 +65112,7 @@ SLUS-20595:
region: "NTSC-U"
compat: 5
gsHWFixes:
textureInsideRT: 1 # Fixes shadows in some scenarios.
halfPixelOffset: 2 # Fixes misaligned lighting and other effects, needs Special otherwise lights flicker.
nativeScaling: 2 # Fixes lights.
SLUS-20596:
@@ -72218,6 +72231,7 @@ SLUS-21801:
compat: 5
gsHWFixes:
recommendedBlendingLevel: 3 # Improves car reflections.
textureInsideRT: 1 # Fixes sun glare.
halfPixelOffset: 2 # Fixes blurriness.
bilinearUpscale: 2 # Fixes sun glare textures.
gpuTargetCLUT: 1 # Fixes sun penetration.

View File

@@ -64,7 +64,8 @@ set(CMAKE_SHARED_LINKER_FLAGS_DEVEL "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}
CACHE STRING "Flags used for linking shared libraries during development builds" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}"
CACHE STRING "Flags used for linking executables during development builds" FORCE)
set(CMAKE_MAP_IMPORTED_CONFIG_DEVEL "RelWithDebInfo" "Release" ""
# Exclude Debug from the configurations we can import from
set(CMAKE_MAP_IMPORTED_CONFIG_DEVEL "RelWithDebInfo" "Release" "MinSizeRel" "None" "NoConfig" ""
CACHE STRING "Configurations used when importing packages for development builds" FORCE)
if(CMAKE_CONFIGURATION_TYPES)
list(INSERT CMAKE_CONFIGURATION_TYPES 0 Devel)

View File

@@ -437,7 +437,7 @@ std::unique_ptr<SharedMemoryMappingArea> SharedMemoryMappingArea::Create(size_t
{
pxAssertRel(Common::IsAlignedPow2(size, __pagesize), "Size is page aligned");
mach_vm_address_t alloc;
mach_vm_address_t alloc = 0;
const kern_return_t res =
mach_vm_map(mach_task_self(), &alloc, size, 0, VM_FLAGS_ANYWHERE,
MEMORY_OBJECT_NULL, 0, false, VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_NONE);

View File

@@ -1455,7 +1455,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode, bool transition_t
}
isSeeking = true;
}
else if(!drive_speed_change_cycles)
else if (!drive_speed_change_cycles)
{
CDVD_LOG("CdSeek Begin > Contiguous block without seek - delta=%d sectors", delta);

View File

@@ -222,7 +222,7 @@ bool IOCtlSrc::ReadDVDInfo()
{
Console.Warning("IOCTL_DVD_READ_STRUCTURE not supported");
}
else if(GetLastError() != ERROR_UNRECOGNIZED_MEDIA) // ERROR_UNRECOGNIZED_MEDIA means probably a CD or no disc
else if (GetLastError() != ERROR_UNRECOGNIZED_MEDIA) // ERROR_UNRECOGNIZED_MEDIA means probably a CD or no disc
{
Console.Warning("IOCTL Unknown Error %d", GetLastError());
}

View File

@@ -236,7 +236,7 @@ static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
cpuClearInt( 10 );
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
}
else if(channel == 2)
else if (channel == 2)
{
cpuClearInt( 11 );
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
@@ -274,7 +274,7 @@ static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
{
func();
}
else if(reg.chcr.STR)
else if (reg.chcr.STR)
{
//DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted

View File

@@ -339,7 +339,7 @@ void GSClut::Read(const GIFRegTEX0& TEX0)
break;
}
}
else if(TEX0.CPSM == PSMCT16 || TEX0.CPSM == PSMCT16S)
else if (TEX0.CPSM == PSMCT16 || TEX0.CPSM == PSMCT16S)
{
switch(TEX0.PSM)
{

View File

@@ -2260,7 +2260,7 @@ void GSState::Move()
vm[doff] = (vm[doff] & 0xff000000) | (vm[soff] & 0x00ffffff);
});
}
else // if(spsm.trbpp == 16)
else // if (spsm.trbpp == 16)
{
u16* vm = m_mem.vm16();
copy(dpo.assertSizesMatch(GSLocalMemory::swizzle16), spo.assertSizesMatch(GSLocalMemory::swizzle16), [vm](u32 doff, u32 soff)

View File

@@ -1236,36 +1236,18 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
D3D11_BOX box = {(UINT)r.left, (UINT)r.top, 0U, (UINT)r.right, (UINT)r.bottom, 1U};
D3D11_BOX box = {static_cast<UINT>(r.left), static_cast<UINT>(r.top), 0U, static_cast<UINT>(r.right), static_cast<UINT>(r.bottom), 1U};
// DX api isn't happy if we pass a box for depth copy
// It complains that depth/multisample must be a full copy
// and asks us to use a NULL for the box
// DX11 doesn't support partial depth copy so we need to
// either pass a nullptr D3D11_BOX for a full depth copy or use CopyResource instead.
// Alternatively use shader copy StretchRect, or full depth copy with
// adjusting the scissor and UVs in the shader.
const bool depth = (sTex->GetType() == GSTexture::Type::DepthStencil);
auto pBox = depth ? nullptr : &box;
const u32 x = depth ? 0 : destX;
const u32 y = depth ? 0 : destY;
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, destX, destY, 0, *(GSTexture11*)sTex, 0, pBox);
}
void GSDevice11::CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect)
{
pxAssertMsg(src->GetType() == GSTexture::Type::DepthStencil || src->GetType() == GSTexture::Type::RenderTarget, "Source is RT or DS.");
CommitClear(src);
const int w = src->GetWidth();
const int h = src->GetHeight();
if (src->GetType() == GSTexture::Type::DepthStencil)
{
// DX11 requires that you copy the entire depth buffer.
*dest = CreateDepthStencil(w, h, src->GetFormat(), false);
CopyRect(src, *dest, GSVector4i(0, 0, w, h), 0, 0);
}
else
{
*dest = CreateRenderTarget(w, h, src->GetFormat(), false);
CopyRect(src, *dest, rect, rect.left, rect.top);
}
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, x, y, 0, *(GSTexture11*)sTex, 0, pBox);
}
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
@@ -2630,20 +2612,33 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
PSSetShaderResource(1, config.pal);
}
GSTexture* rt_copy = nullptr;
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
GSTexture* draw_rt_clone = nullptr;
if (config.require_one_barrier || (config.tex && config.tex == config.rt))
{
// Bind the RT.This way special effect can use it.
// Do not always bind the rt when it's not needed,
// only bind it when effects use it such as fbmask emulation currently
// because we copy the frame buffer and it is quite slow.
CloneTexture(colclip_rt ? colclip_rt : config.rt, &rt_copy, config.drawarea);
if (rt_copy)
// Requires a copy of the RT.
// Used as "bind rt" flag when texture barrier is unsupported for tex is fb.
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
if (draw_rt_clone)
{
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
if (config.require_one_barrier)
PSSetShaderResource(2, rt_copy);
PSSetShaderResource(2, draw_rt_clone);
if (config.tex && config.tex == config.rt)
PSSetShaderResource(0, rt_copy);
PSSetShaderResource(0, draw_rt_clone);
}
}
GSTexture* draw_ds_clone = nullptr;
if (config.tex && config.tex == config.ds)
{
// DX requires a copy when sampling the depth buffer.
draw_ds_clone = CreateDepthStencil(rtsize.x, rtsize.y, config.ds->GetFormat(), false);
if (draw_ds_clone)
{
CopyRect(config.ds, draw_ds_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(0, draw_ds_clone);
}
}
@@ -2697,8 +2692,12 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
DrawIndexedPrimitive();
}
if (rt_copy)
Recycle(rt_copy);
if (draw_rt_clone)
Recycle(draw_rt_clone);
if (draw_ds_clone)
Recycle(draw_ds_clone);
if (primid_tex)
Recycle(primid_tex);

View File

@@ -291,7 +291,6 @@ public:
std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) override;
void CommitClear(GSTexture* t);
void CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect);
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;

View File

@@ -1087,7 +1087,14 @@ GSDevice::PresentResult GSDevice12::BeginPresent(bool frame_skip)
return PresentResult::DeviceLost;
if (frame_skip || !m_swap_chain)
{
if (!m_swap_chain)
{
ExecuteCommandList(WaitType::None);
InvalidateCachedState();
}
return PresentResult::FrameSkipped;
}
// Check if we lost exclusive fullscreen. If so, notify the host, so it can switch to windowed mode.
// This might get called repeatedly if it takes a while to switch back, that's the host's problem.
@@ -3821,6 +3828,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
GSTexture12* draw_rt = static_cast<GSTexture12*>(config.rt);
GSTexture12* draw_ds = static_cast<GSTexture12*>(config.ds);
GSTexture12* draw_rt_clone = nullptr;
GSTexture12* draw_ds_clone = nullptr;
// Align the render area to 128x128, hopefully avoiding render pass restarts for small render area changes (e.g. Ratchet and Clank).
const GSVector2i rtsize(config.rt ? config.rt->GetSize() : config.ds->GetSize());
@@ -3876,7 +3884,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
// bind textures before checking the render pass, in case we need to transition them
if (config.tex)
{
PSSetShaderResource(0, config.tex, config.tex != config.rt);
PSSetShaderResource(0, config.tex, config.tex != config.rt && config.tex != config.ds);
PSSetSampler(config.sampler);
}
if (config.pal)
@@ -3900,15 +3908,16 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
}
}
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
if (config.require_one_barrier || (config.tex && config.tex == config.rt))
{
// requires a copy of the RT
// Requires a copy of the RT.
// Used as "bind rt" flag when texture barrier is unsupported for tex is fb.
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true));
if (draw_rt_clone)
{
EndRenderPass();
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
GL_PUSH("Copy RT to temp texture {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
draw_rt_clone->SetState(GSTexture::State::Invalidated);
@@ -3920,6 +3929,23 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
}
}
if (config.tex && config.tex == config.ds)
{
// DX requires a copy when sampling the depth buffer.
draw_ds_clone = static_cast<GSTexture12*>(CreateDepthStencil(rtsize.x, rtsize.y, config.ds->GetFormat(), false));
if (draw_ds_clone)
{
EndRenderPass();
GL_PUSH("Copy RT to temp texture {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
draw_ds_clone->SetState(GSTexture::State::Invalidated);
CopyRect(config.ds, draw_ds_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(0, draw_ds_clone, true);
}
}
// Switch to colclip target for colclip hw rendering
if (pipe.ps.colclip_hw)
{
@@ -4066,6 +4092,9 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
if (draw_rt_clone)
Recycle(draw_rt_clone);
if (draw_ds_clone)
Recycle(draw_ds_clone);
if (date_image)
Recycle(date_image);

View File

@@ -1037,7 +1037,7 @@ float GSRendererHW::GetTextureScaleFactor()
return GetUpscaleMultiplier();
}
GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex)
GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex, const bool is_shuffle)
{
// Don't blindly expand out to the scissor size if we're not drawing to it.
// e.g. Burnout 3, God of War II, etc.
@@ -1088,10 +1088,9 @@ GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex)
// Early detection of texture shuffles. These double the input height because they're interpreting 64x32 C32 pages as 64x64 C16.
// Why? Well, we don't want to be doubling the heights of targets, but also we don't want to align C32 targets to 64 instead of 32.
// Yumeria's text breaks, and GOW goes to 512x448 instead of 512x416 if we don't.
const bool possible_texture_shuffle =
(tex && m_vt.m_primclass == GS_SPRITE_CLASS && frame_psm.bpp == 16 &&
const bool possible_texture_shuffle = tex && m_vt.m_primclass == GS_SPRITE_CLASS && frame_psm.bpp == 16 &&
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 &&
(tex->m_32_bits_fmt ||
(is_shuffle || (tex->m_32_bits_fmt ||
(m_cached_ctx.TEX0.TBP0 != m_cached_ctx.FRAME.Block() && IsOpaque() && !(m_context->TEX1.MMIN & 1) &&
m_cached_ctx.FRAME.FBMSK && g_texture_cache->Has32BitTarget(m_cached_ctx.FRAME.Block()))));
if (possible_texture_shuffle)
@@ -1128,9 +1127,9 @@ GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex)
return GSVector2i(width, height);
}
GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex, const bool can_expand)
GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex, const bool can_expand, const bool is_shuffle)
{
const GSVector2i valid_size = GetValidSize(tex);
const GSVector2i valid_size = GetValidSize(tex, is_shuffle);
return g_texture_cache->GetTargetSize(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, valid_size.x, valid_size.y, can_expand);
}
@@ -2942,7 +2941,13 @@ void GSRendererHW::Draw()
if (possible_shuffle && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp != 16)
possible_shuffle &= draw_uses_target;
possible_shuffle &= src && (src->m_from_target != nullptr || (m_skip && possible_shuffle));
const bool shuffle_source = src && (src->m_from_target != nullptr || (m_skip && possible_shuffle));
if (!shuffle_source)
{
if(draw_start > src->m_TEX0.TBP0 || draw_end < src->m_TEX0.TBP0)
possible_shuffle &= src && (src->m_from_target != nullptr || (m_skip && possible_shuffle));
}
// We don't know the alpha range of direct sources when we first tried to optimize the alpha test.
// Moving the texture lookup before the ATST optimization complicates things a lot, so instead,
// recompute it, and everything derived from it again if it changes.
@@ -2988,7 +2993,7 @@ void GSRendererHW::Draw()
const bool can_expand = !(m_cached_ctx.ZBUF.ZMSK && output_black);
// Estimate size based on the scissor rectangle and height cache.
GSVector2i t_size = GetTargetSize(src, can_expand);
GSVector2i t_size = GetTargetSize(src, can_expand, possible_shuffle);
const GSVector4i t_size_rect = GSVector4i::loadh(t_size);
// Ensure draw rect is clamped to framebuffer size. Necessary for updating valid area.
@@ -3077,7 +3082,7 @@ void GSRendererHW::Draw()
if (!ds && m_cached_ctx.FRAME.FBP != m_cached_ctx.ZBUF.ZBP)
{
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::DepthStencil,
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src, possible_shuffle), target_scale, GSTextureCache::DepthStencil,
true, 0, false, force_preload, preserve_depth, m_r, src);
if (!ds) [[unlikely]]
{
@@ -3228,7 +3233,7 @@ void GSRendererHW::Draw()
return;
}
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src), (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && scale_draw < 0 && is_possible_mem_clear != ClearType::NormalClear) ? src->m_from_target->GetScale() : target_scale,
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src, possible_shuffle), (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && scale_draw < 0 && is_possible_mem_clear != ClearType::NormalClear) ? src->m_from_target->GetScale() : target_scale,
GSTextureCache::RenderTarget, true, fm, false, force_preload, preserve_rt_color || possible_shuffle, lookup_rect, src);
if (!rt) [[unlikely]]
@@ -3242,6 +3247,49 @@ void GSRendererHW::Draw()
{
rt->UpdateValidity(GSVector4i::loadh(GSVector2i(GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x, GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y)), true);
}
if (src && !src->m_from_target && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp &&
(GSUtil::GetChannelMask(src->m_TEX0.PSM) & GSUtil::GetChannelMask(m_context->FRAME.PSM)) != 0)
{
const u32 draw_end = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r) + 1;
const u32 draw_start = GSLocalMemory::GetStartBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);
if (draw_start <= src->m_TEX0.TBP0 && draw_end > src->m_TEX0.TBP0)
{
g_texture_cache->ReplaceSourceTexture(src, rt->GetTexture(), rt->GetScale(), rt->GetUnscaledSize(), nullptr, true);
src->m_from_target = rt;
src->m_from_target_TEX0 = rt->m_TEX0;
src->m_target_direct = true;
src->m_shared_texture = true;
src->m_target = true;
src->m_texture = rt->m_texture;
src->m_32_bits_fmt = rt->m_32_bits_fmt;
src->m_valid_rect = rt->m_valid;
src->m_alpha_minmax.first = rt->m_alpha_min;
src->m_alpha_minmax.second = rt->m_alpha_max;
const int target_width = std::max(FRAME_TEX0.TBW, 1U);
const int page_offset = (src->m_TEX0.TBP0 - rt->m_TEX0.TBP0) >> 5;
const int vertical_page_offset = page_offset / target_width;
const int horizontal_page_offset = page_offset - (vertical_page_offset * target_width);
if (vertical_page_offset)
{
const int height = std::max(rt->m_valid.w, possible_shuffle ? (m_r.w / 2) : m_r.w);
src->m_region.SetY(vertical_page_offset * GSLocalMemory::m_psm[rt->m_TEX0.PSM].pgs.y, height);
}
if (horizontal_page_offset)
src->m_region.SetX(horizontal_page_offset * GSLocalMemory::m_psm[rt->m_TEX0.PSM].pgs.x, target_width * GSLocalMemory::m_psm[rt->m_TEX0.PSM].pgs.x);
if (rt->m_dirty.empty())
{
RGBAMask rgba_mask;
rgba_mask._u32 = GSUtil::GetChannelMask(rt->m_TEX0.PSM);
g_texture_cache->AddDirtyRectTarget(rt, m_r, FRAME_TEX0.PSM, FRAME_TEX0.TBW, rgba_mask, GSLocalMemory::m_psm[FRAME_TEX0.PSM].trbpp >= 16);
}
}
}
}
else if (rt->m_TEX0.TBP0 != m_cached_ctx.FRAME.Block())
{
@@ -3348,51 +3396,6 @@ void GSRendererHW::Draw()
t_size.x = rt->m_unscaled_size.x - horizontal_offset;
t_size.y = rt->m_unscaled_size.y - vertical_offset;
// Z isn't offset but RT is, so we need a temp Z to align it, hopefully nothing will ever write to the Z too, right??
if (ds && vertical_offset && (m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) != (m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0))
{
m_using_temp_z = true;
const int z_vertical_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) / std::max(rt->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
if (g_texture_cache->GetTemporaryZ() != nullptr)
{
GSTextureCache::TempZAddress z_address_info = g_texture_cache->GetTemporaryZInfo();
if (ds->m_TEX0.TBP0 != z_address_info.ZBP || z_address_info.offset != static_cast<u32>(vertical_offset - z_vertical_offset))
g_texture_cache->InvalidateTemporaryZ();
else if (!m_r.rintersect(z_address_info.rect_since + GSVector4i(0, z_address_info.offset, 0, z_address_info.offset)).rempty() && m_cached_ctx.TEST.ZTST > ZTST_ALWAYS)
{
GL_CACHE("HW: RT in RT Updating Z copy on draw %d z_offset %d", s_n, z_address_info.offset);
GSVector4i dRect = GSVector4i(z_address_info.rect_since.x * ds->m_scale, (z_address_info.offset + z_address_info.rect_since.y) * ds->m_scale, (z_address_info.rect_since.z + (1.0f / ds->m_scale)) * ds->m_scale, (z_address_info.offset + z_address_info.rect_since.w + (1.0f / ds->m_scale)) * ds->m_scale);
g_gs_device->StretchRect(ds->m_texture, GSVector4(z_address_info.rect_since.x / static_cast<float>(ds->m_unscaled_size.x), z_address_info.rect_since.y / static_cast<float>(ds->m_unscaled_size.y), (z_address_info.rect_since.z + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.x), (z_address_info.rect_since.w + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.y)), g_texture_cache->GetTemporaryZ(), GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
z_address_info.rect_since = GSVector4i::zero();
g_texture_cache->SetTemporaryZInfo(z_address_info);
}
}
if (g_texture_cache->GetTemporaryZ() == nullptr)
{
m_temp_z_full_copy = false;
const u32 vertical_size = std::max(rt->m_unscaled_size.y, ds->m_unscaled_size.y);
const GSVector4i dRect = GSVector4i(0, vertical_offset * ds->m_scale, ds->m_unscaled_size.x * ds->m_scale, (vertical_offset + ds->m_unscaled_size.y - z_vertical_offset) * ds->m_scale);
const int new_height = std::max(static_cast<int>(vertical_size * ds->m_scale), dRect.w);
if (GSTexture* tex = g_gs_device->CreateDepthStencil(ds->m_unscaled_size.x * ds->m_scale, new_height, GSTexture::Format::DepthStencil, true))
{
GL_CACHE("HW: RT in RT Z copy on draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
g_gs_device->StretchRect(ds->m_texture, GSVector4(0.0f, z_vertical_offset / static_cast<float>(ds->m_unscaled_size.y), 1.0f, (ds->m_unscaled_size.y - z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y)), tex, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
g_texture_cache->SetTemporaryZ(tex);
g_texture_cache->SetTemporaryZInfo(ds->m_TEX0.TBP0, vertical_offset - z_vertical_offset);
t_size.y = std::max(new_height, t_size.y);
}
else
{
DevCon.Warning("HW: Temporary depth buffer creation failed.");
m_using_temp_z = false;
}
}
}
}
// Don't resize if the BPP don't match.
if (frame_psm.bpp == GSLocalMemory::m_psm[rt->m_TEX0.PSM].bpp)
@@ -3429,6 +3432,106 @@ void GSRendererHW::Draw()
}
}
}
}
// Z or RT are offset from each other, so we need a temp Z to align it
if (ds && rt && (m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) != (m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0))
{
m_using_temp_z = true;
const int page_offset = (static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32);
const int z_vertical_offset = (page_offset / std::max(ds->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int z_horizontal_offset = (page_offset % std::max(ds->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
if (g_texture_cache->GetTemporaryZ() != nullptr)
{
GSTextureCache::TempZAddress z_address_info = g_texture_cache->GetTemporaryZInfo();
const int old_z_vertical_offset = (page_offset / std::max(ds->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int old_z_horizontal_offset = (page_offset % std::max(ds->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
if (ds->m_TEX0.TBP0 != z_address_info.ZBP || z_address_info.offset != page_offset)
g_texture_cache->InvalidateTemporaryZ();
else if (!m_r.rintersect(z_address_info.rect_since).rempty() && m_cached_ctx.TEST.ZTST > ZTST_ALWAYS)
{
GL_CACHE("HW: RT in RT Updating Z copy on draw %d z_offset %d", s_n, z_address_info.offset);
GSVector4 sRect = GSVector4(z_address_info.rect_since.x / static_cast<float>(ds->m_unscaled_size.x), z_address_info.rect_since.y / static_cast<float>(ds->m_unscaled_size.y), (z_address_info.rect_since.z + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.x), (z_address_info.rect_since.w + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.y));
GSVector4i dRect = GSVector4i((old_z_horizontal_offset + z_address_info.rect_since.x) * ds->m_scale, (old_z_vertical_offset + z_address_info.rect_since.y) * ds->m_scale, (old_z_horizontal_offset + z_address_info.rect_since.z + (1.0f / ds->m_scale)) * ds->m_scale, (old_z_vertical_offset + z_address_info.rect_since.w + (1.0f / ds->m_scale)) * ds->m_scale);
sRect = sRect.min(GSVector4(1.0f));
dRect = dRect.min_u32(GSVector4i(ds->m_unscaled_size.x * ds->m_scale, ds->m_unscaled_size.y * ds->m_scale).xyxy());
g_gs_device->StretchRect(ds->m_texture, sRect, g_texture_cache->GetTemporaryZ(), GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
z_address_info.rect_since = GSVector4i::zero();
g_texture_cache->SetTemporaryZInfo(z_address_info);
}
}
if (g_texture_cache->GetTemporaryZ() == nullptr)
{
m_temp_z_full_copy = false;
const int get_next_ctx = m_env.PRIM.CTXT;
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
const int rt_page_offset = (static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32);
const int vertical_page_offset = (rt_page_offset / std::max(static_cast<int>(rt->m_TEX0.TBW), 1));
const int vertical_offset = vertical_page_offset * frame_psm.pgs.y;
const int horizontal_offset = (rt_page_offset - (vertical_page_offset * std::max(static_cast<int>(rt->m_TEX0.TBW), 1))) * frame_psm.pgs.x;
const u32 horizontal_size = std::max(rt->m_unscaled_size.x, ds->m_unscaled_size.x);
const u32 vertical_size = std::max(rt->m_unscaled_size.y, ds->m_unscaled_size.y);
GSVector4i dRect = GSVector4i(horizontal_offset * ds->m_scale, vertical_offset * ds->m_scale, ds->m_unscaled_size.x * ds->m_scale, ds->m_unscaled_size.y * ds->m_scale);
const int new_height = std::max(static_cast<int>(vertical_size * ds->m_scale), dRect.w);
const int new_width = std::max(static_cast<int>(horizontal_size * ds->m_scale), dRect.z);
const int height_diff = new_height - (ds->m_unscaled_size.y * ds->m_scale);
const int width_diff = new_width - (ds->m_unscaled_size.x * ds->m_scale);
if (GSTexture* tex = g_gs_device->CreateDepthStencil(new_width, new_height, GSTexture::Format::DepthStencil, true))
{
GSVector4 sRect = GSVector4(static_cast<float>(z_horizontal_offset) / static_cast<float>(ds->m_unscaled_size.x), static_cast<float>(z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y), 1.0f - (static_cast<float>(horizontal_offset - z_horizontal_offset) / static_cast<float>(ds->m_unscaled_size.x)), 1.0f - (static_cast<float>(vertical_offset - z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y)));
const bool restricted_copy = !(((next_ctx.ZBUF.ZBP == m_context->ZBUF.ZBP && next_ctx.FRAME.FBP == m_context->FRAME.FBP)) && !(IsPossibleChannelShuffle() && !IsPageCopy()));
if (!restricted_copy)
{
if (height_diff)
{
const int adjust = std::min(height_diff, (vertical_offset - z_vertical_offset));
sRect.w += static_cast<float>(adjust) / static_cast<float>(ds->m_unscaled_size.y);
dRect.w += adjust;
}
if (width_diff)
{
const int adjust = std::min(width_diff, (horizontal_offset - z_horizontal_offset));
sRect.z += static_cast<float>(adjust) / static_cast<float>(ds->m_unscaled_size.x);
dRect.z += adjust;
}
}
else
{
// m_r already has horizontal_offset (rt offset) applied)
dRect = GSVector4i(m_r.x * ds->m_scale, m_r.y * ds->m_scale, ((1 + m_r.z) * ds->m_scale), ((1 + m_r.w) * ds->m_scale));
sRect = GSVector4(static_cast<float>((m_r.x - horizontal_offset) + z_horizontal_offset) / static_cast<float>(ds->m_unscaled_size.x), static_cast<float>((m_r.y - vertical_offset) + z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y), (static_cast<float>((m_r.z - horizontal_offset) + z_horizontal_offset) + 1.0f) / static_cast<float>(ds->m_unscaled_size.x), (static_cast<float>((m_r.w - vertical_offset) + z_vertical_offset) + 1.0f) / static_cast<float>(ds->m_unscaled_size.y));
}
// No point in copying more width than the width of the draw, it's going to be wasted (could still be tall, though).
sRect.z = std::min(sRect.z, sRect.x + ((1.0f * ds->m_scale) + (static_cast<float>(m_cached_ctx.FRAME.FBW * 64)) / static_cast<float>(ds->m_unscaled_size.x)));
dRect.z = std::min(dRect.z, dRect.x + static_cast<int>(1 * ds->m_scale) + static_cast<int>(static_cast<float>(m_cached_ctx.FRAME.FBW * 64) * ds->m_scale));
GL_CACHE("HW: RT in RT Z copy on draw %d z_vert_offset %d", s_n, page_offset);
g_gs_device->StretchRect(ds->m_texture, sRect, tex, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
g_texture_cache->SetTemporaryZ(tex);
g_texture_cache->SetTemporaryZInfo(ds->m_TEX0.TBP0, page_offset);
t_size.y = std::max(static_cast<int>(new_height / ds->m_scale), t_size.y);
}
else
{
DevCon.Warning("HW: Temporary depth buffer creation failed.");
m_using_temp_z = false;
}
}
}
if (src && src->m_from_target && src->m_target_direct && src->m_from_target == rt)
@@ -3484,7 +3587,7 @@ void GSRendererHW::Draw()
// This should never happen, but just to be safe..
if (!ds)
{
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::DepthStencil,
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src, possible_shuffle), target_scale, GSTextureCache::DepthStencil,
true, 0, false, force_preload, preserve_depth, m_r, src);
if (!ds) [[unlikely]]
{
@@ -3760,9 +3863,11 @@ void GSRendererHW::Draw()
}
}
const bool blending_cd = PRIM->ABE && !m_context->ALPHA.IsOpaque();
bool valid_width_change = false;
if (rt && ((!is_possible_mem_clear || blending_cd) || rt->m_TEX0.PSM != FRAME_TEX0.PSM) && !m_in_target_draw)
{
if (rt->m_TEX0.TBW != FRAME_TEX0.TBW && !m_cached_ctx.ZBUF.ZMSK && (m_cached_ctx.FRAME.FBMSK & 0xFF000000))
valid_width_change = rt->m_TEX0.TBW != FRAME_TEX0.TBW;
if (valid_width_change && !m_cached_ctx.ZBUF.ZMSK && (m_cached_ctx.FRAME.FBMSK & 0xFF000000))
{
// Alpha could be a font, and since the width is changing it's no longer valid.
// Be careful of downsize copies or other effects, checking Z MSK should hopefully be enough.. (Okami).
@@ -3776,6 +3881,13 @@ void GSRendererHW::Draw()
FRAME_TEX0.TBP0 = rt->m_TEX0.TBP0;
rt->m_TEX0 = FRAME_TEX0;
}
if (valid_width_change)
{
GSVector4i new_valid_width = rt->m_valid;
new_valid_width.z = std::min(new_valid_width.z, static_cast<int>(rt->m_TEX0.TBW) * 64);
rt->ResizeValidity(new_valid_width);
}
}
if (ds && (!is_possible_mem_clear || ds->m_TEX0.PSM != ZBUF_TEX0.PSM || (rt && ds->m_TEX0.TBW != rt->m_TEX0.TBW)) && !m_in_target_draw)
@@ -3785,7 +3897,18 @@ void GSRendererHW::Draw()
ZBUF_TEX0.TBP0 = ds->m_TEX0.TBP0;
ds->m_TEX0 = ZBUF_TEX0;
}
if (valid_width_change)
{
GSVector4i new_valid_width = ds->m_valid;
new_valid_width.z = std::min(new_valid_width.z, static_cast<int>(ds->m_TEX0.TBW) * 64);
ds->ResizeValidity(new_valid_width);
}
}
if (rt)
g_texture_cache->CombineAlignedInsideTargets(rt, src);
if (ds)
g_texture_cache->CombineAlignedInsideTargets(ds, src);
}
else if (!m_texture_shuffle)
{
@@ -3862,7 +3985,7 @@ void GSRendererHW::Draw()
}
// NFS Undercover does a draw with double width of the actual width 1280x240, which functions the same as doubling the height.
// Ignore single page/0 page stuff, that's just gonna get silly
else if (buffer_width > 64 && update_rect.z > buffer_width)
else if (m_texture_shuffle && buffer_width > 64 && update_rect.z > buffer_width)
{
update_rect.w *= static_cast<float>(update_rect.z) / static_cast<float>(buffer_width);
update_rect.z = buffer_width;
@@ -4013,9 +4136,21 @@ void GSRendererHW::Draw()
// Dark cloud writes to 424 when the buffer is only 416 high, but masks the Z.
// Updating the valid causes the Z to overlap the framebuffer, which is obviously incorrect.
const bool z_masked = m_cached_ctx.ZBUF.ZMSK;
const bool z_update = can_update_size && !z_masked;
ds->UpdateValidity(m_r, !z_masked && (can_update_size || m_r.w <= (resolution.y * 2)));
ds->UpdateDrawn(m_r, !z_masked && (can_update_size || m_r.w <= (resolution.y * 2)));
if (rt && m_using_temp_z)
{
const GSLocalMemory::psm_t& z_psm = GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM];
const int vertical_offset = ((static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32) / std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * frame_psm.pgs.y;
const int z_vertical_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) / std::max(static_cast<int>(ds->m_TEX0.TBW), 1)) * z_psm.pgs.y;
const GSVector4i ds_rect = m_r - GSVector4i(vertical_offset - z_vertical_offset);
ds->UpdateValidity(ds_rect, z_update && (can_update_size || (ds_rect.w <= (resolution.y * 2) && !m_texture_shuffle)));
}
else
{
ds->UpdateValidity(m_r, z_update && (can_update_size || m_r.w <= (resolution.y * 2)));
ds->UpdateDrawn(m_r, z_update && (can_update_size || m_r.w <= (resolution.y * 2)));
}
if (!new_rect && new_height && old_end_block != ds->m_end_block)
{
@@ -4240,54 +4375,63 @@ void GSRendererHW::Draw()
}
if (zm != 0xffffffff && ds)
if (ds)
{
const bool z_masked = m_cached_ctx.ZBUF.ZMSK;
const bool was_written = zm != 0xffffffff && m_cached_ctx.DepthWrite();
//ds->m_valid = ds->m_valid.runion(r);
// Limit to 2x the vertical height of the resolution (for double buffering)
ds->UpdateValidity(real_rect, !z_masked && (can_update_size || (real_rect.w <= (resolution.y * 2) && !m_texture_shuffle)));
if (m_using_temp_z)
{
if (m_cached_ctx.DepthWrite())
{
const int get_next_ctx = m_env.PRIM.CTXT;
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
if ((m_state_flush_reason != CONTEXTCHANGE) || (next_ctx.ZBUF.ZBP == m_context->ZBUF.ZBP && next_ctx.FRAME.FBP == m_context->FRAME.FBP))
{
m_temp_z_full_copy = true;
}
else
{
const int vertical_offset = ((static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32) / std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * frame_psm.pgs.y;
const int z_vertical_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) / std::max(rt->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
if (!m_temp_z_full_copy)
{
const GSVector4i dRect = GSVector4i(real_rect.x * ds->m_scale, (z_vertical_offset + (real_rect.y - vertical_offset)) * ds->m_scale, (real_rect.z + (1.0f / ds->m_scale)) * ds->m_scale, (z_vertical_offset + (real_rect.w + (1.0f / ds->m_scale) - vertical_offset)) * ds->m_scale);
const GSVector4 sRect = GSVector4((real_rect.x * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()), static_cast<float>(real_rect.y * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()), ((real_rect.z + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
static_cast<float>((real_rect.w + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
else
{
const GSVector4i dRect = GSVector4i(0, ds->m_valid.y * ds->m_scale, ds->m_valid.z * ds->m_scale, ds->m_valid.w * ds->m_scale);
const GSVector4 sRect = GSVector4((ds->m_valid.x * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()), static_cast<float>((ds->m_valid.y + vertical_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()), ((ds->m_valid.z + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
static_cast<float>(((ds->m_valid.w + vertical_offset) + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
const int get_next_ctx = m_env.PRIM.CTXT;
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
const int z_vertical_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) / std::max(rt->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int z_horizontal_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) % std::max(rt->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
const int vertical_offset = ((static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32) / std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * frame_psm.pgs.y;
const int horizontal_offset = ((static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32) % std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * frame_psm.pgs.x;
m_temp_z_full_copy = false;
if (was_written)
{
const GSVector4i ds_real_rect = real_rect - GSVector4i(vertical_offset - z_vertical_offset);
ds->UpdateValidity(ds_real_rect, !z_masked && (can_update_size || (ds_real_rect.w <= (resolution.y * 2) && !m_texture_shuffle)));
}
if (((m_state_flush_reason != CONTEXTCHANGE) || (next_ctx.ZBUF.ZBP == m_context->ZBUF.ZBP && next_ctx.FRAME.FBP == m_context->FRAME.FBP)) && !(IsPossibleChannelShuffle() && !IsPageCopy()))
{
m_temp_z_full_copy |= was_written;
}
else
{
if (!m_temp_z_full_copy && was_written)
{
GSVector4i dRect = GSVector4i((z_horizontal_offset + (real_rect.x - horizontal_offset)) * ds->m_scale, (z_vertical_offset + (real_rect.y - vertical_offset)) * ds->m_scale, ((z_horizontal_offset + real_rect.z + (1.0f / ds->m_scale)) - horizontal_offset) * ds->m_scale, (z_vertical_offset + (real_rect.w + (1.0f / ds->m_scale) - vertical_offset)) * ds->m_scale);
GSVector4 sRect = GSVector4((real_rect.x * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()), static_cast<float>(real_rect.y * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()), ((real_rect.z + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
static_cast<float>((real_rect.w + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d rt_vert_offset %d z_horz_offset %d rt_horz_offset %d", s_n, z_vertical_offset, vertical_offset, z_horizontal_offset, horizontal_offset);
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
else if (m_temp_z_full_copy)
{
GSVector4i dRect = GSVector4i((ds->m_valid.x + z_horizontal_offset) * ds->m_scale, (ds->m_valid.y + z_vertical_offset) * ds->m_scale, (ds->m_valid.z + z_horizontal_offset + (1.0f / ds->m_scale)) * ds->m_scale, (ds->m_valid.w + z_vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale);
GSVector4 sRect = GSVector4(((ds->m_valid.x + horizontal_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()), static_cast<float>((ds->m_valid.y + vertical_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()), (((ds->m_valid.z + horizontal_offset) + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
static_cast<float>((ds->m_valid.w + vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
m_temp_z_full_copy = false;
}
}
else if (m_cached_ctx.DepthWrite() && g_texture_cache->GetTemporaryZ() != nullptr)
else if (was_written && g_texture_cache->GetTemporaryZ() != nullptr)
{
ds->UpdateValidity(real_rect, !z_masked && (can_update_size || (real_rect.w <= (resolution.y * 2) && !m_texture_shuffle)));
GSTextureCache::TempZAddress z_address_info = g_texture_cache->GetTemporaryZInfo();
if (ds->m_TEX0.TBP0 == z_address_info.ZBP)
{
@@ -6333,7 +6477,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
src_target = rt;
}
// Be careful of single page channel shuffles where depth is the source but it's not going to the same place, we can't read this directly.
else if (ds && m_conf.tex == m_conf.ds && (!m_channel_shuffle || static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) == static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0)))
else if (ds && m_conf.tex == m_conf.ds && (!m_channel_shuffle || (rt && static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) == static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0))))
{
// GL, Vulkan (in General layout), not DirectX!
const bool can_read_current_depth_buffer = g_gs_device->Features().test_and_sample_depth;
@@ -6369,10 +6513,9 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
// We need to copy. Try to cut down the source range as much as possible so we don't copy texels we're not reading.
const GSVector2i& src_unscaled_size = src_target->GetUnscaledSize();
const GSVector4i src_bounds = src_target->GetUnscaledRect();
GSVector4i copy_range;
GSVector2i copy_size;
GSVector2i copy_dst_offset;
const bool copied_rt = src_target && !tex->m_shared_texture;
GSVector4i copy_range = GSVector4i::zero();
GSVector2i copy_size = GSVector2i(0);
GSVector2i copy_dst_offset = GSVector2i(0);
// Shuffles take the whole target. This should've already been halved.
// We can't partially copy depth targets in DirectX, and GL/Vulkan should use the direct read above.
// Restricting it also breaks Tom and Jerry...
@@ -6496,16 +6639,11 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
unscaled_size = copy_size;
scale = m_downscale_source ? 1.0f : src_target->GetScale();
const float src_scale = src_target->GetScale();
GL_CACHE("HW: Copy size: %dx%d, range: %d,%d -> %d,%d (%dx%d) @ %.1f", copy_size.x, copy_size.y, copy_range.x,
copy_range.y, copy_range.z, copy_range.w, copy_range.width(), copy_range.height(), scale);
const GSVector2i scaled_copy_size = GSVector2i(static_cast<int>(std::ceil(static_cast<float>(copy_size.x) * scale)),
static_cast<int>(std::ceil(static_cast<float>(copy_size.y) * scale)));
const GSVector4i scaled_copy_range = GSVector4i((GSVector4(copy_range) * GSVector4(src_scale)).ceil());
const GSVector2i scaled_copy_dst_offset =
GSVector2i(static_cast<int>(std::ceil(static_cast<float>(copy_dst_offset.x) * scale)),
static_cast<int>(std::ceil(static_cast<float>(copy_dst_offset.y) * scale)));
src_copy.reset(src_target->m_texture->IsDepthStencil() ?
g_gs_device->CreateDepthStencil(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), false) :
@@ -6561,6 +6699,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
const GSVector4 src_rect = GSVector4(copy_range) / GSVector4(src_unscaled_size).xyxy();
const GSVector4 dst_rect = (GSVector4(copy_range) - GSVector4(offset).xyxy()) * scale;
g_gs_device->StretchRect(src_target->m_texture, src_rect, src_copy.get(), dst_rect,
src_target->m_texture->IsDepthStencil() ? ShaderConvert::DEPTH_COPY : ShaderConvert::COPY, false);
}

View File

@@ -222,8 +222,8 @@ public:
GSVector4i ComputeBoundingBox(const GSVector2i& rtsize, float rtscale);
void MergeSprite(GSTextureCache::Source* tex);
float GetTextureScaleFactor() override;
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr);
GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true);
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr, const bool is_shuffle = false);
GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true, const bool is_shuffle = false);
void Reset(bool hardware_reset) override;
void UpdateSettings(const Pcsx2Config::GSOptions& old_config) override;

View File

@@ -1107,17 +1107,15 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c
if (dst->m_unscaled_size != t->m_unscaled_size)
{
t->ResizeTexture(t->m_unscaled_size.x, t->m_unscaled_size.y);
t->m_valid = dst->m_valid;
}
CopyRGBFromDepthToColor(t, dst);
}
t->m_valid = t->m_valid.runion(dst->m_valid);
dst = t;
if (GSUtil::GetChannelMask(TEX0.PSM) & 0x8)
t->UnscaleRTAlpha();
// Don't need to de-RTA here as we were actually copying the RGB over, preserving the existing alpha.
inside_target = false;
break;
}
@@ -1410,16 +1408,31 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
if (rect_clean)
{
bool can_use = true;
for (auto& dirty : t->m_dirty)
{
const GSVector4i dirty_rect = dirty.GetDirtyRect(t->m_TEX0, t->m_TEX0.PSM != dirty.psm);
if (!dirty_rect.rintersect(new_rect).rempty())
{
rect_clean = false;
partial |= !new_rect.rintersect(dirty_rect).eq(new_rect) || dirty_rect.eq(new_rect);
if(!dirty_rect.rintersect(t->m_valid).eq(t->m_valid) || GSUtil::GetChannelMask(t->m_TEX0.PSM) != t->m_dirty.GetDirtyChannels())
partial |= !new_rect.rintersect(dirty_rect).eq(new_rect) || dirty_rect.eq(new_rect);
else // Nothing is valid anymore, kill it.
{
can_use = false;
}
break;
}
}
if (!can_use)
{
InvalidateSourcesFromTarget(t);
i = list.erase(i);
delete t;
continue;
}
}
const u32 channel_mask = GSUtil::GetChannelMask(psm);
@@ -1713,7 +1726,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
// If the sizing is completely wrong on the frame vs the source when reading from alpha then it's likely the target has 2 different sizes for rgb and alpha.
// This is just changing the target width for the rect translation, it has no bearing on the actual source read or the target itself.
// Hitman Blood Money is an example of this in the theatre.
const u32 rt_tbw = (possible_shuffle || bw == 1 || GSUtil::GetChannelMask(psm) != 0x8 || frame.FBW <= bw || frame.FBW == t->m_TEX0.TBW) ? t->m_TEX0.TBW : frame.FBW;
const u32 rt_tbw = (possible_shuffle || bw == 1 || GSUtil::GetChannelMask(psm) != 0x8 || frame.FBW <= bw || frame.FBW == t->m_TEX0.TBW || bw == t->m_TEX0.TBW) ? t->m_TEX0.TBW : frame.FBW;
const bool can_translate = CanTranslate(bp, bw, src_psm, new_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, rt_tbw);
if (can_translate)
@@ -2088,6 +2101,10 @@ GSVector2i GSTextureCache::ScaleRenderTargetSize(const GSVector2i& sz, float sca
void GSTextureCache::CombineAlignedInsideTargets(Target* target, GSTextureCache::Source* src)
{
// Don't combine targets if Tex in RT is off, it will just fail to find them and make a new one, causing a loop of copies.
if (GSConfig.UserHacks_TextureInsideRt < GSTextureInRtMode::InsideTargets)
return;
auto& list = m_dst[target->m_type];
for (auto i = list.begin(); i != list.end();)
@@ -2121,12 +2138,17 @@ void GSTextureCache::CombineAlignedInsideTargets(Target* target, GSTextureCache:
const u32 horizontal_offset = page_offset * t_psm.pgs.x;
const GSVector4i target_drect_unscaled = t->m_drawn_since_read + GSVector4i(horizontal_offset, vertical_offset).xyxy();
const GSVector4 source_rect = GSVector4(t->m_drawn_since_read) / (GSVector4(t->m_unscaled_size) * t->GetScale());
const GSVector4 source_rect = GSVector4(t->m_drawn_since_read) / (GSVector4(t->m_unscaled_size).xyxy() * t->GetScale());
const GSVector4 target_drect = GSVector4(target_drect_unscaled) * target->m_scale;
const bool valid_color = t->m_valid_rgb;
const bool valid_alpha = (t->m_valid_alpha_high | t->m_valid_alpha_low) && (GSUtil::GetChannelMask(t->m_TEX0.PSM) & 0x8);
target->m_valid_alpha_high |= t->m_valid_alpha_high;
target->m_valid_alpha_low |= t->m_valid_alpha_low;
GL_CACHE("Combining %x-%x in to %x-%x draw %d", t->m_TEX0.TBP0, t->m_end_block, target->m_TEX0.TBP0, target->m_end_block, GSState::s_n);
g_gs_device->StretchRect(t->m_texture, source_rect, target->m_texture, target_drect, valid_color, valid_color, valid_color, valid_alpha, (target->m_type == RenderTarget) ? ShaderConvert::COPY : ShaderConvert::DEPTH_COPY);
target->UpdateValidity(target_drect_unscaled);
@@ -2270,7 +2292,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
dst->m_32_bits_fmt |= (psm_s.bpp != 16);
break;
}
else if(!(src && src->m_from_target == t))
else if (!(src && src->m_from_target == t))
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to change in target", t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
@@ -2333,11 +2355,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
lookup_rect = lookup_rect & GSVector4i(~8);
const GSVector4i translated_rect = GSVector4i(0, 0, 0, 0).max_i32(TranslateAlignedRectByPage(t, TEX0.TBP0, TEX0.PSM, TEX0.TBW, lookup_rect));
const GSVector4i dirty_rect = t->m_dirty.empty() ? GSVector4i::zero() : t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size).rintersect(t->m_valid);
const GSVector4i dirty_rect = t->m_dirty.empty() ? GSVector4i::zero() : t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size);
const bool all_dirty = dirty_rect.eq(t->m_valid);
if (!is_shuffle && !t->m_dirty.empty() && (!preserve_alpha && !preserve_rgb) && (GSState::s_n - 1) != t->m_last_draw)
if (!is_shuffle && !dirty_rect.rempty() && (!preserve_alpha && !preserve_rgb) && (GSState::s_n - 3) > t->m_last_draw)
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to dirty areas not preserved (Likely change in target)", t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
@@ -2347,7 +2369,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
continue;
}
if (!all_dirty && ((translated_rect.w <= t->m_valid.w) || widthpage_offset == 0 || (GSState::s_n - 1) == t->m_last_draw))
if (!all_dirty && ((translated_rect.w <= t->m_valid.w) || widthpage_offset == 0 || (GSState::s_n - 3) <= t->m_last_draw))
{
if (TEX0.TBW == t->m_TEX0.TBW && !is_shuffle && widthpage_offset == 0 && ((min_rect.w + 63) / 64) > 1)
{
@@ -2593,7 +2615,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
src->m_target_direct = false;
src->m_shared_texture = false;
if(!req_copy)
if (!req_copy)
dst->ResizeTexture(new_size.x, new_size.y, true, true, GSVector4i(dRect), true);
else
{
@@ -2643,7 +2665,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
if ((!is_shuffle && (GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp != GSLocalMemory::m_psm[TEX0.PSM].bpp || GSLocalMemory::m_psm[dst->m_TEX0.PSM].depth != GSLocalMemory::m_psm[TEX0.PSM].depth)) ||
(is_shuffle && GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 16))
{
if(GSLocalMemory::m_psm[dst->m_TEX0.PSM].depth != GSLocalMemory::m_psm[TEX0.PSM].depth || dst->m_TEX0.TBW != TEX0.TBW)
if (GSLocalMemory::m_psm[dst->m_TEX0.PSM].depth != GSLocalMemory::m_psm[TEX0.PSM].depth || dst->m_TEX0.TBW != TEX0.TBW)
dst->m_32_bits_fmt = GSLocalMemory::m_psm[TEX0.PSM].bpp != 16;
if (!is_shuffle || (is_shuffle && GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 16))
@@ -2693,7 +2715,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
}
if (!dst->m_valid_rgb)
const u32 mask = GSLocalMemory::m_psm[TEX0.PSM].fmsk;
if (!dst->m_valid_rgb && ((fbmask & 0x00FFFFFF) & mask) != (mask & 0x00FFFFFF))
{
GL_CACHE("TC: Cannot find RGB target for %s[%x], clearing.", to_string(type), dst->m_TEX0.TBP0);
@@ -2775,11 +2798,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
for (auto i = rev_list.begin(); i != rev_list.end(); ++i)
{
Target* t = *i;
// Don't pull in targets without valid lower 24 bits, it makes no sense to convert them.
// Don't pull in targets without valid lower 24 bits unless the Z is 32bits and the alpha is valid, it makes no sense to convert them otherwise.
// FIXME: Technically the difference in size is fine, but if the target gets reinterpreted, the hw renderer doesn't rearrange the target.
// This does cause some extra uploads in some games (like Burnout), but without this, bad data gets displayed in games like Transformers.
if (bp != t->m_TEX0.TBP0 || !t->m_valid_rgb || (!is_shuffle && t->m_TEX0.TBW != TEX0.TBW &&
(possible_clear || ((~GSLocalMemory::m_psm[t->m_TEX0.PSM].fmsk | fbmask) == 0xffffffff))))
if (bp != t->m_TEX0.TBP0 || (!t->m_valid_rgb && (!(GSUtil::GetChannelMask(TEX0.PSM) & 0x8) || !(t->m_valid_alpha_low || t->m_valid_alpha_high))) ||
(!is_shuffle && t->m_TEX0.TBW != TEX0.TBW && (possible_clear || ((~GSLocalMemory::m_psm[t->m_TEX0.PSM].fmsk | fbmask) == 0xffffffff))))
{
continue;
}
@@ -3014,9 +3037,8 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(GIFRegTEX0 TEX0, const GSVe
if (!is_frame)
{
// Not having this valid could make things explode, but I do enjoy watching the world burn (and this is actually more correct).
dst->m_valid_rgb =true;
const u32 mask = GSLocalMemory::m_psm[TEX0.PSM].fmsk;
dst->m_valid_rgb = GSLocalMemory::m_psm[TEX0.PSM].depth || ((fbmask & 0x00FFFFFF) & mask) != (mask & 0x00FFFFFF) || (dst->m_dirty.GetDirtyChannels() & 0x7);
// If there is an opposite target without valid RGB, we need to match them up
auto& rev_list = m_dst[1 - type];
@@ -3025,9 +3047,6 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(GIFRegTEX0 TEX0, const GSVe
Target* const rev_t = *j;
if (rev_t->m_TEX0.TBP0 == dst->m_TEX0.TBP0 && GSLocalMemory::m_psm[rev_t->m_TEX0.PSM].bpp == GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp)
{
if (GSLocalMemory::m_psm[rev_t->m_TEX0.PSM].trbpp == 24 && ((fbmask & 0x00FFFFFF) & mask) == (mask & 0x00FFFFFF))
dst->m_valid_rgb = false;
if (!rev_t->m_valid_rgb && dst->m_valid_rgb)
rev_t->m_was_dst_matched = true;
@@ -5437,7 +5456,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
src->m_unscaled_size = dst->m_unscaled_size;
src->m_shared_texture = true;
if(channel_shuffle)
if (channel_shuffle)
m_temporary_source = src;
}
@@ -5787,7 +5806,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
src->m_region.SetX(x_offset, x_offset + tw);
src->m_region.SetY(y_offset, y_offset + th);
if(!GSConfig.UserHacks_NativePaletteDraw)
if (!GSConfig.UserHacks_NativePaletteDraw)
m_temporary_source = src;
}
else
@@ -6777,7 +6796,7 @@ GSTextureCache::Source::~Source()
// to recycle.
if (!m_shared_texture && !m_from_hash_cache && m_texture)
{
if(m_from_target)
if (m_from_target)
g_texture_cache->m_target_memory_usage -= m_texture->GetMemUsage();
else
g_texture_cache->m_source_memory_usage -= m_texture->GetMemUsage();

View File

@@ -209,7 +209,7 @@ public:
struct TempZAddress
{
u32 ZBP;
u32 offset;
int offset;
GSVector4i rect_since;
};

View File

@@ -2489,12 +2489,15 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
if (config.require_one_barrier && !m_features.texture_barrier)
{
// Requires a copy of the RT
// Requires a copy of the RT.
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}",
config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
if (draw_rt_clone)
{
GL_PUSH("GL: Copy RT to temp texture {%d,%d %dx%d}",
config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
}
}
IASetVertexBuffer(config.verts, config.nverts);
@@ -2563,7 +2566,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
if (check_barrier && ((config.tex && (config.tex == config.ds || config.tex == config.rt)) || ((psel.ps.IsFeedbackLoop() || psel.ps.blend_c == 1) && GLState::rt == config.rt)))
{
// Ensure all depth writes are finished before sampling
GL_INS("Texture barrier to flush depth or rt before reading");
GL_INS("GL: Texture barrier to flush depth or rt before reading");
glTextureBarrier();
}
// additional non-pipeline config stuff

View File

@@ -1491,7 +1491,7 @@ __ri void GSDrawScanline::CDrawScanline(int pixels, int left, int top, const GSV
case 2: break;
}
if(!(sel.fpsm == 1 && sel.abc == 1))
if (!(sel.fpsm == 1 && sel.abc == 1))
{
switch(sel.abc)
{

View File

@@ -562,7 +562,7 @@ L("loop");
L("step");
// if(steps <= 0) break;
// if (steps <= 0) break;
if (!m_sel.edge)
{
@@ -768,7 +768,7 @@ void GSDrawScanlineCodeGenerator::Init()
cvttps2dq(xym6, vt);
// s = vti.xxxx() + m_local.d[skip].s;
// t = vti.yyyy(); if(!sprite) t += m_local.d[skip].t;
// t = vti.yyyy(); if (!sprite) t += m_local.d[skip].t;
pshufd(s, xym6, _MM_SHUFFLE(0, 0, 0, 0));
pshufd(t, xym6, _MM_SHUFFLE(1, 1, 1, 1));
@@ -925,7 +925,7 @@ void GSDrawScanlineCodeGenerator::Step()
// GSVector4i stq = m_local.d4.stq;
// s += stq.xxxx();
// if(!sprite) t += st.yyyy();
// if (!sprite) t += st.yyyy();
broadcasti128(stq, _rip_local_d(stq));
@@ -2096,7 +2096,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
clamp16(_ga, tmp);
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -2109,7 +2109,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
case TFX_DECAL:
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
// GSVector4i ga = iip ? gaf : m_local.c.ga;
@@ -2139,7 +2139,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
case TFX_HIGHLIGHT2:
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -2990,8 +2990,8 @@ void GSDrawScanlineCodeGenerator::WritePixel(const XYm& src_, const AddressReg&
{
if (fast)
{
// if(fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
// if(fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
// if (fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
// if (fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
test(mask, 0x0000000f << shift);
je("@f");
@@ -3020,10 +3020,10 @@ void GSDrawScanlineCodeGenerator::WritePixel(const XYm& src_, const AddressReg&
}
else
{
// if(fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
// if(fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
// if(fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
// if(fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
// if (fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
// if (fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
// if (fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
// if (fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
test(mask, 0x00000003 << shift);
je("@f");

View File

@@ -158,7 +158,7 @@ void GSDrawScanlineCodeGenerator::Generate()
Label exit;
armAsm->Bind(&m_step_label);
// if(steps <= 0) break;
// if (steps <= 0) break;
if (!m_sel.edge)
{
@@ -332,7 +332,7 @@ void GSDrawScanlineCodeGenerator::Init()
armAsm->Fcvtzs(v6.V4S(), v4.V4S());
// s = vti.xxxx() + m_local.d[skip].s;
// t = vti.yyyy(); if(!sprite) t += m_local.d[skip].t;
// t = vti.yyyy(); if (!sprite) t += m_local.d[skip].t;
armAsm->Dup(_temp_s.V4S(), v6.V4S(), 0);
armAsm->Dup(_temp_t.V4S(), v6.V4S(), 1);
@@ -485,7 +485,7 @@ void GSDrawScanlineCodeGenerator::Step()
// GSVector4i stq = m_local.d4.stq;
// s += stq.xxxx();
// if(!sprite) t += stq.yyyy();
// if (!sprite) t += stq.yyyy();
armAsm->Dup(_vscratch.V4S(), _d4_stq.V4S(), 0);
if (m_sel.prim != GS_SPRITE_CLASS || m_sel.mmin)
@@ -1394,7 +1394,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
modulate16(v6, _temp_ga, 1);
clamp16(v6, v3);
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -1407,7 +1407,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
case TFX_DECAL:
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -1435,7 +1435,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
case TFX_HIGHLIGHT2:
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -2158,8 +2158,8 @@ void GSDrawScanlineCodeGenerator::WritePixel(const VRegister& src, const Registe
{
if (fast)
{
// if(fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
// if(fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
// if (fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
// if (fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
Label skip_low, skip_high;
armAsm->Lsl(_wscratch, addr, 1); // *2
@@ -2177,10 +2177,10 @@ void GSDrawScanlineCodeGenerator::WritePixel(const VRegister& src, const Registe
}
else
{
// if(fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
// if(fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
// if(fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
// if(fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
// if (fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
// if (fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
// if (fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
// if (fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
Label skip_0, skip_1, skip_2, skip_3;

View File

@@ -444,9 +444,9 @@ void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u16* index)
m1 = (y0011 == y1221).mask() & 7;
// if(i == 0) => y0 < y1 < y2
// if(i == 1) => y0 == y1 < y2
// if(i == 4) => y0 < y1 == y2
// if (i == 0) => y0 < y1 < y2
// if (i == 1) => y0 == y1 < y2
// if (i == 4) => y0 < y1 == y2
if (m1 == 7) // y0 == y1 == y2
return;
@@ -623,9 +623,9 @@ void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u16* index)
m1 = (y0011 == y1221).mask() & 7;
// if(i == 0) => y0 < y1 < y2
// if(i == 1) => y0 == y1 < y2
// if(i == 4) => y0 < y1 == y2
// if (i == 0) => y0 < y1 < y2
// if (i == 1) => y0 == y1 < y2
// if (i == 4) => y0 < y1 == y2
if (m1 == 7)
return; // y0 == y1 == y2

View File

@@ -94,7 +94,7 @@ void GSRendererSW::VSync(u32 field, bool registers_written, bool idle_frame)
m_tc->IncAge();
m_draw_transfers.clear();
// if((m_perfmon.GetFrame() & 255) == 0) m_rl->PrintStats();
// if ((m_perfmon.GetFrame() & 255) == 0) m_rl->PrintStats();
}
GSTexture* GSRendererSW::GetOutput(int i, float& scale, int& y_offset)

View File

@@ -515,7 +515,7 @@ void GSSetupPrimCodeGenerator::Color()
pshufd(xym1, xym0, _MM_SHUFFLE(1, 0, 3, 2));
punpcklwd(xym0, xym1);
// if(!tme) c = c.srl16(7);
// if (!tme) c = c.srl16(7);
if (m_sel.tfx == TFX_NONE)
{

View File

@@ -322,7 +322,7 @@ void GSSetupPrimCodeGenerator::Color()
armAsm->Ext(v1.V16B(), v0.V16B(), v0.V16B(), 8);
armAsm->Zip1(v0.V8H(), v0.V8H(), v1.V8H());
// if(!tme) c = c.srl16(7);
// if (!tme) c = c.srl16(7);
if (m_sel.tfx == TFX_NONE)
armAsm->Ushr(v0.V8H(), v0.V8H(), 7);

View File

@@ -10,9 +10,9 @@
#define ipumsk( src ) ( (src) & 0xff )
#define ipucase( src ) case ipumsk(src)
#define IPU_INT_TO( cycles ) if(!(cpuRegs.interrupt & (1<<4))) CPU_INT( DMAC_TO_IPU, cycles )
#define IPU_INT_TO( cycles ) if (!(cpuRegs.interrupt & (1<<4))) CPU_INT( DMAC_TO_IPU, cycles )
#define IPU_INT_FROM( cycles ) CPU_INT( DMAC_FROM_IPU, cycles )
#define IPU_INT_PROCESS( cycles ) if(!(cpuRegs.interrupt & (1 << IPU_PROCESS))) CPU_INT( IPU_PROCESS, cycles )
#define IPU_INT_PROCESS( cycles ) if (!(cpuRegs.interrupt & (1 << IPU_PROCESS))) CPU_INT( IPU_PROCESS, cycles )
//
// Bitfield Structures
//

View File

@@ -190,7 +190,7 @@ static void execI()
#if 0
static long int print_me = 0;
// Based on cycle
// if( cpuRegs.cycle > 0x4f24d714 )
// if ( cpuRegs.cycle > 0x4f24d714 )
// Or dump from a particular PC (useful to debug handler/syscall)
if (pc == 0x80000000)
{

View File

@@ -20,7 +20,7 @@
#define G_GC(reg)
#endif
#define SUM_FLAG if(gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000;
#define SUM_FLAG if (gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000;
#ifdef _MSC_VER_
#pragma warning(disable:4244)

View File

@@ -356,7 +356,7 @@ void ba0W16(u32 mem, u16 value)
s_ba_command_executing = true;
s_ba_error_detected = false;
}
else if(s_ba[0x2] == 0x42) // Read Mode
else if (s_ba[0x2] == 0x42) // Read Mode
{
int size = (s_ba[masked_mem] & 0xF);
@@ -406,7 +406,7 @@ u16 ba0R16(u32 mem)
void MyMemCheck(u32 mem)
{
if( mem == 0x1c02f2a0 )
if ( mem == 0x1c02f2a0 )
Console.WriteLn("yo; (mem == 0x1c02f2a0) in MyMemCheck...");
}

View File

@@ -256,7 +256,7 @@ void iopTestIntc()
// Note: No need to set the iop's branch delta here, since the EE
// will run an IOP branch test regardless.
}
else if( !iopEventTestIsActive )
else if ( !iopEventTestIsActive )
psxSetNextBranchDelta( 2 );
}

View File

@@ -127,9 +127,9 @@ __ri void cpuException(u32 code, u32 bd)
cpuUpdateOperationMode();
return;
}
else if((code & 0x38000) == 0x10000)
else if ((code & 0x38000) == 0x10000)
offset = 0x80; //Performance Counter
else if((code & 0x38000) == 0x18000)
else if ((code & 0x38000) == 0x18000)
offset = 0x100; //Debug
else
Console.Error("Unknown Level 2 Exception!! Cause %x", code);

View File

@@ -1117,7 +1117,7 @@ static void RegWrite_Core(u16 value)
if (!thiscore.DmaMode && !(thiscore.Regs.STATX & 0x400))
thiscore.Regs.STATX &= ~0x80;
else if(!oldDmaMode && thiscore.DmaMode)
else if (!oldDmaMode && thiscore.DmaMode)
thiscore.Regs.STATX |= 0x80;
thiscore.ActiveTSA = thiscore.TSA;

View File

@@ -164,7 +164,7 @@ static int jo_processDU(jo_bits_t *bits, float A[64], const unsigned char htdc[9
jo_writeBits(bits, run, 6);
if (AC < -127) {
jo_writeBits(bits, 128, 12);
} else if(AC > 127) {
} else if (AC > 127) {
jo_writeBits(bits, 0, 12);
}
code = AC & 0xFFF;

View File

@@ -93,7 +93,7 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) {
if(!vifXch.qwc)
vifX.inprogress &= ~0x1;
else if(vifX.irqoffset.value != 0)
else if (vifX.irqoffset.value != 0)
vifX.irqoffset.enabled = true;
}
else

View File

@@ -70,12 +70,12 @@ mem8_t iopHwRead8_Page1( u32 addr )
DevCon.Warning( "HwRead8 from Counter16 [ignored] @ 0x%08x = 0x%02x", addr, psxHu8(addr) );
ret = psxHu8( addr );
}
else if( masked_addr >= 0x480 && masked_addr < 0x4a0 )
else if ( masked_addr >= 0x480 && masked_addr < 0x4a0 )
{
DevCon.Warning( "HwRead8 from Counter32 [ignored] @ 0x%08x = 0x%02x", addr, psxHu8(addr) );
ret = psxHu8( addr );
}
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
else if ( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
{
ret = USBread8( addr );
PSXHW_LOG( "HwRead8 from USB @ 0x%08x = 0x%02x", addr, ret );
@@ -179,7 +179,7 @@ static __fi T _HwRead_16or32_Page1( u32 addr )
// ------------------------------------------------------------------------
// Counters, 32-bit varieties!
//
else if( masked_addr >= 0x480 && masked_addr < 0x4b0 )
else if ( masked_addr >= 0x480 && masked_addr < 0x4b0 )
{
int cntidx = (( masked_addr >> 4 ) & 0xf) - 5;
switch( masked_addr & 0xf )
@@ -218,14 +218,14 @@ static __fi T _HwRead_16or32_Page1( u32 addr )
// ------------------------------------------------------------------------
// USB, with both 16 and 32 bit interfaces
//
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
else if ( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
{
ret = (sizeof(T) == 2) ? USBread16( addr ) : USBread32( addr );
}
// ------------------------------------------------------------------------
// SPU2, accessible in 16 bit mode only!
//
else if( masked_addr >= pgmsk(HW_SPU2_START) && masked_addr < pgmsk(HW_SPU2_END) )
else if ( masked_addr >= pgmsk(HW_SPU2_START) && masked_addr < pgmsk(HW_SPU2_END) )
{
if( sizeof(T) == 2 )
ret = SPU2read( addr );
@@ -238,7 +238,7 @@ static __fi T _HwRead_16or32_Page1( u32 addr )
// ------------------------------------------------------------------------
// PS1 GPU access
//
else if( (masked_addr >= pgmsk(HW_PS1_GPU_START)) && (masked_addr < pgmsk(HW_PS1_GPU_END)) )
else if ( (masked_addr >= pgmsk(HW_PS1_GPU_START)) && (masked_addr < pgmsk(HW_PS1_GPU_END)) )
{
// todo: psx mode: this is new
if( sizeof(T) == 2 )
@@ -418,7 +418,7 @@ mem32_t iopHwRead32_Page8( u32 addr )
ret = g_Sio2.send3[parm];
Sio2Log.WriteLn("%s(%08X) SIO2 SEND3 Read (%08X)", __FUNCTION__, addr, ret);
}
else if( masked_addr < 0x260 )
else if ( masked_addr < 0x260 )
{
// SIO2 Send commands alternate registers. First reg maps to Send1, second
// to Send2, third to Send1, etc. And the following clever code does this:
@@ -426,7 +426,7 @@ mem32_t iopHwRead32_Page8( u32 addr )
ret = (masked_addr & 4) ? g_Sio2.send2[parm] : g_Sio2.send1[parm];
Sio2Log.WriteLn("%s(%08X) SIO2 SEND1/2 Read (%08X)", __FUNCTION__, addr, ret);
}
else if( masked_addr <= 0x280 )
else if ( masked_addr <= 0x280 )
{
switch( masked_addr )
{
@@ -471,7 +471,7 @@ mem32_t iopHwRead32_Page8( u32 addr )
break;
}
}
else if( masked_addr >= pgmsk(HW_FW_START) && masked_addr <= pgmsk(HW_FW_END) )
else if ( masked_addr >= pgmsk(HW_FW_START) && masked_addr <= pgmsk(HW_FW_END) )
{
ret = FWread32( addr );
} else {

View File

@@ -104,12 +104,12 @@ void iopHwWrite8_Page1( u32 addr, mem8_t val )
DbgCon.Warning( "HwWrite8 to Counter16 [ignored] @ addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
psxHu8( addr ) = val;
}
else if( masked_addr >= 0x480 && masked_addr < 0x4a0 )
else if ( masked_addr >= 0x480 && masked_addr < 0x4a0 )
{
DbgCon.Warning( "HwWrite8 to Counter32 [ignored] @ addr 0x%08x = 0x%02x", addr, psxHu8(addr) );
psxHu8( addr ) = val;
}
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
else if ( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
{
USBwrite8( addr, val );
}
@@ -219,7 +219,7 @@ static __fi void _HwWrite_16or32_Page1( u32 addr, T val )
// ------------------------------------------------------------------------
// Counters, 32-bit varieties!
//
else if( masked_addr >= 0x480 && masked_addr < 0x4b0 )
else if ( masked_addr >= 0x480 && masked_addr < 0x4b0 )
{
int cntidx = (( masked_addr >> 4 ) & 0xf) - 5;
switch( masked_addr & 0xf )
@@ -252,14 +252,14 @@ static __fi void _HwWrite_16or32_Page1( u32 addr, T val )
// ------------------------------------------------------------------------
// USB, with both 16 and 32 bit interfaces
//
else if( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
else if ( (masked_addr >= pgmsk(HW_USB_START)) && (masked_addr < pgmsk(HW_USB_END)) )
{
if( sizeof(T) == 2 ) USBwrite16( addr, val ); else USBwrite32( addr, val );
}
// ------------------------------------------------------------------------
// SPU2, accessible in 16 bit mode only!
//
else if( (masked_addr >= pgmsk(HW_SPU2_START)) && (masked_addr < pgmsk(HW_SPU2_END)) )
else if ( (masked_addr >= pgmsk(HW_SPU2_START)) && (masked_addr < pgmsk(HW_SPU2_END)) )
{
if( sizeof(T) == 2 )
SPU2write( addr, val );
@@ -272,7 +272,7 @@ static __fi void _HwWrite_16or32_Page1( u32 addr, T val )
// ------------------------------------------------------------------------
// PS1 GPU access
//
else if( (masked_addr >= pgmsk(HW_PS1_GPU_START)) && (masked_addr < pgmsk(HW_PS1_GPU_END)) )
else if ( (masked_addr >= pgmsk(HW_PS1_GPU_START)) && (masked_addr < pgmsk(HW_PS1_GPU_END)) )
{
// todo: psx mode: this is new
if( sizeof(T) == 2 )
@@ -599,7 +599,7 @@ void iopHwWrite32_Page8( u32 addr, mem32_t val )
const int parm = (masked_addr - 0x200) / 4;
g_Sio2.SetSend3(parm, val);
}
else if( masked_addr < 0x260 )
else if ( masked_addr < 0x260 )
{
// SIO2 Send commands alternate registers. First reg maps to Send1, second
// to Send2, third to Send1, etc. And the following clever code does this:
@@ -617,7 +617,7 @@ void iopHwWrite32_Page8( u32 addr, mem32_t val )
g_Sio2.send1[parm] = val;
}
}
else if( masked_addr <= 0x280 )
else if ( masked_addr <= 0x280 )
{
switch( masked_addr )
{
@@ -661,7 +661,7 @@ void iopHwWrite32_Page8( u32 addr, mem32_t val )
break;
}
}
else if( masked_addr >= pgmsk(HW_FW_START) && masked_addr <= pgmsk(HW_FW_END) )
else if ( masked_addr >= pgmsk(HW_FW_START) && masked_addr <= pgmsk(HW_FW_END) )
{
FWwrite32( addr, val );
}

View File

@@ -161,7 +161,7 @@ static __ri const char* _ioplog_GetHwName( u32 addr, T val )
default: return "Invalid Counter";
}
}
else if( addr >= 0x1f801480 && addr < 0x1f8014b0 )
else if ( addr >= 0x1f801480 && addr < 0x1f8014b0 )
{
switch( addr & 0xf )
{
@@ -174,20 +174,20 @@ static __ri const char* _ioplog_GetHwName( u32 addr, T val )
default: return "Invalid Counter";
}
}
else if( (addr >= HW_USB_START) && (addr < HW_USB_END) )
else if ( (addr >= HW_USB_START) && (addr < HW_USB_END) )
{
return "USB";
}
else if( (addr >= HW_SPU2_START) && (addr < HW_SPU2_END) )
else if ( (addr >= HW_SPU2_START) && (addr < HW_SPU2_END) )
{
return "SPU2";
}
else if( addr >= pgmsk(HW_FW_START) && addr <= pgmsk(HW_FW_END) )
else if ( addr >= pgmsk(HW_FW_START) && addr <= pgmsk(HW_FW_END) )
{
return "FW";
}
else if( addr >= 0x1f808200 && addr < 0x1f808240 ) { return "SIO2 param"; }
else if( addr >= 0x1f808240 && addr < 0x1f808260 ) { return "SIO2 send"; }
else if ( addr >= 0x1f808200 && addr < 0x1f808240 ) { return "SIO2 param"; }
else if ( addr >= 0x1f808240 && addr < 0x1f808260 ) { return "SIO2 send"; }
return NULL; //"Unknown";
}

View File

@@ -648,7 +648,7 @@ static OperandType vtlbUnmappedPReadSm(u32 addr) {
}
return 0;
}
static RETURNS_R128 vtlbUnmappedPReadLg(u32 addr) { vtlb_BusError(addr, 0); if(!CHECK_EEREC && CHECK_CACHE && CheckCache(addr)){ return readCache128(addr, false); } return r128_zero(); }
static RETURNS_R128 vtlbUnmappedPReadLg(u32 addr) { vtlb_BusError(addr, 0); if (!CHECK_EEREC && CHECK_CACHE && CheckCache(addr)){ return readCache128(addr, false); } return r128_zero(); }
template <typename OperandType>
static void vtlbUnmappedPWriteSm(u32 addr, OperandType data) {
@@ -663,7 +663,7 @@ static void vtlbUnmappedPWriteSm(u32 addr, OperandType data) {
}
}
}
static void TAKES_R128 vtlbUnmappedPWriteLg(u32 addr, r128 data) { vtlb_BusError(addr, 1); if(!CHECK_EEREC && CHECK_CACHE && CheckCache(addr)) { writeCache128(addr, reinterpret_cast<mem128_t*>(&data) /*Safe??*/, false); }}
static void TAKES_R128 vtlbUnmappedPWriteLg(u32 addr, r128 data) { vtlb_BusError(addr, 1); if (!CHECK_EEREC && CHECK_CACHE && CheckCache(addr)) { writeCache128(addr, reinterpret_cast<mem128_t*>(&data) /*Safe??*/, false); }}
// clang-format on
// --------------------------------------------------------------------------------------

View File

@@ -1356,7 +1356,7 @@ static void iBranchTest(u32 newpc)
// Check the Event scheduler if our "cycle target" has been reached.
// Equiv code to:
// cpuRegs.cycle += blockcycles;
// if( cpuRegs.cycle > g_nextEventCycle ) { DoEvents(); }
// if ( cpuRegs.cycle > g_nextEventCycle ) { DoEvents(); }
if (EmuConfig.Speedhacks.WaitLoop && s_nBlockFF && newpc == s_branchTo)
{

View File

@@ -247,7 +247,7 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit)
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
}
}
else if(isEbit)
else if (isEbit)
{
if (EmuConfig.Gamefixes.VUSyncHack || EmuConfig.Gamefixes.FullVU0SyncHack)
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);

View File

@@ -1949,7 +1949,7 @@ mVUop(mVU_B)
pass2
{
if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddr(mVU)); }
if (mVUlow.evilBranch) { if(isEvilBlock) xMOV(ptr32[&mVU.evilevilBranch], branchAddr(mVU)); else xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU)); }
if (mVUlow.evilBranch) { if (isEvilBlock) xMOV(ptr32[&mVU.evilevilBranch], branchAddr(mVU)); else xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU)); }
mVU.profiler.EmitOp(opB);
}
pass3 { mVUlog("B [<a href=\"#addr%04x\">%04x</a>]", branchAddr(mVU), branchAddr(mVU)); }