Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add creating and sampling textured quad example #143

Merged
merged 1 commit into from
May 2, 2020

Conversation

chinedufn
Copy link
Collaborator

This PR ports the Swift/Objective-C Creating and Sampling Textures Tutorial to Rust.

image

Overview

  • Added the example to a newly created cargo workspace.

    • I did this because I wanted to add a build script to generate Rust types from metal shader types (C header files)
  • Instead of using the makefile this example is compiling the shaders in the same build.rs that is generating the rust types. I didn't see any reason that this slight deviation from existing patterns would be an issue - but just let me know!

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is some impressive amount of work!
May I ask what is your long-term goal here, and motivation?
Previously, metal-rs was fairly light, we could quickly build and update it. Most testing was done via gfx-rs.
With the large examples like this, the project becomes more standalone and more serious. It also requires more maintenance. Are you using it for something that's not gfx-rs?

Cargo.toml Outdated

[workspace]
members = [
"examples/creating-and-sampling-textures",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could just call it texture?

Copy link
Collaborator Author

@chinedufn chinedufn May 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely!

My original thinking was to mimic the name of the corresponding tutorial in the Apple docs, but that isn't super important I don't think so I'll change this to texture.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this still needs to happen :)

Cargo.toml Outdated

[workspace]
members = [
"examples/creating-and-sampling-textures",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does it need to be a separate project in the workspace?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows the build script to run whenever we compile.

I think that it's valuable to demonstrate that since it can reduce friction when working on a real metal application.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Perhaps, we'd have all the examples in a separate crate here, like in https://github.com/servo/webrender/tree/master/examples ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that since you get one build script per crate we'd want to be sure that we weren't ever adding any additional build scripts before combining examples into one crate.

Thanks for sharing that webrender structure - that's helpful to visualize.

There's also examples in the wild of having examples live in their own crate, a la wasm-bindgen's examples

Personally I'd like to delay this decision until if/when there are more examples to worry about.

But I'm for sure all ears if you think it's better overall to tackle this right now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My expectation is that any other examples are going to need shaders, so the need to build them is inevitable. And if you build them, it would be simpler to maintain if it's a single build script for all.
I'm fine to follow up with that as well, if you aren't convinced :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha - cool I see where you're coming from.

Valid point

Ok cool - let's table this one then. Not blocking for now anyways (:

@chinedufn
Copy link
Collaborator Author

Hey!

I didn't consider the cost of adding another example when I opened this PR - so apologies for springing this PR on you unannounced.

Thanks for taking the time to explain the trade-offs!

So my primary motivation here is that I'd like to see the Rust graphics ecosystem be one of the first places that people turn to when working on graphics applications.

(For no other reason than I love Rust and I love graphics so it's fun to see the Rust + graphics ecosystem grow and to contribute where I can.)

For that to be the case it needs to be easier to write graphics applications with Rust than it is to write them without Rust.

To me some of the key ingredients for this are:

  • Examples of things that you want to do exist and are very good

    • Not suggesting this PR is "very good", more so a stepping stone that could be improved over time
  • Examples of things that you want to do are easy to find

    • Note that this doesn't mean they have to live near the source. But the source repo should at least call attention to other places to look for examples, I think.
  • There aren't a bunch of dependencies to install before getting started, and if there are they are installable with a single command.

    • People can get up and running with ease.

I'd like to see all of the libraries in gfx-rs nail this, not just the most popular ones (i.e. gfx-rs/gfx-rs, probably wgpu-rs soon).

So that's why I PRd this example to metal-rs.


My motivation for using metal-rs in the first place is that I'm working on an application where I'd like to use Metal directly when targeting Apple hardware (I currently use WebGL when targeting the web but have my eyes on wgpu-rs's Wasm support!).

I prefer to work directly with the different graphics APIs because:

  1. I don't ever need to worry about an abstraction layer not supporting a feature that I need. I have full control and visibility by default into the exact behavior of my renderer backends.

  2. More fun for me to get to use and learn all of the APIs (:

  3. If I eventually move to one portable API to rule them all I'd rather wait until it's been battle tested by multiple production use cases

  4. My application's rendering test suite is renderer-agnostic so it's relatively easy to maintain different rendering backends to Rust's type system. So the trade-off of multiple renderers vs. one isn't a large concern for me.

So the above explains why I've been using metal-rs directly.

While using metal-rs I ran into some small papercuts such as

  • The order of function parameters differs from those in Apple's documentation which adds some cognitive overhead as I bounce back and forth between Apple's docs and the metal-rs function signatures.

  • Not knowing how to best handle textures when using metal-rs and in general not having many examples to work off of.

So I wanted to help where I could as I ran into small papercuts.


My original longer term vision was that metal-rs would have counterparts for most of the examples projects in Apple's metal docs https://developer.apple.com/documentation/metal .

However - now that you've forced me to pause and think for a bit..

What I really hope for is that Rust developers have ~zero friction when getting started with metal.

That can be achieved without adding examples to metal-rs.

I do think that an example of working with textures should be included in the main repo - but other examples would certainly exist in a different repository if that made things easier for the gfx-rs team.


So, here are the potential paths forwards that I see

  1. PR this example into the metal-rs repo

  2. Create gfx-rs/metal-rs-examples and let the examples live in a different repository pinned to a specific version of metal-rs. This still has some gfx-rs team maintanence overhead

  3. I can just add the example to chinedufn/metal-rs-examples. Bringing the maintenance overhead to the gfx-rs to zero.


Personally I think that a texture example should definitely exist in metal-rs and other ports of Apple's documentation should also live in metal-rs but I don't mind those not living in the main repo.

Because metal-rs is just a raw bindings library I think it's possible to have examples that have very low maintenance overhead since the library shouldn't change all that much all that often.

But I'm happy with any of the options that you think is best. For both this example as well as any other examples going forwards.

Thanks!

@kvark
Copy link
Member

kvark commented May 1, 2020

Thank you for the extended reply! I really appreciate the enthusiasm, which drives you in this mission 🎖️
Please file issues about things you find concerning.
For this example and the others, let's host them here in this repo, just as a sub-crate. All examples can be in this sub-crate as binary targets, there is no need for a crate per example.

If we ever hit a situation that maintaining this becomes a burden, we'll start looking for alternatives. In the meantime, I included you in the collaborators on this project.

@chinedufn
Copy link
Collaborator Author

Gotcha! I've only had one real issue so far fortunately. I've taken your advice and tracked it #144 .

Hosting them in the repo for now sounds good.

I addressed one crate for all examples vs. crate per example here so I'll pause until whenever you get around to thinking about this #143 (comment)

Thanks for the collaborator add!

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more notes...

Cargo.toml Outdated

[workspace]
members = [
"examples/creating-and-sampling-textures",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this still needs to happen :)

examples/creating-and-sampling-textures/Cargo.toml Outdated Show resolved Hide resolved

unsafe {
let view = window.ns_view() as cocoa_id;
view.setWantsLayer(YES);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should change that to just work with bool. This would be consistent with other functions and let the examples to avoid linking to obj directly.

Copy link
Collaborator Author

@chinedufn chinedufn May 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah so it looks like BOOL is just a type alias for i8. Sweet thanks.

Changed 33cbdac

@chinedufn
Copy link
Collaborator Author

Alright all feedback so far addressed.

I'll rebase on top of master once there's no more new feedback


use std::path::PathBuf;

use cocoa::{appkit::NSView, base::id as cocoa_id};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is NSView used?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a trait that needs to be in scope for these two calls:

view.setWantsLayer(true as _);
view.setLayer(std::mem::transmute(layer.as_ref()));

[dependencies]
cocoa = "0.20"
core-graphics = "0.19"
image = {version = "0.23", default-features = false, features = ["png"]}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as I suggested earlier, let's just depend on png directly

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you!

@kvark
Copy link
Member

kvark commented May 2, 2020

bors r+

bors bot added a commit that referenced this pull request May 2, 2020
143: Add creating and sampling textured quad example r=kvark a=chinedufn

This PR ports the Swift/Objective-C [Creating and Sampling Textures Tutorial](https://developer.apple.com/documentation/metal/creating_and_sampling_textures) to Rust.

![image](https://user-images.githubusercontent.com/2099811/80553340-7db06280-8997-11ea-958f-2ebc647a5464.png)

## Overview

- Added the example to a newly created cargo workspace.
  - I did this because I wanted to add a build script to generate Rust types from metal shader types (C header files)

- Instead of using the makefile this example is compiling the shaders in the same `build.rs` that is generating the rust types. I didn't see any reason that this slight deviation from existing patterns would be an issue - but just let me know!

Co-authored-by: Chinedu Francis Nwafili <[email protected]>
@kvark
Copy link
Member

kvark commented May 2, 2020

bah, we need to migrate to GHA (github actions)

@kvark
Copy link
Member

kvark commented May 2, 2020

Something scary happening on nightly - https://travis-ci.org/github/gfx-rs/metal-rs/jobs/682192239#L183
but unlikely related directly to the code

@kvark kvark merged commit 5858334 into gfx-rs:master May 2, 2020
@bors
Copy link
Contributor

bors bot commented May 2, 2020

Timed out.

@adamnemecek
Copy link
Contributor

This is really solid and really timely work @chinedufn. I've been meaning to figure out how to share types between metal, and rust but I've been putting it off. I'm a big fan of your dual quaternion shader blog post (https://www.chinedufn.com/dual-quaternion-shader-explained/), I've been using it as a demo to show people why dqs are really good.

@chinedufn chinedufn deleted the example-texture branch May 2, 2020 18:37
@chinedufn
Copy link
Collaborator Author

@adamnemecek thanks you're way too kind! DQs all the way for sure!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants