mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Render bundle support, use in msaa-line example
This commit is contained in:
@@ -28,14 +28,14 @@ vulkan = ["wgc/gfx-backend-vulkan"]
|
||||
package = "wgpu-core"
|
||||
version = "0.5"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "64ae59072db443eb1e47ee14d77370eec9f4b012"
|
||||
rev = "b0b99d89b71894cf01d8c938aae87b2348edeb5b"
|
||||
features = ["raw-window-handle"]
|
||||
|
||||
[dependencies.wgt]
|
||||
package = "wgpu-types"
|
||||
version = "0.5"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "64ae59072db443eb1e47ee14d77370eec9f4b012"
|
||||
rev = "b0b99d89b71894cf01d8c938aae87b2348edeb5b"
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.5"
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#[path = "../framework.rs"]
|
||||
mod framework;
|
||||
|
||||
use std::iter;
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
use wgpu::vertex_attr_array;
|
||||
@@ -25,29 +27,31 @@ unsafe impl Pod for Vertex {}
|
||||
unsafe impl Zeroable for Vertex {}
|
||||
|
||||
struct Example {
|
||||
bundle: wgpu::RenderBundle,
|
||||
vs_module: wgpu::ShaderModule,
|
||||
fs_module: wgpu::ShaderModule,
|
||||
pipeline_layout: wgpu::PipelineLayout,
|
||||
pipeline: wgpu::RenderPipeline,
|
||||
multisampled_framebuffer: wgpu::TextureView,
|
||||
vertex_buffer: wgpu::Buffer,
|
||||
vertex_count: u32,
|
||||
rebuild_pipeline: bool,
|
||||
sample_count: u32,
|
||||
rebuild_bundle: bool,
|
||||
sc_desc: wgpu::SwapChainDescriptor,
|
||||
}
|
||||
|
||||
impl Example {
|
||||
fn create_pipeline(
|
||||
fn create_bundle(
|
||||
device: &wgpu::Device,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
vs_module: &wgpu::ShaderModule,
|
||||
fs_module: &wgpu::ShaderModule,
|
||||
pipeline_layout: &wgpu::PipelineLayout,
|
||||
sample_count: u32,
|
||||
) -> wgpu::RenderPipeline {
|
||||
vertex_buffer: &wgpu::Buffer,
|
||||
vertex_count: u32,
|
||||
) -> wgpu::RenderBundle {
|
||||
log::info!("sample_count: {}", sample_count);
|
||||
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: vs_module,
|
||||
@@ -83,6 +87,19 @@ impl Example {
|
||||
sample_count,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
});
|
||||
let mut encoder =
|
||||
device.create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor {
|
||||
label: None,
|
||||
color_formats: &[sc_desc.format],
|
||||
depth_stencil_format: None,
|
||||
sample_count,
|
||||
});
|
||||
encoder.set_pipeline(&pipeline);
|
||||
encoder.set_vertex_buffer(0, vertex_buffer.slice(..));
|
||||
encoder.draw(0..vertex_count, 0..1);
|
||||
encoder.finish(&wgpu::RenderBundleDescriptor {
|
||||
label: Some("main"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -132,14 +149,6 @@ impl framework::Example for Example {
|
||||
bind_group_layouts: &[],
|
||||
});
|
||||
|
||||
let pipeline = Example::create_pipeline(
|
||||
device,
|
||||
&sc_desc,
|
||||
&vs_module,
|
||||
&fs_module,
|
||||
&pipeline_layout,
|
||||
sample_count,
|
||||
);
|
||||
let multisampled_framebuffer =
|
||||
Example::create_multisampled_framebuffer(device, sc_desc, sample_count);
|
||||
|
||||
@@ -165,16 +174,27 @@ impl framework::Example for Example {
|
||||
);
|
||||
let vertex_count = vertex_data.len() as u32;
|
||||
|
||||
let bundle = Example::create_bundle(
|
||||
device,
|
||||
&sc_desc,
|
||||
&vs_module,
|
||||
&fs_module,
|
||||
&pipeline_layout,
|
||||
sample_count,
|
||||
&vertex_buffer,
|
||||
vertex_count,
|
||||
);
|
||||
|
||||
let this = Example {
|
||||
bundle,
|
||||
vs_module,
|
||||
fs_module,
|
||||
pipeline_layout,
|
||||
pipeline,
|
||||
multisampled_framebuffer,
|
||||
vertex_buffer,
|
||||
vertex_count,
|
||||
rebuild_pipeline: false,
|
||||
sample_count,
|
||||
rebuild_bundle: false,
|
||||
sc_desc: sc_desc.clone(),
|
||||
};
|
||||
(this, None)
|
||||
@@ -188,13 +208,13 @@ impl framework::Example for Example {
|
||||
Some(winit::event::VirtualKeyCode::Left) => {
|
||||
if self.sample_count >= 2 {
|
||||
self.sample_count = self.sample_count >> 1;
|
||||
self.rebuild_pipeline = true;
|
||||
self.rebuild_bundle = true;
|
||||
}
|
||||
}
|
||||
Some(winit::event::VirtualKeyCode::Right) => {
|
||||
if self.sample_count <= 16 {
|
||||
self.sample_count = self.sample_count << 1;
|
||||
self.rebuild_pipeline = true;
|
||||
self.rebuild_bundle = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -222,18 +242,20 @@ impl framework::Example for Example {
|
||||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
) -> wgpu::CommandBuffer {
|
||||
if self.rebuild_pipeline {
|
||||
self.pipeline = Example::create_pipeline(
|
||||
if self.rebuild_bundle {
|
||||
self.bundle = Example::create_bundle(
|
||||
device,
|
||||
&self.sc_desc,
|
||||
&self.vs_module,
|
||||
&self.fs_module,
|
||||
&self.pipeline_layout,
|
||||
self.sample_count,
|
||||
&self.vertex_buffer,
|
||||
self.vertex_count,
|
||||
);
|
||||
self.multisampled_framebuffer =
|
||||
Example::create_multisampled_framebuffer(device, &self.sc_desc, self.sample_count);
|
||||
self.rebuild_pipeline = false;
|
||||
self.rebuild_bundle = false;
|
||||
}
|
||||
|
||||
let mut encoder =
|
||||
@@ -257,13 +279,12 @@ impl framework::Example for Example {
|
||||
}
|
||||
};
|
||||
|
||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[rpass_color_attachment],
|
||||
depth_stencil_attachment: None,
|
||||
});
|
||||
rpass.set_pipeline(&self.pipeline);
|
||||
rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
||||
rpass.draw(0..self.vertex_count, 0..1);
|
||||
encoder
|
||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[rpass_color_attachment],
|
||||
depth_stencil_attachment: None,
|
||||
})
|
||||
.execute_bundles(iter::once(&self.bundle));
|
||||
}
|
||||
|
||||
encoder.finish()
|
||||
|
||||
@@ -31,10 +31,11 @@ pub type Context = wgc::hub::Global<wgc::hub::IdentityManagerFactory>;
|
||||
|
||||
mod pass_impl {
|
||||
use super::Context;
|
||||
use smallvec::SmallVec;
|
||||
use std::ops::Range;
|
||||
use wgc::command::{compute_ffi::*, render_ffi::*};
|
||||
use wgc::command::{bundle_ffi::*, compute_ffi::*, render_ffi::*};
|
||||
|
||||
impl crate::ComputePassInner<Context> for wgc::command::RawPass {
|
||||
impl crate::ComputePassInner<Context> for wgc::command::RawPass<wgc::id::CommandEncoderId> {
|
||||
fn set_pipeline(&mut self, pipeline: &wgc::id::ComputePipelineId) {
|
||||
unsafe { wgpu_compute_pass_set_pipeline(self, *pipeline) }
|
||||
}
|
||||
@@ -66,7 +67,7 @@ mod pass_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::RenderPassInner<Context> for wgc::command::RawPass {
|
||||
impl crate::RenderInner<Context> for wgc::command::RawPass<wgc::id::CommandEncoderId> {
|
||||
fn set_pipeline(&mut self, pipeline: &wgc::id::RenderPipelineId) {
|
||||
unsafe { wgpu_render_pass_set_pipeline(self, *pipeline) }
|
||||
}
|
||||
@@ -103,28 +104,6 @@ mod pass_impl {
|
||||
) {
|
||||
unsafe { wgpu_render_pass_set_vertex_buffer(self, slot, *buffer, offset, size) }
|
||||
}
|
||||
fn set_blend_color(&mut self, color: wgt::Color) {
|
||||
unsafe { wgpu_render_pass_set_blend_color(self, &color) }
|
||||
}
|
||||
fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
|
||||
unsafe { wgpu_render_pass_set_scissor_rect(self, x, y, width, height) }
|
||||
}
|
||||
fn set_viewport(
|
||||
&mut self,
|
||||
x: f32,
|
||||
y: f32,
|
||||
width: f32,
|
||||
height: f32,
|
||||
min_depth: f32,
|
||||
max_depth: f32,
|
||||
) {
|
||||
unsafe {
|
||||
wgpu_render_pass_set_viewport(self, x, y, width, height, min_depth, max_depth)
|
||||
}
|
||||
}
|
||||
fn set_stencil_reference(&mut self, reference: u32) {
|
||||
unsafe { wgpu_render_pass_set_stencil_reference(self, reference) }
|
||||
}
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
|
||||
unsafe {
|
||||
wgpu_render_pass_draw(
|
||||
@@ -165,6 +144,123 @@ mod pass_impl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::RenderPassInner<Context> for wgc::command::RawPass<wgc::id::CommandEncoderId> {
|
||||
fn set_blend_color(&mut self, color: wgt::Color) {
|
||||
unsafe { wgpu_render_pass_set_blend_color(self, &color) }
|
||||
}
|
||||
fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
|
||||
unsafe { wgpu_render_pass_set_scissor_rect(self, x, y, width, height) }
|
||||
}
|
||||
fn set_viewport(
|
||||
&mut self,
|
||||
x: f32,
|
||||
y: f32,
|
||||
width: f32,
|
||||
height: f32,
|
||||
min_depth: f32,
|
||||
max_depth: f32,
|
||||
) {
|
||||
unsafe {
|
||||
wgpu_render_pass_set_viewport(self, x, y, width, height, min_depth, max_depth)
|
||||
}
|
||||
}
|
||||
fn set_stencil_reference(&mut self, reference: u32) {
|
||||
unsafe { wgpu_render_pass_set_stencil_reference(self, reference) }
|
||||
}
|
||||
|
||||
fn execute_bundles<'a, I: Iterator<Item = &'a wgc::id::RenderBundleId>>(
|
||||
&mut self,
|
||||
render_bundles: I,
|
||||
) {
|
||||
let temp_render_bundles = render_bundles.cloned().collect::<SmallVec<[_; 4]>>();
|
||||
unsafe {
|
||||
wgpu_render_pass_execute_bundles(
|
||||
self,
|
||||
temp_render_bundles.as_ptr(),
|
||||
temp_render_bundles.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::RenderInner<Context> for wgc::command::RenderBundleEncoder {
|
||||
fn set_pipeline(&mut self, pipeline: &wgc::id::RenderPipelineId) {
|
||||
unsafe { wgpu_render_bundle_set_pipeline(self, *pipeline) }
|
||||
}
|
||||
fn set_bind_group(
|
||||
&mut self,
|
||||
index: u32,
|
||||
bind_group: &wgc::id::BindGroupId,
|
||||
offsets: &[wgt::DynamicOffset],
|
||||
) {
|
||||
unsafe {
|
||||
wgpu_render_bundle_set_bind_group(
|
||||
self,
|
||||
index,
|
||||
*bind_group,
|
||||
offsets.as_ptr(),
|
||||
offsets.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
fn set_index_buffer(
|
||||
&mut self,
|
||||
buffer: &wgc::id::BufferId,
|
||||
offset: wgt::BufferAddress,
|
||||
size: wgt::BufferSize,
|
||||
) {
|
||||
unsafe { wgpu_render_bundle_set_index_buffer(self, *buffer, offset, size) }
|
||||
}
|
||||
fn set_vertex_buffer(
|
||||
&mut self,
|
||||
slot: u32,
|
||||
buffer: &wgc::id::BufferId,
|
||||
offset: wgt::BufferAddress,
|
||||
size: wgt::BufferSize,
|
||||
) {
|
||||
unsafe { wgpu_render_bundle_set_vertex_buffer(self, slot, *buffer, offset, size) }
|
||||
}
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
|
||||
unsafe {
|
||||
wgpu_render_bundle_draw(
|
||||
self,
|
||||
vertices.end - vertices.start,
|
||||
instances.end - instances.start,
|
||||
vertices.start,
|
||||
instances.start,
|
||||
)
|
||||
}
|
||||
}
|
||||
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
|
||||
unsafe {
|
||||
wgpu_render_bundle_draw_indexed(
|
||||
self,
|
||||
indices.end - indices.start,
|
||||
instances.end - instances.start,
|
||||
indices.start,
|
||||
base_vertex,
|
||||
instances.start,
|
||||
)
|
||||
}
|
||||
}
|
||||
fn draw_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &wgc::id::BufferId,
|
||||
indirect_offset: wgt::BufferAddress,
|
||||
) {
|
||||
unsafe { wgpu_render_bundle_draw_indirect(self, *indirect_buffer, indirect_offset) }
|
||||
}
|
||||
fn draw_indexed_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &wgc::id::BufferId,
|
||||
indirect_offset: wgt::BufferAddress,
|
||||
) {
|
||||
unsafe {
|
||||
wgpu_render_pass_bundle_indexed_indirect(self, *indirect_buffer, indirect_offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn map_buffer_copy_view(view: crate::BufferCopyView) -> wgc::command::BufferCopyView {
|
||||
@@ -197,11 +293,13 @@ impl crate::Context for Context {
|
||||
type RenderPipelineId = wgc::id::RenderPipelineId;
|
||||
type ComputePipelineId = wgc::id::ComputePipelineId;
|
||||
type CommandEncoderId = wgc::id::CommandEncoderId;
|
||||
type ComputePassId = wgc::command::RawPass;
|
||||
type ComputePassId = wgc::command::RawPass<wgc::id::CommandEncoderId>;
|
||||
type RenderPassId = wgc::command::RawPass<wgc::id::CommandEncoderId>;
|
||||
type CommandBufferId = wgc::id::CommandBufferId;
|
||||
type RenderBundleEncoderId = wgc::command::RenderBundleEncoder;
|
||||
type RenderBundleId = wgc::id::RenderBundleId;
|
||||
type SurfaceId = wgc::id::SurfaceId;
|
||||
type SwapChainId = wgc::id::SwapChainId;
|
||||
type RenderPassId = wgc::command::RawPass;
|
||||
|
||||
type SwapChainOutputDetail = SwapChainOutputDetail;
|
||||
|
||||
@@ -518,6 +616,14 @@ impl crate::Context for Context {
|
||||
))
|
||||
}
|
||||
|
||||
fn device_create_render_bundle_encoder(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
desc: &wgt::RenderBundleEncoderDescriptor,
|
||||
) -> Self::RenderBundleEncoderId {
|
||||
wgc::command::RenderBundleEncoder::new(desc, *device)
|
||||
}
|
||||
|
||||
fn device_drop(&self, device: &Self::DeviceId) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
gfx_select!(*device => self.device_poll(*device, true));
|
||||
@@ -663,6 +769,9 @@ impl crate::Context for Context {
|
||||
fn command_buffer_drop(&self, command_buffer: &Self::CommandBufferId) {
|
||||
gfx_select!(*command_buffer => self.command_buffer_destroy(*command_buffer))
|
||||
}
|
||||
fn render_bundle_drop(&self, render_bundle: &Self::RenderBundleId) {
|
||||
gfx_select!(*render_bundle => self.render_bundle_destroy(*render_bundle))
|
||||
}
|
||||
fn compute_pipeline_drop(&self, pipeline: &Self::ComputePipelineId) {
|
||||
gfx_select!(*pipeline => self.compute_pipeline_destroy(*pipeline))
|
||||
}
|
||||
@@ -670,7 +779,7 @@ impl crate::Context for Context {
|
||||
gfx_select!(*pipeline => self.render_pipeline_destroy(*pipeline))
|
||||
}
|
||||
|
||||
fn encoder_copy_buffer_to_buffer(
|
||||
fn command_encoder_copy_buffer_to_buffer(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: &Self::BufferId,
|
||||
@@ -689,7 +798,7 @@ impl crate::Context for Context {
|
||||
))
|
||||
}
|
||||
|
||||
fn encoder_copy_buffer_to_texture(
|
||||
fn command_encoder_copy_buffer_to_texture(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: crate::BufferCopyView,
|
||||
@@ -704,7 +813,7 @@ impl crate::Context for Context {
|
||||
))
|
||||
}
|
||||
|
||||
fn encoder_copy_texture_to_buffer(
|
||||
fn command_encoder_copy_texture_to_buffer(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: crate::TextureCopyView,
|
||||
@@ -719,7 +828,7 @@ impl crate::Context for Context {
|
||||
))
|
||||
}
|
||||
|
||||
fn encoder_copy_texture_to_texture(
|
||||
fn command_encoder_copy_texture_to_texture(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: crate::TextureCopyView,
|
||||
@@ -734,11 +843,14 @@ impl crate::Context for Context {
|
||||
))
|
||||
}
|
||||
|
||||
fn encoder_begin_compute_pass(&self, encoder: &Self::CommandEncoderId) -> Self::ComputePassId {
|
||||
fn command_encoder_begin_compute_pass(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
) -> Self::ComputePassId {
|
||||
unsafe { wgc::command::RawPass::new_compute(*encoder) }
|
||||
}
|
||||
|
||||
fn encoder_end_compute_pass(
|
||||
fn command_encoder_end_compute_pass(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
pass: &mut Self::ComputePassId,
|
||||
@@ -752,7 +864,7 @@ impl crate::Context for Context {
|
||||
unsafe { pass.invalidate() };
|
||||
}
|
||||
|
||||
fn encoder_begin_render_pass<'a>(
|
||||
fn command_encoder_begin_render_pass<'a>(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
desc: &crate::RenderPassDescriptor<'a, '_>,
|
||||
@@ -795,7 +907,7 @@ impl crate::Context for Context {
|
||||
}
|
||||
}
|
||||
|
||||
fn encoder_end_render_pass(
|
||||
fn command_encoder_end_render_pass(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
pass: &mut Self::RenderPassId,
|
||||
@@ -809,11 +921,20 @@ impl crate::Context for Context {
|
||||
unsafe { pass.invalidate() };
|
||||
}
|
||||
|
||||
fn encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId {
|
||||
fn command_encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId {
|
||||
let desc = wgt::CommandBufferDescriptor::default();
|
||||
gfx_select!(*encoder => self.command_encoder_finish(*encoder, &desc))
|
||||
}
|
||||
|
||||
fn render_bundle_encoder_finish(
|
||||
&self,
|
||||
encoder: Self::RenderBundleEncoderId,
|
||||
desc: &crate::RenderBundleDescriptor,
|
||||
) -> Self::RenderBundleId {
|
||||
let owned_label = OwnedLabel::new(desc.label.as_deref());
|
||||
gfx_select!(encoder.parent() => self.render_bundle_encoder_finish(encoder, &desc.map_label(|_| owned_label.as_ptr()), PhantomData))
|
||||
}
|
||||
|
||||
fn queue_write_buffer(
|
||||
&self,
|
||||
queue: &Self::QueueId,
|
||||
|
||||
@@ -84,7 +84,7 @@ impl crate::ComputePassInner<Context> for ComputePass {
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::RenderPassInner<Context> for RenderPass {
|
||||
impl crate::RenderInner<Context> for RenderPass {
|
||||
fn set_pipeline(&mut self, pipeline: &Sendable<web_sys::GpuRenderPipeline>) {
|
||||
self.0.set_pipeline(&pipeline.0);
|
||||
}
|
||||
@@ -124,28 +124,6 @@ impl crate::RenderPassInner<Context> for RenderPass {
|
||||
self.0
|
||||
.set_vertex_buffer_with_f64_and_f64(slot, &buffer.0, offset as f64, size.0 as f64);
|
||||
}
|
||||
fn set_blend_color(&mut self, color: wgt::Color) {
|
||||
self.0
|
||||
.set_blend_color_with_gpu_color_dict(&map_color(color));
|
||||
}
|
||||
fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
|
||||
self.0.set_scissor_rect(x, y, width, height);
|
||||
}
|
||||
fn set_viewport(
|
||||
&mut self,
|
||||
x: f32,
|
||||
y: f32,
|
||||
width: f32,
|
||||
height: f32,
|
||||
min_depth: f32,
|
||||
max_depth: f32,
|
||||
) {
|
||||
self.0
|
||||
.set_viewport(x, y, width, height, min_depth, max_depth);
|
||||
}
|
||||
fn set_stencil_reference(&mut self, reference: u32) {
|
||||
self.0.set_stencil_reference(reference);
|
||||
}
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
|
||||
self.0
|
||||
.draw_with_instance_count_and_first_vertex_and_first_instance(
|
||||
@@ -183,6 +161,34 @@ impl crate::RenderPassInner<Context> for RenderPass {
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::RenderPassInner<Context> for RenderPass {
|
||||
fn set_blend_color(&mut self, color: wgt::Color) {
|
||||
self.0
|
||||
.set_blend_color_with_gpu_color_dict(&map_color(color));
|
||||
}
|
||||
fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
|
||||
self.0.set_scissor_rect(x, y, width, height);
|
||||
}
|
||||
fn set_viewport(
|
||||
&mut self,
|
||||
x: f32,
|
||||
y: f32,
|
||||
width: f32,
|
||||
height: f32,
|
||||
min_depth: f32,
|
||||
max_depth: f32,
|
||||
) {
|
||||
self.0
|
||||
.set_viewport(x, y, width, height, min_depth, max_depth);
|
||||
}
|
||||
fn set_stencil_reference(&mut self, reference: u32) {
|
||||
self.0.set_stencil_reference(reference);
|
||||
}
|
||||
fn execute_bundles<'a, I: Iterator<Item = &'a ()>>(&mut self, render_bundles: I) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn map_texture_format(texture_format: wgt::TextureFormat) -> web_sys::GpuTextureFormat {
|
||||
use web_sys::GpuTextureFormat as tf;
|
||||
use wgt::TextureFormat;
|
||||
@@ -615,10 +621,12 @@ impl crate::Context for Context {
|
||||
type ComputePipelineId = Sendable<web_sys::GpuComputePipeline>;
|
||||
type CommandEncoderId = web_sys::GpuCommandEncoder;
|
||||
type ComputePassId = ComputePass;
|
||||
type RenderPassId = RenderPass;
|
||||
type CommandBufferId = Sendable<web_sys::GpuCommandBuffer>;
|
||||
type RenderBundleEncoderId = RenderPass; //web_sys::GpuRenderBundleEncoder;
|
||||
type RenderBundleId = (); //web_sys::GpuRenderBundle;
|
||||
type SurfaceId = Sendable<web_sys::GpuCanvasContext>;
|
||||
type SwapChainId = Sendable<web_sys::GpuSwapChain>;
|
||||
type RenderPassId = RenderPass;
|
||||
|
||||
type SwapChainOutputDetail = SwapChainOutputDetail;
|
||||
|
||||
@@ -1027,6 +1035,14 @@ impl crate::Context for Context {
|
||||
.create_command_encoder_with_descriptor(&mapped_desc)
|
||||
}
|
||||
|
||||
fn device_create_render_bundle_encoder(
|
||||
&self,
|
||||
_device: &Self::DeviceId,
|
||||
_desc: &wgt::RenderBundleEncoderDescriptor,
|
||||
) -> Self::RenderBundleEncoderId {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn device_drop(&self, _device: &Self::DeviceId) {
|
||||
// Device is dropped automatically
|
||||
}
|
||||
@@ -1117,40 +1133,43 @@ impl crate::Context for Context {
|
||||
}
|
||||
|
||||
fn texture_drop(&self, _texture: &Self::TextureId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn texture_view_drop(&self, _texture_view: &Self::TextureViewId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn sampler_drop(&self, _sampler: &Self::SamplerId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn buffer_drop(&self, _buffer: &Self::BufferId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn bind_group_drop(&self, _bind_group: &Self::BindGroupId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn bind_group_layout_drop(&self, _bind_group_layout: &Self::BindGroupLayoutId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn pipeline_layout_drop(&self, _pipeline_layout: &Self::PipelineLayoutId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn shader_module_drop(&self, _shader_module: &Self::ShaderModuleId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn command_buffer_drop(&self, _command_buffer: &Self::CommandBufferId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn render_bundle_drop(&self, _render_bundle: &Self::RenderBundleId) {
|
||||
// Dropped automatically
|
||||
}
|
||||
fn compute_pipeline_drop(&self, _pipeline: &Self::ComputePipelineId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
fn render_pipeline_drop(&self, _pipeline: &Self::RenderPipelineId) {
|
||||
// Buffer is dropped automatically
|
||||
// Dropped automatically
|
||||
}
|
||||
|
||||
fn encoder_copy_buffer_to_buffer(
|
||||
fn command_encoder_copy_buffer_to_buffer(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: &Self::BufferId,
|
||||
@@ -1168,7 +1187,7 @@ impl crate::Context for Context {
|
||||
)
|
||||
}
|
||||
|
||||
fn encoder_copy_buffer_to_texture(
|
||||
fn command_encoder_copy_buffer_to_texture(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: crate::BufferCopyView,
|
||||
@@ -1182,7 +1201,7 @@ impl crate::Context for Context {
|
||||
)
|
||||
}
|
||||
|
||||
fn encoder_copy_texture_to_buffer(
|
||||
fn command_encoder_copy_texture_to_buffer(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: crate::TextureCopyView,
|
||||
@@ -1196,7 +1215,7 @@ impl crate::Context for Context {
|
||||
)
|
||||
}
|
||||
|
||||
fn encoder_copy_texture_to_texture(
|
||||
fn command_encoder_copy_texture_to_texture(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: crate::TextureCopyView,
|
||||
@@ -1210,7 +1229,10 @@ impl crate::Context for Context {
|
||||
)
|
||||
}
|
||||
|
||||
fn encoder_begin_compute_pass(&self, encoder: &Self::CommandEncoderId) -> Self::ComputePassId {
|
||||
fn command_encoder_begin_compute_pass(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
) -> Self::ComputePassId {
|
||||
let mut mapped_desc = web_sys::GpuComputePassDescriptor::new();
|
||||
if let Some(ref label) = encoder.label() {
|
||||
mapped_desc.label(label);
|
||||
@@ -1218,7 +1240,7 @@ impl crate::Context for Context {
|
||||
ComputePass(encoder.begin_compute_pass_with_descriptor(&mapped_desc))
|
||||
}
|
||||
|
||||
fn encoder_end_compute_pass(
|
||||
fn command_encoder_end_compute_pass(
|
||||
&self,
|
||||
_encoder: &Self::CommandEncoderId,
|
||||
pass: &mut Self::ComputePassId,
|
||||
@@ -1226,7 +1248,7 @@ impl crate::Context for Context {
|
||||
pass.0.end_pass();
|
||||
}
|
||||
|
||||
fn encoder_begin_render_pass<'a>(
|
||||
fn command_encoder_begin_render_pass<'a>(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
desc: &crate::RenderPassDescriptor<'a, '_>,
|
||||
@@ -1284,7 +1306,7 @@ impl crate::Context for Context {
|
||||
RenderPass(encoder.begin_render_pass(&mapped_desc))
|
||||
}
|
||||
|
||||
fn encoder_end_render_pass(
|
||||
fn command_encoder_end_render_pass(
|
||||
&self,
|
||||
_encoder: &Self::CommandEncoderId,
|
||||
pass: &mut Self::RenderPassId,
|
||||
@@ -1292,7 +1314,7 @@ impl crate::Context for Context {
|
||||
pass.0.end_pass();
|
||||
}
|
||||
|
||||
fn encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId {
|
||||
fn command_encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId {
|
||||
let mut mapped_desc = web_sys::GpuCommandBufferDescriptor::new();
|
||||
if let Some(ref label) = encoder.label() {
|
||||
mapped_desc.label(label);
|
||||
@@ -1300,6 +1322,14 @@ impl crate::Context for Context {
|
||||
Sendable(encoder.finish_with_descriptor(&mapped_desc))
|
||||
}
|
||||
|
||||
fn render_bundle_encoder_finish(
|
||||
&self,
|
||||
_encoder: Self::RenderBundleEncoderId,
|
||||
_desc: &crate::RenderBundleDescriptor,
|
||||
) -> Self::RenderBundleId {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn queue_write_buffer(
|
||||
&self,
|
||||
_queue: &Self::QueueId,
|
||||
|
||||
372
src/lib.rs
372
src/lib.rs
@@ -24,11 +24,11 @@ pub use wgt::{
|
||||
BufferUsage, Color, ColorStateDescriptor, ColorWrite, CommandBufferDescriptor, CompareFunction,
|
||||
CullMode, DepthStencilStateDescriptor, DeviceDescriptor, DynamicOffset, Extensions, Extent3d,
|
||||
FilterMode, FrontFace, IndexFormat, InputStepMode, Limits, LoadOp, Origin3d, PowerPreference,
|
||||
PresentMode, PrimitiveTopology, RasterizationStateDescriptor, ShaderLocation, ShaderStage,
|
||||
StencilOperation, StencilStateFaceDescriptor, StoreOp, SwapChainDescriptor, SwapChainStatus,
|
||||
TextureAspect, TextureComponentType, TextureDataLayout, TextureDimension, TextureFormat,
|
||||
TextureUsage, TextureViewDimension, UnsafeExtensions, VertexAttributeDescriptor, VertexFormat,
|
||||
BIND_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT,
|
||||
PresentMode, PrimitiveTopology, RasterizationStateDescriptor, RenderBundleEncoderDescriptor,
|
||||
ShaderLocation, ShaderStage, StencilOperation, StencilStateFaceDescriptor, StoreOp,
|
||||
SwapChainDescriptor, SwapChainStatus, TextureAspect, TextureComponentType, TextureDataLayout,
|
||||
TextureDimension, TextureFormat, TextureUsage, TextureViewDimension, UnsafeExtensions,
|
||||
VertexAttributeDescriptor, VertexFormat, BIND_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT,
|
||||
};
|
||||
|
||||
use backend::Context as C;
|
||||
@@ -49,7 +49,7 @@ trait ComputePassInner<Ctx: Context> {
|
||||
);
|
||||
}
|
||||
|
||||
trait RenderPassInner<Ctx: Context> {
|
||||
trait RenderInner<Ctx: Context> {
|
||||
fn set_pipeline(&mut self, pipeline: &Ctx::RenderPipelineId);
|
||||
fn set_bind_group(
|
||||
&mut self,
|
||||
@@ -65,7 +65,18 @@ trait RenderPassInner<Ctx: Context> {
|
||||
offset: BufferAddress,
|
||||
size: BufferSize,
|
||||
);
|
||||
fn set_blend_color(&mut self, color: wgt::Color);
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>);
|
||||
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
|
||||
fn draw_indirect(&mut self, indirect_buffer: &Ctx::BufferId, indirect_offset: BufferAddress);
|
||||
fn draw_indexed_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &Ctx::BufferId,
|
||||
indirect_offset: BufferAddress,
|
||||
);
|
||||
}
|
||||
|
||||
trait RenderPassInner<Ctx: Context>: RenderInner<Ctx> {
|
||||
fn set_blend_color(&mut self, color: Color);
|
||||
fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32);
|
||||
fn set_viewport(
|
||||
&mut self,
|
||||
@@ -77,36 +88,34 @@ trait RenderPassInner<Ctx: Context> {
|
||||
max_depth: f32,
|
||||
);
|
||||
fn set_stencil_reference(&mut self, reference: u32);
|
||||
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>);
|
||||
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
|
||||
fn draw_indirect(&mut self, indirect_buffer: &Ctx::BufferId, indirect_offset: BufferAddress);
|
||||
fn draw_indexed_indirect(
|
||||
fn execute_bundles<'a, I: Iterator<Item = &'a Ctx::RenderBundleId>>(
|
||||
&mut self,
|
||||
indirect_buffer: &Ctx::BufferId,
|
||||
indirect_offset: BufferAddress,
|
||||
render_bundles: I,
|
||||
);
|
||||
}
|
||||
|
||||
trait Context: Sized {
|
||||
type AdapterId: Send + Sync;
|
||||
type DeviceId: Send + Sync;
|
||||
type QueueId: Send + Sync;
|
||||
type ShaderModuleId: Send + Sync;
|
||||
type BindGroupLayoutId: Send + Sync;
|
||||
type BindGroupId: Send + Sync;
|
||||
type TextureViewId: Send + Sync;
|
||||
type SamplerId: Send + Sync;
|
||||
type BufferId: Send + Sync;
|
||||
type TextureId: Send + Sync;
|
||||
type PipelineLayoutId: Send + Sync;
|
||||
type RenderPipelineId: Send + Sync;
|
||||
type ComputePipelineId: Send + Sync;
|
||||
type AdapterId: Send + Sync + 'static;
|
||||
type DeviceId: Send + Sync + 'static;
|
||||
type QueueId: Send + Sync + 'static;
|
||||
type ShaderModuleId: Send + Sync + 'static;
|
||||
type BindGroupLayoutId: Send + Sync + 'static;
|
||||
type BindGroupId: Send + Sync + 'static;
|
||||
type TextureViewId: Send + Sync + 'static;
|
||||
type SamplerId: Send + Sync + 'static;
|
||||
type BufferId: Send + Sync + 'static;
|
||||
type TextureId: Send + Sync + 'static;
|
||||
type PipelineLayoutId: Send + Sync + 'static;
|
||||
type RenderPipelineId: Send + Sync + 'static;
|
||||
type ComputePipelineId: Send + Sync + 'static;
|
||||
type CommandEncoderId;
|
||||
type ComputePassId: ComputePassInner<Self>;
|
||||
type CommandBufferId: Send + Sync;
|
||||
type SurfaceId: Send + Sync;
|
||||
type SwapChainId: Send + Sync;
|
||||
type RenderPassId: RenderPassInner<Self>;
|
||||
type CommandBufferId: Send + Sync;
|
||||
type RenderBundleEncoderId: RenderInner<Self>;
|
||||
type RenderBundleId: Send + Sync + 'static;
|
||||
type SurfaceId: Send + Sync + 'static;
|
||||
type SwapChainId: Send + Sync + 'static;
|
||||
|
||||
type SwapChainOutputDetail: Send;
|
||||
|
||||
@@ -123,8 +132,8 @@ trait Context: Sized {
|
||||
fn instance_request_adapter(
|
||||
&self,
|
||||
options: &RequestAdapterOptions<'_>,
|
||||
unsafe_extensions: wgt::UnsafeExtensions,
|
||||
backends: wgt::BackendBit,
|
||||
unsafe_extensions: UnsafeExtensions,
|
||||
backends: BackendBit,
|
||||
) -> Self::RequestAdapterFuture;
|
||||
fn adapter_request_device(
|
||||
&self,
|
||||
@@ -193,6 +202,11 @@ trait Context: Sized {
|
||||
device: &Self::DeviceId,
|
||||
desc: &CommandEncoderDescriptor,
|
||||
) -> Self::CommandEncoderId;
|
||||
fn device_create_render_bundle_encoder(
|
||||
&self,
|
||||
device: &Self::DeviceId,
|
||||
desc: &RenderBundleEncoderDescriptor,
|
||||
) -> Self::RenderBundleEncoderId;
|
||||
fn device_drop(&self, device: &Self::DeviceId);
|
||||
fn device_poll(&self, device: &Self::DeviceId, maintain: Maintain);
|
||||
|
||||
@@ -238,10 +252,11 @@ trait Context: Sized {
|
||||
fn pipeline_layout_drop(&self, pipeline_layout: &Self::PipelineLayoutId);
|
||||
fn shader_module_drop(&self, shader_module: &Self::ShaderModuleId);
|
||||
fn command_buffer_drop(&self, command_buffer: &Self::CommandBufferId);
|
||||
fn render_bundle_drop(&self, render_bundle: &Self::RenderBundleId);
|
||||
fn compute_pipeline_drop(&self, pipeline: &Self::ComputePipelineId);
|
||||
fn render_pipeline_drop(&self, pipeline: &Self::RenderPipelineId);
|
||||
|
||||
fn encoder_copy_buffer_to_buffer(
|
||||
fn command_encoder_copy_buffer_to_buffer(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: &Self::BufferId,
|
||||
@@ -250,21 +265,21 @@ trait Context: Sized {
|
||||
destination_offset: BufferAddress,
|
||||
copy_size: BufferAddress,
|
||||
);
|
||||
fn encoder_copy_buffer_to_texture(
|
||||
fn command_encoder_copy_buffer_to_texture(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: BufferCopyView,
|
||||
destination: TextureCopyView,
|
||||
copy_size: Extent3d,
|
||||
);
|
||||
fn encoder_copy_texture_to_buffer(
|
||||
fn command_encoder_copy_texture_to_buffer(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: TextureCopyView,
|
||||
destination: BufferCopyView,
|
||||
copy_size: Extent3d,
|
||||
);
|
||||
fn encoder_copy_texture_to_texture(
|
||||
fn command_encoder_copy_texture_to_texture(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
source: TextureCopyView,
|
||||
@@ -272,23 +287,31 @@ trait Context: Sized {
|
||||
copy_size: Extent3d,
|
||||
);
|
||||
|
||||
fn encoder_begin_compute_pass(&self, encoder: &Self::CommandEncoderId) -> Self::ComputePassId;
|
||||
fn encoder_end_compute_pass(
|
||||
fn command_encoder_begin_compute_pass(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
) -> Self::ComputePassId;
|
||||
fn command_encoder_end_compute_pass(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
pass: &mut Self::ComputePassId,
|
||||
);
|
||||
fn encoder_begin_render_pass<'a>(
|
||||
fn command_encoder_begin_render_pass<'a>(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
desc: &RenderPassDescriptor<'a, '_>,
|
||||
) -> Self::RenderPassId;
|
||||
fn encoder_end_render_pass(
|
||||
fn command_encoder_end_render_pass(
|
||||
&self,
|
||||
encoder: &Self::CommandEncoderId,
|
||||
pass: &mut Self::RenderPassId,
|
||||
);
|
||||
fn encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId;
|
||||
fn command_encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId;
|
||||
fn render_bundle_encoder_finish(
|
||||
&self,
|
||||
encoder: Self::RenderBundleEncoderId,
|
||||
desc: &RenderBundleDescriptor,
|
||||
) -> Self::RenderBundleId;
|
||||
fn queue_write_buffer(
|
||||
&self,
|
||||
queue: &Self::QueueId,
|
||||
@@ -301,8 +324,8 @@ trait Context: Sized {
|
||||
queue: &Self::QueueId,
|
||||
texture: TextureCopyView,
|
||||
data: &[u8],
|
||||
data_layout: wgt::TextureDataLayout,
|
||||
size: wgt::Extent3d,
|
||||
data_layout: TextureDataLayout,
|
||||
size: Extent3d,
|
||||
);
|
||||
fn queue_submit<I: Iterator<Item = Self::CommandBufferId>>(
|
||||
&self,
|
||||
@@ -462,7 +485,9 @@ pub struct Sampler {
|
||||
|
||||
impl Drop for Sampler {
|
||||
fn drop(&mut self) {
|
||||
self.context.sampler_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.sampler_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,7 +521,9 @@ pub struct BindGroupLayout {
|
||||
|
||||
impl Drop for BindGroupLayout {
|
||||
fn drop(&mut self) {
|
||||
self.context.bind_group_layout_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.bind_group_layout_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,7 +540,9 @@ pub struct BindGroup {
|
||||
|
||||
impl Drop for BindGroup {
|
||||
fn drop(&mut self) {
|
||||
self.context.bind_group_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.bind_group_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,7 +558,9 @@ pub struct ShaderModule {
|
||||
|
||||
impl Drop for ShaderModule {
|
||||
fn drop(&mut self) {
|
||||
self.context.shader_module_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.shader_module_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +574,9 @@ pub struct PipelineLayout {
|
||||
|
||||
impl Drop for PipelineLayout {
|
||||
fn drop(&mut self) {
|
||||
self.context.pipeline_layout_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.pipeline_layout_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -558,7 +591,9 @@ pub struct RenderPipeline {
|
||||
|
||||
impl Drop for RenderPipeline {
|
||||
fn drop(&mut self) {
|
||||
self.context.render_pipeline_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.render_pipeline_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,7 +605,9 @@ pub struct ComputePipeline {
|
||||
|
||||
impl Drop for ComputePipeline {
|
||||
fn drop(&mut self) {
|
||||
self.context.compute_pipeline_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.compute_pipeline_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,8 +623,10 @@ pub struct CommandBuffer {
|
||||
|
||||
impl Drop for CommandBuffer {
|
||||
fn drop(&mut self) {
|
||||
if let Some(ref id) = self.id {
|
||||
self.context.command_buffer_drop(id);
|
||||
if !thread::panicking() {
|
||||
if let Some(ref id) = self.id {
|
||||
self.context.command_buffer_drop(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -619,6 +658,32 @@ pub struct ComputePass<'a> {
|
||||
parent: &'a mut CommandEncoder,
|
||||
}
|
||||
|
||||
/// An object that encodes GPU operations into a render bundle.
|
||||
///
|
||||
/// It only supports a handful of render commands, but it makes them re-usable.
|
||||
pub struct RenderBundleEncoder<'a> {
|
||||
context: Arc<C>,
|
||||
id: <C as Context>::RenderBundleEncoderId,
|
||||
_parent: &'a Device,
|
||||
/// This type should be !Send !Sync, because it represents an allocation on this thread's
|
||||
/// command buffer.
|
||||
_p: PhantomData<*const u8>,
|
||||
}
|
||||
|
||||
/// A finished render bundle.
|
||||
pub struct RenderBundle {
|
||||
context: Arc<C>,
|
||||
id: <C as Context>::RenderBundleId,
|
||||
}
|
||||
|
||||
impl Drop for RenderBundle {
|
||||
fn drop(&mut self) {
|
||||
if !thread::panicking() {
|
||||
self.context.render_bundle_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to a command queue on a device.
|
||||
///
|
||||
/// A `Queue` executes recorded [`CommandBuffer`] objects.
|
||||
@@ -766,12 +831,10 @@ pub struct RenderPassDescriptor<'a, 'b> {
|
||||
pub type BufferDescriptor<'a> = wgt::BufferDescriptor<Option<&'a str>>;
|
||||
|
||||
/// A description of a command encoder.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
pub struct CommandEncoderDescriptor<'a> {
|
||||
/// An optional label to apply to the command encoder.
|
||||
/// This can be useful for debugging and performance analysis.
|
||||
pub label: Option<&'a str>,
|
||||
}
|
||||
pub type CommandEncoderDescriptor<'a> = wgt::CommandEncoderDescriptor<Option<&'a str>>;
|
||||
|
||||
/// A description of a render bundle.
|
||||
pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Option<&'a str>>;
|
||||
|
||||
/// A description of a texture.
|
||||
pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Option<&'a str>>;
|
||||
@@ -810,7 +873,7 @@ pub struct BufferCopyView<'a> {
|
||||
pub buffer: &'a Buffer,
|
||||
|
||||
/// The layout of the texture data in this buffer.
|
||||
pub layout: wgt::TextureDataLayout,
|
||||
pub layout: TextureDataLayout,
|
||||
}
|
||||
|
||||
/// A view of a texture which can be used to copy to or from a buffer or another texture.
|
||||
@@ -838,8 +901,8 @@ impl Instance {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn enumerate_adapters(
|
||||
&self,
|
||||
unsafe_extensions: wgt::UnsafeExtensions,
|
||||
backends: wgt::BackendBit,
|
||||
unsafe_extensions: UnsafeExtensions,
|
||||
backends: BackendBit,
|
||||
) -> impl Iterator<Item = Adapter> {
|
||||
let context = Arc::clone(&self.context);
|
||||
self.context
|
||||
@@ -900,7 +963,7 @@ impl Instance {
|
||||
pub fn request_adapter(
|
||||
&self,
|
||||
options: &RequestAdapterOptions<'_>,
|
||||
unsafe_extensions: wgt::UnsafeExtensions,
|
||||
unsafe_extensions: UnsafeExtensions,
|
||||
backends: BackendBit,
|
||||
) -> impl Future<Output = Option<Adapter>> + Send {
|
||||
let context = Arc::clone(&self.context);
|
||||
@@ -985,6 +1048,19 @@ impl Device {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an empty [`RenderBundleEncoder`].
|
||||
pub fn create_render_bundle_encoder(
|
||||
&self,
|
||||
desc: &RenderBundleEncoderDescriptor,
|
||||
) -> RenderBundleEncoder {
|
||||
RenderBundleEncoder {
|
||||
context: Arc::clone(&self.context),
|
||||
id: Context::device_create_render_bundle_encoder(&*self.context, &self.id, desc),
|
||||
_parent: self,
|
||||
_p: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new bind group.
|
||||
pub fn create_bind_group(&self, desc: &BindGroupDescriptor) -> BindGroup {
|
||||
BindGroup {
|
||||
@@ -1087,7 +1163,9 @@ impl Device {
|
||||
|
||||
impl Drop for Device {
|
||||
fn drop(&mut self) {
|
||||
self.context.device_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.device_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1283,7 +1361,9 @@ impl BufferSlice<'_> {
|
||||
|
||||
impl Drop for Buffer {
|
||||
fn drop(&mut self) {
|
||||
self.context.buffer_drop(&self.id);
|
||||
if !thread::panicking() {
|
||||
self.context.buffer_drop(&self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1309,7 +1389,7 @@ impl Texture {
|
||||
|
||||
impl Drop for Texture {
|
||||
fn drop(&mut self) {
|
||||
if self.owned {
|
||||
if self.owned && !thread::panicking() {
|
||||
self.context.texture_drop(&self.id);
|
||||
}
|
||||
}
|
||||
@@ -1317,7 +1397,7 @@ impl Drop for Texture {
|
||||
|
||||
impl Drop for TextureView {
|
||||
fn drop(&mut self) {
|
||||
if self.owned {
|
||||
if self.owned && !thread::panicking() {
|
||||
self.context.texture_view_drop(&self.id);
|
||||
}
|
||||
}
|
||||
@@ -1328,7 +1408,7 @@ impl CommandEncoder {
|
||||
pub fn finish(self) -> CommandBuffer {
|
||||
CommandBuffer {
|
||||
context: Arc::clone(&self.context),
|
||||
id: Some(Context::encoder_finish(&*self.context, &self.id)),
|
||||
id: Some(Context::command_encoder_finish(&*self.context, &self.id)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1340,7 +1420,7 @@ impl CommandEncoder {
|
||||
desc: &RenderPassDescriptor<'a, '_>,
|
||||
) -> RenderPass<'a> {
|
||||
RenderPass {
|
||||
id: Context::encoder_begin_render_pass(&*self.context, &self.id, desc),
|
||||
id: Context::command_encoder_begin_render_pass(&*self.context, &self.id, desc),
|
||||
parent: self,
|
||||
}
|
||||
}
|
||||
@@ -1350,7 +1430,7 @@ impl CommandEncoder {
|
||||
/// This function returns a [`ComputePass`] object which records a single compute pass.
|
||||
pub fn begin_compute_pass(&mut self) -> ComputePass {
|
||||
ComputePass {
|
||||
id: Context::encoder_begin_compute_pass(&*self.context, &self.id),
|
||||
id: Context::command_encoder_begin_compute_pass(&*self.context, &self.id),
|
||||
parent: self,
|
||||
}
|
||||
}
|
||||
@@ -1364,7 +1444,7 @@ impl CommandEncoder {
|
||||
destination_offset: BufferAddress,
|
||||
copy_size: BufferAddress,
|
||||
) {
|
||||
Context::encoder_copy_buffer_to_buffer(
|
||||
Context::command_encoder_copy_buffer_to_buffer(
|
||||
&*self.context,
|
||||
&self.id,
|
||||
&source.id,
|
||||
@@ -1382,7 +1462,7 @@ impl CommandEncoder {
|
||||
destination: TextureCopyView,
|
||||
copy_size: Extent3d,
|
||||
) {
|
||||
Context::encoder_copy_buffer_to_texture(
|
||||
Context::command_encoder_copy_buffer_to_texture(
|
||||
&*self.context,
|
||||
&self.id,
|
||||
source,
|
||||
@@ -1398,7 +1478,7 @@ impl CommandEncoder {
|
||||
destination: BufferCopyView,
|
||||
copy_size: Extent3d,
|
||||
) {
|
||||
Context::encoder_copy_texture_to_buffer(
|
||||
Context::command_encoder_copy_texture_to_buffer(
|
||||
&*self.context,
|
||||
&self.id,
|
||||
source,
|
||||
@@ -1414,7 +1494,7 @@ impl CommandEncoder {
|
||||
destination: TextureCopyView,
|
||||
copy_size: Extent3d,
|
||||
) {
|
||||
Context::encoder_copy_texture_to_texture(
|
||||
Context::command_encoder_copy_texture_to_texture(
|
||||
&*self.context,
|
||||
&self.id,
|
||||
source,
|
||||
@@ -1432,14 +1512,14 @@ impl<'a> RenderPass<'a> {
|
||||
bind_group: &'a BindGroup,
|
||||
offsets: &[DynamicOffset],
|
||||
) {
|
||||
RenderPassInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets)
|
||||
RenderInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets)
|
||||
}
|
||||
|
||||
/// Sets the active render pipeline.
|
||||
///
|
||||
/// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
|
||||
pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
|
||||
RenderPassInner::set_pipeline(&mut self.id, &pipeline.id)
|
||||
RenderInner::set_pipeline(&mut self.id, &pipeline.id)
|
||||
}
|
||||
|
||||
pub fn set_blend_color(&mut self, color: Color) {
|
||||
@@ -1451,7 +1531,7 @@ impl<'a> RenderPass<'a> {
|
||||
/// Subsequent calls to [`draw_indexed`](RenderPass::draw_indexed) on this [`RenderPass`] will
|
||||
/// use `buffer` as the source index buffer.
|
||||
pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>) {
|
||||
RenderPassInner::set_index_buffer(
|
||||
RenderInner::set_index_buffer(
|
||||
&mut self.id,
|
||||
&buffer_slice.buffer.id,
|
||||
buffer_slice.offset,
|
||||
@@ -1472,7 +1552,7 @@ impl<'a> RenderPass<'a> {
|
||||
/// [`RenderPass`]: struct.RenderPass.html
|
||||
/// [`RenderPipelineDescriptor::vertex_buffers`]: struct.RenderPipelineDescriptor.html#structfield.vertex_buffers
|
||||
pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
|
||||
RenderPassInner::set_vertex_buffer(
|
||||
RenderInner::set_vertex_buffer(
|
||||
&mut self.id,
|
||||
slot,
|
||||
&buffer_slice.buffer.id,
|
||||
@@ -1506,7 +1586,7 @@ impl<'a> RenderPass<'a> {
|
||||
///
|
||||
/// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
|
||||
pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
|
||||
RenderPassInner::draw(&mut self.id, vertices, instances)
|
||||
RenderInner::draw(&mut self.id, vertices, instances)
|
||||
}
|
||||
|
||||
/// Draws indexed primitives using the active index buffer and the active vertex buffers.
|
||||
@@ -1514,7 +1594,7 @@ impl<'a> RenderPass<'a> {
|
||||
/// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
|
||||
/// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
|
||||
pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
|
||||
RenderPassInner::draw_indexed(&mut self.id, indices, base_vertex, instances);
|
||||
RenderInner::draw_indexed(&mut self.id, indices, base_vertex, instances);
|
||||
}
|
||||
|
||||
/// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
|
||||
@@ -1562,6 +1642,11 @@ impl<'a> RenderPass<'a> {
|
||||
self.id
|
||||
.draw_indexed_indirect(&indirect_buffer.id, indirect_offset);
|
||||
}
|
||||
|
||||
pub fn execute_bundles<I: Iterator<Item = &'a RenderBundle>>(&mut self, render_bundles: I) {
|
||||
self.id
|
||||
.execute_bundles(render_bundles.into_iter().map(|rb| &rb.id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for RenderPass<'a> {
|
||||
@@ -1569,7 +1654,7 @@ impl<'a> Drop for RenderPass<'a> {
|
||||
if !thread::panicking() {
|
||||
self.parent
|
||||
.context
|
||||
.encoder_end_render_pass(&self.parent.id, &mut self.id);
|
||||
.command_encoder_end_render_pass(&self.parent.id, &mut self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1612,11 +1697,134 @@ impl<'a> Drop for ComputePass<'a> {
|
||||
if !thread::panicking() {
|
||||
self.parent
|
||||
.context
|
||||
.encoder_end_compute_pass(&self.parent.id, &mut self.id);
|
||||
.command_encoder_end_compute_pass(&self.parent.id, &mut self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RenderBundleEncoder<'a> {
|
||||
/// Finishes recording and returns a [`RenderBundle`] that can be executed in other render passes.
|
||||
pub fn finish(self, desc: &RenderBundleDescriptor) -> RenderBundle {
|
||||
RenderBundle {
|
||||
context: Arc::clone(&self.context),
|
||||
id: Context::render_bundle_encoder_finish(&*self.context, self.id, desc),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the active bind group for a given bind group index.
|
||||
pub fn set_bind_group(
|
||||
&mut self,
|
||||
index: u32,
|
||||
bind_group: &'a BindGroup,
|
||||
offsets: &[DynamicOffset],
|
||||
) {
|
||||
RenderInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets)
|
||||
}
|
||||
|
||||
/// Sets the active render pipeline.
|
||||
///
|
||||
/// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
|
||||
pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
|
||||
RenderInner::set_pipeline(&mut self.id, &pipeline.id)
|
||||
}
|
||||
|
||||
/// Sets the active index buffer.
|
||||
///
|
||||
/// Subsequent calls to [`draw_indexed`](RenderBundleEncoder::draw_indexed) on this [`RenderBundleEncoder`] will
|
||||
/// use `buffer` as the source index buffer.
|
||||
pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>) {
|
||||
RenderInner::set_index_buffer(
|
||||
&mut self.id,
|
||||
&buffer_slice.buffer.id,
|
||||
buffer_slice.offset,
|
||||
buffer_slice.size,
|
||||
)
|
||||
}
|
||||
|
||||
/// Assign a vertex buffer to a slot.
|
||||
///
|
||||
/// Subsequent calls to [`draw`] and [`draw_indexed`] on this
|
||||
/// [`RenderBundleEncoder`] will use `buffer` as one of the source vertex buffers.
|
||||
///
|
||||
/// The `slot` refers to the index of the matching descriptor in
|
||||
/// [`RenderPipelineDescriptor::vertex_buffers`].
|
||||
///
|
||||
/// [`draw`]: #method.draw
|
||||
/// [`draw_indexed`]: #method.draw_indexed
|
||||
/// [`RenderBundleEncoder`]: struct.RenderBundleEncoder.html
|
||||
/// [`RenderPipelineDescriptor::vertex_buffers`]: struct.RenderPipelineDescriptor.html#structfield.vertex_buffers
|
||||
pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
|
||||
RenderInner::set_vertex_buffer(
|
||||
&mut self.id,
|
||||
slot,
|
||||
&buffer_slice.buffer.id,
|
||||
buffer_slice.offset,
|
||||
buffer_slice.size,
|
||||
)
|
||||
}
|
||||
|
||||
/// Draws primitives from the active vertex buffer(s).
|
||||
///
|
||||
/// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
|
||||
pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
|
||||
RenderInner::draw(&mut self.id, vertices, instances)
|
||||
}
|
||||
|
||||
/// Draws indexed primitives using the active index buffer and the active vertex buffers.
|
||||
///
|
||||
/// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active
|
||||
/// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
|
||||
pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
|
||||
RenderInner::draw_indexed(&mut self.id, indices, base_vertex, instances);
|
||||
}
|
||||
|
||||
/// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
|
||||
///
|
||||
/// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
|
||||
///
|
||||
/// The structure expected in `indirect_buffer` is the following:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[repr(C)]
|
||||
/// struct DrawIndirect {
|
||||
/// vertex_count: u32, // The number of vertices to draw.
|
||||
/// instance_count: u32, // The number of instances to draw.
|
||||
/// base_vertex: u32, // The Index of the first vertex to draw.
|
||||
/// base_instance: u32, // The instance ID of the first instance to draw.
|
||||
/// }
|
||||
/// ```
|
||||
pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
|
||||
self.id.draw_indirect(&indirect_buffer.id, indirect_offset);
|
||||
}
|
||||
|
||||
/// Draws indexed primitives using the active index buffer and the active vertex buffers,
|
||||
/// based on the contents of the `indirect_buffer`.
|
||||
///
|
||||
/// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active
|
||||
/// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
|
||||
///
|
||||
/// The structure expected in `indirect_buffer` is the following:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[repr(C)]
|
||||
/// struct DrawIndexedIndirect {
|
||||
/// vertex_count: u32, // The number of vertices to draw.
|
||||
/// instance_count: u32, // The number of instances to draw.
|
||||
/// base_index: u32, // The base index within the index buffer.
|
||||
/// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
|
||||
/// base_instance: u32, // The instance ID of the first instance to draw.
|
||||
/// }
|
||||
/// ```
|
||||
pub fn draw_indexed_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &'a Buffer,
|
||||
indirect_offset: BufferAddress,
|
||||
) {
|
||||
self.id
|
||||
.draw_indexed_indirect(&indirect_buffer.id, indirect_offset);
|
||||
}
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
/// Schedule a data write into `buffer` starting at `offset`.
|
||||
pub fn write_buffer(&self, buffer: &Buffer, offset: BufferAddress, data: &[u8]) {
|
||||
@@ -1628,8 +1836,8 @@ impl Queue {
|
||||
&self,
|
||||
texture: TextureCopyView,
|
||||
data: &[u8],
|
||||
data_layout: wgt::TextureDataLayout,
|
||||
size: wgt::Extent3d,
|
||||
data_layout: TextureDataLayout,
|
||||
size: Extent3d,
|
||||
) {
|
||||
Context::queue_write_texture(&*self.context, &self.id, texture, data, data_layout, size)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user