什么是渲染队列?在 SDL2 源代码中有一段这样的注释:
Up to SDL 2.0.9, the render API would draw immediately when requested. Now it batches up draw requests and sends them all to the GPU only when forced to (during SDL_RenderPresent, when changing render targets, by updating a texture that the batch needs, etc).
百度翻译:
在SDL 2.0.9及之前,render API将在请求时立即绘制。现在,它成批处理绘制请求,并仅在强制的情况下将它们全部发送到GPU(在SDL_RenderPresent期间,更改渲染目标时,通过更新批处理所需的纹理等)。
实现批处理的方法就是把绘制请求进行命令化。在 SDL_sysrender.h 中定义 SDL_Renderer 结构,其中队列有关的字段:
SDL_bool always_batch;
SDL_bool batching;
SDL_RenderCommand *render_commands;
SDL_RenderCommand *render_commands_tail;
SDL_RenderCommand *render_commands_pool;
Uint32 render_command_generation;
Uint32 last_queued_color;
SDL_Rect last_queued_viewport;
SDL_Rect last_queued_cliprect;
SDL_bool last_queued_cliprect_enabled;
SDL_bool color_queued;
SDL_bool viewport_queued;
SDL_bool cliprect_queued;
字段 render_commands 是渲染命令链表头,字段 render_commands_tail 是链表尾,字段 render_commands_pool 是渲染命令缓存池(已用过的 command 放入,下次分配command 时提取)。
总之最后通过调用 SDL_Renderer 中 RunCommandQueue()(此函数指针可能指向 D3D11_RunCommandQueue ) 函数运行渲染命令队列中的所有命令。
它是 stable 版没错的,稳定的,可靠的!?
直到我在编写基于SDL2的UI时遇到像幽灵一样的BUG!!
看一张效果图:
SDL2-2.0.12
这个程序最底下灰色的为根元素,暗红色的为元素容器,在容器里从“标签1”到“标签32”,横向排列,超出部分被裁剪掉。然而就如看到的“标签1”、“标签5”和“标签9”不见了!这些元素的渲染流程为:
1、先复制“标签1”……“标签32”到“元素容器”的表面纹理;
2、再复制的“元素容器”到“根元素”;
3、最后把“根元素”呈现。
是什么原因导致“标签1”复制无效果(SDL_RenderCopy()返回正常)。所有的标签出自同一个类,渲染流程完全一致。
标签渲染流程:
1、SDL_GetRenderTarget() 先保存渲染器目标以便还原(应该是“元素容器”的纹理);
2、SDL_SetRenderTarget(label_texture) 设置渲染目标为标签纹理;
3、SDL_SetRenderDrawColor(backgroundcolor) 设置背景颜色;
4、SDL_RenderFillRect() 填充背景颜色;
5、SDL_RenderCopy(text_texture) 复制文本纹理到标签纹理;
6、SDL_SetRenderTarget() 还原渲染器之前目标(重新应用“元素容器”的纹理);
7、SDL_RenderCopy(label_texture) 复制标签纹理到“元素容器”纹理。
...
X、回到 1 步骤开始新的标签绘制。
SDL 在 SDL_SetRenderTarget() 时 Flush 所有命令,按照正常情况标签纹理已经复制到容器纹理。
Round1:为了查明原因我在代码里加了断点,流程正常,但是就是不显示。
Round2:加操作断点(继续运行),然后它显示了,包括5和9。:(
Round3:在渲染和复制时SDL_RenderFlush(),没用,情况更糟。
Round4:在复制前乱增加 SDL_SetRenderDrawColor() 代码,貌似都可以显示,但情况不明。
Round5:从头检查我写的代码,一句一句检查,没效果。
...
RoundX:回到 SDL2-2.0.9 一切都正常了!
SDL2-2.0.9
同样的代码 SDL2-2.0.12 和 SDL2-2.0.9 运行效果不同。真不知道是我的代码问题还是 SDL 的 BUG。或者 SDL2-2.0.9 未显现我程序的 BUG。先这样吧。
Up to SDL 2.0.9, the render API would draw immediately when requested. Now it batches up draw requests and sends them all to the GPU only when forced to (during SDL_RenderPresent, when changing render targets, by updating a texture that the batch needs, etc).
百度翻译:
在SDL 2.0.9及之前,render API将在请求时立即绘制。现在,它成批处理绘制请求,并仅在强制的情况下将它们全部发送到GPU(在SDL_RenderPresent期间,更改渲染目标时,通过更新批处理所需的纹理等)。
实现批处理的方法就是把绘制请求进行命令化。在 SDL_sysrender.h 中定义 SDL_Renderer 结构,其中队列有关的字段:
SDL_bool always_batch;
SDL_bool batching;
SDL_RenderCommand *render_commands;
SDL_RenderCommand *render_commands_tail;
SDL_RenderCommand *render_commands_pool;
Uint32 render_command_generation;
Uint32 last_queued_color;
SDL_Rect last_queued_viewport;
SDL_Rect last_queued_cliprect;
SDL_bool last_queued_cliprect_enabled;
SDL_bool color_queued;
SDL_bool viewport_queued;
SDL_bool cliprect_queued;
字段 render_commands 是渲染命令链表头,字段 render_commands_tail 是链表尾,字段 render_commands_pool 是渲染命令缓存池(已用过的 command 放入,下次分配command 时提取)。
总之最后通过调用 SDL_Renderer 中 RunCommandQueue()(此函数指针可能指向 D3D11_RunCommandQueue ) 函数运行渲染命令队列中的所有命令。
它是 stable 版没错的,稳定的,可靠的!?
直到我在编写基于SDL2的UI时遇到像幽灵一样的BUG!!
看一张效果图:
SDL2-2.0.12
这个程序最底下灰色的为根元素,暗红色的为元素容器,在容器里从“标签1”到“标签32”,横向排列,超出部分被裁剪掉。然而就如看到的“标签1”、“标签5”和“标签9”不见了!这些元素的渲染流程为:
1、先复制“标签1”……“标签32”到“元素容器”的表面纹理;
2、再复制的“元素容器”到“根元素”;
3、最后把“根元素”呈现。
是什么原因导致“标签1”复制无效果(SDL_RenderCopy()返回正常)。所有的标签出自同一个类,渲染流程完全一致。
标签渲染流程:
1、SDL_GetRenderTarget() 先保存渲染器目标以便还原(应该是“元素容器”的纹理);
2、SDL_SetRenderTarget(label_texture) 设置渲染目标为标签纹理;
3、SDL_SetRenderDrawColor(backgroundcolor) 设置背景颜色;
4、SDL_RenderFillRect() 填充背景颜色;
5、SDL_RenderCopy(text_texture) 复制文本纹理到标签纹理;
6、SDL_SetRenderTarget() 还原渲染器之前目标(重新应用“元素容器”的纹理);
7、SDL_RenderCopy(label_texture) 复制标签纹理到“元素容器”纹理。
...
X、回到 1 步骤开始新的标签绘制。
SDL 在 SDL_SetRenderTarget() 时 Flush 所有命令,按照正常情况标签纹理已经复制到容器纹理。
Round1:为了查明原因我在代码里加了断点,流程正常,但是就是不显示。
Round2:加操作断点(继续运行),然后它显示了,包括5和9。:(
Round3:在渲染和复制时SDL_RenderFlush(),没用,情况更糟。
Round4:在复制前乱增加 SDL_SetRenderDrawColor() 代码,貌似都可以显示,但情况不明。
Round5:从头检查我写的代码,一句一句检查,没效果。
...
RoundX:回到 SDL2-2.0.9 一切都正常了!
SDL2-2.0.9
同样的代码 SDL2-2.0.12 和 SDL2-2.0.9 运行效果不同。真不知道是我的代码问题还是 SDL 的 BUG。或者 SDL2-2.0.9 未显现我程序的 BUG。先这样吧。