core: indirect draw passes, device feature list, drop handles-specific bundle heuristics

Amp-Thread-ID: https://ampcode.com/threads/T-01a0b2dd-db32-712d-99ce-12ce4a86d979
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-09-18 05:31:11 +00:00
co-authored by heaust
parent dda602c4a2
commit 49c80a209e
11 changed files with 123 additions and 56 deletions
+25
View File
@@ -192,10 +192,23 @@ pub struct Pass {
pub index_buffer: Option<IndexBinding>,
#[serde(default)]
pub draw: Draw,
pub indirect: Option<IndirectBinding>,
#[serde(default = "dispatch")]
pub dispatch: [u32; 3],
}
/// Draw commands read from rows of an `indirect` buffer: one command per row starting at
/// `first`, `count` rows (default: every row to the end of the array). The command occupies the
/// first 16 bytes (non-indexed) or 20 bytes (indexed) of each row; the remainder of the row is
/// free for the caller.
#[derive(Clone, Deserialize, PartialEq, Eq)]
pub struct IndirectBinding {
pub resource: String,
#[serde(default)]
pub first: u32,
pub count: Option<u32>,
}
#[derive(Clone, Deserialize, PartialEq, Eq)]
pub struct Binding {
#[serde(default)]
@@ -344,6 +357,17 @@ impl RenderGraph {
"compute" => _ = compute_pipelines.insert(pass.pipeline.clone()),
_ => return Err("GRAPH_PASS"),
}
if let Some(indirect) = &pass.indirect {
let usable = self
.resources
.buffers
.iter()
.find(|buffer| buffer.id == indirect.resource)
.is_some_and(|buffer| buffer.usage.iter().any(|usage| usage == "indirect"));
if !usable || pass.draw != Draw::default() {
return Err("GRAPH_INDIRECT");
}
}
for id in pass.resources() {
used.insert(id.to_owned());
lifetimes
@@ -532,6 +556,7 @@ impl Pass {
.iter()
.map(|value| value.resource.as_str()),
)
.chain(self.indirect.iter().map(|value| value.resource.as_str()))
.collect()
}
}