1use std::collections::BTreeMap;
5
6use super::pixel::SlotBackend;
7use super::{Bound, Executable};
8use crate::Sampler;
9use iridia::{BufferKind, D3dClass, Program, ResourceId, ResourceKind, StorageTarget};
10
11pub type Constants = BTreeMap<(u32, u32), Vec<[u32; 4]>>;
13
14#[derive(Debug)]
16pub(super) struct Bindings {
17 constants: BTreeMap<ResourceId, (u32, u32)>,
19 slots: BTreeMap<ResourceId, u32>,
20 buffers: BTreeMap<ResourceId, BufferKind>,
21}
22
23impl Bindings {
24 pub(super) fn new(program: &Program) -> Result<Self, String> {
25 let mut constants = BTreeMap::new();
26 let mut slots = BTreeMap::new();
27 let mut buffers = BTreeMap::new();
28 for r in &program.interface.resources {
29 let Some(binding) = r.provenance.d3d else {
30 return Err(format!("resource {} has no D3D bind slot", r.provenance.name));
31 };
32 slots.insert(r.id, binding.register);
33 if matches!(r.kind, ResourceKind::ConstantBuffer { .. })
34 && binding.class == D3dClass::ConstantBuffer
35 {
36 constants.insert(r.id, (binding.register, binding.space));
37 }
38 if let ResourceKind::Buffer(kind)
39 | ResourceKind::Storage {
40 target: StorageTarget::Buffer(kind),
41 ..
42 } = &r.kind
43 {
44 buffers.insert(r.id, *kind);
45 }
46 }
47 Ok(Self {
48 constants,
49 slots,
50 buffers,
51 })
52 }
53
54 pub(super) fn bind<'a>(
56 &self,
57 executable: &Executable,
58 constants: &'a Constants,
59 ) -> Result<Bound<'a>, String> {
60 executable.bind(
61 |id| {
62 let key = self.constants.get(&id)?;
63 constants.get(key).map(Vec::as_slice)
64 },
65 |_| None,
66 )
67 }
68
69 pub(super) fn backend<'a>(&'a self, sampler: &'a mut dyn Sampler) -> SlotBackend<'a> {
71 SlotBackend {
72 sampler,
73 slots: &self.slots,
74 buffers: &self.buffers,
75 }
76 }
77}