diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 32 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 7 |
2 files changed, 23 insertions, 16 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 4ba34ebc4..a1f541e75 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -62,12 +62,12 @@ static std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) { | |||
| 62 | } | 62 | } |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr) { | 65 | void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) { |
| 66 | auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()}; | 66 | auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()}; |
| 67 | const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)}; | 67 | const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)}; |
| 68 | const auto max_size{memory_manager.GetRegionEnd(gpu_addr) - gpu_addr}; | ||
| 69 | 68 | ||
| 70 | addr = cpu_addr ? *cpu_addr : 0; | 69 | addr = cpu_addr ? *cpu_addr : 0; |
| 70 | gpu_addr = gpu_addr_; | ||
| 71 | size_in_bytes = SizeInBytesRaw(); | 71 | size_in_bytes = SizeInBytesRaw(); |
| 72 | 72 | ||
| 73 | if (IsPixelFormatASTC(pixel_format)) { | 73 | if (IsPixelFormatASTC(pixel_format)) { |
| @@ -76,15 +76,6 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr) { | |||
| 76 | } else { | 76 | } else { |
| 77 | size_in_bytes_gl = SizeInBytesGL(); | 77 | size_in_bytes_gl = SizeInBytesGL(); |
| 78 | } | 78 | } |
| 79 | |||
| 80 | // Clamp size to mapped GPU memory region | ||
| 81 | // TODO(bunnei): Super Mario Odyssey maps a 0x40000 byte region and then uses it for a 0x80000 | ||
| 82 | // R32F render buffer. We do not yet know if this is a game bug or something else, but this | ||
| 83 | // check is necessary to prevent flushing from overwriting unmapped memory. | ||
| 84 | if (size_in_bytes > max_size) { | ||
| 85 | LOG_ERROR(HW_GPU, "Surface size {} exceeds region size {}", size_in_bytes, max_size); | ||
| 86 | size_in_bytes = max_size; | ||
| 87 | } | ||
| 88 | } | 79 | } |
| 89 | 80 | ||
| 90 | /*static*/ SurfaceParams SurfaceParams::CreateForTexture( | 81 | /*static*/ SurfaceParams SurfaceParams::CreateForTexture( |
| @@ -719,7 +710,8 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface, | |||
| 719 | } | 710 | } |
| 720 | 711 | ||
| 721 | CachedSurface::CachedSurface(const SurfaceParams& params) | 712 | CachedSurface::CachedSurface(const SurfaceParams& params) |
| 722 | : params(params), gl_target(SurfaceTargetToGL(params.target)) { | 713 | : params(params), gl_target(SurfaceTargetToGL(params.target)), |
| 714 | cached_size_in_bytes(params.size_in_bytes) { | ||
| 723 | texture.Create(); | 715 | texture.Create(); |
| 724 | const auto& rect{params.GetRect()}; | 716 | const auto& rect{params.GetRect()}; |
| 725 | 717 | ||
| @@ -769,6 +761,18 @@ CachedSurface::CachedSurface(const SurfaceParams& params) | |||
| 769 | 761 | ||
| 770 | VideoCore::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, | 762 | VideoCore::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, |
| 771 | SurfaceParams::SurfaceTargetName(params.target)); | 763 | SurfaceParams::SurfaceTargetName(params.target)); |
| 764 | |||
| 765 | // Clamp size to mapped GPU memory region | ||
| 766 | // TODO(bunnei): Super Mario Odyssey maps a 0x40000 byte region and then uses it for a 0x80000 | ||
| 767 | // R32F render buffer. We do not yet know if this is a game bug or something else, but this | ||
| 768 | // check is necessary to prevent flushing from overwriting unmapped memory. | ||
| 769 | |||
| 770 | auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()}; | ||
| 771 | const u64 max_size{memory_manager.GetRegionEnd(params.gpu_addr) - params.gpu_addr}; | ||
| 772 | if (cached_size_in_bytes > max_size) { | ||
| 773 | LOG_ERROR(HW_GPU, "Surface size {} exceeds region size {}", params.size_in_bytes, max_size); | ||
| 774 | cached_size_in_bytes = max_size; | ||
| 775 | } | ||
| 772 | } | 776 | } |
| 773 | 777 | ||
| 774 | static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height, bool reverse) { | 778 | static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height, bool reverse) { |
| @@ -912,7 +916,7 @@ void CachedSurface::FlushGLBuffer() { | |||
| 912 | ASSERT_MSG(!IsPixelFormatASTC(params.pixel_format), "Unimplemented"); | 916 | ASSERT_MSG(!IsPixelFormatASTC(params.pixel_format), "Unimplemented"); |
| 913 | 917 | ||
| 914 | // OpenGL temporary buffer needs to be big enough to store raw texture size | 918 | // OpenGL temporary buffer needs to be big enough to store raw texture size |
| 915 | gl_buffer.resize(params.size_in_bytes); | 919 | gl_buffer.resize(GetSizeInBytes()); |
| 916 | 920 | ||
| 917 | const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); | 921 | const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); |
| 918 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT | 922 | // Ensure no bad interactions with GL_UNPACK_ALIGNMENT |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 843f18cea..39fd7cd75 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h | |||
| @@ -783,6 +783,7 @@ struct SurfaceParams { | |||
| 783 | 783 | ||
| 784 | // Parameters used for caching | 784 | // Parameters used for caching |
| 785 | VAddr addr; | 785 | VAddr addr; |
| 786 | Tegra::GPUVAddr gpu_addr; | ||
| 786 | std::size_t size_in_bytes; | 787 | std::size_t size_in_bytes; |
| 787 | std::size_t size_in_bytes_gl; | 788 | std::size_t size_in_bytes_gl; |
| 788 | 789 | ||
| @@ -802,7 +803,8 @@ struct SurfaceReserveKey : Common::HashableStruct<OpenGL::SurfaceParams> { | |||
| 802 | static SurfaceReserveKey Create(const OpenGL::SurfaceParams& params) { | 803 | static SurfaceReserveKey Create(const OpenGL::SurfaceParams& params) { |
| 803 | SurfaceReserveKey res; | 804 | SurfaceReserveKey res; |
| 804 | res.state = params; | 805 | res.state = params; |
| 805 | res.state.rt = {}; // Ignore rt config in caching | 806 | res.state.gpu_addr = {}; // Ignore GPU vaddr in caching |
| 807 | res.state.rt = {}; // Ignore rt config in caching | ||
| 806 | return res; | 808 | return res; |
| 807 | } | 809 | } |
| 808 | }; | 810 | }; |
| @@ -826,7 +828,7 @@ public: | |||
| 826 | } | 828 | } |
| 827 | 829 | ||
| 828 | std::size_t GetSizeInBytes() const { | 830 | std::size_t GetSizeInBytes() const { |
| 829 | return params.size_in_bytes; | 831 | return cached_size_in_bytes; |
| 830 | } | 832 | } |
| 831 | 833 | ||
| 832 | void Flush() { | 834 | void Flush() { |
| @@ -865,6 +867,7 @@ private: | |||
| 865 | std::vector<u8> gl_buffer; | 867 | std::vector<u8> gl_buffer; |
| 866 | SurfaceParams params; | 868 | SurfaceParams params; |
| 867 | GLenum gl_target; | 869 | GLenum gl_target; |
| 870 | std::size_t cached_size_in_bytes; | ||
| 868 | bool dirty = false; | 871 | bool dirty = false; |
| 869 | }; | 872 | }; |
| 870 | 873 | ||