Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  descriptor.rs

  Sprache: Rust
 

use std::fmt;

use bit_set::BitSet;
use parking_lot::Mutex;
use range_alloc::RangeAllocator;
use windows::Win32::Graphics::Direct3D12;

use crate::auxil::dxgi::result::HResult as _;

const HEAP_SIZE_FIXED: usize = 64;

#[derive(Copy, Clone)]
pub(superstruct DualHandle {
    cpu: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE,
    pub gpu: Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE,
    /// How large the block allocated to this handle is.
    count: u64,
}

impl fmt::Debug for DualHandle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("DualHandle")
            .field("cpu", &self.cpu.ptr)
            .field("gpu", &self.gpu.ptr)
            .field("count", &self.count)
            .finish()
    }
}

type DescriptorIndex = u64;

pub(superstruct GeneralHeap {
    pub raw: Direct3D12::ID3D12DescriptorHeap,
    ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE,
    handle_size: u64,
    total_handles: u64,
    start: DualHandle,
    ranges: Mutex<RangeAllocator<DescriptorIndex>>,
}

impl GeneralHeap {
    pub(superfn new(
        device: &Direct3D12::ID3D12Device,
        ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE,
        total_handles: u64,
    ) -> Result<Selfcrate::DeviceError> {
        let raw = {
            profiling::scope!("ID3D12Device::CreateDescriptorHeap");
            let desc = Direct3D12::D3D12_DESCRIPTOR_HEAP_DESC {
                Type: ty,
                NumDescriptors: total_handles as u32,
                Flags: Direct3D12::D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
                NodeMask: 0,
            };
            unsafe { device.CreateDescriptorHeap::<Direct3D12::ID3D12DescriptorHeap>(&desc) }
                .into_device_result("Descriptor heap creation")?
        };

        let start = DualHandle {
            cpu: unsafe { raw.GetCPUDescriptorHandleForHeapStart() },
            gpu: unsafe { raw.GetGPUDescriptorHandleForHeapStart() },
            count: 0,
        };

        Ok(Self {
            raw,
            ty,
            handle_size: unsafe { device.GetDescriptorHandleIncrementSize(ty) } as u64,
            total_handles,
            start,
            ranges: Mutex::new(RangeAllocator::new(0..total_handles)),
        })
    }

    pub(superfn at(&self, index: DescriptorIndex, count: u64) -> DualHandle {
        assert!(index < self.total_handles);
        DualHandle {
            cpu: self.cpu_descriptor_at(index),
            gpu: self.gpu_descriptor_at(index),
            count,
        }
    }

    fn cpu_descriptor_at(&self, index: u64) -> Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE {
        Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE {
            ptr: self.start.cpu.ptr + (self.handle_size * index) as usize,
        }
    }

    fn gpu_descriptor_at(&self, index: u64) -> Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE {
        Direct3D12::D3D12_GPU_DESCRIPTOR_HANDLE {
            ptr: self.start.gpu.ptr + self.handle_size * index,
        }
    }

    pub(superfn allocate_slice(&self, count: u64) -> Result<DescriptorIndex, crate::DeviceError> {
        let range = self.ranges.lock().allocate_range(count).map_err(|err| {
            log::error!("Unable to allocate descriptors: {:?}", err);
            crate::DeviceError::OutOfMemory
        })?;
        Ok(range.start)
    }

    /// Free handles previously given out by this `DescriptorHeapSlice`.
    /// Do not use this with handles not given out by this `DescriptorHeapSlice`.
    pub(cratefn free_slice(&self, handle: DualHandle) {
        let start = (handle.gpu.ptr - self.start.gpu.ptr) / self.handle_size;
        self.ranges.lock().free_range(start..start + handle.count);
    }
}

/// Fixed-size free-list allocator for CPU descriptors.
struct FixedSizeHeap {
    _raw: Direct3D12::ID3D12DescriptorHeap,
    /// Bit flag representation of available handles in the heap.
    ///
    ///  0 - Occupied
    ///  1 - free
    availability: u64,
    handle_size: usize,
    start: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE,
}

impl FixedSizeHeap {
    fn new(
        device: &Direct3D12::ID3D12Device,
        ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE,
    ) -> Result<Selfcrate::DeviceError> {
        let desc = Direct3D12::D3D12_DESCRIPTOR_HEAP_DESC {
            Type: ty,
            NumDescriptors: HEAP_SIZE_FIXED as u32,
            Flags: Direct3D12::D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
            NodeMask: 0,
        };
        let heap =
            unsafe { device.CreateDescriptorHeap::<Direct3D12::ID3D12DescriptorHeap>(&desc) }
                .into_device_result("Descriptor heap creation")?;

        Ok(Self {
            handle_size: unsafe { device.GetDescriptorHandleIncrementSize(ty) } as usize,
            availability: !0// all free!
            start: unsafe { heap.GetCPUDescriptorHandleForHeapStart() },
            _raw: heap,
        })
    }

    fn alloc_handle(
        &mut self,
    ) -> Result<Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE, crate::DeviceError> {
        // Find first free slot.
        let slot = self.availability.trailing_zeros() as usize;
        if slot >= HEAP_SIZE_FIXED {
            log::error!("Failed to allocate a handle form a fixed size heap");
            return Err(crate::DeviceError::OutOfMemory);
        }
        // Set the slot as occupied.
        self.availability ^= 1 << slot;

        Ok(Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE {
            ptr: self.start.ptr + self.handle_size * slot,
        })
    }

    fn free_handle(&mut self, handle: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE) {
        let slot = (handle.ptr - self.start.ptr) / self.handle_size;
        assert!(slot < HEAP_SIZE_FIXED);
        assert_eq!(self.availability & (1 << slot), 0);
        self.availability ^= 1 << slot;
    }

    fn is_full(&self) -> bool {
        self.availability == 0
    }
}

#[derive(Clone, Copy)]
pub(superstruct Handle {
    pub raw: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE,
    heap_index: usize,
}

impl fmt::Debug for Handle {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Handle")
            .field("ptr", &self.raw.ptr)
            .field("heap_index", &self.heap_index)
            .finish()
    }
}

pub(superstruct CpuPool {
    device: Direct3D12::ID3D12Device,
    ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE,
    heaps: Vec<FixedSizeHeap>,
    available_heap_indices: BitSet,
}

impl CpuPool {
    pub(superfn new(
        device: Direct3D12::ID3D12Device,
        ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE,
    ) -> Self {
        Self {
            device,
            ty,
            heaps: Vec::new(),
            available_heap_indices: BitSet::new(),
        }
    }

    pub(superfn alloc_handle(&mut self) -> Result<Handle, crate::DeviceError> {
        let heap_index = self
            .available_heap_indices
            .iter()
            .next()
            .unwrap_or(self.heaps.len());

        // Allocate a new heap
        if heap_index == self.heaps.len() {
            self.heaps.push(FixedSizeHeap::new(&self.device, self.ty)?);
            self.available_heap_indices.insert(heap_index);
        }

        let heap = &mut self.heaps[heap_index];
        let handle = Handle {
            raw: heap.alloc_handle()?,
            heap_index,
        };
        if heap.is_full() {
            self.available_heap_indices.remove(heap_index);
        }

        Ok(handle)
    }

    pub(superfn free_handle(&mut self, handle: Handle) {
        self.heaps[handle.heap_index].free_handle(handle.raw);
        self.available_heap_indices.insert(handle.heap_index);
    }
}

pub(superstruct CpuHeapInner {
    pub _raw: Direct3D12::ID3D12DescriptorHeap,
    pub stage: Vec<Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE>,
}

pub(superstruct CpuHeap {
    pub inner: Mutex<CpuHeapInner>,
    start: Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE,
    handle_size: u32,
    total: u32,
}

unsafe impl Send for CpuHeap {}
unsafe impl Sync for CpuHeap {}

impl CpuHeap {
    pub(superfn new(
        device: &Direct3D12::ID3D12Device,
        ty: Direct3D12::D3D12_DESCRIPTOR_HEAP_TYPE,
        total: u32,
    ) -> Result<Selfcrate::DeviceError> {
        let handle_size = unsafe { device.GetDescriptorHandleIncrementSize(ty) };
        let desc = Direct3D12::D3D12_DESCRIPTOR_HEAP_DESC {
            Type: ty,
            NumDescriptors: total,
            Flags: Direct3D12::D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
            NodeMask: 0,
        };
        let raw = unsafe { device.CreateDescriptorHeap::<Direct3D12::ID3D12DescriptorHeap>(&desc) ;}
            .into_device_result("CPU descriptor heap creation")?;

        let start = unsafe { raw.GetCPUDescriptorHandleForHeapStart() };

        Ok(Self {
            inner: Mutex::new(CpuHeapInner {
                _raw: raw,
                stage: Vec::new(),
            }),
            start,
            handle_size,
            total,
        })
    }

    pub(superfn at(&self, index: u32) -> Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE {
        Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE {
            ptr: self.start.ptr + (self.handle_size * index) as usize,
        }
    }
}

impl fmt::Debug for CpuHeap {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("CpuHeap")
            .field("start", &self.start.ptr)
            .field("handle_size", &self.handle_size)
            .field("total", &self.total)
            .finish()
    }
}

pub(superunsafe fn upload(
    device: &Direct3D12::ID3D12Device,
    src: &CpuHeapInner,
    dst: &GeneralHeap,
    dummy_copy_counts: &[u32],
) -> Result<DualHandle, crate::DeviceError> {
    let count = src.stage.len() as u32;
    let index = dst.allocate_slice(count as u64)?;
    unsafe {
        device.CopyDescriptors(
            1,
            &dst.cpu_descriptor_at(index),
            Some(&count),
            count,
            src.stage.as_ptr(),
            Some(dummy_copy_counts.as_ptr()),
            dst.ty,
        )
    };
    Ok(dst.at(index, count as u64))
}

Messung V0.5 in Prozent
C=97 H=88 G=92

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet am  2026-06-23) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik