video_core: simplify accelerated surface fetch and crop handling between APIs
This commit is contained in:
parent
7cc7d027f7
commit
80de01a5b4
18 changed files with 262 additions and 316 deletions
|
|
@ -98,9 +98,9 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
|
|||
present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
|
||||
surface),
|
||||
blit_screen(device_memory, render_window, device, memory_allocator, swapchain,
|
||||
present_manager, scheduler, screen_info),
|
||||
rasterizer(render_window, gpu, device_memory, screen_info, device, memory_allocator,
|
||||
state_tracker, scheduler) {
|
||||
present_manager, scheduler),
|
||||
rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker,
|
||||
scheduler) {
|
||||
if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
|
||||
turbo_mode.emplace(instance, dld);
|
||||
scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); });
|
||||
|
|
@ -124,17 +124,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
|||
if (!render_window.IsShown()) {
|
||||
return;
|
||||
}
|
||||
// Update screen info if the framebuffer size has changed.
|
||||
screen_info.width = framebuffer->width;
|
||||
screen_info.height = framebuffer->height;
|
||||
|
||||
const DAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
|
||||
const bool use_accelerated =
|
||||
rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
|
||||
RenderScreenshot(*framebuffer, use_accelerated);
|
||||
|
||||
RenderScreenshot(*framebuffer);
|
||||
Frame* frame = present_manager.GetRenderFrame();
|
||||
blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated);
|
||||
blit_screen.DrawToSwapchain(rasterizer, frame, *framebuffer);
|
||||
scheduler.Flush(*frame->render_ready);
|
||||
present_manager.Present(frame);
|
||||
|
||||
|
|
@ -168,8 +161,7 @@ void RendererVulkan::Report() const {
|
|||
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
|
||||
}
|
||||
|
||||
void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer,
|
||||
bool use_accelerated) {
|
||||
void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) {
|
||||
if (!renderer_settings.screenshot_requested) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -221,7 +213,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr
|
|||
});
|
||||
const VkExtent2D render_area{.width = layout.width, .height = layout.height};
|
||||
const vk::Framebuffer screenshot_fb = blit_screen.CreateFramebuffer(*dst_view, render_area);
|
||||
blit_screen.Draw(framebuffer, *screenshot_fb, layout, render_area, use_accelerated);
|
||||
blit_screen.Draw(rasterizer, framebuffer, *screenshot_fb, layout, render_area);
|
||||
|
||||
const auto buffer_size = static_cast<VkDeviceSize>(layout.width * layout.height * 4);
|
||||
const VkBufferCreateInfo dst_buffer_info{
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public:
|
|||
private:
|
||||
void Report() const;
|
||||
|
||||
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated);
|
||||
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer);
|
||||
|
||||
Core::TelemetrySession& telemetry_session;
|
||||
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
||||
|
|
@ -72,8 +72,6 @@ private:
|
|||
vk::DebugUtilsMessenger debug_messenger;
|
||||
vk::SurfaceKHR surface;
|
||||
|
||||
ScreenInfo screen_info;
|
||||
|
||||
Device device;
|
||||
MemoryAllocator memory_allocator;
|
||||
StateTracker state_tracker;
|
||||
|
|
|
|||
|
|
@ -124,11 +124,10 @@ struct BlitScreen::BufferData {
|
|||
BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||
Core::Frontend::EmuWindow& render_window_, const Device& device_,
|
||||
MemoryAllocator& memory_allocator_, Swapchain& swapchain_,
|
||||
PresentManager& present_manager_, Scheduler& scheduler_,
|
||||
const ScreenInfo& screen_info_)
|
||||
PresentManager& present_manager_, Scheduler& scheduler_)
|
||||
: device_memory{device_memory_}, render_window{render_window_}, device{device_},
|
||||
memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_},
|
||||
scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
|
||||
scheduler{scheduler_}, image_count{swapchain.GetImageCount()} {
|
||||
resource_ticks.resize(image_count);
|
||||
swapchain_view_format = swapchain.GetImageViewFormat();
|
||||
|
||||
|
|
@ -138,56 +137,6 @@ BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||
|
||||
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() {
|
||||
present_manager.WaitPresent();
|
||||
scheduler.Finish();
|
||||
|
|
@ -195,9 +144,16 @@ void BlitScreen::Recreate() {
|
|||
CreateDynamicResources();
|
||||
}
|
||||
|
||||
void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
||||
void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer,
|
||||
const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout,
|
||||
VkExtent2D render_area, bool use_accelerated) {
|
||||
VkExtent2D render_area) {
|
||||
|
||||
const auto texture_info = rasterizer.AccelerateDisplay(
|
||||
framebuffer, framebuffer.address + framebuffer.offset, framebuffer.stride);
|
||||
const u32 texture_width = texture_info ? texture_info->width : framebuffer.width;
|
||||
const u32 texture_height = texture_info ? texture_info->height : framebuffer.height;
|
||||
const bool use_accelerated = texture_info.has_value();
|
||||
|
||||
RefreshResources(framebuffer);
|
||||
|
||||
// Finish any pending renderpass
|
||||
|
|
@ -206,13 +162,13 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
|||
scheduler.Wait(resource_ticks[image_index]);
|
||||
resource_ticks[image_index] = scheduler.CurrentTick();
|
||||
|
||||
VkImage source_image = use_accelerated ? screen_info.image : *raw_images[image_index];
|
||||
VkImage source_image = texture_info ? texture_info->image : *raw_images[image_index];
|
||||
VkImageView source_image_view =
|
||||
use_accelerated ? screen_info.image_view : *raw_image_views[image_index];
|
||||
texture_info ? texture_info->image_view : *raw_image_views[image_index];
|
||||
|
||||
BufferData data;
|
||||
SetUniformData(data, layout);
|
||||
SetVertexData(data, framebuffer, layout);
|
||||
SetVertexData(data, framebuffer, layout, texture_width, texture_height);
|
||||
|
||||
const std::span<u8> mapped_span = buffer.Mapped();
|
||||
std::memcpy(mapped_span.data(), &data, sizeof(data));
|
||||
|
|
@ -405,10 +361,10 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
|||
source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view);
|
||||
}
|
||||
if (fsr) {
|
||||
const auto crop_rect = NormalizeCrop(framebuffer, screen_info);
|
||||
const auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height);
|
||||
const VkExtent2D fsr_input_size{
|
||||
.width = Settings::values.resolution_info.ScaleUp(screen_info.width),
|
||||
.height = Settings::values.resolution_info.ScaleUp(screen_info.height),
|
||||
.width = Settings::values.resolution_info.ScaleUp(texture_width),
|
||||
.height = Settings::values.resolution_info.ScaleUp(texture_height),
|
||||
};
|
||||
VkImageView fsr_image_view =
|
||||
fsr->Draw(scheduler, image_index, source_image_view, fsr_input_size, crop_rect);
|
||||
|
|
@ -480,8 +436,8 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
|||
});
|
||||
}
|
||||
|
||||
void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
|
||||
bool use_accelerated) {
|
||||
void BlitScreen::DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame,
|
||||
const Tegra::FramebufferConfig& framebuffer) {
|
||||
// Recreate dynamic resources if the the image count or input format changed
|
||||
const VkFormat current_framebuffer_format =
|
||||
std::exchange(framebuffer_view_format, GetFormat(framebuffer));
|
||||
|
|
@ -500,7 +456,7 @@ void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& f
|
|||
}
|
||||
|
||||
const VkExtent2D render_area{frame->width, frame->height};
|
||||
Draw(framebuffer, *frame->framebuffer, layout, render_area, use_accelerated);
|
||||
Draw(rasterizer, framebuffer, *frame->framebuffer, layout, render_area);
|
||||
if (++image_index >= image_count) {
|
||||
image_index = 0;
|
||||
}
|
||||
|
|
@ -1434,7 +1390,8 @@ void BlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayou
|
|||
}
|
||||
|
||||
void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
|
||||
const Layout::FramebufferLayout layout) const {
|
||||
const Layout::FramebufferLayout layout, u32 texture_width,
|
||||
u32 texture_height) const {
|
||||
f32 left, top, right, bottom;
|
||||
|
||||
if (fsr) {
|
||||
|
|
@ -1446,7 +1403,7 @@ void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig&
|
|||
bottom = 1;
|
||||
} else {
|
||||
// Get the normalized crop rectangle.
|
||||
const auto crop = NormalizeCrop(framebuffer, screen_info);
|
||||
const auto crop = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height);
|
||||
|
||||
// Apply the crop.
|
||||
left = crop.left;
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ enum class PixelFormat : u32;
|
|||
|
||||
namespace Vulkan {
|
||||
|
||||
struct ScreenInfo;
|
||||
|
||||
class Device;
|
||||
class FSR;
|
||||
class RasterizerVulkan;
|
||||
|
|
@ -44,7 +42,7 @@ class PresentManager;
|
|||
|
||||
struct Frame;
|
||||
|
||||
struct ScreenInfo {
|
||||
struct FramebufferTextureInfo {
|
||||
VkImage image{};
|
||||
VkImageView image_view{};
|
||||
u32 width{};
|
||||
|
|
@ -56,17 +54,17 @@ public:
|
|||
explicit BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory,
|
||||
Core::Frontend::EmuWindow& render_window, const Device& device,
|
||||
MemoryAllocator& memory_manager, Swapchain& swapchain,
|
||||
PresentManager& present_manager, Scheduler& scheduler,
|
||||
const ScreenInfo& screen_info);
|
||||
PresentManager& present_manager, Scheduler& scheduler);
|
||||
~BlitScreen();
|
||||
|
||||
void Recreate();
|
||||
|
||||
void Draw(const Tegra::FramebufferConfig& framebuffer, const VkFramebuffer& host_framebuffer,
|
||||
const Layout::FramebufferLayout layout, VkExtent2D render_area, bool use_accelerated);
|
||||
void Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer,
|
||||
const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout,
|
||||
VkExtent2D render_area);
|
||||
|
||||
void DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
|
||||
bool use_accelerated);
|
||||
void DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame,
|
||||
const Tegra::FramebufferConfig& framebuffer);
|
||||
|
||||
[[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view,
|
||||
VkExtent2D extent);
|
||||
|
|
@ -99,7 +97,8 @@ private:
|
|||
void UpdateAADescriptorSet(VkImageView image_view, bool nn) const;
|
||||
void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const;
|
||||
void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
|
||||
const Layout::FramebufferLayout layout) const;
|
||||
const Layout::FramebufferLayout layout, u32 texture_width,
|
||||
u32 texture_height) const;
|
||||
|
||||
void CreateSMAA(VkExtent2D smaa_size);
|
||||
void CreateFSR();
|
||||
|
|
@ -116,7 +115,6 @@ private:
|
|||
Scheduler& scheduler;
|
||||
std::size_t image_count;
|
||||
std::size_t image_index{};
|
||||
const ScreenInfo& screen_info;
|
||||
|
||||
vk::ShaderModule vertex_shader;
|
||||
vk::ShaderModule fxaa_vertex_shader;
|
||||
|
|
|
|||
|
|
@ -165,10 +165,9 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances,
|
|||
|
||||
RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
||||
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||
ScreenInfo& screen_info_, const Device& device_,
|
||||
MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
|
||||
Scheduler& scheduler_)
|
||||
: gpu{gpu_}, device_memory{device_memory_}, screen_info{screen_info_}, device{device_},
|
||||
const Device& device_, MemoryAllocator& memory_allocator_,
|
||||
StateTracker& state_tracker_, Scheduler& scheduler_)
|
||||
: gpu{gpu_}, device_memory{device_memory_}, device{device_},
|
||||
memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_},
|
||||
staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
|
||||
guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler),
|
||||
|
|
@ -783,23 +782,25 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
|
|||
query_cache.InvalidateRegion(*cpu_addr, copy_size);
|
||||
}
|
||||
|
||||
bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||
DAddr framebuffer_addr, u32 pixel_stride) {
|
||||
std::optional<FramebufferTextureInfo> RasterizerVulkan::AccelerateDisplay(
|
||||
const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, u32 pixel_stride) {
|
||||
if (!framebuffer_addr) {
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
std::scoped_lock lock{texture_cache.mutex};
|
||||
ImageView* const image_view =
|
||||
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
|
||||
if (!image_view) {
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
query_cache.NotifySegment(false);
|
||||
screen_info.image = image_view->ImageHandle();
|
||||
screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D);
|
||||
screen_info.width = image_view->size.width;
|
||||
screen_info.height = image_view->size.height;
|
||||
return true;
|
||||
|
||||
FramebufferTextureInfo info{};
|
||||
info.image = image_view->ImageHandle();
|
||||
info.image_view = image_view->Handle(Shader::TextureType::Color2D);
|
||||
info.width = image_view->size.width;
|
||||
info.height = image_view->size.height;
|
||||
return info;
|
||||
}
|
||||
|
||||
void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class Maxwell3D;
|
|||
|
||||
namespace Vulkan {
|
||||
|
||||
struct ScreenInfo;
|
||||
struct FramebufferTextureInfo;
|
||||
|
||||
class StateTracker;
|
||||
|
||||
|
|
@ -78,9 +78,8 @@ class RasterizerVulkan final : public VideoCore::RasterizerInterface,
|
|||
public:
|
||||
explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
||||
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||
ScreenInfo& screen_info_, const Device& device_,
|
||||
MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
|
||||
Scheduler& scheduler_);
|
||||
const Device& device_, MemoryAllocator& memory_allocator_,
|
||||
StateTracker& state_tracker_, Scheduler& scheduler_);
|
||||
~RasterizerVulkan() override;
|
||||
|
||||
void Draw(bool is_indexed, u32 instance_count) override;
|
||||
|
|
@ -126,8 +125,6 @@ public:
|
|||
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
|
||||
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
||||
std::span<const u8> memory) override;
|
||||
bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr,
|
||||
u32 pixel_stride) override;
|
||||
void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||
|
||||
|
|
@ -137,6 +134,10 @@ public:
|
|||
|
||||
void ReleaseChannel(s32 channel_id) override;
|
||||
|
||||
std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||
VAddr framebuffer_addr,
|
||||
u32 pixel_stride);
|
||||
|
||||
private:
|
||||
static constexpr size_t MAX_TEXTURES = 192;
|
||||
static constexpr size_t MAX_IMAGES = 48;
|
||||
|
|
@ -182,7 +183,6 @@ private:
|
|||
Tegra::GPU& gpu;
|
||||
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
||||
|
||||
ScreenInfo& screen_info;
|
||||
const Device& device;
|
||||
MemoryAllocator& memory_allocator;
|
||||
StateTracker& state_tracker;
|
||||
|
|
|
|||
Reference in a new issue