Skip to main content

interstice_sdk_core/host_calls/
gpu.rs

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
275// compute pass
276
277pub 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
300// Copies
301
302pub 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    // compute pass
489
490    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    // Copies
507
508    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}