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
|
__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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue