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

Validate bind group layouts by value #400

Merged
merged 1 commit into from
Dec 17, 2019

Conversation

yanchith
Copy link
Contributor

@yanchith yanchith commented Dec 6, 2019

This PR widens the comparisons done between two bind group layouts to also consider them equivalent if their vectors of BindGroupLayoutBindings are equal.

Tested on various modifications of the cube example from wgpu-rs. https://gist.github.com/yanchith/56e15fe35658b14587ff9bfcbd53116f

Fixes #335

@yanchith yanchith force-pushed the validate-bind-group-layouts-by-value branch from d2b935f to 20bda02 Compare December 7, 2019 09:59
@yanchith yanchith marked this pull request as ready for review December 7, 2019 10:00
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 for the PR!
Here is an idea on how we can implement this better.

}) if layout_id == bind_group_layout_id => {
LayoutChange::Match(group_id.value, &self.dynamic_offsets)
}) => {
if layout_id == bind_group_layout_id {
Copy link
Member

Choose a reason for hiding this comment

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

I think we can do even better than this. What if we resolve the duplicate layouts earlier, in create_bind_group_layout? If we see that a layout with the same content already exists, we can just return the same ID. This means we'd always be able to compare by ID.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice! I'll give it a shot in the coming days 👍

Copy link
Member

Choose a reason for hiding this comment

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

Thanks! And sorry for coming up with this late. I had a feeling that we were missing something, but didn't realize what it was until now 😅

@yanchith yanchith force-pushed the validate-bind-group-layouts-by-value branch from 20bda02 to 77b5a86 Compare December 12, 2019 14:54
@yanchith
Copy link
Contributor Author

Alright, the changes you requested have some really nice properties: all the work is done at init time and the code is much simpler too 👍

Couple of caveats:

  • The bind group layout storage is currently scanned linearly to see if any bind group layouts have the same bindings. Not sure how expensive the call is considered to be, but we could use an additional or better suited data structure to make the search faster.
  • I added the Backend to the storage's value type, because I had to produce it for the ID. Let's hope it doesn't pessimize the data layout much.
  • Now that the backend is available in the storage, I added a couple of asserts here and there: assert_eq!(backend, storage_backend), similar as was already done for epochs. Not sure if wgpu currently supports running on multiple backends simultaneously, so maybe these new asserts are totally redundant 😂
  • If there ever is a wgpu_bind_group_layout_destroy (not sure if it is planned), we will need to rething this approach so we don't drop the layout while still in use.

@@ -1182,6 +1182,15 @@ impl<F: IdentityFilter<BindGroupLayoutId>> Global<F> {
let hub = B::hub(self);
let bindings = unsafe { slice::from_raw_parts(desc.bindings, desc.bindings_length) };

{
let (bind_group_layout_guard, _) = hub.bind_group_layouts.read(&mut token);
Copy link
Member

Choose a reason for hiding this comment

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

let's add a //TODO: figure out if bindings order matters

@@ -1182,6 +1182,15 @@ impl<F: IdentityFilter<BindGroupLayoutId>> Global<F> {
let hub = B::hub(self);
let bindings = unsafe { slice::from_raw_parts(desc.bindings, desc.bindings_length) };

{
let (bind_group_layout_guard, _) = hub.bind_group_layouts.read(&mut token);
for (id, value) in bind_group_layout_guard.iter() {
Copy link
Member

Choose a reason for hiding this comment

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

let's use bind_group_layout_guard.iter().any(|| {..})

@@ -89,55 +89,67 @@ impl IdentityManager {
#[derive(Debug)]
pub struct Storage<T, I: TypedId> {
//TODO: consider concurrent hashmap?
map: VecMap<(T, Epoch)>,
map: VecMap<(T, Epoch, Backend)>,
Copy link
Member

Choose a reason for hiding this comment

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

this is unexpected, why do we need to add the backend here?
Each storage, conceptually, only stores things for the same backend. There can't be two different indices of that map with different backends.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I thought as much, but good to know! I will have to figure out a way to produce the TypedId for the iterator (need a backend to zip the TypedId), but maybe I can just pass the backend to iter()...

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!
bors r+

bors bot added a commit that referenced this pull request Dec 16, 2019
400: Validate bind group layouts by value r=kvark a=yanchith

This PR widens the comparisons done between two bind group layouts to also consider them equivalent if their vectors of `BindGroupLayoutBinding`s are equal. 

Tested on various modifications of the cube example from wgpu-rs. https://gist.github.com/yanchith/56e15fe35658b14587ff9bfcbd53116f

Fixes #335 

Co-authored-by: yanchith <yanchi.toth@gmail.com>
@kvark
Copy link
Member

kvark commented Dec 16, 2019

You are right that we'll have an issue with deleting the bind groups, and that's something we need to have sooner rather than later.

@kvark
Copy link
Member

kvark commented Dec 16, 2019

bors r-
sorry, just something I clarified only now

@bors
Copy link
Contributor

bors bot commented Dec 16, 2019

Canceled

@kvark
Copy link
Member

kvark commented Dec 16, 2019

@yanchith can we please store the bindings in a map instead of a vec (i.e. binding number -> value)? we want to make sure the contents of the bindings match by value regardless of the order they are specified.
Also, please squash the commits.
Sorry about getting late to you!

@yanchith
Copy link
Contributor Author

yanchith commented Dec 17, 2019

can we please store the bindings in a map instead of a vec (i.e. binding number -> value)? we want to make sure the contents of the bindings match by value regardless of the order they are specified.

No prob, I'll get to it tomorrow 👍

You are right that we'll have an issue with deleting the bind groups, and that's something we need to have sooner rather than later.

Do we want to tackle this now, or once we allow deleting bind group layouts?

@kvark
Copy link
Member

kvark commented Dec 17, 2019

Everything that can be deleted is supposed to be refcounted internally, including the bind group layouts.
I think what we'll be doing is just manually bumping the refcount when the ID is re-used, and decreasing it when the user requests to delete it.

@yanchith yanchith force-pushed the validate-bind-group-layouts-by-value branch from 8d96012 to 659abe7 Compare December 17, 2019 11:50
@yanchith
Copy link
Contributor Author

Done as you requested. There is a caveat now, documented in a TODO I added. We can easily avoid it at the cost of allocating a hashmap that we possibly might throw away right after.

@@ -1203,7 +1230,7 @@ impl<F: IdentityFilter<BindGroupLayoutId>> Global<F> {

let layout = binding_model::BindGroupLayout {
raw,
bindings: bindings.to_vec(),
bindings: bindings.iter().cloned().map(|b| (b.binding, b)).collect(),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the allocation that we can move up to simplify the comparison and also make it more correct. But we may end up not using it.

@yanchith yanchith force-pushed the validate-bind-group-layouts-by-value branch from 659abe7 to 6da253d Compare December 17, 2019 12:08
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! Let's go one more step, and we'll be golden

bind_group_layout_guard
.iter(device_id.backend())
.find(|(_, bgl)| {
bindings.len() == bgl.bindings.len()
Copy link
Member

Choose a reason for hiding this comment

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

ok, I see what you did here. Let's move the hashmap creation early and just compare hashmaps here directly. The code would be simpler, and bind group layout creation is not a place that needs optimization - throwing away the hashmap is fine.

To make later bind group layout compatibility checks simpler (and
cheaper), deduplicate them on creation. If two bind group layouts with
same descriptors are requested, only one is created and the same id is
returned for both.
@yanchith yanchith force-pushed the validate-bind-group-layouts-by-value branch from 6da253d to e9545c9 Compare December 17, 2019 17:34
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!
bors r+

bors bot added a commit that referenced this pull request Dec 17, 2019
400: Validate bind group layouts by value r=kvark a=yanchith

This PR widens the comparisons done between two bind group layouts to also consider them equivalent if their vectors of `BindGroupLayoutBinding`s are equal. 

Tested on various modifications of the cube example from wgpu-rs. https://gist.github.com/yanchith/56e15fe35658b14587ff9bfcbd53116f

Fixes #335 

Co-authored-by: yanchith <yanchi.toth@gmail.com>
@bors
Copy link
Contributor

bors bot commented Dec 17, 2019

Build succeeded

@bors bors bot merged commit e9545c9 into gfx-rs:master Dec 17, 2019
@kvark
Copy link
Member

kvark commented Dec 17, 2019

Sorry it took us long, and congrats on your contribution!

@yanchith
Copy link
Contributor Author

No prob, happy to help again in the future!

@yanchith yanchith deleted the validate-bind-group-layouts-by-value branch December 17, 2019 18:22
kvark pushed a commit to kvark/wgpu that referenced this pull request Jun 3, 2021
400: Added test for "capture" example r=kvark a=bfrazho

I've added a test to validate the capture example. I was planning on using the existing "screenshot.png" that was in there for the assertion for the test, but apparently was slightly different from the one that I was generating. I ended up replacing the screenshot.png with what the test was generating.

I'm a little concerned that they were different from the start, but maybe the png generating library made some small changes over time. I did check to make sure that it generated the same png on Windows and Linux on the same computer.

Let me know if there is anything that you would like me to change!

Co-authored-by: Brian <brian@linux-ccip.lan>
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.

Validate bind group layouts by value instead of "by ID"
2 participants