我正在一些图形 API(DirectX9 和 DirectX11)之上编写一个抽象层,我想听听你的意见。
传统上,我会为每个要抽象的概念创建一个基类。
因此,在典型的 OO 方式中,我将拥有一个类 Shader 和 2 个子类 DX9Shader 和 DX11Shader。
我会重复纹理等的过程......当我需要实例化它们时,我有一个抽象工厂,它将根据当前的图形 API 返回适当的子类。
在 RAII 之后,返回的指针将被封装在 std::shared_ptr 中。
到目前为止一切都很好,但就我而言,这种方法存在一些问题:
- 我需要提供一个公共接口来封装这两个 API(以及未来的其他 API)的功能。
- 派生类存储在单独的 DLL 中(一个用于 DX9,一个用于 DX11 等),并且在客户端中有一个 shared_ptr 是一个诅咒:退出时,图形 dll 被卸载,如果客户端仍然有一个 shared_ptr 到由于从卸载的 DLL 调用代码,图形对象之一繁荣、崩溃。
这促使我重新设计我做事的方式:我认为我可以只返回指向资源的原始指针并让图形 API 自行清理,但仍然存在客户端悬空指针和接口问题的问题。我什至考虑过像 COM 这样的手动引用计数,但我认为这将是一个倒退(如果我错了,请纠正我,来自 shared_ptr 世界,手动引用计数似乎很原始)。
然后我看到了 Humus 的工作,他所有的图形类都用整数 ID 表示(很像 OpenGL 所做的)。创建一个新对象只返回它的整数ID,并在内部存储指针;这一切都是完全不透明的!
代表抽象的类(例如 DX9Shader 等)都隐藏在设备 API 后面,这是唯一的接口。
如果要设置纹理,只需调用 device->SetTexture(ID) 即可,其余的在幕后进行。
缺点是 API 的隐藏部分过于臃肿,需要大量样板代码才能使其工作,而且我不喜欢全能类。
有什么想法/想法吗?