update parallel rdp

This commit is contained in:
Logan McNaughton committed 2022-08-02 11:54:03 -06:00
1 parent d3a26d3959
commit 14e7485541
24 files changed
+1295 -391

No files matched your search

@@ -719,7 +719,7 @@ void VideoInterface::bind_horizontal_info_view(Vulkan::CommandBuffer &cmd, const
Vulkan::ImageHandle VideoInterface::scale_stage(Vulkan::CommandBuffer &cmd, Vulkan::Image &divot_image,
Registers regs, const HorizontalInfoLines &lines,
unsigned scaling_factor, bool degenerate,
const ScanoutOptions &options) const
const ScanoutOptions &options, bool final_pass) const
{
Vulkan::ImageHandle scale_image;
Vulkan::QueryPoolHandle start_ts, end_ts;
@@ -778,8 +778,21 @@ Vulkan::ImageHandle VideoInterface::scale_stage(Vulkan::CommandBuffer &cmd, Vulk
rt_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
rt_info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
rt_info.misc = Vulkan::IMAGE_MISC_MUTABLE_SRGB_BIT;
if (options.export_scanout && final_pass)
{
rt_info.misc |= Vulkan::IMAGE_MISC_EXTERNAL_MEMORY_BIT;
rt_info.external.memory_handle_type = options.export_handle_type;
}
scale_image = device->create_image(rt_info);
if (!scale_image)
{
LOGE("Failed to allocate scale image.\n");
return {};
}
Vulkan::RenderPassInfo rp;
rp.color_attachments[0] = &scale_image->get_view();
memset(&rp.clear_color[0], 0, sizeof(rp.clear_color[0]));
@@ -791,11 +804,20 @@ Vulkan::ImageHandle VideoInterface::scale_stage(Vulkan::CommandBuffer &cmd, Vulk
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
if (prev_scanout_image && prev_image_layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
if (prev_scanout_image)
{
cmd.image_barrier(*prev_scanout_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
if (prev_image_is_external)
{
cmd.acquire_external_image_barrier(*prev_scanout_image, prev_image_layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
}
else if (prev_image_layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
VK_ASSERT(prev_image_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
cmd.image_barrier(*prev_scanout_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
}
}
if (timestamp)
@@ -978,14 +1000,17 @@ Vulkan::ImageHandle VideoInterface::scale_stage(Vulkan::CommandBuffer &cmd, Vulk
}
Vulkan::ImageHandle VideoInterface::downscale_stage(Vulkan::CommandBuffer &cmd, Vulkan::Image &scale_image,
unsigned scaling_factor, unsigned downscale_steps) const
unsigned scaling_factor, unsigned downscale_steps,
const ScanoutOptions &options, bool final_pass) const
{
Vulkan::ImageHandle downscale_image;
const Vulkan::Image *input = &scale_image;
Vulkan::ImageHandle holder;
bool need_pass = scaling_factor > 1 && downscale_steps;
// TODO: Could optimize this to happen in one pass, but ... eh.
while (scaling_factor > 1 && downscale_steps)
while (need_pass)
{
if (input != &scale_image)
{
@@ -1005,8 +1030,25 @@ Vulkan::ImageHandle VideoInterface::downscale_stage(Vulkan::CommandBuffer &cmd,
rt_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
rt_info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
rt_info.misc = Vulkan::IMAGE_MISC_MUTABLE_SRGB_BIT;
scaling_factor /= 2;
downscale_steps--;
need_pass = scaling_factor > 1 && downscale_steps;
if (options.export_scanout && final_pass && !need_pass)
{
rt_info.misc |= Vulkan::IMAGE_MISC_EXTERNAL_MEMORY_BIT;
rt_info.external.memory_handle_type = options.export_handle_type;
}
downscale_image = device->create_image(rt_info);
if (!downscale_image)
{
LOGE("Failed to allocate downscale image.\n");
return {};
}
cmd.image_barrier(*downscale_image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);
@@ -1018,16 +1060,14 @@ Vulkan::ImageHandle VideoInterface::downscale_stage(Vulkan::CommandBuffer &cmd,
input = downscale_image.get();
holder = downscale_image;
scaling_factor /= 2;
downscale_steps--;
}
return downscale_image;
}
Vulkan::ImageHandle VideoInterface::upscale_deinterlace(Vulkan::CommandBuffer &cmd, Vulkan::Image &scale_image,
unsigned scaling_factor, bool field_select) const
unsigned scaling_factor, bool field_select,
const ScanoutOptions &options) const
{
Vulkan::ImageHandle deinterlaced_image;
@@ -1039,8 +1079,21 @@ Vulkan::ImageHandle VideoInterface::upscale_deinterlace(Vulkan::CommandBuffer &c
rt_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
rt_info.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
rt_info.misc = Vulkan::IMAGE_MISC_MUTABLE_SRGB_BIT;
if (options.export_scanout)
{
rt_info.misc |= Vulkan::IMAGE_MISC_EXTERNAL_MEMORY_BIT;
rt_info.external.memory_handle_type = options.export_handle_type;
}
deinterlaced_image = device->create_image(rt_info);
if (!deinterlaced_image)
{
LOGE("Failed to allocate deinterlace image.\n");
return {};
}
Vulkan::RenderPassInfo rp;
rp.color_attachments[0] = &deinterlaced_image->get_view();
rp.num_color_attachments = 1;
@@ -1301,24 +1354,31 @@ Vulkan::ImageHandle VideoInterface::scanout(VkImageLayout target_layout, const S
divot_image = std::move(aa_image);
// Scale pass
bool is_final_pass = !downscale_steps || scaling_factor <= 1;
bool serrate = (regs.status & VI_CONTROL_SERRATE_BIT) != 0;
auto scale_image = scale_stage(*cmd, *divot_image,
regs, lines,
scaling_factor, degenerate, options);
scaling_factor, degenerate, options,
is_final_pass);
auto src_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
if (downscale_steps && scaling_factor > 1)
if (!is_final_pass && scale_image)
{
cmd->image_barrier(*scale_image, src_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
layout_to_stage(src_layout), layout_to_access(src_layout),
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT);
scale_image = downscale_stage(*cmd, *scale_image, scaling_factor, downscale_steps);
is_final_pass = !serrate || !options.upscale_deinterlacing;
scale_image = downscale_stage(*cmd, *scale_image, scaling_factor, downscale_steps,
options, is_final_pass);
src_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
}
bool serrate = (regs.status & VI_CONTROL_SERRATE_BIT) != 0;
if (serrate && options.upscale_deinterlacing)
if (!is_final_pass && scale_image)
{
cmd->image_barrier(*scale_image, src_layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
layout_to_stage(src_layout), layout_to_access(src_layout),
@@ -1327,21 +1387,44 @@ Vulkan::ImageHandle VideoInterface::scanout(VkImageLayout target_layout, const S
bool field_state = regs.v_current_line == 0;
scale_image = upscale_deinterlace(*cmd, *scale_image,
std::max(1, scaling_factor >> downscale_steps),
field_state);
field_state, options);
src_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
cmd->image_barrier(*scale_image, src_layout, target_layout,
layout_to_stage(src_layout), layout_to_access(src_layout),
layout_to_stage(target_layout), layout_to_access(target_layout));
if (scale_image)
{
if (options.export_scanout)
{
// Foreign handle types (e.g. D3D) must use GENERAL layouts.
if (options.export_handle_type != Vulkan::ExternalHandle::get_opaque_memory_handle_type())
target_layout = VK_IMAGE_LAYOUT_GENERAL;
cmd->release_external_image_barrier(*scale_image, src_layout,
target_layout,
layout_to_stage(src_layout),
layout_to_access(src_layout));
}
else
{
cmd->image_barrier(*scale_image, src_layout, target_layout,
layout_to_stage(src_layout), layout_to_access(src_layout),
layout_to_stage(target_layout), layout_to_access(target_layout));
}
}
prev_image_layout = target_layout;
prev_scanout_image = scale_image;
prev_image_is_external = options.export_scanout;
if (options.persist_frame_on_invalid_input && options.export_scanout)
{
LOGE("persist_frame_on_invalid_input cannot be combined with export_scanout.\n");
prev_scanout_image.reset();
}
device->submit(cmd);
scanout = std::move(scale_image);
frame_count++;
return scanout;
}
}