mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 16:24:24 +00:00
trace: replaying all the commands
This commit is contained in:
parent
47f37ad78e
commit
018417f174
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
Cargo.lock
|
|
||||||
/target
|
/target
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
#Cargo.lock
|
#Cargo.lock
|
||||||
|
1419
Cargo.lock
generated
Normal file
1419
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,8 +16,9 @@ publish = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.7"
|
env_logger = "0.7"
|
||||||
ron = { version = "0.5" }
|
log = "0.4"
|
||||||
winit = { version = "0.22" }
|
ron = "0.5"
|
||||||
|
winit = { version = "0.22", optional = true }
|
||||||
|
|
||||||
[dependencies.wgt]
|
[dependencies.wgt]
|
||||||
path = "../wgpu-types"
|
path = "../wgpu-types"
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
use wgc::device::trace;
|
use wgc::device::trace;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
ffi::CString,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
fs::File,
|
fs::File,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
use winit::{event_loop::EventLoop, window::WindowBuilder};
|
|
||||||
|
|
||||||
macro_rules! gfx_select {
|
macro_rules! gfx_select {
|
||||||
($id:expr => $global:ident.$method:ident( $($param:expr),+ )) => {
|
($id:expr => $global:ident.$method:ident( $($param:expr),+ )) => {
|
||||||
@ -28,6 +28,24 @@ macro_rules! gfx_select {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Label(Option<CString>);
|
||||||
|
impl Label {
|
||||||
|
fn new(text: &str) -> Self {
|
||||||
|
Self(if text.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(CString::new(text).expect("invalid label"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> *const std::os::raw::c_char {
|
||||||
|
match self.0 {
|
||||||
|
Some(ref c_string) => c_string.as_ptr(),
|
||||||
|
None => std::ptr::null(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct IdentityPassThrough<I>(PhantomData<I>);
|
struct IdentityPassThrough<I>(PhantomData<I>);
|
||||||
|
|
||||||
@ -52,31 +70,134 @@ impl<I: Clone + Debug + wgc::id::TypedId> wgc::hub::IdentityHandlerFactory<I>
|
|||||||
}
|
}
|
||||||
impl wgc::hub::GlobalIdentityHandlerFactory for IdentityPassThroughFactory {}
|
impl wgc::hub::GlobalIdentityHandlerFactory for IdentityPassThroughFactory {}
|
||||||
|
|
||||||
|
trait GlobalExt {
|
||||||
|
fn encode_commands<B: wgc::hub::GfxBackend>(
|
||||||
|
&self,
|
||||||
|
encoder: wgc::id::CommandEncoderId,
|
||||||
|
commands: Vec<trace::Command>,
|
||||||
|
) -> wgc::id::CommandBufferId;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalExt for wgc::hub::Global<IdentityPassThroughFactory> {
|
||||||
|
fn encode_commands<B: wgc::hub::GfxBackend>(
|
||||||
|
&self,
|
||||||
|
encoder: wgc::id::CommandEncoderId,
|
||||||
|
commands: Vec<trace::Command>,
|
||||||
|
) -> wgc::id::CommandBufferId {
|
||||||
|
for command in commands {
|
||||||
|
match command {
|
||||||
|
trace::Command::CopyBufferToBuffer {
|
||||||
|
src,
|
||||||
|
src_offset,
|
||||||
|
dst,
|
||||||
|
dst_offset,
|
||||||
|
size,
|
||||||
|
} => self.command_encoder_copy_buffer_to_buffer::<B>(
|
||||||
|
encoder, src, src_offset, dst, dst_offset, size,
|
||||||
|
),
|
||||||
|
trace::Command::CopyBufferToTexture { src, dst, size } => {
|
||||||
|
self.command_encoder_copy_buffer_to_texture::<B>(encoder, &src, &dst, size)
|
||||||
|
}
|
||||||
|
trace::Command::CopyTextureToBuffer { src, dst, size } => {
|
||||||
|
self.command_encoder_copy_texture_to_buffer::<B>(encoder, &src, &dst, size)
|
||||||
|
}
|
||||||
|
trace::Command::CopyTextureToTexture { src, dst, size } => {
|
||||||
|
self.command_encoder_copy_texture_to_texture::<B>(encoder, &src, &dst, size)
|
||||||
|
}
|
||||||
|
trace::Command::RunComputePass {
|
||||||
|
commands,
|
||||||
|
dynamic_offsets,
|
||||||
|
} => unsafe {
|
||||||
|
let mut offsets = &dynamic_offsets[..];
|
||||||
|
let mut pass = wgc::command::RawPass::new_compute(encoder);
|
||||||
|
for com in commands {
|
||||||
|
pass.encode(&com);
|
||||||
|
if let wgc::command::ComputeCommand::SetBindGroup {
|
||||||
|
num_dynamic_offsets,
|
||||||
|
..
|
||||||
|
} = com
|
||||||
|
{
|
||||||
|
pass.encode_slice(&offsets[..num_dynamic_offsets as usize]);
|
||||||
|
offsets = &offsets[num_dynamic_offsets as usize..];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let (data, _) = pass.finish_compute();
|
||||||
|
self.command_encoder_run_compute_pass::<B>(encoder, &data);
|
||||||
|
},
|
||||||
|
trace::Command::RunRenderPass {
|
||||||
|
target_colors,
|
||||||
|
target_depth_stencil,
|
||||||
|
commands,
|
||||||
|
dynamic_offsets,
|
||||||
|
} => unsafe {
|
||||||
|
let mut offsets = &dynamic_offsets[..];
|
||||||
|
let mut pass = wgc::command::RawPass::new_render(
|
||||||
|
encoder,
|
||||||
|
&wgc::command::RenderPassDescriptor {
|
||||||
|
color_attachments: target_colors.as_ptr(),
|
||||||
|
color_attachments_length: target_colors.len(),
|
||||||
|
depth_stencil_attachment: target_depth_stencil.as_ref(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
for com in commands {
|
||||||
|
pass.encode(&com);
|
||||||
|
if let wgc::command::RenderCommand::SetBindGroup {
|
||||||
|
num_dynamic_offsets,
|
||||||
|
..
|
||||||
|
} = com
|
||||||
|
{
|
||||||
|
pass.encode_slice(&offsets[..num_dynamic_offsets as usize]);
|
||||||
|
offsets = &offsets[num_dynamic_offsets as usize..];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let (data, _) = pass.finish_render();
|
||||||
|
self.command_encoder_run_render_pass::<B>(encoder, &data);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.command_encoder_finish::<B>(encoder, &wgt::CommandBufferDescriptor { todo: 0 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
#[cfg(feature = "winit")]
|
||||||
|
use winit::{event_loop::EventLoop, window::WindowBuilder};
|
||||||
|
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
let folder = match std::env::args().nth(1) {
|
//TODO: setting for the backend bits
|
||||||
|
|
||||||
|
let dir = match std::env::args().nth(1) {
|
||||||
Some(arg) if Path::new(&arg).is_dir() => PathBuf::from(arg),
|
Some(arg) if Path::new(&arg).is_dir() => PathBuf::from(arg),
|
||||||
_ => panic!("Provide the folder path as the parameter"),
|
_ => panic!("Provide the dir path as the parameter"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let file = File::open(folder.join(trace::FILE_NAME)).unwrap();
|
log::info!("Loading trace '{:?}'", dir);
|
||||||
|
let file = File::open(dir.join(trace::FILE_NAME)).unwrap();
|
||||||
let actions: Vec<trace::Action> = ron::de::from_reader(file).unwrap();
|
let actions: Vec<trace::Action> = ron::de::from_reader(file).unwrap();
|
||||||
|
log::info!("Found {} actions", actions.len());
|
||||||
|
|
||||||
let event_loop = EventLoop::new();
|
#[cfg(feature = "winit")]
|
||||||
let mut builder = WindowBuilder::new();
|
let event_loop = {
|
||||||
builder = builder.with_title("wgpu player");
|
log::info!("Creating a window");
|
||||||
let window = builder.build(&event_loop).unwrap();
|
EventLoop::new()
|
||||||
|
};
|
||||||
|
#[cfg(feature = "winit")]
|
||||||
|
let window = WindowBuilder::new()
|
||||||
|
.with_title("wgpu player")
|
||||||
|
.with_resizable(false)
|
||||||
|
.build(&event_loop)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let global = wgc::hub::Global::new("player", IdentityPassThroughFactory);
|
let global = wgc::hub::Global::new("player", IdentityPassThroughFactory);
|
||||||
let mut surface_id_manager = wgc::hub::IdentityManager::from_index(1);
|
|
||||||
let mut adapter_id_manager = wgc::hub::IdentityManager::default();
|
let mut adapter_id_manager = wgc::hub::IdentityManager::default();
|
||||||
let mut device_id_manager = wgc::hub::IdentityManager::default();
|
let mut command_buffer_id_manager = wgc::hub::IdentityManager::default();
|
||||||
|
|
||||||
|
#[cfg(feature = "winit")]
|
||||||
let (_size, surface) = {
|
let (_size, surface) = {
|
||||||
let size = window.inner_size();
|
let size = window.inner_size();
|
||||||
let id = surface_id_manager.alloc(wgt::Backend::Empty);
|
let id = wgc::id::TypedId::zip(1, 0, wgt::Backend::Empty);
|
||||||
let surface = global.instance_create_surface(&window, id);
|
let surface = global.instance_create_surface(window.raw_window_handle(), id);
|
||||||
(size, surface)
|
(size, surface)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,7 +205,10 @@ fn main() {
|
|||||||
.pick_adapter(
|
.pick_adapter(
|
||||||
&wgc::instance::RequestAdapterOptions {
|
&wgc::instance::RequestAdapterOptions {
|
||||||
power_preference: wgt::PowerPreference::Default,
|
power_preference: wgt::PowerPreference::Default,
|
||||||
|
#[cfg(feature = "winit")]
|
||||||
compatible_surface: Some(surface),
|
compatible_surface: Some(surface),
|
||||||
|
#[cfg(not(feature = "winit"))]
|
||||||
|
compatible_surface: None,
|
||||||
},
|
},
|
||||||
wgc::instance::AdapterInputs::IdSet(
|
wgc::instance::AdapterInputs::IdSet(
|
||||||
&vec![
|
&vec![
|
||||||
@ -92,30 +216,180 @@ fn main() {
|
|||||||
adapter_id_manager.alloc(wgt::Backend::Dx12),
|
adapter_id_manager.alloc(wgt::Backend::Dx12),
|
||||||
adapter_id_manager.alloc(wgt::Backend::Metal),
|
adapter_id_manager.alloc(wgt::Backend::Metal),
|
||||||
],
|
],
|
||||||
|id| wgc::id::TypedId::unzip(*id).2,
|
|id| id.backend(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let limits = match actions.first() {
|
let mut device = wgc::id::DeviceId::default();
|
||||||
Some(&trace::Action::Init { ref limits }) => limits.clone(),
|
|
||||||
other => panic!("Unsupported first action: {:?}", other),
|
|
||||||
};
|
|
||||||
|
|
||||||
let device = gfx_select!(adapter => global.adapter_request_device(
|
log::info!("Executing actions");
|
||||||
adapter,
|
for action in actions {
|
||||||
&wgt::DeviceDescriptor {
|
use wgc::device::trace::Action as A;
|
||||||
extensions: wgt::Extensions {
|
|
||||||
anisotropic_filtering: false,
|
|
||||||
},
|
|
||||||
limits,
|
|
||||||
},
|
|
||||||
device_id_manager.alloc(wgt::Backend::Vulkan)
|
|
||||||
));
|
|
||||||
|
|
||||||
for action in actions.into_iter().skip(1) {
|
|
||||||
match action {
|
match action {
|
||||||
_ => {}
|
A::Init { limits } => {
|
||||||
|
log::info!("Initializing the device");
|
||||||
|
device = gfx_select!(adapter => global.adapter_request_device(
|
||||||
|
adapter,
|
||||||
|
&wgt::DeviceDescriptor {
|
||||||
|
extensions: wgt::Extensions {
|
||||||
|
anisotropic_filtering: false,
|
||||||
|
},
|
||||||
|
limits,
|
||||||
|
},
|
||||||
|
wgc::id::TypedId::zip(1, 0, wgt::Backend::Empty)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
A::CreateBuffer { id, desc } => {
|
||||||
|
let label = Label::new(&desc.label);
|
||||||
|
gfx_select!(device => global.device_create_buffer(device, &desc.map_label(|_| label.as_ptr()), id));
|
||||||
|
}
|
||||||
|
A::DestroyBuffer(id) => {
|
||||||
|
gfx_select!(device => global.buffer_destroy(id));
|
||||||
|
}
|
||||||
|
A::CreateTexture { id, desc } => {
|
||||||
|
let label = Label::new(&desc.label);
|
||||||
|
gfx_select!(device => global.device_create_texture(device, &desc.map_label(|_| label.as_ptr()), id));
|
||||||
|
}
|
||||||
|
A::DestroyTexture(id) => {
|
||||||
|
gfx_select!(device => global.texture_destroy(id));
|
||||||
|
}
|
||||||
|
A::CreateTextureView {
|
||||||
|
id,
|
||||||
|
parent_id,
|
||||||
|
desc,
|
||||||
|
} => {
|
||||||
|
let label = desc.as_ref().map_or(Label(None), |d| Label::new(&d.label));
|
||||||
|
gfx_select!(device => global.texture_create_view(parent_id, desc.map(|d| d.map_label(|_| label.as_ptr())).as_ref(), id));
|
||||||
|
}
|
||||||
|
A::DestroyTextureView(id) => {
|
||||||
|
gfx_select!(device => global.texture_view_destroy(id));
|
||||||
|
}
|
||||||
|
A::CreateSampler { id, desc } => {
|
||||||
|
let label = Label::new(&desc.label);
|
||||||
|
gfx_select!(device => global.device_create_sampler(device, &desc.map_label(|_| label.as_ptr()), id));
|
||||||
|
}
|
||||||
|
A::DestroySampler(id) => {
|
||||||
|
gfx_select!(device => global.sampler_destroy(id));
|
||||||
|
}
|
||||||
|
A::CreateSwapChain { id: _, desc } => {
|
||||||
|
#[cfg(feature = "winit")]
|
||||||
|
{
|
||||||
|
log::info!("Initializing the swapchain");
|
||||||
|
window.set_inner_size(winit::dpi::PhysicalSize::new(desc.width, desc.height));
|
||||||
|
gfx_select!(device => global.device_create_swap_chain(device, surface, &desc));
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "winit"))]
|
||||||
|
let _ = desc;
|
||||||
|
}
|
||||||
|
A::GetSwapChainTexture { id, parent_id } => {
|
||||||
|
gfx_select!(device => global.swap_chain_get_next_texture(parent_id, id)).unwrap();
|
||||||
|
}
|
||||||
|
A::PresentSwapChain(id) => {
|
||||||
|
gfx_select!(device => global.swap_chain_present(id));
|
||||||
|
}
|
||||||
|
A::CreateBindGroupLayout { id, label, entries } => {
|
||||||
|
let label = Label::new(&label);
|
||||||
|
gfx_select!(device => global.device_create_bind_group_layout(
|
||||||
|
device,
|
||||||
|
&wgc::binding_model::BindGroupLayoutDescriptor {
|
||||||
|
label: label.as_ptr(),
|
||||||
|
entries: entries.as_ptr(),
|
||||||
|
entries_length: entries.len(),
|
||||||
|
},
|
||||||
|
id));
|
||||||
|
}
|
||||||
|
A::DestroyBindGroupLayout(id) => {
|
||||||
|
gfx_select!(device => global.bind_group_layout_destroy(id));
|
||||||
|
}
|
||||||
|
A::CreatePipelineLayout {
|
||||||
|
id,
|
||||||
|
bind_group_layouts,
|
||||||
|
} => {
|
||||||
|
gfx_select!(device => global.device_create_pipeline_layout(
|
||||||
|
device,
|
||||||
|
&wgc::binding_model::PipelineLayoutDescriptor {
|
||||||
|
bind_group_layouts: bind_group_layouts.as_ptr(),
|
||||||
|
bind_group_layouts_length: bind_group_layouts.len(),
|
||||||
|
},
|
||||||
|
id));
|
||||||
|
}
|
||||||
|
A::DestroyPipelineLayout(id) => {
|
||||||
|
gfx_select!(device => global.pipeline_layout_destroy(id));
|
||||||
|
}
|
||||||
|
A::CreateBindGroup {
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
layout_id,
|
||||||
|
entries,
|
||||||
|
} => {
|
||||||
|
use wgc::binding_model as bm;
|
||||||
|
let label = Label::new(&label);
|
||||||
|
let entry_vec = entries
|
||||||
|
.into_iter()
|
||||||
|
.map(|(binding, res)| wgc::binding_model::BindGroupEntry {
|
||||||
|
binding,
|
||||||
|
resource: match res {
|
||||||
|
trace::BindingResource::Buffer { id, offset, size } => {
|
||||||
|
bm::BindingResource::Buffer(bm::BufferBinding {
|
||||||
|
buffer: id,
|
||||||
|
offset,
|
||||||
|
size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
trace::BindingResource::Sampler(id) => bm::BindingResource::Sampler(id),
|
||||||
|
trace::BindingResource::TextureView(id) => {
|
||||||
|
bm::BindingResource::TextureView(id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
gfx_select!(device => global.device_create_bind_group(
|
||||||
|
device,
|
||||||
|
&wgc::binding_model::BindGroupDescriptor {
|
||||||
|
label: label.as_ptr(),
|
||||||
|
layout: layout_id,
|
||||||
|
entries: entry_vec.as_ptr(),
|
||||||
|
entries_length: entry_vec.len(),
|
||||||
|
},
|
||||||
|
id
|
||||||
|
));
|
||||||
|
}
|
||||||
|
A::DestroyBindGroup(id) => {
|
||||||
|
gfx_select!(device => global.bind_group_destroy(id));
|
||||||
|
}
|
||||||
|
A::CreateShaderModule { id, data } => {
|
||||||
|
let spv = wgt::read_spirv(File::open(dir.join(data)).unwrap()).unwrap();
|
||||||
|
gfx_select!(device => global.device_create_shader_module(
|
||||||
|
device,
|
||||||
|
&wgc::pipeline::ShaderModuleDescriptor {
|
||||||
|
code: wgc::U32Array {
|
||||||
|
bytes: spv.as_ptr(),
|
||||||
|
length: spv.len(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
id
|
||||||
|
));
|
||||||
|
}
|
||||||
|
A::DestroyShaderModule(id) => {
|
||||||
|
gfx_select!(device => global.shader_module_destroy(id));
|
||||||
|
}
|
||||||
|
A::WriteBuffer { id, data, range } => {
|
||||||
|
let bin = std::fs::read(dir.join(data)).unwrap();
|
||||||
|
let size = (range.end - range.start) as usize;
|
||||||
|
gfx_select!(device => global.device_set_buffer_sub_data(device, id, range.start, &bin[..size]));
|
||||||
|
}
|
||||||
|
A::Submit(commands) => {
|
||||||
|
let encoder = gfx_select!(device => global.device_create_command_encoder(
|
||||||
|
device,
|
||||||
|
&wgt::CommandEncoderDescriptor {
|
||||||
|
label: std::ptr::null(),
|
||||||
|
},
|
||||||
|
command_buffer_id_manager.alloc(device.backend())
|
||||||
|
));
|
||||||
|
let comb = gfx_select!(device => global.encode_commands(encoder, commands));
|
||||||
|
gfx_select!(device => global.queue_submit(device, &[comb]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,13 +109,13 @@ impl RawPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn encode<C: peek_poke::Poke>(&mut self, command: &C) {
|
pub unsafe fn encode<C: peek_poke::Poke>(&mut self, command: &C) {
|
||||||
self.ensure_extra_size(C::max_size());
|
self.ensure_extra_size(C::max_size());
|
||||||
self.data = command.poke_into(self.data);
|
self.data = command.poke_into(self.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn encode_slice<T: Copy>(&mut self, data: &[T]) {
|
pub unsafe fn encode_slice<T: Copy>(&mut self, data: &[T]) {
|
||||||
let align_offset = self.data.align_offset(mem::align_of::<T>());
|
let align_offset = self.data.align_offset(mem::align_of::<T>());
|
||||||
let extra = align_offset + mem::size_of::<T>() * data.len();
|
let extra = align_offset + mem::size_of::<T>() * data.len();
|
||||||
self.ensure_extra_size(extra);
|
self.ensure_extra_size(extra);
|
||||||
|
@ -610,7 +610,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
match device.trace {
|
match device.trace {
|
||||||
Some(ref trace) => {
|
Some(ref trace) => {
|
||||||
let mut trace = trace.lock();
|
let mut trace = trace.lock();
|
||||||
let data_path = trace.make_binary("buffer", data);
|
let data_path = trace.make_binary("bin", data);
|
||||||
trace.add(trace::Action::WriteBuffer {
|
trace.add(trace::Action::WriteBuffer {
|
||||||
id: buffer_id,
|
id: buffer_id,
|
||||||
data: data_path,
|
data: data_path,
|
||||||
@ -1481,7 +1481,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
match device.trace {
|
match device.trace {
|
||||||
Some(ref trace) => {
|
Some(ref trace) => {
|
||||||
let mut trace = trace.lock();
|
let mut trace = trace.lock();
|
||||||
let data = trace.make_binary("shader", unsafe {
|
let data = trace.make_binary("spv", unsafe {
|
||||||
slice::from_raw_parts(desc.code.bytes as *const u8, desc.code.length * 4)
|
slice::from_raw_parts(desc.code.bytes as *const u8, desc.code.length * 4)
|
||||||
});
|
});
|
||||||
trace.add(trace::Action::CreateShaderModule { id, data });
|
trace.add(trace::Action::CreateShaderModule { id, data });
|
||||||
@ -2420,7 +2420,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
Some(ref trace) => {
|
Some(ref trace) => {
|
||||||
let mut trace = trace.lock();
|
let mut trace = trace.lock();
|
||||||
let size = sub_range.size_to(buffer.size);
|
let size = sub_range.size_to(buffer.size);
|
||||||
let data = trace.make_binary("buffer", unsafe {
|
let data = trace.make_binary("bin", unsafe {
|
||||||
slice::from_raw_parts(ptr, size as usize)
|
slice::from_raw_parts(ptr, size as usize)
|
||||||
});
|
});
|
||||||
trace.add(trace::Action::WriteBuffer {
|
trace.add(trace::Action::WriteBuffer {
|
||||||
|
@ -160,7 +160,7 @@ impl Trace {
|
|||||||
|
|
||||||
pub fn make_binary(&mut self, kind: &str, data: &[u8]) -> String {
|
pub fn make_binary(&mut self, kind: &str, data: &[u8]) -> String {
|
||||||
self.binary_id += 1;
|
self.binary_id += 1;
|
||||||
let name = format!("{}{}.bin", kind, self.binary_id);
|
let name = format!("data{}.{}", self.binary_id, kind);
|
||||||
let _ = std::fs::write(self.path.join(&name), data);
|
let _ = std::fs::write(self.path.join(&name), data);
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
@ -208,14 +208,14 @@ impl<I: Clone> AdapterInputs<'_, I> {
|
|||||||
|
|
||||||
impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||||
#[cfg(feature = "raw-window-handle")]
|
#[cfg(feature = "raw-window-handle")]
|
||||||
pub fn instance_create_surface<W: raw_window_handle::HasRawWindowHandle>(
|
pub fn instance_create_surface(
|
||||||
&self,
|
&self,
|
||||||
window: &W,
|
handle: raw_window_handle::RawWindowHandle,
|
||||||
id_in: Input<G, SurfaceId>,
|
id_in: Input<G, SurfaceId>,
|
||||||
) -> SurfaceId {
|
) -> SurfaceId {
|
||||||
use raw_window_handle::RawWindowHandle as Rwh;
|
use raw_window_handle::RawWindowHandle as Rwh;
|
||||||
|
|
||||||
let surface = match window.raw_window_handle() {
|
let surface = match handle {
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
Rwh::IOS(h) => Surface {
|
Rwh::IOS(h) => Surface {
|
||||||
#[cfg(feature = "gfx-backend-vulkan")]
|
#[cfg(feature = "gfx-backend-vulkan")]
|
||||||
|
@ -85,6 +85,9 @@ pub enum BufferMapState {
|
|||||||
Idle,
|
Idle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for BufferMapState {}
|
||||||
|
unsafe impl Sync for BufferMapState {}
|
||||||
|
|
||||||
pub enum BufferMapOperation {
|
pub enum BufferMapOperation {
|
||||||
Read {
|
Read {
|
||||||
callback: crate::device::BufferMapReadCallback,
|
callback: crate::device::BufferMapReadCallback,
|
||||||
|
Loading…
Reference in New Issue
Block a user