Texture_Cache: Initial Implementation of Resolution Scaling

This commit is contained in:
Fernando Sahmkow
2019-07-06 15:13:26 -04:00
committed by FernandoS27
parent b9f21e44ad
commit e1a86c2abc
7 changed files with 168 additions and 21 deletions

View File

@@ -421,7 +421,6 @@ void RasterizerOpenGL::ConfigureFramebuffers() {
texture_cache.GuardRenderTargets(false); texture_cache.GuardRenderTargets(false);
state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(fbkey); state.draw.draw_framebuffer = framebuffer_cache.GetFramebuffer(fbkey);
SyncViewport(state);
} }
void RasterizerOpenGL::ConfigureClearFramebuffer(OpenGLState& current_state, bool using_color_fb, void RasterizerOpenGL::ConfigureClearFramebuffer(OpenGLState& current_state, bool using_color_fb,
@@ -547,9 +546,11 @@ void RasterizerOpenGL::Clear() {
ConfigureClearFramebuffer(clear_state, use_color, use_depth, use_stencil); ConfigureClearFramebuffer(clear_state, use_color, use_depth, use_stencil);
SyncViewport(clear_state); bool res_scaling = texture_cache.IsResolutionScalingEnabled();
SyncViewport(clear_state, res_scaling);
if (regs.clear_flags.scissor) { if (regs.clear_flags.scissor) {
SyncScissorTest(clear_state); SyncScissorTest(clear_state, res_scaling);
} }
if (regs.clear_flags.viewport) { if (regs.clear_flags.viewport) {
@@ -584,7 +585,6 @@ void RasterizerOpenGL::DrawPrelude() {
SyncLogicOpState(); SyncLogicOpState();
SyncCullMode(); SyncCullMode();
SyncPrimitiveRestart(); SyncPrimitiveRestart();
SyncScissorTest(state);
SyncTransformFeedback(); SyncTransformFeedback();
SyncPointState(); SyncPointState();
SyncPolygonOffset(); SyncPolygonOffset();
@@ -641,6 +641,10 @@ void RasterizerOpenGL::DrawPrelude() {
gpu.dirty.ResetVertexArrays(); gpu.dirty.ResetVertexArrays();
} }
bool res_scaling = texture_cache.IsResolutionScalingEnabled();
SyncViewport(state, res_scaling);
SyncScissorTest(state, res_scaling);
shader_program_manager->SetConstants(gpu); shader_program_manager->SetConstants(gpu);
shader_program_manager->ApplyTo(state); shader_program_manager->ApplyTo(state);
state.Apply(); state.Apply();
@@ -1063,20 +1067,21 @@ void RasterizerOpenGL::SetupImage(u32 binding, const Tegra::Texture::TICEntry& t
state.images[binding] = view->GetTexture(); state.images[binding] = view->GetTexture();
} }
void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { void RasterizerOpenGL::SyncViewport(OpenGLState& current_state, bool rescaling) {
const auto& regs = system.GPU().Maxwell3D().regs; const auto& regs = system.GPU().Maxwell3D().regs;
const bool geometry_shaders_enabled = const bool geometry_shaders_enabled =
regs.IsShaderConfigEnabled(static_cast<size_t>(Maxwell::ShaderProgram::Geometry)); regs.IsShaderConfigEnabled(static_cast<size_t>(Maxwell::ShaderProgram::Geometry));
const std::size_t viewport_count = const std::size_t viewport_count =
geometry_shaders_enabled ? Tegra::Engines::Maxwell3D::Regs::NumViewports : 1; geometry_shaders_enabled ? Tegra::Engines::Maxwell3D::Regs::NumViewports : 1;
float factor = rescaling ? Settings::values.resolution_factor : 1.0;
for (std::size_t i = 0; i < viewport_count; i++) { for (std::size_t i = 0; i < viewport_count; i++) {
auto& viewport = current_state.viewports[i]; auto& viewport = current_state.viewports[i];
const auto& src = regs.viewports[i]; const auto& src = regs.viewports[i];
const Common::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()}; const Common::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
viewport.x = viewport_rect.left; viewport.x = viewport_rect.left * factor;
viewport.y = viewport_rect.bottom; viewport.y = viewport_rect.bottom * factor;
viewport.width = viewport_rect.GetWidth(); viewport.width = viewport_rect.GetWidth() * factor;
viewport.height = viewport_rect.GetHeight(); viewport.height = viewport_rect.GetHeight() * factor;
viewport.depth_range_far = src.depth_range_far; viewport.depth_range_far = src.depth_range_far;
viewport.depth_range_near = src.depth_range_near; viewport.depth_range_near = src.depth_range_near;
} }
@@ -1287,12 +1292,13 @@ void RasterizerOpenGL::SyncLogicOpState() {
state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation); state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation);
} }
void RasterizerOpenGL::SyncScissorTest(OpenGLState& current_state) { void RasterizerOpenGL::SyncScissorTest(OpenGLState& current_state, bool rescaling) {
const auto& regs = system.GPU().Maxwell3D().regs; const auto& regs = system.GPU().Maxwell3D().regs;
const bool geometry_shaders_enabled = const bool geometry_shaders_enabled =
regs.IsShaderConfigEnabled(static_cast<size_t>(Maxwell::ShaderProgram::Geometry)); regs.IsShaderConfigEnabled(static_cast<size_t>(Maxwell::ShaderProgram::Geometry));
const std::size_t viewport_count = const std::size_t viewport_count =
geometry_shaders_enabled ? Tegra::Engines::Maxwell3D::Regs::NumViewports : 1; geometry_shaders_enabled ? Tegra::Engines::Maxwell3D::Regs::NumViewports : 1;
float factor = rescaling ? Settings::values.resolution_factor : 1.0;
for (std::size_t i = 0; i < viewport_count; i++) { for (std::size_t i = 0; i < viewport_count; i++) {
const auto& src = regs.scissor_test[i]; const auto& src = regs.scissor_test[i];
auto& dst = current_state.viewports[i].scissor; auto& dst = current_state.viewports[i].scissor;
@@ -1302,10 +1308,10 @@ void RasterizerOpenGL::SyncScissorTest(OpenGLState& current_state) {
} }
const u32 width = src.max_x - src.min_x; const u32 width = src.max_x - src.min_x;
const u32 height = src.max_y - src.min_y; const u32 height = src.max_y - src.min_y;
dst.x = src.min_x; dst.x = src.min_x * factor;
dst.y = src.min_y; dst.y = src.min_y * factor;
dst.width = width; dst.width = width * factor;
dst.height = height; dst.height = height * factor;
} }
} }

View File

@@ -128,7 +128,7 @@ private:
const GLShader::ImageEntry& entry); const GLShader::ImageEntry& entry);
/// Syncs the viewport and depth range to match the guest state /// Syncs the viewport and depth range to match the guest state
void SyncViewport(OpenGLState& current_state); void SyncViewport(OpenGLState& current_state, bool rescaling = false);
/// Syncs the clip enabled status to match the guest state /// Syncs the clip enabled status to match the guest state
void SyncClipEnabled( void SyncClipEnabled(
@@ -162,7 +162,7 @@ private:
void SyncMultiSampleState(); void SyncMultiSampleState();
/// Syncs the scissor test state to match the guest state /// Syncs the scissor test state to match the guest state
void SyncScissorTest(OpenGLState& current_state); void SyncScissorTest(OpenGLState& current_state, bool rescaling = false);
/// Syncs the transform feedback state to match the guest state /// Syncs the transform feedback state to match the guest state
void SyncTransformFeedback(); void SyncTransformFeedback();

View File

@@ -199,7 +199,7 @@ void ApplyTextureDefaults(const SurfaceParams& params, GLuint texture) {
} }
OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum internal_format, OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum internal_format,
OGLBuffer& texture_buffer) { OGLBuffer& texture_buffer, float resolution_factor) {
OGLTexture texture; OGLTexture texture;
texture.Create(target); texture.Create(target);
@@ -214,6 +214,9 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte
glTextureBuffer(texture.handle, internal_format, texture_buffer.handle); glTextureBuffer(texture.handle, internal_format, texture_buffer.handle);
break; break;
case SurfaceTarget::Texture2D: case SurfaceTarget::Texture2D:
glTextureStorage2D(texture.handle, params.emulated_levels, internal_format,
params.width * resolution_factor, params.height * resolution_factor);
break;
case SurfaceTarget::TextureCubemap: case SurfaceTarget::TextureCubemap:
glTextureStorage2D(texture.handle, params.emulated_levels, internal_format, params.width, glTextureStorage2D(texture.handle, params.emulated_levels, internal_format, params.width,
params.height); params.height);
@@ -242,8 +245,12 @@ CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& param
format = tuple.format; format = tuple.format;
type = tuple.type; type = tuple.type;
is_compressed = tuple.compressed; is_compressed = tuple.compressed;
}
void CachedSurface::Init() {
target = GetTextureTarget(params.target); target = GetTextureTarget(params.target);
texture = CreateTexture(params, target, internal_format, texture_buffer); float resolution_factor = IsRescaled() ? Settings::values.resolution_factor : 1.0;
texture = CreateTexture(params, target, internal_format, texture_buffer, resolution_factor);
DecorateSurfaceName(); DecorateSurfaceName();
main_view = CreateViewInner( main_view = CreateViewInner(
ViewParams(params.target, 0, params.is_layered ? params.depth : 1, 0, params.num_levels), ViewParams(params.target, 0, params.is_layered ? params.depth : 1, 0, params.num_levels),
@@ -325,6 +332,7 @@ void CachedSurface::UploadTextureMipmap(u32 level, const std::vector<u8>& stagin
UNREACHABLE(); UNREACHABLE();
} }
} else { } else {
float resolution_factor = IsRescaled() ? Settings::values.resolution_factor : 1.0;
switch (params.target) { switch (params.target) {
case SurfaceTarget::Texture1D: case SurfaceTarget::Texture1D:
glTextureSubImage1D(texture.handle, level, 0, params.GetMipWidth(level), format, type, glTextureSubImage1D(texture.handle, level, 0, params.GetMipWidth(level), format, type,
@@ -337,8 +345,9 @@ void CachedSurface::UploadTextureMipmap(u32 level, const std::vector<u8>& stagin
break; break;
case SurfaceTarget::Texture1DArray: case SurfaceTarget::Texture1DArray:
case SurfaceTarget::Texture2D: case SurfaceTarget::Texture2D:
glTextureSubImage2D(texture.handle, level, 0, 0, params.GetMipWidth(level), glTextureSubImage2D(
params.GetMipHeight(level), format, type, buffer); texture.handle, level, 0, 0, params.GetMipWidth(level) * resolution_factor,
params.GetMipHeight(level) * resolution_factor, format, type, buffer);
break; break;
case SurfaceTarget::Texture3D: case SurfaceTarget::Texture3D:
case SurfaceTarget::Texture2DArray: case SurfaceTarget::Texture2DArray:
@@ -461,7 +470,10 @@ TextureCacheOpenGL::TextureCacheOpenGL(Core::System& system,
TextureCacheOpenGL::~TextureCacheOpenGL() = default; TextureCacheOpenGL::~TextureCacheOpenGL() = default;
Surface TextureCacheOpenGL::CreateSurface(GPUVAddr gpu_addr, const SurfaceParams& params) { Surface TextureCacheOpenGL::CreateSurface(GPUVAddr gpu_addr, const SurfaceParams& params) {
return std::make_shared<CachedSurface>(gpu_addr, params); Surface new_surface = std::make_shared<CachedSurface>(gpu_addr, params);
SignalCreatedSurface(new_surface);
new_surface->Init();
return new_surface;
} }
void TextureCacheOpenGL::ImageCopy(Surface& src_surface, Surface& dst_surface, void TextureCacheOpenGL::ImageCopy(Surface& src_surface, Surface& dst_surface,

View File

@@ -39,6 +39,8 @@ public:
explicit CachedSurface(GPUVAddr gpu_addr, const SurfaceParams& params); explicit CachedSurface(GPUVAddr gpu_addr, const SurfaceParams& params);
~CachedSurface(); ~CachedSurface();
void Init();
void UploadTexture(const std::vector<u8>& staging_buffer) override; void UploadTexture(const std::vector<u8>& staging_buffer) override;
void DownloadTexture(std::vector<u8>& staging_buffer) override; void DownloadTexture(std::vector<u8>& staging_buffer) override;

View File

@@ -0,0 +1,68 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <unordered_set>
#include "video_core/surface.h"
namespace VideoCommon::Resolution {
using VideoCore::Surface::PixelFormat;
struct ResolutionKey {
PixelFormat format;
u32 width;
u32 height;
std::size_t Hash() const {
const std::size_t comp1 = static_cast<std::size_t>(format) << 44;
const std::size_t comp2 = static_cast<std::size_t>(height) << 24;
const std::size_t comp3 = static_cast<std::size_t>(width);
return comp1 | comp2 | comp3;
}
bool operator==(const ResolutionKey& ks) const {
return std::tie(format, width, height) == std::tie(ks.format, ks.width, ks.height);
}
};
} // namespace VideoCommon::Resolution
namespace std {
template <>
struct hash<VideoCommon::Resolution::ResolutionKey> {
std::size_t operator()(const VideoCommon::Resolution::ResolutionKey& k) const {
return k.Hash();
}
};
} // namespace std
namespace VideoCommon::Resolution {
class ScalingDatabase {
public:
explicit ScalingDatabase() : database{} {}
bool IsInDatabase(const PixelFormat format, const u32 width, const u32 height) {
ResolutionKey key{format, width, height};
return database.count(key) > 0;
}
void Register(const PixelFormat format, const u32 width, const u32 height) {
ResolutionKey key{format, width, height};
database.insert(key);
}
void Unregister(const PixelFormat format, const u32 width, const u32 height) {
ResolutionKey key{format, width, height};
database.erase(key);
}
private:
std::unordered_set<ResolutionKey> database;
};
} // namespace VideoCommon::Resolution

View File

@@ -205,6 +205,10 @@ public:
index = index_; index = index_;
} }
void MarkAsRescaled(const bool is_rescaled) {
this->is_rescaled = is_rescaled;
}
void MarkAsPicked(bool is_picked_) { void MarkAsPicked(bool is_picked_) {
is_picked = is_picked_; is_picked = is_picked_;
} }
@@ -226,6 +230,10 @@ public:
return index; return index;
} }
bool IsRescaled() const {
return is_rescaled;
}
bool IsRegistered() const { bool IsRegistered() const {
return is_registered; return is_registered;
} }
@@ -318,6 +326,7 @@ private:
bool is_target{}; bool is_target{};
bool is_registered{}; bool is_registered{};
bool is_picked{}; bool is_picked{};
bool is_rescaled{};
u32 index{NO_RT}; u32 index{NO_RT};
u64 modification_tick{}; u64 modification_tick{};
}; };

View File

@@ -29,6 +29,7 @@
#include "video_core/rasterizer_interface.h" #include "video_core/rasterizer_interface.h"
#include "video_core/surface.h" #include "video_core/surface.h"
#include "video_core/texture_cache/copy_params.h" #include "video_core/texture_cache/copy_params.h"
#include "video_core/texture_cache/resolution_scaling/database.h"
#include "video_core/texture_cache/surface_base.h" #include "video_core/texture_cache/surface_base.h"
#include "video_core/texture_cache/surface_params.h" #include "video_core/texture_cache/surface_params.h"
#include "video_core/texture_cache/surface_view.h" #include "video_core/texture_cache/surface_view.h"
@@ -254,6 +255,39 @@ public:
return ++ticks; return ++ticks;
} }
bool IsResolutionScalingEnabled() const {
if (!EnabledRescaling()) {
return false;
}
u32 enabled_targets = 0;
u32 rescaled_targets = 0;
bool rescaling = false;
for (const auto& target : render_targets) {
if (target.target) {
enabled_targets++;
if (target.target->IsRescaled()) {
rescaling = true;
rescaled_targets++;
}
}
}
if (depth_buffer.target) {
enabled_targets++;
if (depth_buffer.target->IsRescaled()) {
rescaling = true;
rescaled_targets++;
}
}
if (rescaling) {
if (rescaled_targets != enabled_targets) {
LOG_CRITICAL(HW_GPU, "Rescaling Database is incorrectly set! Redo the database.");
return false;
}
return true;
}
return false;
}
protected: protected:
TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer) TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
: system{system}, rasterizer{rasterizer} { : system{system}, rasterizer{rasterizer} {
@@ -353,6 +387,16 @@ protected:
return GetSurface(gpu_addr, params, true, false); return GetSurface(gpu_addr, params, true, false);
} }
// Must be called by child's create surface
void SignalCreatedSurface(TSurface& new_surface) {
const auto& params = new_surface->GetSurfaceParams();
if (guard_render_targets && EnabledRescaling()) {
if (scaling_database.IsInDatabase(params.pixel_format, params.width, params.height)) {
new_surface->MarkAsRescaled(true);
}
}
}
Core::System& system; Core::System& system;
private: private:
@@ -924,6 +968,10 @@ private:
return {}; return {};
} }
bool EnabledRescaling() const {
return Settings::values.resolution_factor != 1.0; //|| Settings::values.res_scanning
}
constexpr PixelFormat GetSiblingFormat(PixelFormat format) const { constexpr PixelFormat GetSiblingFormat(PixelFormat format) const {
return siblings_table[static_cast<std::size_t>(format)]; return siblings_table[static_cast<std::size_t>(format)];
} }
@@ -972,6 +1020,8 @@ private:
StagingCache staging_cache; StagingCache staging_cache;
std::recursive_mutex mutex; std::recursive_mutex mutex;
Resolution::ScalingDatabase scaling_database;
}; };
} // namespace VideoCommon } // namespace VideoCommon