SDL2-2.0.12(stable) 渲染队列有 BUG ?
sdl吧
全部回复
仅看楼主
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
level 7
小二郎998 楼主
我发现在编译 SDL2-2.0.12 时默认是 D3D9 驱动,而不是 D3D11。
在 SDL_config_windows.h 中打开 D3D11
#ifndef SDL_VIDEO_RENDER_D3D11
#define SDL_VIDEO_RENDER_D3D11 1 // 这里原来为0,修改为1.
#endif
重新编译 SDL2。
在应用程序中调用 SDL_SetHint 进行提示创建 D3D11
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "direct3d11");
SDL_CreateRenderer(window, -1, flags); // 此时 -1 就默认创建 D3D11
SDL 使用 D3D11 时创建交换连 swapChain,屏幕将在两个或多个后台资源上来回切换,需要不停的往屏幕上重复绘制,不然闪烁不停。
在D3D11 下 SDL_RenderReadPixels 有点问题,它只读取交换连上像素。必须自己修改源代码,以便读取目标纹理像素。
目前没有出现上面所说的 不显示 BUG。继续
2020年12月21日 10点12分 2
level 8
[惊讶]
2020年12月22日 13点12分 3
level 1
[大拇指]
2021年03月28日 23点03分 4
level 1
[大拇指]
2021年05月25日 02点05分 5
level 1
不要用最新版,多比对细节。
最近在14里也发生了问题,没时间研究先退回到8了
2021年05月30日 03点05分 6
1