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
218pub 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
243pub 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 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 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}