mirror of https://github.com/PCSX2/pcsx2.git
GS/Vulkan: PrimID DATE doesn't need feedback loop
This commit is contained in:
parent
904345ff82
commit
e8293b2e06
|
@ -270,7 +270,7 @@ struct alignas(16) GSHWDrawConfig
|
|||
|
||||
__fi bool IsFeedbackLoop() const
|
||||
{
|
||||
return tex_is_fb || fbmask || date > 0 || blend_a == 1 || blend_b == 1 || blend_c == 1 || blend_d == 1;
|
||||
return tex_is_fb || fbmask || (date > 0 && date != 3) || blend_a == 1 || blend_b == 1 || blend_c == 1 || blend_d == 1;
|
||||
}
|
||||
|
||||
/// Disables color output from the pixel shader, this is done when all channels are masked.
|
||||
|
|
|
@ -248,7 +248,7 @@ bool GSDeviceVK::CheckFeatures()
|
|||
m_features.texture_barrier = GSConfig.OverrideTextureBarriers != 0;
|
||||
m_features.broken_point_sampler = isAMD;
|
||||
m_features.geometry_shader = features.geometryShader && GSConfig.OverrideGeometryShaders != 0;
|
||||
m_features.image_load_store = features.fragmentStoresAndAtomics && m_features.texture_barrier;
|
||||
m_features.image_load_store = features.fragmentStoresAndAtomics;
|
||||
m_features.prefer_new_textures = true;
|
||||
m_features.provoking_vertex_last = g_vulkan_context->GetOptionalExtensions().vk_ext_provoking_vertex;
|
||||
m_features.dual_source_blend = features.dualSrcBlend && !GSConfig.DisableDualSourceBlend;
|
||||
|
@ -2718,7 +2718,7 @@ void GSDeviceVK::SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVect
|
|||
EndRenderPass();
|
||||
}
|
||||
|
||||
GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, PipelineSelector& pipe)
|
||||
GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config)
|
||||
{
|
||||
// How this is done:
|
||||
// - can't put a barrier for the image in the middle of the normal render pass, so that's out
|
||||
|
@ -2742,6 +2742,7 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe
|
|||
|
||||
// if the depth target has been cleared, we need to preserve that clear
|
||||
const VkAttachmentLoadOp ds_load_op = GetLoadOpForTexture(static_cast<GSTextureVK*>(config.ds));
|
||||
const u32 ds = (config.ds ? 1 : 0);
|
||||
|
||||
VkClearValue cv[2] = {};
|
||||
cv[0].color.float32[0] = static_cast<float>(std::numeric_limits<int>::max());
|
||||
|
@ -2749,11 +2750,11 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe
|
|||
{
|
||||
cv[1].depthStencil.depth = static_cast<GSTextureVK*>(config.ds)->GetClearDepth();
|
||||
cv[1].depthStencil.stencil = 1;
|
||||
BeginClearRenderPass(m_date_image_setup_render_passes[pipe.ds][1], GSVector4i(0, 0, rtsize.x, rtsize.y), cv, 2);
|
||||
BeginClearRenderPass(m_date_image_setup_render_passes[ds][1], GSVector4i(0, 0, rtsize.x, rtsize.y), cv, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
BeginClearRenderPass(m_date_image_setup_render_passes[pipe.ds][0], config.drawarea, cv, 1);
|
||||
BeginClearRenderPass(m_date_image_setup_render_passes[ds][0], config.drawarea, cv, 1);
|
||||
}
|
||||
|
||||
// draw the quad to prefill the image
|
||||
|
@ -2765,7 +2766,7 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe
|
|||
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
|
||||
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
|
||||
};
|
||||
const VkPipeline pipeline = m_date_image_setup_pipelines[pipe.ds][config.datm];
|
||||
const VkPipeline pipeline = m_date_image_setup_pipelines[ds][config.datm];
|
||||
SetPipeline(pipeline);
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
|
||||
if (ApplyUtilityState())
|
||||
|
@ -2776,24 +2777,25 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe
|
|||
IASetIndexBuffer(config.indices, config.nindices);
|
||||
|
||||
// cut down the configuration for the prepass, we don't need blending or any feedback loop
|
||||
PipelineSelector init_pipe(m_pipeline_selector);
|
||||
init_pipe.dss.zwe = false;
|
||||
init_pipe.cms.wrgba = 0;
|
||||
init_pipe.bs = {};
|
||||
init_pipe.feedback_loop = false;
|
||||
init_pipe.rt = true;
|
||||
init_pipe.ps.blend_a = init_pipe.ps.blend_b = init_pipe.ps.blend_c = init_pipe.ps.blend_d = false;
|
||||
init_pipe.ps.date += 10;
|
||||
init_pipe.ps.no_color = false;
|
||||
init_pipe.ps.no_color1 = true;
|
||||
if (BindDrawPipeline(init_pipe))
|
||||
PipelineSelector& pipe = m_pipeline_selector;
|
||||
UpdateHWPipelineSelector(config, pipe);
|
||||
pipe.dss.zwe = false;
|
||||
pipe.cms.wrgba = 0;
|
||||
pipe.bs = {};
|
||||
pipe.feedback_loop = false;
|
||||
pipe.rt = true;
|
||||
pipe.ps.blend_a = pipe.ps.blend_b = pipe.ps.blend_c = pipe.ps.blend_d = false;
|
||||
pipe.ps.date += 10;
|
||||
pipe.ps.no_color = false;
|
||||
pipe.ps.no_color1 = true;
|
||||
if (BindDrawPipeline(pipe))
|
||||
DrawIndexedPrimitive();
|
||||
|
||||
// image is initialized/prepass is done, so finish up and get ready to do the "real" draw
|
||||
EndRenderPass();
|
||||
|
||||
// .. by setting it to DATE=3
|
||||
pipe.ps.date = 3;
|
||||
config.ps.date = 3;
|
||||
config.alpha_second_pass.ps.date = 3;
|
||||
|
||||
// and bind the image to the primitive sampler
|
||||
|
@ -2836,11 +2838,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
|||
SetVSConstantBuffer(config.cb_vs);
|
||||
SetPSConstantBuffer(config.cb_ps);
|
||||
|
||||
// figure out the pipeline
|
||||
UpdateHWPipelineSelector(config);
|
||||
|
||||
// bind textures before checking the render pass, in case we need to transition them
|
||||
PipelineSelector& pipe = m_pipeline_selector;
|
||||
if (config.tex)
|
||||
{
|
||||
PSSetShaderResource(0, config.tex, config.tex != config.rt);
|
||||
|
@ -2855,8 +2853,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
|||
GSTextureVK* date_image = nullptr;
|
||||
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking)
|
||||
{
|
||||
pxAssert(pipe.feedback_loop);
|
||||
date_image = SetupPrimitiveTrackingDATE(config, pipe);
|
||||
date_image = SetupPrimitiveTrackingDATE(config);
|
||||
if (!date_image)
|
||||
{
|
||||
Console.WriteLn("Failed to allocate DATE image, aborting draw.");
|
||||
|
@ -2864,6 +2861,10 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
|||
}
|
||||
}
|
||||
|
||||
// figure out the pipeline
|
||||
PipelineSelector& pipe = m_pipeline_selector;
|
||||
UpdateHWPipelineSelector(config, pipe);
|
||||
|
||||
// Align the render area to 128x128, hopefully avoiding render pass restarts for small render area changes (e.g. Ratchet and Clank).
|
||||
const int render_area_alignment = 128 * GSConfig.UpscaleMultiplier;
|
||||
const GSVector2i rtsize(config.rt ? config.rt->GetSize() : config.ds->GetSize());
|
||||
|
@ -3118,26 +3119,25 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
|||
}
|
||||
}
|
||||
|
||||
void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config)
|
||||
void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe)
|
||||
{
|
||||
m_pipeline_selector.vs.key = config.vs.key;
|
||||
m_pipeline_selector.gs.key = config.gs.key;
|
||||
m_pipeline_selector.ps.key_hi = config.ps.key_hi;
|
||||
m_pipeline_selector.ps.key_lo = config.ps.key_lo;
|
||||
m_pipeline_selector.dss.key = config.depth.key;
|
||||
m_pipeline_selector.bs.key = config.blend.key;
|
||||
m_pipeline_selector.bs.constant = 0; // don't dupe states with different alpha values
|
||||
m_pipeline_selector.cms.key = config.colormask.key;
|
||||
m_pipeline_selector.topology = static_cast<u32>(config.topology);
|
||||
m_pipeline_selector.rt = config.rt != nullptr;
|
||||
m_pipeline_selector.ds = config.ds != nullptr;
|
||||
m_pipeline_selector.line_width = config.line_expand;
|
||||
m_pipeline_selector.feedback_loop = m_features.texture_barrier &&
|
||||
(config.ps.IsFeedbackLoop() || config.require_one_barrier || config.require_full_barrier ||
|
||||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking);
|
||||
pipe.vs.key = config.vs.key;
|
||||
pipe.gs.key = config.gs.key;
|
||||
pipe.ps.key_hi = config.ps.key_hi;
|
||||
pipe.ps.key_lo = config.ps.key_lo;
|
||||
pipe.dss.key = config.depth.key;
|
||||
pipe.bs.key = config.blend.key;
|
||||
pipe.bs.constant = 0; // don't dupe states with different alpha values
|
||||
pipe.cms.key = config.colormask.key;
|
||||
pipe.topology = static_cast<u32>(config.topology);
|
||||
pipe.rt = config.rt != nullptr;
|
||||
pipe.ds = config.ds != nullptr;
|
||||
pipe.line_width = config.line_expand;
|
||||
pipe.feedback_loop = m_features.texture_barrier &&
|
||||
(config.ps.IsFeedbackLoop() || config.require_one_barrier || config.require_full_barrier);
|
||||
|
||||
// enable point size in the vertex shader if we're rendering points regardless of upscaling.
|
||||
m_pipeline_selector.vs.point_size |= (config.topology == GSHWDrawConfig::Topology::Point);
|
||||
pipe.vs.point_size |= (config.topology == GSHWDrawConfig::Topology::Point);
|
||||
}
|
||||
|
||||
void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt)
|
||||
|
|
|
@ -240,7 +240,7 @@ public:
|
|||
u32 dLevel, bool linear);
|
||||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox);
|
||||
GSTextureVK* SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, PipelineSelector& pipe);
|
||||
GSTextureVK* SetupPrimitiveTrackingDATE(GSHWDrawConfig& config);
|
||||
|
||||
void IASetVertexBuffer(const void* vertex, size_t stride, size_t count);
|
||||
bool IAMapVertexBuffer(void** vertex, size_t stride, size_t count);
|
||||
|
@ -257,7 +257,7 @@ public:
|
|||
bool BindDrawPipeline(const PipelineSelector& p);
|
||||
|
||||
void RenderHW(GSHWDrawConfig& config) override;
|
||||
void UpdateHWPipelineSelector(GSHWDrawConfig& config);
|
||||
void UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe);
|
||||
void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue