我正在尝试让每个GraphicsContext
实现返回Shader
的不同实现。
pub trait Resources {
type Shader: shader::Shader;
}
pub trait GraphicsContext {
type Resources: Resources;
/// Creates a shader object
fn create_shader<'a>(&'a self, shader::Stage, source: &str)
-> Result<<<Self as GraphicsContext>::Resources as Resources>::Shader,
shader::CreateError>;
/// Creates a shader program object
fn create_shader_program<'a>(&'a self, shaders: Vec<&shader::Shader>)
-> Result<Box<shader::ShaderProgram + 'a>, shader::ProgramCreateError>;
// more to come
}
这样create_shader_program
方法(和其他方法)知道Shader
的具体类型,以便它们可以在着色器对象上调用特定于实现的方法。
我不想将这些方法(例如setCurrent
或attach
)放入所有实现必须使用的特征中。并非所有图形API都使用相同的系统:OpenGL是绑定/解除绑定,Vulkan是结构/设置字段,DirectX是其他等等。
首先,我问这是构建引擎的正确方法。我相信在我的框架/应用程序级代码中需要这些Shader
对象,我可以指定具体的类型基于Context
的当前类型。
// almost certain this doesn't compile, but should be possible in theory
// I'm trying to say:
// the type of the `shader` argument must match to the associated type
// contained within the `context`
fn do_something_with_shader(context: &GraphicsContext,
shader: ??**GraphicsContext::Resources::Shader**??)
-> Result<Foo, Bar>;
或者也许:
fn do_something_with_shader<T>(context: &GraphicsContext<T>,
shader: ??**T::Shader**??)
where T: GraphicsContext::Resources -> Result<Foo, Bar>;
这样的事情可能吗?希望你能看到我理解基本的泛型(我来自Java),但这让我感到疯狂(它确实感觉非常 hackish)。
如果这是正确的方法,那么我的实施就会出现问题。 rustc
希望关联的类型具有指定的生命周期。
wrong number of lifetime parameters: expected 1, found 0 [E0107]
opal_driver_gl/src/context.rs:23 type Shader = Shader;
我的OpenGLShader
结构实际上是OpenGLShader<'a>
类型,所以错误是有道理的。我的问题是,从这堆代码中我可以从哪里获得生命周期:
struct OpenGLResources;
impl Resources for OpenGLResources {
type Shader = OpenGLShader;
}
impl GraphicsContext for OpenGLGraphicsContext {
type Resources = Resources;
/// Creates a shader object
fn create_shader<'a>(&'a self, stage: core_shader::Stage, source: &str)
-> Result<<<Self as GraphicsContext>::Resources as Resources>::Shader,
core_shader::CreateError> {
// impl goes here
}
}
我尝试将生命周期附加到OpenGLResources
和OpenGLGraphicsContext
,这解决了错误,但后来说error: parameter 'a is never used
。
所以其次,我问我如何在相关类型中包含该生命周期。
非常感谢,如果你能看一下这个。我觉得这样的东西必须可以在编译时检查,但我对Rust很新,所以我不太理解如何实现它。
答案 0 :(得分:0)
我最终切换到泛型,这提供了一个成功的实现。
鉴于Resources<'a>
,我可以像这样定义GraphicsContext
:
trait GraphicsContext<'a, R: Resources<'a>>
'a
Shader<'a>
和ShaderProgram<'a>
结构需要2 Resources
个生命周期
然后可以提供OpenGL实现。请注意,Resources
已更改为OpenGLResources
。
// replaced here
impl<'a> GraphicsContext<'a, OpenGLResources<'a>> for OpenGLGraphicsContext<'a> {
fn create_shader(&'a self, ty: Type, source: &str) -> Result<Shader<'a>, ShaderCreationError> {
// do something
}
}