mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	gl_rasterizer_cache: cache texture cube
This commit is contained in:
		
							parent
							
								
									b443eea540
								
							
						
					
					
						commit
						1762ad2dcc
					
				
					 4 changed files with 226 additions and 84 deletions
				
			
		|  | @ -44,7 +44,6 @@ RasterizerOpenGL::RasterizerOpenGL() | ||||||
|     // Create cubemap texture and sampler objects
 |     // Create cubemap texture and sampler objects
 | ||||||
|     texture_cube_sampler.Create(); |     texture_cube_sampler.Create(); | ||||||
|     state.texture_cube_unit.sampler = texture_cube_sampler.sampler.handle; |     state.texture_cube_unit.sampler = texture_cube_sampler.sampler.handle; | ||||||
|     texture_cube.Create(); |  | ||||||
| 
 | 
 | ||||||
|     // Generate VBO, VAO and UBO
 |     // Generate VBO, VAO and UBO
 | ||||||
|     vertex_array.Create(); |     vertex_array.Create(); | ||||||
|  | @ -392,19 +391,18 @@ void RasterizerOpenGL::DrawTriangles() { | ||||||
|                 switch (texture.config.type.Value()) { |                 switch (texture.config.type.Value()) { | ||||||
|                 case TextureType::TextureCube: |                 case TextureType::TextureCube: | ||||||
|                     using CubeFace = Pica::TexturingRegs::CubeFace; |                     using CubeFace = Pica::TexturingRegs::CubeFace; | ||||||
|                     if (res_cache.FillTextureCube( |                     TextureCubeConfig config; | ||||||
|                             texture_cube.handle, texture, |                     config.px = regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveX); | ||||||
|                             regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveX), |                     config.nx = regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeX); | ||||||
|                             regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeX), |                     config.py = regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveY); | ||||||
|                             regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveY), |                     config.ny = regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeY); | ||||||
|                             regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeY), |                     config.pz = regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveZ); | ||||||
|                             regs.texturing.GetCubePhysicalAddress(CubeFace::PositiveZ), |                     config.nz = regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeZ); | ||||||
|                             regs.texturing.GetCubePhysicalAddress(CubeFace::NegativeZ))) { |                     config.width = texture.config.width; | ||||||
|                         state.texture_cube_unit.texture_cube = texture_cube.handle; |                     config.format = texture.format; | ||||||
|                     } else { |                     state.texture_cube_unit.texture_cube = | ||||||
|                         // Can occur when texture addr is null or its memory is unmapped/invalid
 |                         res_cache.GetTextureCube(config).texture.handle; | ||||||
|                         state.texture_cube_unit.texture_cube = 0; | 
 | ||||||
|                     } |  | ||||||
|                     texture_cube_sampler.SyncWithConfig(texture.config); |                     texture_cube_sampler.SyncWithConfig(texture.config); | ||||||
|                     state.texture_units[texture_index].texture_2d = 0; |                     state.texture_units[texture_index].texture_2d = 0; | ||||||
|                     continue; // Texture unit 0 setup finished. Continue to next unit
 |                     continue; // Texture unit 0 setup finished. Continue to next unit
 | ||||||
|  |  | ||||||
|  | @ -244,8 +244,6 @@ private: | ||||||
|     OGLBuffer uniform_buffer; |     OGLBuffer uniform_buffer; | ||||||
|     OGLFramebuffer framebuffer; |     OGLFramebuffer framebuffer; | ||||||
| 
 | 
 | ||||||
|     // TODO (wwylele): consider caching texture cube in the rasterizer cache
 |  | ||||||
|     OGLTexture texture_cube; |  | ||||||
|     SamplerInfo texture_cube_sampler; |     SamplerInfo texture_cube_sampler; | ||||||
| 
 | 
 | ||||||
|     OGLBuffer lighting_lut_buffer; |     OGLBuffer lighting_lut_buffer; | ||||||
|  |  | ||||||
|  | @ -28,7 +28,6 @@ | ||||||
| #include "video_core/pica_state.h" | #include "video_core/pica_state.h" | ||||||
| #include "video_core/renderer_opengl/gl_rasterizer_cache.h" | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" | ||||||
| #include "video_core/renderer_opengl/gl_state.h" | #include "video_core/renderer_opengl/gl_state.h" | ||||||
| #include "video_core/texture/texture_decode.h" |  | ||||||
| #include "video_core/utils.h" | #include "video_core/utils.h" | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| 
 | 
 | ||||||
|  | @ -231,6 +230,32 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup | ||||||
|     cur_state.Apply(); |     cur_state.Apply(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void AllocateTextureCube(GLuint texture, const FormatTuple& format_tuple, u32 width) { | ||||||
|  |     OpenGLState cur_state = OpenGLState::GetCurState(); | ||||||
|  | 
 | ||||||
|  |     // Keep track of previous texture bindings
 | ||||||
|  |     GLuint old_tex = cur_state.texture_cube_unit.texture_cube; | ||||||
|  |     cur_state.texture_cube_unit.texture_cube = texture; | ||||||
|  |     cur_state.Apply(); | ||||||
|  |     glActiveTexture(TextureUnits::TextureCube.Enum()); | ||||||
|  | 
 | ||||||
|  |     for (auto faces : { | ||||||
|  |              GL_TEXTURE_CUBE_MAP_POSITIVE_X, | ||||||
|  |              GL_TEXTURE_CUBE_MAP_POSITIVE_Y, | ||||||
|  |              GL_TEXTURE_CUBE_MAP_POSITIVE_Z, | ||||||
|  |              GL_TEXTURE_CUBE_MAP_NEGATIVE_X, | ||||||
|  |              GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, | ||||||
|  |              GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, | ||||||
|  |          }) { | ||||||
|  |         glTexImage2D(faces, 0, format_tuple.internal_format, width, width, 0, format_tuple.format, | ||||||
|  |                      format_tuple.type, nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Restore previous texture bindings
 | ||||||
|  |     cur_state.texture_cube_unit.texture_cube = old_tex; | ||||||
|  |     cur_state.Apply(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex, | static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex, | ||||||
|                          const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type, |                          const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type, | ||||||
|                          GLuint read_fb_handle, GLuint draw_fb_handle) { |                          GLuint read_fb_handle, GLuint draw_fb_handle) { | ||||||
|  | @ -761,6 +786,8 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint | ||||||
|         BlitTextures(unscaled_tex.handle, {0, rect.GetHeight(), rect.GetWidth(), 0}, texture.handle, |         BlitTextures(unscaled_tex.handle, {0, rect.GetHeight(), rect.GetWidth(), 0}, texture.handle, | ||||||
|                      scaled_rect, type, read_fb_handle, draw_fb_handle); |                      scaled_rect, type, read_fb_handle, draw_fb_handle); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     InvalidateAllWatcher(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MICROPROFILE_DEFINE(OpenGL_TextureDL, "OpenGL", "Texture Download", MP_RGB(128, 192, 64)); | MICROPROFILE_DEFINE(OpenGL_TextureDL, "OpenGL", "Texture Download", MP_RGB(128, 192, 64)); | ||||||
|  | @ -1193,14 +1220,13 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Surface RasterizerCacheOpenGL::GetTextureSurface( | Surface RasterizerCacheOpenGL::GetTextureSurface( | ||||||
|     const Pica::TexturingRegs::FullTextureConfig& config, PAddr addr_override) { |     const Pica::TexturingRegs::FullTextureConfig& config) { | ||||||
|     Pica::Texture::TextureInfo info = |     Pica::Texture::TextureInfo info = | ||||||
|         Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format); |         Pica::Texture::TextureInfo::FromPicaRegister(config.config, config.format); | ||||||
| 
 |     return GetTextureSurface(info); | ||||||
|     if (addr_override != 0) { |  | ||||||
|         info.physical_address = addr_override; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::Texture::TextureInfo& info) { | ||||||
|     SurfaceParams params; |     SurfaceParams params; | ||||||
|     params.addr = info.physical_address; |     params.addr = info.physical_address; | ||||||
|     params.width = info.width; |     params.width = info.width; | ||||||
|  | @ -1228,80 +1254,94 @@ Surface RasterizerCacheOpenGL::GetTextureSurface( | ||||||
|     return GetSurface(params, ScaleMatch::Ignore, true); |     return GetSurface(params, ScaleMatch::Ignore, true); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool RasterizerCacheOpenGL::FillTextureCube(GLuint dest_handle, | const CachedTextureCube& RasterizerCacheOpenGL::GetTextureCube(const TextureCubeConfig& config) { | ||||||
|                                             const Pica::TexturingRegs::FullTextureConfig& config, |     auto& cube = texture_cube_cache[config]; | ||||||
|                                             PAddr px, PAddr nx, PAddr py, PAddr ny, PAddr pz, | 
 | ||||||
|                                             PAddr nz) { |     struct Face { | ||||||
|     ASSERT(config.config.width == config.config.height); |         Face(std::shared_ptr<SurfaceWatcher>& watcher, PAddr address, GLenum gl_face) | ||||||
|     struct FaceTuple { |             : watcher(watcher), address(address), gl_face(gl_face) {} | ||||||
|  |         std::shared_ptr<SurfaceWatcher>& watcher; | ||||||
|         PAddr address; |         PAddr address; | ||||||
|         GLenum gl_face; |         GLenum gl_face; | ||||||
|         Surface surface; |  | ||||||
|     }; |     }; | ||||||
|     std::array<FaceTuple, 6> faces{{ | 
 | ||||||
|         {px, GL_TEXTURE_CUBE_MAP_POSITIVE_X}, |     const std::array<Face, 6> faces{{ | ||||||
|         {nx, GL_TEXTURE_CUBE_MAP_NEGATIVE_X}, |         {cube.px, config.px, GL_TEXTURE_CUBE_MAP_POSITIVE_X}, | ||||||
|         {py, GL_TEXTURE_CUBE_MAP_POSITIVE_Y}, |         {cube.nx, config.nx, GL_TEXTURE_CUBE_MAP_NEGATIVE_X}, | ||||||
|         {ny, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y}, |         {cube.py, config.py, GL_TEXTURE_CUBE_MAP_POSITIVE_Y}, | ||||||
|         {pz, GL_TEXTURE_CUBE_MAP_POSITIVE_Z}, |         {cube.ny, config.ny, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y}, | ||||||
|         {nz, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}, |         {cube.pz, config.pz, GL_TEXTURE_CUBE_MAP_POSITIVE_Z}, | ||||||
|  |         {cube.nz, config.nz, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}, | ||||||
|     }}; |     }}; | ||||||
| 
 | 
 | ||||||
|     u16 res_scale = 1; |     for (const Face& face : faces) { | ||||||
|     for (auto& face : faces) { |         if (!face.watcher || !face.watcher->Get()) { | ||||||
|         face.surface = GetTextureSurface(config, face.address); |             Pica::Texture::TextureInfo info; | ||||||
|         if (face.surface == nullptr) |             info.physical_address = face.address; | ||||||
|             return false; |             info.height = info.width = config.width; | ||||||
|         res_scale = std::max(res_scale, face.surface->res_scale); |             info.format = config.format; | ||||||
|  |             info.SetDefaultStride(); | ||||||
|  |             auto surface = GetTextureSurface(info); | ||||||
|  |             if (surface) { | ||||||
|  |                 face.watcher = surface->CreateWatcher(); | ||||||
|  |             } else { | ||||||
|  |                 // Can occur when texture address is invalid. We mark the watcher with nullptr in
 | ||||||
|  |                 // this case and the content of the face wouldn't get updated. These are usually
 | ||||||
|  |                 // leftover setup in the texture unit and games are not supposed to draw using them.
 | ||||||
|  |                 face.watcher = nullptr; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     u32 scaled_size = res_scale * config.config.width; |     if (cube.texture.handle == 0) { | ||||||
|  |         for (const Face& face : faces) { | ||||||
|  |             if (face.watcher) { | ||||||
|  |                 auto surface = face.watcher->Get(); | ||||||
|  |                 cube.res_scale = std::max(cube.res_scale, surface->res_scale); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         cube.texture.Create(); | ||||||
|  |         AllocateTextureCube( | ||||||
|  |             cube.texture.handle, | ||||||
|  |             GetFormatTuple(CachedSurface::PixelFormatFromTextureFormat(config.format)), | ||||||
|  |             cube.res_scale * config.width); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     u32 scaled_size = cube.res_scale * config.width; | ||||||
| 
 | 
 | ||||||
|     OpenGLState state = OpenGLState::GetCurState(); |     OpenGLState state = OpenGLState::GetCurState(); | ||||||
| 
 | 
 | ||||||
|     OpenGLState prev_state = state; |     OpenGLState prev_state = state; | ||||||
|     SCOPE_EXIT({ prev_state.Apply(); }); |     SCOPE_EXIT({ prev_state.Apply(); }); | ||||||
| 
 | 
 | ||||||
|     state.texture_cube_unit.texture_cube = dest_handle; |  | ||||||
|     state.Apply(); |  | ||||||
|     glActiveTexture(TextureUnits::TextureCube.Enum()); |  | ||||||
|     FormatTuple format_tuple = GetFormatTuple(faces[0].surface->pixel_format); |  | ||||||
| 
 |  | ||||||
|     GLint cur_size, cur_format; |  | ||||||
|     glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_TEXTURE_WIDTH, &cur_size); |  | ||||||
|     glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_TEXTURE_INTERNAL_FORMAT, |  | ||||||
|                              &cur_format); |  | ||||||
| 
 |  | ||||||
|     if (cur_size != scaled_size || cur_format != format_tuple.internal_format) { |  | ||||||
|         for (auto& face : faces) { |  | ||||||
|             glTexImage2D(face.gl_face, 0, format_tuple.internal_format, scaled_size, scaled_size, 0, |  | ||||||
|                          format_tuple.format, format_tuple.type, nullptr); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     state.draw.read_framebuffer = read_framebuffer.handle; |     state.draw.read_framebuffer = read_framebuffer.handle; | ||||||
|     state.draw.draw_framebuffer = draw_framebuffer.handle; |     state.draw.draw_framebuffer = draw_framebuffer.handle; | ||||||
|     state.ResetTexture(dest_handle); |     state.ResetTexture(cube.texture.handle); | ||||||
| 
 | 
 | ||||||
|     for (auto& face : faces) { |     for (const Face& face : faces) { | ||||||
|         state.ResetTexture(face.surface->texture.handle); |         if (face.watcher && !face.watcher->IsValid()) { | ||||||
|  |             auto surface = face.watcher->Get(); | ||||||
|  |             state.ResetTexture(surface->texture.handle); | ||||||
|             state.Apply(); |             state.Apply(); | ||||||
|             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, |             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | ||||||
|                                face.surface->texture.handle, 0); |                                    surface->texture.handle, 0); | ||||||
|         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, |             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||||||
|                                0); |                                    0, 0); | ||||||
| 
 | 
 | ||||||
|         glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, face.gl_face, dest_handle, |             glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, face.gl_face, | ||||||
|                                0); |                                    cube.texture.handle, 0); | ||||||
|         glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, |             glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||||||
|                                0); |                                    0, 0); | ||||||
| 
 | 
 | ||||||
|         auto src_rect = face.surface->GetScaledRect(); |             auto src_rect = surface->GetScaledRect(); | ||||||
|             glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, 0, 0, |             glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, 0, 0, | ||||||
|                               scaled_size, scaled_size, GL_COLOR_BUFFER_BIT, GL_LINEAR); |                               scaled_size, scaled_size, GL_COLOR_BUFFER_BIT, GL_LINEAR); | ||||||
|  |             face.watcher->Validate(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return true; |     return cube; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | ||||||
|  | @ -1316,6 +1356,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( | ||||||
|         FlushAll(); |         FlushAll(); | ||||||
|         while (!surface_cache.empty()) |         while (!surface_cache.empty()) | ||||||
|             UnregisterSurface(*surface_cache.begin()->second.begin()); |             UnregisterSurface(*surface_cache.begin()->second.begin()); | ||||||
|  |         texture_cube_cache.clear(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MathUtil::Rectangle<u32> viewport_clamped{ |     MathUtil::Rectangle<u32> viewport_clamped{ | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <array> | #include <array> | ||||||
|  | #include <list> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <set> | #include <set> | ||||||
| #include <tuple> | #include <tuple> | ||||||
|  | @ -17,6 +18,8 @@ | ||||||
| #ifdef __GNUC__ | #ifdef __GNUC__ | ||||||
| #pragma GCC diagnostic pop | #pragma GCC diagnostic pop | ||||||
| #endif | #endif | ||||||
|  | #include <unordered_map> | ||||||
|  | #include <boost/functional/hash.hpp> | ||||||
| #include <glad/glad.h> | #include <glad/glad.h> | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
|  | @ -26,6 +29,7 @@ | ||||||
| #include "video_core/regs_framebuffer.h" | #include "video_core/regs_framebuffer.h" | ||||||
| #include "video_core/regs_texturing.h" | #include "video_core/regs_texturing.h" | ||||||
| #include "video_core/renderer_opengl/gl_resource_manager.h" | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||||||
|  | #include "video_core/texture/texture_decode.h" | ||||||
| 
 | 
 | ||||||
| struct CachedSurface; | struct CachedSurface; | ||||||
| using Surface = std::shared_ptr<CachedSurface>; | using Surface = std::shared_ptr<CachedSurface>; | ||||||
|  | @ -253,7 +257,41 @@ struct SurfaceParams { | ||||||
|     SurfaceType type = SurfaceType::Invalid; |     SurfaceType type = SurfaceType::Invalid; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct CachedSurface : SurfaceParams { | /**
 | ||||||
|  |  * A watcher that notifies whether a cached surface has been changed. This is useful for caching | ||||||
|  |  * surface collection objects, including texture cube and mipmap. | ||||||
|  |  */ | ||||||
|  | struct SurfaceWatcher { | ||||||
|  | public: | ||||||
|  |     explicit SurfaceWatcher(std::weak_ptr<CachedSurface>&& surface) : surface(std::move(surface)) {} | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Checks whether the surface has been changed. | ||||||
|  |      * @return false if the surface content has been changed since last Validate() call or has been | ||||||
|  |      * destroyed; otherwise true | ||||||
|  |      */ | ||||||
|  |     bool IsValid() const { | ||||||
|  |         return !surface.expired() && valid; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Marks that the content of the referencing surface has been updated to the watcher user.
 | ||||||
|  |     void Validate() { | ||||||
|  |         ASSERT(!surface.expired()); | ||||||
|  |         valid = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// Gets the referencing surface. Returns null if the surface has been destroyed
 | ||||||
|  |     Surface Get() const { | ||||||
|  |         return surface.lock(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     friend struct CachedSurface; | ||||||
|  |     std::weak_ptr<CachedSurface> surface; | ||||||
|  |     bool valid = false; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct CachedSurface : SurfaceParams, std::enable_shared_from_this<CachedSurface> { | ||||||
|     bool CanFill(const SurfaceParams& dest_surface, SurfaceInterval fill_interval) const; |     bool CanFill(const SurfaceParams& dest_surface, SurfaceInterval fill_interval) const; | ||||||
|     bool CanCopy(const SurfaceParams& dest_surface, SurfaceInterval copy_interval) const; |     bool CanCopy(const SurfaceParams& dest_surface, SurfaceInterval copy_interval) const; | ||||||
| 
 | 
 | ||||||
|  | @ -294,6 +332,72 @@ struct CachedSurface : SurfaceParams { | ||||||
|                          GLuint draw_fb_handle); |                          GLuint draw_fb_handle); | ||||||
|     void DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, |     void DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, | ||||||
|                            GLuint draw_fb_handle); |                            GLuint draw_fb_handle); | ||||||
|  | 
 | ||||||
|  |     std::shared_ptr<SurfaceWatcher> CreateWatcher() { | ||||||
|  |         auto watcher = std::make_shared<SurfaceWatcher>(weak_from_this()); | ||||||
|  |         watchers.push_front(watcher); | ||||||
|  |         return watcher; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void InvalidateAllWatcher() { | ||||||
|  |         for (const auto& watcher : watchers) { | ||||||
|  |             if (auto locked = watcher.lock()) { | ||||||
|  |                 locked->valid = false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     std::list<std::weak_ptr<SurfaceWatcher>> watchers; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct TextureCubeConfig { | ||||||
|  |     PAddr px; | ||||||
|  |     PAddr nx; | ||||||
|  |     PAddr py; | ||||||
|  |     PAddr ny; | ||||||
|  |     PAddr pz; | ||||||
|  |     PAddr nz; | ||||||
|  |     u32 width; | ||||||
|  |     Pica::TexturingRegs::TextureFormat format; | ||||||
|  | 
 | ||||||
|  |     bool operator==(const TextureCubeConfig& rhs) const { | ||||||
|  |         return std::tie(px, nx, py, ny, pz, nz, width, format) == | ||||||
|  |                std::tie(rhs.px, rhs.nx, rhs.py, rhs.ny, rhs.pz, rhs.nz, rhs.width, rhs.format); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool operator!=(const TextureCubeConfig& rhs) const { | ||||||
|  |         return !(*this == rhs); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | namespace std { | ||||||
|  | template <> | ||||||
|  | struct hash<TextureCubeConfig> { | ||||||
|  |     size_t operator()(const TextureCubeConfig& config) const { | ||||||
|  |         std::size_t hash = 0; | ||||||
|  |         boost::hash_combine(hash, config.px); | ||||||
|  |         boost::hash_combine(hash, config.nx); | ||||||
|  |         boost::hash_combine(hash, config.py); | ||||||
|  |         boost::hash_combine(hash, config.ny); | ||||||
|  |         boost::hash_combine(hash, config.pz); | ||||||
|  |         boost::hash_combine(hash, config.nz); | ||||||
|  |         boost::hash_combine(hash, config.width); | ||||||
|  |         boost::hash_combine(hash, static_cast<u32>(config.format)); | ||||||
|  |         return hash; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | } // namespace std
 | ||||||
|  | 
 | ||||||
|  | struct CachedTextureCube { | ||||||
|  |     OGLTexture texture; | ||||||
|  |     u16 res_scale = 1; | ||||||
|  |     std::shared_ptr<SurfaceWatcher> px; | ||||||
|  |     std::shared_ptr<SurfaceWatcher> nx; | ||||||
|  |     std::shared_ptr<SurfaceWatcher> py; | ||||||
|  |     std::shared_ptr<SurfaceWatcher> ny; | ||||||
|  |     std::shared_ptr<SurfaceWatcher> pz; | ||||||
|  |     std::shared_ptr<SurfaceWatcher> nz; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class RasterizerCacheOpenGL : NonCopyable { | class RasterizerCacheOpenGL : NonCopyable { | ||||||
|  | @ -322,12 +426,11 @@ public: | ||||||
|                                         bool load_if_create); |                                         bool load_if_create); | ||||||
| 
 | 
 | ||||||
|     /// Get a surface based on the texture configuration
 |     /// Get a surface based on the texture configuration
 | ||||||
|     Surface GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config, |     Surface GetTextureSurface(const Pica::TexturingRegs::FullTextureConfig& config); | ||||||
|                               PAddr addr_override = 0); |     Surface GetTextureSurface(const Pica::Texture::TextureInfo& info); | ||||||
| 
 | 
 | ||||||
|     /// Copy surfaces to a cubemap texture based on the texture configuration
 |     /// Get a texture cube based on the texture configuration
 | ||||||
|     bool FillTextureCube(GLuint dest_handle, const Pica::TexturingRegs::FullTextureConfig& config, |     const CachedTextureCube& GetTextureCube(const TextureCubeConfig& config); | ||||||
|                          PAddr px, PAddr nx, PAddr py, PAddr ny, PAddr pz, PAddr nz); |  | ||||||
| 
 | 
 | ||||||
|     /// Get the color and depth surfaces based on the framebuffer configuration
 |     /// Get the color and depth surfaces based on the framebuffer configuration
 | ||||||
|     SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, |     SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, | ||||||
|  | @ -380,4 +483,6 @@ private: | ||||||
|     OGLProgram d24s8_abgr_shader; |     OGLProgram d24s8_abgr_shader; | ||||||
|     GLint d24s8_abgr_tbo_size_u_id; |     GLint d24s8_abgr_tbo_size_u_id; | ||||||
|     GLint d24s8_abgr_viewport_u_id; |     GLint d24s8_abgr_viewport_u_id; | ||||||
|  | 
 | ||||||
|  |     std::unordered_map<TextureCubeConfig, CachedTextureCube> texture_cube_cache; | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue