mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-10-11 22:49:56 +00:00
GS/HW: Use sampled area for RT/DS sampling hazards.
This commit is contained in:
@@ -1426,6 +1426,17 @@ static const char* GetPSAA1Name(u32 aa1)
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static const char* GetTexHazardName(u32 tex_hazard)
|
||||
{
|
||||
switch (tex_hazard)
|
||||
{
|
||||
case GSHWDrawConfig::TEX_HAZARD_NONE: return "NONE";
|
||||
case GSHWDrawConfig::TEX_HAZARD_RT: return "RT";
|
||||
case GSHWDrawConfig::TEX_HAZARD_DEPTH: return "DEPTH";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static void DumpPSSelector(DrawConfigWriter& out, const GSHWDrawConfig::PSSelector& ps)
|
||||
{
|
||||
out.WriteLn("aem_fmt: {}", ps.aem_fmt);
|
||||
@@ -1469,7 +1480,6 @@ static void DumpPSSelector(DrawConfigWriter& out, const GSHWDrawConfig::PSSelect
|
||||
out.WriteLn("no_color: {}", ps.no_color);
|
||||
out.WriteLn("no_color1: {}", ps.no_color1);
|
||||
out.WriteLn("channel: {} ({})", GetPSChannelName(static_cast<ChannelFetch>(ps.channel)), ps.channel);
|
||||
out.WriteLn("tex_hazard: {}", ps.tex_hazard);
|
||||
out.WriteLn("dither: {} ({})", GetPSDitherName(ps.dither), ps.dither);
|
||||
out.WriteLn("dither_adjust: {}", ps.dither_adjust);
|
||||
out.WriteLn("zclamp: {}", ps.zclamp);
|
||||
@@ -1608,6 +1618,7 @@ static void DumpConfig(DrawConfigWriter& out, const GSHWDrawConfig& conf,
|
||||
out.WriteLn("topology: {} ({})", GetTopologyName(conf.topology), static_cast<u32>(conf.topology));
|
||||
out.WriteLn("require_one_barrier: {}", conf.require_one_barrier);
|
||||
out.WriteLn("require_full_barrier: {}", conf.require_full_barrier);
|
||||
out.WriteLn("tex_hazard: {}", GetTexHazardName(conf.tex_hazard));
|
||||
|
||||
out.WriteLn("destination_alpha: {} ({})", GetDestinationAlphaModeName(conf.destination_alpha), static_cast<u32>(conf.destination_alpha));
|
||||
out.WriteLn("datm: {} ({})", GetSetDATMName(conf.datm), static_cast<u32>(conf.datm));
|
||||
|
||||
@@ -397,7 +397,6 @@ struct alignas(16) GSHWDrawConfig
|
||||
|
||||
// Others ways to fetch the texture
|
||||
u32 channel : 3;
|
||||
u32 tex_hazard : 2; // 1 rt, 2 ds
|
||||
|
||||
// Dithering
|
||||
u32 dither : 2;
|
||||
@@ -445,7 +444,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
const u32 sw_blend_bits = blend_a | blend_b | blend_d;
|
||||
const bool sw_blend_needs_rt = (sw_blend_bits != 0 && ((sw_blend_bits | blend_c) & 1u)) || ((a_masked & blend_c) != 0);
|
||||
const bool afail_needs_rt = afail == PS_AFAIL::ZB_ONLY || afail == PS_AFAIL::RGB_ONLY || afail == PS_AFAIL::RGB_ONLY_SW_Z;
|
||||
return tex_hazard == 1 || tex_is_fb || fbmask || (date >= 5) || sw_blend_needs_rt || afail_needs_rt;
|
||||
return tex_is_fb || fbmask || (date >= 5) || sw_blend_needs_rt || afail_needs_rt;
|
||||
}
|
||||
|
||||
__fi bool IsFeedbackLoopDepth() const
|
||||
@@ -453,7 +452,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
const bool afail_needs_depth = afail == PS_AFAIL::FB_ONLY || afail == PS_AFAIL::RGB_ONLY_SW_Z;
|
||||
const bool ztst_needs_depth = ztst == ZTST_GEQUAL || ztst == ZTST_GREATER;
|
||||
const bool aa1_needs_depth = aa1 == PS_AA1::TRIANGLE_SW_Z;
|
||||
return tex_hazard == 2 || afail_needs_depth || ztst_needs_depth || aa1_needs_depth;
|
||||
return afail_needs_depth || ztst_needs_depth || aa1_needs_depth;
|
||||
}
|
||||
|
||||
/// Disables color output from the pixel shader, this is done when all channels are masked.
|
||||
@@ -820,10 +819,12 @@ struct alignas(16) GSHWDrawConfig
|
||||
u32 nverts; ///< Number of vertices
|
||||
u32 nindices; ///< Number of indices
|
||||
u32 indices_per_prim; ///< Number of indices that make up one primitive
|
||||
const std::vector<size_t>* drawlist; ///< For reducing barriers on sprites
|
||||
const std::vector<GSVector4i>* drawlist_bbox; ///< For RT copy when barriers not available.
|
||||
const std::vector<size_t>* drawlist; ///< For reducing barriers on sprites
|
||||
const std::vector<GSVector4i>* drawlist_bbox; ///< For RT copy when barriers not available.
|
||||
const std::vector<GSVector4i>* drawlist_bbox_tex; ///< Additionally if we need to sample not from the same pixel of the RT.
|
||||
GSVector4i scissor; ///< Scissor rect
|
||||
GSVector4i drawarea; ///< Area in the framebuffer which will be modified.
|
||||
GSVector4i samplearea; ///< Area in the texture which will be sampled.
|
||||
Topology topology; ///< Draw topology
|
||||
|
||||
alignas(8) PSSelector ps;
|
||||
@@ -837,6 +838,13 @@ struct alignas(16) GSHWDrawConfig
|
||||
bool require_one_barrier; ///< Require texture barrier before draw (also used to requst an rt copy if texture barrier isn't supported)
|
||||
bool require_full_barrier; ///< Require texture barrier between all prims
|
||||
|
||||
enum : u32
|
||||
{
|
||||
TEX_HAZARD_NONE,
|
||||
TEX_HAZARD_RT,
|
||||
TEX_HAZARD_DEPTH,
|
||||
} tex_hazard;
|
||||
|
||||
AlphaTestMode alpha_test;
|
||||
|
||||
DestinationAlphaMode destination_alpha;
|
||||
@@ -877,6 +885,16 @@ struct alignas(16) GSHWDrawConfig
|
||||
GIFRegFRAME colclip_frame;
|
||||
GSVector4i colclip_update_area; ///< Area in the framebuffer which colclip will modify;
|
||||
|
||||
__fi bool IsFeedbackLoopRT(const PSSelector& ps) const
|
||||
{
|
||||
return ps.IsFeedbackLoopRT() || (tex_hazard == TEX_HAZARD_RT);
|
||||
}
|
||||
|
||||
__fi bool IsFeedbackLoopDepth(const PSSelector& ps) const
|
||||
{
|
||||
return ps.IsFeedbackLoopDepth() || (tex_hazard == TEX_HAZARD_DEPTH);
|
||||
}
|
||||
|
||||
// Dumping
|
||||
static void DumpConfig(const std::string& path, const GSHWDrawConfig& conf,
|
||||
bool ps = true, bool vs = true, bool bs = true, bool dss = true, bool ss = true, bool asp = true, bool bmp = true,
|
||||
|
||||
@@ -2948,8 +2948,8 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
draw_ds = m_state.current_ds;
|
||||
}
|
||||
|
||||
const bool rt_feedbackloop_pass1 = config.ps.IsFeedbackLoopRT();
|
||||
const bool rt_feedbackloop_pass2 = config.alpha_second_pass.ps.IsFeedbackLoopRT();
|
||||
const bool rt_feedbackloop_pass1 = config.IsFeedbackLoopRT(config.ps);
|
||||
const bool rt_feedbackloop_pass2 = config.IsFeedbackLoopRT(config.alpha_second_pass.ps);
|
||||
if (draw_rt && (((config.require_one_barrier || (config.require_full_barrier && m_features.multidraw_fb_copy)) &&
|
||||
(rt_feedbackloop_pass1 || rt_feedbackloop_pass2))))
|
||||
{
|
||||
@@ -3034,7 +3034,7 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
|
||||
const bool one_barrier, const bool full_barrier)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if ((one_barrier || full_barrier) && !((config.tex && config.tex == draw_rt) || config.ps.IsFeedbackLoopRT() || config.ps.IsFeedbackLoopDepth())) [[unlikely]]
|
||||
if ((one_barrier || full_barrier) && !((config.tex && config.tex == draw_rt) || config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopDepth(config.ps))) [[unlikely]]
|
||||
Console.Warning("D3D11: Possible unnecessary copy detected.");
|
||||
#endif
|
||||
|
||||
@@ -3080,7 +3080,30 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
|
||||
}
|
||||
|
||||
if (one_barrier)
|
||||
CopyAndBind(ProcessCopyArea(rtsize, config.drawarea));
|
||||
{
|
||||
if (config.tex_hazard)
|
||||
{
|
||||
GSVector4i union_rect = config.drawarea.runion(config.samplearea);
|
||||
u32 size_union = union_rect.width() * union_rect.height();
|
||||
u32 size_indiv = config.drawarea.width() * config.drawarea.height() +
|
||||
config.samplearea.width() * config.samplearea.height();
|
||||
|
||||
// Do an individual copy if the union is larger than the sum of individual areas.
|
||||
if (size_union > size_indiv)
|
||||
{
|
||||
CopyAndBind(ProcessCopyArea(rtsize, config.drawarea));
|
||||
CopyAndBind(ProcessCopyArea(rtsize, config.samplearea));
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyAndBind(ProcessCopyArea(rtsize, union_rect));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyAndBind(ProcessCopyArea(rtsize, config.drawarea));
|
||||
}
|
||||
}
|
||||
|
||||
Draw(config);
|
||||
}
|
||||
|
||||
@@ -4364,8 +4364,8 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
GSTexture12* draw_ds_as_rt = static_cast<GSTexture12*>(m_ds_as_rt);
|
||||
|
||||
const bool feedback_rt = draw_rt && (((config.require_one_barrier || (config.require_full_barrier && m_features.texture_barrier)) && (config.ps.IsFeedbackLoopRT() ||
|
||||
config.alpha_second_pass.ps.IsFeedbackLoopRT())));
|
||||
const bool feedback_rt = draw_rt && (((config.require_one_barrier || (config.require_full_barrier && m_features.texture_barrier)) && (config.IsFeedbackLoopRT(config.ps) ||
|
||||
config.IsFeedbackLoopRT(config.alpha_second_pass.ps))));
|
||||
const bool feedback_depth = draw_ds_as_rt != nullptr;
|
||||
|
||||
if (feedback_rt && !m_features.texture_barrier)
|
||||
@@ -4541,7 +4541,7 @@ void GSDevice12::SendHWDraw(const PipelineSelector& pipe, const GSHWDrawConfig&
|
||||
if (feedback_rt || feedback_depth)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if ((one_barrier || full_barrier) && !(config.ps.IsFeedbackLoopRT() || config.ps.IsFeedbackLoopDepth())) [[unlikely]]
|
||||
if ((one_barrier || full_barrier) && !(config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopDepth(config.ps))) [[unlikely]]
|
||||
Console.Warning("D3D12: Possible unnecessary barrier detected.");
|
||||
#endif
|
||||
if ((one_barrier || full_barrier) && feedback_rt)
|
||||
|
||||
@@ -1351,13 +1351,20 @@ GSVector4 GSRendererHW::RealignTargetTextureCoordinate(const GSTextureCache::Sou
|
||||
return half_offset;
|
||||
}
|
||||
|
||||
GSVector4i GSRendererHW::ComputeBoundingBox(const GSVector2i& rtsize, float rtscale)
|
||||
GSVector4i GSRendererHW::ComputeBoundingBoxRT(const GSVector2i& rtsize, float rtscale)
|
||||
{
|
||||
const GSVector4 offset = GSVector4(-1.0f, 1.0f); // Round value
|
||||
const GSVector4 box = m_vt.m_min.p.upld(m_vt.m_max.p) + offset.xxyy();
|
||||
return GSVector4i(box * GSVector4(rtscale)).rintersect(GSVector4i(0, 0, rtsize.x, rtsize.y));
|
||||
}
|
||||
|
||||
GSVector4i GSRendererHW::ComputeBoundingBoxTex(const GSVector2i& texsize, const GSVector4i& region, float texscale)
|
||||
{
|
||||
const GSVector4 offset = GSVector4(region.xyxy()) + GSVector4(-1.0f, -1.0f, 1.0f, 1.0f); // Region offset + round value
|
||||
const GSVector4 box = m_vt.m_min.t.upld(m_vt.m_max.t) + offset;
|
||||
return GSVector4i(box * GSVector4(texscale)).rintersect(GSVector4i(0, 0, texsize.x, texsize.y));
|
||||
}
|
||||
|
||||
void GSRendererHW::MergeSprite(GSTextureCache::Source* tex)
|
||||
{
|
||||
// Upscaling hack to avoid various line/grid issues
|
||||
@@ -7884,7 +7891,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
auto HandleBarrierHazard = [&](bool src_empty) {
|
||||
if (rt && m_conf.tex == m_conf.rt)
|
||||
{
|
||||
m_conf.ps.tex_hazard = 1;
|
||||
m_conf.tex_hazard = GSHWDrawConfig::TEX_HAZARD_RT;
|
||||
if (m_prim_overlap == PRIM_OVERLAP_NO || src_empty || m_channel_shuffle || !g_gs_device->Features().feedback_loops())
|
||||
m_conf.require_one_barrier = true;
|
||||
else
|
||||
@@ -7900,7 +7907,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
// TODO: Add gpu copies for depth on VK/DX12 that doesn't rely on feedback loops.
|
||||
else if (g_gs_device->Features().feedback_loops())
|
||||
{
|
||||
m_conf.ps.tex_hazard = 2;
|
||||
m_conf.tex_hazard = GSHWDrawConfig::TEX_HAZARD_DEPTH;
|
||||
if (m_prim_overlap == PRIM_OVERLAP_NO || src_empty || m_channel_shuffle)
|
||||
m_conf.require_one_barrier = true;
|
||||
else
|
||||
@@ -8046,7 +8053,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
}
|
||||
|
||||
m_conf.cb_ps.ChannelShuffleOffset = GSVector2((horizontal_offset - m_r.x) * tex->GetScale(), (vertical_offset - m_r.y) * tex->GetScale());
|
||||
m_conf.ps.tex_hazard = 1;
|
||||
m_conf.tex_hazard = GSHWDrawConfig::TEX_HAZARD_RT;
|
||||
target_region = false;
|
||||
source_region.bits = 0;
|
||||
|
||||
@@ -8722,7 +8729,7 @@ void GSRendererHW::EmulateAlphaTestSecondPass()
|
||||
{
|
||||
m_conf.alpha_second_pass.ps.DisableDepthOutput();
|
||||
}
|
||||
if (m_conf.alpha_second_pass.ps.IsFeedbackLoopRT() || m_conf.alpha_second_pass.ps.IsFeedbackLoopDepth())
|
||||
if (m_conf.IsFeedbackLoopRT(m_conf.alpha_second_pass.ps) || m_conf.IsFeedbackLoopDepth(m_conf.alpha_second_pass.ps))
|
||||
{
|
||||
m_conf.alpha_second_pass.require_one_barrier = m_conf.require_one_barrier;
|
||||
m_conf.alpha_second_pass.require_full_barrier = m_conf.require_full_barrier;
|
||||
@@ -8968,6 +8975,9 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
const float rtscale = rt_or_ds->GetScale();
|
||||
const GSVector2i rtsize = rt_or_ds->GetTexture()->GetSize();
|
||||
const GSVector2i rt_unscaled_size = rt_or_ds->GetUnscaledSize();
|
||||
|
||||
const float texscale = tex ? tex->GetScale() : 0.0f;
|
||||
const GSVector2i texsize = tex ? tex->GetTexture()->GetSize() : GSVector2i(0, 0);
|
||||
|
||||
// Vertex shader config
|
||||
float vs_scale_x, vs_scale_y;
|
||||
@@ -9014,7 +9024,12 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
const GSVector4i hacked_scissor = m_channel_shuffle ? GSVector4i::cxpr(0, 0, 1024, 1024) : m_context->scissor.in;
|
||||
const GSVector4i scissor(GSVector4i(GSVector4(rtscale) * GSVector4(hacked_scissor)).rintersect(GSVector4i::loadh(rtsize)));
|
||||
|
||||
m_conf.drawarea = m_channel_shuffle ? scissor : scissor.rintersect(ComputeBoundingBox(rtsize, rtscale));
|
||||
m_conf.drawarea = m_channel_shuffle ? scissor : scissor.rintersect(ComputeBoundingBoxRT(rtsize, rtscale));
|
||||
|
||||
const GSVector4i tex_region = tex ? tex->GetRegionRect() : GSVector4i::zero();
|
||||
m_conf.samplearea = m_channel_shuffle ? scissor :
|
||||
GSVector4i::loadh(texsize).rintersect(ComputeBoundingBoxTex(texsize, tex_region, texscale));
|
||||
|
||||
m_conf.scissor = (date_options.enabled && !date_options.barrier) ? m_conf.drawarea : scissor;
|
||||
|
||||
HandleProvokingVertexFirst();
|
||||
|
||||
@@ -349,7 +349,8 @@ public:
|
||||
bool VerifyIndices();
|
||||
void ExpandLineIndices();
|
||||
GSVector4 RealignTargetTextureCoordinate(const GSTextureCache::Source* tex);
|
||||
GSVector4i ComputeBoundingBox(const GSVector2i& rtsize, float rtscale);
|
||||
GSVector4i ComputeBoundingBoxRT(const GSVector2i& rtsize, float rtscale);
|
||||
GSVector4i ComputeBoundingBoxTex(const GSVector2i& texsize, const GSVector4i& region, float texscale);
|
||||
void MergeSprite(GSTextureCache::Source* tex);
|
||||
float GetTextureScaleFactor() override;
|
||||
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr, const bool is_shuffle = false);
|
||||
|
||||
@@ -2828,7 +2828,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
// Pretty sure GL is supposed to guarantee that the blend unit is coherent with previous pixel write out, so calling this a bug.
|
||||
bool broken_blend_coherency_barrier = false;
|
||||
if (m_bugs.broken_blend_coherency)
|
||||
broken_blend_coherency_barrier = (psel.ps.IsFeedbackLoopRT() || psel.ps.blend_c == 1) && GLState::rt == config.rt;
|
||||
broken_blend_coherency_barrier = (config.IsFeedbackLoopRT(psel.ps) || psel.ps.blend_c == 1) && GLState::rt == config.rt;
|
||||
if (config.require_one_barrier || !m_features.texture_barrier)
|
||||
{
|
||||
broken_blend_coherency_barrier = false;
|
||||
@@ -2929,8 +2929,8 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
glTextureBarrier();
|
||||
}
|
||||
|
||||
const bool rt_feedbackloop_pass1 = config.ps.IsFeedbackLoopRT();
|
||||
const bool rt_feedbackloop_pass2 = config.alpha_second_pass.ps.IsFeedbackLoopRT();
|
||||
const bool rt_feedbackloop_pass1 = config.IsFeedbackLoopRT(config.ps);
|
||||
const bool rt_feedbackloop_pass2 = config.IsFeedbackLoopRT(config.alpha_second_pass.ps);
|
||||
if (draw_rt && !m_features.texture_barrier && (((config.require_one_barrier || (config.require_full_barrier && m_features.multidraw_fb_copy)) &&
|
||||
(rt_feedbackloop_pass1 || rt_feedbackloop_pass2))))
|
||||
{
|
||||
@@ -3039,7 +3039,7 @@ void GSDeviceOGL::SendHWDraw(const GSHWDrawConfig& config,
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if ((one_barrier || full_barrier) &&
|
||||
!((!m_features.texture_barrier && config.tex && config.tex == draw_rt) || config.ps.IsFeedbackLoopRT() || config.ps.IsFeedbackLoopDepth())) [[unlikely]]
|
||||
!((!m_features.texture_barrier && config.tex && config.tex == draw_rt) || config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopDepth(config.ps))) [[unlikely]]
|
||||
Console.Warning("OpenGL: Possible unnecessary barrier detected.");
|
||||
#endif
|
||||
|
||||
@@ -3104,7 +3104,28 @@ void GSDeviceOGL::SendHWDraw(const GSHWDrawConfig& config,
|
||||
else
|
||||
{
|
||||
// Optimization: For alpha second pass we can reuse the copy snapshot from the first pass.
|
||||
CopyAndBind(ProcessCopyArea(rtsize, config.drawarea));
|
||||
if (config.tex_hazard)
|
||||
{
|
||||
GSVector4i union_rect = config.drawarea.runion(config.samplearea);
|
||||
u32 size_union = union_rect.width() * union_rect.height();
|
||||
u32 size_indiv = config.drawarea.width() * config.drawarea.height() +
|
||||
config.samplearea.width() * config.samplearea.height();
|
||||
|
||||
// Do an individual copy if the union is larger than the sum of individual areas.
|
||||
if (size_union > size_indiv)
|
||||
{
|
||||
CopyAndBind(ProcessCopyArea(rtsize, config.drawarea));
|
||||
CopyAndBind(ProcessCopyArea(rtsize, config.samplearea));
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyAndBind(ProcessCopyArea(rtsize, union_rect));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyAndBind(ProcessCopyArea(rtsize, config.drawarea));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5994,7 +5994,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
pipe.feedback_loop_flags |= m_current_framebuffer_feedback_loop;
|
||||
}
|
||||
|
||||
if (draw_rt && ((config.require_one_barrier && (config.ps.IsFeedbackLoopRT() || config.alpha_second_pass.ps.IsFeedbackLoopRT()))) && !m_features.texture_barrier)
|
||||
if (draw_rt && ((config.require_one_barrier && (config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopRT(config.alpha_second_pass.ps)))) && !m_features.texture_barrier)
|
||||
{
|
||||
// Requires a copy of the RT.
|
||||
draw_rt_clone = static_cast<GSTextureVK*>(CreateTexture(rtsize.x, rtsize.y, 1, draw_rt->GetFormat(), true));
|
||||
@@ -6222,10 +6222,10 @@ void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelect
|
||||
pipe.feedback_loop_flags = FeedbackLoopFlag_None;
|
||||
if (m_features.texture_barrier && (config.require_one_barrier || config.require_full_barrier))
|
||||
{
|
||||
if (config.ps.IsFeedbackLoopRT())
|
||||
if (config.IsFeedbackLoopRT(config.ps))
|
||||
pipe.feedback_loop_flags |= FeedbackLoopFlag_ReadAndWriteRT;
|
||||
|
||||
if (config.ps.IsFeedbackLoopDepth())
|
||||
if (config.IsFeedbackLoopDepth(config.ps))
|
||||
pipe.feedback_loop_flags |= FeedbackLoopFlag_ReadAndWriteDepth;
|
||||
}
|
||||
if (!(pipe.feedback_loop_flags & FeedbackLoopFlag_ReadAndWriteDepth))
|
||||
@@ -6297,7 +6297,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if ((one_barrier || full_barrier) && !(m_pipeline_selector.ps.IsFeedbackLoopRT() || m_pipeline_selector.ps.IsFeedbackLoopDepth())) [[unlikely]]
|
||||
if ((one_barrier || full_barrier) && !(config.IsFeedbackLoopRT(m_pipeline_selector.ps) || config.IsFeedbackLoopDepth(m_pipeline_selector.ps))) [[unlikely]]
|
||||
Console.Warning("VK: Possible unnecessary barrier detected.");
|
||||
#endif
|
||||
VkDependencyFlags barrier_flags = GetFeedbackBarrierDependencyFlags();
|
||||
|
||||
Reference in New Issue
Block a user