Skip to content

Add support for occlusion queries #3402

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
68ea7ea
Add occlusion query set to pass descriptor, update examples and CHANG…
valaphee Jan 19, 2023
52cc14d
Replace query set id with query set (oops), rustfmt
valaphee Feb 8, 2023
a3ba2e8
Update deno_webgpu/src/01_webgpu.js
valaphee Feb 9, 2023
135a6ac
Update deno_webgpu/src/01_webgpu.js
valaphee Feb 9, 2023
60d4f07
Update deno_webgpu/src/01_webgpu.js
valaphee Feb 9, 2023
1759bdd
Fix trace
valaphee Feb 9, 2023
afbe4d6
Update regr. test, undo prev. doc changes
valaphee Feb 9, 2023
9347284
Fix trace
valaphee Feb 9, 2023
6ca1156
Add occlusion queries to deno_webgpu
valaphee Feb 23, 2023
99db240
Test occlusion queries
valaphee Feb 23, 2023
5740521
Test occlusion queries, rustfmt
valaphee Feb 23, 2023
8c60534
Remove color attachment from occlusion query test, replace D3D12_QUER…
valaphee Feb 23, 2023
cf100b0
Remove occlusion query downlevel flag, as only DX11 FL9.1 doesn't sup…
valaphee Apr 25, 2023
fb01175
Merge branch 'master' into occlusion-query
valaphee Apr 25, 2023
a02353a
Correct CHANGELOG.md, After merge fixes
valaphee Apr 25, 2023
9b17360
Fix mipmap test, fix occlusion query test (using staging buffer)
valaphee Apr 25, 2023
c11e34b
Rustfmt, fix deno
valaphee Apr 25, 2023
46d41de
Remove debug, and re-adding fragment stage to try working around Swif…
valaphee Apr 25, 2023
5b94048
Revert re-adding fragment stage to try working around SwiftShader occ…
valaphee Apr 25, 2023
d4de325
Revert to binary occlusion in d3d12 backend, add hal query resolve bu…
valaphee Apr 26, 2023
f75b612
Use glow::ANY_SAMPLES_PASSED_CONSERVATIVE for occlusion queries, remo…
valaphee Apr 26, 2023
b11f85d
Use glow::ANY_SAMPLES_PASSED_CONSERVATIVE for occlusion queries, remo…
valaphee Apr 26, 2023
199b25f
Merge remote-tracking branch 'origin/trunk' into occlusion-query
valaphee Jul 22, 2023
6e8e7d1
Move occlusion query test, fix scissor_tests, undo stagging buffer fi…
valaphee Jul 22, 2023
fb1b0ac
Update CHANGELOG.md
valaphee Jul 22, 2023
16e9751
Merge branch 'trunk' into occlusion-query
cwfitzgerald Aug 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ Bottom level categories:

## Unreleased

### Major changes

#### Occlusion Query Support

The `occlusion_query_set` value defines where the occlusion query results will be stored for this pass.

```diff
let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
// ...
+ occlusion_query_set: None,
});
```

By @Valaphee in [#3402](https://github.com/gfx-rs/wgpu/pull/3402)

### Changes

- Omit texture store bound checks since they are no-ops if out of bounds on all APIs. By @teoxoy in [#3975](https://github.com/gfx-rs/wgpu/pull/3975)
Expand Down
7 changes: 7 additions & 0 deletions deno_webgpu/command_encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
label: Option<String>,
color_attachments: Vec<Option<GpuRenderPassColorAttachment>>,
depth_stencil_attachment: Option<GpuRenderPassDepthStencilAttachment>,
occlusion_query_set: Option<ResourceId>,
) -> Result<WebGpuResult, AnyError> {
let command_encoder_resource = state
.resource_table
Expand Down Expand Up @@ -171,10 +172,16 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
});
}

let occlusion_query_set_resource = occlusion_query_set
.map(|rid| state.resource_table.get::<super::WebGpuQuerySet>(rid))
.transpose()?
.map(|query_set| query_set.1);

let descriptor = wgpu_core::command::RenderPassDescriptor {
label: label.map(Cow::from),
color_attachments: Cow::from(color_attachments),
depth_stencil_attachment: processed_depth_stencil_attachment.as_ref(),
occlusion_query_set: occlusion_query_set_resource,
};

let render_pass = wgpu_core::command::RenderPass::new(command_encoder_resource.1, &descriptor);
Expand Down
34 changes: 34 additions & 0 deletions deno_webgpu/render_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,40 @@ pub fn op_webgpu_render_pass_set_stencil_reference(
Ok(WebGpuResult::empty())
}

#[op]
pub fn op_webgpu_render_pass_begin_occlusion_query(
state: &mut OpState,
render_pass_rid: ResourceId,
query_index: u32,
) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;

wgpu_core::command::render_ffi::wgpu_render_pass_begin_occlusion_query(
&mut render_pass_resource.0.borrow_mut(),
query_index,
);

Ok(WebGpuResult::empty())
}

#[op]
pub fn op_webgpu_render_pass_end_occlusion_query(
state: &mut OpState,
render_pass_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;

wgpu_core::command::render_ffi::wgpu_render_pass_end_occlusion_query(
&mut render_pass_resource.0.borrow_mut(),
);

Ok(WebGpuResult::empty())
}

#[op]
pub fn op_webgpu_render_pass_begin_pipeline_statistics_query(
state: &mut OpState,
Expand Down
1 change: 1 addition & 0 deletions deno_webgpu/webgpu.idl
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ dictionary GPURenderPassDescriptor
: GPUObjectDescriptorBase {
required sequence<GPURenderPassColorAttachment?> colorAttachments;
GPURenderPassDepthStencilAttachment depthStencilAttachment;
GPUQuerySet occlusionQuerySet;
};

dictionary GPURenderPassColorAttachment {
Expand Down
1 change: 1 addition & 0 deletions examples/boids/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ impl wgpu_example::framework::Example for Example {
label: None,
color_attachments: &color_attachments,
depth_stencil_attachment: None,
occlusion_query_set: None,
};

// get command encoder
Expand Down
1 change: 1 addition & 0 deletions examples/bunnymark/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ impl wgpu_example::framework::Example for Example {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});
rpass.set_pipeline(&self.pipeline);
rpass.set_bind_group(0, &self.global_group, &[]);
Expand Down
1 change: 1 addition & 0 deletions examples/capture/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ async fn create_red_image_with_dimensions(
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});

// Copy the data from the texture to the buffer
Expand Down
2 changes: 2 additions & 0 deletions examples/conservative-raster/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ impl wgpu_example::framework::Example for Example {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});

rpass.set_pipeline(&self.pipeline_triangle_conservative);
Expand All @@ -292,6 +293,7 @@ impl wgpu_example::framework::Example for Example {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});

rpass.set_pipeline(&self.pipeline_upscale);
Expand Down
1 change: 1 addition & 0 deletions examples/cube/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ impl wgpu_example::framework::Example for Example {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});
rpass.push_debug_group("Prepare data for draw.");
rpass.set_pipeline(&self.pipeline);
Expand Down
1 change: 1 addition & 0 deletions examples/hello-triangle/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});
rpass.set_pipeline(&render_pipeline);
rpass.draw(0..3, 0..1);
Expand Down
1 change: 1 addition & 0 deletions examples/hello-windows/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});
}

Expand Down
2 changes: 2 additions & 0 deletions examples/mipmap/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ impl Example {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});
if let Some(ref query_sets) = query_sets {
rpass.write_timestamp(&query_sets.timestamp, timestamp_query_index_base);
Expand Down Expand Up @@ -492,6 +493,7 @@ impl wgpu_example::framework::Example for Example {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});
rpass.set_pipeline(&self.draw_pipeline);
rpass.set_bind_group(0, &self.bind_group, &[]);
Expand Down
1 change: 1 addition & 0 deletions examples/msaa-line/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ impl wgpu_example::framework::Example for Example {
label: None,
color_attachments: &[Some(rpass_color_attachment)],
depth_stencil_attachment: None,
occlusion_query_set: None,
})
.execute_bundles(iter::once(&self.bundle));
}
Expand Down
2 changes: 2 additions & 0 deletions examples/shadow/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ impl wgpu_example::framework::Example for Example {
}),
stencil_ops: None,
}),
occlusion_query_set: None,
});
pass.set_pipeline(&self.shadow_pass.pipeline);
pass.set_bind_group(0, &self.shadow_pass.bind_group, &[]);
Expand Down Expand Up @@ -819,6 +820,7 @@ impl wgpu_example::framework::Example for Example {
}),
stencil_ops: None,
}),
occlusion_query_set: None,
});
pass.set_pipeline(&self.forward_pass.pipeline);
pass.set_bind_group(0, &self.forward_pass.bind_group, &[]);
Expand Down
1 change: 1 addition & 0 deletions examples/skybox/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ impl wgpu_example::framework::Example for Skybox {
}),
stencil_ops: None,
}),
occlusion_query_set: None,
});

rpass.set_bind_group(0, &self.bind_group, &[]);
Expand Down
1 change: 1 addition & 0 deletions examples/stencil-triangles/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ impl wgpu_example::framework::Example for Triangles {
store: true,
}),
}),
occlusion_query_set: None,
});

rpass.set_stencil_reference(1);
Expand Down
1 change: 1 addition & 0 deletions examples/texture-arrays/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ impl wgpu_example::framework::Example for Example {
},
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
});

