1use crate::host_calls::{host_call, unpack};
2use interstice_abi::*;
3
4fn unpack_gpu_response(pack: i64) -> Result<GpuResponse, String> {
5 let response: GpuResponse = unpack(pack);
6 match response {
7 GpuResponse::Err(err) => Err(err),
8 other => Ok(other),
9 }
10}
11
12fn expect_gpu_none(response: GpuResponse) -> Result<(), String> {
13 match response {
14 GpuResponse::None => Ok(()),
15 other => Err(format!("Unexpected GPU response: {:?}", other)),
16 }
17}
18
19fn expect_gpu_i64(response: GpuResponse) -> Result<GpuId, String> {
20 match response {
21 GpuResponse::I64(value) => Ok(value as GpuId),
22 other => Err(format!("Unexpected GPU response: {:?}", other)),
23 }
24}
25
26fn expect_gpu_texture_format(response: GpuResponse) -> Result<TextureFormat, String> {
27 match response {
28 GpuResponse::TextureFormat(format) => Ok(format),
29 other => Err(format!("Unexpected GPU response: {:?}", other)),
30 }
31}
32
33fn expect_gpu_extent2d(response: GpuResponse) -> Result<(u32, u32), String> {
34 match response {
35 GpuResponse::Extent2d { width, height } => Ok((width, height)),
36 other => Err(format!("Unexpected GPU response: {:?}", other)),
37 }
38}
39
40pub fn begin_frame() -> Result<(), String> {
41 let pack = host_call(HostCall::Gpu(GpuCall::BeginFrame));
42 expect_gpu_none(unpack_gpu_response(pack)?)
43}
44
45pub fn request_redraw() -> Result<(), String> {
46 let pack = host_call(HostCall::Gpu(GpuCall::RequestRedraw));
47 expect_gpu_none(unpack_gpu_response(pack)?)
48}
49
50pub fn get_surface_format() -> Result<TextureFormat, String> {
51 let pack = host_call(HostCall::Gpu(GpuCall::GetSurfaceFormat));
52 expect_gpu_texture_format(unpack_gpu_response(pack)?)
53}
54
55pub fn get_surface_size() -> Result<(u32, u32), String> {
56 let pack = host_call(HostCall::Gpu(GpuCall::GetSurfaceSize));
57 expect_gpu_extent2d(unpack_gpu_response(pack)?)
58}
59
60pub fn get_current_surface_texture() -> Result<GpuId, String> {
61 let pack = host_call(HostCall::Gpu(GpuCall::GetCurrentSurfaceTexture));
62 expect_gpu_i64(unpack_gpu_response(pack)?)
63}
64
65pub fn present() -> Result<(), String> {
66 let pack = host_call(HostCall::Gpu(GpuCall::Present));
67 expect_gpu_none(unpack_gpu_response(pack)?)
68}
69
70pub fn create_buffer(
71 size: u64,
72 usage: BufferUsage,
73 mapped_at_creation: bool,
74) -> Result<GpuId, String> {
75 let pack = host_call(HostCall::Gpu(GpuCall::CreateBuffer(CreateBuffer {
76 size,
77 usage,
78 mapped_at_creation,
79 })));
80 expect_gpu_i64(unpack_gpu_response(pack)?)
81}
82
83pub fn write_buffer(buffer: GpuId, offset: u64, data: Vec<u8>) -> Result<(), String> {
84 let pack = host_call(HostCall::Gpu(GpuCall::WriteBuffer(WriteBuffer {
85 buffer,
86 offset,
87 data,
88 })));
89 expect_gpu_none(unpack_gpu_response(pack)?)
90}
91
92pub fn destroy_buffer(id: GpuId) -> Result<(), String> {
93 let pack = host_call(HostCall::Gpu(GpuCall::DestroyBuffer { id }));
94 expect_gpu_none(unpack_gpu_response(pack)?)
95}
96
97pub fn create_texture(desc: CreateTexture) -> Result<GpuId, String> {
98 let pack = host_call(HostCall::Gpu(GpuCall::CreateTexture(desc)));
99 expect_gpu_i64(unpack_gpu_response(pack)?)
100}
101
102pub fn write_texture(desc: WriteTexture) -> Result<(), String> {
103 let pack = host_call(HostCall::Gpu(GpuCall::WriteTexture(desc)));
104 expect_gpu_none(unpack_gpu_response(pack)?)
105}
106
107pub fn create_texture_view(desc: CreateTextureView) -> Result<GpuId, String> {
108 let pack = host_call(HostCall::Gpu(GpuCall::CreateTextureView(desc)));
109 expect_gpu_i64(unpack_gpu_response(pack)?)
110}
111
112pub fn destroy_texture(id: GpuId) -> Result<(), String> {
113 let pack = host_call(HostCall::Gpu(GpuCall::DestroyTexture { id }));
114 expect_gpu_none(unpack_gpu_response(pack)?)
115}
116
117pub fn destroy_texture_view(id: GpuId) -> Result<(), String> {
118 let pack = host_call(HostCall::Gpu(GpuCall::DestroyTextureView { id }));
119 expect_gpu_none(unpack_gpu_response(pack)?)
120}
121
122pub fn create_shader_module(wgsl_source: String) -> Result<GpuId, String> {
123 let pack = host_call(HostCall::Gpu(GpuCall::CreateShaderModule(
124 CreateShaderModule { wgsl_source },
125 )));
126 expect_gpu_i64(unpack_gpu_response(pack)?)
127}
128
129pub fn destroy_shader_module(id: GpuId) -> Result<(), String> {
130 let pack = host_call(HostCall::Gpu(GpuCall::DestroyShaderModule { id }));
131 expect_gpu_none(unpack_gpu_response(pack)?)
132}
133
134pub fn create_bind_group_layout(desc: CreateBindGroupLayout) -> Result<GpuId, String> {
135 let pack = host_call(HostCall::Gpu(GpuCall::CreateBindGroupLayout(desc)));
136 expect_gpu_i64(unpack_gpu_response(pack)?)
137}
138
139pub fn destroy_bind_group_layout(id: GpuId) -> Result<(), String> {
140 let pack = host_call(HostCall::Gpu(GpuCall::DestroyBindGroupLayout { id }));
141 expect_gpu_none(unpack_gpu_response(pack)?)
142}
143
144pub fn create_bind_group(desc: CreateBindGroup) -> Result<GpuId, String> {
145 let pack = host_call(HostCall::Gpu(GpuCall::CreateBindGroup(desc)));
146 expect_gpu_i64(unpack_gpu_response(pack)?)
147}
148
149pub fn destroy_bind_group(id: GpuId) -> Result<(), String> {
150 let pack = host_call(HostCall::Gpu(GpuCall::DestroyBindGroup { id }));
151 expect_gpu_none(unpack_gpu_response(pack)?)
152}
153
154pub fn create_pipeline_layout(desc: CreatePipelineLayout) -> Result<GpuId, String> {
155 let pack = host_call(HostCall::Gpu(GpuCall::CreatePipelineLayout(desc)));
156 expect_gpu_i64(unpack_gpu_response(pack)?)
157}
158
159pub fn destroy_pipeline_layout(id: GpuId) -> Result<(), String> {
160 let pack = host_call(HostCall::Gpu(GpuCall::DestroyPipelineLayout { id }));
161 expect_gpu_none(unpack_gpu_response(pack)?)
162}
163
164pub fn create_render_pipeline(desc: CreateRenderPipeline) -> Result<GpuId, String> {
165 let pack = host_call(HostCall::Gpu(GpuCall::CreateRenderPipeline(desc)));
166 expect_gpu_i64(unpack_gpu_response(pack)?)
167}
168
169pub fn destroy_render_pipeline(id: GpuId) -> Result<(), String> {
170 let pack = host_call(HostCall::Gpu(GpuCall::DestroyRenderPipeline { id }));
171 expect_gpu_none(unpack_gpu_response(pack)?)
172}
173
174pub fn create_compute_pipeline(desc: CreateComputePipeline) -> Result<GpuId, String> {
175 let pack = host_call(HostCall::Gpu(GpuCall::CreateComputePipeline(desc)));
176 expect_gpu_i64(unpack_gpu_response(pack)?)
177}
178
179pub fn destroy_compute_pipeline(id: GpuId) -> Result<(), String> {
180 let pack = host_call(HostCall::Gpu(GpuCall::DestroyComputePipeline { id }));
181 expect_gpu_none(unpack_gpu_response(pack)?)
182}
183
184pub fn create_command_encoder() -> Result<GpuId, String> {
185 let pack = host_call(HostCall::Gpu(GpuCall::CreateCommandEncoder));
186 expect_gpu_i64(unpack_gpu_response(pack)?)
187}
188
189pub fn submit(encoder: GpuId) -> Result<(), String> {
190 let pack = host_call(HostCall::Gpu(GpuCall::Submit { encoder }));
191 expect_gpu_none(unpack_gpu_response(pack)?)
192}
193
194pub fn begin_render_pass(desc: BeginRenderPass) -> Result<GpuId, String> {
195 let pack = host_call(HostCall::Gpu(GpuCall::BeginRenderPass(desc)));
196 expect_gpu_i64(unpack_gpu_response(pack)?)
197}
198
199pub fn end_render_pass(pass: GpuId) -> Result<(), String> {
200 let pack = host_call(HostCall::Gpu(GpuCall::EndRenderPass { pass }));
201 expect_gpu_none(unpack_gpu_response(pack)?)
202}
203
204pub fn set_render_pipeline(pass: GpuId, pipeline: GpuId) -> Result<(), String> {
205 let pack = host_call(HostCall::Gpu(GpuCall::SetRenderPipeline { pass, pipeline }));
206 expect_gpu_none(unpack_gpu_response(pack)?)
207}
208
209pub fn set_bind_group(pass: GpuId, index: u32, bind_group: GpuId) -> Result<(), String> {
210 let pack = host_call(HostCall::Gpu(GpuCall::SetBindGroup {
211 pass,
212 index,
213 bind_group,
214 }));
215 expect_gpu_none(unpack_gpu_response(pack)?)
216}
217
218pub fn set_vertex_buffer(
219 pass: GpuId,
220 buffer: GpuId,
221 offset: u64,
222 slot: u32,
223 size: Option<u64>,
224) -> Result<(), String> {
225 let pack = host_call(HostCall::Gpu(GpuCall::SetVertexBuffer(SetVertexBuffer {
226 pass,
227 buffer,
228 offset,
229 slot,
230 size,
231 })));
232 expect_gpu_none(unpack_gpu_response(pack)?)
233}
234
235pub fn set_index_buffer(
236 pass: GpuId,
237 buffer: GpuId,
238 offset: u64,
239 format: IndexFormat,
240 size: Option<u64>,
241) -> Result<(), String> {
242 let pack = host_call(HostCall::Gpu(GpuCall::SetIndexBuffer(SetIndexBuffer {
243 pass,
244 buffer,
245 offset,
246 index_format: format,
247 size,
248 })));
249 expect_gpu_none(unpack_gpu_response(pack)?)
250}
251
252pub fn draw(pass: GpuId, vertices: u32, instances: u32) -> Result<(), String> {
253 let pack = host_call(HostCall::Gpu(GpuCall::Draw(Draw {
254 pass,
255 vertices,
256 instances,
257 first_vertex: 0,
258 first_instance: 0,
259 })));
260 expect_gpu_none(unpack_gpu_response(pack)?)
261}
262
263pub fn draw_indexed(pass: GpuId, indices: u32, instances: u32) -> Result<(), String> {
264 let pack = host_call(HostCall::Gpu(GpuCall::DrawIndexed(DrawIndexed {
265 pass,
266 indices,
267 instances,
268 first_index: 0,
269 base_vertex: 0,
270 first_instance: 0,
271 })));
272 expect_gpu_none(unpack_gpu_response(pack)?)
273}
274
275pub fn begin_compute_pass(encoder: GpuId) -> Result<(), String> {
278 let pack = host_call(HostCall::Gpu(GpuCall::BeginComputePass { encoder }));
279 expect_gpu_none(unpack_gpu_response(pack)?)
280}
281
282pub fn end_compute_pass(pass: GpuId) -> Result<(), String> {
283 let pack = host_call(HostCall::Gpu(GpuCall::EndComputePass { pass }));
284 expect_gpu_none(unpack_gpu_response(pack)?)
285}
286
287pub fn set_compute_pipeline(pass: GpuId, pipeline: GpuId) -> Result<(), String> {
288 let pack = host_call(HostCall::Gpu(GpuCall::SetComputePipeline {
289 pass,
290 pipeline,
291 }));
292 expect_gpu_none(unpack_gpu_response(pack)?)
293}
294
295pub fn dispatch(pass: GpuId, x: u32, y: u32, z: u32) -> Result<(), String> {
296 let pack = host_call(HostCall::Gpu(GpuCall::Dispatch { pass, x, y, z }));
297 expect_gpu_none(unpack_gpu_response(pack)?)
298}
299
300pub fn copy_buffer_to_buffer(cmd: CopyBufferToBuffer) -> Result<(), String> {
303 let pack = host_call(HostCall::Gpu(GpuCall::CopyBufferToBuffer(cmd)));
304 expect_gpu_none(unpack_gpu_response(pack)?)
305}
306
307pub fn copy_buffer_to_texture(cmd: CopyBufferToTexture) -> Result<(), String> {
308 let pack = host_call(HostCall::Gpu(GpuCall::CopyBufferToTexture(cmd)));
309 expect_gpu_none(unpack_gpu_response(pack)?)
310}
311
312pub fn copy_texture_to_buffer(cmd: CopyTextureToBuffer) -> Result<(), String> {
313 let pack = host_call(HostCall::Gpu(GpuCall::CopyTextureToBuffer(cmd)));
314 expect_gpu_none(unpack_gpu_response(pack)?)
315}
316
317pub struct Buffer(pub GpuId);
318pub struct RenderPipeline(pub GpuId);
319pub struct BindGroup(pub GpuId);
320pub struct Texture(pub GpuId);
321
322pub struct Gpu;
323
324impl Gpu {
325 pub fn request_redraw(&self) -> Result<(), String> {
326 request_redraw()
327 }
328
329 pub fn begin_frame(&self) -> Result<(), String> {
330 begin_frame()
331 }
332
333 pub fn get_surface_format(&self) -> Result<TextureFormat, String> {
334 get_surface_format()
335 }
336
337 pub fn get_surface_size(&self) -> Result<(u32, u32), String> {
338 get_surface_size()
339 }
340
341 pub fn get_current_surface_texture(&self) -> Result<GpuId, String> {
342 get_current_surface_texture()
343 }
344
345 pub fn present(&self) -> Result<(), String> {
346 present()
347 }
348
349 pub fn create_buffer(
350 &self,
351 size: u64,
352 usage: BufferUsage,
353 mapped_at_creation: bool,
354 ) -> Result<GpuId, String> {
355 create_buffer(size, usage, mapped_at_creation)
356 }
357
358 pub fn write_buffer(&self, buffer: GpuId, offset: u64, data: Vec<u8>) -> Result<(), String> {
359 write_buffer(buffer, offset, data)
360 }
361
362 pub fn write_texture(&self, desc: WriteTexture) -> Result<(), String> {
363 write_texture(desc)
364 }
365
366 pub fn destroy_buffer(&self, id: GpuId) -> Result<(), String> {
367 destroy_buffer(id)
368 }
369
370 pub fn create_texture(&self, desc: CreateTexture) -> Result<GpuId, String> {
371 create_texture(desc)
372 }
373
374 pub fn create_texture_view(&self, desc: CreateTextureView) -> Result<GpuId, String> {
375 create_texture_view(desc)
376 }
377
378 pub fn destroy_texture(&self, id: GpuId) -> Result<(), String> {
379 destroy_texture(id)
380 }
381
382 pub fn destroy_texture_view(&self, id: GpuId) -> Result<(), String> {
383 destroy_texture_view(id)
384 }
385
386 pub fn create_shader_module(&self, wgsl_source: String) -> Result<GpuId, String> {
387 create_shader_module(wgsl_source)
388 }
389
390 pub fn destroy_shader_module(&self, id: GpuId) -> Result<(), String> {
391 destroy_shader_module(id)
392 }
393
394 pub fn create_bind_group_layout(&self, desc: CreateBindGroupLayout) -> Result<GpuId, String> {
395 create_bind_group_layout(desc)
396 }
397
398 pub fn destroy_bind_group_layout(&self, id: GpuId) -> Result<(), String> {
399 destroy_bind_group_layout(id)
400 }
401
402 pub fn create_bind_group(&self, desc: CreateBindGroup) -> Result<GpuId, String> {
403 create_bind_group(desc)
404 }
405
406 pub fn destroy_bind_group(&self, id: GpuId) -> Result<(), String> {
407 destroy_bind_group(id)
408 }
409
410 pub fn create_pipeline_layout(&self, desc: CreatePipelineLayout) -> Result<GpuId, String> {
411 create_pipeline_layout(desc)
412 }
413
414 pub fn destroy_pipeline_layout(&self, id: GpuId) -> Result<(), String> {
415 destroy_pipeline_layout(id)
416 }
417
418 pub fn create_render_pipeline(&self, desc: CreateRenderPipeline) -> Result<GpuId, String> {
419 create_render_pipeline(desc)
420 }
421
422 pub fn destroy_render_pipeline(&self, id: GpuId) -> Result<(), String> {
423 destroy_render_pipeline(id)
424 }
425
426 pub fn create_compute_pipeline(&self, desc: CreateComputePipeline) -> Result<GpuId, String> {
427 create_compute_pipeline(desc)
428 }
429
430 pub fn destroy_compute_pipeline(&self, id: GpuId) -> Result<(), String> {
431 destroy_compute_pipeline(id)
432 }
433
434 pub fn create_command_encoder(&self) -> Result<GpuId, String> {
435 create_command_encoder()
436 }
437
438 pub fn submit(&self, encoder: GpuId) -> Result<(), String> {
439 submit(encoder)
440 }
441
442 pub fn begin_render_pass(&self, desc: BeginRenderPass) -> Result<GpuId, String> {
443 begin_render_pass(desc)
444 }
445
446 pub fn end_render_pass(&self, pass: GpuId) -> Result<(), String> {
447 end_render_pass(pass)
448 }
449
450 pub fn set_render_pipeline(&self, pass: GpuId, pipeline: GpuId) -> Result<(), String> {
451 set_render_pipeline(pass, pipeline)
452 }
453
454 pub fn set_bind_group(&self, pass: GpuId, index: u32, bind_group: GpuId) -> Result<(), String> {
455 set_bind_group(pass, index, bind_group)
456 }
457
458 pub fn set_vertex_buffer(
459 &self,
460 pass: GpuId,
461 buffer: GpuId,
462 offset: u64,
463 slot: u32,
464 size: Option<u64>,
465 ) -> Result<(), String> {
466 set_vertex_buffer(pass, buffer, offset, slot, size)
467 }
468
469 pub fn set_index_buffer(
470 &self,
471 pass: GpuId,
472 buffer: GpuId,
473 offset: u64,
474 format: IndexFormat,
475 size: Option<u64>,
476 ) -> Result<(), String> {
477 set_index_buffer(pass, buffer, offset, format, size)
478 }
479
480 pub fn draw(&self, pass: GpuId, vertices: u32, instances: u32) -> Result<(), String> {
481 draw(pass, vertices, instances)
482 }
483
484 pub fn draw_indexed(&self, pass: GpuId, indices: u32, instances: u32) -> Result<(), String> {
485 draw_indexed(pass, indices, instances)
486 }
487
488 pub fn begin_compute_pass(&self, encoder: GpuId) -> Result<(), String> {
491 begin_compute_pass(encoder)
492 }
493
494 pub fn end_compute_pass(&self, pass: GpuId) -> Result<(), String> {
495 end_compute_pass(pass)
496 }
497
498 pub fn set_compute_pipeline(&self, pass: GpuId, pipeline: GpuId) -> Result<(), String> {
499 set_compute_pipeline(pass, pipeline)
500 }
501
502 pub fn dispatch(&self, pass: GpuId, x: u32, y: u32, z: u32) -> Result<(), String> {
503 dispatch(pass, x, y, z)
504 }
505
506 pub fn copy_buffer_to_buffer(&self, cmd: CopyBufferToBuffer) -> Result<(), String> {
509 copy_buffer_to_buffer(cmd)
510 }
511
512 pub fn copy_buffer_to_texture(&self, cmd: CopyBufferToTexture) -> Result<(), String> {
513 copy_buffer_to_texture(cmd)
514 }
515
516 pub fn copy_texture_to_buffer(&self, cmd: CopyTextureToBuffer) -> Result<(), String> {
517 copy_texture_to_buffer(cmd)
518 }
519}