summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2019-02-06 20:17:59 -0500
committerGravatar GitHub2019-02-06 20:17:59 -0500
commit40ac0585574499bc0dee47c4bef354c8e5676695 (patch)
tree096b8e8c32f4affbd791386daa4b1feac2d9bedc /src
parentMerge pull request #2057 from FearlessTobi/port-4586 (diff)
parentgl_rasterizer_cache: Fixup test clause (diff)
downloadyuzu-40ac0585574499bc0dee47c4bef354c8e5676695.tar.gz
yuzu-40ac0585574499bc0dee47c4bef354c8e5676695.tar.xz
yuzu-40ac0585574499bc0dee47c4bef354c8e5676695.zip
Merge pull request #2071 from ReinUsesLisp/dsa-texture
gl_rasterizer: Use DSA for textures and move swizzling to texture state
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp242
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h7
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h2
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp32
-rw-r--r--src/video_core/renderer_opengl/gl_state.h12
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp63
8 files changed, 153 insertions, 216 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 9f7c837d6..53b52753c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -1019,11 +1019,8 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s
1019 if (surface != nullptr) { 1019 if (surface != nullptr) {
1020 unit.texture = 1020 unit.texture =
1021 entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; 1021 entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle;
1022 unit.target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); 1022 surface->UpdateSwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source,
1023 unit.swizzle.r = MaxwellToGL::SwizzleSource(texture.tic.x_source); 1023 texture.tic.w_source);
1024 unit.swizzle.g = MaxwellToGL::SwizzleSource(texture.tic.y_source);
1025 unit.swizzle.b = MaxwellToGL::SwizzleSource(texture.tic.z_source);
1026 unit.swizzle.a = MaxwellToGL::SwizzleSource(texture.tic.w_source);
1027 } else { 1024 } else {
1028 // Can occur when texture addr is null or its memory is unmapped/invalid 1025 // Can occur when texture addr is null or its memory is unmapped/invalid
1029 unit.texture = 0; 1026 unit.texture = 0;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 50286432d..a79eee03e 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -18,7 +18,6 @@
18#include "video_core/morton.h" 18#include "video_core/morton.h"
19#include "video_core/renderer_opengl/gl_rasterizer.h" 19#include "video_core/renderer_opengl/gl_rasterizer.h"
20#include "video_core/renderer_opengl/gl_rasterizer_cache.h" 20#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
21#include "video_core/renderer_opengl/gl_state.h"
22#include "video_core/renderer_opengl/utils.h" 21#include "video_core/renderer_opengl/utils.h"
23#include "video_core/surface.h" 22#include "video_core/surface.h"
24#include "video_core/textures/astc.h" 23#include "video_core/textures/astc.h"
@@ -44,14 +43,14 @@ struct FormatTuple {
44 bool compressed; 43 bool compressed;
45}; 44};
46 45
47static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) { 46static void ApplyTextureDefaults(GLuint texture, u32 max_mip_level) {
48 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 47 glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
49 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 48 glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
50 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 49 glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
51 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 50 glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
52 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); 51 glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1);
53 if (max_mip_level == 1) { 52 if (max_mip_level == 1) {
54 glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0); 53 glTextureParameterf(texture, GL_TEXTURE_LOD_BIAS, 1000.0);
55 } 54 }
56} 55}
57 56
@@ -529,55 +528,41 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
529CachedSurface::CachedSurface(const SurfaceParams& params) 528CachedSurface::CachedSurface(const SurfaceParams& params)
530 : params(params), gl_target(SurfaceTargetToGL(params.target)), 529 : params(params), gl_target(SurfaceTargetToGL(params.target)),
531 cached_size_in_bytes(params.size_in_bytes) { 530 cached_size_in_bytes(params.size_in_bytes) {
532 texture.Create(); 531 texture.Create(gl_target);
533 const auto& rect{params.GetRect()}; 532
534 533 // TODO(Rodrigo): Using params.GetRect() returns a different size than using its Mip*(0)
535 // Keep track of previous texture bindings 534 // alternatives. This signals a bug on those functions.
536 OpenGLState cur_state = OpenGLState::GetCurState(); 535 const auto width = static_cast<GLsizei>(params.MipWidth(0));
537 const auto& old_tex = cur_state.texture_units[0]; 536 const auto height = static_cast<GLsizei>(params.MipHeight(0));
538 SCOPE_EXIT({
539 cur_state.texture_units[0] = old_tex;
540 cur_state.Apply();
541 });
542
543 cur_state.texture_units[0].texture = texture.handle;
544 cur_state.texture_units[0].target = SurfaceTargetToGL(params.target);
545 cur_state.Apply();
546 glActiveTexture(GL_TEXTURE0);
547 537
548 const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); 538 const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type);
549 gl_internal_format = format_tuple.internal_format; 539 gl_internal_format = format_tuple.internal_format;
550 gl_is_compressed = format_tuple.compressed;
551 540
552 if (!format_tuple.compressed) { 541 switch (params.target) {
553 // Only pre-create the texture for non-compressed textures. 542 case SurfaceTarget::Texture1D:
554 switch (params.target) { 543 glTextureStorage1D(texture.handle, params.max_mip_level, format_tuple.internal_format,
555 case SurfaceTarget::Texture1D: 544 width);
556 glTexStorage1D(SurfaceTargetToGL(params.target), params.max_mip_level, 545 break;
557 format_tuple.internal_format, rect.GetWidth()); 546 case SurfaceTarget::Texture2D:
558 break; 547 case SurfaceTarget::TextureCubemap:
559 case SurfaceTarget::Texture2D: 548 glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format,
560 case SurfaceTarget::TextureCubemap: 549 width, height);
561 glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level, 550 break;
562 format_tuple.internal_format, rect.GetWidth(), rect.GetHeight()); 551 case SurfaceTarget::Texture3D:
563 break; 552 case SurfaceTarget::Texture2DArray:
564 case SurfaceTarget::Texture3D: 553 case SurfaceTarget::TextureCubeArray:
565 case SurfaceTarget::Texture2DArray: 554 glTextureStorage3D(texture.handle, params.max_mip_level, format_tuple.internal_format,
566 case SurfaceTarget::TextureCubeArray: 555 width, height, params.depth);
567 glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level, 556 break;
568 format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(), 557 default:
569 params.depth); 558 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
570 break; 559 static_cast<u32>(params.target));
571 default: 560 UNREACHABLE();
572 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", 561 glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format,
573 static_cast<u32>(params.target)); 562 width, height);
574 UNREACHABLE();
575 glTexStorage2D(GL_TEXTURE_2D, params.max_mip_level, format_tuple.internal_format,
576 rect.GetWidth(), rect.GetHeight());
577 }
578 } 563 }
579 564
580 ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level); 565 ApplyTextureDefaults(texture.handle, params.max_mip_level);
581 566
582 OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString()); 567 OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString());
583 568
@@ -751,63 +736,50 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
751 const auto& rect{params.GetRect(mip_map)}; 736 const auto& rect{params.GetRect(mip_map)};
752 737
753 // Load data from memory to the surface 738 // Load data from memory to the surface
754 const GLint x0 = static_cast<GLint>(rect.left); 739 const auto x0 = static_cast<GLint>(rect.left);
755 const GLint y0 = static_cast<GLint>(rect.bottom); 740 const auto y0 = static_cast<GLint>(rect.bottom);
756 std::size_t buffer_offset = 741 auto buffer_offset =
757 static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) + 742 static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) +
758 static_cast<std::size_t>(x0)) * 743 static_cast<std::size_t>(x0)) *
759 GetBytesPerPixel(params.pixel_format); 744 GetBytesPerPixel(params.pixel_format);
760 745
761 const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); 746 const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
762 const GLuint target_tex = texture.handle;
763 OpenGLState cur_state = OpenGLState::GetCurState();
764
765 const auto& old_tex = cur_state.texture_units[0];
766 SCOPE_EXIT({
767 cur_state.texture_units[0] = old_tex;
768 cur_state.Apply();
769 });
770 cur_state.texture_units[0].texture = target_tex;
771 cur_state.texture_units[0].target = SurfaceTargetToGL(params.target);
772 cur_state.Apply();
773 747
774 // Ensure no bad interactions with GL_UNPACK_ALIGNMENT 748 // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
775 ASSERT(params.MipWidth(mip_map) * GetBytesPerPixel(params.pixel_format) % 4 == 0); 749 ASSERT(params.MipWidth(mip_map) * GetBytesPerPixel(params.pixel_format) % 4 == 0);
776 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map))); 750 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map)));
777 751
778 GLsizei image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false)); 752 const auto image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false));
779 glActiveTexture(GL_TEXTURE0);
780 if (tuple.compressed) { 753 if (tuple.compressed) {
781 switch (params.target) { 754 switch (params.target) {
782 case SurfaceTarget::Texture2D: 755 case SurfaceTarget::Texture2D:
783 glCompressedTexImage2D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, 756 glCompressedTextureSubImage2D(
784 static_cast<GLsizei>(params.MipWidth(mip_map)), 757 texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)),
785 static_cast<GLsizei>(params.MipHeight(mip_map)), 0, image_size, 758 static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format, image_size,
786 &gl_buffer[mip_map][buffer_offset]); 759 &gl_buffer[mip_map][buffer_offset]);
787 break; 760 break;
788 case SurfaceTarget::Texture3D: 761 case SurfaceTarget::Texture3D:
789 glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, 762 glCompressedTextureSubImage3D(
790 static_cast<GLsizei>(params.MipWidth(mip_map)), 763 texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)),
791 static_cast<GLsizei>(params.MipHeight(mip_map)), 764 static_cast<GLsizei>(params.MipHeight(mip_map)),
792 static_cast<GLsizei>(params.MipDepth(mip_map)), 0, image_size, 765 static_cast<GLsizei>(params.MipDepth(mip_map)), tuple.internal_format, image_size,
793 &gl_buffer[mip_map][buffer_offset]); 766 &gl_buffer[mip_map][buffer_offset]);
794 break; 767 break;
795 case SurfaceTarget::Texture2DArray: 768 case SurfaceTarget::Texture2DArray:
796 case SurfaceTarget::TextureCubeArray: 769 case SurfaceTarget::TextureCubeArray:
797 glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, 770 glCompressedTextureSubImage3D(
798 static_cast<GLsizei>(params.MipWidth(mip_map)), 771 texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)),
799 static_cast<GLsizei>(params.MipHeight(mip_map)), 772 static_cast<GLsizei>(params.MipHeight(mip_map)), static_cast<GLsizei>(params.depth),
800 static_cast<GLsizei>(params.depth), 0, image_size, 773 tuple.internal_format, image_size, &gl_buffer[mip_map][buffer_offset]);
801 &gl_buffer[mip_map][buffer_offset]);
802 break; 774 break;
803 case SurfaceTarget::TextureCubemap: { 775 case SurfaceTarget::TextureCubemap: {
804 GLsizei layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); 776 const auto layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map));
805 for (std::size_t face = 0; face < params.depth; ++face) { 777 for (std::size_t face = 0; face < params.depth; ++face) {
806 glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), 778 glCompressedTextureSubImage3D(
807 mip_map, tuple.internal_format, 779 texture.handle, mip_map, 0, 0, static_cast<GLint>(face),
808 static_cast<GLsizei>(params.MipWidth(mip_map)), 780 static_cast<GLsizei>(params.MipWidth(mip_map)),
809 static_cast<GLsizei>(params.MipHeight(mip_map)), 0, 781 static_cast<GLsizei>(params.MipHeight(mip_map)), 1, tuple.internal_format,
810 layer_size, &gl_buffer[mip_map][buffer_offset]); 782 layer_size, &gl_buffer[mip_map][buffer_offset]);
811 buffer_offset += layer_size; 783 buffer_offset += layer_size;
812 } 784 }
813 break; 785 break;
@@ -816,46 +788,43 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
816 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", 788 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
817 static_cast<u32>(params.target)); 789 static_cast<u32>(params.target));
818 UNREACHABLE(); 790 UNREACHABLE();
819 glCompressedTexImage2D(GL_TEXTURE_2D, mip_map, tuple.internal_format, 791 glCompressedTextureSubImage2D(
820 static_cast<GLsizei>(params.MipWidth(mip_map)), 792 texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)),
821 static_cast<GLsizei>(params.MipHeight(mip_map)), 0, 793 static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format,
822 static_cast<GLsizei>(params.size_in_bytes_gl), 794 static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[mip_map][buffer_offset]);
823 &gl_buffer[mip_map][buffer_offset]);
824 } 795 }
825 } else { 796 } else {
826
827 switch (params.target) { 797 switch (params.target) {
828 case SurfaceTarget::Texture1D: 798 case SurfaceTarget::Texture1D:
829 glTexSubImage1D(SurfaceTargetToGL(params.target), mip_map, x0, 799 glTextureSubImage1D(texture.handle, mip_map, x0, static_cast<GLsizei>(rect.GetWidth()),
830 static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type, 800 tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
831 &gl_buffer[mip_map][buffer_offset]);
832 break; 801 break;
833 case SurfaceTarget::Texture2D: 802 case SurfaceTarget::Texture2D:
834 glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 803 glTextureSubImage2D(texture.handle, mip_map, x0, y0,
835 static_cast<GLsizei>(rect.GetWidth()), 804 static_cast<GLsizei>(rect.GetWidth()),
836 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, 805 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
837 &gl_buffer[mip_map][buffer_offset]); 806 &gl_buffer[mip_map][buffer_offset]);
838 break; 807 break;
839 case SurfaceTarget::Texture3D: 808 case SurfaceTarget::Texture3D:
840 glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, 809 glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0,
841 static_cast<GLsizei>(rect.GetWidth()), 810 static_cast<GLsizei>(rect.GetWidth()),
842 static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map), 811 static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map),
843 tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); 812 tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
844 break; 813 break;
845 case SurfaceTarget::Texture2DArray: 814 case SurfaceTarget::Texture2DArray:
846 case SurfaceTarget::TextureCubeArray: 815 case SurfaceTarget::TextureCubeArray:
847 glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, 816 glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0,
848 static_cast<GLsizei>(rect.GetWidth()), 817 static_cast<GLsizei>(rect.GetWidth()),
849 static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, 818 static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
850 tuple.type, &gl_buffer[mip_map][buffer_offset]); 819 tuple.type, &gl_buffer[mip_map][buffer_offset]);
851 break; 820 break;
852 case SurfaceTarget::TextureCubemap: { 821 case SurfaceTarget::TextureCubemap: {
853 std::size_t start = buffer_offset; 822 std::size_t start = buffer_offset;
854 for (std::size_t face = 0; face < params.depth; ++face) { 823 for (std::size_t face = 0; face < params.depth; ++face) {
855 glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map, 824 glTextureSubImage3D(texture.handle, mip_map, x0, y0, static_cast<GLint>(face),
856 x0, y0, static_cast<GLsizei>(rect.GetWidth()), 825 static_cast<GLsizei>(rect.GetWidth()),
857 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, 826 static_cast<GLsizei>(rect.GetHeight()), 1, tuple.format,
858 &gl_buffer[mip_map][buffer_offset]); 827 tuple.type, &gl_buffer[mip_map][buffer_offset]);
859 buffer_offset += params.LayerSizeGL(mip_map); 828 buffer_offset += params.LayerSizeGL(mip_map);
860 } 829 }
861 break; 830 break;
@@ -864,9 +833,10 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
864 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", 833 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
865 static_cast<u32>(params.target)); 834 static_cast<u32>(params.target));
866 UNREACHABLE(); 835 UNREACHABLE();
867 glTexSubImage2D(GL_TEXTURE_2D, mip_map, x0, y0, static_cast<GLsizei>(rect.GetWidth()), 836 glTextureSubImage2D(texture.handle, mip_map, x0, y0,
868 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, 837 static_cast<GLsizei>(rect.GetWidth()),
869 &gl_buffer[mip_map][buffer_offset]); 838 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
839 &gl_buffer[mip_map][buffer_offset]);
870 } 840 }
871 } 841 }
872 842
@@ -876,29 +846,18 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
876void CachedSurface::EnsureTextureView() { 846void CachedSurface::EnsureTextureView() {
877 if (texture_view.handle != 0) 847 if (texture_view.handle != 0)
878 return; 848 return;
879 // Compressed texture are not being created with immutable storage
880 UNIMPLEMENTED_IF(gl_is_compressed);
881 849
882 const GLenum target{TargetLayer()}; 850 const GLenum target{TargetLayer()};
883 const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u}; 851 const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u};
884 constexpr GLuint min_layer = 0; 852 constexpr GLuint min_layer = 0;
885 constexpr GLuint min_level = 0; 853 constexpr GLuint min_level = 0;
886 854
887 texture_view.Create(); 855 glGenTextures(1, &texture_view.handle);
888 glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, min_level, 856 glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0,
889 params.max_mip_level, min_layer, num_layers); 857 params.max_mip_level, 0, 1);
890 858 ApplyTextureDefaults(texture_view.handle, params.max_mip_level);
891 OpenGLState cur_state = OpenGLState::GetCurState(); 859 glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA,
892 const auto& old_tex = cur_state.texture_units[0]; 860 reinterpret_cast<const GLint*>(swizzle.data()));
893 SCOPE_EXIT({
894 cur_state.texture_units[0] = old_tex;
895 cur_state.Apply();
896 });
897 cur_state.texture_units[0].texture = texture_view.handle;
898 cur_state.texture_units[0].target = target;
899 cur_state.Apply();
900
901 ApplyTextureDefaults(target, params.max_mip_level);
902} 861}
903 862
904MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); 863MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
@@ -909,6 +868,25 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
909 UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle); 868 UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle);
910} 869}
911 870
871void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x,
872 Tegra::Texture::SwizzleSource swizzle_y,
873 Tegra::Texture::SwizzleSource swizzle_z,
874 Tegra::Texture::SwizzleSource swizzle_w) {
875 const GLenum new_x = MaxwellToGL::SwizzleSource(swizzle_x);
876 const GLenum new_y = MaxwellToGL::SwizzleSource(swizzle_y);
877 const GLenum new_z = MaxwellToGL::SwizzleSource(swizzle_z);
878 const GLenum new_w = MaxwellToGL::SwizzleSource(swizzle_w);
879 if (swizzle[0] == new_x && swizzle[1] == new_y && swizzle[2] == new_z && swizzle[3] == new_w) {
880 return;
881 }
882 swizzle = {new_x, new_y, new_z, new_w};
883 const auto swizzle_data = reinterpret_cast<const GLint*>(swizzle.data());
884 glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data);
885 if (texture_view.handle != 0) {
886 glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data);
887 }
888}
889
912RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer) 890RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer)
913 : RasterizerCache{rasterizer} { 891 : RasterizerCache{rasterizer} {
914 read_framebuffer.Create(); 892 read_framebuffer.Create();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 8d7d6722c..490b8252e 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -382,6 +382,11 @@ public:
382 // Upload data in gl_buffer to this surface's texture 382 // Upload data in gl_buffer to this surface's texture
383 void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); 383 void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle);
384 384
385 void UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x,
386 Tegra::Texture::SwizzleSource swizzle_y,
387 Tegra::Texture::SwizzleSource swizzle_z,
388 Tegra::Texture::SwizzleSource swizzle_w);
389
385private: 390private:
386 void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle); 391 void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle);
387 392
@@ -393,8 +398,8 @@ private:
393 SurfaceParams params{}; 398 SurfaceParams params{};
394 GLenum gl_target{}; 399 GLenum gl_target{};
395 GLenum gl_internal_format{}; 400 GLenum gl_internal_format{};
396 bool gl_is_compressed{};
397 std::size_t cached_size_in_bytes{}; 401 std::size_t cached_size_in_bytes{};
402 std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
398}; 403};
399 404
400class RasterizerCacheOpenGL final : public RasterizerCache<Surface> { 405class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp
index 1da744158..4170cbd3c 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp
@@ -15,12 +15,12 @@ MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_R
15 15
16namespace OpenGL { 16namespace OpenGL {
17 17
18void OGLTexture::Create() { 18void OGLTexture::Create(GLenum target) {
19 if (handle != 0) 19 if (handle != 0)
20 return; 20 return;
21 21
22 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 22 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
23 glGenTextures(1, &handle); 23 glCreateTextures(target, 1, &handle);
24} 24}
25 25
26void OGLTexture::Release() { 26void OGLTexture::Release() {
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h
index e33f1e973..df76cbc4b 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.h
+++ b/src/video_core/renderer_opengl/gl_resource_manager.h
@@ -28,7 +28,7 @@ public:
28 } 28 }
29 29
30 /// Creates a new internal OpenGL resource and stores the handle 30 /// Creates a new internal OpenGL resource and stores the handle
31 void Create(); 31 void Create(GLenum target);
32 32
33 /// Deletes the internal OpenGL resource 33 /// Deletes the internal OpenGL resource
34 void Release(); 34 void Release();
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index b7ba59350..81af803bc 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -462,29 +462,35 @@ void OpenGLState::ApplyPolygonOffset() const {
462} 462}
463 463
464void OpenGLState::ApplyTextures() const { 464void OpenGLState::ApplyTextures() const {
465 bool has_delta{};
466 std::size_t first{};
467 std::size_t last{};
468 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> textures;
469
465 for (std::size_t i = 0; i < std::size(texture_units); ++i) { 470 for (std::size_t i = 0; i < std::size(texture_units); ++i) {
466 const auto& texture_unit = texture_units[i]; 471 const auto& texture_unit = texture_units[i];
467 const auto& cur_state_texture_unit = cur_state.texture_units[i]; 472 const auto& cur_state_texture_unit = cur_state.texture_units[i];
473 textures[i] = texture_unit.texture;
468 474
469 if (texture_unit.texture != cur_state_texture_unit.texture) { 475 if (textures[i] != cur_state_texture_unit.texture) {
470 glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum()); 476 if (!has_delta) {
471 glBindTexture(texture_unit.target, texture_unit.texture); 477 first = i;
472 } 478 has_delta = true;
473 // Update the texture swizzle 479 }
474 if (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r || 480 last = i;
475 texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g ||
476 texture_unit.swizzle.b != cur_state_texture_unit.swizzle.b ||
477 texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a) {
478 std::array<GLint, 4> mask = {texture_unit.swizzle.r, texture_unit.swizzle.g,
479 texture_unit.swizzle.b, texture_unit.swizzle.a};
480 glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data());
481 } 481 }
482 } 482 }
483
484 if (has_delta) {
485 glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
486 textures.data());
487 }
483} 488}
484 489
485void OpenGLState::ApplySamplers() const { 490void OpenGLState::ApplySamplers() const {
486 bool has_delta{}; 491 bool has_delta{};
487 std::size_t first{}, last{}; 492 std::size_t first{};
493 std::size_t last{};
488 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers; 494 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers;
489 for (std::size_t i = 0; i < std::size(samplers); ++i) { 495 for (std::size_t i = 0; i < std::size(samplers); ++i) {
490 samplers[i] = texture_units[i].sampler; 496 samplers[i] = texture_units[i].sampler;
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index a5a7c0920..9e1eda5b1 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -126,26 +126,14 @@ public:
126 struct TextureUnit { 126 struct TextureUnit {
127 GLuint texture; // GL_TEXTURE_BINDING_2D 127 GLuint texture; // GL_TEXTURE_BINDING_2D
128 GLuint sampler; // GL_SAMPLER_BINDING 128 GLuint sampler; // GL_SAMPLER_BINDING
129 GLenum target;
130 struct {
131 GLint r; // GL_TEXTURE_SWIZZLE_R
132 GLint g; // GL_TEXTURE_SWIZZLE_G
133 GLint b; // GL_TEXTURE_SWIZZLE_B
134 GLint a; // GL_TEXTURE_SWIZZLE_A
135 } swizzle;
136 129
137 void Unbind() { 130 void Unbind() {
138 texture = 0; 131 texture = 0;
139 swizzle.r = GL_RED;
140 swizzle.g = GL_GREEN;
141 swizzle.b = GL_BLUE;
142 swizzle.a = GL_ALPHA;
143 } 132 }
144 133
145 void Reset() { 134 void Reset() {
146 Unbind(); 135 Unbind();
147 sampler = 0; 136 sampler = 0;
148 target = GL_TEXTURE_2D;
149 } 137 }
150 }; 138 };
151 std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units; 139 std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index e37b65b38..5b09c38ea 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -171,10 +171,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
171 Memory::GetPointer(framebuffer_addr), 171 Memory::GetPointer(framebuffer_addr),
172 gl_framebuffer_data.data(), true); 172 gl_framebuffer_data.data(), true);
173 173
174 state.texture_units[0].texture = screen_info.texture.resource.handle;
175 state.Apply();
176
177 glActiveTexture(GL_TEXTURE0);
178 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride)); 174 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
179 175
180 // Update existing texture 176 // Update existing texture
@@ -182,14 +178,11 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
182 // they differ from the LCD resolution. 178 // they differ from the LCD resolution.
183 // TODO: Applications could theoretically crash yuzu here by specifying too large 179 // TODO: Applications could theoretically crash yuzu here by specifying too large
184 // framebuffer sizes. We should make sure that this cannot happen. 180 // framebuffer sizes. We should make sure that this cannot happen.
185 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, 181 glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width,
186 screen_info.texture.gl_format, screen_info.texture.gl_type, 182 framebuffer.height, screen_info.texture.gl_format,
187 gl_framebuffer_data.data()); 183 screen_info.texture.gl_type, gl_framebuffer_data.data());
188 184
189 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 185 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
190
191 state.texture_units[0].texture = 0;
192 state.Apply();
193 } 186 }
194} 187}
195 188
@@ -199,17 +192,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
199 */ 192 */
200void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, 193void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
201 const TextureInfo& texture) { 194 const TextureInfo& texture) {
202 state.texture_units[0].texture = texture.resource.handle; 195 const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
203 state.Apply(); 196 glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
204
205 glActiveTexture(GL_TEXTURE0);
206 u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
207
208 // Update existing texture
209 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
210
211 state.texture_units[0].texture = 0;
212 state.Apply();
213} 197}
214 198
215/** 199/**
@@ -249,26 +233,13 @@ void RendererOpenGL::InitOpenGLObjects() {
249 sizeof(ScreenRectVertex)); 233 sizeof(ScreenRectVertex));
250 234
251 // Allocate textures for the screen 235 // Allocate textures for the screen
252 screen_info.texture.resource.Create(); 236 screen_info.texture.resource.Create(GL_TEXTURE_2D);
253 237
254 // Allocation of storage is deferred until the first frame, when we 238 const GLuint texture = screen_info.texture.resource.handle;
255 // know the framebuffer size. 239 glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1);
256
257 state.texture_units[0].texture = screen_info.texture.resource.handle;
258 state.Apply();
259
260 glActiveTexture(GL_TEXTURE0);
261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
263 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
264 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
265 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
266 240
267 screen_info.display_texture = screen_info.texture.resource.handle; 241 screen_info.display_texture = screen_info.texture.resource.handle;
268 242
269 state.texture_units[0].texture = 0;
270 state.Apply();
271
272 // Clear screen to black 243 // Clear screen to black
273 LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); 244 LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture);
274} 245}
@@ -284,20 +255,19 @@ void RendererOpenGL::CreateRasterizer() {
284 255
285void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, 256void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
286 const Tegra::FramebufferConfig& framebuffer) { 257 const Tegra::FramebufferConfig& framebuffer) {
287
288 texture.width = framebuffer.width; 258 texture.width = framebuffer.width;
289 texture.height = framebuffer.height; 259 texture.height = framebuffer.height;
290 260
291 GLint internal_format; 261 GLint internal_format;
292 switch (framebuffer.pixel_format) { 262 switch (framebuffer.pixel_format) {
293 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 263 case Tegra::FramebufferConfig::PixelFormat::ABGR8:
294 internal_format = GL_RGBA; 264 internal_format = GL_RGBA8;
295 texture.gl_format = GL_RGBA; 265 texture.gl_format = GL_RGBA;
296 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; 266 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
297 gl_framebuffer_data.resize(texture.width * texture.height * 4); 267 gl_framebuffer_data.resize(texture.width * texture.height * 4);
298 break; 268 break;
299 default: 269 default:
300 internal_format = GL_RGBA; 270 internal_format = GL_RGBA8;
301 texture.gl_format = GL_RGBA; 271 texture.gl_format = GL_RGBA;
302 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; 272 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
303 gl_framebuffer_data.resize(texture.width * texture.height * 4); 273 gl_framebuffer_data.resize(texture.width * texture.height * 4);
@@ -306,15 +276,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
306 UNREACHABLE(); 276 UNREACHABLE();
307 } 277 }
308 278
309 state.texture_units[0].texture = texture.resource.handle; 279 texture.resource.Release();
310 state.Apply(); 280 texture.resource.Create(GL_TEXTURE_2D);
311 281 glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height);
312 glActiveTexture(GL_TEXTURE0);
313 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0,
314 texture.gl_format, texture.gl_type, nullptr);
315
316 state.texture_units[0].texture = 0;
317 state.Apply();
318} 282}
319 283
320void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, 284void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w,
@@ -356,7 +320,6 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
356 }}; 320 }};
357 321
358 state.texture_units[0].texture = screen_info.display_texture; 322 state.texture_units[0].texture = screen_info.display_texture;
359 state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
360 // Workaround brigthness problems in SMO by enabling sRGB in the final output 323 // Workaround brigthness problems in SMO by enabling sRGB in the final output
361 // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 324 // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987
362 state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); 325 state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();