mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-22 17:40:06 +00:00
video_core: Add debug scopes (#6634)
This commit is contained in:
parent
89663e0db8
commit
7616496456
@ -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…
Reference in New Issue
Block a user