GS:DX11: Add primid destination alpha support

This commit is contained in:
TellowKrinkle 2022-09-01 03:54:20 -05:00 committed by lightningterror
parent 1b34eb14f8
commit 95ad6b8ab4
3 changed files with 58 additions and 17 deletions

View File

@ -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<std::string> 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<ShaderConvert>(i)));
m_convert.ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *convert_hlsl, sm_convert_ptr, shaderName(static_cast<ShaderConvert>(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)
{

View File

@ -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<ID3D11DepthStencilState> dss;
wil::com_ptr_nothrow<ID3D11BlendState> bs;
wil::com_ptr_nothrow<ID3D11PixelShader> primid_init_ps[2];
} m_date;
// Shaders...

View File

@ -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<D3D11_BLEND, 16> 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<D3D11_BLEND_OP, 3> s_d3d11_blend_ops = { {
D3D11_BLEND_OP_ADD, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_OP_REV_SUBTRACT
static constexpr std::array<D3D11_BLEND_OP, 4> s_d3d11_blend_ops = { {
D3D11_BLEND_OP_ADD, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_BLEND_OP_MIN
} };
// clang-format on