level 7
小二郎998
楼主
什么是渲染队列?在 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。先这样吧。
2020年12月19日 08点12分
1
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。先这样吧。