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
33pub fn begin_frame() -> Result<(), String> {
34    let pack = host_call(HostCall::Gpu(GpuCall::BeginFrame));
35    expect_gpu_none(unpack_gpu_response(pack)?)
36}
37
38pub fn get_surface_format() -> Result<TextureFormat, String> {
39    let pack = host_call(HostCall::Gpu(GpuCall::GetSurfaceFormat));
40    expect_gpu_texture_format(unpack_gpu_response(pack)?)
41}
42
43pub fn get_current_surface_texture() -> Result<GpuId, String> {
44    let pack = host_call(HostCall::Gpu(GpuCall::GetCurrentSurfaceTexture));
45    expect_gpu_i64(unpack_gpu_response(pack)?)
46}
47
48pub fn present() -> Result<(), String> {
49    let pack = host_call(HostCall::Gpu(GpuCall::Present));
50    expect_gpu_none(unpack_gpu_response(pack)?)
51}
52
53pub fn create_buffer(
54    size: u64,
55    usage: BufferUsage,
56    mapped_at_creation: bool,
57) -> Result<GpuId, String> {
58    let pack = host_call(HostCall::Gpu(GpuCall::CreateBuffer(CreateBuffer {
59        size,
60        usage,
61        mapped_at_creation,
62    })));
63    expect_gpu_i64(unpack_gpu_response(pack)?)
64}
65
66pub fn write_buffer(buffer: GpuId, offset: u64, data: Vec<u8>) -> Result<(), String> {
67    let pack = host_call(HostCall::Gpu(GpuCall::WriteBuffer(WriteBuffer {
68        buffer,
69        offset,
70        data,
71    })));
72    expect_gpu_none(unpack_gpu_response(pack)?)
73}
74
75pub fn destroy_buffer(id: GpuId) -> Result<(), String> {
76    let pack = host_call(HostCall::Gpu(GpuCall::DestroyBuffer { id }));
77    expect_gpu_none(unpack_gpu_response(pack)?)
78}
79
80pub fn create_texture(desc: CreateTexture) -> Result<GpuId, String> {
81    let pack = host_call(HostCall::Gpu(GpuCall::CreateTexture(desc)));
82    expect_gpu_i64(unpack_gpu_response(pack)?)
83}
84
85pub fn create_texture_view(desc: CreateTextureView) -> Result<GpuId, String> {
86    let pack = host_call(HostCall::Gpu(GpuCall::CreateTextureView(desc)));
87    expect_gpu_i64(unpack_gpu_response(pack)?)
88}
89
90pub fn destroy_texture(id: GpuId) -> Result<(), String> {
91    let pack = host_call(HostCall::Gpu(GpuCall::DestroyTexture { id }));
92    expect_gpu_none(unpack_gpu_response(pack)?)
93}
94
95pub fn create_shader_module(wgsl_source: String) -> Result<GpuId, String> {
96    let pack = host_call(HostCall::Gpu(GpuCall::CreateShaderModule(
97        CreateShaderModule { wgsl_source },
98    )));
99    expect_gpu_i64(unpack_gpu_response(pack)?)
100}
101
102pub fn create_bind_group_layout(desc: CreateBindGroupLayout) -> Result<GpuId, String> {
103    let pack = host_call(HostCall::Gpu(GpuCall::CreateBindGroupLayout(desc)));
104    expect_gpu_i64(unpack_gpu_response(pack)?)
105}
106
107pub fn create_bind_group(desc: CreateBindGroup) -> Result<GpuId, String> {
108    let pack = host_call(HostCall::Gpu(GpuCall::CreateBindGroup(desc)));
109    expect_gpu_i64(unpack_gpu_response(pack)?)
110}
111
112pub fn create_pipeline_layout(desc: CreatePipelineLayout) -> Result<GpuId, String> {
113    let pack = host_call(HostCall::Gpu(GpuCall::CreatePipelineLayout(desc)));
114    expect_gpu_i64(unpack_gpu_response(pack)?)
115}
116
117pub fn create_render_pipeline(desc: CreateRenderPipeline) -> Result<GpuId, String> {
118    let pack = host_call(HostCall::Gpu(GpuCall::CreateRenderPipeline(desc)));
119    expect_gpu_i64(unpack_gpu_response(pack)?)
120}
121
122pub fn create_compute_pipeline(desc: CreateComputePipeline) -> Result<GpuId, String> {
123    let pack = host_call(HostCall::Gpu(GpuCall::CreateComputePipeline(desc)));
124    expect_gpu_i64(unpack_gpu_response(pack)?)
125}
126
127pub fn create_command_encoder() -> Result<GpuId, String> {
128    let pack = host_call(HostCall::Gpu(GpuCall::CreateCommandEncoder));
129    expect_gpu_i64(unpack_gpu_response(pack)?)
130}
131
132pub fn submit(encoder: GpuId) -> Result<(), String> {
133    let pack = host_call(HostCall::Gpu(GpuCall::Submit { encoder }));
134    expect_gpu_none(unpack_gpu_response(pack)?)
135}
136
137pub fn begin_render_pass(desc: BeginRenderPass) -> Result<GpuId, String> {
138    let pack = host_call(HostCall::Gpu(GpuCall::BeginRenderPass(desc)));
139    expect_gpu_i64(unpack_gpu_response(pack)?)
140}
141
142pub fn end_render_pass(pass: GpuId) -> Result<(), String> {
143    let pack = host_call(HostCall::Gpu(GpuCall::EndRenderPass { pass }));
144    expect_gpu_none(unpack_gpu_response(pack)?)
145}
146
147pub fn set_render_pipeline(pass: GpuId, pipeline: GpuId) -> Result<(), String> {
148    let pack = host_call(HostCall::Gpu(GpuCall::SetRenderPipeline { pass, pipeline }));
149    expect_gpu_none(unpack_gpu_response(pack)?)
150}
151
152pub fn set_bind_group(pass: GpuId, index: u32, bind_group: GpuId) -> Result<(), String> {
153    let pack = host_call(HostCall::Gpu(GpuCall::SetBindGroup {
154        pass,
155        index,
156        bind_group,
157    }));
158    expect_gpu_none(unpack_gpu_response(pack)?)
159}
160
161pub fn set_vertex_buffer(
162    pass: GpuId,
163    buffer: GpuId,
164    offset: u64,
165    slot: u32,
166    size: Option<u64>,
167) -> Result<(), String> {
168    let pack = host_call(HostCall::Gpu(GpuCall::SetVertexBuffer(SetVertexBuffer {
169        pass,
170        buffer,
171        offset,
172        slot,
173        size,
174    })));
175    expect_gpu_none(unpack_gpu_response(pack)?)
176}
177
178pub fn set_index_buffer(
179    pass: GpuId,
180    buffer: GpuId,
181    offset: u64,
182    format: IndexFormat,
183    size: Option<u64>,
184) -> Result<(), String> {
185    let pack = host_call(HostCall::Gpu(GpuCall::SetIndexBuffer(SetIndexBuffer {
186        pass,
187        buffer,
188        offset,
189        index_format: format,
190        size,
191    })));
192    expect_gpu_none(unpack_gpu_response(pack)?)
193}
194
195pub fn draw(pass: GpuId, vertices: u32, instances: u32) -> Result<(), String> {
196    let pack = host_call(HostCall::Gpu(GpuCall::Draw(Draw {
197        pass,
198        vertices,
199        instances,
200        first_vertex: 0,
201        first_instance: 0,
202    })));
203    expect_gpu_none(unpack_gpu_response(pack)?)
204}
205
206pub fn draw_indexed(pass: GpuId, indices: u32, instances: u32) -> Result<(), String> {
207    let pack = host_call(HostCall::Gpu(GpuCall::DrawIndexed(DrawIndexed {
208        pass,
209        indices,
210        instances,
211        first_index: 0,
212        base_vertex: 0,
213        first_instance: 0,
214    })));
215    expect_gpu_none(unpack_gpu_response(pack)?)
216}
217
218// compute pass
219
220pub fn begin_compute_pass(encoder: GpuId) -> Result<(), String> {
221    let pack = host_call(HostCall::Gpu(GpuCall::BeginComputePass { encoder }));
222    expect_gpu_none(unpack_gpu_response(pack)?)
223}
224
225pub fn end_compute_pass(pass: GpuId) -> Result<(), String> {
226    let pack = host_call(HostCall::Gpu(GpuCall::EndComputePass { pass }));
227    expect_gpu_none(unpack_gpu_response(pack)?)
228}
229
230pub fn set_compute_pipeline(pass: GpuId, pipeline: GpuId) -> Result<(), String> {
231    let pack = host_call(HostCall::Gpu(GpuCall::SetComputePipeline {
232        pass,
233        pipeline,
234    }));
235    expect_gpu_none(unpack_gpu_response(pack)?)
236}
237
238pub fn dispatch(pass: GpuId, x: u32, y: u32, z: u32) -> Result<(), String> {
239    let pack = host_call(HostCall::Gpu(GpuCall::Dispatch { pass, x, y, z }));
240    expect_gpu_none(unpack_gpu_response(pack)?)
241}
242
243// Copies
244
245pub fn copy_buffer_to_buffer(cmd: CopyBufferToBuffer) -> Result<(), String> {
246    let pack = host_call(HostCall::Gpu(GpuCall::CopyBufferToBuffer(cmd)));
247    expect_gpu_none(unpack_gpu_response(pack)?)
248}
249
250pub fn copy_buffer_to_texture(cmd: CopyBufferToTexture) -> Result<(), String> {
251    let pack = host_call(HostCall::Gpu(GpuCall::CopyBufferToTexture(cmd)));
252    expect_gpu_none(unpack_gpu_response(pack)?)
253}
254
255pub fn copy_texture_to_buffer(cmd: CopyTextureToBuffer) -> Result<(), String> {
256    let pack = host_call(HostCall::Gpu(GpuCall::CopyTextureToBuffer(cmd)));
257    expect_gpu_none(unpack_gpu_response(pack)?)
258}
259
260pub struct Buffer(pub GpuId);
261pub struct RenderPipeline(pub GpuId);
262pub struct BindGroup(pub GpuId);
263pub struct Texture(pub GpuId);
264
265pub struct Gpu;
266
267impl Gpu {
268    pub fn begin_frame(&self) -> Result<(), String> {
269        begin_frame()
270    }
271
272    pub fn get_surface_format(&self) -> Result<TextureFormat, String> {
273        get_surface_format()
274    }
275
276    pub fn get_current_surface_texture(&self) -> Result<GpuId, String> {
277        get_current_surface_texture()
278    }
279
280    pub fn present(&self) -> Result<(), String> {
281        present()
282    }
283
284    pub fn create_buffer(
285        &self,
286        size: u64,
287        usage: BufferUsage,
288        mapped_at_creation: bool,
289    ) -> Result<GpuId, String> {
290        create_buffer(size, usage, mapped_at_creation)
291    }
292
293    pub fn write_buffer(&self, buffer: GpuId, offset: u64, data: Vec<u8>) -> Result<(), String> {
294        write_buffer(buffer, offset, data)
295    }
296
297    pub fn destroy_buffer(&self, id: GpuId) -> Result<(), String> {
298        destroy_buffer(id)
299    }
300
301    pub fn create_texture(&self, desc: CreateTexture) -> Result<GpuId, String> {
302        create_texture(desc)
303    }
304
305    pub fn create_texture_view(&self, desc: CreateTextureView) -> Result<GpuId, String> {
306        create_texture_view(desc)
307    }
308
309    pub fn destroy_texture(&self, id: GpuId) -> Result<(), String> {
310        destroy_texture(id)
311    }
312
313    pub fn create_shader_module(&self, wgsl_source: String) -> Result<GpuId, String> {
314        create_shader_module(wgsl_source)
315    }
316
317    pub fn create_bind_group_layout(&self, desc: CreateBindGroupLayout) -> Result<GpuId, String> {
318        create_bind_group_layout(desc)
319    }
320
321    pub fn create_bind_group(&self, desc: CreateBindGroup) -> Result<GpuId, String> {
322        create_bind_group(desc)
323    }
324
325    pub fn create_pipeline_layout(&self, desc: CreatePipelineLayout) -> Result<GpuId, String> {
326        create_pipeline_layout(desc)
327    }
328
329    pub fn create_render_pipeline(&self, desc: CreateRenderPipeline) -> Result<GpuId, String> {
330        create_render_pipeline(desc)
331    }
332
333    pub fn create_compute_pipeline(&self, desc: CreateComputePipeline) -> Result<GpuId, String> {
334        create_compute_pipeline(desc)
335    }
336
337    pub fn create_command_encoder(&self) -> Result<GpuId, String> {
338        create_command_encoder()
339    }
340
341    pub fn submit(&self, encoder: GpuId) -> Result<(), String> {
342        submit(encoder)
343    }
344
345    pub fn begin_render_pass(&self, desc: BeginRenderPass) -> Result<GpuId, String> {
346        begin_render_pass(desc)
347    }
348
349    pub fn end_render_pass(&self, pass: GpuId) -> Result<(), String> {
350        end_render_pass(pass)
351    }
352
353    pub fn set_render_pipeline(&self, pass: GpuId, pipeline: GpuId) -> Result<(), String> {
354        set_render_pipeline(pass, pipeline)
355    }
356
357    pub fn set_bind_group(&self, pass: GpuId, index: u32, bind_group: GpuId) -> Result<(), String> {
358        set_bind_group(pass, index, bind_group)
359    }
360
361    pub fn set_vertex_buffer(
362        &self,
363        pass: GpuId,
364        buffer: GpuId,
365        offset: u64,
366        slot: u32,
367        size: Option<u64>,
368    ) -> Result<(), String> {
369        set_vertex_buffer(pass, buffer, offset, slot, size)
370    }
371
372    pub fn set_index_buffer(
373        &self,
374        pass: GpuId,
375        buffer: GpuId,
376        offset: u64,
377        format: IndexFormat,
378        size: Option<u64>,
379    ) -> Result<(), String> {
380        set_index_buffer(pass, buffer, offset, format, size)
381    }
382
383    pub fn draw(&self, pass: GpuId, vertices: u32, instances: u32) -> Result<(), String> {
384        draw(pass, vertices, instances)
385    }
386
387    pub fn draw_indexed(&self, pass: GpuId, indices: u32, instances: u32) -> Result<(), String> {
388        draw_indexed(pass, indices, instances)
389    }
390
391    // compute pass
392
393    pub fn begin_compute_pass(&self, encoder: GpuId) -> Result<(), String> {
394        begin_compute_pass(encoder)
395    }
396
397    pub fn end_compute_pass(&self, pass: GpuId) -> Result<(), String> {
398        end_compute_pass(pass)
399    }
400
401    pub fn set_compute_pipeline(&self, pass: GpuId, pipeline: GpuId) -> Result<(), String> {
402        set_compute_pipeline(pass, pipeline)
403    }
404
405    pub fn dispatch(&self, pass: GpuId, x: u32, y: u32, z: u32) -> Result<(), String> {
406        dispatch(pass, x, y, z)
407    }
408
409    // Copies
410
411    pub fn copy_buffer_to_buffer(&self, cmd: CopyBufferToBuffer) -> Result<(), String> {
412        copy_buffer_to_buffer(cmd)
413    }
414
415    pub fn copy_buffer_to_texture(&self, cmd: CopyBufferToTexture) -> Result<(), String> {
416        copy_buffer_to_texture(cmd)
417    }
418
419    pub fn copy_texture_to_buffer(&self, cmd: CopyTextureToBuffer) -> Result<(), String> {
420        copy_texture_to_buffer(cmd)
421    }
422}