Vendor wgpu-hal 29.0.4 and i-slint-renderer-skia 1.17.1, unmodified

The Android develop view reads its frame back through memory (TD-1)
because wgpu's Vulkan swapchain never pre-rotates, and a portrait window
on this tablet's landscape panel then tears. The fix is a small patch to
each of these two crates, and this commit is only the ground it lands on:
both are byte-for-byte the crates.io sources the lockfile already
resolved, so the commits that follow are the patch and nothing else.

third_party/ is excluded from the workspace, or every path dependency
under the root would become a member and `--workspace` would test and
lint upstream code as ours. The README says how to carry the patches
across a Slint or wgpu bump, which matters because a stale version here
does not fail the build — cargo just warns and uses the unpatched crate.
This commit is contained in:
2026-09-25 04:18:39 -04:00
parent b5ae5c2be1
commit dc1add9dbb
112 changed files with 60304 additions and 4 deletions
+81
View File
@@ -0,0 +1,81 @@
use alloc::boxed::Box;
use crate::{
Adapter, Api, DeviceError, OpenDevice, SurfaceCapabilities, TextureFormatCapabilities,
};
use super::{DynDevice, DynQueue, DynResource, DynResourceExt, DynSurface};
pub struct DynOpenDevice {
pub device: Box<dyn DynDevice>,
pub queue: Box<dyn DynQueue>,
}
impl<A: Api> From<OpenDevice<A>> for DynOpenDevice {
fn from(open_device: OpenDevice<A>) -> Self {
Self {
device: Box::new(open_device.device),
queue: Box::new(open_device.queue),
}
}
}
pub trait DynAdapter: DynResource {
unsafe fn open(
&self,
features: wgt::Features,
limits: &wgt::Limits,
memory_hints: &wgt::MemoryHints,
) -> Result<DynOpenDevice, DeviceError>;
unsafe fn texture_format_capabilities(
&self,
format: wgt::TextureFormat,
) -> TextureFormatCapabilities;
unsafe fn surface_capabilities(&self, surface: &dyn DynSurface) -> Option<SurfaceCapabilities>;
unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp;
fn get_ordered_buffer_usages(&self) -> wgt::BufferUses;
fn get_ordered_texture_usages(&self) -> wgt::TextureUses;
}
impl<A: Adapter + DynResource> DynAdapter for A {
unsafe fn open(
&self,
features: wgt::Features,
limits: &wgt::Limits,
memory_hints: &wgt::MemoryHints,
) -> Result<DynOpenDevice, DeviceError> {
unsafe { A::open(self, features, limits, memory_hints) }.map(|open_device| DynOpenDevice {
device: Box::new(open_device.device),
queue: Box::new(open_device.queue),
})
}
unsafe fn texture_format_capabilities(
&self,
format: wgt::TextureFormat,
) -> TextureFormatCapabilities {
unsafe { A::texture_format_capabilities(self, format) }
}
unsafe fn surface_capabilities(&self, surface: &dyn DynSurface) -> Option<SurfaceCapabilities> {
let surface = surface.expect_downcast_ref();
unsafe { A::surface_capabilities(self, surface) }
}
unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp {
unsafe { A::get_presentation_timestamp(self) }
}
fn get_ordered_buffer_usages(&self) -> wgt::BufferUses {
A::get_ordered_buffer_usages(self)
}
fn get_ordered_texture_usages(&self) -> wgt::TextureUses {
A::get_ordered_texture_usages(self)
}
}
+761
View File
@@ -0,0 +1,761 @@
use alloc::{boxed::Box, vec::Vec};
use core::ops::Range;
use crate::{
AccelerationStructureBarrier, Api, Attachment, BufferBarrier, BufferBinding, BufferCopy,
BufferTextureCopy, BuildAccelerationStructureDescriptor, ColorAttachment, CommandEncoder,
ComputePassDescriptor, DepthStencilAttachment, DeviceError, Label, MemoryRange,
PassTimestampWrites, Rect, RenderPassDescriptor, TextureBarrier, TextureCopy,
};
use super::{
DynAccelerationStructure, DynBindGroup, DynBuffer, DynCommandBuffer, DynComputePipeline,
DynPipelineLayout, DynQuerySet, DynRenderPipeline, DynResource, DynResourceExt as _,
DynTexture, DynTextureView,
};
pub trait DynCommandEncoder: DynResource + core::fmt::Debug {
unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
unsafe fn discard_encoding(&mut self);
unsafe fn end_encoding(&mut self) -> Result<Box<dyn DynCommandBuffer>, DeviceError>;
unsafe fn reset_all(&mut self, command_buffers: Vec<Box<dyn DynCommandBuffer>>);
unsafe fn transition_buffers(&mut self, barriers: &[BufferBarrier<'_, dyn DynBuffer>]);
unsafe fn transition_textures(&mut self, barriers: &[TextureBarrier<'_, dyn DynTexture>]);
unsafe fn clear_buffer(&mut self, buffer: &dyn DynBuffer, range: MemoryRange);
unsafe fn copy_buffer_to_buffer(
&mut self,
src: &dyn DynBuffer,
dst: &dyn DynBuffer,
regions: &[BufferCopy],
);
unsafe fn copy_texture_to_texture(
&mut self,
src: &dyn DynTexture,
src_usage: wgt::TextureUses,
dst: &dyn DynTexture,
regions: &[TextureCopy],
);
unsafe fn copy_buffer_to_texture(
&mut self,
src: &dyn DynBuffer,
dst: &dyn DynTexture,
regions: &[BufferTextureCopy],
);
unsafe fn copy_texture_to_buffer(
&mut self,
src: &dyn DynTexture,
src_usage: wgt::TextureUses,
dst: &dyn DynBuffer,
regions: &[BufferTextureCopy],
);
unsafe fn set_bind_group(
&mut self,
layout: &dyn DynPipelineLayout,
index: u32,
group: &dyn DynBindGroup,
dynamic_offsets: &[wgt::DynamicOffset],
);
unsafe fn set_immediates(
&mut self,
layout: &dyn DynPipelineLayout,
offset_bytes: u32,
data: &[u32],
);
unsafe fn insert_debug_marker(&mut self, label: &str);
unsafe fn begin_debug_marker(&mut self, group_label: &str);
unsafe fn end_debug_marker(&mut self);
unsafe fn begin_query(&mut self, set: &dyn DynQuerySet, index: u32);
unsafe fn end_query(&mut self, set: &dyn DynQuerySet, index: u32);
unsafe fn write_timestamp(&mut self, set: &dyn DynQuerySet, index: u32);
unsafe fn reset_queries(&mut self, set: &dyn DynQuerySet, range: Range<u32>);
unsafe fn copy_query_results(
&mut self,
set: &dyn DynQuerySet,
range: Range<u32>,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
stride: wgt::BufferSize,
);
unsafe fn begin_render_pass(
&mut self,
desc: &RenderPassDescriptor<dyn DynQuerySet, dyn DynTextureView>,
) -> Result<(), DeviceError>;
unsafe fn end_render_pass(&mut self);
unsafe fn set_render_pipeline(&mut self, pipeline: &dyn DynRenderPipeline);
unsafe fn set_index_buffer<'a>(
&mut self,
binding: BufferBinding<'a, dyn DynBuffer>,
format: wgt::IndexFormat,
);
unsafe fn set_vertex_buffer<'a>(
&mut self,
index: u32,
binding: BufferBinding<'a, dyn DynBuffer>,
);
unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
unsafe fn set_stencil_reference(&mut self, value: u32);
unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
unsafe fn draw(
&mut self,
first_vertex: u32,
vertex_count: u32,
first_instance: u32,
instance_count: u32,
);
unsafe fn draw_indexed(
&mut self,
first_index: u32,
index_count: u32,
base_vertex: i32,
first_instance: u32,
instance_count: u32,
);
unsafe fn draw_mesh_tasks(
&mut self,
group_count_x: u32,
group_count_y: u32,
group_count_z: u32,
);
unsafe fn draw_indirect(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
draw_count: u32,
);
unsafe fn draw_indexed_indirect(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
draw_count: u32,
);
unsafe fn draw_mesh_tasks_indirect(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
draw_count: u32,
);
unsafe fn draw_indirect_count(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
count_buffer: &dyn DynBuffer,
count_offset: wgt::BufferAddress,
max_count: u32,
);
unsafe fn draw_indexed_indirect_count(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
count_buffer: &dyn DynBuffer,
count_offset: wgt::BufferAddress,
max_count: u32,
);
unsafe fn draw_mesh_tasks_indirect_count(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
count_buffer: &dyn DynBuffer,
count_offset: wgt::BufferAddress,
max_count: u32,
);
unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<dyn DynQuerySet>);
unsafe fn end_compute_pass(&mut self);
unsafe fn set_compute_pipeline(&mut self, pipeline: &dyn DynComputePipeline);
unsafe fn dispatch(&mut self, count: [u32; 3]);
unsafe fn dispatch_indirect(&mut self, buffer: &dyn DynBuffer, offset: wgt::BufferAddress);
unsafe fn build_acceleration_structures<'a>(
&mut self,
descriptors: &'a [BuildAccelerationStructureDescriptor<
'a,
dyn DynBuffer,
dyn DynAccelerationStructure,
>],
);
unsafe fn place_acceleration_structure_barrier(
&mut self,
barrier: AccelerationStructureBarrier,
);
unsafe fn copy_acceleration_structure_to_acceleration_structure(
&mut self,
src: &dyn DynAccelerationStructure,
dst: &dyn DynAccelerationStructure,
copy: wgt::AccelerationStructureCopy,
);
unsafe fn read_acceleration_structure_compact_size(
&mut self,
acceleration_structure: &dyn DynAccelerationStructure,
buf: &dyn DynBuffer,
);
unsafe fn set_acceleration_structure_dependencies(
&self,
command_buffers: &[Box<dyn DynCommandBuffer>],
dependencies: &[&dyn DynAccelerationStructure],
);
}
impl<C: CommandEncoder + DynResource> DynCommandEncoder for C {
unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError> {
unsafe { C::begin_encoding(self, label) }
}
unsafe fn discard_encoding(&mut self) {
unsafe { C::discard_encoding(self) }
}
unsafe fn end_encoding(&mut self) -> Result<Box<dyn DynCommandBuffer>, DeviceError> {
unsafe { C::end_encoding(self) }.map(|cb| {
let boxed_command_buffer: Box<<C::A as Api>::CommandBuffer> = Box::new(cb);
let boxed_command_buffer: Box<dyn DynCommandBuffer> = boxed_command_buffer;
boxed_command_buffer
})
}
unsafe fn reset_all(&mut self, command_buffers: Vec<Box<dyn DynCommandBuffer>>) {
unsafe { C::reset_all(self, command_buffers.into_iter().map(|cb| cb.unbox())) }
}
unsafe fn transition_buffers(&mut self, barriers: &[BufferBarrier<'_, dyn DynBuffer>]) {
let barriers = barriers.iter().map(|barrier| BufferBarrier {
buffer: barrier.buffer.expect_downcast_ref(),
usage: barrier.usage.clone(),
});
unsafe { self.transition_buffers(barriers) };
}
unsafe fn transition_textures(&mut self, barriers: &[TextureBarrier<'_, dyn DynTexture>]) {
let barriers = barriers.iter().map(|barrier| TextureBarrier {
texture: barrier.texture.expect_downcast_ref(),
usage: barrier.usage.clone(),
range: barrier.range,
});
unsafe { self.transition_textures(barriers) };
}
unsafe fn clear_buffer(&mut self, buffer: &dyn DynBuffer, range: MemoryRange) {
let buffer = buffer.expect_downcast_ref();
unsafe { C::clear_buffer(self, buffer, range) };
}
unsafe fn copy_buffer_to_buffer(
&mut self,
src: &dyn DynBuffer,
dst: &dyn DynBuffer,
regions: &[BufferCopy],
) {
let src = src.expect_downcast_ref();
let dst = dst.expect_downcast_ref();
unsafe {
C::copy_buffer_to_buffer(self, src, dst, regions.iter().copied());
}
}
unsafe fn copy_texture_to_texture(
&mut self,
src: &dyn DynTexture,
src_usage: wgt::TextureUses,
dst: &dyn DynTexture,
regions: &[TextureCopy],
) {
let src = src.expect_downcast_ref();
let dst = dst.expect_downcast_ref();
unsafe {
C::copy_texture_to_texture(self, src, src_usage, dst, regions.iter().cloned());
}
}
unsafe fn copy_buffer_to_texture(
&mut self,
src: &dyn DynBuffer,
dst: &dyn DynTexture,
regions: &[BufferTextureCopy],
) {
let src = src.expect_downcast_ref();
let dst = dst.expect_downcast_ref();
unsafe {
C::copy_buffer_to_texture(self, src, dst, regions.iter().cloned());
}
}
unsafe fn copy_texture_to_buffer(
&mut self,
src: &dyn DynTexture,
src_usage: wgt::TextureUses,
dst: &dyn DynBuffer,
regions: &[BufferTextureCopy],
) {
let src = src.expect_downcast_ref();
let dst = dst.expect_downcast_ref();
unsafe {
C::copy_texture_to_buffer(self, src, src_usage, dst, regions.iter().cloned());
}
}
unsafe fn set_bind_group(
&mut self,
layout: &dyn DynPipelineLayout,
index: u32,
group: &dyn DynBindGroup,
dynamic_offsets: &[wgt::DynamicOffset],
) {
let layout = layout.expect_downcast_ref();
let group = group.expect_downcast_ref();
unsafe { C::set_bind_group(self, layout, index, group, dynamic_offsets) };
}
unsafe fn set_immediates(
&mut self,
layout: &dyn DynPipelineLayout,
offset_bytes: u32,
data: &[u32],
) {
let layout = layout.expect_downcast_ref();
unsafe { C::set_immediates(self, layout, offset_bytes, data) };
}
unsafe fn insert_debug_marker(&mut self, label: &str) {
unsafe {
C::insert_debug_marker(self, label);
}
}
unsafe fn begin_debug_marker(&mut self, group_label: &str) {
unsafe {
C::begin_debug_marker(self, group_label);
}
}
unsafe fn end_debug_marker(&mut self) {
unsafe {
C::end_debug_marker(self);
}
}
unsafe fn begin_query(&mut self, set: &dyn DynQuerySet, index: u32) {
let set = set.expect_downcast_ref();
unsafe { C::begin_query(self, set, index) };
}
unsafe fn end_query(&mut self, set: &dyn DynQuerySet, index: u32) {
let set = set.expect_downcast_ref();
unsafe { C::end_query(self, set, index) };
}
unsafe fn write_timestamp(&mut self, set: &dyn DynQuerySet, index: u32) {
let set = set.expect_downcast_ref();
unsafe { C::write_timestamp(self, set, index) };
}
unsafe fn reset_queries(&mut self, set: &dyn DynQuerySet, range: Range<u32>) {
let set = set.expect_downcast_ref();
unsafe { C::reset_queries(self, set, range) };
}
unsafe fn copy_query_results(
&mut self,
set: &dyn DynQuerySet,
range: Range<u32>,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
stride: wgt::BufferSize,
) {
let set = set.expect_downcast_ref();
let buffer = buffer.expect_downcast_ref();
unsafe { C::copy_query_results(self, set, range, buffer, offset, stride) };
}
unsafe fn begin_render_pass(
&mut self,
desc: &RenderPassDescriptor<dyn DynQuerySet, dyn DynTextureView>,
) -> Result<(), DeviceError> {
let color_attachments = desc
.color_attachments
.iter()
.map(|attachment| {
attachment
.as_ref()
.map(|attachment| attachment.expect_downcast())
})
.collect::<Vec<_>>();
let desc: RenderPassDescriptor<<C::A as Api>::QuerySet, <C::A as Api>::TextureView> =
RenderPassDescriptor {
label: desc.label,
extent: desc.extent,
sample_count: desc.sample_count,
color_attachments: &color_attachments,
depth_stencil_attachment: desc
.depth_stencil_attachment
.as_ref()
.map(|ds| ds.expect_downcast()),
multiview_mask: desc.multiview_mask,
timestamp_writes: desc
.timestamp_writes
.as_ref()
.map(|writes| writes.expect_downcast()),
occlusion_query_set: desc
.occlusion_query_set
.map(|set| set.expect_downcast_ref()),
};
unsafe { C::begin_render_pass(self, &desc) }
}
unsafe fn end_render_pass(&mut self) {
unsafe {
C::end_render_pass(self);
}
}
unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>) {
unsafe {
C::set_viewport(self, rect, depth_range);
}
}
unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>) {
unsafe {
C::set_scissor_rect(self, rect);
}
}
unsafe fn set_stencil_reference(&mut self, value: u32) {
unsafe {
C::set_stencil_reference(self, value);
}
}
unsafe fn set_blend_constants(&mut self, color: &[f32; 4]) {
unsafe { C::set_blend_constants(self, color) };
}
unsafe fn draw(
&mut self,
first_vertex: u32,
vertex_count: u32,
first_instance: u32,
instance_count: u32,
) {
unsafe {
C::draw(
self,
first_vertex,
vertex_count,
first_instance,
instance_count,
)
};
}
unsafe fn draw_indexed(
&mut self,
first_index: u32,
index_count: u32,
base_vertex: i32,
first_instance: u32,
instance_count: u32,
) {
unsafe {
C::draw_indexed(
self,
first_index,
index_count,
base_vertex,
first_instance,
instance_count,
)
};
}
unsafe fn draw_mesh_tasks(
&mut self,
group_count_x: u32,
group_count_y: u32,
group_count_z: u32,
) {
unsafe { C::draw_mesh_tasks(self, group_count_x, group_count_y, group_count_z) };
}
unsafe fn draw_indirect(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
draw_count: u32,
) {
let buffer = buffer.expect_downcast_ref();
unsafe { C::draw_indirect(self, buffer, offset, draw_count) };
}
unsafe fn draw_indexed_indirect(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
draw_count: u32,
) {
let buffer = buffer.expect_downcast_ref();
unsafe { C::draw_indexed_indirect(self, buffer, offset, draw_count) };
}
unsafe fn draw_mesh_tasks_indirect(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
draw_count: u32,
) {
let buffer = buffer.expect_downcast_ref();
unsafe { C::draw_mesh_tasks_indirect(self, buffer, offset, draw_count) };
}
unsafe fn draw_indirect_count(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
count_buffer: &dyn DynBuffer,
count_offset: wgt::BufferAddress,
max_count: u32,
) {
let buffer = buffer.expect_downcast_ref();
let count_buffer = count_buffer.expect_downcast_ref();
unsafe {
C::draw_indirect_count(self, buffer, offset, count_buffer, count_offset, max_count)
};
}
unsafe fn draw_indexed_indirect_count(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
count_buffer: &dyn DynBuffer,
count_offset: wgt::BufferAddress,
max_count: u32,
) {
let buffer = buffer.expect_downcast_ref();
let count_buffer = count_buffer.expect_downcast_ref();
unsafe {
C::draw_indexed_indirect_count(
self,
buffer,
offset,
count_buffer,
count_offset,
max_count,
)
};
}
unsafe fn draw_mesh_tasks_indirect_count(
&mut self,
buffer: &dyn DynBuffer,
offset: wgt::BufferAddress,
count_buffer: &dyn DynBuffer,
count_offset: wgt::BufferAddress,
max_count: u32,
) {
let buffer = buffer.expect_downcast_ref();
let count_buffer = count_buffer.expect_downcast_ref();
unsafe {
C::draw_mesh_tasks_indirect_count(
self,
buffer,
offset,
count_buffer,
count_offset,
max_count,
)
};
}
unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<dyn DynQuerySet>) {
let desc = ComputePassDescriptor {
label: desc.label,
timestamp_writes: desc
.timestamp_writes
.as_ref()
.map(|writes| writes.expect_downcast()),
};
unsafe { C::begin_compute_pass(self, &desc) };
}
unsafe fn end_compute_pass(&mut self) {
unsafe { C::end_compute_pass(self) };
}
unsafe fn set_compute_pipeline(&mut self, pipeline: &dyn DynComputePipeline) {
let pipeline = pipeline.expect_downcast_ref();
unsafe { C::set_compute_pipeline(self, pipeline) };
}
unsafe fn dispatch(&mut self, count: [u32; 3]) {
unsafe { C::dispatch(self, count) };
}
unsafe fn dispatch_indirect(&mut self, buffer: &dyn DynBuffer, offset: wgt::BufferAddress) {
let buffer = buffer.expect_downcast_ref();
unsafe { C::dispatch_indirect(self, buffer, offset) };
}
unsafe fn set_render_pipeline(&mut self, pipeline: &dyn DynRenderPipeline) {
let pipeline = pipeline.expect_downcast_ref();
unsafe { C::set_render_pipeline(self, pipeline) };
}
unsafe fn set_index_buffer<'a>(
&mut self,
binding: BufferBinding<'a, dyn DynBuffer>,
format: wgt::IndexFormat,
) {
let binding = binding.expect_downcast();
unsafe { self.set_index_buffer(binding, format) };
}
unsafe fn set_vertex_buffer<'a>(
&mut self,
index: u32,
binding: BufferBinding<'a, dyn DynBuffer>,
) {
let binding = binding.expect_downcast();
unsafe { self.set_vertex_buffer(index, binding) };
}
unsafe fn build_acceleration_structures<'a>(
&mut self,
descriptors: &'a [BuildAccelerationStructureDescriptor<
'a,
dyn DynBuffer,
dyn DynAccelerationStructure,
>],
) {
// Need to collect entries here so we can reference them in the descriptor.
// TODO: API should be redesigned to avoid this and other descriptor copies that happen due to the dyn api.
let descriptor_entries = descriptors
.iter()
.map(|d| d.entries.expect_downcast())
.collect::<Vec<_>>();
let descriptors = descriptors
.iter()
.zip(descriptor_entries.iter())
.map(|(d, entries)| BuildAccelerationStructureDescriptor::<
<C::A as Api>::Buffer,
<C::A as Api>::AccelerationStructure,
> {
entries,
mode: d.mode,
flags: d.flags,
source_acceleration_structure: d
.source_acceleration_structure
.map(|a| a.expect_downcast_ref()),
destination_acceleration_structure: d
.destination_acceleration_structure
.expect_downcast_ref(),
scratch_buffer: d.scratch_buffer.expect_downcast_ref(),
scratch_buffer_offset: d.scratch_buffer_offset,
});
unsafe { C::build_acceleration_structures(self, descriptors.len() as _, descriptors) };
}
unsafe fn place_acceleration_structure_barrier(
&mut self,
barrier: AccelerationStructureBarrier,
) {
unsafe { C::place_acceleration_structure_barrier(self, barrier) };
}
unsafe fn copy_acceleration_structure_to_acceleration_structure(
&mut self,
src: &dyn DynAccelerationStructure,
dst: &dyn DynAccelerationStructure,
copy: wgt::AccelerationStructureCopy,
) {
let src = src.expect_downcast_ref();
let dst = dst.expect_downcast_ref();
unsafe { C::copy_acceleration_structure_to_acceleration_structure(self, src, dst, copy) };
}
unsafe fn read_acceleration_structure_compact_size(
&mut self,
acceleration_structure: &dyn DynAccelerationStructure,
buf: &dyn DynBuffer,
) {
let acceleration_structure = acceleration_structure.expect_downcast_ref();
let buf = buf.expect_downcast_ref();
unsafe { C::read_acceleration_structure_compact_size(self, acceleration_structure, buf) }
}
unsafe fn set_acceleration_structure_dependencies(
&self,
command_buffers: &[Box<dyn DynCommandBuffer>],
dependencies: &[&dyn DynAccelerationStructure],
) {
let command_buffers: Vec<&<C::A as Api>::CommandBuffer> = command_buffers
.iter()
.map(|command_buffer| command_buffer.expect_downcast_ref())
.collect();
let dependencies: Vec<&<C::A as Api>::AccelerationStructure> = dependencies
.iter()
.map(|dependency| dependency.expect_downcast_ref())
.collect();
unsafe { C::set_acceleration_structure_dependencies(&command_buffers, &dependencies) }
}
}
impl<'a> PassTimestampWrites<'a, dyn DynQuerySet> {
pub fn expect_downcast<B: DynQuerySet>(&self) -> PassTimestampWrites<'a, B> {
PassTimestampWrites {
query_set: self.query_set.expect_downcast_ref(),
beginning_of_pass_write_index: self.beginning_of_pass_write_index,
end_of_pass_write_index: self.end_of_pass_write_index,
}
}
}
impl<'a> Attachment<'a, dyn DynTextureView> {
pub fn expect_downcast<B: DynTextureView>(&self) -> Attachment<'a, B> {
Attachment {
view: self.view.expect_downcast_ref(),
usage: self.usage,
}
}
}
impl<'a> ColorAttachment<'a, dyn DynTextureView> {
pub fn expect_downcast<B: DynTextureView>(&self) -> ColorAttachment<'a, B> {
ColorAttachment {
target: self.target.expect_downcast(),
depth_slice: self.depth_slice,
resolve_target: self.resolve_target.as_ref().map(|rt| rt.expect_downcast()),
ops: self.ops,
clear_value: self.clear_value,
}
}
}
impl<'a> DepthStencilAttachment<'a, dyn DynTextureView> {
pub fn expect_downcast<B: DynTextureView>(&self) -> DepthStencilAttachment<'a, B> {
DepthStencilAttachment {
target: self.target.expect_downcast(),
depth_ops: self.depth_ops,
stencil_ops: self.stencil_ops,
clear_value: self.clear_value,
}
}
}
+558
View File
@@ -0,0 +1,558 @@
use alloc::{borrow::ToOwned as _, boxed::Box, vec::Vec};
use crate::{
AccelerationStructureBuildSizes, AccelerationStructureDescriptor, Api, BindGroupDescriptor,
BindGroupLayoutDescriptor, BufferDescriptor, BufferMapping, CommandEncoderDescriptor,
ComputePipelineDescriptor, Device, DeviceError, FenceValue,
GetAccelerationStructureBuildSizesDescriptor, Label, MemoryRange, PipelineCacheDescriptor,
PipelineCacheError, PipelineError, PipelineLayoutDescriptor, RenderPipelineDescriptor,
SamplerDescriptor, ShaderError, ShaderInput, ShaderModuleDescriptor, TextureDescriptor,
TextureViewDescriptor, TlasInstance,
};
use super::{
DynAccelerationStructure, DynBindGroup, DynBindGroupLayout, DynBuffer, DynCommandEncoder,
DynComputePipeline, DynFence, DynPipelineCache, DynPipelineLayout, DynQuerySet, DynQueue,
DynRenderPipeline, DynResource, DynResourceExt as _, DynSampler, DynShaderModule, DynTexture,
DynTextureView,
};
pub trait DynDevice: DynResource {
unsafe fn create_buffer(
&self,
desc: &BufferDescriptor,
) -> Result<Box<dyn DynBuffer>, DeviceError>;
unsafe fn destroy_buffer(&self, buffer: Box<dyn DynBuffer>);
unsafe fn add_raw_buffer(&self, buffer: &dyn DynBuffer);
unsafe fn map_buffer(
&self,
buffer: &dyn DynBuffer,
range: MemoryRange,
) -> Result<BufferMapping, DeviceError>;
unsafe fn unmap_buffer(&self, buffer: &dyn DynBuffer);
unsafe fn flush_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]);
unsafe fn invalidate_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]);
unsafe fn create_texture(
&self,
desc: &TextureDescriptor,
) -> Result<Box<dyn DynTexture>, DeviceError>;
unsafe fn destroy_texture(&self, texture: Box<dyn DynTexture>);
unsafe fn add_raw_texture(&self, texture: &dyn DynTexture);
unsafe fn create_texture_view(
&self,
texture: &dyn DynTexture,
desc: &TextureViewDescriptor,
) -> Result<Box<dyn DynTextureView>, DeviceError>;
unsafe fn destroy_texture_view(&self, view: Box<dyn DynTextureView>);
unsafe fn create_sampler(
&self,
desc: &SamplerDescriptor,
) -> Result<Box<dyn DynSampler>, DeviceError>;
unsafe fn destroy_sampler(&self, sampler: Box<dyn DynSampler>);
unsafe fn create_command_encoder(
&self,
desc: &CommandEncoderDescriptor<dyn DynQueue>,
) -> Result<Box<dyn DynCommandEncoder>, DeviceError>;
unsafe fn create_bind_group_layout(
&self,
desc: &BindGroupLayoutDescriptor,
) -> Result<Box<dyn DynBindGroupLayout>, DeviceError>;
unsafe fn destroy_bind_group_layout(&self, bg_layout: Box<dyn DynBindGroupLayout>);
unsafe fn create_pipeline_layout(
&self,
desc: &PipelineLayoutDescriptor<dyn DynBindGroupLayout>,
) -> Result<Box<dyn DynPipelineLayout>, DeviceError>;
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Box<dyn DynPipelineLayout>);
unsafe fn create_bind_group(
&self,
desc: &BindGroupDescriptor<
dyn DynBindGroupLayout,
dyn DynBuffer,
dyn DynSampler,
dyn DynTextureView,
dyn DynAccelerationStructure,
>,
) -> Result<Box<dyn DynBindGroup>, DeviceError>;
unsafe fn destroy_bind_group(&self, group: Box<dyn DynBindGroup>);
unsafe fn create_shader_module(
&self,
desc: &ShaderModuleDescriptor,
shader: ShaderInput,
) -> Result<Box<dyn DynShaderModule>, ShaderError>;
unsafe fn destroy_shader_module(&self, module: Box<dyn DynShaderModule>);
unsafe fn create_render_pipeline(
&self,
desc: &RenderPipelineDescriptor<
dyn DynPipelineLayout,
dyn DynShaderModule,
dyn DynPipelineCache,
>,
) -> Result<Box<dyn DynRenderPipeline>, PipelineError>;
unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>);
unsafe fn create_compute_pipeline(
&self,
desc: &ComputePipelineDescriptor<
dyn DynPipelineLayout,
dyn DynShaderModule,
dyn DynPipelineCache,
>,
) -> Result<Box<dyn DynComputePipeline>, PipelineError>;
unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>);
unsafe fn create_pipeline_cache(
&self,
desc: &PipelineCacheDescriptor<'_>,
) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError>;
fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
None
}
unsafe fn destroy_pipeline_cache(&self, cache: Box<dyn DynPipelineCache>);
unsafe fn create_query_set(
&self,
desc: &wgt::QuerySetDescriptor<Label>,
) -> Result<Box<dyn DynQuerySet>, DeviceError>;
unsafe fn destroy_query_set(&self, set: Box<dyn DynQuerySet>);
unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError>;
unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>);
unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError>;
unsafe fn wait(
&self,
fence: &dyn DynFence,
value: FenceValue,
timeout: Option<core::time::Duration>,
) -> Result<bool, DeviceError>;
unsafe fn start_graphics_debugger_capture(&self) -> bool;
unsafe fn stop_graphics_debugger_capture(&self);
unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>>;
unsafe fn create_acceleration_structure(
&self,
desc: &AccelerationStructureDescriptor,
) -> Result<Box<dyn DynAccelerationStructure>, DeviceError>;
unsafe fn get_acceleration_structure_build_sizes(
&self,
desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
) -> AccelerationStructureBuildSizes;
unsafe fn get_acceleration_structure_device_address(
&self,
acceleration_structure: &dyn DynAccelerationStructure,
) -> wgt::BufferAddress;
unsafe fn destroy_acceleration_structure(
&self,
acceleration_structure: Box<dyn DynAccelerationStructure>,
);
fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8>;
fn get_internal_counters(&self) -> wgt::HalCounters;
fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport>;
fn check_if_oom(&self) -> Result<(), DeviceError>;
}
impl<D: Device + DynResource> DynDevice for D {
unsafe fn create_buffer(
&self,
desc: &BufferDescriptor,
) -> Result<Box<dyn DynBuffer>, DeviceError> {
unsafe { D::create_buffer(self, desc) }.map(|b| -> Box<dyn DynBuffer> { Box::new(b) })
}
unsafe fn destroy_buffer(&self, buffer: Box<dyn DynBuffer>) {
unsafe { D::destroy_buffer(self, buffer.unbox()) };
}
unsafe fn add_raw_buffer(&self, buffer: &dyn DynBuffer) {
let buffer = buffer.expect_downcast_ref();
unsafe { D::add_raw_buffer(self, buffer) };
}
unsafe fn map_buffer(
&self,
buffer: &dyn DynBuffer,
range: MemoryRange,
) -> Result<BufferMapping, DeviceError> {
let buffer = buffer.expect_downcast_ref();
unsafe { D::map_buffer(self, buffer, range) }
}
unsafe fn unmap_buffer(&self, buffer: &dyn DynBuffer) {
let buffer = buffer.expect_downcast_ref();
unsafe { D::unmap_buffer(self, buffer) }
}
unsafe fn flush_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
let buffer = buffer.expect_downcast_ref();
unsafe { D::flush_mapped_ranges(self, buffer, ranges.iter().cloned()) }
}
unsafe fn invalidate_mapped_ranges(&self, buffer: &dyn DynBuffer, ranges: &[MemoryRange]) {
let buffer = buffer.expect_downcast_ref();
unsafe { D::invalidate_mapped_ranges(self, buffer, ranges.iter().cloned()) }
}
unsafe fn create_texture(
&self,
desc: &TextureDescriptor,
) -> Result<Box<dyn DynTexture>, DeviceError> {
unsafe { D::create_texture(self, desc) }.map(|b| {
let boxed_texture: Box<<D::A as Api>::Texture> = Box::new(b);
let boxed_texture: Box<dyn DynTexture> = boxed_texture;
boxed_texture
})
}
unsafe fn destroy_texture(&self, texture: Box<dyn DynTexture>) {
unsafe { D::destroy_texture(self, texture.unbox()) };
}
unsafe fn add_raw_texture(&self, texture: &dyn DynTexture) {
let texture = texture.expect_downcast_ref();
unsafe { D::add_raw_texture(self, texture) };
}
unsafe fn create_texture_view(
&self,
texture: &dyn DynTexture,
desc: &TextureViewDescriptor,
) -> Result<Box<dyn DynTextureView>, DeviceError> {
let texture = texture.expect_downcast_ref();
unsafe { D::create_texture_view(self, texture, desc) }.map(|b| {
let boxed_texture_view: Box<<D::A as Api>::TextureView> = Box::new(b);
let boxed_texture_view: Box<dyn DynTextureView> = boxed_texture_view;
boxed_texture_view
})
}
unsafe fn destroy_texture_view(&self, view: Box<dyn DynTextureView>) {
unsafe { D::destroy_texture_view(self, view.unbox()) };
}
unsafe fn create_sampler(
&self,
desc: &SamplerDescriptor,
) -> Result<Box<dyn DynSampler>, DeviceError> {
unsafe { D::create_sampler(self, desc) }.map(|b| {
let boxed_sampler: Box<<D::A as Api>::Sampler> = Box::new(b);
let boxed_sampler: Box<dyn DynSampler> = boxed_sampler;
boxed_sampler
})
}
unsafe fn destroy_sampler(&self, sampler: Box<dyn DynSampler>) {
unsafe { D::destroy_sampler(self, sampler.unbox()) };
}
unsafe fn create_command_encoder(
&self,
desc: &CommandEncoderDescriptor<'_, dyn DynQueue>,
) -> Result<Box<dyn DynCommandEncoder>, DeviceError> {
let desc = CommandEncoderDescriptor {
label: desc.label,
queue: desc.queue.expect_downcast_ref(),
};
unsafe { D::create_command_encoder(self, &desc) }
.map(|b| -> Box<dyn DynCommandEncoder> { Box::new(b) })
}
unsafe fn create_bind_group_layout(
&self,
desc: &BindGroupLayoutDescriptor,
) -> Result<Box<dyn DynBindGroupLayout>, DeviceError> {
unsafe { D::create_bind_group_layout(self, desc) }
.map(|b| -> Box<dyn DynBindGroupLayout> { Box::new(b) })
}
unsafe fn destroy_bind_group_layout(&self, bg_layout: Box<dyn DynBindGroupLayout>) {
unsafe { D::destroy_bind_group_layout(self, bg_layout.unbox()) };
}
unsafe fn create_pipeline_layout(
&self,
desc: &PipelineLayoutDescriptor<dyn DynBindGroupLayout>,
) -> Result<Box<dyn DynPipelineLayout>, DeviceError> {
let bind_group_layouts: Vec<_> = desc
.bind_group_layouts
.iter()
.map(|bgl| bgl.map(|bgl| bgl.expect_downcast_ref()))
.collect();
let desc = PipelineLayoutDescriptor {
label: desc.label,
bind_group_layouts: &bind_group_layouts,
immediate_size: desc.immediate_size,
flags: desc.flags,
};
unsafe { D::create_pipeline_layout(self, &desc) }
.map(|b| -> Box<dyn DynPipelineLayout> { Box::new(b) })
}
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Box<dyn DynPipelineLayout>) {
unsafe { D::destroy_pipeline_layout(self, pipeline_layout.unbox()) };
}
unsafe fn create_bind_group(
&self,
desc: &BindGroupDescriptor<
dyn DynBindGroupLayout,
dyn DynBuffer,
dyn DynSampler,
dyn DynTextureView,
dyn DynAccelerationStructure,
>,
) -> Result<Box<dyn DynBindGroup>, DeviceError> {
let buffers: Vec<_> = desc
.buffers
.iter()
.map(|b| b.clone().expect_downcast())
.collect();
let samplers: Vec<_> = desc
.samplers
.iter()
.map(|s| s.expect_downcast_ref())
.collect();
let textures: Vec<_> = desc
.textures
.iter()
.map(|t| t.clone().expect_downcast())
.collect();
let acceleration_structures: Vec<_> = desc
.acceleration_structures
.iter()
.map(|a| a.expect_downcast_ref())
.collect();
let external_textures: Vec<_> = desc
.external_textures
.iter()
.map(|et| et.clone().expect_downcast())
.collect();
let desc = BindGroupDescriptor {
label: desc.label.to_owned(),
layout: desc.layout.expect_downcast_ref(),
buffers: &buffers,
samplers: &samplers,
textures: &textures,
entries: desc.entries,
acceleration_structures: &acceleration_structures,
external_textures: &external_textures,
};
unsafe { D::create_bind_group(self, &desc) }
.map(|b| -> Box<dyn DynBindGroup> { Box::new(b) })
}
unsafe fn destroy_bind_group(&self, group: Box<dyn DynBindGroup>) {
unsafe { D::destroy_bind_group(self, group.unbox()) };
}
unsafe fn create_shader_module(
&self,
desc: &ShaderModuleDescriptor,
shader: ShaderInput,
) -> Result<Box<dyn DynShaderModule>, ShaderError> {
unsafe { D::create_shader_module(self, desc, shader) }
.map(|b| -> Box<dyn DynShaderModule> { Box::new(b) })
}
unsafe fn destroy_shader_module(&self, module: Box<dyn DynShaderModule>) {
unsafe { D::destroy_shader_module(self, module.unbox()) };
}
unsafe fn create_render_pipeline(
&self,
desc: &RenderPipelineDescriptor<
dyn DynPipelineLayout,
dyn DynShaderModule,
dyn DynPipelineCache,
>,
) -> Result<Box<dyn DynRenderPipeline>, PipelineError> {
let desc = RenderPipelineDescriptor {
label: desc.label,
layout: desc.layout.expect_downcast_ref(),
vertex_processor: match &desc.vertex_processor {
crate::VertexProcessor::Standard {
vertex_buffers,
vertex_stage,
} => crate::VertexProcessor::Standard {
vertex_buffers,
vertex_stage: vertex_stage.clone().expect_downcast(),
},
crate::VertexProcessor::Mesh {
task_stage: task,
mesh_stage: mesh,
} => crate::VertexProcessor::Mesh {
task_stage: task.as_ref().map(|a| a.clone().expect_downcast()),
mesh_stage: mesh.clone().expect_downcast(),
},
},
primitive: desc.primitive,
depth_stencil: desc.depth_stencil.clone(),
multisample: desc.multisample,
fragment_stage: desc.fragment_stage.clone().map(|f| f.expect_downcast()),
color_targets: desc.color_targets,
multiview_mask: desc.multiview_mask,
cache: desc.cache.map(|c| c.expect_downcast_ref()),
};
unsafe { D::create_render_pipeline(self, &desc) }
.map(|b| -> Box<dyn DynRenderPipeline> { Box::new(b) })
}
unsafe fn destroy_render_pipeline(&self, pipeline: Box<dyn DynRenderPipeline>) {
unsafe { D::destroy_render_pipeline(self, pipeline.unbox()) };
}
unsafe fn create_compute_pipeline(
&self,
desc: &ComputePipelineDescriptor<
dyn DynPipelineLayout,
dyn DynShaderModule,
dyn DynPipelineCache,
>,
) -> Result<Box<dyn DynComputePipeline>, PipelineError> {
let desc = ComputePipelineDescriptor {
label: desc.label,
layout: desc.layout.expect_downcast_ref(),
stage: desc.stage.clone().expect_downcast(),
cache: desc.cache.as_ref().map(|c| c.expect_downcast_ref()),
};
unsafe { D::create_compute_pipeline(self, &desc) }
.map(|b| -> Box<dyn DynComputePipeline> { Box::new(b) })
}
unsafe fn destroy_compute_pipeline(&self, pipeline: Box<dyn DynComputePipeline>) {
unsafe { D::destroy_compute_pipeline(self, pipeline.unbox()) };
}
unsafe fn create_pipeline_cache(
&self,
desc: &PipelineCacheDescriptor<'_>,
) -> Result<Box<dyn DynPipelineCache>, PipelineCacheError> {
unsafe { D::create_pipeline_cache(self, desc) }
.map(|b| -> Box<dyn DynPipelineCache> { Box::new(b) })
}
fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
D::pipeline_cache_validation_key(self)
}
unsafe fn destroy_pipeline_cache(&self, pipeline_cache: Box<dyn DynPipelineCache>) {
unsafe { D::destroy_pipeline_cache(self, pipeline_cache.unbox()) };
}
unsafe fn create_query_set(
&self,
desc: &wgt::QuerySetDescriptor<Label>,
) -> Result<Box<dyn DynQuerySet>, DeviceError> {
unsafe { D::create_query_set(self, desc) }.map(|b| -> Box<dyn DynQuerySet> { Box::new(b) })
}
unsafe fn destroy_query_set(&self, query_set: Box<dyn DynQuerySet>) {
unsafe { D::destroy_query_set(self, query_set.unbox()) };
}
unsafe fn create_fence(&self) -> Result<Box<dyn DynFence>, DeviceError> {
unsafe { D::create_fence(self) }.map(|b| -> Box<dyn DynFence> { Box::new(b) })
}
unsafe fn destroy_fence(&self, fence: Box<dyn DynFence>) {
unsafe { D::destroy_fence(self, fence.unbox()) };
}
unsafe fn get_fence_value(&self, fence: &dyn DynFence) -> Result<FenceValue, DeviceError> {
let fence = fence.expect_downcast_ref();
unsafe { D::get_fence_value(self, fence) }
}
unsafe fn wait(
&self,
fence: &dyn DynFence,
value: FenceValue,
timeout: Option<core::time::Duration>,
) -> Result<bool, DeviceError> {
let fence = fence.expect_downcast_ref();
unsafe { D::wait(self, fence, value, timeout) }
}
unsafe fn start_graphics_debugger_capture(&self) -> bool {
unsafe { D::start_graphics_debugger_capture(self) }
}
unsafe fn stop_graphics_debugger_capture(&self) {
unsafe { D::stop_graphics_debugger_capture(self) }
}
unsafe fn pipeline_cache_get_data(&self, cache: &dyn DynPipelineCache) -> Option<Vec<u8>> {
let cache = cache.expect_downcast_ref();
unsafe { D::pipeline_cache_get_data(self, cache) }
}
unsafe fn create_acceleration_structure(
&self,
desc: &AccelerationStructureDescriptor,
) -> Result<Box<dyn DynAccelerationStructure>, DeviceError> {
unsafe { D::create_acceleration_structure(self, desc) }
.map(|b| -> Box<dyn DynAccelerationStructure> { Box::new(b) })
}
unsafe fn get_acceleration_structure_build_sizes(
&self,
desc: &GetAccelerationStructureBuildSizesDescriptor<dyn DynBuffer>,
) -> AccelerationStructureBuildSizes {
let entries = desc.entries.expect_downcast();
let desc = GetAccelerationStructureBuildSizesDescriptor {
entries: &entries,
flags: desc.flags,
};
unsafe { D::get_acceleration_structure_build_sizes(self, &desc) }
}
unsafe fn get_acceleration_structure_device_address(
&self,
acceleration_structure: &dyn DynAccelerationStructure,
) -> wgt::BufferAddress {
let acceleration_structure = acceleration_structure.expect_downcast_ref();
unsafe { D::get_acceleration_structure_device_address(self, acceleration_structure) }
}
unsafe fn destroy_acceleration_structure(
&self,
acceleration_structure: Box<dyn DynAccelerationStructure>,
) {
unsafe { D::destroy_acceleration_structure(self, acceleration_structure.unbox()) }
}
fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {
D::tlas_instance_to_bytes(self, instance)
}
fn get_internal_counters(&self) -> wgt::HalCounters {
D::get_internal_counters(self)
}
fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
D::generate_allocator_report(self)
}
fn check_if_oom(&self) -> Result<(), DeviceError> {
D::check_if_oom(self)
}
}
+70
View File
@@ -0,0 +1,70 @@
use alloc::{boxed::Box, vec::Vec};
use crate::{Api, Capabilities, ExposedAdapter, Instance, InstanceError};
use super::{DynAdapter, DynResource, DynResourceExt as _, DynSurface};
pub struct DynExposedAdapter {
pub adapter: Box<dyn DynAdapter>,
pub info: wgt::AdapterInfo,
pub features: wgt::Features,
pub capabilities: Capabilities,
}
impl DynExposedAdapter {
/// Returns the backend this adapter is using.
pub fn backend(&self) -> wgt::Backend {
self.info.backend
}
}
impl<A: Api> From<ExposedAdapter<A>> for DynExposedAdapter {
fn from(exposed_adapter: ExposedAdapter<A>) -> Self {
Self {
adapter: Box::new(exposed_adapter.adapter),
info: exposed_adapter.info,
features: exposed_adapter.features,
capabilities: exposed_adapter.capabilities,
}
}
}
pub trait DynInstance: DynResource {
unsafe fn create_surface(
&self,
display_handle: raw_window_handle::RawDisplayHandle,
window_handle: raw_window_handle::RawWindowHandle,
) -> Result<Box<dyn DynSurface>, InstanceError>;
unsafe fn enumerate_adapters(
&self,
surface_hint: Option<&dyn DynSurface>,
) -> Vec<DynExposedAdapter>;
}
impl<I: Instance + DynResource> DynInstance for I {
unsafe fn create_surface(
&self,
display_handle: raw_window_handle::RawDisplayHandle,
window_handle: raw_window_handle::RawWindowHandle,
) -> Result<Box<dyn DynSurface>, InstanceError> {
unsafe { I::create_surface(self, display_handle, window_handle) }
.map(|surface| -> Box<dyn DynSurface> { Box::new(surface) })
}
unsafe fn enumerate_adapters(
&self,
surface_hint: Option<&dyn DynSurface>,
) -> Vec<DynExposedAdapter> {
let surface_hint = surface_hint.map(|s| s.expect_downcast_ref());
unsafe { I::enumerate_adapters(self, surface_hint) }
.into_iter()
.map(|exposed| DynExposedAdapter {
adapter: Box::new(exposed.adapter),
info: exposed.info,
features: exposed.features,
capabilities: exposed.capabilities,
})
.collect()
}
}
+221
View File
@@ -0,0 +1,221 @@
mod adapter;
mod command;
mod device;
mod instance;
mod queue;
mod surface;
pub use adapter::{DynAdapter, DynOpenDevice};
pub use command::DynCommandEncoder;
pub use device::DynDevice;
pub use instance::{DynExposedAdapter, DynInstance};
pub use queue::DynQueue;
pub use surface::{DynAcquiredSurfaceTexture, DynSurface};
use alloc::boxed::Box;
use core::{
any::{Any, TypeId},
fmt,
};
use wgt::WasmNotSendSync;
use crate::{
AccelerationStructureAABBs, AccelerationStructureEntries, AccelerationStructureInstances,
AccelerationStructureTriangleIndices, AccelerationStructureTriangleTransform,
AccelerationStructureTriangles, BufferBinding, ExternalTextureBinding, ProgrammableStage,
TextureBinding,
};
/// Base trait for all resources, allows downcasting via [`Any`].
pub trait DynResource: Any + WasmNotSendSync + 'static {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
/// Utility macro for implementing `DynResource` for a list of types.
macro_rules! impl_dyn_resource {
($($type:ty),*) => {
$(
impl crate::DynResource for $type {
fn as_any(&self) -> &dyn ::core::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
self
}
}
)*
};
}
pub(crate) use impl_dyn_resource;
/// Extension trait for `DynResource` used by implementations of various dynamic resource traits.
trait DynResourceExt {
/// # Panics
///
/// - Panics if `self` is not downcastable to `T`.
fn expect_downcast_ref<T: DynResource>(&self) -> &T;
/// # Panics
///
/// - Panics if `self` is not downcastable to `T`.
fn expect_downcast_mut<T: DynResource>(&mut self) -> &mut T;
/// Unboxes a `Box<dyn DynResource>` to a concrete type.
///
/// # Safety
///
/// - `self` must be the correct concrete type.
unsafe fn unbox<T: DynResource + 'static>(self: Box<Self>) -> T;
}
impl<R: DynResource + ?Sized> DynResourceExt for R {
fn expect_downcast_ref<'a, T: DynResource>(&'a self) -> &'a T {
self.as_any()
.downcast_ref()
.expect("Resource doesn't have the expected backend type.")
}
fn expect_downcast_mut<'a, T: DynResource>(&'a mut self) -> &'a mut T {
self.as_any_mut()
.downcast_mut()
.expect("Resource doesn't have the expected backend type.")
}
unsafe fn unbox<T: DynResource + 'static>(self: Box<Self>) -> T {
debug_assert!(
<Self as Any>::type_id(self.as_ref()) == TypeId::of::<T>(),
"Resource doesn't have the expected type, expected {:?}, got {:?}",
TypeId::of::<T>(),
<Self as Any>::type_id(self.as_ref())
);
let casted_ptr = Box::into_raw(self).cast::<T>();
// SAFETY: This is adheres to the safety contract of `Box::from_raw` because:
//
// - We are casting the value of a previously `Box`ed value, which guarantees:
// - `casted_ptr` is not null.
// - `casted_ptr` is valid for reads and writes, though by itself this does not mean
// valid reads and writes for `T` (read on for that).
// - We don't change the allocator.
// - The contract of `Box::from_raw` requires that an initialized and aligned `T` is stored
// within `casted_ptr`.
*unsafe { Box::from_raw(casted_ptr) }
}
}
pub trait DynAccelerationStructure: DynResource + fmt::Debug {}
pub trait DynBindGroup: DynResource + fmt::Debug {}
pub trait DynBindGroupLayout: DynResource + fmt::Debug {}
pub trait DynBuffer: DynResource + fmt::Debug {}
pub trait DynCommandBuffer: DynResource + fmt::Debug {}
pub trait DynComputePipeline: DynResource + fmt::Debug {}
pub trait DynFence: DynResource + fmt::Debug {}
pub trait DynPipelineCache: DynResource + fmt::Debug {}
pub trait DynPipelineLayout: DynResource + fmt::Debug {}
pub trait DynQuerySet: DynResource + fmt::Debug {}
pub trait DynRenderPipeline: DynResource + fmt::Debug {}
pub trait DynSampler: DynResource + fmt::Debug {}
pub trait DynShaderModule: DynResource + fmt::Debug {}
pub trait DynSurfaceTexture:
DynResource + core::borrow::Borrow<dyn DynTexture> + fmt::Debug
{
}
pub trait DynTexture: DynResource + fmt::Debug {}
pub trait DynTextureView: DynResource + fmt::Debug {}
impl<'a> BufferBinding<'a, dyn DynBuffer> {
pub fn expect_downcast<B: DynBuffer>(self) -> BufferBinding<'a, B> {
BufferBinding {
buffer: self.buffer.expect_downcast_ref(),
offset: self.offset,
size: self.size,
}
}
}
impl<'a> TextureBinding<'a, dyn DynTextureView> {
pub fn expect_downcast<T: DynTextureView>(self) -> TextureBinding<'a, T> {
TextureBinding {
view: self.view.expect_downcast_ref(),
usage: self.usage,
}
}
}
impl<'a> ExternalTextureBinding<'a, dyn DynBuffer, dyn DynTextureView> {
pub fn expect_downcast<B: DynBuffer, T: DynTextureView>(
self,
) -> ExternalTextureBinding<'a, B, T> {
let planes = self.planes.map(|plane| plane.expect_downcast());
let params = self.params.expect_downcast();
ExternalTextureBinding { planes, params }
}
}
impl<'a> ProgrammableStage<'a, dyn DynShaderModule> {
fn expect_downcast<T: DynShaderModule>(self) -> ProgrammableStage<'a, T> {
ProgrammableStage {
module: self.module.expect_downcast_ref(),
entry_point: self.entry_point,
constants: self.constants,
zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
}
}
}
impl<'a> AccelerationStructureEntries<'a, dyn DynBuffer> {
fn expect_downcast<B: DynBuffer>(&self) -> AccelerationStructureEntries<'a, B> {
match self {
AccelerationStructureEntries::Instances(instances) => {
AccelerationStructureEntries::Instances(AccelerationStructureInstances {
buffer: instances.buffer.map(|b| b.expect_downcast_ref()),
offset: instances.offset,
count: instances.count,
})
}
AccelerationStructureEntries::Triangles(triangles) => {
AccelerationStructureEntries::Triangles(
triangles
.iter()
.map(|t| AccelerationStructureTriangles {
vertex_buffer: t.vertex_buffer.map(|b| b.expect_downcast_ref()),
vertex_format: t.vertex_format,
first_vertex: t.first_vertex,
vertex_count: t.vertex_count,
vertex_stride: t.vertex_stride,
indices: t.indices.as_ref().map(|i| {
AccelerationStructureTriangleIndices {
buffer: i.buffer.map(|b| b.expect_downcast_ref()),
format: i.format,
offset: i.offset,
count: i.count,
}
}),
transform: t.transform.as_ref().map(|t| {
AccelerationStructureTriangleTransform {
buffer: t.buffer.expect_downcast_ref(),
offset: t.offset,
}
}),
flags: t.flags,
})
.collect(),
)
}
AccelerationStructureEntries::AABBs(entries) => AccelerationStructureEntries::AABBs(
entries
.iter()
.map(|e| AccelerationStructureAABBs {
buffer: e.buffer.map(|b| b.expect_downcast_ref()),
offset: e.offset,
count: e.count,
stride: e.stride,
flags: e.flags,
})
.collect(),
),
}
}
}
+56
View File
@@ -0,0 +1,56 @@
use alloc::{boxed::Box, vec::Vec};
use crate::{
DeviceError, DynCommandBuffer, DynFence, DynResource, DynSurface, DynSurfaceTexture,
FenceValue, Queue, SurfaceError,
};
use super::DynResourceExt as _;
pub trait DynQueue: DynResource {
unsafe fn submit(
&self,
command_buffers: &[&dyn DynCommandBuffer],
surface_textures: &[&dyn DynSurfaceTexture],
signal_fence: (&mut dyn DynFence, FenceValue),
) -> Result<(), DeviceError>;
unsafe fn present(
&self,
surface: &dyn DynSurface,
texture: Box<dyn DynSurfaceTexture>,
) -> Result<(), SurfaceError>;
unsafe fn get_timestamp_period(&self) -> f32;
}
impl<Q: Queue + DynResource> DynQueue for Q {
unsafe fn submit(
&self,
command_buffers: &[&dyn DynCommandBuffer],
surface_textures: &[&dyn DynSurfaceTexture],
signal_fence: (&mut dyn DynFence, FenceValue),
) -> Result<(), DeviceError> {
let command_buffers = command_buffers
.iter()
.map(|cb| (*cb).expect_downcast_ref())
.collect::<Vec<_>>();
let surface_textures = surface_textures
.iter()
.map(|surface| (*surface).expect_downcast_ref())
.collect::<Vec<_>>();
let signal_fence = (signal_fence.0.expect_downcast_mut(), signal_fence.1);
unsafe { Q::submit(self, &command_buffers, &surface_textures, signal_fence) }
}
unsafe fn present(
&self,
surface: &dyn DynSurface,
texture: Box<dyn DynSurfaceTexture>,
) -> Result<(), SurfaceError> {
let surface = surface.expect_downcast_ref();
unsafe { Q::present(self, surface, texture.unbox()) }
}
unsafe fn get_timestamp_period(&self) -> f32 {
unsafe { Q::get_timestamp_period(self) }
}
}
+72
View File
@@ -0,0 +1,72 @@
use alloc::boxed::Box;
use core::time::Duration;
use crate::{
DynDevice, DynFence, DynResource, DynSurfaceTexture, Surface, SurfaceConfiguration,
SurfaceError,
};
use super::DynResourceExt as _;
#[derive(Debug)]
pub struct DynAcquiredSurfaceTexture {
pub texture: Box<dyn DynSurfaceTexture>,
/// The presentation configuration no longer matches
/// the surface properties exactly, but can still be used to present
/// to the surface successfully.
pub suboptimal: bool,
}
pub trait DynSurface: DynResource {
unsafe fn configure(
&self,
device: &dyn DynDevice,
config: &SurfaceConfiguration,
) -> Result<(), SurfaceError>;
unsafe fn unconfigure(&self, device: &dyn DynDevice);
unsafe fn acquire_texture(
&self,
timeout: Option<Duration>,
fence: &dyn DynFence,
) -> Result<DynAcquiredSurfaceTexture, SurfaceError>;
unsafe fn discard_texture(&self, texture: Box<dyn DynSurfaceTexture>);
}
impl<S: Surface + DynResource> DynSurface for S {
unsafe fn configure(
&self,
device: &dyn DynDevice,
config: &SurfaceConfiguration,
) -> Result<(), SurfaceError> {
let device = device.expect_downcast_ref();
unsafe { S::configure(self, device, config) }
}
unsafe fn unconfigure(&self, device: &dyn DynDevice) {
let device = device.expect_downcast_ref();
unsafe { S::unconfigure(self, device) }
}
unsafe fn acquire_texture(
&self,
timeout: Option<Duration>,
fence: &dyn DynFence,
) -> Result<DynAcquiredSurfaceTexture, SurfaceError> {
let fence = fence.expect_downcast_ref();
unsafe { S::acquire_texture(self, timeout, fence) }.map(|ast| {
let texture = Box::new(ast.texture);
let suboptimal = ast.suboptimal;
DynAcquiredSurfaceTexture {
texture,
suboptimal,
}
})
}
unsafe fn discard_texture(&self, texture: Box<dyn DynSurfaceTexture>) {
unsafe { S::discard_texture(self, texture.unbox()) }
}
}