pub(crate) mod backend;
pub mod buffer;
pub mod compute;
pub mod context;
pub mod device;
pub mod error;
pub mod frame_orchestrator;
pub(crate) mod frame_table;
pub(crate) mod handles;
pub mod pipeline;
pub(crate) mod render_target;
pub mod sampler;
pub mod shader;
pub mod shader_library;
pub mod shaders;
pub(crate) mod surface;
pub mod task_graph;
pub mod texture;
pub mod types;
pub mod shader_cache;
pub mod slang;
pub mod validation_env;
pub(crate) mod gpu_profiler;
pub(crate) mod instrumentation;
pub mod tracy;
#[cfg(feature = "tracy")]
#[doc(hidden)]
pub use tracy_client as _tracy_client;
pub(crate) mod allocation_policy;
mod buffer_alloc_tests;
pub mod exchange;
#[cfg(test)]
mod heap_tests;
pub mod parcel;
pub mod retained_pool;
pub mod scheme;
pub mod signal;
pub mod swapchain_pool;
pub(crate) mod timeline;
pub mod transient_pool;
pub(crate) mod vram_allocator;
pub use allocation_policy::BudgetPolicy;
pub use error::GoldyError;
pub use exchange::{
Claim, DepositTransaction, MemoryExchange, SurfaceExchange, WithdrawBytes, WithdrawClaim, WithdrawTransaction,
};
pub use frame_orchestrator::{FrameHandle, FrameOrchestrator};
pub use parcel::{field, ordinal, Buffer, Init, Parcel, RecordField, Texture};
pub use retained_pool::RetainedPool;
pub use scheme::{Lease, LeaseRenderTarget, ReplayStats, Scheme, SchemeRenderPassBuilder, Submission, Transaction};
pub use swapchain_pool::{AcquiredPresent, PresentLease};
pub use task_graph::{ShaderResourceSlot, PRESENT_LEASE_SLOT_PLACEHOLDER};
pub use vram_allocator::DeferredPayload;
pub use buffer::StructuredBufferElement;
pub use compute::ComputePipeline;
pub use context::Context;
pub use device::{
Adapter, AdapterInfo, BufferHeapStats, Device, DeviceCapabilities, DeviceDescriptor, Instance, PowerPreference,
RequestAdapterOptions, TextureHeapStats, VideoMemoryInfo,
};
pub use goldy_derive::LayoutCheckable;
pub use goldy_derive::StructuredBufferElement;
pub use pipeline::{RenderPipeline, RenderPipelineDesc};
pub use sampler::Sampler;
pub use shader::{builtins, ShaderModule};
pub use shader_library::ShaderLibrary;
pub use signal::{OversubscribedReason, Signal};
pub use slang::{layout_validation_enabled, LayoutCheck, StructFieldLayout, StructLayout};
pub use task_graph::NodeAccess;
pub use texture::TextureCopyFootprint;
pub use handles::{SamplerHandle, TextureHandle};
pub use types::*;
pub use types::{PresentMode, SurfaceConfig};
pub use raw_window_handle;
#[cfg(test)]
mod boundary_reclamation;
#[cfg(all(feature = "dx12", target_os = "windows"))]
pub use backend::dx12::WARP_ADAPTER_ID;
#[cfg(all(feature = "dx12", target_os = "windows"))]
pub fn dx12_debug_mode() -> bool {
backend::dx12::is_debug_mode()
}
#[cfg(not(all(feature = "dx12", target_os = "windows")))]
pub fn dx12_debug_mode() -> bool {
false
}
#[doc(hidden)]
pub mod test_support {
use crate::backend::mock::MockBackend;
use crate::device::{Adapter, DeviceDescriptor, Instance, RequestAdapterOptions};
use crate::{BackendType, Device, DeviceType};
use std::ops::Deref;
use std::sync::{Arc, Mutex, MutexGuard, OnceLock};
pub fn mock_device() -> Arc<Device> {
Arc::new(Device::from_backend(Box::new(MockBackend::new())).expect("mock device"))
}
#[allow(private_bounds)]
pub fn with_mock<R>(device: &Device, f: impl FnOnce(&mut MockBackend) -> R) -> R {
device.with_mock_backend(f)
}
pub fn mock_reset_tracking(device: &Device) {
with_mock(device, |m| m.reset_tracking());
}
pub fn mock_recorded_waits(device: &Device) -> Vec<Vec<(u64, u64)>> {
with_mock(device, |m| {
m.recorded_waits
.iter()
.map(|batch| batch.iter().map(|e| (e.context, e.value)).collect())
.collect()
})
}
pub fn mock_retained_resubmit_count(device: &Device) -> usize {
with_mock(device, |m| m.retained_resubmit_count)
}
pub fn mock_compute_dispatch_count(device: &Device) -> usize {
with_mock(device, |m| m.compute_dispatch_count)
}
pub fn mock_all_graph_syncs_some(device: &Device) -> bool {
with_mock(device, |m| m.recorded_graph_syncs.iter().all(|&s| s))
}
pub fn mock_recorded_graph_syncs(device: &Device) -> Vec<bool> {
with_mock(device, |m| m.recorded_graph_syncs.clone())
}
pub fn mock_has_nonempty_host_observed_waits(device: &Device) -> bool {
with_mock(device, |m| {
m.recorded_host_observed_waits.iter().any(|batch| !batch.is_empty())
})
}
pub fn mock_has_nonempty_deferred_host_writes(device: &Device) -> bool {
with_mock(device, |m| {
m.recorded_deferred_host_writes.iter().any(|batch| !batch.is_empty())
})
}
pub fn mock_barrier_buffer_count(device: &Device) -> usize {
use crate::backend::GpuCommand;
with_mock(device, |m| {
m.recorded_compute_commands
.iter()
.flat_map(|batch| batch.iter())
.find_map(|cmd| match cmd {
GpuCommand::ResourceBarrier { buffers, .. } => Some(buffers.len()),
_ => None,
})
.unwrap_or(0)
})
}
pub fn mock_surface_exchange(device: &Arc<Device>) -> (crate::Context, crate::SurfaceExchange) {
struct MockWindow;
impl raw_window_handle::HasWindowHandle for MockWindow {
fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
Ok(unsafe {
raw_window_handle::WindowHandle::borrow_raw(raw_window_handle::RawWindowHandle::Web(
raw_window_handle::WebWindowHandle::new(0),
))
})
}
}
impl raw_window_handle::HasDisplayHandle for MockWindow {
fn display_handle(&self) -> Result<raw_window_handle::DisplayHandle<'_>, raw_window_handle::HandleError> {
Ok(unsafe {
raw_window_handle::DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::Web(
raw_window_handle::WebDisplayHandle::new(),
))
})
}
}
let ctx = device.create_context().expect("mock context");
let surface =
crate::SurfaceExchange::new_with_depth(&ctx, &MockWindow, 2, crate::types::SurfaceConfig::default())
.expect("mock surface exchange");
(ctx, surface)
}
pub fn scheme_advance_timeline(ctx: &crate::Context) -> u64 {
use crate::{BufferFlags, BufferKind, RetainedPool, Scheme};
let device = Arc::new(ctx.device().clone());
let mut pool = RetainedPool::new(device);
let buf = pool
.acquire_buffer(256, BufferKind::Scattered, None, BufferFlags::empty(), None)
.expect("buf");
let mut scheme = Scheme::new(ctx);
scheme.clear_parcel(&buf, 0, 256).expect("clear");
scheme.submit().expect("submit").timeline_value()
}
pub fn submission_epoch(submission: &crate::Submission) -> u64 {
submission.timeline_value()
}
pub fn gpu_progress(ctx: &crate::Context) -> u64 {
ctx.gpu_progress()
}
pub fn wait_until(ctx: &crate::Context, epoch: u64) -> Result<(), crate::GoldyError> {
ctx.wait_until(epoch)
}
pub fn parcel_last_epoch_on(parcel: &crate::Parcel, ctx: &crate::Context) -> Option<u64> {
parcel.last_referenced_on(ctx.backend_handle())
}
static WARP_LIB_TEST_SERIAL: OnceLock<Mutex<()>> = OnceLock::new();
fn warp_lib_test_serial() -> &'static Mutex<()> {
WARP_LIB_TEST_SERIAL.get_or_init(|| Mutex::new(()))
}
fn env_force_warp() -> bool {
#[cfg(all(feature = "dx12", target_os = "windows"))]
{
crate::backend::dx12::env_force_warp()
}
#[cfg(not(all(feature = "dx12", target_os = "windows")))]
{
false
}
}
fn is_dx12_warp_adapter(instance: &Instance, adapter: &Adapter) -> bool {
#[cfg(all(feature = "dx12", target_os = "windows"))]
{
instance.backend_type() == BackendType::Dx12 && adapter.id() == crate::WARP_ADAPTER_ID
}
#[cfg(not(all(feature = "dx12", target_os = "windows")))]
{
let _ = (instance, adapter);
false
}
}
pub struct SerialGpuDevice {
device: Device,
_warp_guard: Option<MutexGuard<'static, ()>>,
}
impl Default for SerialGpuDevice {
fn default() -> Self {
Self::new()
}
}
impl SerialGpuDevice {
pub fn new() -> Self {
Self::from_adapter_factory(|instance| {
instance
.request_adapter(&RequestAdapterOptions::default())
.expect("adapter")
})
}
pub fn preferring(preferred: DeviceType) -> Self {
Self::from_adapter_factory(|instance| {
if env_force_warp() && instance.backend_type() == BackendType::Dx12 {
return instance
.request_adapter(&RequestAdapterOptions {
force_fallback_adapter: true,
..RequestAdapterOptions::default()
})
.expect("WARP adapter");
}
let adapters = instance.enumerate_adapters();
adapters
.iter()
.find(|a| a.device_type() == preferred)
.or(adapters.first())
.cloned()
.expect("no adapter")
})
}
fn from_adapter_factory(select: impl FnOnce(&Instance) -> Adapter) -> Self {
let instance = Instance::new().expect("Instance::new");
let adapter = select(&instance);
let _warp_guard = if is_dx12_warp_adapter(&instance, &adapter) {
Some(warp_lib_test_serial().lock().unwrap())
} else {
None
};
let device = adapter.request_device(&DeviceDescriptor::default()).expect("device");
drop(instance);
Self { device, _warp_guard }
}
}
impl Deref for SerialGpuDevice {
type Target = Device;
fn deref(&self) -> &Device {
&self.device
}
}
pub struct CbReuseOverride {
_private: (),
}
impl CbReuseOverride {
pub fn force_enabled() -> Self {
crate::validation_env::set_cb_reuse_override(false);
Self { _private: () }
}
pub fn force_disabled() -> Self {
crate::validation_env::set_cb_reuse_override(true);
Self { _private: () }
}
}
impl Drop for CbReuseOverride {
fn drop(&mut self) {
crate::validation_env::clear_cb_reuse_override();
}
}
}