diff options
| author | 2021-07-21 00:02:35 -0400 | |
|---|---|---|
| committer | 2021-11-16 22:11:27 +0100 | |
| commit | de66a69ed4b556ad96f38570ea0a31cb2a1870f1 (patch) | |
| tree | 1ccad15e5a9a202494a72fdf6edf2b0abb6fa2b5 | |
| parent | TextureCache: Fix rescaling of ImageCopies (diff) | |
| download | yuzu-de66a69ed4b556ad96f38570ea0a31cb2a1870f1.tar.gz yuzu-de66a69ed4b556ad96f38570ea0a31cb2a1870f1.tar.xz yuzu-de66a69ed4b556ad96f38570ea0a31cb2a1870f1.zip | |
renderer_gl: Resolution scaling fixes
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 23 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 136 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 9 |
3 files changed, 107 insertions, 61 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a6d9f7c43..b91e7edf8 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -577,6 +577,14 @@ void RasterizerOpenGL::SyncViewport() { | |||
| 577 | const bool force = flags[Dirty::ViewportTransform]; | 577 | const bool force = flags[Dirty::ViewportTransform]; |
| 578 | flags[Dirty::ViewportTransform] = false; | 578 | flags[Dirty::ViewportTransform] = false; |
| 579 | 579 | ||
| 580 | const auto& resolution = Settings::values.resolution_info; | ||
| 581 | const auto scale_up = [&](u32 value) -> u32 { | ||
| 582 | if (value == 0) { | ||
| 583 | return 0U; | ||
| 584 | } | ||
| 585 | const u32 converted_value = (value * resolution.up_scale) >> resolution.down_shift; | ||
| 586 | return std::max<u32>(converted_value, 1U); | ||
| 587 | }; | ||
| 580 | for (std::size_t i = 0; i < Maxwell::NumViewports; ++i) { | 588 | for (std::size_t i = 0; i < Maxwell::NumViewports; ++i) { |
| 581 | if (!force && !flags[Dirty::Viewport0 + i]) { | 589 | if (!force && !flags[Dirty::Viewport0 + i]) { |
| 582 | continue; | 590 | continue; |
| @@ -585,8 +593,8 @@ void RasterizerOpenGL::SyncViewport() { | |||
| 585 | 593 | ||
| 586 | const auto& src = regs.viewport_transform[i]; | 594 | const auto& src = regs.viewport_transform[i]; |
| 587 | const Common::Rectangle<f32> rect{src.GetRect()}; | 595 | const Common::Rectangle<f32> rect{src.GetRect()}; |
| 588 | glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, rect.GetWidth(), | 596 | glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, |
| 589 | rect.GetHeight()); | 597 | scale_up(rect.GetWidth()), scale_up(rect.GetHeight())); |
| 590 | 598 | ||
| 591 | const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; | 599 | const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; |
| 592 | const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z; | 600 | const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z; |
| @@ -909,6 +917,15 @@ void RasterizerOpenGL::SyncScissorTest() { | |||
| 909 | flags[Dirty::Scissors] = false; | 917 | flags[Dirty::Scissors] = false; |
| 910 | 918 | ||
| 911 | const auto& regs = maxwell3d.regs; | 919 | const auto& regs = maxwell3d.regs; |
| 920 | |||
| 921 | const auto& resolution = Settings::values.resolution_info; | ||
| 922 | const auto scale_up = [&](u32 value) -> u32 { | ||
| 923 | if (value == 0) { | ||
| 924 | return 0U; | ||
| 925 | } | ||
| 926 | const u32 converted_value = (value * resolution.up_scale) >> resolution.down_shift; | ||
| 927 | return std::max<u32>(converted_value, 1U); | ||
| 928 | }; | ||
| 912 | for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) { | 929 | for (std::size_t index = 0; index < Maxwell::NumViewports; ++index) { |
| 913 | if (!flags[Dirty::Scissor0 + index]) { | 930 | if (!flags[Dirty::Scissor0 + index]) { |
| 914 | continue; | 931 | continue; |
| @@ -919,7 +936,7 @@ void RasterizerOpenGL::SyncScissorTest() { | |||
| 919 | if (src.enable) { | 936 | if (src.enable) { |
| 920 | glEnablei(GL_SCISSOR_TEST, static_cast<GLuint>(index)); | 937 | glEnablei(GL_SCISSOR_TEST, static_cast<GLuint>(index)); |
| 921 | glScissorIndexed(static_cast<GLuint>(index), src.min_x, src.min_y, | 938 | glScissorIndexed(static_cast<GLuint>(index), src.min_x, src.min_y, |
| 922 | src.max_x - src.min_x, src.max_y - src.min_y); | 939 | scale_up(src.max_x - src.min_x), scale_up(src.max_y - src.min_y)); |
| 923 | } else { | 940 | } else { |
| 924 | glDisablei(GL_SCISSOR_TEST, static_cast<GLuint>(index)); | 941 | glDisablei(GL_SCISSOR_TEST, static_cast<GLuint>(index)); |
| 925 | } | 942 | } |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 2d9f770cd..ecde5b600 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -316,6 +316,52 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) { | |||
| 316 | } | 316 | } |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_format) { | ||
| 320 | const GLenum target = ImageTarget(info); | ||
| 321 | const GLsizei width = info.size.width; | ||
| 322 | const GLsizei height = info.size.height; | ||
| 323 | const GLsizei depth = info.size.depth; | ||
| 324 | const int max_host_mip_levels = std::bit_width(info.size.width); | ||
| 325 | const GLsizei num_levels = std::min(info.resources.levels, max_host_mip_levels); | ||
| 326 | const GLsizei num_layers = info.resources.layers; | ||
| 327 | const GLsizei num_samples = info.num_samples; | ||
| 328 | |||
| 329 | GLuint handle = 0; | ||
| 330 | OGLTexture texture; | ||
| 331 | if (target != GL_TEXTURE_BUFFER) { | ||
| 332 | texture.Create(target); | ||
| 333 | handle = texture.handle; | ||
| 334 | } | ||
| 335 | switch (target) { | ||
| 336 | case GL_TEXTURE_1D_ARRAY: | ||
| 337 | glTextureStorage2D(handle, num_levels, gl_internal_format, width, num_layers); | ||
| 338 | break; | ||
| 339 | case GL_TEXTURE_2D_ARRAY: | ||
| 340 | glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, num_layers); | ||
| 341 | break; | ||
| 342 | case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { | ||
| 343 | // TODO: Where should 'fixedsamplelocations' come from? | ||
| 344 | const auto [samples_x, samples_y] = SamplesLog2(info.num_samples); | ||
| 345 | glTextureStorage3DMultisample(handle, num_samples, gl_internal_format, width >> samples_x, | ||
| 346 | height >> samples_y, num_layers, GL_FALSE); | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | case GL_TEXTURE_RECTANGLE: | ||
| 350 | glTextureStorage2D(handle, num_levels, gl_internal_format, width, height); | ||
| 351 | break; | ||
| 352 | case GL_TEXTURE_3D: | ||
| 353 | glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, depth); | ||
| 354 | break; | ||
| 355 | case GL_TEXTURE_BUFFER: | ||
| 356 | UNREACHABLE(); | ||
| 357 | break; | ||
| 358 | default: | ||
| 359 | UNREACHABLE_MSG("Invalid target=0x{:x}", target); | ||
| 360 | break; | ||
| 361 | } | ||
| 362 | return texture; | ||
| 363 | } | ||
| 364 | |||
| 319 | [[nodiscard]] bool IsPixelFormatBGR(PixelFormat format) { | 365 | [[nodiscard]] bool IsPixelFormatBGR(PixelFormat format) { |
| 320 | switch (format) { | 366 | switch (format) { |
| 321 | case PixelFormat::B5G6R5_UNORM: | 367 | case PixelFormat::B5G6R5_UNORM: |
| @@ -430,6 +476,11 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, ProgramManager& | |||
| 430 | 476 | ||
| 431 | TextureCacheRuntime::~TextureCacheRuntime() = default; | 477 | TextureCacheRuntime::~TextureCacheRuntime() = default; |
| 432 | 478 | ||
| 479 | void TextureCacheRuntime::Init() { | ||
| 480 | resolution = Settings::values.resolution_info; | ||
| 481 | is_rescaling_on = resolution.up_scale != 1 || resolution.down_shift != 0; | ||
| 482 | } | ||
| 483 | |||
| 433 | void TextureCacheRuntime::Finish() { | 484 | void TextureCacheRuntime::Finish() { |
| 434 | glFinish(); | 485 | glFinish(); |
| 435 | } | 486 | } |
| @@ -605,13 +656,13 @@ std::optional<size_t> TextureCacheRuntime::StagingBuffers::FindBuffer(size_t req | |||
| 605 | return found; | 656 | return found; |
| 606 | } | 657 | } |
| 607 | 658 | ||
| 608 | Image::Image(TextureCacheRuntime& runtime, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_, | 659 | Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, GPUVAddr gpu_addr_, |
| 609 | VAddr cpu_addr_) | 660 | VAddr cpu_addr_) |
| 610 | : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_) { | 661 | : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), runtime{&runtime_} { |
| 611 | if (CanBeAccelerated(runtime, info)) { | 662 | if (CanBeAccelerated(*runtime, info)) { |
| 612 | flags |= ImageFlagBits::AcceleratedUpload; | 663 | flags |= ImageFlagBits::AcceleratedUpload; |
| 613 | } | 664 | } |
| 614 | if (IsConverted(runtime.device, info.format, info.type)) { | 665 | if (IsConverted(runtime->device, info.format, info.type)) { |
| 615 | flags |= ImageFlagBits::Converted; | 666 | flags |= ImageFlagBits::Converted; |
| 616 | gl_internal_format = IsPixelFormatSRGB(info.format) ? GL_SRGB8_ALPHA8 : GL_RGBA8; | 667 | gl_internal_format = IsPixelFormatSRGB(info.format) ? GL_SRGB8_ALPHA8 : GL_RGBA8; |
| 617 | gl_format = GL_RGBA; | 668 | gl_format = GL_RGBA; |
| @@ -622,51 +673,11 @@ Image::Image(TextureCacheRuntime& runtime, const VideoCommon::ImageInfo& info_, | |||
| 622 | gl_format = tuple.format; | 673 | gl_format = tuple.format; |
| 623 | gl_type = tuple.type; | 674 | gl_type = tuple.type; |
| 624 | } | 675 | } |
| 625 | const GLenum target = ImageTarget(info); | 676 | texture = MakeImage(info, gl_internal_format); |
| 626 | const GLsizei width = info.size.width; | 677 | if (runtime->device.HasDebuggingToolAttached()) { |
| 627 | const GLsizei height = info.size.height; | ||
| 628 | const GLsizei depth = info.size.depth; | ||
| 629 | const int max_host_mip_levels = std::bit_width(info.size.width); | ||
| 630 | const GLsizei num_levels = std::min(info.resources.levels, max_host_mip_levels); | ||
| 631 | const GLsizei num_layers = info.resources.layers; | ||
| 632 | const GLsizei num_samples = info.num_samples; | ||
| 633 | |||
| 634 | GLuint handle = 0; | ||
| 635 | if (target != GL_TEXTURE_BUFFER) { | ||
| 636 | texture.Create(target); | ||
| 637 | handle = texture.handle; | ||
| 638 | } | ||
| 639 | switch (target) { | ||
| 640 | case GL_TEXTURE_1D_ARRAY: | ||
| 641 | glTextureStorage2D(handle, num_levels, gl_internal_format, width, num_layers); | ||
| 642 | break; | ||
| 643 | case GL_TEXTURE_2D_ARRAY: | ||
| 644 | glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, num_layers); | ||
| 645 | break; | ||
| 646 | case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { | ||
| 647 | // TODO: Where should 'fixedsamplelocations' come from? | ||
| 648 | const auto [samples_x, samples_y] = SamplesLog2(info.num_samples); | ||
| 649 | glTextureStorage3DMultisample(handle, num_samples, gl_internal_format, width >> samples_x, | ||
| 650 | height >> samples_y, num_layers, GL_FALSE); | ||
| 651 | break; | ||
| 652 | } | ||
| 653 | case GL_TEXTURE_RECTANGLE: | ||
| 654 | glTextureStorage2D(handle, num_levels, gl_internal_format, width, height); | ||
| 655 | break; | ||
| 656 | case GL_TEXTURE_3D: | ||
| 657 | glTextureStorage3D(handle, num_levels, gl_internal_format, width, height, depth); | ||
| 658 | break; | ||
| 659 | case GL_TEXTURE_BUFFER: | ||
| 660 | UNREACHABLE(); | ||
| 661 | break; | ||
| 662 | default: | ||
| 663 | UNREACHABLE_MSG("Invalid target=0x{:x}", target); | ||
| 664 | break; | ||
| 665 | } | ||
| 666 | if (runtime.device.HasDebuggingToolAttached()) { | ||
| 667 | const std::string name = VideoCommon::Name(*this); | 678 | const std::string name = VideoCommon::Name(*this); |
| 668 | glObjectLabel(target == GL_TEXTURE_BUFFER ? GL_BUFFER : GL_TEXTURE, handle, | 679 | glObjectLabel(ImageTarget(info) == GL_TEXTURE_BUFFER ? GL_BUFFER : GL_TEXTURE, |
| 669 | static_cast<GLsizei>(name.size()), name.data()); | 680 | texture.handle, static_cast<GLsizei>(name.size()), name.data()); |
| 670 | } | 681 | } |
| 671 | } | 682 | } |
| 672 | 683 | ||
| @@ -855,7 +866,7 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b | |||
| 855 | } | 866 | } |
| 856 | } | 867 | } |
| 857 | 868 | ||
| 858 | void Image::Scale() { | 869 | void Image::Scale(u32 up, u32 down) { |
| 859 | // TODO: Pass scaling factor? | 870 | // TODO: Pass scaling factor? |
| 860 | if (gl_format == 0 || gl_type == 0) { | 871 | if (gl_format == 0 || gl_type == 0) { |
| 861 | // compressed textures | 872 | // compressed textures |
| @@ -902,12 +913,22 @@ void Image::Scale() { | |||
| 902 | glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_handle); | 913 | glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_handle); |
| 903 | glNamedFramebufferTexture(fbo_handle, attachment, texture.handle, 0); | 914 | glNamedFramebufferTexture(fbo_handle, attachment, texture.handle, 0); |
| 904 | 915 | ||
| 905 | const size_t scaled_width = info.size.width; | 916 | const auto scale_up = [&](u32 value) { return std::max<u32>((value * up) >> down, 1U); }; |
| 906 | const size_t scaled_height = info.size.height * 2; | 917 | const u32 scaled_width = scale_up(info.size.width); |
| 907 | glBlitNamedFramebuffer(fbo_handle, fbo_handle, 0, 0, info.size.width, info.size.height, 0, 0, | 918 | const u32 scaled_height = scale_up(info.size.height); |
| 919 | const u32 original_width = info.size.width; | ||
| 920 | const u32 original_height = info.size.height; | ||
| 921 | |||
| 922 | auto scaled_info = info; | ||
| 923 | scaled_info.size.width = scaled_width; | ||
| 924 | scaled_info.size.height = scaled_height; | ||
| 925 | auto scaled_texture = MakeImage(scaled_info, gl_internal_format); | ||
| 926 | |||
| 927 | glBlitNamedFramebuffer(fbo_handle, fbo_handle, 0, 0, original_width, original_height, 0, 0, | ||
| 908 | scaled_width, scaled_height, mask, filter); | 928 | scaled_width, scaled_height, mask, filter); |
| 909 | // TODO: resize texture? | 929 | glCopyTextureSubImage3D(scaled_texture.handle, 0, 0, 0, 0, 0, 0, scaled_width, scaled_height); |
| 910 | glCopyTextureSubImage3D(texture.handle, 0, 0, 0, 0, 0, 0, scaled_width, scaled_height / 2); | 930 | texture = std::move(scaled_texture); |
| 931 | |||
| 911 | // Restore previous framebuffers | 932 | // Restore previous framebuffers |
| 912 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prev_draw_fbo); | 933 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prev_draw_fbo); |
| 913 | glBindFramebuffer(GL_READ_FRAMEBUFFER, prev_read_fbo); | 934 | glBindFramebuffer(GL_READ_FRAMEBUFFER, prev_read_fbo); |
| @@ -918,7 +939,8 @@ bool Image::ScaleUp() { | |||
| 918 | return false; | 939 | return false; |
| 919 | } | 940 | } |
| 920 | flags |= ImageFlagBits::Rescaled; | 941 | flags |= ImageFlagBits::Rescaled; |
| 921 | //Scale(); | 942 | const auto& resolution = runtime->resolution; |
| 943 | Scale(resolution.up_scale, resolution.down_shift); | ||
| 922 | return true; | 944 | return true; |
| 923 | } | 945 | } |
| 924 | 946 | ||
| @@ -927,7 +949,9 @@ bool Image::ScaleDown() { | |||
| 927 | return false; | 949 | return false; |
| 928 | } | 950 | } |
| 929 | flags &= ~ImageFlagBits::Rescaled; | 951 | flags &= ~ImageFlagBits::Rescaled; |
| 930 | //Scale(); | 952 | UNIMPLEMENTED(); |
| 953 | // const auto& resolution = runtime->resolution; | ||
| 954 | // Scale(); | ||
| 931 | return true; | 955 | return true; |
| 932 | } | 956 | } |
| 933 | 957 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 324a0f1cb..77ca14132 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include <glad/glad.h> | 10 | #include <glad/glad.h> |
| 11 | 11 | ||
| 12 | #include "common/settings.h" | ||
| 12 | #include "shader_recompiler/shader_info.h" | 13 | #include "shader_recompiler/shader_info.h" |
| 13 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 14 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 14 | #include "video_core/renderer_opengl/util_shaders.h" | 15 | #include "video_core/renderer_opengl/util_shaders.h" |
| @@ -72,7 +73,7 @@ public: | |||
| 72 | StateTracker& state_tracker); | 73 | StateTracker& state_tracker); |
| 73 | ~TextureCacheRuntime(); | 74 | ~TextureCacheRuntime(); |
| 74 | 75 | ||
| 75 | void Init() {} | 76 | void Init(); |
| 76 | 77 | ||
| 77 | void Finish(); | 78 | void Finish(); |
| 78 | 79 | ||
| @@ -153,6 +154,9 @@ private: | |||
| 153 | OGLTextureView null_image_view_cube; | 154 | OGLTextureView null_image_view_cube; |
| 154 | 155 | ||
| 155 | std::array<GLuint, Shader::NUM_TEXTURE_TYPES> null_image_views{}; | 156 | std::array<GLuint, Shader::NUM_TEXTURE_TYPES> null_image_views{}; |
| 157 | |||
| 158 | Settings::ResolutionScalingInfo resolution; | ||
| 159 | bool is_rescaling_on{}; | ||
| 156 | }; | 160 | }; |
| 157 | 161 | ||
| 158 | class Image : public VideoCommon::ImageBase { | 162 | class Image : public VideoCommon::ImageBase { |
| @@ -198,13 +202,14 @@ private: | |||
| 198 | 202 | ||
| 199 | void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset); | 203 | void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset); |
| 200 | 204 | ||
| 201 | void Scale(); | 205 | void Scale(u32 up, u32 down); |
| 202 | 206 | ||
| 203 | OGLTexture texture; | 207 | OGLTexture texture; |
| 204 | OGLTextureView store_view; | 208 | OGLTextureView store_view; |
| 205 | GLenum gl_internal_format = GL_NONE; | 209 | GLenum gl_internal_format = GL_NONE; |
| 206 | GLenum gl_format = GL_NONE; | 210 | GLenum gl_format = GL_NONE; |
| 207 | GLenum gl_type = GL_NONE; | 211 | GLenum gl_type = GL_NONE; |
| 212 | TextureCacheRuntime* runtime; | ||
| 208 | }; | 213 | }; |
| 209 | 214 | ||
| 210 | class ImageView : public VideoCommon::ImageViewBase { | 215 | class ImageView : public VideoCommon::ImageViewBase { |