| 
1 | 1 | use crate::ray_tracing::{acceleration_structure_limits, AsBuildContext};  | 
 | 2 | +use wgpu::util::{BufferInitDescriptor, DeviceExt};  | 
2 | 3 | use wgpu::{  | 
3 |  | -    include_wgsl, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferDescriptor,  | 
 | 4 | +    include_wgsl, Backends, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferDescriptor,  | 
4 | 5 |     CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor,  | 
5 | 6 | };  | 
6 | 7 | use wgpu::{AccelerationStructureFlags, BufferUsages};  | 
7 | 8 | use wgpu_macros::gpu_test;  | 
8 |  | -use wgpu_test::GpuTestInitializer;  | 
 | 9 | +use wgpu_test::{FailureCase, GpuTestInitializer};  | 
9 | 10 | use wgpu_test::{GpuTestConfiguration, TestParameters, TestingContext};  | 
10 | 11 | 
 
  | 
11 | 12 | const STRUCT_SIZE: wgpu::BufferAddress = 176;  | 
12 | 13 | 
 
  | 
13 | 14 | pub fn all_tests(tests: &mut Vec<GpuTestInitializer>) {  | 
14 | 15 |     tests.push(ACCESS_ALL_STRUCT_MEMBERS);  | 
 | 16 | +    tests.push(PREVENT_INVALID_RAY_QUERY_CALLS);  | 
15 | 17 | }  | 
16 | 18 | 
 
  | 
17 | 19 | #[gpu_test]  | 
@@ -103,3 +105,95 @@ fn access_all_struct_members(ctx: TestingContext) {  | 
103 | 105 | 
 
  | 
104 | 106 |     ctx.queue.submit([encoder_compute.finish()]);  | 
105 | 107 | }  | 
 | 108 | + | 
 | 109 | +#[gpu_test]  | 
 | 110 | +static PREVENT_INVALID_RAY_QUERY_CALLS: GpuTestConfiguration = GpuTestConfiguration::new()  | 
 | 111 | +    .parameters(  | 
 | 112 | +        TestParameters::default()  | 
 | 113 | +            .test_features_limits()  | 
 | 114 | +            .limits(acceleration_structure_limits())  | 
 | 115 | +            .features(wgpu::Features::EXPERIMENTAL_RAY_QUERY)  | 
 | 116 | +            // not yet implemented in directx12  | 
 | 117 | +            .skip(FailureCase::backend(Backends::DX12)),  | 
 | 118 | +    )  | 
 | 119 | +    .run_sync(prevent_invalid_ray_query_calls);  | 
 | 120 | + | 
 | 121 | +fn prevent_invalid_ray_query_calls(ctx: TestingContext) {  | 
 | 122 | +    let invalid_values_buffer = ctx.device.create_buffer_init(&BufferInitDescriptor {  | 
 | 123 | +        label: Some("invalid values buffer"),  | 
 | 124 | +        contents: bytemuck::cast_slice(&[f32::NAN, f32::INFINITY]),  | 
 | 125 | +        usage: BufferUsages::STORAGE,  | 
 | 126 | +    });  | 
 | 127 | + | 
 | 128 | +    //  | 
 | 129 | +    // Create a clean `AsBuildContext`  | 
 | 130 | +    //  | 
 | 131 | + | 
 | 132 | +    let as_ctx = AsBuildContext::new(  | 
 | 133 | +        &ctx,  | 
 | 134 | +        AccelerationStructureFlags::empty(),  | 
 | 135 | +        AccelerationStructureFlags::empty(),  | 
 | 136 | +    );  | 
 | 137 | + | 
 | 138 | +    let mut encoder_build = ctx  | 
 | 139 | +        .device  | 
 | 140 | +        .create_command_encoder(&CommandEncoderDescriptor {  | 
 | 141 | +            label: Some("Build"),  | 
 | 142 | +        });  | 
 | 143 | + | 
 | 144 | +    encoder_build.build_acceleration_structures([&as_ctx.blas_build_entry()], [&as_ctx.tlas]);  | 
 | 145 | + | 
 | 146 | +    ctx.queue.submit([encoder_build.finish()]);  | 
 | 147 | + | 
 | 148 | +    //  | 
 | 149 | +    // Create shader  | 
 | 150 | +    //  | 
 | 151 | + | 
 | 152 | +    let shader = ctx  | 
 | 153 | +        .device  | 
 | 154 | +        .create_shader_module(include_wgsl!("shader.wgsl"));  | 
 | 155 | +    let compute_pipeline = ctx  | 
 | 156 | +        .device  | 
 | 157 | +        .create_compute_pipeline(&ComputePipelineDescriptor {  | 
 | 158 | +            label: None,  | 
 | 159 | +            layout: None,  | 
 | 160 | +            module: &shader,  | 
 | 161 | +            entry_point: Some("invalid_usages"),  | 
 | 162 | +            compilation_options: Default::default(),  | 
 | 163 | +            cache: None,  | 
 | 164 | +        });  | 
 | 165 | + | 
 | 166 | +    let bind_group = ctx.device.create_bind_group(&BindGroupDescriptor {  | 
 | 167 | +        label: None,  | 
 | 168 | +        layout: &compute_pipeline.get_bind_group_layout(0),  | 
 | 169 | +        entries: &[  | 
 | 170 | +            BindGroupEntry {  | 
 | 171 | +                binding: 0,  | 
 | 172 | +                resource: BindingResource::AccelerationStructure(&as_ctx.tlas),  | 
 | 173 | +            },  | 
 | 174 | +            BindGroupEntry {  | 
 | 175 | +                binding: 1,  | 
 | 176 | +                resource: BindingResource::Buffer(invalid_values_buffer.as_entire_buffer_binding()),  | 
 | 177 | +            },  | 
 | 178 | +        ],  | 
 | 179 | +    });  | 
 | 180 | + | 
 | 181 | +    //  | 
 | 182 | +    // Submit once to check for no issues  | 
 | 183 | +    //  | 
 | 184 | + | 
 | 185 | +    let mut encoder_compute = ctx  | 
 | 186 | +        .device  | 
 | 187 | +        .create_command_encoder(&CommandEncoderDescriptor::default());  | 
 | 188 | +    {  | 
 | 189 | +        let mut pass = encoder_compute.begin_compute_pass(&ComputePassDescriptor {  | 
 | 190 | +            label: None,  | 
 | 191 | +            timestamp_writes: None,  | 
 | 192 | +        });  | 
 | 193 | +        pass.set_pipeline(&compute_pipeline);  | 
 | 194 | +        pass.set_bind_group(0, Some(&bind_group), &[]);  | 
 | 195 | +        pass.dispatch_workgroups(1, 1, 1)  | 
 | 196 | +    }  | 
 | 197 | + | 
 | 198 | +    ctx.queue.submit([encoder_compute.finish()]);  | 
 | 199 | +}  | 
0 commit comments