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

mtl: Use pointers for temporary state #2175

Merged
merged 1 commit into from
Jun 25, 2018
Merged

mtl: Use pointers for temporary state #2175

merged 1 commit into from
Jun 25, 2018

Conversation

grovesNL
Copy link
Contributor

@grovesNL grovesNL commented Jun 24, 2018

Partially fix to #2161
PR checklist:

  • make succeeds (on *nix)
  • make reftests succeeds
  • tested examples with the following backends:

This replaces buffer/texture/sampler object usage with pointers instead. This allows us to bypass Objective-C's reference counting (i.e. retain/release). The idea is to create the same objects as before, but purposely leak them and acquire a pointer to them instead. When we're finished with the objects, we take back ownership and release as usual. We should be able to do this either through drop on the owning struct, or through relevant destroy_* functions.

Still heavily WIP (but works with quad/Dota 2) because there are a few places that will cause leaks or use-after-free in its current state (need to fix cases where the same image is returned for an image view, verify drop exists on all the correct owners, etc.)

@jrmuizel
Copy link
Contributor

How does this approach ensure safety? It seems like it would be error prone.

@grovesNL
Copy link
Contributor Author

@jrmuizel It would be nice to rely on Objective-C to reference count these correctly, but we shouldn't really need it. The objects we expose externally have well-defined lifetimes matching the Vulkan spec. That's why we could decide to use the destroy_* functions from Vulkan (which no-op currently) instead of drop.

We only have to be really careful while handling temporary objects that we create internally. We already have to work around this issue in some other places, for example we have retained_buffers and retained_textures to hold onto our own temporary buffers/textures until the owning command buffer has been reset or dropped.

@grovesNL
Copy link
Contributor Author

I'm going to think about this some more and try to restrict pointer usage to high frequency retains/releases as @kvark mentioned on Gitter

@@ -938,11 +921,12 @@ fn exec_render<'a>(encoder: &metal::RenderCommandEncoderRef, command: soft::Rend
encoder.set_stencil_front_back_reference_value(front, back);
}
Cmd::BindBuffer { stage, index, buffer, offset } => {
let native = buffer.as_ref().map(|b| b.as_native());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kvark without as_ref, the borrow checker complains because b is dropped in these cases

@grovesNL grovesNL changed the title [WIP] metal: Use pointers for buffers/textures/samplers mtl: Use pointers for temporary state Jun 24, 2018
@grovesNL
Copy link
Contributor Author

Updated the commit – slightly safer now with less pointer usage for low frequency calls

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.

Good stuff! We are almost there :)

@@ -71,8 +76,8 @@ impl Channel {


pub struct SamplerStates {
nearest: metal::SamplerState,
linear: metal::SamplerState,
nearest: SamplerPtr,
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should have weak pointers here (in this module)

@@ -260,7 +261,7 @@ impl hal::DescriptorPool<Backend> for DescriptorPool {
sampler_offset += layout.count;
slice
.iter()
.map(|s| Some(s.clone()))
.map(|s| Some(SamplerPtr(s.as_ptr())))
Copy link
Member

Choose a reason for hiding this comment

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

isn't this just a copy? e.g. ca't we just do cloned() instead of map

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's still DescriptorSetLayout::Emulated(Vec<pso::DescriptorSetLayoutBinding>, Vec<metal::SamplerState>). Do we want Vec<SamplerPtr> here instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I assume we do want SamplerPtr, but even then we still need to map to get Some here

Copy link
Member

Choose a reason for hiding this comment

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

oh, nvm then. I thought it's SamplerPtr, but it doesn't have to be

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let's leave metal::SamplerState for now I guess – we appear to rely on it being retained here (not sure if its intentional or if there is supposed to be another owner)

@grovesNL
Copy link
Contributor Author

@kvark thanks, updated to remove SamplerPtr changes to internal

@kvark
Copy link
Member

kvark commented Jun 25, 2018 via email

bors bot added a commit that referenced this pull request Jun 25, 2018
2175: mtl: Use pointers for temporary state r=kvark a=grovesNL

Partially fix to #2161
PR checklist:
- [ ] `make` succeeds (on *nix)
- [ ] `make reftests` succeeds
- [ ] tested examples with the following backends:

This replaces buffer/texture/sampler object usage with pointers instead. This allows us to bypass Objective-C's reference counting (i.e. retain/release). The idea is to create the same objects as before, but purposely leak them and acquire a pointer to them instead. When we're finished with the objects, we take back ownership and release as usual. We should be able to do this either through `drop` on the owning struct, or through relevant `destroy_*` functions.

Still heavily WIP (but works with quad/Dota 2) because there are a few places that will cause leaks or use-after-free in its current state (need to fix cases where the same image is returned for an image view, verify `drop` exists on all the correct owners, etc.)

Co-authored-by: Joshua Groves <[email protected]>
@bors
Copy link
Contributor

bors bot commented Jun 25, 2018

@bors bors bot merged commit a6cb5a0 into gfx-rs:master Jun 25, 2018
@kvark kvark mentioned this pull request Jun 25, 2018
22 tasks
@grovesNL grovesNL deleted the ptr branch June 30, 2018 06:49
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