vk: Rewrite partial clear shader

- Completely removes the feedback loop and replaces with hardware channel masking
This commit is contained in:
kd-11 2021-05-31 23:51:14 +03:00 committed by kd-11
parent f85881c18c
commit 98f534b1bd
5 changed files with 22 additions and 75 deletions

View file

@ -1273,33 +1273,8 @@ void VKGSRender::clear_surface(u32 mask)
color_clear_values.color.float32[3]
};
VkRenderPass renderpass = VK_NULL_HANDLE;
auto attachment_clear_pass = vk::get_overlay_pass<vk::attachment_clear_pass>();
attachment_clear_pass->update_config(colormask, clear_color);
for (const auto &index : m_draw_buffers)
{
if (auto rtt = m_rtts.m_bound_render_targets[index].second)
{
if (require_mem_load) rtt->write_barrier(*m_current_command_buffer);
// Add a barrier to ensure previous writes are visible; also transitions into GENERAL layout
rtt->push_barrier(*m_current_command_buffer, VK_IMAGE_LAYOUT_GENERAL);
if (!renderpass)
{
std::vector<vk::image*> surfaces = { rtt };
std::vector<u8> input_attachments = { 0 };
const auto key = vk::get_renderpass_key(surfaces, input_attachments);
renderpass = vk::get_renderpass(*m_device, key);
}
attachment_clear_pass->run(*m_current_command_buffer, rtt, region.rect, renderpass);
rtt->pop_layout(*m_current_command_buffer);
}
else
fmt::throw_exception("Unreachable");
}
attachment_clear_pass->run(*m_current_command_buffer, m_draw_fbo, region.rect, colormask, clear_color, get_render_pass());
}
for (u8 index = m_rtts.m_bound_render_targets_config.first, count = 0;

View file

@ -32,21 +32,9 @@ namespace vk
u64 overlay_pass::get_pipeline_key(VkRenderPass pass)
{
if (!multi_primitive)
{
// Default fast path
return reinterpret_cast<u64>(pass);
}
else
{
struct
{
u64 pass_value;
u64 config;
}
key{ reinterpret_cast<uptr>(pass), static_cast<u64>(renderpass_config.ia.topology) };
return rpcs3::hash_struct(key);
}
u64 key = rpcs3::hash_struct(renderpass_config);
key ^= reinterpret_cast<uptr>(pass);
return key;
}
void overlay_pass::check_heap()
@ -500,9 +488,6 @@ namespace vk
" }\n"
"}\n";
// Allow mixed primitive rendering
multi_primitive = true;
// 2 input textures
m_num_usable_samplers = 2;
@ -807,13 +792,11 @@ namespace vk
"#extension GL_ARB_separate_shader_objects : enable\n"
"layout(push_constant) uniform static_data{ vec4 regs[2]; };\n"
"layout(location=0) out vec4 color;\n"
"layout(location=1) out vec4 mask;\n"
"\n"
"void main()\n"
"{\n"
" vec2 positions[] = {vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)};\n"
" color = regs[0];\n"
" mask = regs[1];\n"
" gl_Position = vec4(positions[gl_VertexIndex % 4], 0., 1.);\n"
"}\n";
@ -822,21 +805,16 @@ namespace vk
"#extension GL_ARB_separate_shader_objects : enable\n"
"layout(input_attachment_index=0, binding=1) uniform subpassInput sp0;\n"
"layout(location=0) in vec4 color;\n"
"layout(location=1) in vec4 mask;\n"
"layout(location=0) out vec4 out_color;\n"
"\n"
"void main()\n"
"{\n"
" vec4 original_color = subpassLoad(sp0);\n"
" out_color = mix(original_color, color, bvec4(mask));\n"
" out_color = color;\n"
"}\n";
// Disable samplers
m_num_usable_samplers = 0;
// Enable subpass attachment 0
m_num_input_attachments = 1;
renderpass_config.set_depth_mask(false);
renderpass_config.set_color_mask(0, true, true, true, true);
renderpass_config.set_attachment_count(1);
@ -852,7 +830,7 @@ namespace vk
return { constant };
}
void attachment_clear_pass::update_uniforms(vk::command_buffer& cmd, vk::glsl::program* program)
void attachment_clear_pass::update_uniforms(vk::command_buffer& cmd, vk::glsl::program* /*program*/)
{
f32 data[8];
data[0] = clear_color.r;
@ -865,9 +843,6 @@ namespace vk
data[7] = colormask.a;
vkCmdPushConstants(cmd, m_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 32, data);
// Bind subpass attachment 0
program->bind_uniform(input_attachment_info, "sp0", VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_descriptor_set);
}
void attachment_clear_pass::set_up_viewport(vk::command_buffer& cmd, u32 x, u32 y, u32 w, u32 h)
@ -884,8 +859,10 @@ namespace vk
vkCmdSetScissor(cmd, 0, 1, &region);
}
bool attachment_clear_pass::update_config(u32 clearmask, color4f color)
void attachment_clear_pass::run(vk::command_buffer& cmd, vk::framebuffer* target, VkRect2D rect, u32 clearmask, color4f color, VkRenderPass render_pass)
{
region = rect;
color4f mask = { 0.f, 0.f, 0.f, 0.f };
if (clearmask & 0x10) mask.r = 1.f;
if (clearmask & 0x20) mask.g = 1.f;
@ -896,22 +873,15 @@ namespace vk
{
colormask = mask;
clear_color = color;
return true;
// Update color mask to match request
renderpass_config.set_color_mask(0, colormask.r, colormask.g, colormask.b, colormask.a);
}
return false;
}
void attachment_clear_pass::run(vk::command_buffer& cmd, vk::render_target* target, VkRect2D rect, VkRenderPass render_pass)
{
region = rect;
input_attachment_info = { VK_NULL_HANDLE, target->get_view(0xAAE4, rsx::default_remap_vector)->value, target->current_layout };
target->read_barrier(cmd);
// Coverage sampling disabled, but actually report correct number of samples
// Update renderpass configuration with the real number of samples
renderpass_config.set_multisample_state(target->samples(), 0xFFFF, false, false, false);
// Render fullscreen quad
overlay_pass::run(cmd, { 0, 0, target->width(), target->height() }, target, std::vector<vk::image_view*>{}, render_pass);
}

View file

@ -62,7 +62,6 @@ namespace vk
std::string fs_src;
graphics_pipeline_state renderpass_config;
bool multi_primitive = false;
bool initialized = false;
bool compiled = false;
@ -176,7 +175,6 @@ namespace vk
color4f clear_color = { 0.f, 0.f, 0.f, 0.f };
color4f colormask = { 1.f, 1.f, 1.f, 1.f };
VkRect2D region = {};
VkDescriptorImageInfo input_attachment_info = {};
attachment_clear_pass();
@ -186,9 +184,7 @@ namespace vk
void set_up_viewport(vk::command_buffer& cmd, u32 x, u32 y, u32 w, u32 h) override;
bool update_config(u32 clearmask, color4f color);
void run(vk::command_buffer& cmd, vk::render_target* target, VkRect2D rect, VkRenderPass render_pass);
void run(vk::command_buffer& cmd, vk::framebuffer* target, VkRect2D rect, u32 clearmask, color4f color, VkRenderPass render_pass);
};
struct stencil_clear_pass : public overlay_pass

View file

@ -98,7 +98,7 @@ namespace rsx
sample_layout = surface_sample_layout::null;
}
VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (samples == 1) [[likely]]
{
usage_flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

View file

@ -57,6 +57,12 @@ namespace vk
return m_height;
}
u8 samples()
{
ensure(!attachments.empty());
return attachments[0]->image()->samples();
}
bool matches(std::vector<vk::image*> fbo_images, u32 width, u32 height)
{
if (m_width != width || m_height != height)