在ps做网站分辨率96可以吗/电脑培训网上培训班

在ps做网站分辨率96可以吗,电脑培训网上培训班,公众号小程序注册,网站建设基本我们将在某个时候替换C标准库函数 今天我们要进行的工作是替换C标准库函数,这是因为目前我们仍然在使用C语言开发,并且在某些情况下会调用C标准库函数,例如一些数学函数和字符串格式化函数,尤其是在调试系统中,我们使…

我们将在某个时候替换C标准库函数

今天我们要进行的工作是替换C标准库函数,这是因为目前我们仍然在使用C语言开发,并且在某些情况下会调用C标准库函数,例如一些数学函数和字符串格式化函数,尤其是在调试系统中,我们使用字符串格式化来打印信息。我们的目标是逐步去除这些C标准库的依赖,最终实现“零库”的状态,即完全不依赖除操作系统外的任何外部库。

目前的挑战之一是我们在C语言开发中已经依赖了一些标准库函数,虽然这些功能对于开发很有帮助,但我们希望能够不依赖它们,逐步用自定义代码来替代。最初的目标是移除数学函数和字符串格式化这类功能。

今天的工作重点是继续处理历史调试数据,我们会通过调试系统来查看和操作这些数据,尝试让调试工作变得更加有用和高效。我们会进行一些基本的格式化工作,以便更好地显示调试信息。历史调试信息的处理将为我们在未来删除C运行时库函数做好准备。

在下周,我们的目标是开始替换掉C运行时库的相关功能,特别是数学函数(如正弦、余弦、正切等)和字符串格式化功能。由于我们的项目目前只依赖这些功能,其他C运行时库的内容并没有使用,所以替换起来相对简单。

今天的任务是继续使用当前的调试系统,准备好在接下来的时间里开始替换C标准库函数。这项工作虽然看似简单,但会使我们的代码更加纯粹和独立,不依赖任何外部的标准库。

回顾

在这里插入图片描述

我们现在加载了调试输出系统,可以看到目前的调试情况。通过之前的工作,我们已经能够在程序中插入一些循环计数器,这样就可以显示出程序的一些运行信息,例如地面块(ground chunks)何时被填充等。这些信息以前是无法得知的,现在通过这些调试代码,我们能够实时看到这些事件的发生。

目前的调试输出已经提供了一些我们之前不知道的信息,帮助我们更好地理解程序的运行过程。但如之前提到的,这些信息虽然有用,但使用起来仍然有些困难。它们虽然给了我们更多的视角,但我们希望能够获得更多、更直观的调试数据。

昨天的工作使我们能够跟踪这些信息随时间的变化,我们展示的并不是某一帧的单一数据,而是运行的平均值。这意味着我们正在朝着一个更加有意义、易于理解的调试界面迈进。虽然还有改进的空间,但这已经为我们提供了比之前更多的洞察力。

让我们以更有用的方式显示调试信息

接下来,我们计划进一步利用目前已经能够看到的值,尝试让这些数据变得更有用。为了实现这一点,可以考虑在显示中加入一些图表,帮助展示数据中的波动或突增。例如,可以绘制一些图形,显示不同指标的波动情况。这样做的目的是为了在已经完成存储数据和正确跟踪的基础上,进一步探索如何更有效地展示这些信息,让它们对我们更加有意义。

我们会继续努力,逐步改善展示方式,使得这些数据不仅能被记录下来,还能以一种更直观和易于理解的方式呈现出来。通过这种方式,能够帮助更好地分析和理解程序的表现。

将调试代码移动到game_debug.cpp

当前的调试系统已经建立了基础框架,并将相关代码放入了 game_debug.cpp 文件中,但目前仅仅是初步实现了一些信息输出功能。为了优化代码结构,需要进一步整理和调整,将部分代码从主程序文件中移出,以保持代码的清晰和模块化。

在现有代码中,debug_record_array_counter 是唯一需要在当前作用域中声明的变量,因此可以将其移动到更合适的位置,这样能够使代码更加整洁,并有助于代码的组织结构。接下来需要做的一步是确保 game_debug_out.cpp 文件被正确包含在项目中,这样就可以将所有的调试代码放入这个专门的调试文件中,而不会干扰主文件的逻辑,使得主文件不至于被调试代码弄得混乱不堪。

此外,现有的调试更新逻辑和绘制代码也应该拆分开来,绘制相关的代码应归类到调试部分中。这部分代码包括调试文本行的渲染、全局变量的管理等,而这些全局变量在调试系统中的作用是提供额外的可视化信息,帮助分析程序运行状况。为了进一步优化代码组织结构,需要将这些代码移至合适的调试模块中,以保持代码逻辑的清晰。

当前的调试信息输出仍然依赖于 C 运行时库(如 stdio.h 进行格式化字符串输出)。为了解决这一问题,可以考虑完全去除对 C 运行时库的依赖。如果目标是实现“零库”开发,那么即便是 C 语言自带的标准库也可以被移除。实际上,C 运行时库并不是强制性的,只是一个链接的库而已。可以在编译时通过特定的编译选项来禁用它,使得最终生成的程序不会依赖于它,这样可以进一步减少程序的外部依赖,使得程序更加轻量级,并具有更高的独立性。

这种做法的优势在于,它不仅符合无库开发的目标,同时也能使程序更加灵活,完全控制底层实现,而不会受到 C 标准库的约束。这与某些语言不同,在某些语言中,标准库可能是语言本身的一部分,无法彻底移除,而在 C 语言中,只要不调用标准库的函数,就可以完全去掉标准库的依赖。这种方式可以减少程序的额外开销,使得最终的程序更加精简、高效,并且避免了不必要的库加载,提高运行效率。

综上所述,当前的优化方向主要包括:

  1. 整理调试代码——将调试代码从主文件中拆分,放入 game_debug_out.cpp 以保持代码结构清晰。
  2. 拆分绘制逻辑——将调试绘制代码单独归类到调试模块,避免主程序逻辑与调试逻辑混杂。
  3. 去除 C 运行时库——未来计划彻底移除对 C 标准库的依赖,使程序真正做到零库开发,提高独立性和性能。

通过这些优化,调试系统将更加完善,代码结构也会更加清晰,最终使得整个程序的维护和扩展变得更加方便。

在这里插入图片描述

在这里插入图片描述

相关的调试代码移动到game_debug.cpp 中
保留

extern uint32 const DebugRecords_Main_Count = __COUNTER__;
debug_record DebugRecordArray[DebugRecords_Main_Count];

在这里插入图片描述

绘制计时器的值图表

当前的工作重点是创建一个能够随时间变化的平均值计算系统,并尝试将这些数据以图形化的方式呈现。已经实现了一个基础系统来计算这些值的平均变化情况,接下来的目标是绘制出一条反映实际数值变化的曲线或柱状图,以便更直观地观察数据走势。

目前尚未具备完善的工具来进行可视化处理,但可以尝试利用现有的渲染系统来实现基本的图形绘制。具体做法是将这些数据转换为一系列小矩形,并通过矩形的高度来表示对应函数在不同时间点的计算开销。这样一来,每次数据更新时,都能以图形化的方式直观地展现出函数的运行成本变化趋势。

计划中的图表绘制方式:

  1. 数据映射:将计算出的数值映射为可视化的高度,使得数据变化能以直观的方式展现出来。
  2. 渲染矩形:利用渲染系统绘制多个小矩形,并根据计算结果调整其高度,以反映不同时间点的数值情况。
  3. 时间维度:随着时间推进,持续更新图表,以便实时观察数据的动态变化。

目标是通过这种方式构建一个简易的性能监控工具,使得调试过程更加直观,提高分析效率。

同时显示上一帧未更新的计数器

在遍历所有计数器并处理快照索引时,希望能够保持所有计数器始终可见,而不是当某些计数器未被使用时它们就消失。因此,即使某个计数器的数值为零,也希望它仍然能够显示出来,以保持数据的稳定性,并能够观察到随时间变化的图表。

由于调试信息需要访问渲染系统,因此需要调整代码结构,使其能够正确访问资源管理系统,并确保所有调试计数器都能够正常显示。这样,即使某些计数器的值为零,它们依然会出现在调试界面上,从而形成稳定的图表,便于长期观察数据变化。

在实际绘制这些信息时,需要考虑如何以直观的方式展示数据。计划绘制的图表需要处理不同计数器的数值范围问题,因为不同计数器的最大值可能差异极大。例如:

  • 记录某个功能的总周期计数时,可能会产生一个极大的数值。
  • 轻量级函数的调用开销较小,与核心渲染例程相比,数据量级相差甚远。

因此,在绘图时需要处理不同计数器数据范围的差异,确保所有数据都能合理地在同一图表中显示,并提供一种标准化的方法,使不同数据类别之间的可视化效果保持一致。这样就可以有效地展示各个函数的性能开销,使调试更加直观和高效。
在这里插入图片描述

在这里插入图片描述

我们将选择一段时间内计时器的最大值,并用它来缩放图表

如果采用固定比例来绘制图表,可能无法很好地展现数据的变化,因此需要采用一种自适应的方法来调整比例。具体来说,可以利用当前计数器的最大周期数作为基准,在计算快照时获取该最大值,并用它来归一化所有数据点。

实现方式如下:

  1. 遍历快照,获取最大周期计数值
    在遍历快照数据后,就能得知当前计数器的最大周期计数值。

  2. 计算归一化比例
    由于已经知道最大周期计数值,因此可以对所有数据进行归一化,将其映射到 0 到 1 之间。例如:

    • 如果最大周期计数值不为 0,则当前计数值除以最大周期计数值,就能得到一个 0 到 1 之间的比例值。
  3. 映射到图表高度
    归一化后的值可以直接乘以图表的高度,将其映射到合适的显示区域:

    • 计算比例 scale = ChartHeight / CycleCount.Max
    • 然后将所有周期计数值乘以 scale,得到最终的绘制高度。

这样,每个数据点的高度都能在合理范围内变化,不会因为数值范围不同而导致显示失真。同时,这种方法还能动态适应不同数据规模的变化,使得图表更具可读性。

不过,这种方法可能会带来一些意料之外的情况,但可以先实现并观察实际效果,再决定是否需要进一步调整。例如,可能需要考虑如何处理异常值,或者是否需要对数据进行平滑处理,以获得更清晰的可视化效果。
在这里插入图片描述

为每个计数器绘制一个矩形

在进行缩放操作之后,我们已经得到了每个快照的周期计数对应的高度,这个高度将决定在图表中每个数据点的显示高度。接下来,我们需要绘制矩形来可视化这些数据。

具体实现思路

  1. 绘制矩形条形图

    • 我们希望为每个快照绘制一个矩形条,形成类似条形图的效果。
    • 通过 PushRect(或者类似的矩形绘制方法),我们可以在屏幕上绘制这些数据。
  2. 数据映射到像素级别

    • 采用 1 像素对应 1 个快照 的方式,即每个快照的数据用一个像素宽度的条来表示。
    • 由于快照数量是 120,因此最终绘制出的图像宽度将是 120 像素,形成一个紧凑的条形图。
  3. 渲染机制的选择

    • 目前已有的 DebugTextLine 机制用于调试文本渲染,我们可以借鉴其中的设计。
    • render_group 提供了绘制矩形的能力,因此我们可以直接向其中推送矩形数据,无需额外处理坐标转换,因为 render_group 已经使用了屏幕空间。
  4. 确保 render_group 可用

    • 在绘制数据前,必须先检查 render_group 是否可用,如果不存在 render_group,那么绘制操作就没有意义。
    • 通过这种方式,避免在无效的渲染环境中执行多余的绘制操作,提高运行效率。

总结

本次改进的关键在于:

  • 计算快照数据的最大值并归一化,使其适应图表高度。
  • 采用 1 像素宽度表示 1 个快照 的方式,形成条形图。
  • 直接使用 render_group 进行矩形绘制,避免不必要的中间处理步骤。
  • 事先检查 render_group 是否可用,以确保渲染操作的有效性。

这样,我们就能够以直观的方式呈现调试数据,使其更具可读性和实用性。
在这里插入图片描述

将矩形绘制在文本旁边,基准线对齐

在绘制调试信息时,我们希望在打印文本之后再绘制图表,这样可以确保文本先输出,然后紧接着绘制相关的可视化信息。但如果要让图表和文本对齐,存在一些问题:

文本与图表的对齐问题

  1. 文本行的自动换行影响对齐

    • 由于文本行会自动向下推进,因此如果直接在文本之后绘制图表,可能无法保证它与文本正确对齐。
    • 目前还没有一个完善的布局系统来管理文本和图表的相对位置,因此需要手动调整。
  2. 需要获取文本的基准线

    • 为了正确放置图表,需要知道文本的基准线(baseline)。
    • 具体来说,AtY 变量存储了当前文本行的 Y 轴位置,这个信息可以用来计算图表的放置位置。

图表高度计算

  • ChartHeight(图表高度)应该等于 一行文本的高度,这样可以让图表和文本保持一致的视觉比例。
  • chart_min_y(图表的最小 Y 值)应该等于 文本基准线 的位置,这样图表的底部对齐文本的底部,看起来更整齐。
  • chart_max_y 则可以通过 chart_min_y + chart_height 计算得到,确定图表的顶端。

调整顺序

  1. 提前计算文本基准线

    • 先计算 AtY,确定文本的基准线位置。
    • 这样可以预留出正确的空间,确保文本和图表能够正确对齐。
  2. 在绘制文本之前计算图表位置

    • 由于文本行会自动推进,我们需要 先确定图表的位置,然后再绘制文本。
    • 这样可以保证绘制的矩形条形图与相应的文本一一对应,而不会因为换行问题导致错位。
  3. 合理规划布局

    • 目前暂时使用手动对齐的方式,未来可能需要引入更完善的布局系统来自动调整文本和图表的相对位置。

总结

  • 由于文本行的自动推进特性,我们需要 提前计算文本基准线,确保图表正确对齐。
  • 图表的高度 (chart_height) 设定为 文本行的高度,保证视觉统一。
  • 图表的底部对齐文本基准线 (chart_min_y),使得数据与文本保持一致。
  • 在绘制文本之前 先确定图表位置,然后再绘制文本,以防止错位。
  • 目前是临时解决方案,未来可能需要引入 更完善的布局系统 来优化对齐问题。
    在这里插入图片描述

使用文本的升高作为图表的高度

在处理文本行的推进(line advance)时,直接使用 整行的推进量 可能并不是最合理的方式。原因在于,整行推进 指的是整个文本行的高度,但在当前需求下,可能更适合使用 字符的上伸部分(ascender height) 来确定图表的高度。

对比两种方案

  1. 整行推进(line advance)

    • 这个值表示整行文本的整体高度,包括了上伸(ascender)、基线(baseline)和下沉(descender)部分。
    • 如果直接用这个值作为图表高度,可能会导致图表比实际需要的区域更大,影响对齐效果。
  2. 上伸高度(ascender height)

    • 上伸高度 指的是从基线向上的部分,不包含字符的下沉部分(如 gy 这样的字母的下探部分)。
    • 这个值更加贴合实际可读的文本部分,与文本的视觉效果更匹配。
    • 因此,使用 上伸高度 作为 chart_height 可能更合理。

调整方案

  • ascender_height 设为图表的高度 chart_height,这样可以更精准地对齐文本和图表的显示区域。
  • 避免使用 line_advance 直接作为图表的高度,以防止图表尺寸过大或对齐出现问题。
  • 这种方式可以使得 图表与文本的视觉高度一致,在排版上更加整洁。

总结

  • 直接使用整行推进(line advance)可能会导致图表高度过大,不利于对齐。
  • 改为使用上伸高度(ascender height)作为 chart_height 更符合文本的视觉范围。
  • 这一调整有助于使图表更精准地匹配文本区域,避免显示不协调的问题。
    在这里插入图片描述

调试显示代码需要更简单的字体信息访问

当前的问题是 无法直接获取字体信息,这影响了调试信息的正确渲染,特别是在确定 ascender_height(上伸高度)以计算图表高度时。

主要问题

  1. 缺少字体信息
    • 现阶段 debug_text 机制 无法直接提供字体数据,导致 无法正确计算文本基线,进而影响图表对齐。
  • 现在可以在合适的位置获取 font 和 info,并用于计算 ascender_height,确保 正确调整图表高度
  • 需要进一步优化 调试 UI 系统,确保 所有调试信息的布局更加直观和高效
  • 未来可以通过 更精细的布局管理,减少调试 UI 的复杂度,使其更加灵活可扩展。
    在这里插入图片描述

使用计时器相对于其最大值的相对值来调节矩形的颜色

目前的目标是实现能够绘制图表的功能。具体来说,计划通过 推送矩形 来可视化调试数据,并通过调节颜色来展示不同的数值。接下来,详细描述以下步骤:

绘制矩形

  1. 绘制矩形
    目前有能力开始绘制矩形来表示每个数据快照(snapshot)。初步设计为使用 黄色 作为矩形的颜色,随着数值的变化,颜色将会变成不同的颜色,比如绿色表示最小值,黄色表示最大值,主要通过数值在颜色通道中设置。

  2. 比例计算

    • 通过一个数值计算,比例值会在 0 到 1 之间波动,表示该数值相对于最大值的大小。这个数值将决定矩形在图表中的 高度,以可视化每个样本的占比。
    • 这样,就能通过颜色渐变来展现数据的波动,比如最大值对应黄色,最小值对应绿色。
  3. 计算矩形的位置和尺寸
    为了确定每个矩形的绘制位置和尺寸:

    • Y 轴的高度是根据计算出的比例值来设置的。
    • X 轴的偏移量需要使用 图表的左边界ChartLeft)和 快照索引SnapshotIndex)来定位。
    • Y 轴的起始位置则基于 最小 Y 坐标ChartMinY)来确定。
    • 此外,还需要考虑矩形的 宽度高度,目前这个矩形的绘制可能需要对矩形绘制的 函数进行检查,以确保其正常工作。
  4. 暂时硬编码

    • 当前对于 ChartLeft 这个值并没有确切的定义,所以暂时 硬编码 该值,并使用默认值来开始。
    • 这样可以先简单实现图表功能,然后后续再优化布局系统。

图表布局与优化

  1. 初步工作

    • 目前的目标是使得图表功能能够正常工作,并能 绘制矩形 来表示每个数据点。通过这种方式,可以开始查看数据随时间变化的可视化效果。
  2. 布局问题

    • 布局 是一个待优化的方面,尤其是 文本图表 的配合问题。未来可以改进布局,使得 文本和图表更好地融合,并且能更加灵活地适配不同尺寸和位置。
  3. 进一步优化

    • 初期目标是能够 绘制矩形并显示数据,一旦这个过程可行,再考虑如何让不同的元素(文本、图表、颜色等) 协调工作,以优化最终的调试显示。

总结

通过硬编码当前的布局和计算,矩形绘制功能可以初步实现,展示数据随时间变化的可视化效果。后续将进一步优化图表布局和功能,尤其是在文本和图表的结合部分。
在这里插入图片描述

    if (CycleCount.Max > 0.0f) {real32 ChartLeft = 0.0f;real32 ChartMinY = AtY;real32 ChartHeight = Info->AscenderHeight * FontScale;real32 Scale = 1.0f / (real32)CycleCount.Max;for (uint32 SnapshotIndex = 0; SnapshotIndex < MAX_DEBUG_SNAPSHOT_COUNT;++SnapshotIndex) {// 【proportion】 n. 比例, 比率, 均衡, 部分, 面积 vt. 使成比例, 使均衡real32 ThisProportion =Scale * (real32)Counter->Snapshots[SnapshotIndex].CycleCount;real32 ThisHeight = ChartHeight * ThisProportion;PushRect(RenderGroup,v3{ChartLeft + (real32)SnapshotIndex, ChartMinY, 0.0f},v2{1.0f, ThisHeight}, v4{ThisProportion, 1, 0.0f, 1});}}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

测试到目前为止的代码。我们的心跳图与文本对不齐

目前遇到的问题是矩形绘制的位置和大小不完全对齐,主要是因为矩形的绘制函数是以矩形的 中心点 为基准,向外扩展的,这样会导致图表显示时,矩形的定位不完全准确。具体来说,矩形的实际位置并不完全符合预期,导致显示效果上有偏差。

解决方案:

虽然这种绘制方式在某些情况下是合适的,但在这里它并没有按预期对齐,可能需要对绘制函数进行调整,确保矩形的 左上角右下角 对齐到正确的位置。这个调整可以相对容易地实现。

  1. 矩形绘制问题

    • 当前绘制矩形时,它的基准点是 矩形的中心,这就导致了在显示图表时,矩形的位置没有准确对齐。
    • 对于需要精确对齐的图表来说,这个绘制方法可能不够理想,可能需要根据左上角的坐标来重新调整位置。
  2. 如何解决

    • 可以通过调整矩形绘制的函数,使得矩形的 位置和尺寸 能够更精确地与数据图表的坐标系匹配。
    • 这意味着可以在绘制时,使用 左上角右下角 来确定矩形的位置,而不是使用中心点。
  3. 快速修复

    • 这一问题的修复是比较简单的,只需要修改绘制函数的参数,使其能够正确地将矩形对齐到所需位置即可。

总结来说,目前遇到的问题是由于矩形绘制基于中心点而导致的不对齐,但通过简单的修复,可以解决这个问题,使得矩形的绘制更加符合图表的实际需求。

使计时器图表与文本居中

假设矩形是以 中心点 为基准绘制的,那么为了让矩形正确显示,需要对矩形的位置进行调整。具体来说,需要将矩形的 纵坐标(y轴)上偏移一半的高度,这样矩形的 底部 就能对齐到期望的位置。

解决方案:

  1. 矩形偏移

    • 由于当前矩形是以 中心点 为基准绘制的,矩形的 底部 会比预期位置低。为了让矩形的 底部 对齐正确的 基准线,需要将其 向上偏移 以补偿这个偏差。具体来说,需要将矩形的 纵坐标(y轴) 减去矩形高度的一半,使得矩形正确对齐。
  2. 结果效果

    • 通过这个偏移调整后,矩形的显示效果会像一个 标准的条形图,并且矩形的 底部 将更好地对齐于预期的 基准线
    • 这样一来,矩形图形的对齐会更加准确,避免了之前的错位。
  3. 验证和确认

    • 为了确保调整生效,可以通过 可视化检查 来确认矩形的位置是否正确对齐,或者使用一些工具进行对比(例如使用标尺来进行精确检查)。

最终,经过这样的调整后,矩形的绘制效果更接近预期,图形看起来像一个 正常的条形图,并且与相关的 基准线 对齐更加准确。
在这里插入图片描述

在这里插入图片描述

计时器图表的自动缩放并不完美,但目前没有立即的解决方法

现在,我们已经可以在侧边绘制一个小图表了。但是,接下来会有很多需要讨论的内容,其中一个明显的问题是,这些图表的 比例会发生变化。图表比例之所以变化,是因为它们使用的是过去 一百二十帧 的最大值来确定比例。

主要问题:

  1. 比例变化的原因

    • 图表的比例会基于过去 一百二十帧 内的 最大值 来设置。如果某一时刻发生了 性能瓶颈(比如操作系统在那时占用了一些时间),图表的比例就会重置。这会导致图表在性能瓶颈期间的显示变得不稳定。
    • 一旦性能瓶颈 过去,图表的比例又会恢复正常,这种变化会带来 图表跳动 的现象,即比例的变化很突兀。
  2. 处理性能瓶颈的难题

    • 目前,图表会基于最近的 最大值 来重置比例,造成图表的不稳定。为了更好地展示这些数据,可能需要考虑 过滤异常值,比如去除掉性能瓶颈带来的影响,或者使用 平均值 来平滑图表。
    • 但是,即使采取这种方法,问题依旧存在:因为比例会变化,无法直接比较不同图表之间的 性能表现。比如,不能轻易判断 图表 A图表 B 中哪一个更慢,因为它们的比例不同。
  3. 数据展示的局限性

    • 目前这种图表展示的方式,并不完美,可能不是 最理想的可视化方法。虽然图表能够显示调试数据并且随着时间的推移展示出来,但由于图表比例的跳动,很难清晰地比较不同时间段的性能。

结论:

尽管这种方法可能不是最理想的可视化方式,但它至少能做到 记录并展示调试数据。通过这种方式,能够看到性能数据随时间的变化,尽管存在 比例变化带来的不稳定性,但至少可以获取到一定的有用信息。

调整图表大小

可以考虑将每个条形图的宽度设置为一个固定值,比如 4个像素。这样做的目的是为图表提供足够的空间,使得每个条形图的宽度不会过小,便于查看。具体来说,可以通过设置一个 条形宽度 参数来控制每个条形图的宽度。

实现过程:

  1. 计算位置

    • 每个条形图的位置可以通过 快照索引 乘以 条形宽度 来计算,这样每个条形图就会根据其位置在图表上依次排列。
    • 为了使条形图能够对齐,可以在计算时 减去条形宽度的一半,这样可以确保条形图是以其中心为基准对齐的。
  2. 条形宽度

    • 设置条形图的宽度为 4像素 或者其他合适的值,可以使得条形图更加 粗一些,这样也许更容易看到图表中的波动和变化。
    • 使用这种方式,可以清晰地看到 心跳(性能的波动)以及 性能峰值,即在某些时刻系统的性能出现了明显的波动。
  3. 性能波动

    • 通过这种图表展示方式,能够明显看到 性能峰值,这些波动在图表中呈现为突然上升的部分,比较容易识别出异常。
    • 这些 性能波动 可能与某些操作系统进程的干扰有关,比如后台程序(如 OBS 等)占用了部分资源,导致的性能问题。

观察与挑战:

  • 即使可以看到明显的性能波动,实际原因还不容易追踪。可能这些波动并非源于代码本身的效率问题,而是由于系统后台任务的影响。具体原因还需要进一步调查。
  • 所以,虽然图表能显示出明显的性能变化,但要准确找到性能波动的具体原因,需要对 性能瓶颈 进行更详细的分析和跟踪。

在这里插入图片描述

在这里插入图片描述

一些性能计数器从未被触发,它们显示为“null”。我们不会绘制这些

现在,想要从更整体的角度来审视当前的实现。首先需要注意的是,性能计数器的“节点”只有在函数被调用时才会有记录,因此如果某个函数从未被调用过,那么它的性能计数器就不会被触发。在这样的情况下,图表上是不会显示这些函数的信息的,直到它们被调用一次为止。

当前的工作流程:

  1. 性能计数器的工作原理:性能计数器仅在相关的代码被执行时才会记录数据。因此,如果函数从未被调用过,它的性能数据就不会出现在图表中。
  2. 实现的设计:为了让系统更易于调试,代码设计时仅在函数执行时插入性能计数器的相关代码。因此,无法在未调用的函数上看到任何性能数据。

解决方案:

为了能够准确反映那些未被调用但存在的函数,我们可以在绘制调试信息时做一些额外的判断。具体方法是:

  • 在渲染时,可以通过检查性能计数器,确保只有那些至少被调用过一次的函数才会被显示在图表中。这样,未被调用过的函数不会占用图表空间,而已调用的函数才会显示其性能数据。

在这里插入图片描述

在这里插入图片描述

我们将把平台层debug_frame_end_info的时间戳保存为快照,并将它们作为堆叠图显示

接下来,目标是创建一个堆叠图,用来展示每一帧中各个部分所消耗的时间,并且以更具比例性的方式展示这些数据。为了实现这一点,首先需要在现有的系统中进行一些修改。

关键步骤:

  1. 数据采集:在之前的工作中,已经有了一个类似“快照”的功能,这个功能记录了多个时间点的数据,比如输入处理的时间、游戏更新的时间、自动绘制的时间、帧率完成的时间等等。现在的目标是将这些时间数据保存为独立的快照。

  2. 修改框架结构

    • game_debug.h文件中,创建一个新的数据结构,用来存储每一帧的相关信息。这个数据结构将保存每一帧的时间快照。
    • 每当执行到帧的结束并且进行调试更新时,保存一份该帧的数据快照。
      在这里插入图片描述
  3. 帧信息存储:这些时间快照将会包含每一帧的各个时间点(例如输入时间、更新完成时间等),并通过独立的快照方式进行存储,以便后续使用。这样可以确保每帧的数据被独立记录,便于后续绘制堆叠图。

通过这种方式,每一帧的性能数据将被完整记录,并为生成堆叠图提供所需的数据。这些堆叠图将帮助更直观地查看和分析每一帧内各个环节的时间占比,进一步优化性能分析过程。
在这里插入图片描述

game_debug.cpp一些调整

接下来的目标是对现有的调试系统进行一些调整和重构。当前的思路是将调试功能的部分移动到game_debug的底部,或者将相关的代码提取到一个单独的文件中,以便更好地组织和管理。

主要操作:

  1. 代码重构

    • 将需要的代码移到头文件中,以便在其他地方调用。这包括一些全局变量以及调试重置功能等。
    • 某些变量和函数不需要放在game_debug文件中,可能需要重新整理和组织,特别是全局变量。
    • DEBUGReset 函数有可能需要在某个特定时刻(例如在帧更新或某个周期结束时)被调用,而不仅仅是在当前的地方。这部分可能在未来需要进一步优化。
  2. 命名优化

    • 一些变量的命名需要调整,例如将“OverlayCycleCounters”更改为更符合其实际功能的名字,比如DebugOverlay。这样命名更加清晰,表明它是一个调试覆盖层的操作。
    • 通过修改这些命名和结构,可以使得代码更加清晰、易于管理,同时也为后续的调试功能扩展提供了基础。
  3. 调试覆盖层

    • DebugOverlay将承担所有调试覆盖层的工作,包括显示调试信息和图表等。原本的“OverlayCycleCountersr”功能被重命名为DebugOverlay,并通过这个新的函数进行管理。

总结:

通过对现有代码进行重构和命名优化,调试系统变得更加模块化、易于管理。现在的目标是将这些调整实施,并在后续进一步优化和扩展调试功能,以便更好地进行性能监测和分析。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

捕获debug_frame_end_info快照

为了更好地捕捉和显示调试信息,首先需要保存调试信息并捕获快照。在debug overlay中,首先将当前的调试状态保存为一个快照。具体步骤是通过将获取的调试信息传入debug frame,然后将其与snapshot进行绑定,从而创建一组快照数据。接下来,在显示所有的计数器信息之后,可以通过这些快照数据进行绘制。

关键步骤:

  1. 捕获快照

    • debug overlay中,将当前的调试信息(debug state)捕捉并存储为一个快照。这个快照包含了当前帧的信息,后续可以用来绘制图形或进行分析。
    • 将这个快照与当前的调试信息关联,方便后续展示和分析。
  2. 绘制调试信息

    • 在所有计数器信息显示之后,可以添加代码来绘制从快照中提取的调试信息。
    • 由于这些调试信息包含多个部分,因此在绘制时需要对信息进行合理的拆分和组织。
  3. 改进绘制方式

    • 为了让显示更清晰,可以考虑对每个快照的信息进行进一步的处理,使得每个信息块更加易于理解和查看。

通过这些步骤,能够有效地捕获并显示调试信息,帮助更好地进行性能分析和调试。同时,改进绘制方式也能提升视觉效果,使得调试过程更加直观易懂。
在这里插入图片描述

debug_frame_end_info字段的顺序是特定于平台层的,不应该改变

这个想法很有趣,之前也有考虑过类似的问题。如果查看debug_frame_end_info(调试框架中的信息捕捉点),会发现这些调试信息的捕获和处理方式是依赖于平台的,特别是与特定平台层(例如Windows平台)的顺序和步骤密切相关。这个顺序和步骤的安排非常特定于该平台,意味着如果更换其他平台,可能会因为平台的不同处理顺序或步骤而导致问题。这种做法并不理想,因为它强依赖于某个平台的特定实现方式。

从抽象的角度来看,这样的设计并不合适,因为它将平台的特定实现细节直接暴露在调试框架中,这使得系统变得不够灵活,难以适应不同平台的需求。因此,需要重新考虑如何抽象出这些调试捕捉点,使其能够更加通用,不依赖于特定平台的实现。

将单个debug_frame_end_info计数器转换为一个自描述的debug_frame_timestamps数组

考虑到当前的方法,可能更好的做法是将调试帧信息设计成类似一个“调试帧时间戳”的结构。这个结构会包含时间戳的名称以及该时间戳对应的时钟值(以秒为单位)。这样,传递这些信息时,就可以明确知道时间戳的数量,并能够追踪每个时间戳的具体信息。

可以通过类似于“debug_frame_timestamps”的方式来定义这个结构,其中包含一个时间戳计数,表示有多少个时间戳数据。为了避免过多复杂性,也可以考虑在结构体中嵌套时间戳的信息,或许可以使用数组来存储这些时间戳。由于时间戳的数量有限,也可以选择固定大小的数组来存储它们,而不必担心内存开销问题。

此外,这个数据结构可以通过指针或结构体传递,具体方式可以根据实际需求灵活调整。总之,时间戳的信息存储和传递应该尽量简单有效,未来也可以根据需要进行调整和优化。
在这里插入图片描述

现在我们可以遍历所有平台时间戳,并将它们绘制为一组堆叠条形图

如果按照这种方式设计,那么可以将每个时间戳的数据显示为堆叠的条形图。这些条形图可以反映每个时间戳所占的时间比例,并且在调试帧的时间戳信息中,应该包括时间戳的数量,以及每个时间戳在整个帧中所占用的时间(以总秒数表示)。

在实际实现过程中,可以为图表设置一个固定的高度,比如300像素。在绘制条形图时,条形的高度将根据每个时间戳在总时间中所占的比例来计算。为此,需要计算一个比例因子:将图表的高度除以该帧的总秒数,这样可以为每个时间戳绘制出合适大小的条形图。

为了避免频繁地创建居中的矩形框,建议使用一个更简洁的方式来定义矩形,直接设定最小值和最大值作为参数,这样会更加方便和高效。

接下来可以按照这个思路进行实际的绘制,并逐步修正目前还未实现的功能。
在这里插入图片描述

使用我们帧率的倒数(33毫秒)作为图表的高度

为了实现堆叠图表来展示每帧的时间戳信息,首先需要明确图表的高度。我们假设目标是30帧每秒(即每帧大约33毫秒)。如果帧时间超过这个值,图表将显示为超出范围的部分。为了实现这一点,图表的总高度可以设为例如60毫秒,这样即使帧时间过长,也能使图表能够展示出来。

每个时间戳的显示需要根据该帧总时间进行缩放,并根据其所占比例来绘制条形图。具体做法是:我们要获取时间戳的时间差(即当前时间戳与上一个时间戳的差值),这能够帮助我们绘制正确的条形图。由于时间戳是基于某个基准计数器的,因此需要计算时间戳之间的实际时间差,然后再根据比例绘制图表。

另外,在绘制时,需要确保图表的每一部分(例如每一个条形图)能够正确堆叠。为了避免频繁指定矩形的位置,建议为条形图的渲染提供更方便的设置,例如可以指定矩形的最小值和最大值。这将使得图表的渲染更加简洁和直观。

接着,绘制堆叠条形图时,底部位置可以根据已有的屏幕边界进行调整,同时考虑到合适的间距和条形宽度,使得每个条形图之间不会重叠,能够清晰地展示时间戳信息。

总的来说,这个过程主要包括:计算每个时间戳所占的时间差、根据比例绘制堆叠条形图、以及合理设置图表的显示参数以保证图表的可读性和美观性。
在这里插入图片描述

在这里插入图片描述

实现RecordTimestamp

我们在帧信息中要进行一些调整,引入一个用于记录时间戳的机制。这可以是一个宏,也可以是一个简单的内联函数。这个函数的作用是获取当前时间,并将其记录到调试帧时间戳数组中,同时存储相应的名称,以便后续分析。

时间戳记录机制

  1. 创建时间戳记录函数

    • 这个函数(或者宏)会接收一个调试帧信息结构体,并记录当前时间戳。
    • 需要确保当前时间戳索引不超过数组大小。
    • 记录时间戳的同时存储事件的名称,以便后续分析和可视化。
  2. 计算时间

    • 需要获取当前时间(通常是某种系统时钟)。
    • 由于时间戳是基于累计计数器的,所以计算秒数时,需要记录上一个时间戳的值,以便计算时间间隔。
    • 可能需要宏来正确传递时间信息,以保证能够正确计算经过的秒数。

具体实现步骤

  1. 定义 record_time_stamp 函数

    • 该函数会接收一个调试信息结构体,并在时间戳数组中存储当前时间戳。
    • 例如:

    inline void Win32RecordTimestamp(debug_frame_end_info *Info, const char *Name, real32 Seconds) {
    Assert(Info->TimestampCount < ArrayCount(Info->Timestamps));
    debug_frame_timestamp *Timestamp = Info->Timestamps + Info->TimestampCount++;
    Timestamp->Name = Name;
    Timestamp->Seconds = Seconds;
    }

    
    
  2. 插入时间戳记录点

    • 在关键代码段插入 Win32RecordTimestamp() 调用:
      Win32RecordTimestamp(&FrameEndInfo, "ExecutableReady",Win32GetSecondsElapsed(LastCounter, Win32GetWallClock()));
      
    • 这样我们就能在帧的各个关键部分记录时间。
  3. 处理时间间隔

    • 由于存储的是时间戳,因此绘制图表时,不能直接使用这些时间戳,而是要计算时间间隔:
      
      

    for (uint32 SnapshotIndex = 0; SnapshotIndex < MAX_DEBUG_SNAPSHOT_COUNT;++SnapshotIndex)
    {
    debug_frame_end_info *FrameEndInfo = DebugState->FrameEndInfo + DebugState->SnapshotIndex;
    real32 PrevTimestampSeconds = 0.0f;
    for (uint32 TimestampIndex = 0;
    TimestampIndex < FrameEndInfo->TimestampCount;
    ++TimestampIndex)
    {
    debug_frame_timestamp *Timestamp = FrameEndInfo->Timestamps + TimestampIndex;
    real32 ThisSecondsElapsed = Timestamp->Seconds - PrevTimestampSeconds;
    PrevTimestampSeconds = Timestamp->Seconds;

         real32 ThisProportion = Scale * ThisSecondsElapsed;real32 ThisHeight = ChartHeight * ThisProportion;PushRect(RenderGroup,v3{ChartLeft + BarSpacing * (real32)SnapshotIndex + 0.5f * BarWidth,ChartMinY + 0.5f * ThisHeight, 0.0f},v2{BarWidth, ThisHeight}, v4{ThisProportion, 1, 0.0f, 1});}
    

    }

    - 这样才能正确绘制每个阶段所占的时间比例。
  4. 绘制图表

    • 计算比例后,可以绘制堆叠条形图,使不同阶段的时间在图表上直观呈现。
    • 例如:

    real32 BarWidth = 10.0f;
    real32 BarSpacing = 10.0f;
    real32 ChartLeft = LeftEdge + 10.0f;
    real32 ChartHeight = 300.0f;
    real32 ChartMinY = AtY + ChartHeight + 10;
    real32 Scale = 1.0f / 0.033333f;

    real32 ThisProportion = Scale * ThisSecondsElapsed;
    real32 ThisHeight = ChartHeight * ThisProportion;
    PushRect(RenderGroup,
    v3{ChartLeft + BarSpacing * (real32)SnapshotIndex + 0.5f * BarWidth,
    ChartMinY + 0.5f * ThisHeight, 0.0f},
    v2{BarWidth, ThisHeight}, v4{ThisProportion, 1, 0.0f, 1});

    
    

优化点

  • 优化剪切板操作
    在编辑代码时,发现删除代码后可能会丢失剪贴板内容,影响工作流。如果能改进剪切板管理,比如提供多级撤销,或者提供专门的寄存器管理机制,会让开发体验更顺畅。
  • 优化宏和内联函数的使用
    由于某些情况下需要访问额外的计时信息,因此可能需要在宏和函数之间权衡,确保既能正确计算时间,又不会影响代码可读性。

总结

  • 通过 record_time_stamp() 记录各个关键时刻的时间戳。
  • 计算时间间隔以获得各个阶段的时间消耗。
  • 采用堆叠条形图可视化不同阶段的时间分布。
  • 需要改进代码编辑体验,优化剪切板操作。
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

测试堆叠条形图。它的位置不正确

当前遇到的问题是图表没有按照预期的位置显示,需要对其进行调整和优化。经过分析,发现几个可能导致问题的原因,包括坐标计算方向错误、绘制超出目标高度、以及调试信息可能影响最终渲染结果。

在这里插入图片描述

一开始没显示半天才显示
在这里插入图片描述

在这里插入图片描述

宽度太宽减少宽度
在这里插入图片描述


问题分析

  1. Y 轴方向问题
    • 在程序设计中,Y 轴通常是向下递增,而数学坐标系中 Y 轴是向上递增。这种差异导致在计算图表位置时容易混淆,尤其是在调整绘制方向时。
    • 由于默认 Y 轴向下递增,因此在调整图表时要确保正确控制方向,避免出现反向偏移的情况。

在这里插入图片描述

在这里插入图片描述

图表似乎超过了33毫秒。我们画一条参考线来检查

当前的任务是绘制一个表示 30 帧每秒(FPS)目标线的标记,以便在图表上明确显示性能目标。为此,需要在图表中添加一条基准线,该线表示 33 毫秒的帧时间(1 秒 / 30 帧 ≈ 33.33 毫秒)。


实现步骤

  1. 确定基准线的位置

    • 目标是绘制一个标记,表示 30 FPS 的阈值。
    • 计算基准线的 Y 轴位置,应位于 ChartMinY + ChartHeight,即图表的底部加上目标帧时间的高度:
    • 由于 33 毫秒是一个固定阈值,使用图表的时间比例进行缩放,以确保基准线出现在正确的位置。
  2. 计算基准线的宽度

    • 需要确定 ChartWidth,即图表的宽度:
      real32 ChartWidth = BarSpacing * (real32)MAX_DEBUG_SNAPSHOT_COUNT
      
    • 这样可以确保绘制的线段覆盖整个图表的宽度。
  3. 绘制基准线

    • 采用 1 像素高度的线,以清晰区分数据条形图:
      PushRect(RenderGroup, v3{ChartLeft + 0.5f * ChartWidth, ChartMinY + ChartHeight, 0.0f},v2{ChartWidth, 1.0f}, v4{1.0f, 1.0f, 1.0f, 1.0f});
      
    • 这里 PushRect 代表一个通用的绘制函数,v4{1.0f, 1.0f, 1.0f, 1.0f} white 使其易于识别。

最终调整

  1. 计算 30 FPS 对应的帧时间,并转换成 Y 轴坐标。
  2. 确定图表宽度,使基准线正确覆盖整个图表。
  3. 使用 1 像素高的细线绘制,提高可读性。
  4. 确保所有计算逻辑正确,防止线条偏移或错误显示。

最终,30 FPS 基准线能够清晰地呈现在图表上,方便对比实际性能情况。
在这里插入图片描述

在这里插入图片描述

对堆叠矩形进行颜色编码,以便更容易区分它们

目前接近直播的结束时间,下一步的目标是让单独的矩形更加清晰可见。为此,我们将使用不同的颜色进行区分,使其在堆叠时更容易分辨。

颜色区分的实现方案

  1. 定义颜色集

    • 先创建一个颜色数组,手动指定颜色。
    • 目前颜色选择并不讲究,可以后续调整优化。
    • 颜色方案暂时采用原色(Primary)、次要颜色(Secondary)以及一些中性色调。
    • 颜色可能采用 RGB 形式,例如 (0.5, 1, 0)(1, 0.5, 0) 等等。
  2. 颜色分配策略

    • 根据时间戳索引 TimestampIndex 来确定颜色。
    • 通过 TimestampIndex % ArrayCount(Colors) 计算出当前矩形的颜色索引。
    • 确保不同的时间戳数据使用不同的颜色进行填充,使得数据更加直观可视化。
  3. 具体代码逻辑

    • 计算颜色索引 TimestampIndex % ArrayCount(Colors)
    • 通过 Colors[TimestampIndex % ArrayCount(Colors)] 获取对应的颜色值。
    • 使用该颜色值填充矩形,例如 PushRect(..., color)

在这里插入图片描述

在这里插入图片描述

测试颜色编码的矩形。图表看起来不对

我们从未堆叠矩形!

目前仍未实现堆叠效果,之前的代码并没有真正把元素进行堆叠。因此,需要修改代码,使其能够正确地将元素累加堆叠起来。

调整堆叠逻辑

  1. 初始化 StackY

    • 需要定义 StackY 变量,并将其初始化为起始位置。
    • 这样可以确保堆叠的元素从正确的位置开始绘制。
  2. 累加 StackY 以实现堆叠

    • 在绘制完一个元素后,需要将其高度 height 累加到 StackY 上,使得下一个元素能正确堆叠在上方。
    • 计算方式类似于 StackY += ThisHeight,确保每个矩形按照预期堆叠。

修正方案

  • 在循环遍历所有元素时,确保 StackY 持续累加,以保证正确的堆叠顺序。
  • 之前可能遗漏了 StackY 的更新,导致所有矩形仍然绘制在同一水平线上,而没有向上堆叠。
  • 通过 StackY += ThisHeight,使得新的矩形能够正确放置在上一个矩形的顶部,而不是覆盖或错位。

下一步

  • 测试是否正确堆叠:运行程序,观察矩形是否能逐步向上堆叠,而不是全部集中在同一位置。
  • 调整 StackY 初始值:确保 StackY 从正确的基线开始,而不是从错误的参考位置。
  • 优化堆叠间距:如果需要,可以在 StackY 计算时加入一些额外的间隔,例如 StackY += ThisHeight + padding,让矩形之间保持合理的距离,使其更清晰可见。
    在这里插入图片描述

在这里插入图片描述

现在它正常工作,大部分时间都花费在GameUpdateAndRender函数内

现在的堆叠效果基本符合预期,能够清晰地显示不同时间段的占用情况。从结果来看,毫无意外,主要的时间消耗都集中在游戏逻辑处理部分。因此,下一步的重点是让这个可视化工具更有用,并对游戏内部的时间分配进行更精细的拆解。

当前进展

  • 已经成功绘制时间条形图,并且能够直观地看到主要的时间消耗点。
  • 游戏逻辑部分占用了大部分的帧时间,需要进一步细分和优化。
  • 目前的图表可以作为初步的性能分析工具,但仍然缺乏更细粒度的时间划分。

下一步优化方向

  1. 调整图表间距

    • 目前的图表可能过于密集,不够清晰。
    • 需要适当增加间距,使得各个时间段的占用情况更直观。
  2. 统一时间戳和时间块

    • 目前,时间戳和时间块的处理方式还未完全统一。
    • 需要找到一种方法,让时间戳的数据和时间块的数据能够一致地展示,方便分析。
  3. 细分游戏内部时间消耗

    • 目前只看到游戏逻辑部分占用了大量时间,但具体的细节尚不明确。
    • 需要在游戏内部进一步打点,拆分出更多的细分项,例如物理计算、AI 处理、渲染等,以便找出性能瓶颈。
  4. 确定如何处理时间戳数据

    • 目前还不确定最佳的方式来组织时间戳和时间块数据。
    • 可能需要重新思考数据结构,使其能够更方便地被可视化工具解析和展示。

最终目标

  • 让这个可视化工具不仅能展示整体帧时间,还能细化到各个子系统的时间消耗情况。
  • 使时间数据的组织方式更加统一,从而方便进一步扩展和分析。
  • 结合游戏内部的实际情况,优化代码结构,使得性能瓶颈更加直观可见。

目前进度虽然不快,但已经朝着正确的方向前进,接下来需要深入思考如何更好地整合时间戳和时间块,并逐步完善这一工具的功能。

修改一下缓冲区大小为1920x1080

禁用之前的一直缩放
在这里插入图片描述

全屏之后不会进行缩放
在这里插入图片描述

多核渲染会破坏你的时间控制吗?

多核渲染是否会影响计时?理论上不会。
计时器已经被设计为多核安全,因此即使多个线程同时运行相同的代码,所有计数器的值在理论上应该能够正确累加,并返回正确的结果。

当前计时系统的情况

  • 计时器线程安全性

    • 计时器经过专门设计,以确保多线程环境下的安全性。
    • 计数器的值应该能正确累加,并不会因多线程运行而出现偏差。
  • 现有的时间记录不够精细

    • 目前的时间记录系统并不够精细,导致无法深入分析性能问题。
    • 现有的时间采样可能没有足够的分辨率,无法准确反映某些细节问题。
  • 需要整合两个系统

    • 目前的时间记录系统和性能采样系统需要整合,以便获取更精准的数据。
    • 这样可以更清晰地看到各个子系统的具体运行情况。

下一步改进方向

  1. 进一步验证计时器的多核安全性

    • 进行更多测试,确保多线程环境下计时器的数据不会出现异常。
    • 观察是否存在时间偏移或计时误差。
  2. 提升计时精度

    • 目前的时间记录可能过于粗略,需要更细粒度的时间采样。
    • 可能需要调整采样方式,使其能更精确地捕捉每个子系统的运行时间。
  3. 整合时间记录和性能分析系统

    • 让计时系统能够更好地与性能分析工具配合,提供更详细的数据。
    • 可能需要调整数据结构,以更合理的方式存储和展示时间信息。

目前来看,现有的计时系统在理论上应该是可行的,但为了确保精度和正确性,还需要进一步的测试和优化。

你能简要解释一下它是如何追踪帧工作和渲染引擎工作所花费的时间的吗?如果渲染调试是工作的一部分呢?另外一个建议,使用一个键切换调试显示,以便查看游戏

修改一下位置和高度

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

当前帧时间和渲染时间的跟踪方式

目前系统还没有明确区分渲染部分对总帧时间的影响,但由于调试渲染(debug rendering)是单独执行的,因此可以在一定程度上分析其耗时。

  • 调试渲染的影响

    • 调试渲染是渲染流程中的一个单独部分,因此可以测量它的执行时间。
    • 观察当前数据,调试渲染占据了大部分帧时间。
    • 由于 GameUpdateAndRender 是一个包含调试渲染的总函数,因此调试渲染会显著影响其统计数据。
  • 帧时间的计算

    • 目前帧时间是整体计算的,并未明确剥离调试渲染的影响。
    • 通过优化,可以分离调试渲染时间,使得主渲染引擎的耗时统计更准确。

优化与改进方向

  1. 剥离调试渲染的时间

    • 由于调试渲染独立执行,可以单独统计其时间,避免其影响整体性能分析。
    • 在正式性能分析中,可以排除调试渲染部分,以获取更准确的渲染时间。
  2. 进行优化编译

    • 目前未使用优化编译(release mode),优化后可能会减少一些额外的性能损耗。
    • 即使优化后,调试渲染仍然是一个主要的性能开销,因此仍需关注其影响。
      release模式下运行
      在这里插入图片描述
  3. 稳定帧率分析

    • 目前帧率稳定在 30Hz,但若启用调试渲染,60Hz 帧率难以维持。
    • 关闭调试渲染时,60Hz 运行无压力,说明调试渲染是主要的性能瓶颈。
    • 未来可能需要优化调试渲染的方式,使其对帧率的影响最小化。

未来改进方向

  • 进一步优化调试渲染,减少其对整体帧时间的影响。
  • 考虑在渲染时间统计时剥离调试渲染,使得主渲染管线的统计更精准。
  • 未来可能会调整调试工具的交互方式,目前暂未决定是否基于键盘或鼠标。

你是否曾觉得令人惊讶,成百上千的设计师因为过于复杂而搞砸了一个项目,而独立设计师可以在几个月内做出更好的游戏?

  • 关于独立游戏与大型游戏开发的对比
    • 复杂性与设计问题
      许多大型游戏(AAA 游戏)因为涉及众多开发人员,设计上可能会变得过于复杂,导致最终的产品质量下降。而一些独立游戏开发者可能在短时间内制作出更优秀的作品。
    • 独立游戏并不全是成功案例
      不能仅以成功的独立游戏来比较大型游戏,因为每年发布的独立游戏数量巨大,其中大部分作品质量较差。因此,认为“独立游戏更优秀”可能是一种选择性偏见,只关注了少数成功的案例。
    • AAA 游戏的高风险与复杂性
      大型游戏开发涉及庞大的制作团队、数百万美元的预算以及复杂的管线流程。因此,在开发后期做出重大改动往往意味着浪费大量资金和资源。而独立游戏则相对灵活,开发者可以更自由地调整设计。
    • 游戏开发的现实
      并非所有大型游戏的设计都是失败的,也并非所有独立游戏都优秀。二者的开发环境、目标和限制都完全不同,不能简单地直接对比。大型游戏由于其复杂性,难免会遇到挑战,而独立游戏也同样面临市场竞争和资源有限的问题。

总的来说,独立游戏和 AAA 游戏各有优劣,不能简单地说某一方一定比另一方更优秀,而是需要具体分析各自的特点和局限性。

你提到绘制矩形的方式没有优化。你想改变什么?

  • 当前绘制矩形的优化问题
    • 纹理填充优化已完成
      目前已经优化了带有缩放和旋转的纹理填充功能,使其运行高效。
    • 纯色矩形填充未优化
      目前的矩形填充(不涉及纹理,仅为纯色填充)尚未进行优化。它仍然是逐像素绘制,没有利用 SIMD(单指令多数据)优化技术,因此性能较低。
    • 潜在的优化方向
      通过 SIMD 指令优化,可以一次处理多个像素,从而提升矩形填充的速度。预估优化后性能可能提高数倍,例如可能达到 4 倍的加速效果。
    • 优化的必要性
      由于目前的绘制方式效率较低,改进这部分代码能够显著提升整体渲染性能,尤其是在需要绘制大量矩形的场景下。

由于你在多个线程上进行渲染,是不是意味着你在DrawRectangle / DrawRectangleQuickly中花费的时间比在GameUpdateAndRender中更多?

  • 多线程渲染的时间计算问题
    • 计时器的计时方式
      当前的计时器会记录所有渲染线程的总耗时,而不仅仅是主线程的渲染时间。
    • 游戏更新与渲染的关系
      GameUpdateAndRender 阶段,主线程不仅执行了一部分渲染任务,还会等待所有其他渲染线程完成工作。
    • 多线程渲染的影响
      由于渲染是多线程进行的,每个线程的渲染时间都会被单独统计。因此,如果有 8 个线程同时渲染,最终统计的时间可能会比单线程情况下高出 8 倍。
    • 时间统计的误导性
      这种方式会让 DrawRectangle 的时间看起来远大于 GameUpdateAndRender,因为它的时间是所有线程计算的总和,而 GameUpdateAndRender 只是主线程的时间。
    • 确认多线程影响
      由于当前使用了多个核心(可能是 6 或 8),并行执行的线程数直接影响了最终统计结果,这也是为什么 DrawRectangle 的耗时看起来特别高的原因。

为什么你在bat文件中回显到lock.tmp?

  • 批处理文件中 echo 到 lock 文件的作用

    • 主要用于 代码热重载 机制。
    • 当前 调试系统 仍未完全兼容代码重载,需要重新启用和修复。
  • 代码重载时的锁定机制

    • 由于 Visual C++ 在加载调试符号时可能会有问题,因此需要一个 锁定机制 来确保安全加载。
    • 当需要 重载游戏代码 时,程序会检查 lock 文件是否存在。
    • 如果 lock 文件存在,则不会尝试重载,避免加载 调试信息 仍未完全写入的 DLL 文件。
  • 问题来源

    • 之前的情况是:当新 DLL 编译完成后,程序立即加载它,但 PDB(调试信息文件)可能尚未写入完成
    • Visual Studio 在检测到新 DLL 后,会尝试加载调试符号,但如果 PDB 还没写好,就会导致调试信息加载失败。
  • 解决方案

    • 通过 lock 文件,确保 只有在编译完全完成后,才会进行 DLL 重载。
    • 这样可以防止 Visual Studio 在调试时因为 找不到完整的 PDB 文件 而崩溃或出错。

那么在“lib freedom week”之后,我们能否很容易地把HH从类似baremetalOS的系统上启动?

  • 在“自由周”之后引导游戏运行在裸机 OS 上的可行性

    • 理论上可以让游戏在 裸机 OS(如 Bare Metal OS)上运行,但仍然存在一些技术挑战。
    • 关键问题 在于是否有 图形子系统的初始化代码,否则游戏无法正确显示画面。
  • 必要的硬件支持

    • 游戏需要能够处理 位图声音,这意味着必须有相应的 硬件接口
    • 如果裸机 OS 不包含 显卡驱动和声卡驱动,就必须手写这些驱动程序。
  • 额外的挑战

    • 除了 图形和声音 之外,还需要 输入设备(如键盘)支持。
    • 如果裸机 OS 没有相关代码,就必须自己实现 键盘读取 等功能。
  • 结论

    • 是否可行 取决于裸机 OS 的功能支持范围。
    • 如果没有现成的驱动程序,可能 需要手写显卡、声卡和输入设备的驱动,这会增加大量开发工作。
    • 由于不了解具体的 Bare Metal OS 细节,因此 无法确定 是否能直接运行游戏。

HH会优化为GPU渲染,还是坚持CPU渲染?那会是一个艰巨的任务,还是相对简单?

  • 是否会针对 GPU 进行优化?

    • 目前仍然不确定,是否会对 GPU 进行深度优化还需要进一步观察。
  • 是否仍然坚持使用 CPU 渲染?

    • 目前仍然坚持使用 CPU 进行渲染,但未来是否会调整仍未确定。
  • 优化 GPU 是否是一个艰巨的任务?

    • 不会特别艰巨,但也不能说是非常简单的事情。
    • 优化的具体程度 还需要进一步评估。

如果我有一个简单的应用概念,我因为技术不行而无法自己编程,有没有好的方法让别人为我开发这个相对简单的应用,我们分利润,或者我拿10%也行?我不在乎利润,我只是想帮助开发应用

  • 关于如何找到人帮忙开发应用

    • 自己不会编程,但有一个简单的应用概念,希望找人来开发。
    • 想法是:可以按利润分成,甚至只拿 10% 的收益,不在乎盈利,只想参与开发过程。
  • 对此的看法

    • 这不是合适的讨论场合,这里主要是面向想要自己做编程的人,所以不太适合讨论这个问题。
    • 是否有可能找到人来做? 可能可以,但这与当前话题相去甚远,因此无法提供具体建议。

为什么你不使用Visual Studio写代码?看起来你是在Windows机器上工作

  • 关于为什么不使用 Visual Studio 编写代码
    • 不喜欢 Visual Studio 的代码编辑器,所以没有使用它来编写代码。
    • 但使用它的调试器,因为它是 Windows 上最好的调试工具之一。
    • 虽然依赖其调试功能,但在编写代码时,更倾向于使用其他编辑工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/75484.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习PyTorch之动态计算图可视化 - 使用 torchviz 生成计算图

序号系列文章1深度学习训练中GPU内存管理2深度学习PyTorch之数据加载DataLoader3深度学习 PyTorch 中 18 种数据增强策略与实现4深度学习pytorch之简单方法自定义9类卷积即插即用5深度学习PyTorch之13种模型精度评估公式及调用方法6深度学习pytorch之4种归一化方法&#xff08;…

K8S学习之基础四十五:k8s中部署elasticsearch

k8s中部署elasticsearch 安装并启动nfs服务yum install nfs-utils -y systemctl start nfs systemctl enable nfs.service mkdir /data/v1 -p echo /data/v1 *(rw,no_root_squash) >> /etc/exports exports -arv systemctl restart nfs创建运行nfs-provisioner需要的sa账…

Go红队开发—CLI框架(一)

CLI开发框架 命令行工具开发&#xff0c;主要是介绍开发用到的包&#xff0c;集成了一个框架&#xff0c;只要学会了基本每个人都能开发安全工具了。 该文章先学flags包&#xff0c;是比较经典的一个包&#xff0c;相比后面要学习的集成框架这个比较自由比较细化点&#xff0…

eclipse [jvm memory monitor] SHOW_MEMORY_MONITOR=true

eclipse虚拟机内存监控设置SHOW_MEMORY_MONITORtrue D:\eclipse-jee-oxygen-2-win32-x86_64\workspace\.metadata\.plugins\org.eclipse.core.runtime\.settings org.eclipse.ui.prefs (文件比较多&#xff0c;别找错了&#xff09; SHOW_MEMORY_MONITORtrue 重启 -xms 1024…

量子计算与人工智能的融合:下一代算力革命

1. 引言&#xff1a;算力需求的飞速增长与量子计算的潜力 在信息技术飞速发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到我们生活的方方面面&#xff0c;从智能助手到自动驾驶&#xff0c;再到医疗诊断&#xff0c;AI 的应用场景日益广泛。然而&#xf…

【网络】网关

【网络】网关 网关 是计算机网络中用于连接两个不同网络的设备或服务器&#xff0c;它充当着“翻译器”和“转发器”的角色&#xff0c;将数据包从一个网络传递到另一个网络&#xff0c;并在必要时进行协议转换和数据重包装。 主要功能 数据转发&#xff1a;当本地网络设备发…

Axure大屏可视化模板:赋能多领域,开启数据展示新篇章

在当今这个数据爆炸的时代&#xff0c;数据已经成为各行各业的核心资产。然而&#xff0c;如何高效、直观地展示数据&#xff0c;并将其转化为有价值的决策依据&#xff0c;成为了许多企业和组织面临的共同挑战。Axure大屏可视化模板&#xff0c;作为一款强大的数据展示工具&am…

数据不外传!通过内网穿透实现绿联NAS远程访问的安全配置方案

文章目录 前言1. 开启ssh服务2. ssh连接3. 安装cpolar内网穿透4. 配置绿联NAS公网地址 前言 大家好&#xff0c;今天要带给大家一个超级酷炫的技能——如何让绿联NAS秒变‘千里眼’&#xff0c;通过简单的几步操作就能轻松实现内网穿透。想象一下&#xff0c;无论你身处何地&a…

面试题精选《剑指Offer》:JVM类加载机制与Spring设计哲学深度剖析-大厂必考

一、JVM类加载核心机制 &#x1f525; 问题5&#xff1a;类从编译到执行的全链路过程 完整生命周期流程图 关键技术拆解 编译阶段 查看字节码指令&#xff1a;javap -v Robot.class 常量池结构解析&#xff08;CONSTANT_Class_info等&#xff09; 类加载阶段 // 手动加载…

WordPress分类目录绑定二级域名插件

一.子域名访问形式 1.wordpress 分类目录 转换为 子域名 &#xff08;绑定二级域名&#xff09;形式 2.wordpress 页面转换为 子域名 &#xff08;绑定二级域名&#xff09; 形式 3.wordpress 作者页转换为 子域名 &#xff08;绑定二级域名&#xff09;形式 4.为不同子域名…

Shopify Checkout UI Extensions

结账界面的UI扩展允许应用开发者构建自定义功能&#xff0c;商家可以在结账流程的定义点安装&#xff0c;包括产品信息、运输、支付、订单摘要和Shop Pay。 Shopify官方在去年2024年使用结账扩展取代了checkout.liquid&#xff0c;并将于2025年8月28日彻底停用checkout.liquid…

华为HCIE方向那么多应该如何选择?

在华为认证体系里&#xff0c;HCIE作为最高等级的认证&#xff0c;是ICT领域专业实力的有力象征。HCIE设置了多个细分方向&#xff0c;这些方向宛如不同的专业赛道&#xff0c;为期望在ICT行业深入发展的人提供了丰富的选择。今天&#xff0c;咱们就来好好聊聊华为HCIE方向的相…

FastGPT原理分析-数据集创建第二步:处理任务的执行

概述 文章《FastGPT原理分析-数据集创建第一步》已经分析了数据集创建的第一步&#xff1a;文件上传和预处理的实现逻辑。本文介绍文件上传后&#xff0c;数据处理任务的具体实现逻辑。 数据集创建总体实现步骤 从上文可知数据集创建总体上来说分为两大步骤&#xff1a; &a…

vue中keep-alive组件的使用

keep-alive是vue的内置组件&#xff0c;它的主要作用是对组件进行缓存&#xff0c;避免组件在切换时被重复创建和销毁&#xff0c;从而提高应用的性能和用户体验。它自身不会渲染一个 DOM 元素&#xff0c;也不会出现在父组件链中。使用时&#xff0c;只需要将需要缓存的组件包…

进程间通信(匿名管道) ─── linux第22课

目录 进程间通信 进程间通信目的 进程间通信的发展 进程间通信分类 1. 管道 2. System V IPC 3. POSIX IPC 管道 什么是管道 站在文件描述符角度-深度理解管道 站在内核角度-管道本质 ​编辑 匿名管道 测试匿名管道的读写 匿名管道的四大现象&#xff1a; 匿…

架构思维:通用系统设计方法论_从复杂度分析到技术实现指南

文章目录 Question订单履约原始架构痛点目标架构架构图说明关键设计点优点 设计方法论复杂来源解决方案评估标准从设计原则出发 技术实现 &#xff08;以选型Redis为例&#xff09;Redis消息队列的实现细节高可用设计 总结 Question 我们经常聊如何设计一个比较完善的系统&…

Excel(实战):INDEX函数和MATCH函数、INDEX函数实战题

目录 经典用法两者嵌套查值题目解题分析 INDEX巧妙用法让数组公式&#xff0c;自动填充所有、有数据的行/列INDEX函数和SEQUENCE函数 经典用法两者嵌套查值 题目 根据左表查询这三个人的所有数据 解题分析 INDEX函数的参数&#xff1a;第1个参数是选定查找范围&#xff0c…

ECharts仪表盘-仪表盘25,附视频讲解与代码下载

引言&#xff1a; ECharts仪表盘&#xff08;Gauge Chart&#xff09;是一种类似于速度表的数据可视化图表类型&#xff0c;用于展示单个或多个变量的指标和状态&#xff0c;特别适用于展示指标的实时变化和状态。本文将详细介绍如何使用ECharts库实现一个仪表盘&#xff0c;…

清华大学.智灵动力-《DeepSeek行业应用实践报告》附PPT下载方法

导 读INTRODUCTION 今天分享是由清华大学.智灵动力&#xff1a;《DeepSeek行业应用实践报告》&#xff0c;主要介绍了DeepSeek模型的概述、优势、使用技巧、与其他模型的对比&#xff0c;以及在多个行业中的应用和未来发展趋势。为理解DeepSeek模型的应用和未来发展提供了深入的…

VSCODE上ckg_server_linux进程占用CPU过多

现象描述 每次一打开VSCODE&#xff0c;ckg_server_linux进程就启动了&#xff0c;并且一直运行&#xff0c;且占用CPU过高&#xff1b; 推测应该是某个插件的问题导致的&#xff1b; 问题处理 本地搜索了一下&#xff0c;发现是 marscode插件影响的&#xff1b; 禁用marsc…