<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>风牛菜籽 &#187; 调优</title>
	<atom:link href="http://www.caiyanpei.com/category/network-technology/%e8%b0%83%e4%bc%98/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.caiyanpei.com</link>
	<description>拖延症重症患者</description>
	<lastBuildDate>Tue, 25 Mar 2025 01:51:19 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.6.1</generator>
		<item>
		<title>C++客户端使用RenderDoc和Visual Studio截帧工具调优</title>
		<link>http://www.caiyanpei.com/c_renderdoc_visual-studio_opt/</link>
		<comments>http://www.caiyanpei.com/c_renderdoc_visual-studio_opt/#comments</comments>
		<pubDate>Mon, 25 Dec 2023 13:44:09 +0000</pubDate>
		<dc:creator>tsai</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[调优]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[性能分析]]></category>

		<guid isPermaLink="false">http://www.caiyanpei.com/?p=651</guid>
		<description><![CDATA[在C++游戏客户端开发中，经常会碰到渲染性能优化各种头疼的问题。为了分析渲染问题 &#8230; <a href="http://www.caiyanpei.com/c_renderdoc_visual-studio_opt/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>在C++游戏客户端开发中，经常会碰到渲染性能优化各种头疼的问题。为了分析渲染问题并找到性能瓶颈，可以借助截帧工具，如<strong>RenderDoc或</strong><strong>Visual Studio自带的截帧工具</strong>。本文探讨使用这两种工具进行调试和优化，尝试提升开发中客户端的渲染性能。</p>
<hr />
<h1>一、为什么需要截帧工具？</h1>
<p>在游戏开发中，渲染性能问题往往表现为帧率下降、卡顿或画面异常。通过截帧工具，我们可以：</p>
<ol>
<li>​<strong>分析每一帧的渲染过程</strong>：查看Draw Call、渲染状态、资源使用情况等。</li>
<li>​<strong>定位性能瓶颈</strong>：找到渲染性能问题的根源，如过多的Draw Call、高复杂度的Shader、不合理的资源使用等。</li>
<li>​<strong>验证优化效果</strong>：通过对比优化前后的截帧数据，验证优化策略的有效性。</li>
</ol>
<hr />
<h1>二、RenderDoc的使用</h1>
<p>RenderDoc是一款开源的图形调试工具，支持DirectX、OpenGL、Vulkan等多种图形API。以下是使用RenderDoc优化C++游戏客户端的步骤：</p>
<h2>1. ​<strong>安装与配置</strong></h2>
<ul>
<li>下载并安装RenderDoc：<a title="RenderDoc官网" href="https://renderdoc.org/" target="_blank">RenderDoc官网</a></li>
<li>启动RenderDoc，配置游戏客户端的可执行文件路径和启动参数。</li>
</ul>
<h2>2. ​<strong>捕获帧数据</strong></h2>
<ul>
<li>在RenderDoc中点击“Launch”启动游戏客户端。</li>
<li>在游戏中运行到需要调试的场景，按下<code>F12</code>（默认快捷键）捕获当前帧。</li>
<li>捕获完成后，RenderDoc会自动加载帧数据。</li>
</ul>
<h2>3. ​<strong>分析帧数据</strong></h2>
<ul>
<li>​<strong>Draw Call分析</strong>：查看每一帧的Draw Call数量，找出过多的Draw Call或重复的渲染操作。</li>
<li>​<strong>资源查看</strong>：检查纹理、缓冲区等资源的使用情况，确保资源加载和释放合理。</li>
<li>​<strong>Shader调试</strong>：查看Shader的输入输出，分析Shader的性能问题。</li>
<li>​<strong>渲染状态</strong>：检查深度测试、混合模式等渲染状态，确保设置正确。</li>
</ul>
<h2>4. ​<strong>优化建议</strong></h2>
<ul>
<li>​<strong>减少Draw Call</strong>：使用批处理（Batching）或实例化（Instancing）减少Draw Call数量。</li>
<li>​<strong>优化Shader</strong>：简化Shader计算，减少纹理采样次数。</li>
<li>​<strong>合理使用资源</strong>：压缩纹理格式，减少显存占用。</li>
</ul>
<hr />
<h1>三、Visual Studio截帧工具的使用指南</h1>
<p>Visual Studio自带的截帧工具（Graphics Debugger）是DirectX开发的强大调试工具，以下是使用步骤：</p>
<h2>1. ​<strong>启用Graphics Debugger</strong></h2>
<ul>
<li>在Visual Studio中打开游戏客户端项目。</li>
<li>点击“调试”菜单，选择“Graphics &gt; Start Graphics Debugging”。</li>
</ul>
<h2>2. ​<strong>捕获帧数据</strong></h2>
<ul>
<li>游戏启动后，运行到需要调试的场景。</li>
<li>在Visual Studio中点击“Graphics &gt; Capture Frame”捕获当前帧。</li>
</ul>
<h2>3. ​<strong>分析帧数据</strong></h2>
<ul>
<li>​<strong>事件列表</strong>：查看每一帧的渲染事件，分析Draw Call和渲染状态。</li>
<li>​<strong>资源查看</strong>：检查纹理、缓冲区等资源的使用情况。</li>
<li>​<strong>Pipeline状态</strong>：查看顶点着色器、像素着色器等阶段的输入输出。</li>
<li>​<strong>帧性能分析</strong>：使用“Frame Analysis”工具分析每一帧的性能瓶颈。</li>
</ul>
<h2>4. ​<strong>优化建议</strong></h2>
<ul>
<li>​<strong>减少渲染状态切换</strong>：合并相同渲染状态的Draw Call。</li>
<li>​<strong>优化资源使用</strong>：使用Mipmaps、压缩纹理格式。</li>
<li>​<strong>Shader优化</strong>：减少复杂计算，使用低精度数据类型。</li>
</ul>
<hr />
<h1>四、常见优化点</h1>
<h2>1：Draw Call过多</h2>
<ul>
<li>​<strong>问题描述</strong>：游戏帧率下降，RenderDoc显示Draw Call数量过多。</li>
<li>​<strong>可能解决方案</strong>：
<ol>
<li>使用批处理（Batching）合并相同材质的物体。</li>
<li>使用实例化（Instancing）渲染大量相同的物体。</li>
</ol>
</li>
<li>​<strong>验证效果</strong>：RenderDoc显示Draw Call数量显著减少，帧率提升。</li>
</ul>
<h2>2：Shader性能瓶颈</h2>
<ul>
<li>​<strong>问题描述</strong>：Visual Studio截帧工具显示像素着色器耗时较高。</li>
<li>​<strong>可能解决方案</strong>：
<ol>
<li>简化Shader计算，减少纹理采样次数。</li>
<li>使用低精度数据类型（如<code>half</code>代替<code>float</code>）。</li>
</ol>
</li>
<li>​<strong>验证效果</strong>：Visual Studio帧性能分析显示像素着色器耗时降低。</li>
</ul>
<h2>3：纹理资源过大</h2>
<ul>
<li>​<strong>问题描述</strong>：RenderDoc显示纹理资源占用显存过高。</li>
<li>​<strong>可能解决方案</strong>：
<ol>
<li>压缩纹理格式（如BC7、ASTC）。</li>
<li>使用Mipmaps优化远处纹理的渲染。</li>
</ol>
</li>
<li>​<strong>验证效果</strong>：RenderDoc显示显存占用显著减少。</li>
</ul>
<hr />
<h1>五、工具对比与选择</h1>
<div>
<table>
<thead>
<tr>
<th>工具</th>
<th>优点</th>
<th>缺点</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td>​<strong>RenderDoc</strong></td>
<td>跨平台，支持多种图形API，功能强大</td>
<td>需要单独安装，学习曲线较陡</td>
<td>跨平台开发，深度调试</td>
</tr>
<tr>
<td>​<strong>Visual Studio</strong></td>
<td>集成开发环境，与C++项目无缝衔接</td>
<td>仅支持DirectX，功能相对有限</td>
<td>DirectX开发，快速调试</td>
</tr>
</tbody>
</table>
</div>
<p><strong>选择建议</strong>：</p>
<ul>
<li>如果需要跨平台支持或深度调试，选择RenderDoc。</li>
<li>如果是DirectX开发且追求快速调试，选择Visual Studio。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.caiyanpei.com/c_renderdoc_visual-studio_opt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unity Shader：从“五彩斑斓的黑”到丝滑渲染的调试探索</title>
		<link>http://www.caiyanpei.com/unity_shader_debug_check/</link>
		<comments>http://www.caiyanpei.com/unity_shader_debug_check/#comments</comments>
		<pubDate>Sun, 23 Apr 2023 12:46:26 +0000</pubDate>
		<dc:creator>tsai</dc:creator>
				<category><![CDATA[shader]]></category>
		<category><![CDATA[Unity]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[调优]]></category>
		<category><![CDATA[unity]]></category>

		<guid isPermaLink="false">http://www.caiyanpei.com/?p=653</guid>
		<description><![CDATA[在Unity中编写Shader时，常常会遇到一些令人抓狂的问题：颜色显示异常、光 &#8230; <a href="http://www.caiyanpei.com/unity_shader_debug_check/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>在Unity中编写Shader时，常常会遇到一些令人抓狂的问题：颜色显示异常、光照计算错误、性能突然暴跌，甚至直接导致屏幕“五彩斑斓”或完全黑屏。由于Shader代码在GPU上执行，无法像C#一样逐行调试，这让问题定位变得异常困难。本文探讨几个实用调试技巧，一起尝试下驯服“暴躁”的Shader代码。</p>
<hr />
<h1>​<strong>一、基础调试工具：你的Shader显微镜</strong></h1>
<h2>1. ​<strong>假色输出法（False Color Debugging）​</strong></h2>
<p>当计算结果超出预期范围时，将中间值映射为可视颜色是最直接的调试方式。</p>
<p><strong>示例：​</strong></p>
<pre><code>// 将法线向量可视化（范围[-1,1] → [0,1]）
fixed4 frag (v2f i) : SV_Target {
    float3 normal = i.worldNormal * 0.5 + 0.5; // 映射到颜色范围
    return fixed4(normal, 1.0);
}</code></pre>
<p>通过逐步替换输出值，可以快速定位哪一步计算出现了异常。</p>
<h2>2. ​<strong>分阶段注释法</strong></h2>
<p>将复杂的Shader拆分成多个阶段，逐步启用/禁用代码块：</p>
<ul>
<li>注释掉光照计算，仅输出基础颜色</li>
<li>逐步启用法线贴图、高光、阴影等模块</li>
<li>使用宏定义快速切换（如 <code>#define ENABLE_SPECULAR 0</code>）</li>
</ul>
<h2>3. ​<strong>Unity帧调试器（Frame Debugger）​</strong></h2>
<ul>
<li>​<strong>路径：Window &gt; Analysis &gt; Frame Debugger</strong></li>
<li>逐帧查看Draw Call的执行顺序</li>
<li>检查渲染目标（Render Texture）的中间结果</li>
<li>验证Uniform变量（如矩阵、光照参数）是否正确传递</li>
</ul>
<hr />
<h1>​<strong>二、高级武器库</strong></h1>
<h2>1. ​<strong>RenderDoc：GPU级别的侦探工具</strong></h2>
<ul>
<li>​<strong>适用场景</strong>：深度分析渲染管线、纹理采样、缓冲区内容</li>
<li>​<strong>操作步骤</strong>：
<ol>
<li>在Unity中启动游戏并触发问题</li>
<li>使用RenderDoc捕获一帧</li>
<li>检查Shader输入/输出、纹理坐标、顶点数据</li>
</ol>
</li>
<li>​<strong>关键功能</strong>：
<ul>
<li>查看每个像素的历史记录（Pixel History）</li>
<li>动态修改Shader变量并实时预览</li>
</ul>
</li>
</ul>
<h2>2. ​<strong>Shader Variant剥离（Preprocessor魔法）​</strong></h2>
<p>通过自定义预处理指令，快速定位多平台兼容性问题：</p>
<pre><code>#pragma shader_feature _USE_NORMAL_MAP
// ...
#if _USE_NORMAL_MAP
    // 法线贴图相关代码
#endif</code></pre>
<p>在材质面板中切换<code>_USE_NORMAL_MAP</code>开关，观察表现差异。</p>
<h2>3. ​<strong>GPU Instancing的“陷阱”​</strong></h2>
<p>当使用<code>UNITY_INSTANCING_BUFFER_START</code>时，若出现数据错乱：</p>
<ul>
<li>检查<code>unity_WorldTransformParams</code>是否正确处理</li>
<li>在Vertex Shader中输出实例ID，验证数据索引：
<pre><code>float instanceID = (float)unity_InstanceID;
return fixed4(instanceID, 0, 0, 1);</code></pre>
</li>
</ul>
<hr />
<h1>​<strong>三、常见问题急救手册</strong></h1>
<h2>​<strong>1. 颜色全黑/全白？先检查这些！​</strong></h2>
<ul>
<li>​<strong>UV坐标错误</strong>：输出UV为颜色，观察是否超出[0,1]范围</li>
<li>​<strong>法线方向错误</strong>：在片段着色器中返回<code>fixed4(i.normal * 0.5 + 0.5, 1)</code></li>
<li>​<strong>光照向量计算错误</strong>：手动硬编码光照方向测试</li>
<li>​<strong>Alpha通道问题</strong>：检查混合模式（Blend）和深度写入（ZWrite）</li>
</ul>
<h2>​<strong>2. 性能断崖下跌？GPU在“燃烧”什么？</strong></h2>
<ul>
<li>​<strong>过度分支</strong>：避免在片段着色器中使用<code>if</code>语句，改用<code>step()</code>或<code>lerp()</code></li>
<li>​<strong>采样次数爆炸</strong>：合并纹理采样（如使用RGBA通道存储不同数据）</li>
<li>​<strong>精度问题</strong>：将不必要的<code>float</code>改为<code>half</code>或<code>fixed</code></li>
<li>​<strong>隐藏的循环</strong>：检查<code>for</code>循环是否在片段着色器中意外执行多次</li>
</ul>
<h2>​<strong>3. 平台差异：为什么Android和PC表现不同？</strong></h2>
<ul>
<li>​<strong>精度差异</strong>：移动端GPU的<code>half</code>可能只有10位精度</li>
<li>​<strong>纹理压缩格式</strong>：检查ASTC/RGBA32等格式的兼容性</li>
<li>​<strong>ES3.0限制</strong>：避免使用<code>tex2Dlod</code>等需要Shader Model 3.0以上特性的函数</li>
</ul>
<hr />
<h1>​<strong>四、防御性编码</strong></h1>
<h2>1. ​<strong>数学计算的“安全网”​</strong></h2>
<ul>
<li>使用<code>saturate()</code>函数限制数值范围：
<pre><code>float specular = saturate(dot(N, L)); // 避免负数导致意外结果</code></pre>
</li>
<li>除法保护：<code>(a + 1e-5) / (b + 1e-5)</code></li>
</ul>
<h2>2. ​<strong>Debug宏的妙用</strong></h2>
<p>自定义调试宏，快速切换调试模式：</p>
<pre><code>#define DEBUG_NORMAL 1

fixed4 frag (v2f i) : SV_Target {
    #if DEBUG_NORMAL
        return fixed4(i.normal * 0.5 + 0.5, 1);
    #else
        // 正式代码
    #endif
}</code></pre>
<h2>3. ​<strong>版本兼容性声明</strong></h2>
<p>在Shader开头明确声明目标级别：</p>
<pre><code>#pragma target 3.5
#pragma require tessellation</code></pre>
<hr />
<h1>​<strong>五、调试思维</strong></h1>
<ol>
<li>​<strong>最小化复现</strong>：将Shader简化到仅保留问题的最小代码块</li>
<li>​<strong>对比法</strong>：与官方Standard Shader或已知正常Shader对比输入输出</li>
<li>​<strong>边界值测试</strong>：测试UV(0,0)、(1,1)、法线(0,0,1)等极端情况</li>
<li>​<strong>物理合理性检查</strong>：高光是否能量守恒？光照衰减是否符合预期？</li>
</ol>
<hr />
<p>可能用到的工具清单</p>
<ul>
<li><a title="VSCode Shaderlab插件" href="https://marketplace.visualstudio.com/items?itemName=amlovey.shaderlabvscodefree" target="_blank">VSCode Shaderlab</a>插件：支持语法高亮和自动补全</li>
<li><a title="Unity Graphics Test Framework" href="https://docs.unity3d.com/Packages/com.unity.test-framework@1.1/manual/reference-attribute-unitytest.html" target="_blank">Unity Graphics Test Framework</a>：自动化测试Shader表现</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.caiyanpei.com/unity_shader_debug_check/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
