mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
GS/DX11: Implement depth testing and sampling.
When tex is depth, instead of copying the depth if it needs to be read only we can instead simultaneously bind a read only depth stencil view and shader resource view at the same time with no cost avoiding copies. If the z buffer is read only then no copies are created and can be safely read. If the z buffer isn't safe to be read then a copy was already created on a previous pass so we don't have to create another copy on the following pass for reading and doing testing.
This commit is contained in:
parent
49f4c36b0e
commit
2534cb2c9d
@ -55,7 +55,7 @@ GSDevice11::GSDevice11()
|
||||
m_features.framebuffer_fetch = false;
|
||||
m_features.stencil_buffer = true;
|
||||
m_features.cas_sharpening = true;
|
||||
m_features.test_and_sample_depth = false;
|
||||
m_features.test_and_sample_depth = true;
|
||||
}
|
||||
|
||||
GSDevice11::~GSDevice11() = default;
|
||||
@ -978,7 +978,7 @@ void GSDevice11::EndPresent()
|
||||
KickTimestampQuery();
|
||||
|
||||
// clear out the swap chain view, it might get resized..
|
||||
OMSetRenderTargets(nullptr, nullptr, nullptr);
|
||||
OMSetRenderTargets(nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool GSDevice11::CreateTimestampQueries()
|
||||
@ -2453,7 +2453,7 @@ void GSDevice11::OMSetBlendState(ID3D11BlendState* bs, u8 bf)
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor)
|
||||
void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor, ID3D11DepthStencilView* read_only_dsv)
|
||||
{
|
||||
ID3D11RenderTargetView* rtv = nullptr;
|
||||
ID3D11DepthStencilView* dsv = nullptr;
|
||||
@ -2463,7 +2463,11 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
|
||||
CommitClear(rt);
|
||||
rtv = *static_cast<GSTexture11*>(rt);
|
||||
}
|
||||
if (ds)
|
||||
if (read_only_dsv)
|
||||
{
|
||||
dsv = read_only_dsv;
|
||||
}
|
||||
else if (ds)
|
||||
{
|
||||
CommitClear(ds);
|
||||
dsv = *static_cast<GSTexture11*>(ds);
|
||||
@ -2698,24 +2702,14 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
Console.Warning("D3D11: Failed to allocate temp texture for DS copy.");
|
||||
}
|
||||
|
||||
SetupVS(config.vs, &config.cb_vs);
|
||||
SetupPS(config.ps, &config.cb_ps, config.sampler);
|
||||
|
||||
// Depth testing and sampling, bind resource as dsv read only and srv at the same time without the need of a copy.
|
||||
ID3D11DepthStencilView* read_only_dsv = nullptr;
|
||||
if (config.tex && config.tex == config.ds)
|
||||
read_only_dsv = static_cast<GSTexture11*>(config.ds)->ReadOnlyDepthStencilView();
|
||||
|
||||
if (primid_texture)
|
||||
{
|
||||
OMDepthStencilSelector dss = config.depth;
|
||||
@ -2723,7 +2717,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
const OMBlendSelector blend(GSHWDrawConfig::ColorMaskSelector(1),
|
||||
GSHWDrawConfig::BlendState(true, CONST_ONE, CONST_ONE, 3 /* MIN */, CONST_ONE, CONST_ZERO, false, 0));
|
||||
SetupOM(dss, blend, 0);
|
||||
OMSetRenderTargets(primid_texture, config.ds, &config.scissor);
|
||||
OMSetRenderTargets(primid_texture, config.ds, &config.scissor, read_only_dsv);
|
||||
DrawIndexedPrimitive();
|
||||
|
||||
config.ps.date = 3;
|
||||
@ -2749,7 +2743,11 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
draw_ds = m_state.cached_dsv;
|
||||
}
|
||||
|
||||
OMSetRenderTargets(draw_rt, draw_ds, &config.scissor);
|
||||
// Update again as it may have changed.
|
||||
if (config.tex && config.tex == config.ds)
|
||||
read_only_dsv = static_cast<GSTexture11*>(draw_ds)->ReadOnlyDepthStencilView();
|
||||
|
||||
OMSetRenderTargets(draw_rt, draw_ds, &config.scissor, read_only_dsv);
|
||||
SetupOM(config.depth, OMBlendSelector(config.colormask, config.blend), config.blend.constant);
|
||||
DrawIndexedPrimitive();
|
||||
|
||||
@ -2782,9 +2780,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
if (draw_rt_clone)
|
||||
Recycle(draw_rt_clone);
|
||||
|
||||
if (draw_ds_clone)
|
||||
Recycle(draw_ds_clone);
|
||||
|
||||
if (primid_texture)
|
||||
Recycle(primid_texture);
|
||||
|
||||
|
||||
@ -334,7 +334,7 @@ public:
|
||||
|
||||
void OMSetDepthStencilState(ID3D11DepthStencilState* dss, u8 sref);
|
||||
void OMSetBlendState(ID3D11BlendState* bs, u8 bf);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = nullptr);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = nullptr, ID3D11DepthStencilView* read_only_dsv = nullptr);
|
||||
void SetViewport(const GSVector2i& viewport);
|
||||
void SetScissor(const GSVector4i& scissor);
|
||||
|
||||
|
||||
@ -173,6 +173,24 @@ GSTexture11::operator ID3D11UnorderedAccessView*()
|
||||
return m_uav.get();
|
||||
}
|
||||
|
||||
ID3D11DepthStencilView* GSTexture11::ReadOnlyDepthStencilView()
|
||||
{
|
||||
if (!m_read_only_dsv)
|
||||
{
|
||||
if (m_desc.Format == DXGI_FORMAT_R32G8X24_TYPELESS || m_desc.Format == DXGI_FORMAT_D32_FLOAT_S8X24_UINT)
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC desc = {};
|
||||
desc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||
desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
desc.Flags = D3D11_DSV_READ_ONLY_DEPTH;
|
||||
|
||||
GSDevice11::GetInstance()->GetD3DDevice()->CreateDepthStencilView(m_texture.get(), &desc, m_read_only_dsv.put());
|
||||
}
|
||||
}
|
||||
|
||||
return m_read_only_dsv.get();
|
||||
}
|
||||
|
||||
GSDownloadTexture11::GSDownloadTexture11(wil::com_ptr_nothrow<ID3D11Texture2D> tex, u32 width, u32 height, GSTexture::Format format)
|
||||
: GSDownloadTexture(width, height, format)
|
||||
, m_texture(std::move(tex))
|
||||
|
||||
@ -17,6 +17,7 @@ class GSTexture11 final : public GSTexture
|
||||
wil::com_ptr_nothrow<ID3D11RenderTargetView> m_rtv;
|
||||
wil::com_ptr_nothrow<ID3D11DepthStencilView> m_dsv;
|
||||
wil::com_ptr_nothrow<ID3D11UnorderedAccessView> m_uav;
|
||||
wil::com_ptr_nothrow<ID3D11DepthStencilView> m_read_only_dsv;
|
||||
D3D11_TEXTURE2D_DESC m_desc;
|
||||
|
||||
public:
|
||||
@ -41,6 +42,8 @@ public:
|
||||
operator ID3D11RenderTargetView*();
|
||||
operator ID3D11DepthStencilView*();
|
||||
operator ID3D11UnorderedAccessView*();
|
||||
|
||||
ID3D11DepthStencilView* ReadOnlyDepthStencilView();
|
||||
};
|
||||
|
||||
class GSDownloadTexture11 final : public GSDownloadTexture
|
||||
|
||||
@ -6787,7 +6787,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
// 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 || (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!
|
||||
// GL, Vulkan (in General layout), DirectX11 (binding dsv as read only) no support for DirectX12 yet!
|
||||
const bool can_read_current_depth_buffer = g_gs_device->Features().test_and_sample_depth;
|
||||
|
||||
// If this is our current Z buffer, we might not be able to read it directly if it's being written to.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user