mirror of https://github.com/PCSX2/pcsx2.git
GS:MTL: Use GSTexture base class's clear tracking
This commit is contained in:
parent
d88921bb58
commit
ff9a910c1a
|
@ -395,23 +395,36 @@ void GSDeviceMTL::BeginRenderPass(NSString* name, GSTexture* color, MTLLoadActio
|
|||
|| stencil != m_current_render.stencil_target;
|
||||
GSVector4 color_clear;
|
||||
float depth_clear;
|
||||
int stencil_clear;
|
||||
bool needs_color_clear = false;
|
||||
bool needs_depth_clear = false;
|
||||
bool needs_stencil_clear = false;
|
||||
// Depth and stencil might be the same, so do all invalidation checks before resetting invalidation
|
||||
if (mc && mc->IsInvalidated()) color_load = MTLLoadActionDontCare;
|
||||
if (md && md->IsInvalidated()) depth_load = MTLLoadActionDontCare;
|
||||
if (ms && ms->IsInvalidated()) stencil_load = MTLLoadActionDontCare;
|
||||
if (mc) { mc->ResetInvalidation(); needs_color_clear = mc->GetResetNeedsColorClear(color_clear); }
|
||||
if (md) { md->ResetInvalidation(); needs_depth_clear = md->GetResetNeedsDepthClear(depth_clear); }
|
||||
if (ms) { ms->ResetInvalidation(); needs_stencil_clear = ms->GetResetNeedsStencilClear(stencil_clear); }
|
||||
if (needs_color_clear && color_load != MTLLoadActionDontCare) color_load = MTLLoadActionClear;
|
||||
if (needs_depth_clear && depth_load != MTLLoadActionDontCare) depth_load = MTLLoadActionClear;
|
||||
if (needs_stencil_clear && stencil_load != MTLLoadActionDontCare) stencil_load = MTLLoadActionClear;
|
||||
#define CHECK_CLEAR(tex, load_action, clear, ClearGetter) \
|
||||
if (tex) \
|
||||
{ \
|
||||
if (tex->GetState() == GSTexture::State::Invalidated) \
|
||||
{ \
|
||||
load_action = MTLLoadActionDontCare; \
|
||||
} \
|
||||
else if (tex->GetState() == GSTexture::State::Cleared && load_action != MTLLoadActionDontCare) \
|
||||
{ \
|
||||
clear = tex->ClearGetter(); \
|
||||
load_action = MTLLoadActionClear; \
|
||||
} \
|
||||
}
|
||||
|
||||
CHECK_CLEAR(mc, color_load, color_clear, GetClearColor)
|
||||
CHECK_CLEAR(md, depth_load, depth_clear, GetClearDepth)
|
||||
#undef CHECK_CLEAR
|
||||
// Stencil and depth are one texture, stencil clears aren't supported
|
||||
if (ms && ms->GetState() == GSTexture::State::Invalidated)
|
||||
stencil_load = MTLLoadActionDontCare;
|
||||
needs_new |= mc && color_load == MTLLoadActionClear;
|
||||
needs_new |= md && depth_load == MTLLoadActionClear;
|
||||
needs_new |= ms && stencil_load == MTLLoadActionClear;
|
||||
|
||||
// Reset texture state
|
||||
if (mc) mc->SetState(GSTexture::State::Dirty);
|
||||
if (md) md->SetState(GSTexture::State::Dirty);
|
||||
if (ms) ms->SetState(GSTexture::State::Dirty);
|
||||
|
||||
if (!needs_new)
|
||||
{
|
||||
|
@ -457,8 +470,7 @@ void GSDeviceMTL::BeginRenderPass(NSString* name, GSTexture* color, MTLLoadActio
|
|||
{
|
||||
ms->m_last_write = m_current_draw;
|
||||
desc.stencilAttachment.texture = ms->GetTexture();
|
||||
if (stencil_load == MTLLoadActionClear)
|
||||
desc.stencilAttachment.clearStencil = stencil_clear;
|
||||
assert(stencil_load != MTLLoadActionClear);
|
||||
desc.stencilAttachment.loadAction = stencil_load;
|
||||
}
|
||||
|
||||
|
@ -1423,7 +1435,7 @@ void GSDeviceMTL::AccumulateCommandBufferTime(id<MTLCommandBuffer> buffer)
|
|||
void GSDeviceMTL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
|
||||
{
|
||||
if (!t) return;
|
||||
static_cast<GSTextureMTL*>(t)->RequestColorClear(c);
|
||||
t->SetClearColor(c);
|
||||
}
|
||||
|
||||
void GSDeviceMTL::ClearRenderTarget(GSTexture* t, uint32 c)
|
||||
|
@ -1435,13 +1447,13 @@ void GSDeviceMTL::ClearRenderTarget(GSTexture* t, uint32 c)
|
|||
void GSDeviceMTL::ClearDepth(GSTexture* t)
|
||||
{
|
||||
if (!t) return;
|
||||
static_cast<GSTextureMTL*>(t)->RequestDepthClear(0);
|
||||
t->SetClearDepth(0);
|
||||
}
|
||||
|
||||
void GSDeviceMTL::InvalidateRenderTarget(GSTexture* t)
|
||||
{
|
||||
if (!t) return;
|
||||
static_cast<GSTextureMTL*>(t)->Invalidate();
|
||||
t->SetState(GSTexture::State::Invalidated);
|
||||
}
|
||||
|
||||
std::unique_ptr<GSDownloadTexture> GSDeviceMTL::CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format)
|
||||
|
@ -1468,7 +1480,7 @@ void GSDeviceMTL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
|
|||
if (r.width() < dsize.x || r.height() < dsize.y)
|
||||
dT->FlushClears();
|
||||
else
|
||||
dT->InvalidateClears();
|
||||
dT->SetState(GSTexture::State::Dirty);
|
||||
|
||||
EndRenderPass();
|
||||
|
||||
|
|
|
@ -33,16 +33,6 @@ class GSTextureMTL : public GSTexture
|
|||
MRCOwned<id<MTLTexture>> m_texture;
|
||||
bool m_has_mipmaps = false;
|
||||
|
||||
// In Metal clears happen as a part of render passes instead of as separate steps, but the GSDevice API has it as a separate step
|
||||
// To deal with that, store the fact that a clear was requested here and it'll be applied on the next render pass
|
||||
bool m_needs_color_clear = false;
|
||||
bool m_needs_depth_clear = false;
|
||||
bool m_needs_stencil_clear = false;
|
||||
bool m_invalidated = false;
|
||||
GSVector4 m_clear_color;
|
||||
float m_clear_depth;
|
||||
int m_clear_stencil;
|
||||
|
||||
public:
|
||||
u64 m_last_read = 0; ///< Last time this texture was read by a draw
|
||||
u64 m_last_write = 0; ///< Last time this texture was written by a draw
|
||||
|
@ -52,28 +42,8 @@ public:
|
|||
/// For making fake backbuffers
|
||||
void SetSize(GSVector2i size) { m_size = size; }
|
||||
|
||||
/// Requests the texture be cleared the next time a color render is done
|
||||
void RequestColorClear(GSVector4 color);
|
||||
/// Requests the texture be cleared the next time a depth render is done
|
||||
void RequestDepthClear(float depth);
|
||||
/// Requests the texture be cleared the next time a stencil render is done
|
||||
void RequestStencilClear(int stencil);
|
||||
/// Reads whether a color clear was requested, then clears the request
|
||||
bool GetResetNeedsColorClear(GSVector4& colorOut);
|
||||
/// Reads whether a depth clear was requested, then clears the request
|
||||
bool GetResetNeedsDepthClear(float& depthOut);
|
||||
/// Reads whether a stencil clear was requested, then clears the request
|
||||
bool GetResetNeedsStencilClear(int& stencilOut);
|
||||
/// Flushes requested clears to the texture
|
||||
void FlushClears();
|
||||
/// Marks pending clears as done (e.g. if the whole texture is about to be overwritten)
|
||||
void InvalidateClears();
|
||||
/// Marks the texture as invalid (will load with DontCare)
|
||||
void Invalidate();
|
||||
/// Reads whether the texture has been invalidated, then clears the invalidation
|
||||
bool IsInvalidated() const { return m_invalidated; };
|
||||
/// Clears any invalidation requests
|
||||
void ResetInvalidation() { m_invalidated = false; }
|
||||
|
||||
void* GetNativeHandle() const override;
|
||||
bool Update(const GSVector4i& r, const void* data, int pitch, int layer = 0) override;
|
||||
|
|
|
@ -39,64 +39,14 @@ GSTextureMTL::~GSTextureMTL()
|
|||
{
|
||||
}
|
||||
|
||||
void GSTextureMTL::RequestColorClear(GSVector4 color)
|
||||
{
|
||||
m_needs_color_clear = true;
|
||||
m_invalidated = false;
|
||||
m_clear_color = color;
|
||||
}
|
||||
void GSTextureMTL::RequestDepthClear(float depth)
|
||||
{
|
||||
m_needs_depth_clear = true;
|
||||
m_invalidated = false;
|
||||
m_clear_depth = depth;
|
||||
}
|
||||
void GSTextureMTL::RequestStencilClear(int stencil)
|
||||
{
|
||||
m_needs_stencil_clear = true;
|
||||
m_invalidated = false;
|
||||
m_clear_stencil = stencil;
|
||||
}
|
||||
bool GSTextureMTL::GetResetNeedsColorClear(GSVector4& colorOut)
|
||||
{
|
||||
if (m_needs_color_clear)
|
||||
{
|
||||
m_needs_color_clear = false;
|
||||
colorOut = m_clear_color;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GSTextureMTL::GetResetNeedsDepthClear(float& depthOut)
|
||||
{
|
||||
if (m_needs_depth_clear)
|
||||
{
|
||||
m_needs_depth_clear = false;
|
||||
depthOut = m_clear_depth;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GSTextureMTL::GetResetNeedsStencilClear(int& stencilOut)
|
||||
{
|
||||
if (m_needs_stencil_clear)
|
||||
{
|
||||
m_needs_stencil_clear = false;
|
||||
stencilOut = m_clear_stencil;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GSTextureMTL::FlushClears()
|
||||
{
|
||||
if (!m_needs_color_clear && !m_needs_depth_clear && !m_needs_stencil_clear)
|
||||
if (m_state != GSTexture::State::Cleared)
|
||||
return;
|
||||
|
||||
m_dev->BeginRenderPass(@"Clear",
|
||||
m_needs_color_clear ? this : nullptr, MTLLoadActionLoad,
|
||||
m_needs_depth_clear ? this : nullptr, MTLLoadActionLoad,
|
||||
m_needs_stencil_clear ? this : nullptr, MTLLoadActionLoad);
|
||||
!IsDepthStencil() ? this : nullptr, MTLLoadActionLoad,
|
||||
IsDepthStencil() ? this : nullptr, MTLLoadActionLoad);
|
||||
}
|
||||
|
||||
void* GSTextureMTL::GetNativeHandle() const
|
||||
|
@ -104,19 +54,6 @@ void* GSTextureMTL::GetNativeHandle() const
|
|||
return (__bridge void*)m_texture;
|
||||
}
|
||||
|
||||
void GSTextureMTL::InvalidateClears()
|
||||
{
|
||||
m_needs_color_clear = false;
|
||||
m_needs_depth_clear = false;
|
||||
m_needs_stencil_clear = false;
|
||||
}
|
||||
|
||||
void GSTextureMTL::Invalidate()
|
||||
{
|
||||
InvalidateClears();
|
||||
m_invalidated = true;
|
||||
}
|
||||
|
||||
bool GSTextureMTL::Update(const GSVector4i& r, const void* data, int pitch, int layer)
|
||||
{
|
||||
if (void* buffer = MapWithPitch(r, pitch, layer))
|
||||
|
@ -151,9 +88,9 @@ void* GSTextureMTL::MapWithPitch(const GSVector4i& r, int pitch, int layer)
|
|||
GSDeviceMTL::Map map;
|
||||
|
||||
bool needs_clear = false;
|
||||
if (m_needs_color_clear)
|
||||
if (m_state == GSTexture::State::Cleared)
|
||||
{
|
||||
m_needs_color_clear = false;
|
||||
m_state = GSTexture::State::Dirty;
|
||||
// Not uploading to full texture
|
||||
needs_clear = r.left > 0 || r.top > 0 || r.right < m_size.x || r.bottom < m_size.y;
|
||||
}
|
||||
|
@ -163,7 +100,7 @@ void* GSTextureMTL::MapWithPitch(const GSVector4i& r, int pitch, int layer)
|
|||
{
|
||||
if (needs_clear)
|
||||
{
|
||||
m_needs_color_clear = true;
|
||||
m_state = GSTexture::State::Cleared;
|
||||
m_dev->BeginRenderPass(@"Pre-Upload Clear", this, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
|
||||
}
|
||||
enc = m_dev->GetLateTextureUploadEncoder();
|
||||
|
@ -212,12 +149,6 @@ void GSTextureMTL::Swap(GSTexture* other)
|
|||
#define SWAP(x) std::swap(x, mtex->x)
|
||||
SWAP(m_texture);
|
||||
SWAP(m_has_mipmaps);
|
||||
SWAP(m_needs_color_clear);
|
||||
SWAP(m_needs_depth_clear);
|
||||
SWAP(m_needs_stencil_clear);
|
||||
SWAP(m_clear_color);
|
||||
SWAP(m_clear_depth);
|
||||
SWAP(m_clear_stencil);
|
||||
#undef SWAP
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue