citra-emu
/
citra
Archived
1
0
Fork 0

video_core: Add debug scopes (#6634)

This commit is contained in:
GPUCode 2023-06-23 04:37:13 +03:00 committed by GitHub
parent 89663e0db8
commit 7616496456
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 3 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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();

View File

@ -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

View File

@ -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>;