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
|
@ -55,6 +55,7 @@ add_library(video_core STATIC
|
||||||
engines/maxwell_dma.h
|
engines/maxwell_dma.h
|
||||||
engines/puller.cpp
|
engines/puller.cpp
|
||||||
engines/puller.h
|
engines/puller.h
|
||||||
|
framebuffer_config.cpp
|
||||||
framebuffer_config.h
|
framebuffer_config.h
|
||||||
fsr.cpp
|
fsr.cpp
|
||||||
fsr.h
|
fsr.h
|
||||||
|
|
55
src/video_core/framebuffer_config.cpp
Normal file
55
src/video_core/framebuffer_config.cpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "video_core/framebuffer_config.h"
|
||||||
|
|
||||||
|
namespace Tegra {
|
||||||
|
|
||||||
|
Common::Rectangle<f32> NormalizeCrop(const FramebufferConfig& framebuffer, u32 texture_width,
|
||||||
|
u32 texture_height) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize coordinate space.
|
||||||
|
left /= static_cast<f32>(texture_width);
|
||||||
|
top /= static_cast<f32>(texture_height);
|
||||||
|
right /= static_cast<f32>(texture_width);
|
||||||
|
bottom /= static_cast<f32>(texture_height);
|
||||||
|
|
||||||
|
return Common::Rectangle<f32>(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Tegra
|
|
@ -24,4 +24,7 @@ struct FramebufferConfig {
|
||||||
Common::Rectangle<int> crop_rect;
|
Common::Rectangle<int> crop_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Common::Rectangle<f32> NormalizeCrop(const FramebufferConfig& framebuffer, u32 texture_width,
|
||||||
|
u32 texture_height);
|
||||||
|
|
||||||
} // namespace Tegra
|
} // namespace Tegra
|
||||||
|
|
|
@ -155,12 +155,6 @@ public:
|
||||||
virtual void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
virtual void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
||||||
std::span<const u8> memory) = 0;
|
std::span<const u8> memory) = 0;
|
||||||
|
|
||||||
/// Attempt to use a faster method to display the framebuffer to screen
|
|
||||||
[[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
|
||||||
DAddr framebuffer_addr, u32 pixel_stride) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialize disk cached resources for the game being emulated
|
/// Initialize disk cached resources for the game being emulated
|
||||||
virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||||
const DiskResourceLoadCallback& callback) {}
|
const DiskResourceLoadCallback& callback) {}
|
||||||
|
|
|
@ -92,10 +92,6 @@ bool RasterizerNull::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surfac
|
||||||
}
|
}
|
||||||
void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
||||||
std::span<const u8> memory) {}
|
std::span<const u8> memory) {}
|
||||||
bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
|
||||||
DAddr framebuffer_addr, u32 pixel_stride) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||||
const VideoCore::DiskResourceLoadCallback& callback) {}
|
const VideoCore::DiskResourceLoadCallback& callback) {}
|
||||||
void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) {
|
void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) {
|
||||||
|
|
|
@ -77,8 +77,6 @@ public:
|
||||||
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
|
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
|
||||||
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
||||||
std::span<const u8> memory) override;
|
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,
|
void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||||
void InitializeChannel(Tegra::Control::ChannelState& channel) override;
|
void InitializeChannel(Tegra::Control::ChannelState& channel) override;
|
||||||
|
|
|
@ -25,7 +25,7 @@ FSR::~FSR() = default;
|
||||||
|
|
||||||
void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
|
void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
|
||||||
u32 input_image_width, u32 input_image_height,
|
u32 input_image_width, u32 input_image_height,
|
||||||
const Common::Rectangle<int>& crop_rect) {
|
const Common::Rectangle<f32>& crop_rect) {
|
||||||
|
|
||||||
const auto output_image_width = screen.GetWidth();
|
const auto output_image_width = screen.GetWidth();
|
||||||
const auto output_image_height = screen.GetHeight();
|
const auto output_image_height = screen.GetHeight();
|
||||||
|
@ -57,14 +57,19 @@ void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& sc
|
||||||
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width),
|
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width),
|
||||||
static_cast<GLfloat>(output_image_height));
|
static_cast<GLfloat>(output_image_height));
|
||||||
|
|
||||||
FsrConstants constants;
|
const f32 input_width = static_cast<f32>(input_image_width);
|
||||||
FsrEasuConOffset(
|
const f32 input_height = static_cast<f32>(input_image_height);
|
||||||
constants.data() + 0, constants.data() + 4, constants.data() + 8, constants.data() + 12,
|
const f32 output_width = static_cast<f32>(screen.GetWidth());
|
||||||
|
const f32 output_height = static_cast<f32>(screen.GetHeight());
|
||||||
|
const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width;
|
||||||
|
const f32 viewport_x = crop_rect.left * input_width;
|
||||||
|
const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height;
|
||||||
|
const f32 viewport_y = crop_rect.top * input_height;
|
||||||
|
|
||||||
static_cast<f32>(crop_rect.GetWidth()), static_cast<f32>(crop_rect.GetHeight()),
|
FsrConstants constants;
|
||||||
static_cast<f32>(input_image_width), static_cast<f32>(input_image_height),
|
FsrEasuConOffset(constants.data() + 0, constants.data() + 4, constants.data() + 8,
|
||||||
static_cast<f32>(output_image_width), static_cast<f32>(output_image_height),
|
constants.data() + 12, viewport_width, viewport_height, input_width,
|
||||||
static_cast<f32>(crop_rect.left), static_cast<f32>(crop_rect.top));
|
input_height, output_width, output_height, viewport_x, viewport_y);
|
||||||
|
|
||||||
glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants));
|
glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants));
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
|
|
||||||
void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
|
void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
|
||||||
u32 input_image_width, u32 input_image_height,
|
u32 input_image_width, u32 input_image_height,
|
||||||
const Common::Rectangle<int>& crop_rect);
|
const Common::Rectangle<f32>& crop_rect);
|
||||||
|
|
||||||
void InitBuffers();
|
void InitBuffers();
|
||||||
|
|
||||||
|
|
|
@ -71,10 +71,10 @@ std::optional<VideoCore::QueryType> MaxwellToVideoCoreQuery(VideoCommon::QueryTy
|
||||||
|
|
||||||
RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
||||||
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
const Device& device_, ScreenInfo& screen_info_,
|
const Device& device_, ProgramManager& program_manager_,
|
||||||
ProgramManager& program_manager_, StateTracker& state_tracker_)
|
StateTracker& state_tracker_)
|
||||||
: gpu(gpu_), device_memory(device_memory_), device(device_), screen_info(screen_info_),
|
: gpu(gpu_), device_memory(device_memory_), device(device_), program_manager(program_manager_),
|
||||||
program_manager(program_manager_), state_tracker(state_tracker_),
|
state_tracker(state_tracker_),
|
||||||
texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool),
|
texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool),
|
||||||
texture_cache(texture_cache_runtime, device_memory_),
|
texture_cache(texture_cache_runtime, device_memory_),
|
||||||
buffer_cache_runtime(device, staging_buffer_pool),
|
buffer_cache_runtime(device, staging_buffer_pool),
|
||||||
|
@ -739,10 +739,10 @@ void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
|
||||||
query_cache.InvalidateRegion(*cpu_addr, copy_size);
|
query_cache.InvalidateRegion(*cpu_addr, copy_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
std::optional<FramebufferTextureInfo> RasterizerOpenGL::AccelerateDisplay(
|
||||||
DAddr framebuffer_addr, u32 pixel_stride) {
|
const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, u32 pixel_stride) {
|
||||||
if (framebuffer_addr == 0) {
|
if (framebuffer_addr == 0) {
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
||||||
|
|
||||||
|
@ -750,16 +750,14 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||||
ImageView* const image_view{
|
ImageView* const image_view{
|
||||||
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
|
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
|
||||||
if (!image_view) {
|
if (!image_view) {
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
// Verify that the cached surface is the same size and format as the requested framebuffer
|
|
||||||
// ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different");
|
|
||||||
// ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different");
|
|
||||||
|
|
||||||
screen_info.texture.width = image_view->size.width;
|
FramebufferTextureInfo info{};
|
||||||
screen_info.texture.height = image_view->size.height;
|
info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
|
||||||
screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
|
info.width = image_view->size.width;
|
||||||
return true;
|
info.height = image_view->size.height;
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncState() {
|
void RasterizerOpenGL::SyncState() {
|
||||||
|
|
|
@ -37,7 +37,7 @@ class MemoryManager;
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
struct ScreenInfo;
|
struct FramebufferTextureInfo;
|
||||||
struct ShaderEntries;
|
struct ShaderEntries;
|
||||||
|
|
||||||
struct BindlessSSBO {
|
struct BindlessSSBO {
|
||||||
|
@ -76,8 +76,8 @@ class RasterizerOpenGL : public VideoCore::RasterizerInterface,
|
||||||
public:
|
public:
|
||||||
explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
||||||
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
const Device& device_, ScreenInfo& screen_info_,
|
const Device& device_, ProgramManager& program_manager_,
|
||||||
ProgramManager& program_manager_, StateTracker& state_tracker_);
|
StateTracker& state_tracker_);
|
||||||
~RasterizerOpenGL() override;
|
~RasterizerOpenGL() override;
|
||||||
|
|
||||||
void Draw(bool is_indexed, u32 instance_count) override;
|
void Draw(bool is_indexed, u32 instance_count) override;
|
||||||
|
@ -122,8 +122,6 @@ public:
|
||||||
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
|
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
|
||||||
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
||||||
std::span<const u8> memory) override;
|
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,
|
void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||||
|
|
||||||
|
@ -144,6 +142,10 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||||
|
VAddr framebuffer_addr,
|
||||||
|
u32 pixel_stride);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t MAX_TEXTURES = 192;
|
static constexpr size_t MAX_TEXTURES = 192;
|
||||||
static constexpr size_t MAX_IMAGES = 48;
|
static constexpr size_t MAX_IMAGES = 48;
|
||||||
|
@ -237,7 +239,6 @@ private:
|
||||||
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
||||||
|
|
||||||
const Device& device;
|
const Device& device;
|
||||||
ScreenInfo& screen_info;
|
|
||||||
ProgramManager& program_manager;
|
ProgramManager& program_manager;
|
||||||
StateTracker& state_tracker;
|
StateTracker& state_tracker;
|
||||||
|
|
||||||
|
|
|
@ -148,8 +148,7 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
|
||||||
: RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
|
: RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
|
||||||
emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_},
|
emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_},
|
||||||
state_tracker{}, program_manager{device},
|
state_tracker{}, program_manager{device},
|
||||||
rasterizer(emu_window, gpu, device_memory, device, screen_info, program_manager,
|
rasterizer(emu_window, gpu, device_memory, device, program_manager, state_tracker) {
|
||||||
state_tracker) {
|
|
||||||
if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
|
if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
|
@ -184,11 +183,11 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
if (!framebuffer) {
|
if (!framebuffer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PrepareRendertarget(framebuffer);
|
|
||||||
RenderScreenshot();
|
RenderScreenshot(*framebuffer);
|
||||||
|
|
||||||
state_tracker.BindFramebuffer(0);
|
state_tracker.BindFramebuffer(0);
|
||||||
DrawScreen(emu_window.GetFramebufferLayout());
|
DrawScreen(*framebuffer, emu_window.GetFramebufferLayout());
|
||||||
|
|
||||||
++m_current_frame;
|
++m_current_frame;
|
||||||
|
|
||||||
|
@ -199,41 +198,37 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
render_window.OnFrameDisplayed();
|
render_window.OnFrameDisplayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) {
|
FramebufferTextureInfo RendererOpenGL::PrepareRenderTarget(
|
||||||
if (!framebuffer) {
|
const Tegra::FramebufferConfig& framebuffer) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If framebuffer is provided, reload it from memory to a texture
|
// If framebuffer is provided, reload it from memory to a texture
|
||||||
if (screen_info.texture.width != static_cast<GLsizei>(framebuffer->width) ||
|
if (framebuffer_texture.width != static_cast<GLsizei>(framebuffer.width) ||
|
||||||
screen_info.texture.height != static_cast<GLsizei>(framebuffer->height) ||
|
framebuffer_texture.height != static_cast<GLsizei>(framebuffer.height) ||
|
||||||
screen_info.texture.pixel_format != framebuffer->pixel_format ||
|
framebuffer_texture.pixel_format != framebuffer.pixel_format ||
|
||||||
gl_framebuffer_data.empty()) {
|
gl_framebuffer_data.empty()) {
|
||||||
// Reallocate texture if the framebuffer size has changed.
|
// Reallocate texture if the framebuffer size has changed.
|
||||||
// This is expected to not happen very often and hence should not be a
|
// This is expected to not happen very often and hence should not be a
|
||||||
// performance problem.
|
// performance problem.
|
||||||
ConfigureFramebufferTexture(screen_info.texture, *framebuffer);
|
ConfigureFramebufferTexture(framebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the framebuffer from memory, draw it to the screen, and swap buffers
|
// Load the framebuffer from memory if needed
|
||||||
LoadFBToScreenInfo(*framebuffer);
|
return LoadFBToScreenInfo(framebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) {
|
FramebufferTextureInfo RendererOpenGL::LoadFBToScreenInfo(
|
||||||
// Framebuffer orientation handling
|
const Tegra::FramebufferConfig& framebuffer) {
|
||||||
framebuffer_transform_flags = framebuffer.transform_flags;
|
|
||||||
framebuffer_crop_rect = framebuffer.crop_rect;
|
|
||||||
framebuffer_width = framebuffer.width;
|
|
||||||
framebuffer_height = framebuffer.height;
|
|
||||||
|
|
||||||
const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
|
const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
|
||||||
screen_info.was_accelerated =
|
const auto accelerated_info =
|
||||||
rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride);
|
rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride);
|
||||||
if (screen_info.was_accelerated) {
|
if (accelerated_info) {
|
||||||
return;
|
return *accelerated_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the screen info's display texture to its own permanent texture
|
// Reset the screen info's display texture to its own permanent texture
|
||||||
screen_info.display_texture = screen_info.texture.resource.handle;
|
FramebufferTextureInfo info{};
|
||||||
|
info.display_texture = framebuffer_texture.resource.handle;
|
||||||
|
info.width = framebuffer.width;
|
||||||
|
info.height = framebuffer.height;
|
||||||
|
|
||||||
// TODO(Rodrigo): Read this from HLE
|
// TODO(Rodrigo): Read this from HLE
|
||||||
constexpr u32 block_height_log2 = 4;
|
constexpr u32 block_height_log2 = 4;
|
||||||
|
@ -256,17 +251,13 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
|
||||||
// they differ from the LCD resolution.
|
// they differ from the LCD resolution.
|
||||||
// TODO: Applications could theoretically crash yuzu here by specifying too large
|
// TODO: Applications could theoretically crash yuzu here by specifying too large
|
||||||
// framebuffer sizes. We should make sure that this cannot happen.
|
// framebuffer sizes. We should make sure that this cannot happen.
|
||||||
glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width,
|
glTextureSubImage2D(framebuffer_texture.resource.handle, 0, 0, 0, framebuffer.width,
|
||||||
framebuffer.height, screen_info.texture.gl_format,
|
framebuffer.height, framebuffer_texture.gl_format,
|
||||||
screen_info.texture.gl_type, gl_framebuffer_data.data());
|
framebuffer_texture.gl_type, gl_framebuffer_data.data());
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
}
|
|
||||||
|
|
||||||
void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
|
return info;
|
||||||
const TextureInfo& texture) {
|
|
||||||
const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
|
|
||||||
glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::InitOpenGLObjects() {
|
void RendererOpenGL::InitOpenGLObjects() {
|
||||||
|
@ -343,15 +334,15 @@ void RendererOpenGL::InitOpenGLObjects() {
|
||||||
glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
|
glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
|
||||||
|
|
||||||
// Allocate textures for the screen
|
// Allocate textures for the screen
|
||||||
screen_info.texture.resource.Create(GL_TEXTURE_2D);
|
framebuffer_texture.resource.Create(GL_TEXTURE_2D);
|
||||||
|
|
||||||
const GLuint texture = screen_info.texture.resource.handle;
|
const GLuint texture = framebuffer_texture.resource.handle;
|
||||||
glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1);
|
glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1);
|
||||||
|
|
||||||
screen_info.display_texture = screen_info.texture.resource.handle;
|
|
||||||
|
|
||||||
// Clear screen to black
|
// Clear screen to black
|
||||||
LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture);
|
const u8 framebuffer_data[4] = {0, 0, 0, 0};
|
||||||
|
glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
framebuffer_data);
|
||||||
|
|
||||||
aa_framebuffer.Create();
|
aa_framebuffer.Create();
|
||||||
|
|
||||||
|
@ -380,60 +371,65 @@ void RendererOpenGL::AddTelemetryFields() {
|
||||||
telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
|
telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
|
void RendererOpenGL::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer) {
|
||||||
const Tegra::FramebufferConfig& framebuffer) {
|
framebuffer_texture.width = framebuffer.width;
|
||||||
texture.width = framebuffer.width;
|
framebuffer_texture.height = framebuffer.height;
|
||||||
texture.height = framebuffer.height;
|
framebuffer_texture.pixel_format = framebuffer.pixel_format;
|
||||||
texture.pixel_format = framebuffer.pixel_format;
|
|
||||||
|
|
||||||
const auto pixel_format{
|
const auto pixel_format{
|
||||||
VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
|
VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
|
||||||
const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
|
const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
|
||||||
gl_framebuffer_data.resize(texture.width * texture.height * bytes_per_pixel);
|
gl_framebuffer_data.resize(framebuffer_texture.width * framebuffer_texture.height *
|
||||||
|
bytes_per_pixel);
|
||||||
|
|
||||||
GLint internal_format;
|
GLint internal_format;
|
||||||
switch (framebuffer.pixel_format) {
|
switch (framebuffer.pixel_format) {
|
||||||
case Service::android::PixelFormat::Rgba8888:
|
case Service::android::PixelFormat::Rgba8888:
|
||||||
internal_format = GL_RGBA8;
|
internal_format = GL_RGBA8;
|
||||||
texture.gl_format = GL_RGBA;
|
framebuffer_texture.gl_format = GL_RGBA;
|
||||||
texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||||
break;
|
break;
|
||||||
case Service::android::PixelFormat::Rgb565:
|
case Service::android::PixelFormat::Rgb565:
|
||||||
internal_format = GL_RGB565;
|
internal_format = GL_RGB565;
|
||||||
texture.gl_format = GL_RGB;
|
framebuffer_texture.gl_format = GL_RGB;
|
||||||
texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
|
framebuffer_texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
internal_format = GL_RGBA8;
|
internal_format = GL_RGBA8;
|
||||||
texture.gl_format = GL_RGBA;
|
framebuffer_texture.gl_format = GL_RGBA;
|
||||||
texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||||
// UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
|
// UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
|
||||||
// static_cast<u32>(framebuffer.pixel_format));
|
// static_cast<u32>(framebuffer.pixel_format));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture.resource.Release();
|
framebuffer_texture.resource.Release();
|
||||||
texture.resource.Create(GL_TEXTURE_2D);
|
framebuffer_texture.resource.Create(GL_TEXTURE_2D);
|
||||||
glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height);
|
glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format,
|
||||||
|
framebuffer_texture.width, framebuffer_texture.height);
|
||||||
aa_texture.Release();
|
aa_texture.Release();
|
||||||
aa_texture.Create(GL_TEXTURE_2D);
|
aa_texture.Create(GL_TEXTURE_2D);
|
||||||
glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F,
|
glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F,
|
||||||
Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
|
Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
|
||||||
Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
|
Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
|
||||||
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0);
|
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0);
|
||||||
smaa_edges_tex.Release();
|
smaa_edges_tex.Release();
|
||||||
smaa_edges_tex.Create(GL_TEXTURE_2D);
|
smaa_edges_tex.Create(GL_TEXTURE_2D);
|
||||||
glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F,
|
glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F,
|
||||||
Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
|
Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
|
||||||
Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
|
Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
|
||||||
smaa_blend_tex.Release();
|
smaa_blend_tex.Release();
|
||||||
smaa_blend_tex.Create(GL_TEXTURE_2D);
|
smaa_blend_tex.Create(GL_TEXTURE_2D);
|
||||||
glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F,
|
glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F,
|
||||||
Settings::values.resolution_info.ScaleUp(screen_info.texture.width),
|
Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
|
||||||
Settings::values.resolution_info.ScaleUp(screen_info.texture.height));
|
Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
|
||||||
|
const Layout::FramebufferLayout& layout) {
|
||||||
|
FramebufferTextureInfo info = PrepareRenderTarget(framebuffer);
|
||||||
|
const auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height);
|
||||||
|
|
||||||
// TODO: Signal state tracker about these changes
|
// TODO: Signal state tracker about these changes
|
||||||
state_tracker.NotifyScreenDrawVertexArray();
|
state_tracker.NotifyScreenDrawVertexArray();
|
||||||
state_tracker.NotifyPolygonModes();
|
state_tracker.NotifyPolygonModes();
|
||||||
|
@ -469,7 +465,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
||||||
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
glDepthRangeIndexed(0, 0.0, 0.0);
|
glDepthRangeIndexed(0, 0.0, 0.0);
|
||||||
|
|
||||||
glBindTextureUnit(0, screen_info.display_texture);
|
glBindTextureUnit(0, info.display_texture);
|
||||||
|
|
||||||
auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
|
auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
|
||||||
if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
|
if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
|
||||||
|
@ -480,22 +476,22 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
||||||
|
|
||||||
if (anti_aliasing != Settings::AntiAliasing::None) {
|
if (anti_aliasing != Settings::AntiAliasing::None) {
|
||||||
glEnablei(GL_SCISSOR_TEST, 0);
|
glEnablei(GL_SCISSOR_TEST, 0);
|
||||||
auto viewport_width = screen_info.texture.width;
|
auto viewport_width = info.width;
|
||||||
auto scissor_width = framebuffer_crop_rect.GetWidth();
|
auto scissor_width = static_cast<u32>(crop.GetWidth());
|
||||||
if (scissor_width <= 0) {
|
if (scissor_width <= 0) {
|
||||||
scissor_width = viewport_width;
|
scissor_width = viewport_width;
|
||||||
}
|
}
|
||||||
auto viewport_height = screen_info.texture.height;
|
auto viewport_height = info.height;
|
||||||
auto scissor_height = framebuffer_crop_rect.GetHeight();
|
auto scissor_height = static_cast<u32>(crop.GetHeight());
|
||||||
if (scissor_height <= 0) {
|
if (scissor_height <= 0) {
|
||||||
scissor_height = viewport_height;
|
scissor_height = viewport_height;
|
||||||
}
|
}
|
||||||
if (screen_info.was_accelerated) {
|
|
||||||
viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width);
|
viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width);
|
||||||
scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width);
|
scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width);
|
||||||
viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height);
|
viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height);
|
||||||
scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height);
|
scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height);
|
||||||
}
|
|
||||||
glScissorIndexed(0, 0, 0, scissor_width, scissor_height);
|
glScissorIndexed(0, 0, 0, scissor_width, scissor_height);
|
||||||
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width),
|
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width),
|
||||||
static_cast<GLfloat>(viewport_height));
|
static_cast<GLfloat>(viewport_height));
|
||||||
|
@ -536,7 +532,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
||||||
smaa_blending_weight_calculation_frag.handle);
|
smaa_blending_weight_calculation_frag.handle);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
|
||||||
glBindTextureUnit(0, screen_info.display_texture);
|
glBindTextureUnit(0, info.display_texture);
|
||||||
glBindTextureUnit(1, smaa_blend_tex.handle);
|
glBindTextureUnit(1, smaa_blend_tex.handle);
|
||||||
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
|
glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
|
||||||
aa_texture.handle, 0);
|
aa_texture.handle, 0);
|
||||||
|
@ -561,18 +557,10 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
||||||
fsr->InitBuffers();
|
fsr->InitBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto crop_rect = framebuffer_crop_rect;
|
const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(info.width);
|
||||||
if (crop_rect.GetWidth() == 0) {
|
const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(info.height);
|
||||||
crop_rect.right = framebuffer_width;
|
|
||||||
}
|
|
||||||
if (crop_rect.GetHeight() == 0) {
|
|
||||||
crop_rect.bottom = framebuffer_height;
|
|
||||||
}
|
|
||||||
crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor);
|
|
||||||
const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(framebuffer_width);
|
|
||||||
const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(framebuffer_height);
|
|
||||||
glBindSampler(0, present_sampler.handle);
|
glBindSampler(0, present_sampler.handle);
|
||||||
fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop_rect);
|
fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop);
|
||||||
} else {
|
} else {
|
||||||
if (fsr->AreBuffersInitialized()) {
|
if (fsr->AreBuffersInitialized()) {
|
||||||
fsr->ReleaseBuffers();
|
fsr->ReleaseBuffers();
|
||||||
|
@ -603,61 +591,34 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
||||||
glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
|
glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
|
||||||
ortho_matrix.data());
|
ortho_matrix.data());
|
||||||
|
|
||||||
const auto& texcoords = screen_info.display_texcoords;
|
f32 left, top, right, bottom;
|
||||||
auto left = texcoords.left;
|
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
|
||||||
auto right = texcoords.right;
|
// FSR has already applied the crop, so we just want to render the image
|
||||||
if (framebuffer_transform_flags != Service::android::BufferTransformFlags::Unset) {
|
// it has produced.
|
||||||
if (framebuffer_transform_flags == Service::android::BufferTransformFlags::FlipV) {
|
left = 0;
|
||||||
// Flip the framebuffer vertically
|
top = 0;
|
||||||
left = texcoords.right;
|
right = 1;
|
||||||
right = texcoords.left;
|
bottom = 1;
|
||||||
} else {
|
} else {
|
||||||
// Other transformations are unsupported
|
// Apply the precomputed crop.
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags={}",
|
left = crop.left;
|
||||||
framebuffer_transform_flags);
|
top = crop.top;
|
||||||
UNIMPLEMENTED();
|
right = crop.right;
|
||||||
}
|
bottom = crop.bottom;
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented");
|
|
||||||
|
|
||||||
f32 left_start{};
|
|
||||||
if (framebuffer_crop_rect.Top() > 0) {
|
|
||||||
left_start = static_cast<f32>(framebuffer_crop_rect.Top()) /
|
|
||||||
static_cast<f32>(framebuffer_crop_rect.Bottom());
|
|
||||||
}
|
|
||||||
f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width);
|
|
||||||
f32 scale_v =
|
|
||||||
static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height);
|
|
||||||
|
|
||||||
if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::Fsr) {
|
|
||||||
// Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
|
|
||||||
// (e.g. handheld mode) on a 1920x1080 framebuffer.
|
|
||||||
if (framebuffer_crop_rect.GetWidth() > 0) {
|
|
||||||
scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) /
|
|
||||||
static_cast<f32>(screen_info.texture.width);
|
|
||||||
}
|
|
||||||
if (framebuffer_crop_rect.GetHeight() > 0) {
|
|
||||||
scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) /
|
|
||||||
static_cast<f32>(screen_info.texture.height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa &&
|
|
||||||
!screen_info.was_accelerated) {
|
|
||||||
scale_u /= Settings::values.resolution_info.up_factor;
|
|
||||||
scale_v /= Settings::values.resolution_info.up_factor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map the coordinates to the screen.
|
||||||
const auto& screen = layout.screen;
|
const auto& screen = layout.screen;
|
||||||
|
const auto x = screen.left;
|
||||||
|
const auto y = screen.top;
|
||||||
|
const auto w = screen.GetWidth();
|
||||||
|
const auto h = screen.GetHeight();
|
||||||
|
|
||||||
const std::array vertices = {
|
const std::array vertices = {
|
||||||
ScreenRectVertex(screen.left, screen.top, texcoords.top * scale_u,
|
ScreenRectVertex(x, y, left, top),
|
||||||
left_start + left * scale_v),
|
ScreenRectVertex(x + w, y, right, top),
|
||||||
ScreenRectVertex(screen.right, screen.top, texcoords.bottom * scale_u,
|
ScreenRectVertex(x, y + h, left, bottom),
|
||||||
left_start + left * scale_v),
|
ScreenRectVertex(x + w, y + h, right, bottom),
|
||||||
ScreenRectVertex(screen.left, screen.bottom, texcoords.top * scale_u,
|
|
||||||
left_start + right * scale_v),
|
|
||||||
ScreenRectVertex(screen.right, screen.bottom, texcoords.bottom * scale_u,
|
|
||||||
left_start + right * scale_v),
|
|
||||||
};
|
};
|
||||||
glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
|
glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
|
||||||
|
|
||||||
|
@ -701,7 +662,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
||||||
// program_manager.RestoreGuestPipeline();
|
// program_manager.RestoreGuestPipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::RenderScreenshot() {
|
void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) {
|
||||||
if (!renderer_settings.screenshot_requested) {
|
if (!renderer_settings.screenshot_requested) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -723,7 +684,7 @@ void RendererOpenGL::RenderScreenshot() {
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
|
||||||
|
|
||||||
DrawScreen(layout);
|
DrawScreen(framebuffer, layout);
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||||
|
|
|
@ -50,11 +50,10 @@ struct TextureInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Structure used for storing information about the display target for the Switch screen
|
/// Structure used for storing information about the display target for the Switch screen
|
||||||
struct ScreenInfo {
|
struct FramebufferTextureInfo {
|
||||||
GLuint display_texture{};
|
GLuint display_texture{};
|
||||||
bool was_accelerated = false;
|
u32 width;
|
||||||
const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f};
|
u32 height;
|
||||||
TextureInfo texture;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RendererOpenGL final : public VideoCore::RendererBase {
|
class RendererOpenGL final : public VideoCore::RendererBase {
|
||||||
|
@ -81,23 +80,18 @@ private:
|
||||||
|
|
||||||
void AddTelemetryFields();
|
void AddTelemetryFields();
|
||||||
|
|
||||||
void ConfigureFramebufferTexture(TextureInfo& texture,
|
void ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer);
|
||||||
const Tegra::FramebufferConfig& framebuffer);
|
|
||||||
|
|
||||||
/// Draws the emulated screens to the emulator window.
|
/// Draws the emulated screens to the emulator window.
|
||||||
void DrawScreen(const Layout::FramebufferLayout& layout);
|
void DrawScreen(const Tegra::FramebufferConfig& framebuffer,
|
||||||
|
const Layout::FramebufferLayout& layout);
|
||||||
|
|
||||||
void RenderScreenshot();
|
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer);
|
||||||
|
|
||||||
/// Loads framebuffer from emulated memory into the active OpenGL texture.
|
/// Loads framebuffer from emulated memory into the active OpenGL texture.
|
||||||
void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer);
|
FramebufferTextureInfo LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer);
|
||||||
|
|
||||||
/// Fills active OpenGL texture with the given RGB color.Since the color is solid, the texture
|
FramebufferTextureInfo PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer);
|
||||||
/// can be 1x1 but will stretch across whatever it's rendered on.
|
|
||||||
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
|
|
||||||
const TextureInfo& texture);
|
|
||||||
|
|
||||||
void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer);
|
|
||||||
|
|
||||||
Core::TelemetrySession& telemetry_session;
|
Core::TelemetrySession& telemetry_session;
|
||||||
Core::Frontend::EmuWindow& emu_window;
|
Core::Frontend::EmuWindow& emu_window;
|
||||||
|
@ -126,7 +120,7 @@ private:
|
||||||
GLuint64EXT vertex_buffer_address = 0;
|
GLuint64EXT vertex_buffer_address = 0;
|
||||||
|
|
||||||
/// Display information for Switch screen
|
/// Display information for Switch screen
|
||||||
ScreenInfo screen_info;
|
TextureInfo framebuffer_texture;
|
||||||
OGLTexture aa_texture;
|
OGLTexture aa_texture;
|
||||||
OGLFramebuffer aa_framebuffer;
|
OGLFramebuffer aa_framebuffer;
|
||||||
|
|
||||||
|
@ -145,12 +139,6 @@ private:
|
||||||
|
|
||||||
/// OpenGL framebuffer data
|
/// OpenGL framebuffer data
|
||||||
std::vector<u8> gl_framebuffer_data;
|
std::vector<u8> gl_framebuffer_data;
|
||||||
|
|
||||||
/// Used for transforming the framebuffer orientation
|
|
||||||
Service::android::BufferTransformFlags framebuffer_transform_flags{};
|
|
||||||
Common::Rectangle<int> framebuffer_crop_rect;
|
|
||||||
u32 framebuffer_width;
|
|
||||||
u32 framebuffer_height;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
|
@ -98,9 +98,9 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
|
||||||
present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
|
present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
|
||||||
surface),
|
surface),
|
||||||
blit_screen(device_memory, render_window, device, memory_allocator, swapchain,
|
blit_screen(device_memory, render_window, device, memory_allocator, swapchain,
|
||||||
present_manager, scheduler, screen_info),
|
present_manager, scheduler),
|
||||||
rasterizer(render_window, gpu, device_memory, screen_info, device, memory_allocator,
|
rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker,
|
||||||
state_tracker, scheduler) {
|
scheduler) {
|
||||||
if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
|
if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
|
||||||
turbo_mode.emplace(instance, dld);
|
turbo_mode.emplace(instance, dld);
|
||||||
scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); });
|
scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); });
|
||||||
|
@ -124,17 +124,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
if (!render_window.IsShown()) {
|
if (!render_window.IsShown()) {
|
||||||
return;
|
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();
|
Frame* frame = present_manager.GetRenderFrame();
|
||||||
blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated);
|
blit_screen.DrawToSwapchain(rasterizer, frame, *framebuffer);
|
||||||
scheduler.Flush(*frame->render_ready);
|
scheduler.Flush(*frame->render_ready);
|
||||||
present_manager.Present(frame);
|
present_manager.Present(frame);
|
||||||
|
|
||||||
|
@ -168,8 +161,7 @@ void RendererVulkan::Report() const {
|
||||||
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
|
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer,
|
void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) {
|
||||||
bool use_accelerated) {
|
|
||||||
if (!renderer_settings.screenshot_requested) {
|
if (!renderer_settings.screenshot_requested) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +213,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr
|
||||||
});
|
});
|
||||||
const VkExtent2D render_area{.width = layout.width, .height = layout.height};
|
const VkExtent2D render_area{.width = layout.width, .height = layout.height};
|
||||||
const vk::Framebuffer screenshot_fb = blit_screen.CreateFramebuffer(*dst_view, render_area);
|
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 auto buffer_size = static_cast<VkDeviceSize>(layout.width * layout.height * 4);
|
||||||
const VkBufferCreateInfo dst_buffer_info{
|
const VkBufferCreateInfo dst_buffer_info{
|
||||||
|
|
|
@ -59,7 +59,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void Report() const;
|
void Report() const;
|
||||||
|
|
||||||
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated);
|
void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer);
|
||||||
|
|
||||||
Core::TelemetrySession& telemetry_session;
|
Core::TelemetrySession& telemetry_session;
|
||||||
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
||||||
|
@ -72,8 +72,6 @@ private:
|
||||||
vk::DebugUtilsMessenger debug_messenger;
|
vk::DebugUtilsMessenger debug_messenger;
|
||||||
vk::SurfaceKHR surface;
|
vk::SurfaceKHR surface;
|
||||||
|
|
||||||
ScreenInfo screen_info;
|
|
||||||
|
|
||||||
Device device;
|
Device device;
|
||||||
MemoryAllocator memory_allocator;
|
MemoryAllocator memory_allocator;
|
||||||
StateTracker state_tracker;
|
StateTracker state_tracker;
|
||||||
|
|
|
@ -124,11 +124,10 @@ struct BlitScreen::BufferData {
|
||||||
BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
Core::Frontend::EmuWindow& render_window_, const Device& device_,
|
Core::Frontend::EmuWindow& render_window_, const Device& device_,
|
||||||
MemoryAllocator& memory_allocator_, Swapchain& swapchain_,
|
MemoryAllocator& memory_allocator_, Swapchain& swapchain_,
|
||||||
PresentManager& present_manager_, Scheduler& scheduler_,
|
PresentManager& present_manager_, Scheduler& scheduler_)
|
||||||
const ScreenInfo& screen_info_)
|
|
||||||
: device_memory{device_memory_}, render_window{render_window_}, device{device_},
|
: device_memory{device_memory_}, render_window{render_window_}, device{device_},
|
||||||
memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_},
|
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);
|
resource_ticks.resize(image_count);
|
||||||
swapchain_view_format = swapchain.GetImageViewFormat();
|
swapchain_view_format = swapchain.GetImageViewFormat();
|
||||||
|
|
||||||
|
@ -138,56 +137,6 @@ BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
|
|
||||||
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();
|
||||||
|
@ -195,9 +144,16 @@ void BlitScreen::Recreate() {
|
||||||
CreateDynamicResources();
|
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,
|
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);
|
RefreshResources(framebuffer);
|
||||||
|
|
||||||
// Finish any pending renderpass
|
// Finish any pending renderpass
|
||||||
|
@ -206,13 +162,13 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
||||||
scheduler.Wait(resource_ticks[image_index]);
|
scheduler.Wait(resource_ticks[image_index]);
|
||||||
resource_ticks[image_index] = scheduler.CurrentTick();
|
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 =
|
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;
|
BufferData data;
|
||||||
SetUniformData(data, layout);
|
SetUniformData(data, layout);
|
||||||
SetVertexData(data, framebuffer, layout);
|
SetVertexData(data, framebuffer, layout, texture_width, texture_height);
|
||||||
|
|
||||||
const std::span<u8> mapped_span = buffer.Mapped();
|
const std::span<u8> mapped_span = buffer.Mapped();
|
||||||
std::memcpy(mapped_span.data(), &data, sizeof(data));
|
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);
|
source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view);
|
||||||
}
|
}
|
||||||
if (fsr) {
|
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{
|
const VkExtent2D fsr_input_size{
|
||||||
.width = Settings::values.resolution_info.ScaleUp(screen_info.width),
|
.width = Settings::values.resolution_info.ScaleUp(texture_width),
|
||||||
.height = Settings::values.resolution_info.ScaleUp(screen_info.height),
|
.height = Settings::values.resolution_info.ScaleUp(texture_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);
|
||||||
|
@ -480,8 +436,8 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
|
void BlitScreen::DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame,
|
||||||
bool use_accelerated) {
|
const Tegra::FramebufferConfig& framebuffer) {
|
||||||
// Recreate dynamic resources if the the image count or input format changed
|
// Recreate dynamic resources if the the image count or input format changed
|
||||||
const VkFormat current_framebuffer_format =
|
const VkFormat current_framebuffer_format =
|
||||||
std::exchange(framebuffer_view_format, GetFormat(framebuffer));
|
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};
|
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) {
|
if (++image_index >= image_count) {
|
||||||
image_index = 0;
|
image_index = 0;
|
||||||
}
|
}
|
||||||
|
@ -1434,7 +1390,8 @@ void BlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayou
|
||||||
}
|
}
|
||||||
|
|
||||||
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, u32 texture_width,
|
||||||
|
u32 texture_height) const {
|
||||||
f32 left, top, right, bottom;
|
f32 left, top, right, bottom;
|
||||||
|
|
||||||
if (fsr) {
|
if (fsr) {
|
||||||
|
@ -1446,7 +1403,7 @@ void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig&
|
||||||
bottom = 1;
|
bottom = 1;
|
||||||
} else {
|
} else {
|
||||||
// Get the normalized crop rectangle.
|
// 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.
|
// Apply the crop.
|
||||||
left = crop.left;
|
left = crop.left;
|
||||||
|
|
|
@ -32,8 +32,6 @@ enum class PixelFormat : u32;
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
struct ScreenInfo;
|
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
class FSR;
|
class FSR;
|
||||||
class RasterizerVulkan;
|
class RasterizerVulkan;
|
||||||
|
@ -44,7 +42,7 @@ class PresentManager;
|
||||||
|
|
||||||
struct Frame;
|
struct Frame;
|
||||||
|
|
||||||
struct ScreenInfo {
|
struct FramebufferTextureInfo {
|
||||||
VkImage image{};
|
VkImage image{};
|
||||||
VkImageView image_view{};
|
VkImageView image_view{};
|
||||||
u32 width{};
|
u32 width{};
|
||||||
|
@ -56,17 +54,17 @@ public:
|
||||||
explicit BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory,
|
explicit BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory,
|
||||||
Core::Frontend::EmuWindow& render_window, const Device& device,
|
Core::Frontend::EmuWindow& render_window, const Device& device,
|
||||||
MemoryAllocator& memory_manager, Swapchain& swapchain,
|
MemoryAllocator& memory_manager, Swapchain& swapchain,
|
||||||
PresentManager& present_manager, Scheduler& scheduler,
|
PresentManager& present_manager, Scheduler& scheduler);
|
||||||
const ScreenInfo& screen_info);
|
|
||||||
~BlitScreen();
|
~BlitScreen();
|
||||||
|
|
||||||
void Recreate();
|
void Recreate();
|
||||||
|
|
||||||
void Draw(const Tegra::FramebufferConfig& framebuffer, const VkFramebuffer& host_framebuffer,
|
void Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer,
|
||||||
const Layout::FramebufferLayout layout, VkExtent2D render_area, bool use_accelerated);
|
const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout,
|
||||||
|
VkExtent2D render_area);
|
||||||
|
|
||||||
void DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
|
void DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame,
|
||||||
bool use_accelerated);
|
const Tegra::FramebufferConfig& framebuffer);
|
||||||
|
|
||||||
[[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view,
|
[[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view,
|
||||||
VkExtent2D extent);
|
VkExtent2D extent);
|
||||||
|
@ -99,7 +97,8 @@ private:
|
||||||
void UpdateAADescriptorSet(VkImageView image_view, bool nn) const;
|
void UpdateAADescriptorSet(VkImageView image_view, bool nn) const;
|
||||||
void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const;
|
void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const;
|
||||||
void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
|
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 CreateSMAA(VkExtent2D smaa_size);
|
||||||
void CreateFSR();
|
void CreateFSR();
|
||||||
|
@ -116,7 +115,6 @@ private:
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
std::size_t image_count;
|
std::size_t image_count;
|
||||||
std::size_t image_index{};
|
std::size_t image_index{};
|
||||||
const ScreenInfo& screen_info;
|
|
||||||
|
|
||||||
vk::ShaderModule vertex_shader;
|
vk::ShaderModule vertex_shader;
|
||||||
vk::ShaderModule fxaa_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_,
|
RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
||||||
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
ScreenInfo& screen_info_, const Device& device_,
|
const Device& device_, MemoryAllocator& memory_allocator_,
|
||||||
MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
|
StateTracker& state_tracker_, Scheduler& scheduler_)
|
||||||
Scheduler& scheduler_)
|
: gpu{gpu_}, device_memory{device_memory_}, device{device_},
|
||||||
: gpu{gpu_}, device_memory{device_memory_}, screen_info{screen_info_}, device{device_},
|
|
||||||
memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_},
|
memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_},
|
||||||
staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
|
staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
|
||||||
guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(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);
|
query_cache.InvalidateRegion(*cpu_addr, copy_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
std::optional<FramebufferTextureInfo> RasterizerVulkan::AccelerateDisplay(
|
||||||
DAddr framebuffer_addr, u32 pixel_stride) {
|
const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, u32 pixel_stride) {
|
||||||
if (!framebuffer_addr) {
|
if (!framebuffer_addr) {
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
std::scoped_lock lock{texture_cache.mutex};
|
std::scoped_lock lock{texture_cache.mutex};
|
||||||
ImageView* const image_view =
|
ImageView* const image_view =
|
||||||
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
|
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
|
||||||
if (!image_view) {
|
if (!image_view) {
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
query_cache.NotifySegment(false);
|
query_cache.NotifySegment(false);
|
||||||
screen_info.image = image_view->ImageHandle();
|
|
||||||
screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D);
|
FramebufferTextureInfo info{};
|
||||||
screen_info.width = image_view->size.width;
|
info.image = image_view->ImageHandle();
|
||||||
screen_info.height = image_view->size.height;
|
info.image_view = image_view->Handle(Shader::TextureType::Color2D);
|
||||||
return true;
|
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,
|
void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Maxwell3D;
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
struct ScreenInfo;
|
struct FramebufferTextureInfo;
|
||||||
|
|
||||||
class StateTracker;
|
class StateTracker;
|
||||||
|
|
||||||
|
@ -78,9 +78,8 @@ class RasterizerVulkan final : public VideoCore::RasterizerInterface,
|
||||||
public:
|
public:
|
||||||
explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
||||||
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
||||||
ScreenInfo& screen_info_, const Device& device_,
|
const Device& device_, MemoryAllocator& memory_allocator_,
|
||||||
MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
|
StateTracker& state_tracker_, Scheduler& scheduler_);
|
||||||
Scheduler& scheduler_);
|
|
||||||
~RasterizerVulkan() override;
|
~RasterizerVulkan() override;
|
||||||
|
|
||||||
void Draw(bool is_indexed, u32 instance_count) override;
|
void Draw(bool is_indexed, u32 instance_count) override;
|
||||||
|
@ -126,8 +125,6 @@ public:
|
||||||
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
|
Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
|
||||||
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
|
||||||
std::span<const u8> memory) override;
|
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,
|
void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||||
|
|
||||||
|
@ -137,6 +134,10 @@ public:
|
||||||
|
|
||||||
void ReleaseChannel(s32 channel_id) override;
|
void ReleaseChannel(s32 channel_id) override;
|
||||||
|
|
||||||
|
std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||||
|
VAddr framebuffer_addr,
|
||||||
|
u32 pixel_stride);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t MAX_TEXTURES = 192;
|
static constexpr size_t MAX_TEXTURES = 192;
|
||||||
static constexpr size_t MAX_IMAGES = 48;
|
static constexpr size_t MAX_IMAGES = 48;
|
||||||
|
@ -182,7 +183,6 @@ private:
|
||||||
Tegra::GPU& gpu;
|
Tegra::GPU& gpu;
|
||||||
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
||||||
|
|
||||||
ScreenInfo& screen_info;
|
|
||||||
const Device& device;
|
const Device& device;
|
||||||
MemoryAllocator& memory_allocator;
|
MemoryAllocator& memory_allocator;
|
||||||
StateTracker& state_tracker;
|
StateTracker& state_tracker;
|
||||||
|
|
Loading…
Reference in a new issue