-
Notifications
You must be signed in to change notification settings - Fork 542
d3d12: Refactor pipeline layouts to match Vulkan's compatibility rules. #1632
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
Conversation
Switching root signatures requires rebinding all tables. Rebinding will now be done automatically and data tracked internally to allow support of two different pipeline bind points.
Actually, I prefer the current way. Unification would require to introducte a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good in general! A few concerns before we proceed.
src/backend/dx12/src/command.rs
Outdated
if self.active_bindpoint != BindPoint::Graphics { | ||
// Switch to graphics bind point | ||
assert!(self.gr_pipeline.pipeline.is_some(), "No graphics pipeline bound"); | ||
let (pipeline, _) = self.gr_pipeline.pipeline.unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just doing expect
would be more idiomatic (than checking for is_some()
in an assert!
)
src/backend/dx12/src/command.rs
Outdated
let table_index = i + table_start; | ||
if ((user_data.dirty_mask >> table_index) & 1) == 1 { | ||
let slot = (i + table_slot_start) as _; | ||
match user_data.data[i] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should probably just do let ptr = match ... {... };
src/backend/dx12/src/command.rs
Outdated
} | ||
|
||
/// Clear dirty flag. | ||
fn clear(&mut self, i: usize) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be renamed for clarity, maybe to clear_dirty
src/backend/dx12/src/command.rs
Outdated
self.flush_compute_user_data(); | ||
} | ||
|
||
fn flush_compute_user_data(&mut self) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems to be awfully similar to flush_gr_user_data
. Would it make sense to share the implementations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, I can try to unify them (I remember that we have something similar done prior).
src/backend/dx12/src/command.rs
Outdated
self.flush_gr_user_data(); | ||
} | ||
|
||
fn flush_gr_user_data(&mut self) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naming is a bit inconsistent ("gr" versus "compute")
table_id += 1; | ||
}); | ||
} | ||
} | ||
|
||
fn bind_compute_pipeline(&mut self, pipeline: &n::ComputePipeline) { | ||
unsafe { | ||
match self.comp_pipeline.pipeline { | ||
Some((_, signature)) if signature == pipeline.signature => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just to clarify: so if the current pipeline is graphics, but the last compute pipeline matches this one, we still don't need to rebind anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pipelines only get bound on draw/dispatch calls to avoid redundant rebinds. We only need/know which pipeline to bind at these calls.
e.g
BindGraphicsPipeline() // the pipeline bind here would be useless
... // Fill graphics user data
BindComputePipeline()
... // Fill compute user data
dispatch()
dispatch()
draw()
Edit: Acutally I implemented it by rebinding, so nvm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add a comment as it's sensible question
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, now I think I understood the question correctly. As far as I can see from the dx12 docs, the graphics and compute root signature are independent so they shouldn't affect each other. The current pipeline state is independent from the root signature stuff afaik.
If a root signature is changed on a command list, all previous root signature bindings become stale and all newly expected bindings must be set before Draw/Dispatch
Should be ready 🚀 |
thank you! |
1632: d3d12: Refactor pipeline layouts to match Vulkan's compatibility rules. r=kvark a=msiglreith Switching root signatures requires rebinding all tables. Rebinding will now be done automatically and data tracked internally to allow support of two different pipeline bind points. We now cache the user data inside the command buffer and rebind the required parts on draw/dispatch calls. Upcoming push constant support was considered during implementation. This mostly follows the compatibility aspect from the RFC #1631. Actual compatibility check is not required and the user is supposed to update the corresponding parts following vulkan specs. Therefore a valid program in Vulkan will run in D3D12, and an invalid application might still run correctly in D3D12. Corresponding parts of the Vulkan API specified the behavior as implementation specific. Next step is to unify the `bind_graphics_descriptor_sets`/`bind_compute_descriptor_sets` and `bind_graphics_pipeline`/`bind_compute_pipeline` calls.
Looks like bors crashed |
1632: d3d12: Refactor pipeline layouts to match Vulkan's compatibility rules. r=kvark a=msiglreith Switching root signatures requires rebinding all tables. Rebinding will now be done automatically and data tracked internally to allow support of two different pipeline bind points. We now cache the user data inside the command buffer and rebind the required parts on draw/dispatch calls. Upcoming push constant support was considered during implementation. This mostly follows the compatibility aspect from the RFC #1631. Actual compatibility check is not required and the user is supposed to update the corresponding parts following vulkan specs. Therefore a valid program in Vulkan will run in D3D12, and an invalid application might still run correctly in D3D12. Corresponding parts of the Vulkan API specified the behavior as implementation specific. Next step is to unify the `bind_graphics_descriptor_sets`/`bind_compute_descriptor_sets` and `bind_graphics_pipeline`/`bind_compute_pipeline` calls.
Perhaps, we need to disable MSVC/nightly build for now... |
(or at least, allow it to fail) |
I would like to try again, giving that it built correctly on the |
1632: d3d12: Refactor pipeline layouts to match Vulkan's compatibility rules. r=msiglreith a=msiglreith Switching root signatures requires rebinding all tables. Rebinding will now be done automatically and data tracked internally to allow support of two different pipeline bind points. We now cache the user data inside the command buffer and rebind the required parts on draw/dispatch calls. Upcoming push constant support was considered during implementation. This mostly follows the compatibility aspect from the RFC #1631. Actual compatibility check is not required and the user is supposed to update the corresponding parts following vulkan specs. Therefore a valid program in Vulkan will run in D3D12, and an invalid application might still run correctly in D3D12. Corresponding parts of the Vulkan API specified the behavior as implementation specific. Next step is to unify the `bind_graphics_descriptor_sets`/`bind_compute_descriptor_sets` and `bind_graphics_pipeline`/`bind_compute_pipeline` calls.
bors keeps crashing 😕
Manually merging? |
we'll give a friendly heads up to @notriddle and merge |
1634: Specialization constants r=kvark a=msiglreith Add support for specialization constants on pipeline creation for HAL, Vulkan and D3D12. Specialization constants allow to change specially marked constants in the shader at compile time to allow some optimizations. In contrast to Vulkan, we use a strong-typed API for defining the overrides for specialization constants as this is easier on the user side. Only scalar constants can be overriden adapting it for vulkan portability should be possible without API changes. On D3D12, these are implemented by shifting the SPIR-V -> HLSL -> DXBC compilation process over to pipeline creation **if** we detect that the shader module contains specialization constants (or push constants as anticipation for future support). On pipeline creation the parsed SPIR-V module gets patched with the specialization constants and compiled. `quad` example has been upated to use the new feature. The image/quad gets scaled by a specialization constant. Metal <-> Vulkan/D3D12 should now show slightly different sized quads as overridden and default values differ. ~~**WIP** as the branch sits on top of #1632 and spirv-cross changes are outstanding grovesNL/spirv_cross#37
Switching root signatures requires rebinding all tables. Rebinding will now be done automatically and data tracked internally to allow support of two different pipeline bind points.
We now cache the user data inside the command buffer and rebind the required parts on draw/dispatch calls. Upcoming push constant support was considered during implementation. This mostly follows the compatibility aspect from the RFC #1631. Actual compatibility check is not required and the user is supposed to update the corresponding parts following vulkan specs. Therefore a valid program in Vulkan will run in D3D12, and an invalid application might still run correctly in D3D12. Corresponding parts of the Vulkan API specified the behavior as implementation specific.
Next step is to unify the
bind_graphics_descriptor_sets
/bind_compute_descriptor_sets
andbind_graphics_pipeline
/bind_compute_pipeline
calls.