diff options
| author | 2018-10-29 22:34:00 -0400 | |
|---|---|---|
| committer | 2018-10-29 22:34:00 -0400 | |
| commit | c5a849212f6a1ee2945e4584bcda50a082872336 (patch) | |
| tree | 580b80a9c68c78f6e28b49bff2263fe421377972 | |
| parent | Merge pull request #1617 from FearlessTobi/fix-stretch-delay (diff) | |
| parent | Fixed black textures, pixelation and we no longer require to auto-generate mi... (diff) | |
| download | yuzu-c5a849212f6a1ee2945e4584bcda50a082872336.tar.gz yuzu-c5a849212f6a1ee2945e4584bcda50a082872336.tar.xz yuzu-c5a849212f6a1ee2945e4584bcda50a082872336.zip | |
Merge pull request #1580 from FernandoS27/mm-impl
Implemented Mipmaps
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 234 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 85 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 27 | ||||
| -rw-r--r-- | src/video_core/textures/decoders.h | 6 |
6 files changed, 254 insertions, 109 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index cb180b93c..7bb5544fc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -731,11 +731,15 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr | |||
| 731 | 731 | ||
| 732 | if (mag_filter != config.mag_filter) { | 732 | if (mag_filter != config.mag_filter) { |
| 733 | mag_filter = config.mag_filter; | 733 | mag_filter = config.mag_filter; |
| 734 | glSamplerParameteri(s, GL_TEXTURE_MAG_FILTER, MaxwellToGL::TextureFilterMode(mag_filter)); | 734 | glSamplerParameteri( |
| 735 | s, GL_TEXTURE_MAG_FILTER, | ||
| 736 | MaxwellToGL::TextureFilterMode(mag_filter, Tegra::Texture::TextureMipmapFilter::None)); | ||
| 735 | } | 737 | } |
| 736 | if (min_filter != config.min_filter) { | 738 | if (min_filter != config.min_filter || mip_filter != config.mip_filter) { |
| 737 | min_filter = config.min_filter; | 739 | min_filter = config.min_filter; |
| 738 | glSamplerParameteri(s, GL_TEXTURE_MIN_FILTER, MaxwellToGL::TextureFilterMode(min_filter)); | 740 | mip_filter = config.mip_filter; |
| 741 | glSamplerParameteri(s, GL_TEXTURE_MIN_FILTER, | ||
| 742 | MaxwellToGL::TextureFilterMode(min_filter, mip_filter)); | ||
| 739 | } | 743 | } |
| 740 | 744 | ||
| 741 | if (wrap_u != config.wrap_u) { | 745 | if (wrap_u != config.wrap_u) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 5020a5392..7b0615125 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -93,6 +93,7 @@ private: | |||
| 93 | private: | 93 | private: |
| 94 | Tegra::Texture::TextureFilter mag_filter; | 94 | Tegra::Texture::TextureFilter mag_filter; |
| 95 | Tegra::Texture::TextureFilter min_filter; | 95 | Tegra::Texture::TextureFilter min_filter; |
| 96 | Tegra::Texture::TextureMipmapFilter mip_filter; | ||
| 96 | Tegra::Texture::WrapMode wrap_u; | 97 | Tegra::Texture::WrapMode wrap_u; |
| 97 | Tegra::Texture::WrapMode wrap_v; | 98 | Tegra::Texture::WrapMode wrap_v; |
| 98 | Tegra::Texture::WrapMode wrap_p; | 99 | Tegra::Texture::WrapMode wrap_p; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 30c2803f5..1d43a419d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -91,27 +91,36 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) { | |||
| 91 | } | 91 | } |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const { | 94 | std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only, |
| 95 | bool uncompressed) const { | ||
| 95 | const u32 compression_factor{GetCompressionFactor(pixel_format)}; | 96 | const u32 compression_factor{GetCompressionFactor(pixel_format)}; |
| 96 | const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)}; | 97 | const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)}; |
| 97 | u32 m_depth = (layer_only ? 1U : depth); | 98 | u32 m_depth = (layer_only ? 1U : depth); |
| 98 | u32 m_width = std::max(1U, width / compression_factor); | 99 | u32 m_width = MipWidth(mip_level); |
| 99 | u32 m_height = std::max(1U, height / compression_factor); | 100 | u32 m_height = MipHeight(mip_level); |
| 100 | std::size_t size = Tegra::Texture::CalculateSize(is_tiled, bytes_per_pixel, m_width, m_height, | 101 | m_width = uncompressed ? m_width |
| 101 | m_depth, block_height, block_depth); | 102 | : std::max(1U, (m_width + compression_factor - 1) / compression_factor); |
| 102 | u32 m_block_height = block_height; | 103 | m_height = uncompressed |
| 103 | u32 m_block_depth = block_depth; | 104 | ? m_height |
| 104 | std::size_t block_size_bytes = 512 * block_height * block_depth; // 512 is GOB size | 105 | : std::max(1U, (m_height + compression_factor - 1) / compression_factor); |
| 105 | for (u32 i = 1; i < max_mip_level; i++) { | 106 | m_depth = std::max(1U, m_depth >> mip_level); |
| 106 | m_width = std::max(1U, m_width / 2); | 107 | u32 m_block_height = MipBlockHeight(mip_level); |
| 107 | m_height = std::max(1U, m_height / 2); | 108 | u32 m_block_depth = MipBlockDepth(mip_level); |
| 108 | m_depth = std::max(1U, m_depth / 2); | 109 | return Tegra::Texture::CalculateSize(force_gl ? false : is_tiled, bytes_per_pixel, m_width, |
| 109 | m_block_height = std::max(1U, m_block_height / 2); | 110 | m_height, m_depth, m_block_height, m_block_depth); |
| 110 | m_block_depth = std::max(1U, m_block_depth / 2); | 111 | } |
| 111 | size += Tegra::Texture::CalculateSize(is_tiled, bytes_per_pixel, m_width, m_height, m_depth, | 112 | |
| 112 | m_block_height, m_block_depth); | 113 | std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only, |
| 114 | bool uncompressed) const { | ||
| 115 | std::size_t block_size_bytes = Tegra::Texture::GetGOBSize() * block_height * block_depth; | ||
| 116 | std::size_t size = 0; | ||
| 117 | for (u32 i = 0; i < max_mip_level; i++) { | ||
| 118 | size += InnerMipmapMemorySize(i, force_gl, layer_only, uncompressed); | ||
| 119 | } | ||
| 120 | if (!force_gl && is_tiled) { | ||
| 121 | size = Common::AlignUp(size, block_size_bytes); | ||
| 113 | } | 122 | } |
| 114 | return is_tiled ? Common::AlignUp(size, block_size_bytes) : size; | 123 | return size; |
| 115 | } | 124 | } |
| 116 | 125 | ||
| 117 | /*static*/ SurfaceParams SurfaceParams::CreateForTexture( | 126 | /*static*/ SurfaceParams SurfaceParams::CreateForTexture( |
| @@ -189,7 +198,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const { | |||
| 189 | params.unaligned_height = config.height; | 198 | params.unaligned_height = config.height; |
| 190 | params.target = SurfaceTarget::Texture2D; | 199 | params.target = SurfaceTarget::Texture2D; |
| 191 | params.depth = 1; | 200 | params.depth = 1; |
| 192 | params.max_mip_level = 0; | 201 | params.max_mip_level = 1; |
| 193 | params.is_layered = false; | 202 | params.is_layered = false; |
| 194 | 203 | ||
| 195 | // Render target specific parameters, not used for caching | 204 | // Render target specific parameters, not used for caching |
| @@ -223,7 +232,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const { | |||
| 223 | params.unaligned_height = zeta_height; | 232 | params.unaligned_height = zeta_height; |
| 224 | params.target = SurfaceTarget::Texture2D; | 233 | params.target = SurfaceTarget::Texture2D; |
| 225 | params.depth = 1; | 234 | params.depth = 1; |
| 226 | params.max_mip_level = 0; | 235 | params.max_mip_level = 1; |
| 227 | params.is_layered = false; | 236 | params.is_layered = false; |
| 228 | params.rt = {}; | 237 | params.rt = {}; |
| 229 | 238 | ||
| @@ -250,7 +259,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const { | |||
| 250 | params.unaligned_height = config.height; | 259 | params.unaligned_height = config.height; |
| 251 | params.target = SurfaceTarget::Texture2D; | 260 | params.target = SurfaceTarget::Texture2D; |
| 252 | params.depth = 1; | 261 | params.depth = 1; |
| 253 | params.max_mip_level = 0; | 262 | params.max_mip_level = 1; |
| 254 | params.rt = {}; | 263 | params.rt = {}; |
| 255 | 264 | ||
| 256 | params.InitCacheParameters(config.Address()); | 265 | params.InitCacheParameters(config.Address()); |
| @@ -374,13 +383,13 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType | |||
| 374 | return format; | 383 | return format; |
| 375 | } | 384 | } |
| 376 | 385 | ||
| 377 | MathUtil::Rectangle<u32> SurfaceParams::GetRect() const { | 386 | MathUtil::Rectangle<u32> SurfaceParams::GetRect(u32 mip_level) const { |
| 378 | u32 actual_height{unaligned_height}; | 387 | u32 actual_height{std::max(1U, unaligned_height >> mip_level)}; |
| 379 | if (IsPixelFormatASTC(pixel_format)) { | 388 | if (IsPixelFormatASTC(pixel_format)) { |
| 380 | // ASTC formats must stop at the ATSC block size boundary | 389 | // ASTC formats must stop at the ATSC block size boundary |
| 381 | actual_height = Common::AlignDown(actual_height, GetASTCBlockSize(pixel_format).second); | 390 | actual_height = Common::AlignDown(actual_height, GetASTCBlockSize(pixel_format).second); |
| 382 | } | 391 | } |
| 383 | return {0, actual_height, width, 0}; | 392 | return {0, actual_height, MipWidth(mip_level), 0}; |
| 384 | } | 393 | } |
| 385 | 394 | ||
| 386 | /// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN | 395 | /// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN |
| @@ -564,28 +573,31 @@ static constexpr GLConversionArray gl_to_morton_fns = { | |||
| 564 | }; | 573 | }; |
| 565 | 574 | ||
| 566 | void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params, | 575 | void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params, |
| 567 | std::vector<u8>& gl_buffer) { | 576 | std::vector<u8>& gl_buffer, u32 mip_level) { |
| 568 | u32 depth = params.depth; | 577 | u32 depth = params.MipDepth(mip_level); |
| 569 | if (params.target == SurfaceParams::SurfaceTarget::Texture2D) { | 578 | if (params.target == SurfaceParams::SurfaceTarget::Texture2D) { |
| 570 | // TODO(Blinkhawk): Eliminate this condition once all texture types are implemented. | 579 | // TODO(Blinkhawk): Eliminate this condition once all texture types are implemented. |
| 571 | depth = 1U; | 580 | depth = 1U; |
| 572 | } | 581 | } |
| 573 | if (params.is_layered) { | 582 | if (params.is_layered) { |
| 574 | u64 offset = 0; | 583 | u64 offset = params.GetMipmapLevelOffset(mip_level); |
| 575 | u64 offset_gl = 0; | 584 | u64 offset_gl = 0; |
| 576 | u64 layer_size = params.LayerMemorySize(); | 585 | u64 layer_size = params.LayerMemorySize(); |
| 577 | u64 gl_size = params.LayerSizeGL(); | 586 | u64 gl_size = params.LayerSizeGL(mip_level); |
| 578 | for (u32 i = 0; i < depth; i++) { | 587 | for (u32 i = 0; i < params.depth; i++) { |
| 579 | functions[static_cast<std::size_t>(params.pixel_format)]( | 588 | functions[static_cast<std::size_t>(params.pixel_format)]( |
| 580 | params.width, params.block_height, params.height, params.block_depth, 1, | 589 | params.MipWidth(mip_level), params.MipBlockHeight(mip_level), |
| 590 | params.MipHeight(mip_level), params.MipBlockDepth(mip_level), 1, | ||
| 581 | gl_buffer.data() + offset_gl, gl_size, params.addr + offset); | 591 | gl_buffer.data() + offset_gl, gl_size, params.addr + offset); |
| 582 | offset += layer_size; | 592 | offset += layer_size; |
| 583 | offset_gl += gl_size; | 593 | offset_gl += gl_size; |
| 584 | } | 594 | } |
| 585 | } else { | 595 | } else { |
| 596 | u64 offset = params.GetMipmapLevelOffset(mip_level); | ||
| 586 | functions[static_cast<std::size_t>(params.pixel_format)]( | 597 | functions[static_cast<std::size_t>(params.pixel_format)]( |
| 587 | params.width, params.block_height, params.height, params.block_depth, depth, | 598 | params.MipWidth(mip_level), params.MipBlockHeight(mip_level), |
| 588 | gl_buffer.data(), gl_buffer.size(), params.addr); | 599 | params.MipHeight(mip_level), params.MipBlockDepth(mip_level), depth, gl_buffer.data(), |
| 600 | gl_buffer.size(), params.addr + offset); | ||
| 589 | } | 601 | } |
| 590 | } | 602 | } |
| 591 | 603 | ||
| @@ -840,31 +852,38 @@ CachedSurface::CachedSurface(const SurfaceParams& params) | |||
| 840 | // Only pre-create the texture for non-compressed textures. | 852 | // Only pre-create the texture for non-compressed textures. |
| 841 | switch (params.target) { | 853 | switch (params.target) { |
| 842 | case SurfaceParams::SurfaceTarget::Texture1D: | 854 | case SurfaceParams::SurfaceTarget::Texture1D: |
| 843 | glTexStorage1D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format, | 855 | glTexStorage1D(SurfaceTargetToGL(params.target), params.max_mip_level, |
| 844 | rect.GetWidth()); | 856 | format_tuple.internal_format, rect.GetWidth()); |
| 845 | break; | 857 | break; |
| 846 | case SurfaceParams::SurfaceTarget::Texture2D: | 858 | case SurfaceParams::SurfaceTarget::Texture2D: |
| 847 | case SurfaceParams::SurfaceTarget::TextureCubemap: | 859 | case SurfaceParams::SurfaceTarget::TextureCubemap: |
| 848 | glTexStorage2D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format, | 860 | glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level, |
| 849 | rect.GetWidth(), rect.GetHeight()); | 861 | format_tuple.internal_format, rect.GetWidth(), rect.GetHeight()); |
| 850 | break; | 862 | break; |
| 851 | case SurfaceParams::SurfaceTarget::Texture3D: | 863 | case SurfaceParams::SurfaceTarget::Texture3D: |
| 852 | case SurfaceParams::SurfaceTarget::Texture2DArray: | 864 | case SurfaceParams::SurfaceTarget::Texture2DArray: |
| 853 | glTexStorage3D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format, | 865 | glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level, |
| 854 | rect.GetWidth(), rect.GetHeight(), params.depth); | 866 | format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(), |
| 867 | params.depth); | ||
| 855 | break; | 868 | break; |
| 856 | default: | 869 | default: |
| 857 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", | 870 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", |
| 858 | static_cast<u32>(params.target)); | 871 | static_cast<u32>(params.target)); |
| 859 | UNREACHABLE(); | 872 | UNREACHABLE(); |
| 860 | glTexStorage2D(GL_TEXTURE_2D, 1, format_tuple.internal_format, rect.GetWidth(), | 873 | glTexStorage2D(GL_TEXTURE_2D, params.max_mip_level, format_tuple.internal_format, |
| 861 | rect.GetHeight()); | 874 | rect.GetWidth(), rect.GetHeight()); |
| 862 | } | 875 | } |
| 863 | } | 876 | } |
| 864 | 877 | ||
| 865 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 878 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 879 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
| 866 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 880 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 867 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 881 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 882 | glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, | ||
| 883 | params.max_mip_level - 1); | ||
| 884 | if (params.max_mip_level == 1) { | ||
| 885 | glTexParameterf(SurfaceTargetToGL(params.target), GL_TEXTURE_LOD_BIAS, 1000.0); | ||
| 886 | } | ||
| 868 | 887 | ||
| 869 | LabelGLObject(GL_TEXTURE, texture.handle, params.addr, | 888 | LabelGLObject(GL_TEXTURE, texture.handle, params.addr, |
| 870 | SurfaceParams::SurfaceTargetName(params.target)); | 889 | SurfaceParams::SurfaceTargetName(params.target)); |
| @@ -993,20 +1012,22 @@ static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelForm | |||
| 993 | MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192)); | 1012 | MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192)); |
| 994 | void CachedSurface::LoadGLBuffer() { | 1013 | void CachedSurface::LoadGLBuffer() { |
| 995 | MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); | 1014 | MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); |
| 996 | 1015 | gl_buffer.resize(params.max_mip_level); | |
| 997 | gl_buffer.resize(params.size_in_bytes_gl); | 1016 | for (u32 i = 0; i < params.max_mip_level; i++) |
| 1017 | gl_buffer[i].resize(params.GetMipmapSizeGL(i)); | ||
| 998 | if (params.is_tiled) { | 1018 | if (params.is_tiled) { |
| 999 | ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}", | 1019 | ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}", |
| 1000 | params.block_width, static_cast<u32>(params.target)); | 1020 | params.block_width, static_cast<u32>(params.target)); |
| 1001 | 1021 | for (u32 i = 0; i < params.max_mip_level; i++) | |
| 1002 | SwizzleFunc(morton_to_gl_fns, params, gl_buffer); | 1022 | SwizzleFunc(morton_to_gl_fns, params, gl_buffer[i], i); |
| 1003 | } else { | 1023 | } else { |
| 1004 | const auto texture_src_data{Memory::GetPointer(params.addr)}; | 1024 | const auto texture_src_data{Memory::GetPointer(params.addr)}; |
| 1005 | const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl}; | 1025 | const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl}; |
| 1006 | gl_buffer.assign(texture_src_data, texture_src_data_end); | 1026 | gl_buffer[0].assign(texture_src_data, texture_src_data_end); |
| 1007 | } | 1027 | } |
| 1008 | 1028 | for (u32 i = 0; i < params.max_mip_level; i++) | |
| 1009 | ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer, params.pixel_format, params.width, params.height); | 1029 | ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), |
| 1030 | params.MipHeight(i)); | ||
| 1010 | } | 1031 | } |
| 1011 | 1032 | ||
| 1012 | MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); | 1033 | MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); |
| @@ -1016,7 +1037,8 @@ void CachedSurface::FlushGLBuffer() { | |||
| 1016 | ASSERT_MSG(!IsPixelFormatASTC(params.pixel_format), "Unimplemented"); | 1037 | ASSERT_MSG(!IsPixelFormatASTC(params.pixel_format), "Unimplemented"); |
| 1017 | 1038 | ||
| 1018 | // OpenGL temporary buffer needs to be big enough to store raw texture size | 1039 | // OpenGL temporary buffer needs to be big enough to store raw texture size |
| 1019 | gl_buffer.resize(GetSizeInBytes()); | 1040 | gl_buffer.resize(1); |
| 1041 | gl_buffer[0].resize(GetSizeInBytes()); | ||
| 1020 | 1042 | ||
| 1021 | const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); | 1043 | const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); |
| 1022 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT | 1044 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT |
| @@ -1025,9 +1047,9 @@ void CachedSurface::FlushGLBuffer() { | |||
| 1025 | ASSERT(!tuple.compressed); | 1047 | ASSERT(!tuple.compressed); |
| 1026 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); | 1048 | glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); |
| 1027 | glGetTextureImage(texture.handle, 0, tuple.format, tuple.type, | 1049 | glGetTextureImage(texture.handle, 0, tuple.format, tuple.type, |
| 1028 | static_cast<GLsizei>(gl_buffer.size()), gl_buffer.data()); | 1050 | static_cast<GLsizei>(gl_buffer[0].size()), gl_buffer[0].data()); |
| 1029 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); | 1051 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); |
| 1030 | ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer, params.pixel_format, params.width, | 1052 | ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer[0], params.pixel_format, params.width, |
| 1031 | params.height); | 1053 | params.height); |
| 1032 | ASSERT(params.type != SurfaceType::Fill); | 1054 | ASSERT(params.type != SurfaceType::Fill); |
| 1033 | const u8* const texture_src_data = Memory::GetPointer(params.addr); | 1055 | const u8* const texture_src_data = Memory::GetPointer(params.addr); |
| @@ -1036,26 +1058,21 @@ void CachedSurface::FlushGLBuffer() { | |||
| 1036 | ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}", | 1058 | ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}", |
| 1037 | params.block_width, static_cast<u32>(params.target)); | 1059 | params.block_width, static_cast<u32>(params.target)); |
| 1038 | 1060 | ||
| 1039 | SwizzleFunc(gl_to_morton_fns, params, gl_buffer); | 1061 | SwizzleFunc(gl_to_morton_fns, params, gl_buffer[0], 0); |
| 1040 | } else { | 1062 | } else { |
| 1041 | std::memcpy(Memory::GetPointer(GetAddr()), gl_buffer.data(), GetSizeInBytes()); | 1063 | std::memcpy(Memory::GetPointer(GetAddr()), gl_buffer[0].data(), GetSizeInBytes()); |
| 1042 | } | 1064 | } |
| 1043 | } | 1065 | } |
| 1044 | 1066 | ||
| 1045 | MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192)); | 1067 | void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, |
| 1046 | void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) { | 1068 | GLuint draw_fb_handle) { |
| 1047 | if (params.type == SurfaceType::Fill) | 1069 | const auto& rect{params.GetRect(mip_map)}; |
| 1048 | return; | ||
| 1049 | |||
| 1050 | MICROPROFILE_SCOPE(OpenGL_TextureUL); | ||
| 1051 | |||
| 1052 | const auto& rect{params.GetRect()}; | ||
| 1053 | 1070 | ||
| 1054 | // Load data from memory to the surface | 1071 | // Load data from memory to the surface |
| 1055 | const GLint x0 = static_cast<GLint>(rect.left); | 1072 | const GLint x0 = static_cast<GLint>(rect.left); |
| 1056 | const GLint y0 = static_cast<GLint>(rect.bottom); | 1073 | const GLint y0 = static_cast<GLint>(rect.bottom); |
| 1057 | std::size_t buffer_offset = | 1074 | std::size_t buffer_offset = |
| 1058 | static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.width + | 1075 | static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) + |
| 1059 | static_cast<std::size_t>(x0)) * | 1076 | static_cast<std::size_t>(x0)) * |
| 1060 | SurfaceParams::GetBytesPerPixel(params.pixel_format); | 1077 | SurfaceParams::GetBytesPerPixel(params.pixel_format); |
| 1061 | 1078 | ||
| @@ -1073,88 +1090,117 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle | |||
| 1073 | cur_state.Apply(); | 1090 | cur_state.Apply(); |
| 1074 | 1091 | ||
| 1075 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT | 1092 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT |
| 1076 | ASSERT(params.width * SurfaceParams::GetBytesPerPixel(params.pixel_format) % 4 == 0); | 1093 | ASSERT(params.MipWidth(mip_map) * SurfaceParams::GetBytesPerPixel(params.pixel_format) % 4 == |
| 1077 | glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.width)); | 1094 | 0); |
| 1095 | glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map))); | ||
| 1078 | 1096 | ||
| 1097 | GLsizei image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false)); | ||
| 1079 | glActiveTexture(GL_TEXTURE0); | 1098 | glActiveTexture(GL_TEXTURE0); |
| 1080 | if (tuple.compressed) { | 1099 | if (tuple.compressed) { |
| 1081 | switch (params.target) { | 1100 | switch (params.target) { |
| 1082 | case SurfaceParams::SurfaceTarget::Texture2D: | 1101 | case SurfaceParams::SurfaceTarget::Texture2D: |
| 1083 | glCompressedTexImage2D( | 1102 | glCompressedTexImage2D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, |
| 1084 | SurfaceTargetToGL(params.target), 0, tuple.internal_format, | 1103 | static_cast<GLsizei>(params.MipWidth(mip_map)), |
| 1085 | static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height), 0, | 1104 | static_cast<GLsizei>(params.MipHeight(mip_map)), 0, image_size, |
| 1086 | static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[buffer_offset]); | 1105 | &gl_buffer[mip_map][buffer_offset]); |
| 1087 | break; | 1106 | break; |
| 1088 | case SurfaceParams::SurfaceTarget::Texture3D: | 1107 | case SurfaceParams::SurfaceTarget::Texture3D: |
| 1108 | glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, | ||
| 1109 | static_cast<GLsizei>(params.MipWidth(mip_map)), | ||
| 1110 | static_cast<GLsizei>(params.MipHeight(mip_map)), | ||
| 1111 | static_cast<GLsizei>(params.MipDepth(mip_map)), 0, image_size, | ||
| 1112 | &gl_buffer[mip_map][buffer_offset]); | ||
| 1113 | break; | ||
| 1089 | case SurfaceParams::SurfaceTarget::Texture2DArray: | 1114 | case SurfaceParams::SurfaceTarget::Texture2DArray: |
| 1090 | glCompressedTexImage3D( | 1115 | glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, |
| 1091 | SurfaceTargetToGL(params.target), 0, tuple.internal_format, | 1116 | static_cast<GLsizei>(params.MipWidth(mip_map)), |
| 1092 | static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height), | 1117 | static_cast<GLsizei>(params.MipHeight(mip_map)), |
| 1093 | static_cast<GLsizei>(params.depth), 0, | 1118 | static_cast<GLsizei>(params.depth), 0, image_size, |
| 1094 | static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[buffer_offset]); | 1119 | &gl_buffer[mip_map][buffer_offset]); |
| 1095 | break; | 1120 | break; |
| 1096 | case SurfaceParams::SurfaceTarget::TextureCubemap: | 1121 | case SurfaceParams::SurfaceTarget::TextureCubemap: { |
| 1122 | GLsizei layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); | ||
| 1097 | for (std::size_t face = 0; face < params.depth; ++face) { | 1123 | for (std::size_t face = 0; face < params.depth; ++face) { |
| 1098 | glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), | 1124 | glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), |
| 1099 | 0, tuple.internal_format, static_cast<GLsizei>(params.width), | 1125 | mip_map, tuple.internal_format, |
| 1100 | static_cast<GLsizei>(params.height), 0, | 1126 | static_cast<GLsizei>(params.MipWidth(mip_map)), |
| 1101 | static_cast<GLsizei>(params.SizeInBytesCubeFaceGL()), | 1127 | static_cast<GLsizei>(params.MipHeight(mip_map)), 0, |
| 1102 | &gl_buffer[buffer_offset]); | 1128 | layer_size, &gl_buffer[mip_map][buffer_offset]); |
| 1103 | buffer_offset += params.SizeInBytesCubeFace(); | 1129 | buffer_offset += layer_size; |
| 1104 | } | 1130 | } |
| 1105 | break; | 1131 | break; |
| 1132 | } | ||
| 1106 | default: | 1133 | default: |
| 1107 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", | 1134 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", |
| 1108 | static_cast<u32>(params.target)); | 1135 | static_cast<u32>(params.target)); |
| 1109 | UNREACHABLE(); | 1136 | UNREACHABLE(); |
| 1110 | glCompressedTexImage2D( | 1137 | glCompressedTexImage2D(GL_TEXTURE_2D, mip_map, tuple.internal_format, |
| 1111 | GL_TEXTURE_2D, 0, tuple.internal_format, static_cast<GLsizei>(params.width), | 1138 | static_cast<GLsizei>(params.MipWidth(mip_map)), |
| 1112 | static_cast<GLsizei>(params.height), 0, | 1139 | static_cast<GLsizei>(params.MipHeight(mip_map)), 0, |
| 1113 | static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[buffer_offset]); | 1140 | static_cast<GLsizei>(params.size_in_bytes_gl), |
| 1141 | &gl_buffer[mip_map][buffer_offset]); | ||
| 1114 | } | 1142 | } |
| 1115 | } else { | 1143 | } else { |
| 1116 | 1144 | ||
| 1117 | switch (params.target) { | 1145 | switch (params.target) { |
| 1118 | case SurfaceParams::SurfaceTarget::Texture1D: | 1146 | case SurfaceParams::SurfaceTarget::Texture1D: |
| 1119 | glTexSubImage1D(SurfaceTargetToGL(params.target), 0, x0, | 1147 | glTexSubImage1D(SurfaceTargetToGL(params.target), mip_map, x0, |
| 1120 | static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type, | 1148 | static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type, |
| 1121 | &gl_buffer[buffer_offset]); | 1149 | &gl_buffer[mip_map][buffer_offset]); |
| 1122 | break; | 1150 | break; |
| 1123 | case SurfaceParams::SurfaceTarget::Texture2D: | 1151 | case SurfaceParams::SurfaceTarget::Texture2D: |
| 1124 | glTexSubImage2D(SurfaceTargetToGL(params.target), 0, x0, y0, | 1152 | glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0, |
| 1125 | static_cast<GLsizei>(rect.GetWidth()), | 1153 | static_cast<GLsizei>(rect.GetWidth()), |
| 1126 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, | 1154 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, |
| 1127 | &gl_buffer[buffer_offset]); | 1155 | &gl_buffer[mip_map][buffer_offset]); |
| 1128 | break; | 1156 | break; |
| 1129 | case SurfaceParams::SurfaceTarget::Texture3D: | 1157 | case SurfaceParams::SurfaceTarget::Texture3D: |
| 1158 | glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, | ||
| 1159 | static_cast<GLsizei>(rect.GetWidth()), | ||
| 1160 | static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map), | ||
| 1161 | tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); | ||
| 1162 | break; | ||
| 1130 | case SurfaceParams::SurfaceTarget::Texture2DArray: | 1163 | case SurfaceParams::SurfaceTarget::Texture2DArray: |
| 1131 | glTexSubImage3D(SurfaceTargetToGL(params.target), 0, x0, y0, 0, | 1164 | glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, |
| 1132 | static_cast<GLsizei>(rect.GetWidth()), | 1165 | static_cast<GLsizei>(rect.GetWidth()), |
| 1133 | static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, | 1166 | static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, |
| 1134 | tuple.type, &gl_buffer[buffer_offset]); | 1167 | tuple.type, &gl_buffer[mip_map][buffer_offset]); |
| 1135 | break; | 1168 | break; |
| 1136 | case SurfaceParams::SurfaceTarget::TextureCubemap: | 1169 | case SurfaceParams::SurfaceTarget::TextureCubemap: { |
| 1170 | std::size_t start = buffer_offset; | ||
| 1137 | for (std::size_t face = 0; face < params.depth; ++face) { | 1171 | for (std::size_t face = 0; face < params.depth; ++face) { |
| 1138 | glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), 0, x0, | 1172 | glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map, |
| 1139 | y0, static_cast<GLsizei>(rect.GetWidth()), | 1173 | x0, y0, static_cast<GLsizei>(rect.GetWidth()), |
| 1140 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, | 1174 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, |
| 1141 | &gl_buffer[buffer_offset]); | 1175 | &gl_buffer[mip_map][buffer_offset]); |
| 1142 | buffer_offset += params.SizeInBytesCubeFace(); | 1176 | buffer_offset += params.LayerSizeGL(mip_map); |
| 1143 | } | 1177 | } |
| 1144 | break; | 1178 | break; |
| 1179 | } | ||
| 1145 | default: | 1180 | default: |
| 1146 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", | 1181 | LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", |
| 1147 | static_cast<u32>(params.target)); | 1182 | static_cast<u32>(params.target)); |
| 1148 | UNREACHABLE(); | 1183 | UNREACHABLE(); |
| 1149 | glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()), | 1184 | glTexSubImage2D(GL_TEXTURE_2D, mip_map, x0, y0, static_cast<GLsizei>(rect.GetWidth()), |
| 1150 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, | 1185 | static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, |
| 1151 | &gl_buffer[buffer_offset]); | 1186 | &gl_buffer[mip_map][buffer_offset]); |
| 1152 | } | 1187 | } |
| 1153 | } | 1188 | } |
| 1154 | 1189 | ||
| 1155 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | 1190 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
| 1156 | } | 1191 | } |
| 1157 | 1192 | ||
| 1193 | MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192)); | ||
| 1194 | void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) { | ||
| 1195 | if (params.type == SurfaceType::Fill) | ||
| 1196 | return; | ||
| 1197 | |||
| 1198 | MICROPROFILE_SCOPE(OpenGL_TextureUL); | ||
| 1199 | |||
| 1200 | for (u32 i = 0; i < params.max_mip_level; i++) | ||
| 1201 | UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle); | ||
| 1202 | } | ||
| 1203 | |||
| 1158 | RasterizerCacheOpenGL::RasterizerCacheOpenGL() { | 1204 | RasterizerCacheOpenGL::RasterizerCacheOpenGL() { |
| 1159 | read_framebuffer.Create(); | 1205 | read_framebuffer.Create(); |
| 1160 | draw_framebuffer.Create(); | 1206 | draw_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 6a49880c2..e72f4f2d2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -834,7 +834,7 @@ struct SurfaceParams { | |||
| 834 | } | 834 | } |
| 835 | 835 | ||
| 836 | /// Returns the rectangle corresponding to this surface | 836 | /// Returns the rectangle corresponding to this surface |
| 837 | MathUtil::Rectangle<u32> GetRect() const; | 837 | MathUtil::Rectangle<u32> GetRect(u32 mip_level = 0) const; |
| 838 | 838 | ||
| 839 | /// Returns the total size of this surface in bytes, adjusted for compression | 839 | /// Returns the total size of this surface in bytes, adjusted for compression |
| 840 | std::size_t SizeInBytesRaw(bool ignore_tiled = false) const { | 840 | std::size_t SizeInBytesRaw(bool ignore_tiled = false) const { |
| @@ -865,7 +865,7 @@ struct SurfaceParams { | |||
| 865 | 865 | ||
| 866 | /// Returns the exact size of memory occupied by the texture in VRAM, including mipmaps. | 866 | /// Returns the exact size of memory occupied by the texture in VRAM, including mipmaps. |
| 867 | std::size_t MemorySize() const { | 867 | std::size_t MemorySize() const { |
| 868 | std::size_t size = InnerMemorySize(is_layered); | 868 | std::size_t size = InnerMemorySize(false, is_layered); |
| 869 | if (is_layered) | 869 | if (is_layered) |
| 870 | return size * depth; | 870 | return size * depth; |
| 871 | return size; | 871 | return size; |
| @@ -874,12 +874,78 @@ struct SurfaceParams { | |||
| 874 | /// Returns the exact size of the memory occupied by a layer in a texture in VRAM, including | 874 | /// Returns the exact size of the memory occupied by a layer in a texture in VRAM, including |
| 875 | /// mipmaps. | 875 | /// mipmaps. |
| 876 | std::size_t LayerMemorySize() const { | 876 | std::size_t LayerMemorySize() const { |
| 877 | return InnerMemorySize(true); | 877 | return InnerMemorySize(false, true); |
| 878 | } | 878 | } |
| 879 | 879 | ||
| 880 | /// Returns the size of a layer of this surface in OpenGL. | 880 | /// Returns the size of a layer of this surface in OpenGL. |
| 881 | std::size_t LayerSizeGL() const { | 881 | std::size_t LayerSizeGL(u32 mip_level) const { |
| 882 | return SizeInBytesRaw(true) / depth; | 882 | return InnerMipmapMemorySize(mip_level, true, is_layered, false); |
| 883 | } | ||
| 884 | |||
| 885 | std::size_t GetMipmapSizeGL(u32 mip_level, bool ignore_compressed = true) const { | ||
| 886 | std::size_t size = InnerMipmapMemorySize(mip_level, true, is_layered, ignore_compressed); | ||
| 887 | if (is_layered) | ||
| 888 | return size * depth; | ||
| 889 | return size; | ||
| 890 | } | ||
| 891 | |||
| 892 | std::size_t GetMipmapLevelOffset(u32 mip_level) const { | ||
| 893 | std::size_t offset = 0; | ||
| 894 | for (u32 i = 0; i < mip_level; i++) | ||
| 895 | offset += InnerMipmapMemorySize(i, false, is_layered); | ||
| 896 | return offset; | ||
| 897 | } | ||
| 898 | |||
| 899 | std::size_t GetMipmapLevelOffsetGL(u32 mip_level) const { | ||
| 900 | std::size_t offset = 0; | ||
| 901 | for (u32 i = 0; i < mip_level; i++) | ||
| 902 | offset += InnerMipmapMemorySize(i, true, is_layered); | ||
| 903 | return offset; | ||
| 904 | } | ||
| 905 | |||
| 906 | u32 MipWidth(u32 mip_level) const { | ||
| 907 | return std::max(1U, width >> mip_level); | ||
| 908 | } | ||
| 909 | |||
| 910 | u32 MipHeight(u32 mip_level) const { | ||
| 911 | return std::max(1U, height >> mip_level); | ||
| 912 | } | ||
| 913 | |||
| 914 | u32 MipDepth(u32 mip_level) const { | ||
| 915 | return std::max(1U, depth >> mip_level); | ||
| 916 | } | ||
| 917 | |||
| 918 | // Auto block resizing algorithm from: | ||
| 919 | // https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c | ||
| 920 | u32 MipBlockHeight(u32 mip_level) const { | ||
| 921 | if (mip_level == 0) | ||
| 922 | return block_height; | ||
| 923 | u32 alt_height = MipHeight(mip_level); | ||
| 924 | u32 h = GetDefaultBlockHeight(pixel_format); | ||
| 925 | u32 blocks_in_y = (alt_height + h - 1) / h; | ||
| 926 | u32 bh = 16; | ||
| 927 | while (bh > 1 && blocks_in_y <= bh * 4) { | ||
| 928 | bh >>= 1; | ||
| 929 | } | ||
| 930 | return bh; | ||
| 931 | } | ||
| 932 | |||
| 933 | u32 MipBlockDepth(u32 mip_level) const { | ||
| 934 | if (mip_level == 0) | ||
| 935 | return block_depth; | ||
| 936 | if (is_layered) | ||
| 937 | return 1; | ||
| 938 | u32 depth = MipDepth(mip_level); | ||
| 939 | u32 bd = 32; | ||
| 940 | while (bd > 1 && depth * 2 <= bd) { | ||
| 941 | bd >>= 1; | ||
| 942 | } | ||
| 943 | if (bd == 32) { | ||
| 944 | u32 bh = MipBlockHeight(mip_level); | ||
| 945 | if (bh >= 4) | ||
| 946 | return 16; | ||
| 947 | } | ||
| 948 | return bd; | ||
| 883 | } | 949 | } |
| 884 | 950 | ||
| 885 | /// Creates SurfaceParams from a texture configuration | 951 | /// Creates SurfaceParams from a texture configuration |
| @@ -940,7 +1006,10 @@ struct SurfaceParams { | |||
| 940 | } rt; | 1006 | } rt; |
| 941 | 1007 | ||
| 942 | private: | 1008 | private: |
| 943 | std::size_t InnerMemorySize(bool layer_only = false) const; | 1009 | std::size_t InnerMipmapMemorySize(u32 mip_level, bool force_gl = false, bool layer_only = false, |
| 1010 | bool uncompressed = false) const; | ||
| 1011 | std::size_t InnerMemorySize(bool force_gl = false, bool layer_only = false, | ||
| 1012 | bool uncompressed = false) const; | ||
| 944 | }; | 1013 | }; |
| 945 | 1014 | ||
| 946 | }; // namespace OpenGL | 1015 | }; // namespace OpenGL |
| @@ -1002,8 +1071,10 @@ public: | |||
| 1002 | void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); | 1071 | void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); |
| 1003 | 1072 | ||
| 1004 | private: | 1073 | private: |
| 1074 | void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle); | ||
| 1075 | |||
| 1005 | OGLTexture texture; | 1076 | OGLTexture texture; |
| 1006 | std::vector<u8> gl_buffer; | 1077 | std::vector<std::vector<u8>> gl_buffer; |
| 1007 | SurfaceParams params; | 1078 | SurfaceParams params; |
| 1008 | GLenum gl_target; | 1079 | GLenum gl_target; |
| 1009 | std::size_t cached_size_in_bytes; | 1080 | std::size_t cached_size_in_bytes; |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 0f6dcab2b..87d511c38 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -135,12 +135,29 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) { | |||
| 135 | return {}; | 135 | return {}; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode) { | 138 | inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode, |
| 139 | Tegra::Texture::TextureMipmapFilter mip_filter_mode) { | ||
| 139 | switch (filter_mode) { | 140 | switch (filter_mode) { |
| 140 | case Tegra::Texture::TextureFilter::Linear: | 141 | case Tegra::Texture::TextureFilter::Linear: { |
| 141 | return GL_LINEAR; | 142 | switch (mip_filter_mode) { |
| 142 | case Tegra::Texture::TextureFilter::Nearest: | 143 | case Tegra::Texture::TextureMipmapFilter::None: |
| 143 | return GL_NEAREST; | 144 | return GL_LINEAR; |
| 145 | case Tegra::Texture::TextureMipmapFilter::Nearest: | ||
| 146 | return GL_NEAREST_MIPMAP_LINEAR; | ||
| 147 | case Tegra::Texture::TextureMipmapFilter::Linear: | ||
| 148 | return GL_LINEAR_MIPMAP_LINEAR; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | case Tegra::Texture::TextureFilter::Nearest: { | ||
| 152 | switch (mip_filter_mode) { | ||
| 153 | case Tegra::Texture::TextureMipmapFilter::None: | ||
| 154 | return GL_NEAREST; | ||
| 155 | case Tegra::Texture::TextureMipmapFilter::Nearest: | ||
| 156 | return GL_NEAREST_MIPMAP_NEAREST; | ||
| 157 | case Tegra::Texture::TextureMipmapFilter::Linear: | ||
| 158 | return GL_LINEAR_MIPMAP_NEAREST; | ||
| 159 | } | ||
| 160 | } | ||
| 144 | } | 161 | } |
| 145 | LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}", | 162 | LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}", |
| 146 | static_cast<u32>(filter_mode)); | 163 | static_cast<u32>(filter_mode)); |
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h index 4726f54a5..b390219e4 100644 --- a/src/video_core/textures/decoders.h +++ b/src/video_core/textures/decoders.h | |||
| @@ -10,6 +10,12 @@ | |||
| 10 | 10 | ||
| 11 | namespace Tegra::Texture { | 11 | namespace Tegra::Texture { |
| 12 | 12 | ||
| 13 | // GOBSize constant. Calculated by 64 bytes in x multiplied by 8 y coords, represents | ||
| 14 | // an small rect of (64/bytes_per_pixel)X8. | ||
| 15 | inline std::size_t GetGOBSize() { | ||
| 16 | return 512; | ||
| 17 | } | ||
| 18 | |||
| 13 | /** | 19 | /** |
| 14 | * Unswizzles a swizzled texture without changing its format. | 20 | * Unswizzles a swizzled texture without changing its format. |
| 15 | */ | 21 | */ |