Skip to content

Commit 484b182

Browse files
committed
[refactor] instance, gpu, and render passes.
1 parent df6c102 commit 484b182

File tree

11 files changed

+707
-351
lines changed

11 files changed

+707
-351
lines changed

crates/lambda-rs-platform/src/wgpu/bind.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use wgpu;
1010

1111
use crate::wgpu::{
1212
buffer,
13-
Gpu,
13+
gpu::Gpu,
1414
};
1515

1616
#[derive(Debug)]

crates/lambda-rs-platform/src/wgpu/buffer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use wgpu::{
88
util::DeviceExt,
99
};
1010

11-
use crate::wgpu::Gpu;
11+
use crate::wgpu::gpu::Gpu;
1212

1313
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1414
/// Index format for indexed drawing.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//! Command encoding abstractions around `wgpu::CommandEncoder`, `wgpu::RenderPass`,
2+
//! and `wgpu::CommandBuffer` that expose only the operations needed by the
3+
//! engine while keeping raw `wgpu` types crate-internal.
4+
5+
use super::gpu;
6+
7+
#[derive(Debug)]
8+
/// Thin wrapper around `wgpu::CommandEncoder` with convenience helpers.
9+
pub struct CommandEncoder {
10+
raw: wgpu::CommandEncoder,
11+
}
12+
13+
#[derive(Debug)]
14+
/// Wrapper around `wgpu::CommandBuffer` to avoid exposing raw types upstream.
15+
pub struct CommandBuffer {
16+
raw: wgpu::CommandBuffer,
17+
}
18+
19+
impl CommandBuffer {
20+
pub(crate) fn into_raw(self) -> wgpu::CommandBuffer {
21+
self.raw
22+
}
23+
}
24+
25+
impl CommandEncoder {
26+
/// Create a new command encoder with an optional label.
27+
pub fn new(gpu: &gpu::Gpu, label: Option<&str>) -> Self {
28+
let raw = gpu
29+
.device()
30+
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label });
31+
return Self { raw };
32+
}
33+
34+
/// Internal helper for beginning a render pass. Used by the render pass builder.
35+
pub(crate) fn begin_render_pass_raw<'view>(
36+
&'view mut self,
37+
desc: &wgpu::RenderPassDescriptor<'view>,
38+
) -> wgpu::RenderPass<'view> {
39+
return self.raw.begin_render_pass(desc);
40+
}
41+
42+
/// Finish recording and return the command buffer.
43+
pub fn finish(self) -> CommandBuffer {
44+
return CommandBuffer {
45+
raw: self.raw.finish(),
46+
};
47+
}
48+
}
49+
50+
// RenderPass wrapper and its methods now live under `wgpu::render_pass`.

crates/lambda-rs-platform/src/wgpu/gpu.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use pollster::block_on;
22

33
use super::{
4+
command::CommandBuffer,
5+
instance::Instance,
46
surface::Surface,
5-
Instance,
67
};
78

89
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -239,7 +240,7 @@ impl Gpu {
239240
/// Submit one or more command buffers to the device queue.
240241
pub fn submit<I>(&self, list: I)
241242
where
242-
I: IntoIterator<Item = super::CommandBuffer>,
243+
I: IntoIterator<Item = CommandBuffer>,
243244
{
244245
let iter = list.into_iter().map(|cb| cb.into_raw());
245246
self.queue.submit(iter);
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
//! Instance abstractions and type wrappers to avoid leaking raw `wgpu` types
2+
//! at higher layers. This keeps the platform crate free to evolve with `wgpu`
3+
//! while presenting a stable surface to the engine.
4+
5+
use pollster::block_on;
6+
7+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8+
/// Wrapper over `wgpu::Backends` as a bitset.
9+
pub struct Backends(wgpu::Backends);
10+
11+
impl Backends {
12+
/// Primary desktop backends (Vulkan/Metal/DX12) per `wgpu` defaults.
13+
pub const PRIMARY: Backends = Backends(wgpu::Backends::PRIMARY);
14+
/// Vulkan backend.
15+
pub const VULKAN: Backends = Backends(wgpu::Backends::VULKAN);
16+
/// Metal backend (macOS/iOS).
17+
pub const METAL: Backends = Backends(wgpu::Backends::METAL);
18+
/// DirectX 12 backend (Windows).
19+
pub const DX12: Backends = Backends(wgpu::Backends::DX12);
20+
/// OpenGL / WebGL backend.
21+
pub const GL: Backends = Backends(wgpu::Backends::GL);
22+
/// Browser WebGPU backend.
23+
pub const BROWSER_WEBGPU: Backends = Backends(wgpu::Backends::BROWSER_WEBGPU);
24+
25+
pub(crate) fn to_wgpu(self) -> wgpu::Backends {
26+
self.0
27+
}
28+
}
29+
30+
impl Default for Backends {
31+
fn default() -> Self {
32+
return Backends::PRIMARY;
33+
}
34+
}
35+
36+
impl std::ops::BitOr for Backends {
37+
type Output = Backends;
38+
fn bitor(self, rhs: Backends) -> Backends {
39+
return Backends(self.0 | rhs.0);
40+
}
41+
}
42+
43+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44+
/// Wrapper over `wgpu::InstanceFlags` as a bitset.
45+
pub struct InstanceFlags(wgpu::InstanceFlags);
46+
47+
impl InstanceFlags {
48+
/// Validation flags (debugging and validation).
49+
pub const VALIDATION: InstanceFlags =
50+
InstanceFlags(wgpu::InstanceFlags::VALIDATION);
51+
/// Enable additional debugging features where available.
52+
pub const DEBUG: InstanceFlags = InstanceFlags(wgpu::InstanceFlags::DEBUG);
53+
54+
pub(crate) fn to_wgpu(self) -> wgpu::InstanceFlags {
55+
self.0
56+
}
57+
}
58+
59+
impl Default for InstanceFlags {
60+
fn default() -> Self {
61+
return InstanceFlags(wgpu::InstanceFlags::default());
62+
}
63+
}
64+
65+
impl std::ops::BitOr for InstanceFlags {
66+
type Output = InstanceFlags;
67+
fn bitor(self, rhs: InstanceFlags) -> InstanceFlags {
68+
return InstanceFlags(self.0 | rhs.0);
69+
}
70+
}
71+
72+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
73+
/// Which DX12 shader compiler to use on Windows platforms.
74+
pub enum Dx12Compiler {
75+
Fxc,
76+
}
77+
78+
impl Dx12Compiler {
79+
pub(crate) fn to_wgpu(self) -> wgpu::Dx12Compiler {
80+
return match self {
81+
Dx12Compiler::Fxc => wgpu::Dx12Compiler::Fxc,
82+
};
83+
}
84+
}
85+
86+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
87+
/// OpenGL ES 3 minor version (used by GL/Web targets).
88+
pub enum Gles3MinorVersion {
89+
Automatic,
90+
Version0,
91+
Version1,
92+
Version2,
93+
}
94+
95+
impl Gles3MinorVersion {
96+
pub(crate) fn to_wgpu(self) -> wgpu::Gles3MinorVersion {
97+
return match self {
98+
Gles3MinorVersion::Automatic => wgpu::Gles3MinorVersion::Automatic,
99+
Gles3MinorVersion::Version0 => wgpu::Gles3MinorVersion::Version0,
100+
Gles3MinorVersion::Version1 => wgpu::Gles3MinorVersion::Version1,
101+
Gles3MinorVersion::Version2 => wgpu::Gles3MinorVersion::Version2,
102+
};
103+
}
104+
}
105+
106+
#[derive(Debug, Clone)]
107+
/// Builder for creating a `wgpu::Instance` with consistent defaults.
108+
///
109+
/// Defaults to primary backends and no special flags. Options map to
110+
/// `wgpu::InstanceDescriptor` internally without leaking raw types.
111+
pub struct InstanceBuilder {
112+
label: Option<String>,
113+
backends: Backends,
114+
flags: InstanceFlags,
115+
// Keep backend options/memory thresholds internal; expose focused knobs via
116+
// typed methods to avoid leaking raw structs.
117+
backend_options: wgpu::BackendOptions,
118+
memory_budget_thresholds: wgpu::MemoryBudgetThresholds,
119+
}
120+
121+
impl InstanceBuilder {
122+
/// Construct a new builder with Lambda defaults.
123+
pub fn new() -> Self {
124+
Self {
125+
label: None,
126+
backends: Backends::PRIMARY,
127+
flags: InstanceFlags::default(),
128+
backend_options: wgpu::BackendOptions::default(),
129+
memory_budget_thresholds: wgpu::MemoryBudgetThresholds::default(),
130+
}
131+
}
132+
133+
/// Attach a debug label to the instance.
134+
pub fn with_label(mut self, label: &str) -> Self {
135+
self.label = Some(label.to_string());
136+
self
137+
}
138+
139+
/// Select which graphics backends to enable.
140+
pub fn with_backends(mut self, backends: Backends) -> Self {
141+
self.backends = backends;
142+
self
143+
}
144+
145+
/// Set additional instance flags (e.g., debugging/validation).
146+
pub fn with_flags(mut self, flags: InstanceFlags) -> Self {
147+
self.flags = flags;
148+
self
149+
}
150+
151+
/// Choose a DX12 shader compiler variant when on Windows.
152+
pub fn with_dx12_shader_compiler(mut self, compiler: Dx12Compiler) -> Self {
153+
self.backend_options.dx12.shader_compiler = compiler.to_wgpu();
154+
self
155+
}
156+
157+
/// Configure the GLES minor version for WebGL/OpenGL ES targets.
158+
pub fn with_gles_minor_version(mut self, version: Gles3MinorVersion) -> Self {
159+
self.backend_options.gl.gles_minor_version = version.to_wgpu();
160+
self
161+
}
162+
163+
/// Build the `Instance` wrapper from the accumulated options.
164+
pub fn build(self) -> Instance {
165+
let descriptor = wgpu::InstanceDescriptor {
166+
backends: self.backends.to_wgpu(),
167+
flags: self.flags.to_wgpu(),
168+
memory_budget_thresholds: self.memory_budget_thresholds,
169+
backend_options: self.backend_options,
170+
};
171+
172+
Instance {
173+
label: self.label,
174+
instance: wgpu::Instance::new(&descriptor),
175+
}
176+
}
177+
}
178+
179+
#[derive(Debug)]
180+
/// Thin wrapper over `wgpu::Instance` that preserves a user label and exposes
181+
/// a blocking `request_adapter` convenience.
182+
pub struct Instance {
183+
pub(crate) label: Option<String>,
184+
pub(crate) instance: wgpu::Instance,
185+
}
186+
187+
impl Instance {
188+
/// Borrow the underlying `wgpu::Instance`.
189+
pub fn raw(&self) -> &wgpu::Instance {
190+
&self.instance
191+
}
192+
193+
/// Return the optional label attached at construction time.
194+
pub fn label(&self) -> Option<&str> {
195+
self.label.as_deref()
196+
}
197+
198+
/// Request a compatible GPU adapter synchronously.
199+
pub(crate) fn request_adapter<'surface, 'window>(
200+
&self,
201+
options: &wgpu::RequestAdapterOptions<'surface, 'window>,
202+
) -> Result<wgpu::Adapter, wgpu::RequestAdapterError> {
203+
block_on(self.instance.request_adapter(options))
204+
}
205+
}
206+
207+
#[cfg(test)]
208+
mod tests {
209+
use super::*;
210+
211+
#[test]
212+
fn instance_builder_sets_label() {
213+
let instance = InstanceBuilder::new().with_label("Test").build();
214+
assert_eq!(instance.label(), Some("Test"));
215+
}
216+
}

0 commit comments

Comments
 (0)