renderer_vulkan: fix FSR cropping
This commit is contained in:
parent
65d4a16afd
commit
6513a356f0
|
@ -137,6 +137,56 @@ BlitScreen::BlitScreen(Core::Memory::Memory& cpu_memory_, Core::Frontend::EmuWin
|
||||||
|
|
||||||
BlitScreen::~BlitScreen() = default;
|
BlitScreen::~BlitScreen() = default;
|
||||||
|
|
||||||
|
static Common::Rectangle<f32> NormalizeCrop(const Tegra::FramebufferConfig& framebuffer,
|
||||||
|
const ScreenInfo& screen_info) {
|
||||||
|
f32 left, top, right, bottom;
|
||||||
|
|
||||||
|
if (!framebuffer.crop_rect.IsEmpty()) {
|
||||||
|
// If crop rectangle is not empty, apply properties from rectangle.
|
||||||
|
left = static_cast<f32>(framebuffer.crop_rect.left);
|
||||||
|
top = static_cast<f32>(framebuffer.crop_rect.top);
|
||||||
|
right = static_cast<f32>(framebuffer.crop_rect.right);
|
||||||
|
bottom = static_cast<f32>(framebuffer.crop_rect.bottom);
|
||||||
|
} else {
|
||||||
|
// Otherwise, fall back to framebuffer dimensions.
|
||||||
|
left = 0;
|
||||||
|
top = 0;
|
||||||
|
right = static_cast<f32>(framebuffer.width);
|
||||||
|
bottom = static_cast<f32>(framebuffer.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply transformation flags.
|
||||||
|
auto framebuffer_transform_flags = framebuffer.transform_flags;
|
||||||
|
|
||||||
|
if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) {
|
||||||
|
// Switch left and right.
|
||||||
|
std::swap(left, right);
|
||||||
|
}
|
||||||
|
if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) {
|
||||||
|
// Switch top and bottom.
|
||||||
|
std::swap(top, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH;
|
||||||
|
framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV;
|
||||||
|
if (True(framebuffer_transform_flags)) {
|
||||||
|
UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}",
|
||||||
|
static_cast<u32>(framebuffer_transform_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the screen properties.
|
||||||
|
const f32 screen_width = static_cast<f32>(screen_info.width);
|
||||||
|
const f32 screen_height = static_cast<f32>(screen_info.height);
|
||||||
|
|
||||||
|
// Normalize coordinate space.
|
||||||
|
left /= screen_width;
|
||||||
|
top /= screen_height;
|
||||||
|
right /= screen_width;
|
||||||
|
bottom /= screen_height;
|
||||||
|
|
||||||
|
return Common::Rectangle<f32>(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
void BlitScreen::Recreate() {
|
void BlitScreen::Recreate() {
|
||||||
present_manager.WaitPresent();
|
present_manager.WaitPresent();
|
||||||
scheduler.Finish();
|
scheduler.Finish();
|
||||||
|
@ -354,17 +404,10 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
||||||
source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view);
|
source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view);
|
||||||
}
|
}
|
||||||
if (fsr) {
|
if (fsr) {
|
||||||
auto crop_rect = framebuffer.crop_rect;
|
const auto crop_rect = NormalizeCrop(framebuffer, screen_info);
|
||||||
if (crop_rect.GetWidth() == 0) {
|
const VkExtent2D fsr_input_size{
|
||||||
crop_rect.right = framebuffer.width;
|
.width = Settings::values.resolution_info.ScaleUp(screen_info.width),
|
||||||
}
|
.height = Settings::values.resolution_info.ScaleUp(screen_info.height),
|
||||||
if (crop_rect.GetHeight() == 0) {
|
|
||||||
crop_rect.bottom = framebuffer.height;
|
|
||||||
}
|
|
||||||
crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor);
|
|
||||||
VkExtent2D fsr_input_size{
|
|
||||||
.width = Settings::values.resolution_info.ScaleUp(framebuffer.width),
|
|
||||||
.height = Settings::values.resolution_info.ScaleUp(framebuffer.height),
|
|
||||||
};
|
};
|
||||||
VkImageView fsr_image_view =
|
VkImageView fsr_image_view =
|
||||||
fsr->Draw(scheduler, image_index, source_image_view, fsr_input_size, crop_rect);
|
fsr->Draw(scheduler, image_index, source_image_view, fsr_input_size, crop_rect);
|
||||||
|
@ -1395,60 +1438,27 @@ void BlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayou
|
||||||
MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height));
|
MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Common::Rectangle<f32> NormalizeCrop(Common::Rectangle<int> crop,
|
|
||||||
const Tegra::FramebufferConfig& framebuffer) {
|
|
||||||
f32 left, top, right, bottom;
|
|
||||||
|
|
||||||
if (!crop.IsEmpty()) {
|
|
||||||
// If crop rectangle is not empty, apply properties from rectangle.
|
|
||||||
left = static_cast<f32>(crop.left);
|
|
||||||
top = static_cast<f32>(crop.top);
|
|
||||||
right = static_cast<f32>(crop.right);
|
|
||||||
bottom = static_cast<f32>(crop.bottom);
|
|
||||||
} else {
|
|
||||||
// Otherwise, fall back to framebuffer dimensions.
|
|
||||||
left = 0;
|
|
||||||
top = 0;
|
|
||||||
right = static_cast<f32>(framebuffer.width);
|
|
||||||
bottom = static_cast<f32>(framebuffer.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply transformation flags.
|
|
||||||
auto framebuffer_transform_flags = framebuffer.transform_flags;
|
|
||||||
|
|
||||||
if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) {
|
|
||||||
// Switch left and right.
|
|
||||||
std::swap(left, right);
|
|
||||||
}
|
|
||||||
if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) {
|
|
||||||
// Switch top and bottom.
|
|
||||||
std::swap(top, bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH;
|
|
||||||
framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV;
|
|
||||||
if (True(framebuffer_transform_flags)) {
|
|
||||||
UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}",
|
|
||||||
static_cast<u32>(framebuffer_transform_flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Common::Rectangle<f32>(left, top, right, bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
|
void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
|
||||||
const Layout::FramebufferLayout layout) const {
|
const Layout::FramebufferLayout layout) const {
|
||||||
// Get the normalized crop rectangle.
|
f32 left, top, right, bottom;
|
||||||
const auto crop = NormalizeCrop(framebuffer.crop_rect, framebuffer);
|
|
||||||
|
|
||||||
// Get the screen properties.
|
if (fsr) {
|
||||||
const f32 screen_width = static_cast<f32>(screen_info.width);
|
// FSR has already applied the crop, so we just want to render the image
|
||||||
const f32 screen_height = static_cast<f32>(screen_info.height);
|
// it has produced.
|
||||||
|
left = 0;
|
||||||
|
top = 0;
|
||||||
|
right = 1;
|
||||||
|
bottom = 1;
|
||||||
|
} else {
|
||||||
|
// Get the normalized crop rectangle.
|
||||||
|
const auto crop = NormalizeCrop(framebuffer, screen_info);
|
||||||
|
|
||||||
// Apply the crop.
|
// Apply the crop.
|
||||||
const f32 left = crop.left / screen_width;
|
left = crop.left;
|
||||||
const f32 top = crop.top / screen_height;
|
top = crop.top;
|
||||||
const f32 right = crop.right / screen_width;
|
right = crop.right;
|
||||||
const f32 bottom = crop.bottom / screen_height;
|
bottom = crop.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
// Map the coordinates to the screen.
|
// Map the coordinates to the screen.
|
||||||
const auto& screen = layout.screen;
|
const auto& screen = layout.screen;
|
||||||
|
|
|
@ -34,7 +34,7 @@ FSR::FSR(const Device& device_, MemoryAllocator& memory_allocator_, size_t image
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImageView image_view,
|
VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImageView image_view,
|
||||||
VkExtent2D input_image_extent, const Common::Rectangle<int>& crop_rect) {
|
VkExtent2D input_image_extent, const Common::Rectangle<f32>& crop_rect) {
|
||||||
|
|
||||||
UpdateDescriptorSet(image_index, image_view);
|
UpdateDescriptorSet(image_index, image_view);
|
||||||
|
|
||||||
|
@ -61,15 +61,21 @@ VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImageView imag
|
||||||
|
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *easu_pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *easu_pipeline);
|
||||||
|
|
||||||
std::array<u32, 4 * 4> push_constants;
|
const f32 input_image_width = static_cast<f32>(input_image_extent.width);
|
||||||
FsrEasuConOffset(
|
const f32 input_image_height = static_cast<f32>(input_image_extent.height);
|
||||||
push_constants.data() + 0, push_constants.data() + 4, push_constants.data() + 8,
|
const f32 output_image_width = static_cast<f32>(output_size.width);
|
||||||
push_constants.data() + 12,
|
const f32 output_image_height = static_cast<f32>(output_size.height);
|
||||||
|
const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_image_width;
|
||||||
|
const f32 viewport_x = crop_rect.left * input_image_width;
|
||||||
|
const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_image_height;
|
||||||
|
const f32 viewport_y = crop_rect.top * input_image_height;
|
||||||
|
|
||||||
static_cast<f32>(crop_rect.GetWidth()), static_cast<f32>(crop_rect.GetHeight()),
|
std::array<u32, 4 * 4> push_constants;
|
||||||
static_cast<f32>(input_image_extent.width), static_cast<f32>(input_image_extent.height),
|
FsrEasuConOffset(push_constants.data() + 0, push_constants.data() + 4,
|
||||||
static_cast<f32>(output_size.width), static_cast<f32>(output_size.height),
|
push_constants.data() + 8, push_constants.data() + 12,
|
||||||
static_cast<f32>(crop_rect.left), static_cast<f32>(crop_rect.top));
|
|
||||||
|
viewport_width, viewport_height, input_image_width, input_image_height,
|
||||||
|
output_image_width, output_image_height, viewport_x, viewport_y);
|
||||||
cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_constants);
|
cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_constants);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count,
|
explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count,
|
||||||
VkExtent2D output_size);
|
VkExtent2D output_size);
|
||||||
VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImageView image_view,
|
VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImageView image_view,
|
||||||
VkExtent2D input_image_extent, const Common::Rectangle<int>& crop_rect);
|
VkExtent2D input_image_extent, const Common::Rectangle<f32>& crop_rect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreateDescriptorPool();
|
void CreateDescriptorPool();
|
||||||
|
|
Reference in New Issue