forked from 1b-agent/opencadstudio-upstream
revert(web): drop vendored iced renderer
Keep iced_wgpu external and leave the WebGPU storage-buffer optimization out of scope.
This commit is contained in:
1 parent
deec48ad99
commit
fe49cc8eb5
46 files changed
+47
-9347
No files matched your search
@@ -47,7 +47,7 @@ pub struct Pipeline {
|
||||
/// Used to draw ghost copies of selected wires through occluding geometry.
|
||||
wire_xray_pipeline: wgpu::RenderPipeline,
|
||||
/// Layout for the per-wire `WireConst` storage buffer (group 1 of the wire /
|
||||
/// xray pipelines). `Some` on native/WebGPU fast paths; `None` in packed
|
||||
/// xray pipelines). `Some` only on the fast native path; `None` in packed
|
||||
/// compatibility mode. Passed to `WireGpu::from_run` / `from_batch`.
|
||||
pub(crate) wire_const_bgl: Option<wgpu::BindGroupLayout>,
|
||||
wipeout_pipeline: wgpu::RenderPipeline,
|
||||
@@ -338,8 +338,8 @@ impl Pipeline {
|
||||
});
|
||||
|
||||
// ── Wire pipeline ──────────────────────────────────────────────────
|
||||
// Select once per device. Native and WebGPU hoist shared constants into
|
||||
// storage when limits allow; WebGL2/compat keeps packed attributes.
|
||||
// Select once per device. The fast native path hoists shared constants
|
||||
// into storage; compatibility mode keeps them in 10 packed attributes.
|
||||
let wire_mode = wire_gpu::WirePipelineMode::select(device);
|
||||
let renderer_mode_name =
|
||||
if wire_mode.uses_storage() { "fast-storage" } else { "packed-compat" };
|
||||
@@ -357,9 +357,12 @@ impl Pipeline {
|
||||
renderer_mode_name,
|
||||
device.limits().max_storage_buffers_per_shader_stage
|
||||
);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let wire_const_bgl = wire_mode
|
||||
.uses_storage()
|
||||
.then(|| wire_gpu::WireConst::bind_group_layout(device));
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let wire_const_bgl: Option<wgpu::BindGroupLayout> = None;
|
||||
let mut wire_bgls: Vec<&wgpu::BindGroupLayout> = vec![&frame_bgl];
|
||||
if let Some(bgl) = &wire_const_bgl {
|
||||
wire_bgls.push(bgl);
|
||||
@@ -376,6 +379,7 @@ impl Pipeline {
|
||||
let wire_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("wire.shader"),
|
||||
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(match wire_mode {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
wire_gpu::WirePipelineMode::IndexedStorage => {
|
||||
include_str!("../../shaders/wire_indexed.wgsl")
|
||||
}
|
||||
|
||||
@@ -58,17 +58,18 @@ fn instance_buffer_mapped<T: bytemuck::Pod>(
|
||||
|
||||
// ── Instance layout ───────────────────────────────────────────────────────
|
||||
|
||||
// ── WebGPU/native: slim per-segment instance + shared constants ─────────────
|
||||
// ── Native: slim per-segment instance + shared per-wire constants ───────────
|
||||
//
|
||||
// Every segment of a wire used to carry the wire's color / line-weight / dash
|
||||
// pattern / draw-depth (~44 B) on each instance — re-fetched once per segment
|
||||
// even though it's constant along the wire. On storage-capable adapters we hoist those into a
|
||||
// even though it's constant along the wire. On native we hoist those into a
|
||||
// per-wire `WireConst` storage buffer indexed by `wire_id`, so the instance
|
||||
// keeps only the per-segment data (endpoints + arc-length distances). Cuts the
|
||||
// instance from 104 B to one 64-byte cache line and removes the redundant
|
||||
// per-segment re-fetch of the shared constants. WebGL2 has no vertex-stage
|
||||
// storage buffers, so the wasm build below keeps the original self-contained
|
||||
// fat instance.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct WireInstance {
|
||||
@@ -86,6 +87,8 @@ pub struct WireInstance {
|
||||
/// exactly one 64-byte cache line.
|
||||
pub taper_ratio: [u16; 2],
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl WireInstance {
|
||||
pub fn layout<'a>() -> wgpu::VertexBufferLayout<'a> {
|
||||
// Must match `InstanceIn` in wire_indexed.wgsl.
|
||||
@@ -107,10 +110,11 @@ impl WireInstance {
|
||||
}
|
||||
}
|
||||
|
||||
/// Per-wire constants shared by every segment of a wire. std430
|
||||
/// Per-wire constants shared by every segment of a wire (native only). std430
|
||||
/// layout: three vec4 then eight scalars = 80 B, matching `WireConst` in
|
||||
/// wire_indexed.wgsl. `align_end` / `align_total` carry the "A"-type endpoint
|
||||
/// alignment (see `wire_distances`); 0.0 total = no alignment.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct WireConst {
|
||||
@@ -130,6 +134,8 @@ pub struct WireConst {
|
||||
pub _pad1: f32,
|
||||
pub _pad2: f32,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl WireConst {
|
||||
/// Bind-group layout for the per-wire storage buffer (group 1 of the wire /
|
||||
/// xray pipelines). Read-only storage, visible to the vertex stage.
|
||||
@@ -152,8 +158,8 @@ impl WireConst {
|
||||
|
||||
// ── Packed compatibility instance (no vertex-stage storage) ────────────────
|
||||
//
|
||||
// WebGL2 and limited native adapters use this layout. WebGPU selects the
|
||||
// indexed storage path when its reported limits satisfy the same requirement.
|
||||
// Web always uses this layout. Native selects it at runtime for adapters whose
|
||||
// storage-buffer limits are insufficient, or when --compat-renderer is set.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
pub struct PackedWireInstance {
|
||||
@@ -218,15 +224,21 @@ impl PackedWireInstance {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub type WireInstance = PackedWireInstance;
|
||||
|
||||
/// Wire and hatch pipelines switch together: the fast path uses storage
|
||||
/// buffers; the compatibility path carries wire constants in packed vertex
|
||||
/// attributes and hatch data in a texture.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum WirePipelineMode {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
IndexedStorage,
|
||||
Packed,
|
||||
}
|
||||
fn select_pipeline(max_storage_buffers_per_stage: u32, forced: bool) -> WirePipelineMode {
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn select_native_pipeline(max_storage_buffers_per_stage: u32, forced: bool) -> WirePipelineMode {
|
||||
const REQUIRED_STORAGE_BUFFERS_PER_STAGE: u32 = 5;
|
||||
if forced || max_storage_buffers_per_stage < REQUIRED_STORAGE_BUFFERS_PER_STAGE {
|
||||
WirePipelineMode::Packed
|
||||
@@ -237,15 +249,23 @@ fn select_pipeline(max_storage_buffers_per_stage: u32, forced: bool) -> WirePipe
|
||||
|
||||
impl WirePipelineMode {
|
||||
pub fn select(device: &wgpu::Device) -> Self {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let forced = crate::cli::gui_config().compat_renderer;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let forced = false;
|
||||
select_pipeline(device.limits().max_storage_buffers_per_shader_stage, forced)
|
||||
{
|
||||
let _ = device;
|
||||
Self::Packed
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
select_native_pipeline(
|
||||
device.limits().max_storage_buffers_per_shader_stage,
|
||||
crate::cli::gui_config().compat_renderer,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uses_storage(self) -> bool {
|
||||
match self {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Self::IndexedStorage => true,
|
||||
Self::Packed => false,
|
||||
}
|
||||
@@ -253,6 +273,7 @@ impl WirePipelineMode {
|
||||
|
||||
pub fn layout<'a>(self) -> wgpu::VertexBufferLayout<'a> {
|
||||
match self {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Self::IndexedStorage => WireInstance::layout(),
|
||||
Self::Packed => PackedWireInstance::layout(),
|
||||
}
|
||||
@@ -473,8 +494,9 @@ fn emit_wire_packed(
|
||||
instances
|
||||
}
|
||||
|
||||
/// Storage path: emit slim per-segment instances (positions + distances + `wire_id`)
|
||||
/// Native: emit slim per-segment instances (positions + distances + `wire_id`)
|
||||
/// plus the one `WireConst` record every segment of this wire shares.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) fn emit_wire_native(
|
||||
wire: &WireModel,
|
||||
wire_id: u32,
|
||||
@@ -557,10 +579,11 @@ pub(crate) fn wire_draw_depth(
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the shared per-wire `WireConst` storage buffer and its bind group.
|
||||
/// All instance-buffer chunks from one build reference the same
|
||||
/// Build the shared per-wire `WireConst` storage buffer and its bind group
|
||||
/// (native only). All instance-buffer chunks from one build reference the same
|
||||
/// buffer via their global `wire_id`, so a single bind group is cloned into
|
||||
/// each chunk.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn build_const_bind_group(
|
||||
device: &wgpu::Device,
|
||||
bgl: &wgpu::BindGroupLayout,
|
||||
@@ -654,6 +677,7 @@ impl WireGpu {
|
||||
mesh_edge: bool,
|
||||
const_bgl: Option<&wgpu::BindGroupLayout>,
|
||||
) -> Vec<Self> {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if let Some(const_bgl) = const_bgl {
|
||||
const MAX_INSTANCES: usize =
|
||||
268_435_456 / std::mem::size_of::<WireInstance>();
|
||||
@@ -745,6 +769,7 @@ impl WireGpu {
|
||||
if total_segs == 0 {
|
||||
return vec![];
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if let Some(const_bgl) = const_bgl {
|
||||
// GPU max buffer size is 256 MB; chunk to stay within the limit.
|
||||
const MAX_INSTANCES: usize =
|
||||
|
||||
@@ -436,10 +436,7 @@ impl shader::Primitive for Primitive {
|
||||
// the whole wire buffer. Only for the scissor-free, mesh-free
|
||||
// (single-batch) Model set; scissored paper viewports and mixed
|
||||
// 2D/3D sets fall through to the shared batched path below.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let mut arena_served = false;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let arena_served = false;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let _perf = crate::perf::enabled();
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
||||
Reference in new issue
Block a user