1use crate::resources::pipeline_cache::GraphicsPipelineRenderTargetMeta;
2use crate::resources::resource_arc::{ResourceId, ResourceWithHash, WeakResourceArc};
3use crate::resources::ResourceArc;
4use crate::ResourceDropSink;
5use crossbeam_channel::{Receiver, Sender};
6use fnv::{FnvHashMap, FnvHasher};
7use rafx_api::RafxTexture;
8use rafx_api::*;
9use serde::{Deserialize, Serialize};
10use std::hash::{Hash, Hasher};
11use std::marker::PhantomData;
12use std::sync::atomic::AtomicU64;
13use std::sync::atomic::Ordering;
14use std::sync::{Arc, Mutex};
15
16#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
18pub struct ResourceHash(u64);
19
20impl ResourceHash {
21 pub fn from_key<KeyT: Hash>(key: &KeyT) -> ResourceHash {
22 let mut hasher = FnvHasher::default();
23 key.hash(&mut hasher);
24 ResourceHash(hasher.finish())
25 }
26}
27
28impl From<ResourceId> for ResourceHash {
29 fn from(resource_id: ResourceId) -> Self {
30 ResourceHash(resource_id.0)
31 }
32}
33
34impl Into<ResourceId> for ResourceHash {
35 fn into(self) -> ResourceId {
36 ResourceId(self.0)
37 }
38}
39
40pub struct ResourceLookupInner<KeyT, ResourceT>
45where
46 KeyT: Eq + Hash + Clone,
47 ResourceT: Clone,
48{
49 resources: FnvHashMap<ResourceHash, WeakResourceArc<ResourceT>>,
50 drop_sink: ResourceDropSink<ResourceT>,
53 drop_tx: Sender<ResourceWithHash<ResourceT>>,
54 drop_rx: Receiver<ResourceWithHash<ResourceT>>,
55 phantom_data: PhantomData<KeyT>,
56 #[cfg(debug_assertions)]
57 keys: FnvHashMap<ResourceHash, KeyT>,
58 #[cfg(debug_assertions)]
59 lock_call_count_previous_frame: u64,
60 #[cfg(debug_assertions)]
61 lock_call_count: u64,
62 create_count_previous_frame: u64,
63 create_count: u64,
64}
65
66pub struct ResourceLookup<KeyT, ResourceT>
73where
74 KeyT: Eq + Hash + Clone,
75 ResourceT: Clone,
76{
77 inner: Mutex<ResourceLookupInner<KeyT, ResourceT>>,
78}
79
80impl<KeyT, ResourceT> ResourceLookup<KeyT, ResourceT>
81where
82 KeyT: Eq + Hash + Clone,
83 ResourceT: Clone + std::fmt::Debug,
84{
85 pub fn new(max_frames_in_flight: u32) -> Self {
86 let (drop_tx, drop_rx) = crossbeam_channel::unbounded();
87
88 let inner = ResourceLookupInner {
89 resources: Default::default(),
90 drop_sink: ResourceDropSink::new(max_frames_in_flight),
91 drop_tx,
92 drop_rx,
93 phantom_data: Default::default(),
94 #[cfg(debug_assertions)]
95 keys: Default::default(),
96 #[cfg(debug_assertions)]
97 lock_call_count_previous_frame: 0,
98 #[cfg(debug_assertions)]
99 lock_call_count: 0,
100 create_count_previous_frame: 0,
101 create_count: 0,
102 };
103
104 ResourceLookup {
105 inner: Mutex::new(inner),
106 }
107 }
108
109 fn do_get(
110 inner: &mut ResourceLookupInner<KeyT, ResourceT>,
111 hash: ResourceHash,
112 _key: &KeyT,
113 ) -> Option<ResourceArc<ResourceT>> {
114 let resource = inner.resources.get(&hash);
115
116 if let Some(resource) = resource {
117 let upgrade = resource.upgrade();
118 #[cfg(debug_assertions)]
119 if upgrade.is_some() {
120 debug_assert!(inner.keys.get(&hash).unwrap() == _key);
121 }
122
123 upgrade
124 } else {
125 None
126 }
127 }
128
129 fn do_create<F>(
130 inner: &mut ResourceLookupInner<KeyT, ResourceT>,
131 hash: ResourceHash,
132 _key: &KeyT,
133 create_resource_fn: F,
134 ) -> RafxResult<ResourceArc<ResourceT>>
135 where
136 F: FnOnce() -> RafxResult<ResourceT>,
137 {
138 Self::handle_dropped_resources(inner);
141
142 inner.create_count += 1;
143
144 let resource = (create_resource_fn)()?;
145 log::trace!(
146 "insert resource {} {:?}",
147 core::any::type_name::<ResourceT>(),
148 resource
149 );
150
151 let arc = ResourceArc::new(resource, hash.into(), inner.drop_tx.clone());
152 let downgraded = arc.downgrade();
153 let old = inner.resources.insert(hash, downgraded);
154 assert!(old.is_none());
155
156 #[cfg(debug_assertions)]
157 {
158 inner.keys.insert(hash, _key.clone());
159 assert!(old.is_none());
160 }
161
162 Ok(arc)
163 }
164
165 #[allow(dead_code)]
166 pub fn get(
167 &self,
168 key: &KeyT,
169 ) -> Option<ResourceArc<ResourceT>> {
170 let hash = ResourceHash::from_key(key);
171 let mut guard = self.inner.lock().unwrap();
172 #[cfg(debug_assertions)]
173 {
174 guard.lock_call_count += 1;
175 }
176
177 Self::do_get(&mut *guard, hash, key)
178 }
179
180 pub fn create<F>(
181 &self,
182 key: &KeyT,
183 create_resource_fn: F,
184 ) -> RafxResult<ResourceArc<ResourceT>>
185 where
186 F: FnOnce() -> RafxResult<ResourceT>,
187 {
188 let hash = ResourceHash::from_key(key);
189 let mut guard = self.inner.lock().unwrap();
190 #[cfg(debug_assertions)]
191 {
192 guard.lock_call_count += 1;
193 }
194
195 Self::do_create(&mut *guard, hash, key, create_resource_fn)
196 }
197
198 pub fn get_or_create<F>(
199 &self,
200 key: &KeyT,
201 create_resource_fn: F,
202 ) -> RafxResult<ResourceArc<ResourceT>>
203 where
204 F: FnOnce() -> RafxResult<ResourceT>,
205 {
206 let hash = ResourceHash::from_key(key);
207
208 let mut guard = self.inner.lock().unwrap();
209 #[cfg(debug_assertions)]
210 {
211 guard.lock_call_count += 1;
212 }
213
214 if let Some(resource) = Self::do_get(&mut *guard, hash, key) {
215 Ok(resource)
217 } else {
218 Self::do_create(&mut *guard, hash, key, create_resource_fn)
220 }
221 }
222
223 fn handle_dropped_resources(inner: &mut ResourceLookupInner<KeyT, ResourceT>) {
224 for dropped in inner.drop_rx.try_iter() {
225 log::trace!(
226 "queue for delete {} {:?}",
227 core::any::type_name::<ResourceT>(),
228 dropped.resource_hash
229 );
230 inner.drop_sink.retire(dropped.resource);
231 inner.resources.remove(&dropped.resource_hash.into());
232
233 #[cfg(debug_assertions)]
234 {
235 inner.keys.remove(&dropped.resource_hash.into());
236 }
237 }
238 }
239
240 fn on_frame_complete(&self) -> RafxResult<()> {
241 let mut guard = self.inner.lock().unwrap();
242 #[cfg(debug_assertions)]
243 {
244 guard.lock_call_count_previous_frame = guard.lock_call_count + 1;
245 guard.lock_call_count = 0;
246 }
247
248 guard.create_count_previous_frame = guard.create_count;
249 guard.create_count = 0;
250
251 Self::handle_dropped_resources(&mut guard);
252 guard.drop_sink.on_frame_complete()?;
253 Ok(())
254 }
255
256 fn metrics(&self) -> ResourceLookupMetric {
257 let guard = self.inner.lock().unwrap();
258 ResourceLookupMetric {
259 count: guard.resources.len(),
260 previous_frame_create_count: guard.create_count_previous_frame,
261 #[cfg(debug_assertions)]
262 previous_frame_lock_call_count: guard.lock_call_count_previous_frame,
263 }
264 }
265
266 fn destroy(&self) -> RafxResult<()> {
267 let mut guard = self.inner.lock().unwrap();
268 #[cfg(debug_assertions)]
269 {
270 guard.lock_call_count += 1;
271 }
272
273 Self::handle_dropped_resources(&mut guard);
274
275 if !guard.resources.is_empty() {
276 log::warn!(
277 "{} resource count {} > 0, resources will leak",
278 core::any::type_name::<ResourceT>(),
279 guard.resources.len()
280 );
281 }
282
283 guard.drop_sink.destroy()?;
284 Ok(())
285 }
286}
287
288#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
295pub struct FixedFunctionState {
296 pub blend_state: RafxBlendState,
297 pub depth_state: RafxDepthState,
298 pub rasterizer_state: RafxRasterizerState,
299}
300
301#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
302pub struct ShaderHash(u64);
303impl ShaderHash {
304 pub fn new(
305 entry_points: &[&RafxReflectedEntryPoint],
306 shader_module_hashes: &[RafxShaderPackageHash],
307 ) -> Self {
308 let reflection_data: Vec<_> = entry_points
309 .iter()
310 .map(|x| &x.rafx_api_reflection)
311 .collect();
312 let mut hasher = FnvHasher::default();
313 RafxShaderStageDef::hash_definition(&mut hasher, &reflection_data, shader_module_hashes);
314 let hash = hasher.finish();
315 ShaderHash(hash)
316 }
317}
318
319#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
320pub struct SamplerHash(u64);
321impl SamplerHash {
322 pub fn new(sampler_def: &RafxSamplerDef) -> Self {
323 let mut hasher = FnvHasher::default();
324 sampler_def.hash(&mut hasher);
325 let hash = hasher.finish();
326 SamplerHash(hash)
327 }
328}
329
330#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
331pub struct RootSignatureHash(u64);
332impl RootSignatureHash {
333 pub fn new(
334 shader_hashes: &[ShaderHash],
335 immutable_sampler_keys: &[RafxImmutableSamplerKey],
336 immutable_sampler_hashes: &[Vec<SamplerHash>],
337 ) -> Self {
338 let mut hasher = FnvHasher::default();
339 RafxRootSignatureDef::hash_definition(
340 &mut hasher,
341 shader_hashes,
342 immutable_sampler_keys,
343 immutable_sampler_hashes,
344 );
345 let hash = hasher.finish();
346 RootSignatureHash(hash)
347 }
348}
349
350#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
351pub struct DescriptorSetLayoutHash(u64);
352impl DescriptorSetLayoutHash {
353 pub fn new(
354 root_signature_hash: RootSignatureHash,
355 set_index: u32,
356 bindings: &RafxReflectedDescriptorSetLayout,
357 ) -> Self {
358 let mut hasher = FnvHasher::default();
359 root_signature_hash.hash(&mut hasher);
360 set_index.hash(&mut hasher);
361 bindings.hash(&mut hasher);
362 let hash = hasher.finish();
363 DescriptorSetLayoutHash(hash)
364 }
365}
366
367#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
368pub struct MaterialPassHash(u64);
369impl MaterialPassHash {
370 pub fn new(
371 shader_hash: ShaderHash,
372 root_signature_hash: RootSignatureHash,
373 descriptor_set_layout_hashes: &[DescriptorSetLayoutHash],
374 fixed_function_state: &FixedFunctionState,
375 vertex_inputs: &[MaterialPassVertexInput],
376 ) -> Self {
377 let mut hasher = FnvHasher::default();
378 shader_hash.hash(&mut hasher);
379 root_signature_hash.hash(&mut hasher);
380 descriptor_set_layout_hashes.hash(&mut hasher);
381 fixed_function_state.hash(&mut hasher);
382 for vertex_input in vertex_inputs {
383 vertex_input.hash(&mut hasher);
384 }
385 let hash = hasher.finish();
386 MaterialPassHash(hash)
387 }
388}
389
390#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
391pub struct GraphicsPipelineHash(u64);
392impl GraphicsPipelineHash {
393 pub fn new(
394 material_pass_key: MaterialPassHash,
395 render_target_meta: &GraphicsPipelineRenderTargetMeta,
396 primitive_topology: RafxPrimitiveTopology,
397 vertex_layout: &RafxVertexLayout,
398 ) -> Self {
399 let mut hasher = FnvHasher::default();
400 material_pass_key.hash(&mut hasher);
401 render_target_meta
402 .render_target_meta_hash()
403 .hash(&mut hasher);
404 primitive_topology.hash(&mut hasher);
405 vertex_layout.hash(&mut hasher);
406 let hash = hasher.finish();
407 GraphicsPipelineHash(hash)
408 }
409}
410
411#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
412pub struct ComputePipelineHash(u64);
413impl ComputePipelineHash {
414 pub fn new(
415 shader_hash: ShaderHash,
416 root_signature_hash: RootSignatureHash,
417 descriptor_set_layout_hashes: &[DescriptorSetLayoutHash],
418 ) -> Self {
419 let mut hasher = FnvHasher::default();
420 shader_hash.hash(&mut hasher);
421 root_signature_hash.hash(&mut hasher);
422 descriptor_set_layout_hashes.hash(&mut hasher);
423 let hash = hasher.finish();
424 ComputePipelineHash(hash)
425 }
426}
427
428#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
429pub struct ShaderModuleKey {
430 hash: RafxShaderPackageHash,
431}
432
433#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
434pub struct ShaderKey {
435 hash: ShaderHash,
436}
437
438#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
439pub struct RootSignatureKey {
440 hash: RootSignatureHash,
442}
443
444#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
445pub struct DescriptorSetLayoutKey {
446 hash: DescriptorSetLayoutHash,
447}
448
449#[derive(Debug, Clone, PartialEq, Eq, Hash)]
450pub struct MaterialPassVertexInput {
451 pub semantic: String,
452 pub location: u32,
453 pub gl_attribute_name: String,
454}
455
456#[derive(Debug, Clone, PartialEq, Eq, Hash)]
457pub struct MaterialPassKey {
458 hash: MaterialPassHash,
459}
460
461#[derive(Debug, Clone, PartialEq, Eq, Hash)]
462pub struct GraphicsPipelineKey {
463 hash: GraphicsPipelineHash,
464}
465
466#[derive(Debug, Clone, PartialEq, Eq, Hash)]
467pub struct ComputePipelineKey {
468 hash: ComputePipelineHash,
469}
470
471#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
472pub struct ImageKey {
473 id: u64,
474}
475
476#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
477pub struct BufferKey {
478 id: u64,
479}
480
481#[derive(Debug, Clone, PartialEq, Eq, Hash)]
482pub struct SamplerKey {
483 hash: SamplerHash,
484}
485
486#[derive(Debug, Clone, PartialEq, Eq, Hash)]
487pub struct ImageViewKey {
488 image_key: ImageKey,
489 texture_bind_type: Option<RafxTextureBindType>,
490}
491
492#[derive(Debug)]
493pub struct ResourceLookupMetric {
494 pub count: usize,
495 pub previous_frame_create_count: u64,
496 #[cfg(debug_assertions)]
497 pub previous_frame_lock_call_count: u64,
498}
499
500#[derive(Debug)]
501pub struct ResourceMetrics {
502 pub shader_module_metrics: ResourceLookupMetric,
503 pub shader_metrics: ResourceLookupMetric,
504 pub root_signature_metrics: ResourceLookupMetric,
505 pub descriptor_set_layout_metrics: ResourceLookupMetric,
506 pub material_pass_metrics: ResourceLookupMetric,
507 pub graphics_pipeline_metrics: ResourceLookupMetric,
508 pub compute_pipeline_metrics: ResourceLookupMetric,
509 pub image_metrics: ResourceLookupMetric,
510 pub image_view_metrics: ResourceLookupMetric,
511 pub sampler_metrics: ResourceLookupMetric,
512 pub buffer_metrics: ResourceLookupMetric,
513}
514
515#[derive(Debug, Clone)]
516pub struct ShaderModuleResource {
517 pub shader_module_key: ShaderModuleKey,
518 pub shader_package: Arc<RafxShaderPackage>,
519 pub shader_module: RafxShaderModule,
520}
521
522#[derive(Debug, Clone)]
523pub struct ShaderResource {
524 pub key: ShaderKey,
525 pub shader_modules: Vec<ResourceArc<ShaderModuleResource>>,
526 pub shader: RafxShader,
527}
528
529#[derive(Debug, Clone)]
530pub struct RootSignatureResource {
531 pub key: RootSignatureKey,
532 pub shaders: Vec<ResourceArc<ShaderResource>>,
533 pub immutable_samplers: Vec<ResourceArc<SamplerResource>>,
534 pub root_signature: RafxRootSignature,
535}
536
537#[derive(Debug, Clone)]
538pub struct DescriptorSetLayoutResource {
539 pub root_signature_arc: ResourceArc<RootSignatureResource>,
541 pub root_signature: RafxRootSignature,
542 pub set_index: u32,
543
544 pub descriptor_set_layout_def: Arc<RafxReflectedDescriptorSetLayout>,
545 pub key: DescriptorSetLayoutKey,
546}
547
548#[derive(Debug, Clone)]
549pub struct MaterialPassResource {
550 pub material_pass_key: MaterialPassKey,
551 pub shader: ResourceArc<ShaderResource>,
552 pub root_signature: ResourceArc<RootSignatureResource>,
553 pub descriptor_set_layouts: Arc<Vec<ResourceArc<DescriptorSetLayoutResource>>>,
554 pub fixed_function_state: Arc<FixedFunctionState>,
555 pub vertex_inputs: Arc<Vec<MaterialPassVertexInput>>,
556 pub debug_name: Option<String>,
557}
558
559#[derive(Debug, Clone)]
560pub struct GraphicsPipelineResource {
561 pub render_target_meta: GraphicsPipelineRenderTargetMeta,
562 pub pipeline: Arc<RafxPipeline>,
563 pub descriptor_set_layouts: Arc<Vec<ResourceArc<DescriptorSetLayoutResource>>>,
564}
565
566#[derive(Debug, Clone)]
567pub struct ComputePipelineResource {
568 pub root_signature: ResourceArc<RootSignatureResource>,
569 pub pipeline: Arc<RafxPipeline>,
570 pub descriptor_set_layouts: Arc<Vec<ResourceArc<DescriptorSetLayoutResource>>>,
571}
572
573#[derive(Debug, Clone)]
574pub struct ImageResource {
575 pub image: RafxTexture,
576 pub image_key: Option<ImageKey>,
578}
579
580#[derive(Debug, Clone)]
581pub struct ImageViewResource {
582 pub image: ResourceArc<ImageResource>,
583 pub image_view_key: Option<ImageViewKey>,
585 pub texture_bind_type: Option<RafxTextureBindType>,
586}
587
588#[derive(Debug, Clone)]
589pub struct SamplerResource {
590 pub sampler: RafxSampler,
591 pub sampler_key: SamplerKey,
592}
593
594#[derive(Debug, Clone)]
595pub struct BufferResource {
596 pub buffer: Arc<RafxBuffer>,
597 pub buffer_key: Option<BufferKey>,
599}
600
601pub struct ResourceLookupSetInner {
611 device_context: RafxDeviceContext,
612
613 shader_modules: ResourceLookup<ShaderModuleKey, ShaderModuleResource>,
614 shaders: ResourceLookup<ShaderKey, ShaderResource>,
615 root_signatures: ResourceLookup<RootSignatureKey, RootSignatureResource>,
616 descriptor_set_layouts: ResourceLookup<DescriptorSetLayoutKey, DescriptorSetLayoutResource>,
617 material_passes: ResourceLookup<MaterialPassKey, MaterialPassResource>,
618 graphics_pipelines: ResourceLookup<GraphicsPipelineKey, GraphicsPipelineResource>,
619 compute_pipelines: ResourceLookup<ComputePipelineKey, ComputePipelineResource>,
620 images: ResourceLookup<ImageKey, ImageResource>,
621 image_views: ResourceLookup<ImageViewKey, ImageViewResource>,
622 samplers: ResourceLookup<SamplerKey, SamplerResource>,
623 buffers: ResourceLookup<BufferKey, BufferResource>,
624
625 next_image_id: AtomicU64,
627 next_buffer_id: AtomicU64,
628}
629
630#[derive(Clone)]
631pub struct ResourceLookupSet {
632 inner: Arc<ResourceLookupSetInner>,
633}
634
635impl ResourceLookupSet {
636 pub fn new(
637 device_context: &RafxDeviceContext,
638 max_frames_in_flight: u32,
639 ) -> Self {
640 let set = ResourceLookupSetInner {
641 device_context: device_context.clone(),
642 shader_modules: ResourceLookup::new(max_frames_in_flight),
643 shaders: ResourceLookup::new(max_frames_in_flight),
644 root_signatures: ResourceLookup::new(max_frames_in_flight),
645 descriptor_set_layouts: ResourceLookup::new(max_frames_in_flight),
646 material_passes: ResourceLookup::new(max_frames_in_flight),
647 graphics_pipelines: ResourceLookup::new(max_frames_in_flight),
648 compute_pipelines: ResourceLookup::new(max_frames_in_flight),
649 images: ResourceLookup::new(max_frames_in_flight),
650 image_views: ResourceLookup::new(max_frames_in_flight),
651 samplers: ResourceLookup::new(max_frames_in_flight),
652 buffers: ResourceLookup::new(max_frames_in_flight),
653 next_image_id: AtomicU64::new(0),
654 next_buffer_id: AtomicU64::new(0),
655 };
656
657 ResourceLookupSet {
658 inner: Arc::new(set),
659 }
660 }
661
662 pub fn device_context(&self) -> &RafxDeviceContext {
663 &self.inner.device_context
664 }
665
666 #[profiling::function]
667 pub fn on_frame_complete(&self) -> RafxResult<()> {
668 self.inner.images.on_frame_complete()?;
669 self.inner.image_views.on_frame_complete()?;
670 self.inner.buffers.on_frame_complete()?;
671 self.inner.shader_modules.on_frame_complete()?;
672 self.inner.shaders.on_frame_complete()?;
673 self.inner.samplers.on_frame_complete()?;
674 self.inner.root_signatures.on_frame_complete()?;
675 self.inner.descriptor_set_layouts.on_frame_complete()?;
676 self.inner.material_passes.on_frame_complete()?;
677 self.inner.graphics_pipelines.on_frame_complete()?;
678 self.inner.compute_pipelines.on_frame_complete()?;
679 Ok(())
680 }
681
682 pub fn destroy(&self) -> RafxResult<()> {
685 self.inner.compute_pipelines.destroy()?;
688 self.inner.graphics_pipelines.destroy()?;
689 self.inner.material_passes.destroy()?;
690 self.inner.descriptor_set_layouts.destroy()?;
691 self.inner.root_signatures.destroy()?;
692 self.inner.samplers.destroy()?;
693 self.inner.shaders.destroy()?;
694 self.inner.shader_modules.destroy()?;
695 self.inner.buffers.destroy()?;
696 self.inner.image_views.destroy()?;
697 self.inner.images.destroy()?;
698 Ok(())
699 }
700
701 pub fn metrics(&self) -> ResourceMetrics {
702 ResourceMetrics {
703 shader_module_metrics: self.inner.shader_modules.metrics(),
704 shader_metrics: self.inner.shaders.metrics(),
705 root_signature_metrics: self.inner.root_signatures.metrics(),
706 descriptor_set_layout_metrics: self.inner.descriptor_set_layouts.metrics(),
707 material_pass_metrics: self.inner.material_passes.metrics(),
708 graphics_pipeline_metrics: self.inner.graphics_pipelines.metrics(),
709 compute_pipeline_metrics: self.inner.compute_pipelines.metrics(),
710 image_metrics: self.inner.images.metrics(),
711 image_view_metrics: self.inner.image_views.metrics(),
712 sampler_metrics: self.inner.samplers.metrics(),
713 buffer_metrics: self.inner.buffers.metrics(),
714 }
715 }
716
717 pub fn get_or_create_shader_module_from_hashed_package(
718 &self,
719 package: &RafxHashedShaderPackage,
720 ) -> RafxResult<ResourceArc<ShaderModuleResource>> {
721 self.get_or_create_shader_module(
722 package.shader_package(),
723 Some(package.shader_package_hash()),
724 )
725 }
726
727 pub fn get_or_create_shader_module(
728 &self,
729 shader_package: &RafxShaderPackage,
730 shader_package_hash: Option<RafxShaderPackageHash>,
731 ) -> RafxResult<ResourceArc<ShaderModuleResource>> {
732 let shader_package_hash =
733 shader_package_hash.unwrap_or_else(|| RafxShaderPackageHash::new(shader_package));
734
735 let shader_module_key = ShaderModuleKey {
736 hash: shader_package_hash,
737 };
738
739 self.inner
740 .shader_modules
741 .get_or_create(&shader_module_key, || {
742 log::trace!(
743 "Creating shader module\n[hash: {:?}]",
744 shader_module_key.hash,
745 );
746
747 let shader_module = self
748 .inner
749 .device_context
750 .create_shader_module(shader_package.module_def())?;
751
752 let resource = ShaderModuleResource {
753 shader_module,
754 shader_package: Arc::new(shader_package.clone()),
755 shader_module_key: shader_module_key.clone(),
756 };
757 log::trace!("Created shader module {:?}", resource);
758 Ok(resource)
759 })
760 }
761
762 pub fn get_or_create_sampler(
763 &self,
764 sampler_def: &RafxSamplerDef,
765 ) -> RafxResult<ResourceArc<SamplerResource>> {
766 let hash = SamplerHash::new(sampler_def);
767 let sampler_key = SamplerKey { hash };
768
769 self.inner.samplers.get_or_create(&sampler_key, || {
770 log::trace!("Creating sampler\n{:#?}", sampler_def);
771
772 let sampler = self.inner.device_context.create_sampler(sampler_def)?;
773
774 let resource = SamplerResource {
775 sampler,
776 sampler_key: sampler_key.clone(),
777 };
778
779 log::trace!("Created sampler {:?}", resource);
780 Ok(resource)
781 })
782 }
783
784 pub fn get_or_create_shader(
785 &self,
786 shader_modules: &[ResourceArc<ShaderModuleResource>],
787 entry_points: &[&RafxReflectedEntryPoint],
788 ) -> RafxResult<ResourceArc<ShaderResource>> {
789 let shader_module_hashes: Vec<_> = shader_modules
790 .iter()
791 .map(|x| x.get_raw().shader_module_key.hash)
792 .collect();
793
794 let hash = ShaderHash::new(entry_points, &shader_module_hashes);
795 let key = ShaderKey { hash };
796
797 self.inner.shaders.get_or_create(&key, || {
798 log::trace!("Creating shader\n");
799
800 let mut shader_defs = Vec::with_capacity(entry_points.len());
801 for (entry_point, module) in entry_points.iter().zip(shader_modules) {
802 shader_defs.push(RafxShaderStageDef {
803 shader_module: module.get_raw().shader_module.clone(),
804 reflection: entry_point.rafx_api_reflection.clone(),
805 });
806 }
807
808 let shader = self.inner.device_context.create_shader(shader_defs)?;
809
810 let resource = ShaderResource {
811 key,
812 shader,
813 shader_modules: shader_modules.iter().cloned().collect(),
814 };
815
816 log::trace!("Created shader {:?}", resource);
817 Ok(resource)
818 })
819 }
820
821 pub fn get_or_create_root_signature(
822 &self,
823 shader_resources: &[ResourceArc<ShaderResource>],
824 immutable_sampler_keys: &[RafxImmutableSamplerKey],
825 immutable_sampler_resources: &[Vec<ResourceArc<SamplerResource>>],
826 ) -> RafxResult<ResourceArc<RootSignatureResource>> {
827 let shader_hashes: Vec<_> = shader_resources
828 .iter()
829 .map(|x| x.get_raw().key.hash)
830 .collect();
831
832 let mut sampler_hashes = Vec::with_capacity(immutable_sampler_resources.len());
833 for sampler_list in immutable_sampler_resources {
834 let hashes: Vec<_> = sampler_list
835 .iter()
836 .map(|x| x.get_raw().sampler_key.hash)
837 .collect();
838 sampler_hashes.push(hashes);
839 }
840
841 let hash = RootSignatureHash::new(&shader_hashes, immutable_sampler_keys, &sampler_hashes);
842 let key = RootSignatureKey { hash };
843
844 self.inner.root_signatures.get_or_create(&key, || {
845 let mut samplers = Vec::with_capacity(immutable_sampler_resources.len());
846 for sampler_list in immutable_sampler_resources {
847 let cloned_sampler_list: Vec<_> = sampler_list
848 .iter()
849 .map(|x| x.get_raw().sampler.clone())
850 .collect();
851 samplers.push(cloned_sampler_list);
852 }
853
854 let mut immutable_samplers = Vec::with_capacity(samplers.len());
855 for i in 0..samplers.len() {
856 immutable_samplers.push(RafxImmutableSamplers {
857 key: immutable_sampler_keys[i].clone(),
858 samplers: &samplers[i],
859 });
860 }
861
862 log::trace!("Creating root signature\n{:#?}", key);
863 let shaders: Vec<_> = shader_resources
864 .iter()
865 .map(|x| x.get_raw().shader.clone())
866 .collect();
867 let root_signature =
868 self.inner
869 .device_context
870 .create_root_signature(&RafxRootSignatureDef {
871 shaders: &shaders,
872 immutable_samplers: &immutable_samplers,
873 })?;
874
875 let shaders = shader_resources.iter().cloned().collect();
876
877 let mut immutable_samplers = vec![];
878 for resource_list in immutable_sampler_resources {
879 for resource in resource_list {
880 immutable_samplers.push(resource.clone());
881 }
882 }
883
884 let resource = RootSignatureResource {
885 key,
886 root_signature,
887 shaders,
888 immutable_samplers,
889 };
890
891 log::trace!("Created root signature");
892 Ok(resource)
893 })
894 }
895
896 pub fn get_or_create_descriptor_set_layout(
897 &self,
898 root_signature: &ResourceArc<RootSignatureResource>,
899 set_index: u32,
900 descriptor_set_layout_def: &RafxReflectedDescriptorSetLayout,
901 ) -> RafxResult<ResourceArc<DescriptorSetLayoutResource>> {
902 let hash = DescriptorSetLayoutHash::new(
903 root_signature.get_raw().key.hash,
904 set_index,
905 descriptor_set_layout_def,
906 );
907 let key = DescriptorSetLayoutKey { hash };
908
909 self.inner.descriptor_set_layouts.get_or_create(&key, || {
910 log::trace!(
911 "Creating descriptor set layout set_index={}, root_signature:\n{:#?}",
912 set_index,
913 root_signature
914 );
915
916 let resource = DescriptorSetLayoutResource {
919 root_signature_arc: root_signature.clone(),
920 root_signature: root_signature.get_raw().root_signature.clone(),
921 set_index,
922 descriptor_set_layout_def: Arc::new(descriptor_set_layout_def.clone()),
923 key: key.clone(),
924 };
925
926 log::trace!("Created descriptor set layout {:?}", resource);
927 Ok(resource)
928 })
929 }
930
931 pub fn get_or_create_material_pass(
932 &self,
933 shader: ResourceArc<ShaderResource>,
934 root_signature: ResourceArc<RootSignatureResource>,
935 descriptor_sets: Vec<ResourceArc<DescriptorSetLayoutResource>>,
936 fixed_function_state: Arc<FixedFunctionState>,
937 vertex_inputs: Arc<Vec<MaterialPassVertexInput>>,
938 debug_name: Option<&str>,
939 ) -> RafxResult<ResourceArc<MaterialPassResource>> {
940 let descriptor_set_hashes: Vec<_> = descriptor_sets
941 .iter()
942 .map(|x| x.get_raw().key.hash)
943 .collect();
944 let hash = MaterialPassHash::new(
945 shader.get_raw().key.hash,
946 root_signature.get_raw().key.hash,
947 &descriptor_set_hashes,
948 &*fixed_function_state,
949 &*vertex_inputs,
950 );
951 let material_pass_key = MaterialPassKey { hash };
952
953 self.inner
954 .material_passes
955 .get_or_create(&material_pass_key, || {
956 log::trace!("Creating material pass\n{:#?}", material_pass_key);
957 let debug_name = debug_name.map(|x| format!("MaterialPass {}", x));
958 let resource = MaterialPassResource {
959 material_pass_key: material_pass_key.clone(),
960 root_signature,
961 descriptor_set_layouts: Arc::new(descriptor_sets),
962 shader,
963 fixed_function_state,
964 vertex_inputs,
965 debug_name,
966 };
967 Ok(resource)
968 })
969 }
970
971 pub fn get_or_create_graphics_pipeline(
972 &self,
973 material_pass: &ResourceArc<MaterialPassResource>,
974 render_target_meta: &GraphicsPipelineRenderTargetMeta,
975 primitive_topology: RafxPrimitiveTopology,
976 vertex_layout: &RafxVertexLayout,
977 ) -> RafxResult<ResourceArc<GraphicsPipelineResource>> {
978 let hash = GraphicsPipelineHash::new(
979 material_pass.get_raw().material_pass_key.hash,
980 render_target_meta,
981 primitive_topology,
982 vertex_layout,
983 );
984
985 let pipeline_key = GraphicsPipelineKey { hash };
986
987 self.inner
988 .graphics_pipelines
989 .get_or_create(&pipeline_key, || {
990 log::trace!("Creating graphics pipeline\n{:#?}", pipeline_key);
991 let debug_name = material_pass
992 .get_raw()
993 .debug_name
994 .as_ref()
995 .map(|x| format!("RafxGraphicsPipeline {}", x));
996
997 let fixed_function_state = &material_pass.get_raw().fixed_function_state;
998 let pipeline = self.inner.device_context.create_graphics_pipeline(
999 &RafxGraphicsPipelineDef {
1000 root_signature: &material_pass
1001 .get_raw()
1002 .root_signature
1003 .get_raw()
1004 .root_signature,
1005
1006 shader: &material_pass.get_raw().shader.get_raw().shader,
1007
1008 blend_state: &fixed_function_state.blend_state,
1009 depth_state: &fixed_function_state.depth_state,
1010 rasterizer_state: &fixed_function_state.rasterizer_state,
1011
1012 primitive_topology,
1013 vertex_layout: &vertex_layout,
1014
1015 color_formats: &render_target_meta.color_formats(),
1016 depth_stencil_format: render_target_meta.depth_stencil_format(),
1017 sample_count: render_target_meta.sample_count(),
1018 debug_name: debug_name.as_deref(),
1019 },
1020 )?;
1021
1022 let resource = GraphicsPipelineResource {
1023 render_target_meta: render_target_meta.clone(),
1024 pipeline: Arc::new(pipeline),
1025 descriptor_set_layouts: material_pass.get_raw().descriptor_set_layouts.clone(),
1026 };
1027 Ok(resource)
1028 })
1029 }
1030
1031 pub fn get_or_create_compute_pipeline(
1032 &self,
1033 shader: &ResourceArc<ShaderResource>,
1034 root_signature: &ResourceArc<RootSignatureResource>,
1035 descriptor_set_layouts: Vec<ResourceArc<DescriptorSetLayoutResource>>,
1036 debug_name: Option<&str>,
1037 ) -> RafxResult<ResourceArc<ComputePipelineResource>> {
1038 let descriptor_set_hashes: Vec<_> = descriptor_set_layouts
1039 .iter()
1040 .map(|x| x.get_raw().key.hash)
1041 .collect();
1042 let hash = ComputePipelineHash::new(
1043 shader.get_raw().key.hash,
1044 root_signature.get_raw().key.hash,
1045 &descriptor_set_hashes,
1046 );
1047 let pipeline_key = ComputePipelineKey { hash };
1048
1049 self.inner
1050 .compute_pipelines
1051 .get_or_create(&pipeline_key, || {
1052 log::trace!("Creating compute pipeline\n{:#?}", pipeline_key);
1053 let debug_name = debug_name.map(|x| format!("RafxComputePipeline {}", x));
1054 let rafx_pipeline =
1055 self.inner
1056 .device_context
1057 .create_compute_pipeline(&RafxComputePipelineDef {
1058 root_signature: &root_signature.get_raw().root_signature,
1059 shader: &shader.get_raw().shader,
1060 debug_name: debug_name.as_deref(),
1061 })?;
1062 log::trace!("Created compute pipeline {:?}", rafx_pipeline);
1063
1064 let resource = ComputePipelineResource {
1065 root_signature: root_signature.clone(),
1066 pipeline: Arc::new(rafx_pipeline),
1067 descriptor_set_layouts: Arc::new(descriptor_set_layouts),
1068 };
1069 Ok(resource)
1070 })
1071 }
1072
1073 pub fn insert_image(
1074 &self,
1075 image: RafxTexture,
1076 ) -> ResourceArc<ImageResource> {
1077 let image_id = self.inner.next_image_id.fetch_add(1, Ordering::Relaxed);
1078
1079 let image_key = ImageKey { id: image_id };
1080
1081 let resource = ImageResource {
1082 image,
1083 image_key: Some(image_key),
1084 };
1085
1086 self.inner
1087 .images
1088 .create(&image_key, || Ok(resource))
1089 .unwrap()
1090 }
1091
1092 pub fn insert_buffer(
1098 &self,
1099 buffer: RafxBuffer,
1100 ) -> ResourceArc<BufferResource> {
1101 let buffer_id = self.inner.next_buffer_id.fetch_add(1, Ordering::Relaxed);
1102 let buffer_key = BufferKey { id: buffer_id };
1103
1104 let resource = BufferResource {
1105 buffer: Arc::new(buffer),
1106 buffer_key: Some(buffer_key),
1107 };
1108
1109 self.inner
1110 .buffers
1111 .create(&buffer_key, || Ok(resource))
1112 .unwrap()
1113 }
1114
1115 pub fn get_or_create_image_view(
1116 &self,
1117 image: &ResourceArc<ImageResource>,
1118 texture_bind_type: Option<RafxTextureBindType>,
1119 ) -> RafxResult<ResourceArc<ImageViewResource>> {
1120 if image.get_raw().image_key.is_none() {
1121 log::error!("Tried to create an image view resource with a dynamic image");
1122 return Err("Tried to create an image view resource with a dynamic image")?;
1123 }
1124
1125 let image_view_key = ImageViewKey {
1126 image_key: image.get_raw().image_key.unwrap(),
1127 texture_bind_type,
1128 };
1129
1130 self.inner.image_views.get_or_create(&image_view_key, || {
1131 log::trace!("Creating image view\n{:#?}", image_view_key);
1132 let resource = ImageViewResource {
1133 image: image.clone(),
1134 texture_bind_type,
1135 image_view_key: Some(image_view_key.clone()),
1136 };
1137 log::trace!("Created image view\n{:#?}", resource);
1138
1139 Ok(resource)
1140 })
1141 }
1142}