renderer_gl: Resolution scaling fixes
This commit is contained in:
parent
8704c93913
commit
de66a69ed4
|
@ -577,6 +577,14 @@ void RasterizerOpenGL::SyncViewport() {
|
||||||
const bool force = flags[Dirty::ViewportTransform];
|
const bool force = flags[Dirty::ViewportTransform];
|
||||||
flags[Dirty::ViewportTransform] = false;
|
flags[Dirty::ViewportTransform] = false;
|
||||||
|
|
||||||
|
const auto& resolution = Settings::values.resolution_info;
|
||||||
|
const auto scale_up = [&](u32 value) -> u32 {
|
||||||
|
if (value == 0) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
const u32 converted_value = (value * resolution.up_scale) >> resolution.down_shift;
|
||||||
|
return std::max<u32>(converted_value, 1U);
|
||||||
|
};
|
||||||
for (std::size_t i = 0; i < Maxwell::NumViewports; ++i) {
|
for (std::size_t i = 0; i < Maxwell::NumViewports; ++i) {
|
||||||
if (!force && !flags[Dirty::Viewport0 + i]) {
|
if (!force && !flags[Dirty::Viewport0 + i]) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -585,8 +593,8 @@ void RasterizerOpenGL::SyncViewport() {
|
||||||
|
|
||||||
const auto& src = regs.viewport_transform[i];
|
const auto& src = regs.viewport_transform[i];
|
||||||
const Common::Rectangle<f32> rect{src.GetRect()};
|
const Common::Rectangle<f32> rect{src.GetRect()};
|
||||||
glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, rect.GetWidth(),
|
glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom,
|
||||||
rect.GetHeight());
|
scale_up(rect.GetWidth()), scale_up(rect.GetHeight()));
|
||||||
|
|
||||||
const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
|
const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
|
||||||
const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z;
|
const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z;
|
||||||
|
@ -909,6 +917,15 @@ void RasterizerOpenGL::SyncScissorTest() {
|
||||||
flags[Dirty::Scissors] = false;
|
flags[Dirty::Scissors] = false;
|
||||||
|
|
||||||
const auto& regs = maxwell3d.regs;
|
const auto& regs = maxwell3d.regs;
|
||||||
|
|
||||||
|
const auto& resolution = Settings::values.resolution_info;
|
||||||
|
const auto scale_up = [&](u32 value) -> u32 {
|
||||||
|
if (value == 0) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
const u32 converted_value = (value * resolution.up_scale) >> resolution.down_shift;
|
||||||
|
return std::max<u32>(converted_value, 1U);
|
||||||
|
};
|
||||||
for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) {
|
for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) {
|
||||||
if (!flags[Dirty::Scissor0 + index]) {
|
if (!flags[Dirty::Scissor0 + index]) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -919,7 +936,7 @@ void RasterizerOpenGL::SyncScissorTest() {
|
||||||
if (src.enable) {
|
if (src.enable) {
|
||||||
glEnablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
|
glEnablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
|
||||||
glScissorIndexed(static_cast<GLuint>(index), src.min_x, src.min_y,
|
glScissorIndexed(static_cast<GLuint>(index), src.min_x, src.min_y,
|
||||||
src.max_x - src.min_x, src.max_y - src.min_y);
|
scale_up(src.max_x - src.min_x), scale_up(src.max_y - src.min_y));
|
||||||
} else {
|
} else {
|
||||||
glDisablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
|
glDisablei(GL_SCISSOR_TEST, static_cast<GLuint>(index));
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,6 +316,52 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_format) {
|
||||||
|
const GLenum target = ImageTarget(info);
|
||||||
|
const GLsizei width = info.size.width;
|
||||||
|
const GLsizei height = info.size.height;
|
||||||
|
const GLsizei depth = info.size.depth;
|
||||||
|
const int max_host_mip_levels = std::bit_width(info.size.width);
|
||||||
|
const GLsizei num_levels = std::min(info.resources.levels, max_host_mip_levels);
|
||||||
|
const GLsizei num_layers = info.resources.layers;
|
||||||
|
const GLsizei num_samples = info.num_samples;
|
||||||
|
|
||||||
|
GLuint handle = 0;
|
||||||
|
OGLTexture texture;
|
||||||
|
if (target != GL_TEXTURE_BUFFER) {
|
||||||
|
texture.Create(target);
|
||||||
|
handle = texture.handle;
|
||||||
|
}
|
||||||
|
switch (target) {
|
||||||
|
case GL_TEXTURE_1D_ARRAY:
|
||||||
|
glTextureStorage2D(handle, num_levels, gl_internal_format, width, num_layers);
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_2D_ARRAY:
|
||||||
|
glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, num_layers);
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
|
||||||
|
// TODO: Where should 'fixedsamplelocations' come from?
|
||||||
|
const auto [samples_x, samples_y] = SamplesLog2(info.num_samples);
|
||||||
|
glTextureStorage3DMultisample(handle, num_samples, gl_internal_format, width >> samples_x,
|
||||||
|
height >> samples_y, num_layers, GL_FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GL_TEXTURE_RECTANGLE:
|
||||||
|
glTextureStorage2D(handle, num_levels, gl_internal_format, width, height);
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_3D:
|
||||||
|
glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, depth);
|
||||||
|
break;
|
||||||
|
case GL_TEXTURE_BUFFER:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE_MSG("Invalid target=0x{:x}", target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsPixelFormatBGR(PixelFormat format) {
|
[[nodiscard]] bool IsPixelFormatBGR(PixelFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case PixelFormat::B5G6R5_UNORM:
|
case PixelFormat::B5G6R5_UNORM:
|
||||||
|
@ -430,6 +476,11 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager&
|
||||||
|
|
||||||
TextureCacheRuntime::~TextureCacheRuntime() = default;
|
TextureCacheRuntime::~TextureCacheRuntime() = default;
|
||||||
|
|
||||||
|
void TextureCacheRuntime::Init() {
|
||||||
|
resolution = Settings::values.resolution_info;
|
||||||
|
is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void TextureCacheRuntime::Finish() {
|
void TextureCacheRuntime::Finish() {
|
||||||
glFinish();
|
glFinish();
|
||||||
}
|
}
|
||||||
|
@ -605,13 +656,13 @@ std::optional<size_t> TextureCacheRuntime::StagingBuffers::FindBuffer(size_t req
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Image(TextureCacheRuntime& runtime, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_,
|
Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_,
|
||||||
VAddr cpu_addr_)
|
VAddr cpu_addr_)
|
||||||
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_) {
|
: VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), runtime{&runtime_} {
|
||||||
if (CanBeAccelerated(runtime, info)) {
|
if (CanBeAccelerated(*runtime, info)) {
|
||||||
flags |= ImageFlagBits::AcceleratedUpload;
|
flags |= ImageFlagBits::AcceleratedUpload;
|
||||||
}
|
}
|
||||||
if (IsConverted(runtime.device, info.format, info.type)) {
|
if (IsConverted(runtime->device, info.format, info.type)) {
|
||||||
flags |= ImageFlagBits::Converted;
|
flags |= ImageFlagBits::Converted;
|
||||||
gl_internal_format = IsPixelFormatSRGB(info.format) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
gl_internal_format = IsPixelFormatSRGB(info.format) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||||
gl_format = GL_RGBA;
|
gl_format = GL_RGBA;
|
||||||
|
@ -622,51 +673,11 @@ Image::Image(TextureCacheRuntime& runtime, const VideoCommon::ImageInfo& info_,
|
||||||
gl_format = tuple.format;
|
gl_format = tuple.format;
|
||||||
gl_type = tuple.type;
|
gl_type = tuple.type;
|
||||||
}
|
}
|
||||||
const GLenum target = ImageTarget(info);
|
texture = MakeImage(info, gl_internal_format);
|
||||||
const GLsizei width = info.size.width;
|
if (runtime->device.HasDebuggingToolAttached()) {
|
||||||
const GLsizei height = info.size.height;
|
|
||||||
const GLsizei depth = info.size.depth;
|
|
||||||
const int max_host_mip_levels = std::bit_width(info.size.width);
|
|
||||||
const GLsizei num_levels = std::min(info.resources.levels, max_host_mip_levels);
|
|
||||||
const GLsizei num_layers = info.resources.layers;
|
|
||||||
const GLsizei num_samples = info.num_samples;
|
|
||||||
|
|
||||||
GLuint handle = 0;
|
|
||||||
if (target != GL_TEXTURE_BUFFER) {
|
|
||||||
texture.Create(target);
|
|
||||||
handle = texture.handle;
|
|
||||||
}
|
|
||||||
switch (target) {
|
|
||||||
case GL_TEXTURE_1D_ARRAY:
|
|
||||||
glTextureStorage2D(handle, num_levels, gl_internal_format, width, num_layers);
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_2D_ARRAY:
|
|
||||||
glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, num_layers);
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
|
|
||||||
// TODO: Where should 'fixedsamplelocations' come from?
|
|
||||||
const auto [samples_x, samples_y] = SamplesLog2(info.num_samples);
|
|
||||||
glTextureStorage3DMultisample(handle, num_samples, gl_internal_format, width >> samples_x,
|
|
||||||
height >> samples_y, num_layers, GL_FALSE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GL_TEXTURE_RECTANGLE:
|
|
||||||
glTextureStorage2D(handle, num_levels, gl_internal_format, width, height);
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_3D:
|
|
||||||
glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, depth);
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_BUFFER:
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE_MSG("Invalid target=0x{:x}", target);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (runtime.device.HasDebuggingToolAttached()) {
|
|
||||||
const std::string name = VideoCommon::Name(*this);
|
const std::string name = VideoCommon::Name(*this);
|
||||||
glObjectLabel(target == GL_TEXTURE_BUFFER ? GL_BUFFER : GL_TEXTURE, handle,
|
glObjectLabel(ImageTarget(info) == GL_TEXTURE_BUFFER ? GL_BUFFER : GL_TEXTURE,
|
||||||
static_cast<GLsizei>(name.size()), name.data());
|
texture.handle, static_cast<GLsizei>(name.size()), name.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,7 +866,7 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Scale() {
|
void Image::Scale(u32 up, u32 down) {
|
||||||
// TODO: Pass scaling factor?
|
// TODO: Pass scaling factor?
|
||||||
if (gl_format == 0 || gl_type == 0) {
|
if (gl_format == 0 || gl_type == 0) {
|
||||||
// compressed textures
|
// compressed textures
|
||||||
|
@ -902,12 +913,22 @@ void Image::Scale() {
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_handle);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_handle);
|
||||||
glNamedFramebufferTexture(fbo_handle, attachment, texture.handle, 0);
|
glNamedFramebufferTexture(fbo_handle, attachment, texture.handle, 0);
|
||||||
|
|
||||||
const size_t scaled_width = info.size.width;
|
const auto scale_up = [&](u32 value) { return std::max<u32>((value * up) >> down, 1U); };
|
||||||
const size_t scaled_height = info.size.height * 2;
|
const u32 scaled_width = scale_up(info.size.width);
|
||||||
glBlitNamedFramebuffer(fbo_handle, fbo_handle, 0, 0, info.size.width, info.size.height, 0, 0,
|
const u32 scaled_height = scale_up(info.size.height);
|
||||||
|
const u32 original_width = info.size.width;
|
||||||
|
const u32 original_height = info.size.height;
|
||||||
|
|
||||||
|
auto scaled_info = info;
|
||||||
|
scaled_info.size.width = scaled_width;
|
||||||
|
scaled_info.size.height = scaled_height;
|
||||||
|
auto scaled_texture = MakeImage(scaled_info, gl_internal_format);
|
||||||
|
|
||||||
|
glBlitNamedFramebuffer(fbo_handle, fbo_handle, 0, 0, original_width, original_height, 0, 0,
|
||||||
scaled_width, scaled_height, mask, filter);
|
scaled_width, scaled_height, mask, filter);
|
||||||
// TODO: resize texture?
|
glCopyTextureSubImage3D(scaled_texture.handle, 0, 0, 0, 0, 0, 0, scaled_width, scaled_height);
|
||||||
glCopyTextureSubImage3D(texture.handle, 0, 0, 0, 0, 0, 0, scaled_width, scaled_height / 2);
|
texture = std::move(scaled_texture);
|
||||||
|
|
||||||
// Restore previous framebuffers
|
// Restore previous framebuffers
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prev_draw_fbo);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prev_draw_fbo);
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, prev_read_fbo);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, prev_read_fbo);
|
||||||
|
@ -918,7 +939,8 @@ bool Image::ScaleUp() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
flags |= ImageFlagBits::Rescaled;
|
flags |= ImageFlagBits::Rescaled;
|
||||||
//Scale();
|
const auto& resolution = runtime->resolution;
|
||||||
|
Scale(resolution.up_scale, resolution.down_shift);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -927,6 +949,8 @@ bool Image::ScaleDown() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
flags &= ~ImageFlagBits::Rescaled;
|
flags &= ~ImageFlagBits::Rescaled;
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
// const auto& resolution = runtime->resolution;
|
||||||
// Scale();
|
// Scale();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include "common/settings.h"
|
||||||
#include "shader_recompiler/shader_info.h"
|
#include "shader_recompiler/shader_info.h"
|
||||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
#include "video_core/renderer_opengl/util_shaders.h"
|
#include "video_core/renderer_opengl/util_shaders.h"
|
||||||
|
@ -72,7 +73,7 @@ public:
|
||||||
StateTracker& state_tracker);
|
StateTracker& state_tracker);
|
||||||
~TextureCacheRuntime();
|
~TextureCacheRuntime();
|
||||||
|
|
||||||
void Init() {}
|
void Init();
|
||||||
|
|
||||||
void Finish();
|
void Finish();
|
||||||
|
|
||||||
|
@ -153,6 +154,9 @@ private:
|
||||||
OGLTextureView null_image_view_cube;
|
OGLTextureView null_image_view_cube;
|
||||||
|
|
||||||
std::array<GLuint, Shader::NUM_TEXTURE_TYPES> null_image_views{};
|
std::array<GLuint, Shader::NUM_TEXTURE_TYPES> null_image_views{};
|
||||||
|
|
||||||
|
Settings::ResolutionScalingInfo resolution;
|
||||||
|
bool is_rescaling_on{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class Image : public VideoCommon::ImageBase {
|
class Image : public VideoCommon::ImageBase {
|
||||||
|
@ -198,13 +202,14 @@ private:
|
||||||
|
|
||||||
void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset);
|
void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset);
|
||||||
|
|
||||||
void Scale();
|
void Scale(u32 up, u32 down);
|
||||||
|
|
||||||
OGLTexture texture;
|
OGLTexture texture;
|
||||||
OGLTextureView store_view;
|
OGLTextureView store_view;
|
||||||
GLenum gl_internal_format = GL_NONE;
|
GLenum gl_internal_format = GL_NONE;
|
||||||
GLenum gl_format = GL_NONE;
|
GLenum gl_format = GL_NONE;
|
||||||
GLenum gl_type = GL_NONE;
|
GLenum gl_type = GL_NONE;
|
||||||
|
TextureCacheRuntime* runtime;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ImageView : public VideoCommon::ImageViewBase {
|
class ImageView : public VideoCommon::ImageViewBase {
|
||||||
|
|
Loading…
Reference in New Issue