forked from suyu/suyu
video_core: consistently account for resolution scaling when rendering
This commit is contained in:
parent
80de01a5b4
commit
453091f611
10 changed files with 40 additions and 31 deletions
|
@ -747,16 +747,20 @@ std::optional<FramebufferTextureInfo> RasterizerOpenGL::AccelerateDisplay(
|
||||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
||||||
|
|
||||||
std::scoped_lock lock{texture_cache.mutex};
|
std::scoped_lock lock{texture_cache.mutex};
|
||||||
ImageView* const image_view{
|
const auto [image_view, scaled] =
|
||||||
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
|
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
|
||||||
if (!image_view) {
|
if (!image_view) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& resolution = Settings::values.resolution_info;
|
||||||
|
|
||||||
FramebufferTextureInfo info{};
|
FramebufferTextureInfo info{};
|
||||||
info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
|
info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
|
||||||
info.width = image_view->size.width;
|
info.width = image_view->size.width;
|
||||||
info.height = image_view->size.height;
|
info.height = image_view->size.height;
|
||||||
|
info.scaled_width = scaled ? resolution.ScaleUp(info.width) : info.width;
|
||||||
|
info.scaled_height = scaled ? resolution.ScaleUp(info.height) : info.height;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1051,6 +1051,10 @@ void Image::Scale(bool up_scale) {
|
||||||
state_tracker.NotifyScissor0();
|
state_tracker.NotifyScissor0();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Image::IsRescaled() const {
|
||||||
|
return True(flags & ImageFlagBits::Rescaled);
|
||||||
|
}
|
||||||
|
|
||||||
bool Image::ScaleUp(bool ignore) {
|
bool Image::ScaleUp(bool ignore) {
|
||||||
const auto& resolution = runtime->resolution;
|
const auto& resolution = runtime->resolution;
|
||||||
if (!resolution.active) {
|
if (!resolution.active) {
|
||||||
|
|
|
@ -217,6 +217,8 @@ public:
|
||||||
return gl_type;
|
return gl_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsRescaled() const;
|
||||||
|
|
||||||
bool ScaleUp(bool ignore = false);
|
bool ScaleUp(bool ignore = false);
|
||||||
|
|
||||||
bool ScaleDown(bool ignore = false);
|
bool ScaleDown(bool ignore = false);
|
||||||
|
|
|
@ -229,6 +229,8 @@ FramebufferTextureInfo RendererOpenGL::LoadFBToScreenInfo(
|
||||||
info.display_texture = framebuffer_texture.resource.handle;
|
info.display_texture = framebuffer_texture.resource.handle;
|
||||||
info.width = framebuffer.width;
|
info.width = framebuffer.width;
|
||||||
info.height = framebuffer.height;
|
info.height = framebuffer.height;
|
||||||
|
info.scaled_width = framebuffer.width;
|
||||||
|
info.scaled_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;
|
||||||
|
@ -476,25 +478,13 @@ void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
|
||||||
|
|
||||||
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 = info.width;
|
auto scissor_width = Settings::values.resolution_info.ScaleUp(framebuffer_texture.width);
|
||||||
auto scissor_width = static_cast<u32>(crop.GetWidth());
|
auto viewport_width = static_cast<GLfloat>(scissor_width);
|
||||||
if (scissor_width <= 0) {
|
auto scissor_height = Settings::values.resolution_info.ScaleUp(framebuffer_texture.height);
|
||||||
scissor_width = viewport_width;
|
auto viewport_height = static_cast<GLfloat>(scissor_height);
|
||||||
}
|
|
||||||
auto viewport_height = info.height;
|
|
||||||
auto scissor_height = static_cast<u32>(crop.GetHeight());
|
|
||||||
if (scissor_height <= 0) {
|
|
||||||
scissor_height = viewport_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width);
|
|
||||||
scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width);
|
|
||||||
viewport_height = Settings::values.resolution_info.ScaleUp(viewport_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, viewport_width, viewport_height);
|
||||||
static_cast<GLfloat>(viewport_height));
|
|
||||||
|
|
||||||
glBindSampler(0, present_sampler.handle);
|
glBindSampler(0, present_sampler.handle);
|
||||||
GLint old_read_fb;
|
GLint old_read_fb;
|
||||||
|
@ -557,10 +547,8 @@ void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
|
||||||
fsr->InitBuffers();
|
fsr->InitBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(info.width);
|
|
||||||
const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(info.height);
|
|
||||||
glBindSampler(0, present_sampler.handle);
|
glBindSampler(0, present_sampler.handle);
|
||||||
fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop);
|
fsr->Draw(program_manager, layout.screen, info.scaled_width, info.scaled_height, crop);
|
||||||
} else {
|
} else {
|
||||||
if (fsr->AreBuffersInitialized()) {
|
if (fsr->AreBuffersInitialized()) {
|
||||||
fsr->ReleaseBuffers();
|
fsr->ReleaseBuffers();
|
||||||
|
|
|
@ -54,6 +54,8 @@ struct FramebufferTextureInfo {
|
||||||
GLuint display_texture{};
|
GLuint display_texture{};
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
|
u32 scaled_width;
|
||||||
|
u32 scaled_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RendererOpenGL final : public VideoCore::RendererBase {
|
class RendererOpenGL final : public VideoCore::RendererBase {
|
||||||
|
|
|
@ -152,6 +152,8 @@ void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConf
|
||||||
framebuffer, framebuffer.address + framebuffer.offset, framebuffer.stride);
|
framebuffer, framebuffer.address + framebuffer.offset, framebuffer.stride);
|
||||||
const u32 texture_width = texture_info ? texture_info->width : framebuffer.width;
|
const u32 texture_width = texture_info ? texture_info->width : framebuffer.width;
|
||||||
const u32 texture_height = texture_info ? texture_info->height : framebuffer.height;
|
const u32 texture_height = texture_info ? texture_info->height : framebuffer.height;
|
||||||
|
const u32 scaled_width = texture_info ? texture_info->scaled_width : texture_width;
|
||||||
|
const u32 scaled_height = texture_info ? texture_info->scaled_height : texture_height;
|
||||||
const bool use_accelerated = texture_info.has_value();
|
const bool use_accelerated = texture_info.has_value();
|
||||||
|
|
||||||
RefreshResources(framebuffer);
|
RefreshResources(framebuffer);
|
||||||
|
@ -363,8 +365,8 @@ void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConf
|
||||||
if (fsr) {
|
if (fsr) {
|
||||||
const auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height);
|
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(texture_width),
|
.width = scaled_width,
|
||||||
.height = Settings::values.resolution_info.ScaleUp(texture_height),
|
.height = scaled_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);
|
||||||
|
|
|
@ -47,6 +47,8 @@ struct FramebufferTextureInfo {
|
||||||
VkImageView image_view{};
|
VkImageView image_view{};
|
||||||
u32 width{};
|
u32 width{};
|
||||||
u32 height{};
|
u32 height{};
|
||||||
|
u32 scaled_width{};
|
||||||
|
u32 scaled_height{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlitScreen {
|
class BlitScreen {
|
||||||
|
|
|
@ -788,18 +788,22 @@ std::optional<FramebufferTextureInfo> RasterizerVulkan::AccelerateDisplay(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
std::scoped_lock lock{texture_cache.mutex};
|
std::scoped_lock lock{texture_cache.mutex};
|
||||||
ImageView* const image_view =
|
const auto [image_view, scaled] =
|
||||||
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
|
texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
|
||||||
if (!image_view) {
|
if (!image_view) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
query_cache.NotifySegment(false);
|
query_cache.NotifySegment(false);
|
||||||
|
|
||||||
|
const auto& resolution = Settings::values.resolution_info;
|
||||||
|
|
||||||
FramebufferTextureInfo info{};
|
FramebufferTextureInfo info{};
|
||||||
info.image = image_view->ImageHandle();
|
info.image = image_view->ImageHandle();
|
||||||
info.image_view = image_view->Handle(Shader::TextureType::Color2D);
|
info.image_view = image_view->Handle(Shader::TextureType::Color2D);
|
||||||
info.width = image_view->size.width;
|
info.width = image_view->size.width;
|
||||||
info.height = image_view->size.height;
|
info.height = image_view->size.height;
|
||||||
|
info.scaled_width = scaled ? resolution.ScaleUp(info.width) : info.width;
|
||||||
|
info.scaled_height = scaled ? resolution.ScaleUp(info.height) : info.height;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -713,12 +713,12 @@ bool TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(
|
std::pair<typename P::ImageView*, bool> TextureCache<P>::TryFindFramebufferImageView(
|
||||||
const Tegra::FramebufferConfig& config, DAddr cpu_addr) {
|
const Tegra::FramebufferConfig& config, DAddr cpu_addr) {
|
||||||
// TODO: Properly implement this
|
// TODO: Properly implement this
|
||||||
const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS);
|
const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS);
|
||||||
if (it == page_table.end()) {
|
if (it == page_table.end()) {
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
const auto& image_map_ids = it->second;
|
const auto& image_map_ids = it->second;
|
||||||
boost::container::small_vector<ImageId, 4> valid_image_ids;
|
boost::container::small_vector<ImageId, 4> valid_image_ids;
|
||||||
|
@ -747,7 +747,8 @@ typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(
|
||||||
|
|
||||||
const auto GetImageViewForFramebuffer = [&](ImageId image_id) {
|
const auto GetImageViewForFramebuffer = [&](ImageId image_id) {
|
||||||
const ImageViewInfo info{ImageViewType::e2D, view_format};
|
const ImageViewInfo info{ImageViewType::e2D, view_format};
|
||||||
return &slot_image_views[FindOrEmplaceImageView(image_id, info)];
|
return std::make_pair(&slot_image_views[FindOrEmplaceImageView(image_id, info)],
|
||||||
|
slot_images[image_id].IsRescaled());
|
||||||
};
|
};
|
||||||
|
|
||||||
if (valid_image_ids.size() == 1) [[likely]] {
|
if (valid_image_ids.size() == 1) [[likely]] {
|
||||||
|
@ -761,7 +762,7 @@ typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(
|
||||||
return GetImageViewForFramebuffer(*most_recent);
|
return GetImageViewForFramebuffer(*most_recent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
|
|
@ -212,8 +212,8 @@ public:
|
||||||
const Tegra::Engines::Fermi2D::Config& copy);
|
const Tegra::Engines::Fermi2D::Config& copy);
|
||||||
|
|
||||||
/// Try to find a cached image view in the given CPU address
|
/// Try to find a cached image view in the given CPU address
|
||||||
[[nodiscard]] ImageView* TryFindFramebufferImageView(const Tegra::FramebufferConfig& config,
|
[[nodiscard]] std::pair<ImageView*, bool> TryFindFramebufferImageView(
|
||||||
DAddr cpu_addr);
|
const Tegra::FramebufferConfig& config, DAddr cpu_addr);
|
||||||
|
|
||||||
/// Return true when there are uncommitted images to be downloaded
|
/// Return true when there are uncommitted images to be downloaded
|
||||||
[[nodiscard]] bool HasUncommittedFlushes() const noexcept;
|
[[nodiscard]] bool HasUncommittedFlushes() const noexcept;
|
||||||
|
|
Loading…
Reference in a new issue