GS/Vulkan: PrimID DATE doesn't need feedback loop

This commit is contained in:
Connor McLaughlin 2022-03-28 21:25:34 +10:00 committed by refractionpcsx2
parent 904345ff82
commit e8293b2e06
3 changed files with 43 additions and 43 deletions

View File

@ -270,7 +270,7 @@ struct alignas(16) GSHWDrawConfig
__fi bool IsFeedbackLoop() const __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. /// Disables color output from the pixel shader, this is done when all channels are masked.

View File

@ -248,7 +248,7 @@ bool GSDeviceVK::CheckFeatures()
m_features.texture_barrier = GSConfig.OverrideTextureBarriers != 0; m_features.texture_barrier = GSConfig.OverrideTextureBarriers != 0;
m_features.broken_point_sampler = isAMD; m_features.broken_point_sampler = isAMD;
m_features.geometry_shader = features.geometryShader && GSConfig.OverrideGeometryShaders != 0; 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.prefer_new_textures = true;
m_features.provoking_vertex_last = g_vulkan_context->GetOptionalExtensions().vk_ext_provoking_vertex; m_features.provoking_vertex_last = g_vulkan_context->GetOptionalExtensions().vk_ext_provoking_vertex;
m_features.dual_source_blend = features.dualSrcBlend && !GSConfig.DisableDualSourceBlend; 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(); EndRenderPass();
} }
GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, PipelineSelector& pipe) GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config)
{ {
// How this is done: // How this is done:
// - can't put a barrier for the image in the middle of the normal render pass, so that's out // - 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 // 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 VkAttachmentLoadOp ds_load_op = GetLoadOpForTexture(static_cast<GSTextureVK*>(config.ds));
const u32 ds = (config.ds ? 1 : 0);
VkClearValue cv[2] = {}; VkClearValue cv[2] = {};
cv[0].color.float32[0] = static_cast<float>(std::numeric_limits<int>::max()); 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.depth = static_cast<GSTextureVK*>(config.ds)->GetClearDepth();
cv[1].depthStencil.stencil = 1; 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 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 // 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.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)}, {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); SetPipeline(pipeline);
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices)); IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
if (ApplyUtilityState()) if (ApplyUtilityState())
@ -2776,24 +2777,25 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe
IASetIndexBuffer(config.indices, config.nindices); IASetIndexBuffer(config.indices, config.nindices);
// cut down the configuration for the prepass, we don't need blending or any feedback loop // cut down the configuration for the prepass, we don't need blending or any feedback loop
PipelineSelector init_pipe(m_pipeline_selector); PipelineSelector& pipe = m_pipeline_selector;
init_pipe.dss.zwe = false; UpdateHWPipelineSelector(config, pipe);
init_pipe.cms.wrgba = 0; pipe.dss.zwe = false;
init_pipe.bs = {}; pipe.cms.wrgba = 0;
init_pipe.feedback_loop = false; pipe.bs = {};
init_pipe.rt = true; pipe.feedback_loop = false;
init_pipe.ps.blend_a = init_pipe.ps.blend_b = init_pipe.ps.blend_c = init_pipe.ps.blend_d = false; pipe.rt = true;
init_pipe.ps.date += 10; pipe.ps.blend_a = pipe.ps.blend_b = pipe.ps.blend_c = pipe.ps.blend_d = false;
init_pipe.ps.no_color = false; pipe.ps.date += 10;
init_pipe.ps.no_color1 = true; pipe.ps.no_color = false;
if (BindDrawPipeline(init_pipe)) pipe.ps.no_color1 = true;
if (BindDrawPipeline(pipe))
DrawIndexedPrimitive(); DrawIndexedPrimitive();
// image is initialized/prepass is done, so finish up and get ready to do the "real" draw // image is initialized/prepass is done, so finish up and get ready to do the "real" draw
EndRenderPass(); EndRenderPass();
// .. by setting it to DATE=3 // .. by setting it to DATE=3
pipe.ps.date = 3; config.ps.date = 3;
config.alpha_second_pass.ps.date = 3; config.alpha_second_pass.ps.date = 3;
// and bind the image to the primitive sampler // and bind the image to the primitive sampler
@ -2836,11 +2838,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
SetVSConstantBuffer(config.cb_vs); SetVSConstantBuffer(config.cb_vs);
SetPSConstantBuffer(config.cb_ps); SetPSConstantBuffer(config.cb_ps);
// figure out the pipeline
UpdateHWPipelineSelector(config);
// bind textures before checking the render pass, in case we need to transition them // bind textures before checking the render pass, in case we need to transition them
PipelineSelector& pipe = m_pipeline_selector;
if (config.tex) if (config.tex)
{ {
PSSetShaderResource(0, config.tex, config.tex != config.rt); PSSetShaderResource(0, config.tex, config.tex != config.rt);
@ -2855,8 +2853,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
GSTextureVK* date_image = nullptr; GSTextureVK* date_image = nullptr;
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking) if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking)
{ {
pxAssert(pipe.feedback_loop); date_image = SetupPrimitiveTrackingDATE(config);
date_image = SetupPrimitiveTrackingDATE(config, pipe);
if (!date_image) if (!date_image)
{ {
Console.WriteLn("Failed to allocate DATE image, aborting draw."); 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). // 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 int render_area_alignment = 128 * GSConfig.UpscaleMultiplier;
const GSVector2i rtsize(config.rt ? config.rt->GetSize() : config.ds->GetSize()); 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; pipe.vs.key = config.vs.key;
m_pipeline_selector.gs.key = config.gs.key; pipe.gs.key = config.gs.key;
m_pipeline_selector.ps.key_hi = config.ps.key_hi; pipe.ps.key_hi = config.ps.key_hi;
m_pipeline_selector.ps.key_lo = config.ps.key_lo; pipe.ps.key_lo = config.ps.key_lo;
m_pipeline_selector.dss.key = config.depth.key; pipe.dss.key = config.depth.key;
m_pipeline_selector.bs.key = config.blend.key; pipe.bs.key = config.blend.key;
m_pipeline_selector.bs.constant = 0; // don't dupe states with different alpha values pipe.bs.constant = 0; // don't dupe states with different alpha values
m_pipeline_selector.cms.key = config.colormask.key; pipe.cms.key = config.colormask.key;
m_pipeline_selector.topology = static_cast<u32>(config.topology); pipe.topology = static_cast<u32>(config.topology);
m_pipeline_selector.rt = config.rt != nullptr; pipe.rt = config.rt != nullptr;
m_pipeline_selector.ds = config.ds != nullptr; pipe.ds = config.ds != nullptr;
m_pipeline_selector.line_width = config.line_expand; pipe.line_width = config.line_expand;
m_pipeline_selector.feedback_loop = m_features.texture_barrier && pipe.feedback_loop = m_features.texture_barrier &&
(config.ps.IsFeedbackLoop() || config.require_one_barrier || config.require_full_barrier || (config.ps.IsFeedbackLoop() || config.require_one_barrier || config.require_full_barrier);
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking);
// enable point size in the vertex shader if we're rendering points regardless of upscaling. // 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) void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt)

View File

@ -240,7 +240,7 @@ public:
u32 dLevel, bool linear); u32 dLevel, bool linear);
void SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox); 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); void IASetVertexBuffer(const void* vertex, size_t stride, size_t count);
bool IAMapVertexBuffer(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); bool BindDrawPipeline(const PipelineSelector& p);
void RenderHW(GSHWDrawConfig& config) override; void RenderHW(GSHWDrawConfig& config) override;
void UpdateHWPipelineSelector(GSHWDrawConfig& config); void UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe);
void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt); void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt);
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////