feat(renderer): add hardware RT shadows to deferred_demo

Integrate BLAS/TLAS acceleration structures and RT shadow compute pass
into the deferred rendering demo. Adds GpuContext::new_with_features()
for requesting EXPERIMENTAL_RAY_QUERY, Mesh::new_with_usage() for
BLAS_INPUT buffer flags, and extends the lighting shadow bind group
to 9 entries (shadow map + IBL + SSGI + RT shadow).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 13:23:34 +09:00
parent b556cdd768
commit a5c0179793
4 changed files with 258 additions and 13 deletions

View File

@@ -28,10 +28,15 @@ pub struct GpuContext {
impl GpuContext {
pub fn new(window: Arc<Window>) -> Self {
pollster::block_on(Self::new_async(window))
pollster::block_on(Self::new_async(window, wgpu::Features::empty()))
}
async fn new_async(window: Arc<Window>) -> Self {
/// Create a GpuContext requesting additional device features (e.g. ray tracing).
pub fn new_with_features(window: Arc<Window>, features: wgpu::Features) -> Self {
pollster::block_on(Self::new_async(window, features))
}
async fn new_async(window: Arc<Window>, extra_features: wgpu::Features) -> Self {
let size = window.inner_size();
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
@@ -50,11 +55,19 @@ impl GpuContext {
.await
.expect("Failed to find a suitable GPU adapter");
// When extra features are requested (e.g. ray tracing), use adapter limits
// so RT-specific limits (max_acceleration_structures_per_shader_stage, etc.) are satisfied.
let required_limits = if extra_features.is_empty() {
wgpu::Limits::default()
} else {
adapter.limits()
};
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor {
label: Some("Voltex Device"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
required_features: extra_features,
required_limits,
memory_hints: Default::default(),
..Default::default()
})

View File

@@ -41,5 +41,5 @@ pub use deferred_pipeline::{
rt_shadow_gbuffer_bind_group_layout, rt_shadow_data_bind_group_layout, create_rt_shadow_pipeline,
};
pub use ssgi::{SsgiResources, SsgiUniform, SSGI_OUTPUT_FORMAT};
pub use rt_accel::{RtAccel, BlasMeshData, mat4_to_tlas_transform};
pub use rt_accel::{RtAccel, RtInstance, BlasMeshData, mat4_to_tlas_transform};
pub use rt_shadow::{RtShadowResources, RtShadowUniform, RT_SHADOW_FORMAT};

View File

@@ -21,4 +21,24 @@ impl Mesh {
});
Self { vertex_buffer, index_buffer, num_indices: indices.len() as u32 }
}
/// Create a mesh with additional buffer usage flags (e.g. `BLAS_INPUT` for ray tracing).
pub fn new_with_usage(
device: &wgpu::Device,
vertices: &[MeshVertex],
indices: &[u32],
extra_usage: wgpu::BufferUsages,
) -> Self {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Mesh Vertex Buffer"),
contents: bytemuck::cast_slice(vertices),
usage: wgpu::BufferUsages::VERTEX | extra_usage,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Mesh Index Buffer"),
contents: bytemuck::cast_slice(indices),
usage: wgpu::BufferUsages::INDEX | extra_usage,
});
Self { vertex_buffer, index_buffer, num_indices: indices.len() as u32 }
}
}