3

我试图让每个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以便他们可以调用着色器对象上的实现特定方法。

我不想将这些方法(例如setCurrentor 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结构实际上是 type 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
    }

}

我尝试将生命周期附加到OpenGLResourcesand OpenGLGraphicsContext,这解决了错误,但随后说error: parameter 'a is never used

所以其次,我问我如何才能在我的关联类型中包含那个生命周期

非常感谢,如果你能看看这个。我觉得这样的事情必须可以在编译时检查,但我对 Rust 还很陌生,所以我不太了解如何实现它。

4

1 回答 1

0

我最终切换到泛型,它提供了一个成功的实现。

鉴于Resources<'a>,我可以GraphicsContext这样定义:

trait GraphicsContext<'a, R: Resources<'a>>

里面的and结构'a需要上面的 2 个生命周期Shader<'a>ShaderProgram<'a>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
    }

}
于 2015-06-21T03:23:04.467 回答