rpass.set_pipeline(&self.pipeline);
Expand Down
3 changes: 3 additions & 0 deletions examples/water/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,7 @@ impl wgpu_example::framework::Example for Example {
}),
stencil_ops: None,
}),
occlusion_query_set: None,
});

rpass.execute_bundles([&self.terrain_bundle]);
Expand All @@ -777,6 +778,7 @@ impl wgpu_example::framework::Example for Example {
}),
stencil_ops: None,
}),
occlusion_query_set: None,
});
rpass.set_pipeline(&self.terrain_pipeline);
rpass.set_bind_group(0, &self.terrain_normal_bind_group, &[]);
Expand All @@ -801,6 +803,7 @@ impl wgpu_example::framework::Example for Example {
depth_ops: None,
stencil_ops: None,
}),
occlusion_query_set: None,
});

rpass.set_pipeline(&self.water_pipeline);
Expand Down
2 changes: 2 additions & 0 deletions player/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,14 @@ impl GlobalPlay for wgc::global::Global<IdentityPassThroughFactory> {
base,
target_colors,
target_depth_stencil,
occlusion_query_set_id,
} => {
self.command_encoder_run_render_pass_impl::<A>(
encoder,
base.as_ref(),
&target_colors,
target_depth_stencil.as_ref(),
occlusion_query_set_id,
)
.unwrap();
}
Expand Down
127 changes: 127 additions & 0 deletions tests/tests/occlusion_query/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use std::borrow::Cow;
use wgpu_test::{initialize_test, TestParameters};

#[test]
fn occlusion_query() {
initialize_test(TestParameters::default(), |ctx| {
// Create depth texture
let depth_texture = ctx.device.create_texture(&wgpu::TextureDescriptor {
label: Some("Depth texture"),
size: wgpu::Extent3d {
width: 64,
height: 64,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Depth32Float,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
});
let depth_texture_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());

// Setup pipeline using a simple shader with hardcoded vertices
let shader = ctx
.device
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("Shader module"),
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
});
let pipeline = ctx
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Pipeline"),
layout: None,
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[],
},
fragment: None,
primitive: wgpu::PrimitiveState::default(),
depth_stencil: Some(wgpu::DepthStencilState {
format: wgpu::TextureFormat::Depth32Float,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
stencil: wgpu::StencilState::default(),
bias: wgpu::DepthBiasState::default(),
}),
multisample: wgpu::MultisampleState::default(),
multiview: None,
});

// Create occlusion query set
let query_set = ctx.device.create_query_set(&wgpu::QuerySetDescriptor {
label: Some("Query set"),
ty: wgpu::QueryType::Occlusion,
count: 3,
});

let mut encoder = ctx
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
{
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render pass"),
color_attachments: &[],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
view: &depth_texture_view,
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Clear(1.0),
store: true,
}),
stencil_ops: None,
}),
occlusion_query_set: Some(&query_set),
});
render_pass.set_pipeline(&pipeline);

// Not occluded (z = 1.0, nothing drawn yet)
render_pass.begin_occlusion_query(0);
render_pass.draw(4..7, 0..1);
render_pass.end_occlusion_query();

// Not occluded (z = 0.0)
render_pass.begin_occlusion_query(1);
render_pass.draw(0..3, 0..1);
render_pass.end_occlusion_query();

// Occluded (z = 1.0)
render_pass.begin_occlusion_query(2);
render_pass.draw(4..7, 0..1);
render_pass.end_occlusion_query();
}

// Resolve query set to buffer
let query_buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("Query buffer"),
size: std::mem::size_of::<u64>() as u64 * 3,
usage: wgpu::BufferUsages::QUERY_RESOLVE | wgpu::BufferUsages::COPY_SRC,
mapped_at_creation: false,
});
encoder.resolve_query_set(&query_set, 0..3, &query_buffer, 0);

let mapping_buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("Mapping buffer"),
size: query_buffer.size(),
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
encoder.copy_buffer_to_buffer(&query_buffer, 0, &mapping_buffer, 0, query_buffer.size());

ctx.queue.submit(Some(encoder.finish()));

mapping_buffer
.slice(..)
.map_async(wgpu::MapMode::Read, |_| ());
ctx.device.poll(wgpu::Maintain::Wait);
let query_buffer_view = mapping_buffer.slice(..).get_mapped_range();
let query_data: &[u64; 3] = bytemuck::from_bytes(&query_buffer_view);

// WebGPU only defines query results as zero/non-zero
assert_ne!(query_data[0], 0);
assert_ne!(query_data[1], 0);
assert_eq!(query_data[2], 0);
})
}
7 changes: 7 additions & 0 deletions tests/tests/occlusion_query/shader.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@vertex
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
let x = f32(i32(in_vertex_index & 3u) - 1);
let y = f32(i32(in_vertex_index & 1u) * 2 - 1);

return vec4<f32>(x, y, f32(in_vertex_index & 4u) / 8.0, 1.0);
}
Loading