mirror of
https://github.com/simple64/simple64.git
synced 2026-11-12 15:38:42 +01:00
update parallel rdp
This commit is contained in:
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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user