diff --git a/pcsx2/GS/Renderers/DX11/GSDevice11.cpp b/pcsx2/GS/Renderers/DX11/GSDevice11.cpp index 682864f21a..60136023e9 100644 --- a/pcsx2/GS/Renderers/DX11/GSDevice11.cpp +++ b/pcsx2/GS/Renderers/DX11/GSDevice11.cpp @@ -45,7 +45,7 @@ GSDevice11::GSDevice11() m_state.bf = -1; m_features.geometry_shader = true; - m_features.primitive_id = false; + m_features.primitive_id = true; m_features.texture_barrier = false; m_features.provoking_vertex_last = false; m_features.point_expand = false; @@ -132,11 +132,11 @@ bool GSDevice11::Create(HostDisplay* display) ShaderMacro sm_model(m_shader_cache.GetFeatureLevel()); - shader = Host::ReadResourceFileToString("shaders/dx11/convert.fx"); - if (!shader.has_value()) + std::optional convert_hlsl = Host::ReadResourceFileToString("shaders/dx11/convert.fx"); + if (!convert_hlsl.has_value()) return false; if (!m_shader_cache.GetVertexShaderAndInputLayout(m_dev.get(), m_convert.vs.put(), m_convert.il.put(), - il_convert, std::size(il_convert), *shader, sm_model.GetPtr(), "vs_main")) + il_convert, std::size(il_convert), *convert_hlsl, sm_model.GetPtr(), "vs_main")) { return false; } @@ -148,7 +148,7 @@ bool GSDevice11::Create(HostDisplay* display) for (size_t i = 0; i < std::size(m_convert.ps); i++) { - m_convert.ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *shader, sm_convert_ptr, shaderName(static_cast(i))); + m_convert.ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *convert_hlsl, sm_convert_ptr, shaderName(static_cast(i))); if (!m_convert.ps[i]) return false; } @@ -341,6 +341,14 @@ bool GSDevice11::Create(HostDisplay* display) m_dev->CreateBlendState(&blend, m_date.bs.put()); + for (size_t i = 0; i < std::size(m_date.primid_init_ps); i++) + { + const std::string entry_point(StringUtil::StdStringFromFormat("ps_stencil_image_init_%d", i)); + m_date.primid_init_ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *convert_hlsl, sm_model.GetPtr(), entry_point.c_str()); + if (!m_date.primid_init_ps[i]) + return false; + } + return true; } @@ -462,7 +470,7 @@ GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int width, int height case GSTexture::Format::UNorm8: dxformat = DXGI_FORMAT_A8_UNORM; break; case GSTexture::Format::UInt16: dxformat = DXGI_FORMAT_R16_UINT; break; case GSTexture::Format::UInt32: dxformat = DXGI_FORMAT_R32_UINT; break; - case GSTexture::Format::PrimID: dxformat = DXGI_FORMAT_R32_SINT; break; + case GSTexture::Format::PrimID: dxformat = DXGI_FORMAT_R32_FLOAT; break; case GSTexture::Format::BC1: dxformat = DXGI_FORMAT_BC1_UNORM; break; case GSTexture::Format::BC2: dxformat = DXGI_FORMAT_BC2_UNORM; break; case GSTexture::Format::BC3: dxformat = DXGI_FORMAT_BC3_UNORM; break; @@ -1336,7 +1344,6 @@ static GSDevice11::OMBlendSelector convertSel(GSHWDrawConfig::ColorMaskSelector /// Clears things we don't support that can be quietly disabled static void preprocessSel(GSDevice11::PSSelector& sel) { - ASSERT(sel.date == 0); // In-shader destination alpha not supported and shouldn't be sent ASSERT(sel.write_rg == 0); // Not supported, shouldn't be sent } @@ -1345,7 +1352,16 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) ASSERT(!config.require_full_barrier); // We always specify no support so it shouldn't request this preprocessSel(config.ps); - if (config.destination_alpha != GSHWDrawConfig::DestinationAlphaMode::Off) + GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize(); + + GSTexture* primid_tex = nullptr; + if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking) + { + primid_tex = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::PrimID, false); + StretchRect(config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(), + primid_tex, GSVector4(config.drawarea), m_date.primid_init_ps[config.datm].get(), nullptr, false); + } + else if (config.destination_alpha != GSHWDrawConfig::DestinationAlphaMode::Off) { const GSVector4 src = GSVector4(config.drawarea) / GSVector4(config.ds->GetSize()).xyxy(); const GSVector4 dst = src * 2.0f - 1.0f; @@ -1364,10 +1380,9 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) GSTexture* hdr_rt = nullptr; if (config.ps.hdr) { - const GSVector2i size = config.rt->GetSize(); const GSVector4 dRect(config.drawarea); - const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy(); - hdr_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::FloatColor); + const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy(); + hdr_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::FloatColor); // Warning: StretchRect must be called before BeginScene otherwise // vertices will be overwritten. Trust me you don't want to do that. StretchRect(config.rt, sRect, hdr_rt, dRect, ShaderConvert::COPY, false); @@ -1391,8 +1406,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) } IASetPrimitiveTopology(topology); - OMSetRenderTargets(hdr_rt ? hdr_rt : config.rt, config.ds, &config.scissor); - PSSetShaderResources(config.tex, config.pal); GSTexture* rt_copy = nullptr; @@ -1422,11 +1435,35 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) PSSetShaderResource(0, ds_copy); } - SetupOM(config.depth, convertSel(config.colormask, config.blend), config.blend.constant); SetupVS(config.vs, &config.cb_vs); SetupGS(config.gs); SetupPS(config.ps, &config.cb_ps, config.sampler); + if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking) + { + OMDepthStencilSelector dss = config.depth; + dss.zwe = 0; + OMBlendSelector blend; + blend.wrgba = 0; + blend.wr = 1; + blend.blend_enable = 1; + blend.blend_src_factor = CONST_ONE; + blend.blend_dst_factor = CONST_ONE; + blend.blend_op = 3; // MIN + SetupOM(dss, blend, 0); + OMSetRenderTargets(primid_tex, config.ds, &config.scissor); + + DrawIndexedPrimitive(); + + config.ps.date = 3; + config.alpha_second_pass.ps.date = 3; + SetupPS(config.ps, nullptr, config.sampler); + PSSetShaderResource(3, primid_tex); + } + + SetupOM(config.depth, convertSel(config.colormask, config.blend), config.blend.constant); + OMSetRenderTargets(hdr_rt ? hdr_rt : config.rt, config.ds, &config.scissor); + DrawIndexedPrimitive(); if (config.separate_alpha_pass) @@ -1474,6 +1511,8 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config) Recycle(rt_copy); if (ds_copy) Recycle(ds_copy); + if (primid_tex) + Recycle(primid_tex); if (hdr_rt) { diff --git a/pcsx2/GS/Renderers/DX11/GSDevice11.h b/pcsx2/GS/Renderers/DX11/GSDevice11.h index e27966ed46..d08655f918 100644 --- a/pcsx2/GS/Renderers/DX11/GSDevice11.h +++ b/pcsx2/GS/Renderers/DX11/GSDevice11.h @@ -111,7 +111,7 @@ private: // Increment this constant whenever shaders change, to invalidate user's shader cache. static constexpr u32 SHADER_VERSION = 1; - static constexpr u32 MAX_TEXTURES = 3; + static constexpr u32 MAX_TEXTURES = 4; static constexpr u32 MAX_SAMPLERS = 2; int m_d3d_texsize; @@ -209,6 +209,7 @@ private: { wil::com_ptr_nothrow dss; wil::com_ptr_nothrow bs; + wil::com_ptr_nothrow primid_init_ps[2]; } m_date; // Shaders... diff --git a/pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp b/pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp index 9d188cb85a..9762463973 100644 --- a/pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp +++ b/pcsx2/GS/Renderers/DX11/GSTextureFX11.cpp @@ -164,6 +164,7 @@ void GSDevice11::SetupPS(const PSSelector& sel, const GSHWDrawConfig::PSConstant sm.AddMacro("PS_AEM", sel.aem); sm.AddMacro("PS_TFX", sel.tfx); sm.AddMacro("PS_TCC", sel.tcc); + sm.AddMacro("PS_DATE", sel.date); sm.AddMacro("PS_ATST", sel.atst); sm.AddMacro("PS_FOG", sel.fog); sm.AddMacro("PS_IIP", sel.iip); @@ -290,8 +291,8 @@ static constexpr std::array s_d3d11_blend_factors = { { D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_INV_DEST_ALPHA, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA, D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_ONE, D3D11_BLEND_ZERO } }; -static constexpr std::array s_d3d11_blend_ops = { { - D3D11_BLEND_OP_ADD, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_OP_REV_SUBTRACT +static constexpr std::array s_d3d11_blend_ops = { { + D3D11_BLEND_OP_ADD, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_OP_MIN } }; // clang-format on