Skip to content

Commit 76b672a

Browse files
author
GBDixonAlex
committed
- working example of inline raytracing
1 parent 1d9fe7e commit 76b672a

File tree

8 files changed

+163
-44
lines changed

8 files changed

+163
-44
lines changed

config.jsn

+3
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@
122122
"-num_threads 1"
123123
"-args"
124124
"-Zpr"
125+
"-Zi"
126+
"-Qembed_debug"
127+
"-Od"
125128
]
126129
}
127130
pmfx_dev: {

plugins/ecs_examples/src/raytraced_shadows.rs

+33-14
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ pub fn raytraced_shadows(client: &mut Client<gfx_platform::Device, os_platform::
3232
"animate_meshes",
3333
"animate_lights",
3434
"batch_lights",
35-
"update_tlas"
35+
"setup_tlas"
3636
],
37-
render_graph: "mesh_lit_rt_shadow",
37+
render_graph: "mesh_lit_rt_shadow2",
3838
..Default::default()
3939
}
4040
}
@@ -49,7 +49,7 @@ pub fn blas_from_mesh(device: &mut ResMut<DeviceRes>, mesh: &pmfx::Mesh<gfx_plat
4949
transform3x4: None,
5050
index_count: mesh.num_indices as usize,
5151
index_format: gfx::Format::R16u,
52-
vertex_count: mesh.num_indices as usize,
52+
vertex_count: mesh.num_vertices as usize,
5353
vertex_format: gfx::Format::RGB32f,
5454
vertex_stride: 56
5555
}),
@@ -66,7 +66,6 @@ pub fn setup_raytraced_shadows_scene(
6666
mut commands: Commands) -> Result<(), hotline_rs::Error> {
6767

6868
let cube_mesh = hotline_rs::primitives::create_cube_mesh(&mut device.0);
69-
7069
let tourus_mesh = hotline_rs::primitives::create_tourus_mesh(&mut device.0, 32);
7170
let teapot_mesh = hotline_rs::primitives::create_teapot_mesh(&mut device.0, 32);
7271
let tube_mesh = hotline_rs::primitives::create_tube_prism_mesh(&mut device.0, 32, 0, 32, true, true, 1.0, 0.66, 1.0);
@@ -202,7 +201,7 @@ pub fn setup_raytraced_shadows_scene(
202201
}
203202

204203
#[export_update_fn]
205-
pub fn update_tlas(
204+
pub fn setup_tlas(
206205
mut device: ResMut<DeviceRes>,
207206
mut pmfx: ResMut<PmfxRes>,
208207
mut entities_query: Query<(&mut Position, &mut Scale, &mut Rotation, &BLAS)>,
@@ -235,6 +234,9 @@ pub fn update_tlas(
235234
},
236235
&mut pmfx.shader_heap
237236
)?;
237+
let tlas_srv = tlas.get_srv_index().expect("expect tlas to have an srv");
238+
pmfx.push_constant_user_data[0] = tlas_srv as u32;
239+
println!("tlas_srv = {tlas_srv}");
238240
t.tlas = Some(tlas);
239241
}
240242
}
@@ -255,13 +257,8 @@ pub fn animate_lights (
255257
Ok(())
256258
}
257259

258-
// TODO_RT
259-
// update tlas
260-
// mesh vertex count
261-
// fix: Ignoring InitialState D3D12_RESOURCE_STATE_COPY_DEST. Buffers are effectively created in state D3D12_RESOURCE_STATE_COMMON.
262-
263260
#[export_compute_fn]
264-
pub fn render_meshes_raytraced(
261+
pub fn update_tlas(
265262
mut device: ResMut<DeviceRes>,
266263
pmfx: &Res<PmfxRes>,
267264
pass: &pmfx::ComputePass<gfx_platform::Device>,
@@ -272,9 +269,6 @@ pub fn render_meshes_raytraced(
272269

273270
let mut heap = pmfx.shader_heap.clone();
274271

275-
let output_size = pmfx.get_texture_2d_size("staging_output").expect("expected staging_output");
276-
let output_tex = pmfx.get_texture("staging_output").expect("expected staging_output");
277-
278272
// update tlas
279273
for mut t in &mut tlas_query {
280274
let mut instances = Vec::new();
@@ -301,6 +295,31 @@ pub fn render_meshes_raytraced(
301295
}
302296
}
303297

298+
Ok(())
299+
}
300+
301+
// TODO_RT
302+
// mesh vertex count
303+
// crash when switching demo
304+
305+
// TODO clean
306+
// fix: Ignoring InitialState D3D12_RESOURCE_STATE_COPY_DEST. Buffers are effectively created in state D3D12_RESOURCE_STATE_COMMON.
307+
308+
#[export_compute_fn]
309+
pub fn render_meshes_raytraced(
310+
mut device: ResMut<DeviceRes>,
311+
pmfx: &Res<PmfxRes>,
312+
pass: &pmfx::ComputePass<gfx_platform::Device>,
313+
mut entities_query: Query<(&mut Position, &mut Scale, &mut Rotation, &BLAS)>,
314+
mut tlas_query: Query<&mut TLAS>,
315+
) -> Result<(), hotline_rs::Error> {
316+
let pmfx = &pmfx.0;
317+
318+
let mut heap = pmfx.shader_heap.clone();
319+
320+
let output_size = pmfx.get_texture_2d_size("staging_output").expect("expected staging_output");
321+
let output_tex = pmfx.get_texture("staging_output").expect("expected staging_output");
322+
304323
let camera = pmfx.get_camera_constants("main_camera");
305324
if let Ok(camera) = camera {
306325
for t in &tlas_query {

shaders/ecs.hlsl

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ struct world_buffer_info_data {
8282
uint2 directional_light;
8383
uint2 camera;
8484
uint2 shadow_matrix;
85+
uint4 user_data;
8586
}
8687

8788
// info to lookup shadow srv and matrix

shaders/material.hlsl

+67-24
Original file line numberDiff line numberDiff line change
@@ -267,45 +267,44 @@ float4 ps_mesh_pbr_ibl(vs_output input) : SV_TARGET {
267267
return float4(((kd * max(diffuse, 0.0) + max(specular, 0.0))), 1.0);
268268
}
269269

270+
struct RayPayload
271+
{
272+
float4 col;
273+
};
274+
275+
cbuffer ray_tracing_constants : register(b0) {
276+
float4x4 inverse_wvp;
277+
int4 resource_indices; // x = uav output, y = scene_tlas
278+
};
279+
270280
// basic ray traced shadow
271-
bool is_occluded(float3 origin, float3 direction, float tMin, float tMax)
281+
bool is_occluded(float3 origin, float3 direction, float tmin, float tmax)
272282
{
273-
RayQuery<RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES> rayQuery;
283+
RayQuery<RAY_FLAG_CULL_NON_OPAQUE | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH> ray_query;
274284

275285
RayDesc desc;
276286
desc.Origin = origin;
277-
desc.TMin = tMin;
287+
desc.TMin = tmin;
278288
desc.Direction = direction;
279-
desc.TMax = tMax;
289+
desc.TMax = tmax;
280290

281-
rayQuery.TraceRayInline(
282-
scene_tlas[resource_indices.y],
283-
RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH,
284-
0xFF,
291+
ray_query.TraceRayInline(
292+
scene_tlas[world_buffer_info.user_data.x],
293+
RAY_FLAG_NONE,
294+
0xff,
285295
desc
286296
);
287297

288-
while (rayQuery.Proceed()) // Traverse BVH
298+
ray_query.Proceed();
299+
300+
if (ray_query.CommittedStatus() == COMMITTED_TRIANGLE_HIT)
289301
{
290-
if (rayQuery.CommittedStatus() == COMMITTED_TRIANGLE_HIT)
291-
{
292-
return true; // Something is occluding
293-
}
302+
return true;
294303
}
295304

296-
return false; // No occlusion
305+
return false;
297306
}
298307

299-
struct RayPayload
300-
{
301-
float4 col;
302-
};
303-
304-
cbuffer ray_tracing_constants : register(b0) {
305-
float4x4 inverse_wvp;
306-
int4 resource_indices; // x = uav output, y = scene_tlas
307-
};
308-
309308
[shader("raygeneration")]
310309
void scene_raygen_shader()
311310
{
@@ -437,4 +436,48 @@ void shadow_closest_hit_shader(inout RayPayload payload, in BuiltInTriangleInter
437436
void scene_miss_shader(inout RayPayload payload)
438437
{
439438
payload.col = float4(0.0, 0.0, 0.0, 0.0);
439+
}
440+
441+
ps_output ps_mesh_lit_rt_shadow(vs_output input) {
442+
ps_output output;
443+
output.colour = input.colour;
444+
445+
int i = 0;
446+
float ks = 2.0;
447+
float shininess = 32.0;
448+
float roughness = 0.1;
449+
float k = 0.3;
450+
451+
float3 v = normalize(input.world_pos.xyz - view_position.xyz);
452+
float3 n = input.normal;
453+
454+
// point lights
455+
uint point_lights_id = world_buffer_info.point_light.x;
456+
uint point_lights_count = world_buffer_info.point_light.y;
457+
for(i = 0; i < point_lights_count; ++i) {
458+
point_light_data light = point_lights[point_lights_id][i];
459+
460+
float3 l = normalize(input.world_pos.xyz - light.pos);
461+
float rl = length(light.pos - input.world_pos.xyz);
462+
463+
float diffuse = lambert(l, n);
464+
float specular = cook_torrance(l, n, v, roughness, k);
465+
466+
float atteniuation = point_light_attenuation(
467+
light.pos,
468+
light.radius,
469+
input.world_pos.xyz
470+
);
471+
472+
float4 light_colour = atteniuation * light.colour * diffuse;
473+
light_colour += atteniuation * light.colour * specular;
474+
475+
bool occluded = is_occluded(input.world_pos.xyz, -l, 0.001, rl);
476+
477+
if(!occluded) {
478+
output.colour += light_colour;
479+
}
480+
}
481+
482+
return output;
440483
}

shaders/material.jsn

+36-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@
7979
ray_tracing_constants
8080
]
8181
}
82+
mesh_lit_rt_shadow2: {
83+
vs: "vs_mesh",
84+
ps: "ps_mesh_lit_rt_shadow"
85+
push_constants: [
86+
"view_push_constants"
87+
"draw_push_constants"
88+
"world_buffer_info"
89+
]
90+
depth_stencil_state: depth_test_less
91+
raster_state: cull_back
92+
topology: "TriangleList"
93+
}
8294
mesh_pbr_ibl: {
8395
vs: "vs_mesh",
8496
ps: "ps_mesh_pbr_ibl"
@@ -136,16 +148,39 @@
136148
depends_on: ["debug"]
137149
}
138150
}
151+
mesh_lit_rt_shadow2: {
152+
debug: {
153+
view: "main_view"
154+
pipelines: ["imdraw_3d"]
155+
function: "render_debug"
156+
}
157+
update_tlas: {
158+
pipelines: []
159+
function: "update_tlas"
160+
depends_on: ["debug"]
161+
}
162+
meshes: {
163+
view: "main_view"
164+
pipelines: ["mesh_lit_rt_shadow2"]
165+
function: "render_meshes_bindless"
166+
depends_on: ["update_tlas"]
167+
}
168+
}
139169
mesh_lit_rt_shadow: {
140170
debug: {
141171
view: "main_view"
142172
pipelines: ["imdraw_3d"]
143173
function: "render_debug"
144174
}
175+
update_tlas: {
176+
pipelines: []
177+
function: "update_tlas"
178+
depends_on: ["debug"]
179+
}
145180
meshes: {
146181
pipelines: ["mesh_lit_rt_shadow"]
147182
function: "render_meshes_raytraced"
148-
depends_on: ["debug"]
183+
depends_on: ["update_tlas"]
149184
uses: [
150185
["staging_output", "Write"]
151186
]

src/gfx/d3d12.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,7 @@ impl super::Device for Device {
18531853
std::ptr::addr_of!(options5) as *mut _,
18541854
std::mem::size_of::<D3D12_FEATURE_DATA_D3D12_OPTIONS5>() as u32).is_ok() {
18551855
if options5.RaytracingTier != D3D12_RAYTRACING_TIER_NOT_SUPPORTED {
1856+
println!("raytracing tier = {:?}", options5.RaytracingTier);
18561857
feature_flags |= super::DeviceFeatureFlags::RAYTRACING;
18571858
}
18581859
}

src/pmfx.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ pub struct Mesh<D: gfx::Device> {
9999
pub ib: D::Buffer,
100100
/// Number of indices to draw from the index buffer
101101
pub num_indices: u32,
102+
/// Number of vertices in the vertex buffer
103+
pub num_vertices: u32,
102104
/// Bounding aabb min
103105
pub aabb_min: Vec3f,
104106
/// Bounding aabb mix
@@ -185,6 +187,8 @@ pub struct Pmfx<D: gfx::Device> {
185187
pub view_errors: Arc<Mutex<HashMap<String, String>>>,
186188
/// Tracks the currently active render graph name
187189
pub active_render_graph: String,
190+
/// Quick access user data
191+
pub push_constant_user_data: [u32; 4],
188192
}
189193

190194
/// Contains frame statistics from the GPU for all pmfx jobs
@@ -716,7 +720,9 @@ pub struct WorldBufferInfo {
716720
/// cbv index of the camera
717721
pub camera: GpuBufferLookup,
718722
/// srv index of shadow matrices
719-
pub shadow_matrix: GpuBufferLookup
723+
pub shadow_matrix: GpuBufferLookup,
724+
/// custom user data
725+
pub user_data: [u32; 4]
720726
}
721727

722728
pub fn cubemap_camera_face(face: usize, pos: Vec3f, near: f32, far: f32) -> CameraConstants {
@@ -1009,6 +1015,7 @@ impl<D> Pmfx<D> where D: gfx::Device {
10091015
unit_quad_mesh: primitives::create_unit_quad_mesh(device),
10101016
total_stats: TotalStats::new(),
10111017
view_errors: Arc::new(Mutex::new(HashMap::new())),
1018+
push_constant_user_data: [0; 4]
10121019
}
10131020
}
10141021

@@ -1043,7 +1050,8 @@ impl<D> Pmfx<D> where D: gfx::Device {
10431050
spot_light: self.world_buffers.spot_light.get_lookup(),
10441051
directional_light: self.world_buffers.directional_light.get_lookup(),
10451052
camera: self.world_buffers.camera.get_lookup(),
1046-
shadow_matrix: self.world_buffers.shadow_matrix.get_lookup()
1053+
shadow_matrix: self.world_buffers.shadow_matrix.get_lookup(),
1054+
user_data: self.push_constant_user_data
10471055
}
10481056
}
10491057

@@ -1596,13 +1604,18 @@ impl<D> Pmfx<D> where D: gfx::Device {
15961604
threads
15971605
}
15981606
else {
1599-
let pipeline = self.pmfx.pipelines.get(&pass_pipeline).unwrap();
1600-
if let Some(num_threads) = pipeline["0"].numthreads {
1601-
num_threads
1607+
if let Some(pipeline) = self.pmfx.pipelines.get(&pass_pipeline) {
1608+
if let Some(num_threads) = pipeline["0"].numthreads {
1609+
num_threads
1610+
}
1611+
else {
1612+
(1, 1, 1)
1613+
}
16021614
}
16031615
else {
16041616
(1, 1, 1)
16051617
}
1618+
//let pipeline = self.pmfx.pipelines.get(&pass_pipeline).unwrap();
16061619
};
16071620

16081621
// hashes

0 commit comments

Comments
 (0)