perf(gpui): batch-upload wgpu instances under resource budgets - #8
Conversation
审查者指南Linux WGPU 渲染现在会在每帧批量上传场景的实例数据一次,并复用共享绑定组;同时,基于配置文件和设备感知的水位线限制了缓冲区增长,并在创建渲染器和恢复过程中保留完整的 GPU 预算;着色器布局以及相关文档和测试也已相应更新。 支持预算感知的 WGPU 帧上传时序图sequenceDiagram
participant Scene
participant Renderer as WgpuRenderer
participant Budget as GpuResourceBudget
participant Queue as WGPUQueue
participant Pass as RenderPass
Scene->>Renderer: record_frame(scene, frame_view)
Renderer->>Renderer: frame_instance_bytes(scene)
Renderer->>Budget: next_instance_buffer_capacity(current, required, max_buffer_size)
alt scene exceeds profile/device cap
Budget-->>Renderer: None
Renderer-->>Scene: frame fails
else scene fits budget
Budget-->>Renderer: capacity
Renderer->>Queue: write_buffer(instance_buffer, offsets, primitive arrays)
Renderer->>Renderer: write_instances(scene)
loop scene batches
Renderer->>Pass: draw_instances(bind_group, instance_range)
end
Queue-->>Renderer: submit(encoder)
end
文件级变更
提示和命令与 Sourcery 交互
自定义使用体验访问你的控制面板以:
获取帮助Original review guide in EnglishReviewer's GuideLinux WGPU rendering now bulk-uploads a scene’s instance data once per frame and reuses shared bind groups, while profile- and device-aware watermarks bound buffer growth and preserve the full GPU budget through renderer creation and recovery; shader layouts and documentation/tests were updated accordingly. Sequence diagram for budget-aware WGPU frame uploadsequenceDiagram
participant Scene
participant Renderer as WgpuRenderer
participant Budget as GpuResourceBudget
participant Queue as WGPUQueue
participant Pass as RenderPass
Scene->>Renderer: record_frame(scene, frame_view)
Renderer->>Renderer: frame_instance_bytes(scene)
Renderer->>Budget: next_instance_buffer_capacity(current, required, max_buffer_size)
alt scene exceeds profile/device cap
Budget-->>Renderer: None
Renderer-->>Scene: frame fails
else scene fits budget
Budget-->>Renderer: capacity
Renderer->>Queue: write_buffer(instance_buffer, offsets, primitive arrays)
Renderer->>Renderer: write_instances(scene)
loop scene batches
Renderer->>Pass: draw_instances(bind_group, instance_range)
end
Queue-->>Renderer: submit(encoder)
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
你好——我发现了 2 个问题
面向 AI Agent 的提示
请处理这次代码审查中的评论:
## 单条评论
### 评论 1
<location path="crates/gpui/src/resource_profile.rs" line_range="245-254" />
<code_context>
/// Default: 2 MiB for desktop applications.
pub instance_buffer_initial_size: usize,
+
+ /// Maximum renderer instance buffer capacity in bytes, where supported.
+ ///
+ /// Batch upload sizes the GPU buffer to fit the whole scene at frame start.
+ /// This is the growth ceiling after device limits are applied. Desktop
+ /// matches Zed's 256 MiB native cap; Utility and Minimal stay lower so a
+ /// tray or dialog profile cannot balloon to a full-editor working set.
+ ///
+ /// Values below [`Self::instance_buffer_initial_size`] are raised to that
+ /// initial budget.
+ pub instance_buffer_max_size: usize,
}
</code_context>
<issue_to_address>
**issue (bug_risk):** 向 `GpuResourceBudget` 添加必需的公共字段,会导致现有下游结构体字面量无法编译,因为现在每个字面量都必须提供 `instance_buffer_max_size`。对于直接构造自定义 GPU 预算的调用方而言,这是一个破坏源码兼容性的 API 回归。
**触发条件:** 当应用或下游 crate 使用 `GpuResourceBudget { ... }`,而不是通过更新后的辅助方法来构造它时。
**建议修复:** 提供不破坏兼容性的构造函数/更新路径,或通过带默认值的配置表示形式来保持兼容性;至少应将其记录为有意进行的破坏性 API 变更,并更新所有受支持的下游字面量。
</issue_to_address>
### 评论 2
<location path="crates/gpui-wgpu/src/wgpu_renderer.rs" line_range="1478-1500" />
<code_context>
+ fn create_texture_bind_group(
</code_context>
<issue_to_address>
**nitpick (performance):** 每次 sprite 绘制调用中都会创建一个新的纹理绑定组,因此包含许多图集纹理批次的场景会为每个批次分配并保留一个绑定组,直到命令提交,而不是复用使用相同纹理 ID 的批次的绑定组。这会增加每帧 CPU/GPU 资源的频繁分配与释放,并使针对 sprite 的共享绑定组批处理优化失去作用。
**触发条件:** 当一帧包含许多单色或多色 sprite 批次时,尤其是多个批次使用同一个图集纹理时。
**建议修复:** 在帧的持续期间按 `AtlasTextureId` 缓存纹理绑定组,或将它们与图集纹理元数据一起保留。
</issue_to_address>请帮助我变得更有用!请在每条评论上点击 👍 或 👎,我会利用这些反馈来改进审查结果。
Original comment in English
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="crates/gpui/src/resource_profile.rs" line_range="245-254" />
<code_context>
/// Default: 2 MiB for desktop applications.
pub instance_buffer_initial_size: usize,
+
+ /// Maximum renderer instance buffer capacity in bytes, where supported.
+ ///
+ /// Batch upload sizes the GPU buffer to fit the whole scene at frame start.
+ /// This is the growth ceiling after device limits are applied. Desktop
+ /// matches Zed's 256 MiB native cap; Utility and Minimal stay lower so a
+ /// tray or dialog profile cannot balloon to a full-editor working set.
+ ///
+ /// Values below [`Self::instance_buffer_initial_size`] are raised to that
+ /// initial budget.
+ pub instance_buffer_max_size: usize,
}
</code_context>
<issue_to_address>
**issue (bug_risk):** Adding the required public field to `GpuResourceBudget` makes existing downstream struct literals fail to compile because every literal must now provide `instance_buffer_max_size`. This is a source-compatible API regression for callers that construct custom GPU budgets directly.
**Triggers:** When an application or downstream crate uses `GpuResourceBudget { ... }` rather than constructing it through an updated helper.
**Suggested fix:** Provide a non-breaking constructor/update path or preserve compatibility with a defaulted configuration representation; at minimum, document this as a deliberate breaking API change and update all supported downstream literals.
</issue_to_address>
### Comment 2
<location path="crates/gpui-wgpu/src/wgpu_renderer.rs" line_range="1478-1500" />
<code_context>
+ fn create_texture_bind_group(
</code_context>
<issue_to_address>
**nitpick (performance):** A new texture bind group is created inside every sprite draw call, so scenes with many atlas texture batches allocate and retain one bind group per batch until command submission rather than reusing bind groups for repeated texture IDs. This increases per-frame CPU/GPU resource churn and defeats the stated shared-bind-group batching optimization for sprites.
**Triggers:** When a frame contains many monochrome or polychrome sprite batches, especially repeated batches using the same atlas texture.
**Suggested fix:** Cache texture bind groups by `AtlasTextureId` for the duration of the frame or retain them alongside atlas texture metadata.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| fn create_texture_bind_group( | ||
| &self, | ||
| sprites: &[PolychromeSprite], | ||
| texture_id: AtlasTextureId, | ||
| instance_offset: &mut u64, | ||
| pass: &mut wgpu::RenderPass<'_>, | ||
| ) -> bool { | ||
| let tex_info = self.atlas.get_texture_info(texture_id); | ||
| let data = unsafe { Self::instance_bytes(sprites) }; | ||
| self.draw_instances_with_texture( | ||
| data, | ||
| sprites.len() as u32, | ||
| &tex_info.view, | ||
| &self.resources().pipelines.poly_sprites, | ||
| instance_offset, | ||
| pass, | ||
| ) | ||
| label: &str, | ||
| texture_view: &wgpu::TextureView, | ||
| ) -> wgpu::BindGroup { | ||
| let resources = self.resources(); | ||
| resources | ||
| .device | ||
| .create_bind_group(&wgpu::BindGroupDescriptor { | ||
| label: Some(label), | ||
| layout: &resources.bind_group_layouts.texture, | ||
| entries: &[ | ||
| wgpu::BindGroupEntry { | ||
| binding: 0, | ||
| resource: wgpu::BindingResource::TextureView(texture_view), | ||
| }, | ||
| wgpu::BindGroupEntry { | ||
| binding: 1, | ||
| resource: wgpu::BindingResource::Sampler(&resources.atlas_sampler), | ||
| }, | ||
| ], | ||
| }) | ||
| } |
There was a problem hiding this comment.
nitpick (performance): 每次 sprite 绘制调用中都会创建一个新的纹理绑定组,因此包含许多图集纹理批次的场景会为每个批次分配并保留一个绑定组,直到命令提交,而不是复用使用相同纹理 ID 的批次的绑定组。这会增加每帧 CPU/GPU 资源的频繁分配与释放,并使针对 sprite 的共享绑定组批处理优化失去作用。
触发条件: 当一帧包含许多单色或多色 sprite 批次时,尤其是多个批次使用同一个图集纹理时。
建议修复: 在帧的持续期间按 AtlasTextureId 缓存纹理绑定组,或将它们与图集纹理元数据一起保留。
Original comment in English
nitpick (performance): A new texture bind group is created inside every sprite draw call, so scenes with many atlas texture batches allocate and retain one bind group per batch until command submission rather than reusing bind groups for repeated texture IDs. This increases per-frame CPU/GPU resource churn and defeats the stated shared-bind-group batching optimization for sprites.
Triggers: When a frame contains many monochrome or polychrome sprite batches, especially repeated batches using the same atlas texture.
Suggested fix: Cache texture bind groups by AtlasTextureId for the duration of the frame or retain them alongside atlas texture metadata.
a8f4bc0 to
cbd8510
Compare
Port Zed's frame-start instance-buffer upload onto the Linux wgpu renderer without overwriting local recovery or profile wiring. Size and grow the buffer from GpuResourceBudget watermarks so Minimal/Utility cannot follow Zed's 256 MiB desktop ceiling. Zed-Origin: be8c6f9fb356dcd40a7ff06149568753e64ee171 Co-authored-by: freefcw <freefcw@gmail.com>
Do not present an unrecorded swapchain image when instance upload exceeds the profile/device cap. Replace offset_from with a release-safe subslice check so a non-scene batch cannot invoke UB. Co-authored-by: freefcw <freefcw@gmail.com>
Add GpuResourceBudget::new and Default so 0.9 callers can set atlas and initial instance-buffer sizes without inventing a max. Document the struct-literal break in the 0.9 changelog. Co-authored-by: freefcw <freefcw@gmail.com>
cbd8510 to
6f9ffc4
Compare
Port Zed
be8c6f9wgpu frame-start batch upload onto this fork’s existingGpuResourceBudget/AppResourceProfilewatermarks. Dedicated renderer-path change, not a wholesale wgpu rewrite.Rebased onto
develop/0.9at1e1d854(merged #7: demand-driven Wayland loop, font prewarm, hide/retry,shellcheck --source-path=scripts -x). This PR does not touchwgpu_context.rs; #3’sWGPU_BACKENDenv honor remains on develop.What landed
Zed bulk-uploads the whole scene’s instance arrays once at frame start, then draws from shared bind groups. That is more aggressive than the previous per-batch
queue.write_buffer+ retry-grow loop.Locally that upload is now budget-aware:
maxraised toinitialif lower)Growth still doubles from the profile allocation (not a hardcoded 2 MiB), is also limited by
max_buffer_size∩max_storage_buffer_binding_size, and fails the frame instead of ballooning past the watermark.The renderer now:
Application::new()unchangedLinux windows pass the full
GpuResourceBudgetintoWgpuRenderer::newso atlas size, initial buffer, and max watermark travel together (including after GPU recovery). WaylandFrameLoop/PresentationState/hide()unmapped guards from #7 are unchanged.Follow-ups on this branch (do not rewrite the Zed-Origin commit)
89d2477— do not present when batch upload fails; release-safe batch range check6f9ffc4—GpuResourceBudget::new/Defaultso two-field construction still works; 0.9 changelog notes the struct-literal breakThe previous
shellcheck -x -P SCRIPTDIRfollow-up was dropped: #7 already follows sourced scripts withshellcheck --source-path=scripts -x.Sourcery’s per-draw texture bind-group cache note is a nit matching Zed; not changed.
Intentionally not pasted
window.rslargest_border_interior(already covered by local border-only quad tests)Application::new()is unchanged.Zed-Origin: be8c6f9fb356dcd40a7ff06149568753e64ee171Sourcery 摘要
通过在每帧内按批次处理实例数据,并遵循配置文件和设备的资源限制,使 Linux WGPU 场景上传具备预算感知能力。
新功能:
错误修复:
增强功能:
文档:
测试:
Original summary in English
Sourcery 总结
通过在配置文件和设备资源限制范围内批量处理实例数据,使 Linux WGPU 场景上传具备预算感知能力。
新功能:
错误修复:
增强功能:
文档:
测试:
Original summary in English
Sourcery 总结
通过在配置文件和设备资源限制范围内对每帧实例数据进行批处理,使 Linux WGPU 场景上传具备预算感知能力。
新功能:
错误修复:
增强功能:
文档:
测试:
Original summary in English
Sourcery 摘要
通过在配置文件和设备资源限制范围内批量处理每帧实例数据,使 Linux WGPU 场景上传具备预算感知能力。
新功能:
错误修复:
增强功能:
文档:
测试:
杂项:
Original summary in English
Sourcery 总结
通过根据配置文件和设备限制,对每帧实例数据进行批处理,使 Linux WGPU 场景上传具备预算感知能力。
新功能:
错误修复:
增强功能:
构建:
文档:
测试:
日常维护:
Original summary in English
Sourcery 摘要
通过在配置文件和设备资源限制范围内对每帧实例数据进行批处理,使 Linux WGPU 场景上传具备预算感知能力。
新功能:
错误修复:
增强功能:
构建:
文档:
测试:
杂项:
Original summary in English
Sourcery 摘要
通过根据配置文件和设备资源限制,对每帧实例数据进行批处理,使 Linux WGPU 场景上传具备预算感知能力。
新功能:
错误修复:
增强功能:
文档:
测试:
Original summary in English
Summary by Sourcery
Make Linux WGPU scene uploads budget-aware by batching per-frame instance data within profile and device resource limits.
New Features:
Bug Fixes:
Enhancements:
Documentation:
Tests: