mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	video_core: Add debug scopes (#6634)
This commit is contained in:
		
							parent
							
								
									89663e0db8
								
							
						
					
					
						commit
						7616496456
					
				
					 6 changed files with 82 additions and 3 deletions
				
			
		|  | @ -116,6 +116,12 @@ struct Regs { | ||||||
|         inline u32 GetEndAddress() const { |         inline u32 GetEndAddress() const { | ||||||
|             return DecodeAddressRegister(address_end); |             return DecodeAddressRegister(address_end); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         inline std::string DebugName() const { | ||||||
|  |             return fmt::format("from {:#X} to {:#X} with {}-bit value {:#X}", GetStartAddress(), | ||||||
|  |                                GetEndAddress(), fill_32bit ? "32" : (fill_24bit ? "24" : "16"), | ||||||
|  |                                value_32bit); | ||||||
|  |         } | ||||||
|     } memory_fill_config[2]; |     } memory_fill_config[2]; | ||||||
|     ASSERT_MEMBER_SIZE(memory_fill_config[0], 0x10); |     ASSERT_MEMBER_SIZE(memory_fill_config[0], 0x10); | ||||||
| 
 | 
 | ||||||
|  | @ -176,6 +182,13 @@ struct Regs { | ||||||
|             return DecodeAddressRegister(output_address); |             return DecodeAddressRegister(output_address); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         inline std::string DebugName() const noexcept { | ||||||
|  |             return fmt::format("from {:#x} to {:#x} with {} scaling and stride {}, width {}", | ||||||
|  |                                GetPhysicalInputAddress(), GetPhysicalOutputAddress(), | ||||||
|  |                                scaling == NoScale ? "no" : (scaling == ScaleX ? "X" : "XY"), | ||||||
|  |                                input_width, output_width); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         union { |         union { | ||||||
|             u32 output_size; |             u32 output_size; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -95,6 +95,9 @@ void RasterizerCache<T>::TickFrame() { | ||||||
| 
 | 
 | ||||||
| template <class T> | template <class T> | ||||||
| bool RasterizerCache<T>::AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) { | bool RasterizerCache<T>::AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) { | ||||||
|  |     const DebugScope scope{runtime, Common::Vec4f{0.f, 0.f, 1.f, 1.f}, | ||||||
|  |                            "RasterizerCache::AccelerateTextureCopy ({})", config.DebugName()}; | ||||||
|  | 
 | ||||||
|     // Texture copy size is aligned to 16 byte units
 |     // Texture copy size is aligned to 16 byte units
 | ||||||
|     const u32 copy_size = Common::AlignDown(config.texture_copy.size, 16); |     const u32 copy_size = Common::AlignDown(config.texture_copy.size, 16); | ||||||
|     if (copy_size == 0) { |     if (copy_size == 0) { | ||||||
|  | @ -190,6 +193,9 @@ bool RasterizerCache<T>::AccelerateTextureCopy(const GPU::Regs::DisplayTransferC | ||||||
| 
 | 
 | ||||||
| template <class T> | template <class T> | ||||||
| bool RasterizerCache<T>::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) { | bool RasterizerCache<T>::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) { | ||||||
|  |     const DebugScope scope{runtime, Common::Vec4f{0.f, 0.f, 1.f, 1.f}, | ||||||
|  |                            "RasterizerCache::AccelerateDisplayTransfer ({})", config.DebugName()}; | ||||||
|  | 
 | ||||||
|     SurfaceParams src_params; |     SurfaceParams src_params; | ||||||
|     src_params.addr = config.GetPhysicalInputAddress(); |     src_params.addr = config.GetPhysicalInputAddress(); | ||||||
|     src_params.width = config.output_width; |     src_params.width = config.output_width; | ||||||
|  | @ -250,6 +256,9 @@ bool RasterizerCache<T>::AccelerateDisplayTransfer(const GPU::Regs::DisplayTrans | ||||||
| 
 | 
 | ||||||
| template <class T> | template <class T> | ||||||
| bool RasterizerCache<T>::AccelerateFill(const GPU::Regs::MemoryFillConfig& config) { | bool RasterizerCache<T>::AccelerateFill(const GPU::Regs::MemoryFillConfig& config) { | ||||||
|  |     const DebugScope scope{runtime, Common::Vec4f{1.f, 0.f, 1.f, 1.f}, | ||||||
|  |                            "RasterizerCache::AccelerateFill ({})", config.DebugName()}; | ||||||
|  | 
 | ||||||
|     SurfaceParams params; |     SurfaceParams params; | ||||||
|     params.addr = config.GetStartAddress(); |     params.addr = config.GetStartAddress(); | ||||||
|     params.end = config.GetEndAddress(); |     params.end = config.GetEndAddress(); | ||||||
|  | @ -924,11 +933,19 @@ void RasterizerCache<T>::ValidateSurface(SurfaceId surface_id, PAddr addr, u32 s | ||||||
| 
 | 
 | ||||||
|     SurfaceRegions validate_regions = surface.invalid_regions & validate_interval; |     SurfaceRegions validate_regions = surface.invalid_regions & validate_interval; | ||||||
| 
 | 
 | ||||||
|  |     if (validate_regions.empty()) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     auto notify_validated = [&](SurfaceInterval interval) { |     auto notify_validated = [&](SurfaceInterval interval) { | ||||||
|         surface.MarkValid(interval); |         surface.MarkValid(interval); | ||||||
|         validate_regions.erase(interval); |         validate_regions.erase(interval); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     const DebugScope scope{runtime, Common::Vec4f{0.f, 1.f, 0.f, 1.f}, | ||||||
|  |                            "RasterizerCache::ValidateSurface (from {:#x} to {:#x})", addr, | ||||||
|  |                            addr + size}; | ||||||
|  | 
 | ||||||
|     u32 level = surface.LevelOf(addr); |     u32 level = surface.LevelOf(addr); | ||||||
|     SurfaceInterval level_interval = surface.LevelInterval(level); |     SurfaceInterval level_interval = surface.LevelInterval(level); | ||||||
|     while (!validate_regions.empty()) { |     while (!validate_regions.empty()) { | ||||||
|  | @ -1213,19 +1230,34 @@ void RasterizerCache<T>::FlushRegion(PAddr addr, u32 size, SurfaceId flush_surfa | ||||||
|         // Small sizes imply that this most likely comes from the cpu, flush the entire region
 |         // Small sizes imply that this most likely comes from the cpu, flush the entire region
 | ||||||
|         // the point is to avoid thousands of small writes every frame if the cpu decides to
 |         // the point is to avoid thousands of small writes every frame if the cpu decides to
 | ||||||
|         // access that region, anything higher than 8 you're guaranteed it comes from a service
 |         // access that region, anything higher than 8 you're guaranteed it comes from a service
 | ||||||
|         const auto interval = size <= 8 ? region : region & flush_interval; |         auto interval = size <= 8 ? region : region & flush_interval; | ||||||
|         if (flush_surface_id && surface_id != flush_surface_id) { |         if (flush_surface_id && surface_id != flush_surface_id) { | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         const DebugScope scope{runtime, Common::Vec4f{0.f, 0.f, 0.f, 1.f}, | ||||||
|  |                                "RasterizerCache::FlushRegion (from {:#x} to {:#x})", | ||||||
|  |                                interval.lower(), interval.upper()}; | ||||||
|  | 
 | ||||||
|         // Sanity check, this surface is the last one that marked this region dirty
 |         // Sanity check, this surface is the last one that marked this region dirty
 | ||||||
|         Surface& surface = slot_surfaces[surface_id]; |         Surface& surface = slot_surfaces[surface_id]; | ||||||
|         ASSERT(surface.IsRegionValid(interval)); |         ASSERT(surface.IsRegionValid(interval)); | ||||||
| 
 | 
 | ||||||
|         if (surface.type == SurfaceType::Fill) { |         if (surface.type == SurfaceType::Fill) { | ||||||
|             DownloadFillSurface(surface, interval); |             DownloadFillSurface(surface, interval); | ||||||
|         } else { |             flushed_intervals += interval; | ||||||
|             DownloadSurface(surface, interval); |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Download each requested level of the surface.
 | ||||||
|  |         const u32 start_level = surface.LevelOf(interval.lower()); | ||||||
|  |         const u32 end_level = surface.LevelOf(interval.upper()); | ||||||
|  |         for (u32 level = start_level; level <= end_level; level++) { | ||||||
|  |             const auto download_interval = interval & surface.LevelInterval(level); | ||||||
|  |             if (boost::icl::is_empty(download_interval)) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             DownloadSurface(surface, download_interval); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         flushed_intervals += interval; |         flushed_intervals += interval; | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ class RasterizerCache { | ||||||
|     using Sampler = typename T::Sampler; |     using Sampler = typename T::Sampler; | ||||||
|     using Surface = typename T::Surface; |     using Surface = typename T::Surface; | ||||||
|     using Framebuffer = typename T::Framebuffer; |     using Framebuffer = typename T::Framebuffer; | ||||||
|  |     using DebugScope = typename T::DebugScope; | ||||||
| 
 | 
 | ||||||
|     using SurfaceMap = boost::icl::interval_map<PAddr, SurfaceId, boost::icl::partial_absorber, |     using SurfaceMap = boost::icl::interval_map<PAddr, SurfaceId, boost::icl::partial_absorber, | ||||||
|                                                 std::less, boost::icl::inplace_plus, |                                                 std::less, boost::icl::inplace_plus, | ||||||
|  |  | ||||||
|  | @ -765,6 +765,14 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     const DebugScope scope{runtime, | ||||||
|  |                            Common::Vec4f{0.f, 1.f, 1.f, 1.f}, | ||||||
|  |                            "RasterizerOpenGL::AccelerateDisplay ({}x{} {} at {:#X})", | ||||||
|  |                            src_params.width, | ||||||
|  |                            src_params.height, | ||||||
|  |                            VideoCore::PixelFormatAsString(src_params.pixel_format), | ||||||
|  |                            src_params.addr}; | ||||||
|  | 
 | ||||||
|     const Surface& src_surface = res_cache.GetSurface(src_surface_id); |     const Surface& src_surface = res_cache.GetSurface(src_surface_id); | ||||||
|     const u32 scaled_width = src_surface.GetScaledWidth(); |     const u32 scaled_width = src_surface.GetScaledWidth(); | ||||||
|     const u32 scaled_height = src_surface.GetScaledHeight(); |     const u32 scaled_height = src_surface.GetScaledHeight(); | ||||||
|  |  | ||||||
|  | @ -700,4 +700,14 @@ Sampler::Sampler(TextureRuntime&, VideoCore::SamplerParams params) { | ||||||
| 
 | 
 | ||||||
| Sampler::~Sampler() = default; | Sampler::~Sampler() = default; | ||||||
| 
 | 
 | ||||||
|  | DebugScope::DebugScope(TextureRuntime& runtime, Common::Vec4f, std::string_view label) | ||||||
|  |     : local_scope_depth{global_scope_depth++} { | ||||||
|  |     glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, local_scope_depth, label.size(), label.data()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DebugScope::~DebugScope() { | ||||||
|  |     glPopDebugGroup(); | ||||||
|  |     global_scope_depth--; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace OpenGL
 | } // namespace OpenGL
 | ||||||
|  |  | ||||||
|  | @ -230,11 +230,26 @@ private: | ||||||
|     OGLSampler sampler; |     OGLSampler sampler; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | class DebugScope { | ||||||
|  | public: | ||||||
|  |     template <typename... T> | ||||||
|  |     explicit DebugScope(TextureRuntime& runtime, Common::Vec4f color, | ||||||
|  |                         fmt::format_string<T...> format, T... args) | ||||||
|  |         : DebugScope{runtime, color, fmt::format(format, std::forward<T>(args)...)} {} | ||||||
|  |     explicit DebugScope(TextureRuntime& runtime, Common::Vec4f, std::string_view label); | ||||||
|  |     ~DebugScope(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     inline static GLuint global_scope_depth = 0; | ||||||
|  |     const GLuint local_scope_depth{}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Traits { | struct Traits { | ||||||
|     using Runtime = OpenGL::TextureRuntime; |     using Runtime = OpenGL::TextureRuntime; | ||||||
|     using Sampler = OpenGL::Sampler; |     using Sampler = OpenGL::Sampler; | ||||||
|     using Surface = OpenGL::Surface; |     using Surface = OpenGL::Surface; | ||||||
|     using Framebuffer = OpenGL::Framebuffer; |     using Framebuffer = OpenGL::Framebuffer; | ||||||
|  |     using DebugScope = OpenGL::DebugScope; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| using RasterizerCache = VideoCore::RasterizerCache<Traits>; | using RasterizerCache = VideoCore::RasterizerCache<Traits>; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue